UNPKG

electron-builder

Version:

A complete solution to package and build a ready for distribution Electron app for MacOS, Windows and Linux with “auto update” support out of the box

575 lines (528 loc) 27.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getResolvedPublishConfig = exports.PlatformPackager = exports.TargetEx = exports.Target = undefined; var _bluebirdLstC; function _load_bluebirdLstC() { return _bluebirdLstC = require("bluebird-lst-c"); } var _bluebirdLstC2; function _load_bluebirdLstC2() { return _bluebirdLstC2 = _interopRequireDefault(require("bluebird-lst-c")); } let getResolvedPublishConfig = exports.getResolvedPublishConfig = (() => { var _ref2 = (0, (_bluebirdLstC || _load_bluebirdLstC()).coroutine)(function* (packager, publishConfig, errorIfCannot) { let getInfo = (() => { var _ref3 = (0, (_bluebirdLstC || _load_bluebirdLstC()).coroutine)(function* () { const info = yield (0, (_repositoryInfo || _load_repositoryInfo()).getRepositoryInfo)(packager.metadata, packager.devMetadata); if (info != null) { return info; } if (!errorIfCannot) { return null; } (0, (_log || _load_log()).warn)("Cannot detect repository by .git/config"); throw new Error(`Please specify "repository" in the dev package.json ('${ packager.devPackageFile }').\nPlease see https://github.com/electron-userland/electron-builder/wiki/Publishing-Artifacts`); }); return function getInfo() { return _ref3.apply(this, arguments); }; })(); if (publishConfig.provider === "generic") { if (publishConfig.url == null) { throw new Error(`Please specify "url" for "generic" update server`); } return publishConfig; } let owner = publishConfig.owner; let project = publishConfig.provider === "github" ? publishConfig.repo : publishConfig.package; if (!owner || !project) { const info = yield getInfo(); if (info == null) { return null; } if (!owner) { owner = info.user; } if (!project) { project = info.project; } } const copy = Object.assign({}, publishConfig); if (copy.owner == null) { copy.owner = owner; } if (publishConfig.provider === "github") { const options = copy; if (options.repo == null) { options.repo = project; } return options; } else if (publishConfig.provider === "bintray") { const options = copy; if (options.package == null) { options.package = project; } return options; } else { return null; } }); return function getResolvedPublishConfig(_x2, _x3, _x4) { return _ref2.apply(this, arguments); }; })(); //# sourceMappingURL=platformPackager.js.map exports.getArchSuffix = getArchSuffix; exports.smarten = smarten; exports.normalizeExt = normalizeExt; exports.getPublishConfigs = getPublishConfigs; var _metadata; function _load_metadata() { return _metadata = require("./metadata"); } var _path; function _load_path() { return _path = _interopRequireWildcard(require("path")); } var _fsExtraP; function _load_fsExtraP() { return _fsExtraP = require("fs-extra-p"); } var _util; function _load_util() { return _util = require("./util/util"); } var _archive; function _load_archive() { return _archive = require("./targets/archive"); } var _asarUtil; function _load_asarUtil() { return _asarUtil = require("./asarUtil"); } var _log; function _load_log() { return _log = require("./util/log"); } var _filter; function _load_filter() { return _filter = require("./util/filter"); } var _dirPackager; function _load_dirPackager() { return _dirPackager = require("./packager/dirPackager"); } var _fileMatcher; function _load_fileMatcher() { return _fileMatcher = require("./fileMatcher"); } var _repositoryInfo; function _load_repositoryInfo() { return _repositoryInfo = require("./repositoryInfo"); } var _yarn; function _load_yarn() { return _yarn = require("./yarn"); } function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } class Target { constructor(name) { this.name = name; } finishBuild() { return (_bluebirdLstC2 || _load_bluebirdLstC2()).default.resolve(); } } exports.Target = Target; class TargetEx extends Target {} exports.TargetEx = TargetEx; class PlatformPackager { constructor(info) { this.info = info; this.devMetadata = info.devMetadata; this.platformSpecificBuildOptions = this.normalizePlatformSpecificBuildOptions(info.devMetadata.build[this.platform.buildConfigurationKey]); this.appInfo = this.prepareAppInfo(info.appInfo); this.options = info.options; this.projectDir = info.projectDir; this.buildResourcesDir = (_path || _load_path()).resolve(this.projectDir, this.relativeBuildResourcesDirname); this.resourceList = (0, (_fsExtraP || _load_fsExtraP()).readdir)(this.buildResourcesDir).catch(e => { if (e.code !== "ENOENT") { throw e; } return []; }); } prepareAppInfo(appInfo) { return appInfo; } normalizePlatformSpecificBuildOptions(options) { return options == null ? Object.create(null) : options; } getCscPassword() { const password = this.doGetCscPassword(); if ((0, (_util || _load_util()).isEmptyOrSpaces)(password)) { (0, (_log || _load_log()).log)("CSC_KEY_PASSWORD is not defined, empty password will be used"); return ""; } else { return password.trim(); } } doGetCscPassword() { return this.options.cscKeyPassword || process.env.CSC_KEY_PASSWORD; } get relativeBuildResourcesDirname() { return (0, (_util || _load_util()).use)(this.devMetadata.directories, it => it.buildResources) || "build"; } computeAppOutDir(outDir, arch) { return (_path || _load_path()).join(outDir, `${ this.platform.buildConfigurationKey }${ getArchSuffix(arch) }${ this.platform === (_metadata || _load_metadata()).Platform.MAC ? "" : "-unpacked" }`); } dispatchArtifactCreated(file, artifactName) { this.info.eventEmitter.emit("artifactCreated", { file: file, artifactName: artifactName, packager: this }); } getExtraFileMatchers(isResources, appOutDir, fileMatchOptions, customBuildOptions) { const base = isResources ? this.getResourcesDir(appOutDir) : this.platform === (_metadata || _load_metadata()).Platform.MAC ? (_path || _load_path()).join(appOutDir, `${ this.appInfo.productFilename }.app`, "Contents") : appOutDir; return this.getFileMatchers(isResources ? "extraResources" : "extraFiles", this.projectDir, base, true, fileMatchOptions, customBuildOptions); } doPack(outDir, appOutDir, platformName, arch, platformSpecificBuildOptions) { var _this = this; return (0, (_bluebirdLstC || _load_bluebirdLstC()).coroutine)(function* () { const asarOptions = _this.computeAsarOptions(platformSpecificBuildOptions); const fileMatchOptions = { arch: (_metadata || _load_metadata()).Arch[arch], os: _this.platform.buildConfigurationKey }; const extraResourceMatchers = _this.getExtraFileMatchers(true, appOutDir, fileMatchOptions, platformSpecificBuildOptions); const extraFileMatchers = _this.getExtraFileMatchers(false, appOutDir, fileMatchOptions, platformSpecificBuildOptions); const resourcesPath = _this.platform === (_metadata || _load_metadata()).Platform.MAC ? (_path || _load_path()).join(appOutDir, "Electron.app", "Contents", "Resources") : (_path || _load_path()).join(appOutDir, "resources"); (0, (_log || _load_log()).log)(`Packaging for ${ platformName } ${ (_metadata || _load_metadata()).Arch[arch] } using electron ${ _this.info.electronVersion } to ${ (_path || _load_path()).relative(_this.projectDir, appOutDir) }`); yield (0, (_dirPackager || _load_dirPackager()).pack)(_this, appOutDir, platformName, (_metadata || _load_metadata()).Arch[arch], _this.info.electronVersion, (0, (_bluebirdLstC || _load_bluebirdLstC()).coroutine)(function* () { const appDir = _this.info.appDir; const ignoreFiles = new Set([(_path || _load_path()).resolve(appDir, outDir), (_path || _load_path()).resolve(appDir, _this.buildResourcesDir)]); // prune dev or not listed dependencies yield (0, (_yarn || _load_yarn()).dependencies)(appDir, true, ignoreFiles); if ((_util || _load_util()).debug.enabled) { const nodeModulesDir = (_path || _load_path()).join(appDir, "node_modules"); (0, (_util || _load_util()).debug)(`Pruned dev or extraneous dependencies: ${ Array.from(ignoreFiles).slice(2).map(function (it) { return (_path || _load_path()).relative(nodeModulesDir, it); }).join(", ") }`); } const patterns = _this.getFileMatchers("files", appDir, (_path || _load_path()).join(resourcesPath, "app"), false, fileMatchOptions, platformSpecificBuildOptions); let defaultMatcher = patterns != null ? patterns[0] : new (_fileMatcher || _load_fileMatcher()).FileMatcher(appDir, (_path || _load_path()).join(resourcesPath, "app"), fileMatchOptions); if (defaultMatcher.isEmpty()) { defaultMatcher.addPattern("**/*"); } else { defaultMatcher.addPattern("package.json"); } defaultMatcher.addPattern("!**/node_modules/*/{CHANGELOG.md,README.md,README,readme.md,readme,test,__tests__,tests,powered-test,example,examples,*.d.ts}"); defaultMatcher.addPattern("!**/node_modules/.bin"); defaultMatcher.addPattern("!**/*.{o,hprof,orig,pyc,pyo,rbc,swp}"); defaultMatcher.addPattern("!**/._*"); //noinspection SpellCheckingInspection defaultMatcher.addPattern("!**/{.DS_Store,.git,.hg,.svn,CVS,RCS,SCCS,__pycache__,thumbs.db,.gitignore,.gitattributes,.editorconfig,.flowconfig,.yarn-metadata.json,.idea,appveyor.yml,.travis.yml,circle.yml,npm-debug.log,.nyc_output,yarn.lock,.yarn-integrity}"); let rawFilter = null; const deprecatedIgnore = _this.devMetadata.build.ignore; if (deprecatedIgnore != null) { if (typeof deprecatedIgnore === "function") { (0, (_log || _load_log()).warn)(`"ignore" is specified as function, may be new "files" option will be suit your needs? Please see https://github.com/electron-userland/electron-builder/wiki/Options#BuildMetadata-files`); } else { (0, (_log || _load_log()).warn)(`"ignore" is deprecated, please use "files", see https://github.com/electron-userland/electron-builder/wiki/Options#BuildMetadata-files`); } rawFilter = (0, (_fileMatcher || _load_fileMatcher()).deprecatedUserIgnoreFilter)(deprecatedIgnore, appDir); } let excludePatterns = []; if (extraResourceMatchers != null) { for (let i = 0; i < extraResourceMatchers.length; i++) { const patterns = extraResourceMatchers[i].getParsedPatterns(_this.info.projectDir); excludePatterns = excludePatterns.concat(patterns); } } if (extraFileMatchers != null) { for (let i = 0; i < extraFileMatchers.length; i++) { const patterns = extraFileMatchers[i].getParsedPatterns(_this.info.projectDir); excludePatterns = excludePatterns.concat(patterns); } } const filter = defaultMatcher.createFilter(ignoreFiles, rawFilter, excludePatterns.length ? excludePatterns : null); const promise = asarOptions == null ? (0, (_filter || _load_filter()).copyFiltered)(appDir, (_path || _load_path()).join(resourcesPath, "app"), filter, _this.info.devMetadata.build.dereference || _this.platform === (_metadata || _load_metadata()).Platform.WINDOWS) : (0, (_asarUtil || _load_asarUtil()).createAsarArchive)(appDir, resourcesPath, asarOptions, filter); const promises = [promise, (0, (_util || _load_util()).unlinkIfExists)((_path || _load_path()).join(resourcesPath, "default_app.asar")), (0, (_util || _load_util()).unlinkIfExists)((_path || _load_path()).join(appOutDir, "version"))]; if (_this.info.electronVersion != null && _this.info.electronVersion[0] === "0") { // electron release >= 0.37.4 - the default_app/ folder is a default_app.asar file promises.push((0, (_fsExtraP || _load_fsExtraP()).remove)((_path || _load_path()).join(resourcesPath, "default_app"))); } promises.push(_this.postInitApp(appOutDir)); yield (_bluebirdLstC2 || _load_bluebirdLstC2()).default.all(promises); })); yield _this.doCopyExtraFiles(extraResourceMatchers); yield _this.doCopyExtraFiles(extraFileMatchers); const afterPack = _this.devMetadata.build.afterPack; if (afterPack != null) { yield afterPack({ appOutDir: appOutDir, options: _this.devMetadata.build, packager: _this }); } yield _this.sanityCheckPackage(appOutDir, asarOptions != null); })(); } postInitApp(executableFile) { return (_bluebirdLstC2 || _load_bluebirdLstC2()).default.resolve(null); } getIconPath() { return (0, (_bluebirdLstC || _load_bluebirdLstC()).coroutine)(function* () { return null; })(); } computeAsarOptions(customBuildOptions) { let result = this.devMetadata.build.asar; let platformSpecific = customBuildOptions.asar; if (platformSpecific != null) { result = platformSpecific; } if (result === false) { return null; } const buildMetadata = this.devMetadata.build; if (buildMetadata["asar-unpack"] != null) { (0, (_log || _load_log()).warn)("asar-unpack is deprecated, please set as asar.unpack"); } if (buildMetadata["asar-unpack-dir"] != null) { (0, (_log || _load_log()).warn)("asar-unpack-dir is deprecated, please set as asar.unpackDir"); } if (result == null || result === true) { result = { unpack: buildMetadata["asar-unpack"], unpackDir: buildMetadata["asar-unpack-dir"] }; } return Object.assign(result, { extraMetadata: this.options.extraMetadata }); } doCopyExtraFiles(patterns) { if (patterns == null || patterns.length === 0) { return (_bluebirdLstC2 || _load_bluebirdLstC2()).default.resolve(); } else { const promises = []; for (let i = 0; i < patterns.length; i++) { if (patterns[i].isEmpty()) { patterns[i].addPattern("**/*"); } promises.push((0, (_filter || _load_filter()).copyFiltered)(patterns[i].from, patterns[i].to, patterns[i].createFilter(), this.platform === (_metadata || _load_metadata()).Platform.WINDOWS)); } return (_bluebirdLstC2 || _load_bluebirdLstC2()).default.all(promises); } } getFileMatchers(name, defaultSrc, defaultDest, allowAdvancedMatching, fileMatchOptions, customBuildOptions) { let globalPatterns = this.devMetadata.build[name]; let platformSpecificPatterns = customBuildOptions[name]; const defaultMatcher = new (_fileMatcher || _load_fileMatcher()).FileMatcher(defaultSrc, defaultDest, fileMatchOptions); const fileMatchers = []; function addPatterns(patterns) { if (patterns == null) { return; } else if (!Array.isArray(patterns)) { defaultMatcher.addPattern(patterns); return; } for (let i = 0; i < patterns.length; i++) { const pattern = patterns[i]; if (typeof pattern === "string") { defaultMatcher.addPattern(pattern); } else if (allowAdvancedMatching) { const from = pattern.from ? (_path || _load_path()).isAbsolute(pattern.from) ? pattern.from : (_path || _load_path()).join(defaultSrc, pattern.from) : defaultSrc; const to = pattern.to ? (_path || _load_path()).isAbsolute(pattern.to) ? pattern.to : (_path || _load_path()).join(defaultDest, pattern.to) : defaultDest; fileMatchers.push(new (_fileMatcher || _load_fileMatcher()).FileMatcher(from, to, fileMatchOptions, pattern.filter)); } else { throw new Error(`Advanced file copying not supported for "${ name }"`); } } } addPatterns(globalPatterns); addPatterns(platformSpecificPatterns); if (!defaultMatcher.isEmpty()) { // Default matcher should be first in the array fileMatchers.unshift(defaultMatcher); } return fileMatchers.length ? fileMatchers : null; } getResourcesDir(appOutDir) { return this.platform === (_metadata || _load_metadata()).Platform.MAC ? this.getOSXResourcesDir(appOutDir) : (_path || _load_path()).join(appOutDir, "resources"); } getOSXResourcesDir(appOutDir) { return (_path || _load_path()).join(appOutDir, `${ this.appInfo.productFilename }.app`, "Contents", "Resources"); } checkFileInPackage(resourcesDir, file, messagePrefix, isAsar) { var _this2 = this; return (0, (_bluebirdLstC || _load_bluebirdLstC()).coroutine)(function* () { const relativeFile = (_path || _load_path()).relative(_this2.info.appDir, (_path || _load_path()).resolve(_this2.info.appDir, file)); if (isAsar) { yield (0, (_asarUtil || _load_asarUtil()).checkFileInArchive)((_path || _load_path()).join(resourcesDir, "app.asar"), relativeFile, messagePrefix); return; } const pathParsed = (_path || _load_path()).parse(file); // Even when packaging to asar is disabled, it does not imply that the main file can not be inside an .asar archive. // This may occur when the packaging is done manually before processing with electron-builder. if (pathParsed.dir.indexOf(".asar") !== -1) { // The path needs to be split to the part with an asar archive which acts like a directory and the part with // the path to main file itself. (e.g. path/arch.asar/dir/index.js -> path/arch.asar, dir/index.js) const pathSplit = pathParsed.dir.split((_path || _load_path()).sep); let partWithAsarIndex = 0; pathSplit.some(function (pathPart, index) { partWithAsarIndex = index; return pathPart.endsWith(".asar"); }); const asarPath = (_path || _load_path()).join.apply(_path || _load_path(), pathSplit.slice(0, partWithAsarIndex + 1)); let mainPath = pathSplit.length > partWithAsarIndex + 1 ? (_path || _load_path()).join.apply(pathSplit.slice(partWithAsarIndex + 1)) : ""; mainPath += (_path || _load_path()).join(mainPath, pathParsed.base); yield (0, (_asarUtil || _load_asarUtil()).checkFileInArchive)((_path || _load_path()).join(resourcesDir, "app", asarPath), mainPath, messagePrefix); } else { const outStat = yield (0, (_util || _load_util()).statOrNull)((_path || _load_path()).join(resourcesDir, "app", relativeFile)); if (outStat == null) { throw new Error(`${ messagePrefix } "${ relativeFile }" does not exist. Seems like a wrong configuration.`); } else if (!outStat.isFile()) { throw new Error(`${ messagePrefix } "${ relativeFile }" is not a file. Seems like a wrong configuration.`); } } })(); } sanityCheckPackage(appOutDir, isAsar) { var _this3 = this; return (0, (_bluebirdLstC || _load_bluebirdLstC()).coroutine)(function* () { const outStat = yield (0, (_util || _load_util()).statOrNull)(appOutDir); if (outStat == null) { throw new Error(`Output directory "${ appOutDir }" does not exist. Seems like a wrong configuration.`); } else if (!outStat.isDirectory()) { throw new Error(`Output directory "${ appOutDir }" is not a directory. Seems like a wrong configuration.`); } const resourcesDir = _this3.getResourcesDir(appOutDir); yield _this3.checkFileInPackage(resourcesDir, _this3.appInfo.metadata.main || "index.js", "Application entry file", isAsar); yield _this3.checkFileInPackage(resourcesDir, "package.json", "Application", isAsar); })(); } archiveApp(format, appOutDir, outFile) { var _this4 = this; return (0, (_bluebirdLstC || _load_bluebirdLstC()).coroutine)(function* () { const isMac = _this4.platform === (_metadata || _load_metadata()).Platform.MAC; return (0, (_archive || _load_archive()).archiveApp)(_this4.devMetadata.build.compression, format, outFile, isMac ? (_path || _load_path()).join(appOutDir, `${ _this4.appInfo.productFilename }.app`) : appOutDir, isMac); })(); } generateName(ext, arch, deployment) { let classifier = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; let c = null; if (arch === (_metadata || _load_metadata()).Arch.x64) { if (ext === "AppImage") { c = "x86_64"; } else if (ext === "deb") { c = "amd64"; } } else { c = (_metadata || _load_metadata()).Arch[arch]; } if (c == null) { c = classifier; } else if (classifier != null) { c += `-${ classifier }`; } return this.generateName2(ext, c, deployment); } generateName2(ext, classifier, deployment) { const dotExt = ext == null ? "" : `.${ ext }`; return `${ deployment ? this.appInfo.name : this.appInfo.productFilename }-${ this.appInfo.version }${ classifier == null ? "" : `-${ classifier }` }${ dotExt }`; } getDefaultIcon(ext) { var _this5 = this; return (0, (_bluebirdLstC || _load_bluebirdLstC()).coroutine)(function* () { const resourceList = yield _this5.resourceList; const name = `icon.${ ext }`; if (resourceList.indexOf(name) !== -1) { return (_path || _load_path()).join(_this5.buildResourcesDir, name); } else { (0, (_log || _load_log()).warn)("Application icon is not set, default Electron icon will be used"); return null; } })(); } getTempFile(suffix) { return this.info.tempDirManager.getTempFile(suffix); } getFileAssociations() { return (0, (_util || _load_util()).asArray)(this.devMetadata.build.fileAssociations).concat((0, (_util || _load_util()).asArray)(this.platformSpecificBuildOptions.fileAssociations)); } getResource(custom) { var _this6 = this; for (var _len = arguments.length, names = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { names[_key - 1] = arguments[_key]; } return (0, (_bluebirdLstC || _load_bluebirdLstC()).coroutine)(function* () { if (custom === undefined) { const resourceList = yield _this6.resourceList; for (let name of names) { if (resourceList.indexOf(name) !== -1) { return (_path || _load_path()).join(_this6.buildResourcesDir, name); } } } else if (!(0, (_util || _load_util()).isEmptyOrSpaces)(custom)) { return (_path || _load_path()).resolve(_this6.projectDir, custom); } return null; })(); } } exports.PlatformPackager = PlatformPackager; function getArchSuffix(arch) { return arch === (_metadata || _load_metadata()).Arch.x64 ? "" : `-${ (_metadata || _load_metadata()).Arch[arch] }`; } // fpm bug - rpm build --description is not escaped, well... decided to replace quite to smart quote // http://leancrew.com/all-this/2010/11/smart-quotes-in-javascript/ function smarten(s) { // opening singles s = s.replace(/(^|[-\u2014\s(\["])'/g, "$1\u2018"); // closing singles & apostrophes s = s.replace(/'/g, "\u2019"); // opening doubles s = s.replace(/(^|[-\u2014/\[(\u2018\s])"/g, "$1\u201c"); // closing doubles s = s.replace(/"/g, "\u201d"); return s; } // remove leading dot function normalizeExt(ext) { return ext.startsWith(".") ? ext.substring(1) : ext; } function getPublishConfigs(packager, platformSpecificBuildOptions) { // check build.nsis (target) let publishers = platformSpecificBuildOptions.publish; // if explicitly set to null - do not publish if (publishers === null) { return null; } // check build.win (platform) if (packager.platformSpecificBuildOptions !== platformSpecificBuildOptions) { publishers = packager.platformSpecificBuildOptions.publish; if (publishers === null) { return null; } } if (publishers == null) { publishers = packager.info.devMetadata.build.publish; if (publishers === null) { return null; } if (publishers == null && !(0, (_util || _load_util()).isEmptyOrSpaces)(process.env.GH_TOKEN)) { publishers = [{ provider: "github" }]; } // if both tokens are set — still publish to github (because default publisher is github) if (publishers == null && !(0, (_util || _load_util()).isEmptyOrSpaces)(process.env.BT_TOKEN)) { publishers = [{ provider: "bintray" }]; } } return (0, (_util || _load_util()).asArray)(publishers).map(it => typeof it === "string" ? { provider: it } : it); }