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

389 lines (350 loc) 19.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var _bluebirdLstC; function _load_bluebirdLstC() { return _bluebirdLstC = require("bluebird-lst-c"); } var _bluebirdLstC2; function _load_bluebirdLstC2() { return _bluebirdLstC2 = _interopRequireDefault(require("bluebird-lst-c")); } var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); var _metadata; function _load_metadata() { return _metadata = require("../metadata"); } var _util; function _load_util() { return _util = require("../util/util"); } var _path; function _load_path() { return _path = _interopRequireWildcard(require("path")); } var _binDownload; function _load_binDownload() { return _binDownload = require("../util/binDownload"); } var _uuid; function _load_uuid() { return _uuid = require("uuid-1345"); } var _platformPackager; function _load_platformPackager() { return _platformPackager = require("../platformPackager"); } var _archive; function _load_archive() { return _archive = require("./archive"); } var _log; function _load_log() { return _log = require("../util/log"); } var _fsExtraP; function _load_fsExtraP() { return _fsExtraP = require("fs-extra-p"); } var _semver; function _load_semver() { return _semver = require("semver"); } var _jsYaml; function _load_jsYaml() { return _jsYaml = require("js-yaml"); } var _crypto; function _load_crypto() { return _crypto = require("crypto"); } 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 }; } const NSIS_VERSION = "3.0.2"; //noinspection SpellCheckingInspection const NSIS_SHA2 = "012c29d62e167ff74e858eeb929641dc2c9d7bfe7465e748648814660c61b419"; //noinspection SpellCheckingInspection const ELECTRON_BUILDER_NS_UUID = "50e065bc-3134-11e6-9bab-38c9862bdaf3"; const nsisPathPromise = (0, (_binDownload || _load_binDownload()).getBinFromBintray)("nsis", NSIS_VERSION, NSIS_SHA2); class NsisTarget extends (_platformPackager || _load_platformPackager()).TargetEx { constructor(packager, outDir) { super("nsis"); this.packager = packager; this.outDir = outDir; this.options = this.packager.info.devMetadata.build.nsis || Object.create(null); this.archs = new Map(); this.nsisTemplatesDir = (_path || _load_path()).join(__dirname, "..", "..", "templates", "nsis"); this.publishConfigs = this.computePublishConfigs(); } computePublishConfigs() { const publishConfigs = (0, (_platformPackager || _load_platformPackager()).getPublishConfigs)(this.packager, this.options); if (publishConfigs != null && publishConfigs.length > 0) { return (_bluebirdLstC2 || _load_bluebirdLstC2()).default.map(publishConfigs, it => (0, (_platformPackager || _load_platformPackager()).getResolvedPublishConfig)(this.packager.info, it, true)); } else { return (_bluebirdLstC2 || _load_bluebirdLstC2()).default.resolve(null); } } build(appOutDir, arch) { this.archs.set(arch, this.doBuild(appOutDir, arch)); return (_bluebirdLstC2 || _load_bluebirdLstC2()).default.resolve(null); } doBuild(appOutDir, arch) { var _this = this; return (0, (_bluebirdLstC || _load_bluebirdLstC()).coroutine)(function* () { (0, (_log || _load_log()).log)(`Packaging NSIS installer for arch ${ (_metadata || _load_metadata()).Arch[arch] }`); const publishConfigs = yield _this.publishConfigs; if (publishConfigs != null) { yield (0, (_fsExtraP || _load_fsExtraP()).writeFile)((_path || _load_path()).join(appOutDir, "resources", "app-update.yml"), (0, (_jsYaml || _load_jsYaml()).safeDump)(publishConfigs[0])); } const packager = _this.packager; const archiveFile = (_path || _load_path()).join(_this.outDir, `${ packager.appInfo.name }-${ packager.appInfo.version }-${ (_metadata || _load_metadata()).Arch[arch] }.nsis.7z`); return yield (0, (_archive || _load_archive()).archiveApp)(packager.devMetadata.build.compression, "7z", archiveFile, appOutDir, false, true); })(); } finishBuild() { var _this2 = this; return (0, (_bluebirdLstC || _load_bluebirdLstC()).coroutine)(function* () { (0, (_log || _load_log()).log)("Building NSIS installer"); try { yield _this2.buildInstaller(); } finally { yield (_bluebirdLstC2 || _load_bluebirdLstC2()).default.map(_this2.archs.values(), function (it) { return (0, (_fsExtraP || _load_fsExtraP()).unlink)(it); }); } })(); } buildInstaller() { var _this3 = this; return (0, (_bluebirdLstC || _load_bluebirdLstC()).coroutine)(function* () { const packager = _this3.packager; const appInfo = packager.appInfo; const version = appInfo.version; const installerFilename = `${ appInfo.productFilename } Setup ${ version }.exe`; const iconPath = yield packager.getIconPath(); const installerPath = (_path || _load_path()).join(_this3.outDir, installerFilename); const guid = _this3.options.guid || (yield (_bluebirdLstC2 || _load_bluebirdLstC2()).default.promisify((_uuid || _load_uuid()).v5)({ namespace: ELECTRON_BUILDER_NS_UUID, name: appInfo.id })); const defines = { APP_ID: appInfo.id, APP_GUID: guid, PRODUCT_NAME: appInfo.productName, PRODUCT_FILENAME: appInfo.productFilename, APP_DESCRIPTION: appInfo.description, VERSION: version, COMPANY_NAME: appInfo.companyName, PROJECT_DIR: _this3.packager.projectDir, BUILD_RESOURCES_DIR: _this3.packager.buildResourcesDir }; if (iconPath != null) { defines.MUI_ICON = iconPath; defines.MUI_UNICON = iconPath; } for (let _ref of _this3.archs) { var _ref2 = _slicedToArray(_ref, 2); let arch = _ref2[0]; let file = _ref2[1]; defines[arch === (_metadata || _load_metadata()).Arch.x64 ? "APP_64" : "APP_32"] = yield file; } const oneClick = _this3.options.oneClick !== false; const installerHeader = oneClick ? null : yield _this3.packager.getResource(_this3.options.installerHeader, "installerHeader.bmp"); if (installerHeader != null) { defines.MUI_HEADERIMAGE = null; defines.MUI_HEADERIMAGE_RIGHT = null; defines.MUI_HEADERIMAGE_BITMAP = installerHeader; } const installerHeaderIcon = oneClick ? yield _this3.packager.getResource(_this3.options.installerHeaderIcon, "installerHeaderIcon.ico") : null; if (installerHeaderIcon != null) { defines.HEADER_ICO = installerHeaderIcon; } if (_this3.options.perMachine === true) { defines.INSTALL_MODE_PER_ALL_USERS = null; } if (!oneClick || _this3.options.perMachine === true) { defines.INSTALL_MODE_PER_ALL_USERS_REQUIRED = null; } if (oneClick) { if (_this3.options.runAfterFinish !== false) { defines.RUN_AFTER_FINISH = null; } } else if (_this3.options.allowElevation !== false) { defines.MULTIUSER_INSTALLMODE_ALLOW_ELEVATION = null; } // Error: invalid VIProductVersion format, should be X.X.X.X // so, we must strip beta const parsedVersion = new (_semver || _load_semver()).SemVer(appInfo.version); const localeId = _this3.options.language || "1033"; const versionKey = [`/LANG=${ localeId } ProductName "${ appInfo.productName }"`, `/LANG=${ localeId } ProductVersion "${ appInfo.version }"`, `/LANG=${ localeId } CompanyName "${ appInfo.companyName }"`, `/LANG=${ localeId } LegalCopyright "${ appInfo.copyright }"`, `/LANG=${ localeId } FileDescription "${ appInfo.description }"`, `/LANG=${ localeId } FileVersion "${ appInfo.buildVersion }"`]; (0, (_util || _load_util()).use)(_this3.packager.platformSpecificBuildOptions.legalTrademarks, function (it) { return versionKey.push(`/LANG=${ localeId } LegalTrademarks "${ it }"`); }); const commands = { OutFile: `"${ installerPath }"`, VIProductVersion: `${ parsedVersion.major }.${ parsedVersion.minor }.${ parsedVersion.patch }.${ appInfo.buildNumber || "0" }`, VIAddVersionKey: versionKey, Unicode: true }; if (packager.devMetadata.build.compression === "store") { commands.SetCompress = "off"; defines.COMPRESS = "off"; } else { commands.SetCompressor = "lzma"; // default is 8: test app installer size 37.2 vs 36 if dict size 64 commands.SetCompressorDictSize = "64"; defines.COMPRESS = "auto"; } if (oneClick) { defines.ONE_CLICK = null; } (0, (_util || _load_util()).debug)(defines); (0, (_util || _load_util()).debug)(commands); if (_this3.packager.options.effectiveOptionComputed != null && _this3.packager.options.effectiveOptionComputed([defines, commands])) { return; } const licenseFile = yield _this3.packager.getResource(_this3.options.license, "license.rtf", "license.txt"); if (licenseFile != null) { defines.LICENSE_FILE = licenseFile; } const customScriptPath = yield _this3.packager.getResource(_this3.options.script, "installer.nsi"); const script = yield (0, (_fsExtraP || _load_fsExtraP()).readFile)(customScriptPath || (_path || _load_path()).join(_this3.nsisTemplatesDir, "installer.nsi"), "utf8"); if (customScriptPath == null) { const uninstallerPath = yield packager.getTempFile("uninstaller.exe"); const isWin = process.platform === "win32"; defines.BUILD_UNINSTALLER = null; defines.UNINSTALLER_OUT_FILE = isWin ? uninstallerPath : (_path || _load_path()).win32.join("Z:", uninstallerPath); yield (0, (_log || _load_log()).subTask)(`Executing makensis — uninstaller`, _this3.executeMakensis(defines, commands, false, script)); yield (0, (_util || _load_util()).exec)(isWin ? installerPath : "wine", isWin ? [] : [installerPath]); yield packager.sign(uninstallerPath); delete defines.BUILD_UNINSTALLER; // platform-specific path, not wine defines.UNINSTALLER_OUT_FILE = uninstallerPath; } else { (0, (_log || _load_log()).log)("Custom NSIS script is used - uninstaller is not signed by electron-builder"); } yield (0, (_log || _load_log()).subTask)(`Executing makensis — installer`, _this3.executeMakensis(defines, commands, true, script)); yield packager.sign(installerPath); const publishConfigs = yield _this3.publishConfigs; const githubArtifactName = `${ appInfo.name }-Setup-${ version }.exe`; if (publishConfigs != null) { let sha2 = null; for (let publishConfig of publishConfigs) { if (publishConfig.provider === "generic" || publishConfig.provider === "github") { if (sha2 == null) { sha2 = yield sha256(installerPath); } const channel = publishConfig.channel || "latest"; if (publishConfig.provider === "generic") { yield (0, (_fsExtraP || _load_fsExtraP()).writeFile)((_path || _load_path()).join(_this3.outDir, `${ channel }.yml`), (0, (_jsYaml || _load_jsYaml()).safeDump)({ version: version, path: installerFilename, sha2: sha2 })); } else { packager.info.eventEmitter.emit("artifactCreated", { data: new Buffer((0, (_jsYaml || _load_jsYaml()).safeDump)({ version: version, path: githubArtifactName, sha2: sha2 })), artifactName: `${ channel }.yml`, packager: packager, publishConfig: publishConfig }); } } } } packager.dispatchArtifactCreated(installerPath, githubArtifactName); })(); } executeMakensis(defines, commands, isInstaller, originalScript) { var _this4 = this; return (0, (_bluebirdLstC || _load_bluebirdLstC()).coroutine)(function* () { const args = _this4.options.warningsAsErrors === false ? [] : ["-WX"]; for (let name of Object.keys(defines)) { const value = defines[name]; if (value == null) { args.push(`-D${ name }`); } else { args.push(`-D${ name }=${ value }`); } } for (let name of Object.keys(commands)) { const value = commands[name]; if (Array.isArray(value)) { for (let c of value) { args.push(`-X${ name } ${ c }`); } } else { args.push(`-X${ name } ${ value }`); } } args.push("-"); const binDir = process.platform === "darwin" ? "mac" : process.platform === "win32" ? "Bin" : "linux"; const nsisPath = yield nsisPathPromise; let script = originalScript; const packager = _this4.packager; const customInclude = yield packager.getResource(_this4.options.include, "installer.nsh"); if (customInclude != null) { script = `!include "${ customInclude }"\n!addincludedir "${ packager.buildResourcesDir }"\n${ script }`; } const fileAssociations = packager.getFileAssociations(); if (fileAssociations.length !== 0) { script = "!include FileAssociation.nsh\n" + script; if (isInstaller) { let registerFileAssociationsScript = ""; for (let item of fileAssociations) { const extensions = (0, (_util || _load_util()).asArray)(item.ext).map((_platformPackager || _load_platformPackager()).normalizeExt); for (let ext of extensions) { const customIcon = yield packager.getResource(item.icon, `${ extensions[0] }.ico`); let installedIconPath = "$appExe,0"; if (customIcon != null) { installedIconPath = `$INSTDIR\\resources\\${ (_path || _load_path()).basename(customIcon) }`; //noinspection SpellCheckingInspection registerFileAssociationsScript += ` File "/oname=${ installedIconPath }" "${ customIcon }"\n`; } const icon = `"${ installedIconPath }"`; const commandText = `"Open with ${ packager.appInfo.productName }"`; const command = '"$appExe $\\"%1$\\""'; registerFileAssociationsScript += ` !insertmacro APP_ASSOCIATE "${ ext }" "${ item.name }" "${ item.description || "" }" ${ icon } ${ commandText } ${ command }\n`; } } script = `!macro registerFileAssociations\n${ registerFileAssociationsScript }!macroend\n${ script }`; } else { let unregisterFileAssociationsScript = ""; for (let item of fileAssociations) { for (let ext of (0, (_util || _load_util()).asArray)(item.ext)) { unregisterFileAssociationsScript += ` !insertmacro APP_UNASSOCIATE "${ (0, (_platformPackager || _load_platformPackager()).normalizeExt)(ext) }" "${ item.name }"\n`; } } script = `!macro unregisterFileAssociations\n${ unregisterFileAssociationsScript }!macroend\n${ script }`; } } if ((_util || _load_util()).debug.enabled) { process.stdout.write("\n\nNSIS script:\n\n" + script + "\n\n---\nEnd of NSIS script.\n\n"); } yield new (_bluebirdLstC2 || _load_bluebirdLstC2()).default(function (resolve, reject) { const command = (_path || _load_path()).join(nsisPath, binDir, process.platform === "win32" ? "makensis.exe" : "makensis"); const childProcess = (0, (_util || _load_util()).doSpawn)(command, args, { // we use NSIS_CONFIG_CONST_DATA_PATH=no to build makensis on Linux, but in any case it doesn't use stubs as MacOS/Windows version, so, we explicitly set NSISDIR env: Object.assign({}, process.env, { NSISDIR: nsisPath }), cwd: _this4.nsisTemplatesDir }, true); (0, (_util || _load_util()).handleProcess)("close", childProcess, command, resolve, reject); childProcess.stdin.end(script); }); })(); } } exports.default = NsisTarget; function sha256(file) { return new (_bluebirdLstC2 || _load_bluebirdLstC2()).default((resolve, reject) => { const hash = (0, (_crypto || _load_crypto()).createHash)("sha256"); hash.on("error", reject).setEncoding("hex"); (0, (_fsExtraP || _load_fsExtraP()).createReadStream)(file).on("error", reject).on("end", () => { hash.end(); resolve(hash.read()); }).pipe(hash, { end: false }); }); } //# sourceMappingURL=nsis.js.map