From ae187b6d75c8079da0be1dc288613bad8466fe61 Mon Sep 17 00:00:00 2001 From: RaindropsSys Date: Tue, 24 Oct 2023 17:43:37 +0200 Subject: Initial commit --- .../node_modules/electron-packager/src/platform.js | 277 +++++++++++++++++++++ 1 file changed, 277 insertions(+) create mode 100644 desktop/node_modules/electron-packager/src/platform.js (limited to 'desktop/node_modules/electron-packager/src/platform.js') diff --git a/desktop/node_modules/electron-packager/src/platform.js b/desktop/node_modules/electron-packager/src/platform.js new file mode 100644 index 0000000..18df14f --- /dev/null +++ b/desktop/node_modules/electron-packager/src/platform.js @@ -0,0 +1,277 @@ +'use strict' + +const asar = require('@electron/asar') +const crypto = require('crypto') +const debug = require('debug')('electron-packager') +const fs = require('fs-extra') +const path = require('path') + +const common = require('./common') +const copyFilter = require('./copy-filter') +const hooks = require('./hooks') + +class App { + constructor (opts, templatePath) { + this.opts = opts + this.templatePath = templatePath + this.asarOptions = common.createAsarOpts(opts) + + if (this.opts.prune === undefined) { + this.opts.prune = true + } + } + + /** + * Resource directory path before renaming. + */ + get originalResourcesDir () { + return this.resourcesDir + } + + /** + * Resource directory path after renaming. + */ + get resourcesDir () { + return path.join(this.stagingPath, 'resources') + } + + get originalResourcesAppDir () { + return path.join(this.originalResourcesDir, 'app') + } + + get electronBinaryDir () { + return this.stagingPath + } + + get originalElectronName () { + /* istanbul ignore next */ + throw new Error('Child classes must implement this') + } + + get newElectronName () { + /* istanbul ignore next */ + throw new Error('Child classes must implement this') + } + + get executableName () { + return this.opts.executableName || this.opts.name + } + + get stagingPath () { + if (this.opts.tmpdir === false) { + return common.generateFinalPath(this.opts) + } else { + if (!this.cachedStagingPath) { + const parentDir = path.join( + common.baseTempDir(this.opts), + `${this.opts.platform}-${this.opts.arch}` + ) + fs.mkdirpSync(parentDir) + this.cachedStagingPath = fs.mkdtempSync(path.join(parentDir, `${common.generateFinalBasename(this.opts)}-`)) + } + return this.cachedStagingPath + } + } + + get appAsarPath () { + return path.join(this.originalResourcesDir, 'app.asar') + } + + get commonHookArgs () { + return [ + this.opts.electronVersion, + this.opts.platform, + this.opts.arch + ] + } + + get hookArgsWithOriginalResourcesAppDir () { + return [ + this.originalResourcesAppDir, + ...this.commonHookArgs + ] + } + + async relativeRename (basePath, oldName, newName) { + debug(`Renaming ${oldName} to ${newName} in ${basePath}`) + await fs.rename(path.join(basePath, oldName), path.join(basePath, newName)) + } + + async renameElectron () { + return this.relativeRename(this.electronBinaryDir, this.originalElectronName, this.newElectronName) + } + + /** + * Performs the following initial operations for an app: + * * Creates temporary directory + * * Remove default_app (which is either a folder or an asar file) + * * If a prebuilt asar is specified: + * * Copies asar into temporary directory as app.asar + * * Otherwise: + * * Copies template into temporary directory + * * Copies user's app into temporary directory + * * Prunes non-production node_modules (if opts.prune is either truthy or undefined) + * * Creates an asar (if opts.asar is set) + * + * Prune and asar are performed before platform-specific logic, primarily so that + * this.originalResourcesAppDir is predictable (e.g. before .app is renamed for Mac) + */ + async initialize () { + debug(`Initializing app in ${this.stagingPath} from ${this.templatePath} template`) + + await fs.move(this.templatePath, this.stagingPath, { clobber: true }) + await this.removeDefaultApp() + if (this.opts.prebuiltAsar) { + await this.copyPrebuiltAsar() + } else { + await this.buildApp() + } + + await hooks.promisifyHooks(this.opts.afterInitialize, this.hookArgsWithOriginalResourcesAppDir) + } + + async buildApp () { + await this.copyTemplate() + await common.validateElectronApp(this.opts.dir, this.originalResourcesAppDir) + await this.asarApp() + } + + async copyTemplate () { + await hooks.promisifyHooks(this.opts.beforeCopy, this.hookArgsWithOriginalResourcesAppDir) + + await fs.copy(this.opts.dir, this.originalResourcesAppDir, { + filter: copyFilter.userPathFilter(this.opts), + dereference: this.opts.derefSymlinks + }) + await hooks.promisifyHooks(this.opts.afterCopy, this.hookArgsWithOriginalResourcesAppDir) + if (this.opts.prune) { + await hooks.promisifyHooks(this.opts.afterPrune, this.hookArgsWithOriginalResourcesAppDir) + } + } + + async removeDefaultApp () { + await Promise.all(['default_app', 'default_app.asar'].map(async basename => fs.remove(path.join(this.originalResourcesDir, basename)))) + } + + /** + * Forces an icon filename to a given extension and returns the normalized filename, + * if it exists. Otherwise, returns null. + * + * This error path is used by win32 if no icon is specified. + */ + async normalizeIconExtension (targetExt) { + if (!this.opts.icon) throw new Error('No filename specified to normalizeIconExtension') + + let iconFilename = this.opts.icon + const ext = path.extname(iconFilename) + if (ext !== targetExt) { + iconFilename = path.join(path.dirname(iconFilename), path.basename(iconFilename, ext) + targetExt) + } + + if (await fs.pathExists(iconFilename)) { + return iconFilename + } else { + /* istanbul ignore next */ + common.warning(`Could not find icon "${iconFilename}", not updating app icon`, this.opts.quiet) + } + } + + prebuiltAsarWarning (option, triggerWarning) { + if (triggerWarning) { + common.warning(`prebuiltAsar and ${option} are incompatible, ignoring the ${option} option`, this.opts.quiet) + } + } + + async copyPrebuiltAsar () { + if (this.asarOptions) { + common.warning('prebuiltAsar has been specified, all asar options will be ignored', this.opts.quiet) + } + + for (const hookName of ['beforeCopy', 'afterCopy', 'afterPrune']) { + if (this.opts[hookName]) { + throw new Error(`${hookName} is incompatible with prebuiltAsar`) + } + } + + this.prebuiltAsarWarning('ignore', this.opts.originalIgnore) + this.prebuiltAsarWarning('prune', !this.opts.prune) + this.prebuiltAsarWarning('derefSymlinks', this.opts.derefSymlinks !== undefined) + + const src = path.resolve(this.opts.prebuiltAsar) + + const stat = await fs.stat(src) + if (!stat.isFile()) { + throw new Error(`${src} specified in prebuiltAsar must be an asar file.`) + } + + debug(`Copying asar: ${src} to ${this.appAsarPath}`) + await fs.copy(src, this.appAsarPath, { overwrite: false, errorOnExist: true }) + } + + appRelativePath (p) { + return path.relative(this.stagingPath, p) + } + + async asarApp () { + if (!this.asarOptions) { + return Promise.resolve() + } + + debug(`Running asar with the options ${JSON.stringify(this.asarOptions)}`) + + await hooks.promisifyHooks(this.opts.beforeAsar, this.hookArgsWithOriginalResourcesAppDir) + + await asar.createPackageWithOptions(this.originalResourcesAppDir, this.appAsarPath, this.asarOptions) + const { headerString } = asar.getRawHeader(this.appAsarPath) + this.asarIntegrity = { + [this.appRelativePath(this.appAsarPath)]: { + algorithm: 'SHA256', + hash: crypto.createHash('SHA256').update(headerString).digest('hex') + } + } + await fs.remove(this.originalResourcesAppDir) + + await hooks.promisifyHooks(this.opts.afterAsar, this.hookArgsWithOriginalResourcesAppDir) + } + + async copyExtraResources () { + if (!this.opts.extraResource) return Promise.resolve() + + const extraResources = common.ensureArray(this.opts.extraResource) + + const hookArgs = [ + this.stagingPath, + ...this.commonHookArgs + ] + + await hooks.promisifyHooks(this.opts.beforeCopyExtraResources, hookArgs) + + await Promise.all(extraResources.map( + resource => fs.copy(resource, path.resolve(this.stagingPath, this.resourcesDir, path.basename(resource))) + )) + + await hooks.promisifyHooks(this.opts.afterCopyExtraResources, hookArgs) + } + + async move () { + const finalPath = common.generateFinalPath(this.opts) + + if (this.opts.tmpdir !== false) { + debug(`Moving ${this.stagingPath} to ${finalPath}`) + await fs.move(this.stagingPath, finalPath) + } + + if (this.opts.afterComplete) { + const hookArgs = [ + finalPath, + ...this.commonHookArgs + ] + + await hooks.promisifyHooks(this.opts.afterComplete, hookArgs) + } + + return finalPath + } +} + +module.exports = App -- cgit