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
JavaScript
;
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