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

483 lines (448 loc) 22.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.checkFileInArchive = exports.createAsarArchive = exports.walk = 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 walk = exports.walk = (() => { var _ref = (0, (_bluebirdLstC || _load_bluebirdLstC()).coroutine)(function* (initialDirPath, consumer, filter) { const result = []; const queue = [initialDirPath]; let addDirToResult = false; while (queue.length > 0) { const dirPath = queue.pop(); if (addDirToResult) { result.push(dirPath); } else { addDirToResult = true; } const childNames = yield (0, (_fsExtraP || _load_fsExtraP()).readdir)(dirPath); childNames.sort(); const dirs = []; yield (_bluebirdLstC2 || _load_bluebirdLstC2()).default.map(childNames, function (name) { const filePath = dirPath + (_path || _load_path()).sep + name; return (0, (_fsExtraP || _load_fsExtraP()).lstat)(filePath).then(function (stat) { if (filter != null && !filter(filePath, stat)) { return; } if (consumer != null) { consumer(filePath, stat); } if (stat.isDirectory()) { dirs.push(filePath); } else { result.push(filePath); } }); }, concurrency); for (let i = dirs.length - 1; i > -1; i--) { queue.push(dirs[i]); } } return result; }); return function walk(_x, _x2, _x3) { return _ref.apply(this, arguments); }; })(); let createAsarArchive = exports.createAsarArchive = (() => { var _ref2 = (0, (_bluebirdLstC || _load_bluebirdLstC()).coroutine)(function* (src, resourcesPath, options, filter) { // sort files to minimize file change (i.e. asar file is not changed dramatically on small change) yield new AsarPackager(src, resourcesPath, options).pack(filter); }); return function createAsarArchive(_x4, _x5, _x6, _x7) { return _ref2.apply(this, arguments); }; })(); let checkFileInArchive = exports.checkFileInArchive = (() => { var _ref3 = (0, (_bluebirdLstC || _load_bluebirdLstC()).coroutine)(function* (asarFile, relativeFile, messagePrefix) { function error(text) { return new Error(`${ messagePrefix } "${ relativeFile }" in the "${ asarFile }" ${ text }`); } let stat; try { stat = (0, (_asarElectronBuilder || _load_asarElectronBuilder()).statFile)(asarFile, relativeFile); } catch (e) { const fileStat = yield (0, (_util || _load_util()).statOrNull)(asarFile); if (fileStat == null) { throw error(`does not exist. Seems like a wrong configuration.`); } try { (0, (_asarElectronBuilder || _load_asarElectronBuilder()).listPackage)(asarFile); } catch (e) { throw error(`is corrupted: ${ e }`); } // asar throws error on access to undefined object (info.link) stat = null; } if (stat == null) { throw error(`does not exist. Seems like a wrong configuration.`); } if (stat.size === 0) { throw error(`is corrupted: size 0`); } }); return function checkFileInArchive(_x8, _x9, _x10) { return _ref3.apply(this, arguments); }; })(); var _asarElectronBuilder; function _load_asarElectronBuilder() { return _asarElectronBuilder = require("asar-electron-builder"); } var _util; function _load_util() { return _util = require("./util/util"); } var _fsExtraP; function _load_fsExtraP() { return _fsExtraP = require("fs-extra-p"); } var _path; function _load_path() { return _path = _interopRequireWildcard(require("path")); } var _log; function _load_log() { return _log = require("./util/log"); } var _minimatch; function _load_minimatch() { return _minimatch = require("minimatch"); } var _deepAssign; function _load_deepAssign() { return _deepAssign = require("./util/deepAssign"); } 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 isBinaryFile = (_bluebirdLstC2 || _load_bluebirdLstC2()).default.promisify(require("isbinaryfile")); const pickle = require("chromium-pickle-js"); const Filesystem = require("asar-electron-builder/lib/filesystem"); const UINT64 = require("cuint").UINT64; const MAX_FILE_REQUESTS = 8; const concurrency = { concurrency: MAX_FILE_REQUESTS }; const NODE_MODULES_PATTERN = (_path || _load_path()).sep + "node_modules" + (_path || _load_path()).sep; function isUnpackDir(path, pattern, rawPattern) { return path.startsWith(rawPattern) || pattern.match(path); } class AsarPackager { constructor(src, resourcesPath, options) { this.src = src; this.resourcesPath = resourcesPath; this.options = options; this.toPack = []; this.fs = new Filesystem(this.src); this.changedFiles = new Map(); this.outFile = (_path || _load_path()).join(this.resourcesPath, "app.asar"); } pack(filter) { var _this = this; return (0, (_bluebirdLstC || _load_bluebirdLstC()).coroutine)(function* () { const metadata = new Map(); const files = yield walk(_this.src, function (it, stat) { metadata.set(it, stat); }, filter); yield _this.createPackageFromFiles(_this.options.ordering == null ? files : yield _this.order(files), metadata); yield _this.writeAsarFile(); })(); } getSrcRealPath() { if (this.srcRealPath == null) { this.srcRealPath = (0, (_fsExtraP || _load_fsExtraP()).realpath)(this.src); } return this.srcRealPath; } detectUnpackedDirs(files, metadata, autoUnpackDirs, createDirPromises, unpackedDest, fileIndexToModulePackageData) { var _this2 = this; return (0, (_bluebirdLstC || _load_bluebirdLstC()).coroutine)(function* () { const packageJsonStringLength = "package.json".length; const readPackageJsonPromises = []; for (let i = 0, n = files.length; i < n; i++) { const file = files[i]; const index = file.lastIndexOf(NODE_MODULES_PATTERN); if (index < 0) { continue; } const nextSlashIndex = file.indexOf((_path || _load_path()).sep, index + NODE_MODULES_PATTERN.length + 1); if (nextSlashIndex < 0) { continue; } if (!metadata.get(file).isFile()) { continue; } const nodeModuleDir = file.substring(0, nextSlashIndex); if (file.length === nodeModuleDir.length + 1 + packageJsonStringLength && file.endsWith("package.json")) { const promise = (0, (_fsExtraP || _load_fsExtraP()).readJson)(file); if (readPackageJsonPromises.length > MAX_FILE_REQUESTS) { yield (_bluebirdLstC2 || _load_bluebirdLstC2()).default.all(readPackageJsonPromises); readPackageJsonPromises.length = 0; } readPackageJsonPromises.push(promise); fileIndexToModulePackageData[i] = promise; } if (autoUnpackDirs.has(nodeModuleDir)) { const fileParent = (_path || _load_path()).dirname(file); if (fileParent !== nodeModuleDir && !autoUnpackDirs.has(fileParent)) { autoUnpackDirs.add(fileParent); createDirPromises.push((0, (_fsExtraP || _load_fsExtraP()).ensureDir)((_path || _load_path()).join(unpackedDest, (_path || _load_path()).relative(_this2.src, fileParent)))); if (createDirPromises.length > MAX_FILE_REQUESTS) { yield (_bluebirdLstC2 || _load_bluebirdLstC2()).default.all(createDirPromises); createDirPromises.length = 0; } } continue; } const ext = (_path || _load_path()).extname(file); let shouldUnpack = false; if (ext === ".dll" || ext === ".exe") { shouldUnpack = true; } else if (ext === "") { shouldUnpack = yield isBinaryFile(file); } if (!shouldUnpack) { continue; } (0, (_util || _load_util()).debug)(`${ (_path || _load_path()).relative(_this2.src, nodeModuleDir) } is not packed into asar archive - contains executable code`); let fileParent = (_path || _load_path()).dirname(file); // create parent dir to be able to copy file later without directory existence check createDirPromises.push((0, (_fsExtraP || _load_fsExtraP()).ensureDir)((_path || _load_path()).join(unpackedDest, (_path || _load_path()).relative(_this2.src, fileParent)))); if (createDirPromises.length > MAX_FILE_REQUESTS) { yield (_bluebirdLstC2 || _load_bluebirdLstC2()).default.all(createDirPromises); createDirPromises.length = 0; } while (fileParent !== nodeModuleDir) { autoUnpackDirs.add(fileParent); fileParent = (_path || _load_path()).dirname(fileParent); } autoUnpackDirs.add(nodeModuleDir); } if (readPackageJsonPromises.length > 0) { yield (_bluebirdLstC2 || _load_bluebirdLstC2()).default.all(readPackageJsonPromises); } if (createDirPromises.length > 0) { yield (_bluebirdLstC2 || _load_bluebirdLstC2()).default.all(createDirPromises); createDirPromises.length = 0; } })(); } createPackageFromFiles(files, metadata) { var _this3 = this; return (0, (_bluebirdLstC || _load_bluebirdLstC()).coroutine)(function* () { // search auto unpacked dir const autoUnpackDirs = new Set(); const createDirPromises = [(0, (_fsExtraP || _load_fsExtraP()).ensureDir)((_path || _load_path()).dirname(_this3.outFile))]; const unpackedDest = `${ _this3.outFile }.unpacked`; const fileIndexToModulePackageData = new Array(files.length); if (_this3.options.smartUnpack !== false) { yield _this3.detectUnpackedDirs(files, metadata, autoUnpackDirs, createDirPromises, unpackedDest, fileIndexToModulePackageData); } const unpackDir = _this3.options.unpackDir == null ? null : new (_minimatch || _load_minimatch()).Minimatch(_this3.options.unpackDir); const unpack = _this3.options.unpack == null ? null : new (_minimatch || _load_minimatch()).Minimatch(_this3.options.unpack, { matchBase: true }); const copyPromises = []; const mainPackageJson = (_path || _load_path()).join(_this3.src, "package.json"); for (let i = 0, n = files.length; i < n; i++) { const file = files[i]; const stat = metadata.get(file); if (stat.isFile()) { const fileParent = (_path || _load_path()).dirname(file); const dirNode = _this3.fs.searchNodeFromPath(fileParent); if (dirNode.unpacked && createDirPromises.length > 0) { yield (_bluebirdLstC2 || _load_bluebirdLstC2()).default.all(createDirPromises); createDirPromises.length = 0; } const packageDataPromise = fileIndexToModulePackageData[i]; let newData = null; if (packageDataPromise == null) { if (_this3.options.extraMetadata != null && file === mainPackageJson) { newData = JSON.stringify((0, (_deepAssign || _load_deepAssign()).deepAssign)((yield (0, (_fsExtraP || _load_fsExtraP()).readJson)(file)), _this3.options.extraMetadata), null, 2); } } else { newData = cleanupPackageJson(packageDataPromise.value()); } const fileSize = newData == null ? stat.size : Buffer.byteLength(newData); const node = _this3.fs.searchNodeFromPath(file); node.size = fileSize; if (dirNode.unpacked || unpack != null && unpack.match(file)) { node.unpacked = true; if (!dirNode.unpacked) { createDirPromises.push((0, (_fsExtraP || _load_fsExtraP()).ensureDir)((_path || _load_path()).join(unpackedDest, (_path || _load_path()).relative(_this3.src, fileParent)))); yield (_bluebirdLstC2 || _load_bluebirdLstC2()).default.all(createDirPromises); createDirPromises.length = 0; } const unpackedFile = (_path || _load_path()).join(unpackedDest, (_path || _load_path()).relative(_this3.src, file)); copyPromises.push(newData == null ? copyFile(file, unpackedFile, stat) : (0, (_fsExtraP || _load_fsExtraP()).writeFile)(unpackedFile, newData)); if (copyPromises.length > MAX_FILE_REQUESTS) { yield (_bluebirdLstC2 || _load_bluebirdLstC2()).default.all(copyPromises); copyPromises.length = 0; } } else { if (newData != null) { _this3.changedFiles.set(file, newData); } if (fileSize > 4294967295) { throw new Error(`${ file }: file size can not be larger than 4.2GB`); } node.offset = _this3.fs.offset.toString(); //noinspection JSBitwiseOperatorUsage if (process.platform !== "win32" && stat.mode & 0x40) { node.executable = true; } _this3.toPack.push(file); _this3.fs.offset.add(UINT64(fileSize)); } } else if (stat.isDirectory()) { let unpacked = false; if (autoUnpackDirs.has(file)) { unpacked = true; } else { unpacked = unpackDir != null && isUnpackDir((_path || _load_path()).relative(_this3.src, file), unpackDir, _this3.options.unpackDir); if (unpacked) { createDirPromises.push((0, (_fsExtraP || _load_fsExtraP()).ensureDir)((_path || _load_path()).join(unpackedDest, (_path || _load_path()).relative(_this3.src, file)))); } else { for (let d of autoUnpackDirs) { if (file.length > d.length + 2 && file[d.length] === (_path || _load_path()).sep && file.startsWith(d)) { unpacked = true; autoUnpackDirs.add(file); // not all dirs marked as unpacked after first iteration - because node module dir can be marked as unpacked after processing node module dir content // e.g. node-notifier/example/advanced.js processed, but only on process vendor/terminal-notifier.app module will be marked as unpacked createDirPromises.push((0, (_fsExtraP || _load_fsExtraP()).ensureDir)((_path || _load_path()).join(unpackedDest, (_path || _load_path()).relative(_this3.src, file)))); break; } } } } _this3.fs.insertDirectory(file, unpacked); } else if (stat.isSymbolicLink()) { yield _this3.addLink(file); } } yield (_bluebirdLstC2 || _load_bluebirdLstC2()).default.all(copyPromises); })(); } addLink(file) { var _this4 = this; return (0, (_bluebirdLstC || _load_bluebirdLstC()).coroutine)(function* () { const realFile = yield (0, (_fsExtraP || _load_fsExtraP()).realpath)(file); const link = (_path || _load_path()).relative((yield _this4.getSrcRealPath()), realFile); if (link.startsWith("..")) { throw new Error(realFile + ": file links out of the package"); } else { _this4.fs.searchNodeFromPath(file).link = link; } })(); } writeAsarFile() { const headerPickle = pickle.createEmpty(); headerPickle.writeString(JSON.stringify(this.fs.header)); const headerBuf = headerPickle.toBuffer(); const sizePickle = pickle.createEmpty(); sizePickle.writeUInt32(headerBuf.length); const sizeBuf = sizePickle.toBuffer(); const writeStream = (0, (_fsExtraP || _load_fsExtraP()).createWriteStream)(this.outFile); return new (_bluebirdLstC2 || _load_bluebirdLstC2()).default((resolve, reject) => { writeStream.on("error", reject); writeStream.once("finish", resolve); writeStream.write(sizeBuf); let w; w = (list, index) => { if (list.length === index) { writeStream.end(); return; } const file = list[index]; const data = this.changedFiles.get(file); if (data != null) { writeStream.write(data, () => w(list, index + 1)); return; } const readStream = (0, (_fsExtraP || _load_fsExtraP()).createReadStream)(file); readStream.on("error", reject); readStream.once("end", () => w(list, index + 1)); readStream.pipe(writeStream, { end: false }); }; writeStream.write(headerBuf, () => w(this.toPack, 0)); }); } order(filenames) { var _this5 = this; return (0, (_bluebirdLstC || _load_bluebirdLstC()).coroutine)(function* () { const orderingFiles = (yield (0, (_fsExtraP || _load_fsExtraP()).readFile)(_this5.options.ordering, "utf8")).split("\n").map(function (line) { if (line.indexOf(":") !== -1) { line = line.split(":").pop(); } line = line.trim(); if (line[0] === "/") { line = line.slice(1); } return line; }); const ordering = []; for (let file of orderingFiles) { let pathComponents = file.split((_path || _load_path()).sep); let str = _this5.src; for (let pathComponent of pathComponents) { str = (_path || _load_path()).join(str, pathComponent); ordering.push(str); } } const filenamesSorted = []; let missing = 0; const total = filenames.length; for (let file of ordering) { if (!(filenamesSorted.indexOf(file) !== -1) && filenames.indexOf(file) !== -1) { filenamesSorted.push(file); } } for (let file of filenames) { if (!(filenamesSorted.indexOf(file) !== -1)) { filenamesSorted.push(file); missing += 1; } } (0, (_log || _load_log()).log)(`Ordering file has ${ (total - missing) / total * 100 }% coverage.`); return filenamesSorted; })(); } } function cleanupPackageJson(data) { try { let changed = false; for (let prop of Object.getOwnPropertyNames(data)) { if (prop[0] === "_" || prop === "dist" || prop === "gitHead" || prop === "keywords") { delete data[prop]; changed = true; } } if (changed) { return JSON.stringify(data, null, 2); } } catch (e) { (0, (_util || _load_util()).debug)(e); } return null; } function copyFile(src, dest, stats) { return new (_bluebirdLstC2 || _load_bluebirdLstC2()).default(function (resolve, reject) { const readStream = (0, (_fsExtraP || _load_fsExtraP()).createReadStream)(src); const writeStream = (0, (_fsExtraP || _load_fsExtraP()).createWriteStream)(dest, { mode: stats.mode }); readStream.on("error", reject); writeStream.on("error", reject); writeStream.on("open", function () { readStream.pipe(writeStream); }); writeStream.once("finish", resolve); }); } //# sourceMappingURL=asarUtil.js.map