forked from olcxjas-softworks/LarpixClient
update electron to v43
This commit is contained in:
parent
68ac0beedf
commit
fb6c8b6ee9
5385 changed files with 513060 additions and 123058 deletions
4
electron/node_modules/app-builder-lib/out/Framework.d.ts
generated
vendored
4
electron/node_modules/app-builder-lib/out/Framework.d.ts
generated
vendored
|
|
@ -1,6 +1,6 @@
|
|||
import { FileTransformer } from "builder-util/out/fs";
|
||||
import { FileTransformer } from "builder-util";
|
||||
import { AsarIntegrity } from "./asar/integrity";
|
||||
import { Platform, PlatformPackager, ElectronPlatformName, AfterPackContext } from "./index";
|
||||
import { AfterPackContext, ElectronPlatformName, Platform, PlatformPackager } from "./index";
|
||||
export interface Framework {
|
||||
readonly name: string;
|
||||
readonly version: string;
|
||||
|
|
|
|||
3
electron/node_modules/app-builder-lib/out/Framework.js
generated
vendored
3
electron/node_modules/app-builder-lib/out/Framework.js
generated
vendored
|
|
@ -1,8 +1,7 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.isElectronBased = void 0;
|
||||
exports.isElectronBased = isElectronBased;
|
||||
function isElectronBased(framework) {
|
||||
return framework.name === "electron";
|
||||
}
|
||||
exports.isElectronBased = isElectronBased;
|
||||
//# sourceMappingURL=Framework.js.map
|
||||
2
electron/node_modules/app-builder-lib/out/Framework.js.map
generated
vendored
2
electron/node_modules/app-builder-lib/out/Framework.js.map
generated
vendored
|
|
@ -1 +1 @@
|
|||
{"version":3,"file":"Framework.js","sourceRoot":"","sources":["../src/Framework.ts"],"names":[],"mappings":";;;AAmDA,SAAgB,eAAe,CAAC,SAAoB;IAClD,OAAO,SAAS,CAAC,IAAI,KAAK,UAAU,CAAA;AACtC,CAAC;AAFD,0CAEC","sourcesContent":["import { FileTransformer } from \"builder-util/out/fs\"\nimport { AsarIntegrity } from \"./asar/integrity\"\nimport { Platform, PlatformPackager, ElectronPlatformName, AfterPackContext } from \"./index\"\n\nexport interface Framework {\n readonly name: string\n readonly version: string\n readonly distMacOsAppName: string\n readonly macOsDefaultTargets: Array<string>\n readonly defaultAppIdPrefix: string\n\n readonly isNpmRebuildRequired: boolean\n\n readonly isCopyElevateHelper: boolean\n\n getDefaultIcon?(platform: Platform): string | null\n\n getMainFile?(platform: Platform): string | null\n\n getExcludedDependencies?(platform: Platform): Array<string> | null\n\n prepareApplicationStageDirectory(options: PrepareApplicationStageDirectoryOptions): Promise<any>\n\n beforeCopyExtraFiles?(options: BeforeCopyExtraFilesOptions): Promise<any>\n\n afterPack?(context: AfterPackContext): Promise<any>\n\n createTransformer?(): FileTransformer | null\n}\n\nexport interface BeforeCopyExtraFilesOptions {\n packager: PlatformPackager<any>\n appOutDir: string\n\n asarIntegrity: AsarIntegrity | null\n\n // ElectronPlatformName\n platformName: string\n}\n\nexport interface PrepareApplicationStageDirectoryOptions {\n readonly packager: PlatformPackager<any>\n /**\n * Platform doesn't process application output directory in any way. Unpack implementation must create or empty dir if need.\n */\n readonly appOutDir: string\n readonly platformName: ElectronPlatformName\n readonly arch: string\n readonly version: string\n}\n\nexport function isElectronBased(framework: Framework): boolean {\n return framework.name === \"electron\"\n}\n"]}
|
||||
{"version":3,"file":"Framework.js","sourceRoot":"","sources":["../src/Framework.ts"],"names":[],"mappings":";;AAmDA,0CAEC;AAFD,SAAgB,eAAe,CAAC,SAAoB;IAClD,OAAO,SAAS,CAAC,IAAI,KAAK,UAAU,CAAA;AACtC,CAAC","sourcesContent":["import { FileTransformer } from \"builder-util\"\nimport { AsarIntegrity } from \"./asar/integrity\"\nimport { AfterPackContext, ElectronPlatformName, Platform, PlatformPackager } from \"./index\"\n\nexport interface Framework {\n readonly name: string\n readonly version: string\n readonly distMacOsAppName: string\n readonly macOsDefaultTargets: Array<string>\n readonly defaultAppIdPrefix: string\n\n readonly isNpmRebuildRequired: boolean\n\n readonly isCopyElevateHelper: boolean\n\n getDefaultIcon?(platform: Platform): string | null\n\n getMainFile?(platform: Platform): string | null\n\n getExcludedDependencies?(platform: Platform): Array<string> | null\n\n prepareApplicationStageDirectory(options: PrepareApplicationStageDirectoryOptions): Promise<any>\n\n beforeCopyExtraFiles?(options: BeforeCopyExtraFilesOptions): Promise<any>\n\n afterPack?(context: AfterPackContext): Promise<any>\n\n createTransformer?(): FileTransformer | null\n}\n\nexport interface BeforeCopyExtraFilesOptions {\n packager: PlatformPackager<any>\n appOutDir: string\n\n asarIntegrity: AsarIntegrity | null\n\n // ElectronPlatformName\n platformName: string\n}\n\nexport interface PrepareApplicationStageDirectoryOptions {\n readonly packager: PlatformPackager<any>\n /**\n * Platform doesn't process application output directory in any way. Unpack implementation must create or empty dir if need.\n */\n readonly appOutDir: string\n readonly platformName: ElectronPlatformName\n readonly arch: string\n readonly version: string\n}\n\nexport function isElectronBased(framework: Framework): boolean {\n return framework.name === \"electron\"\n}\n"]}
|
||||
4
electron/node_modules/app-builder-lib/out/ProtonFramework.d.ts
generated
vendored
4
electron/node_modules/app-builder-lib/out/ProtonFramework.d.ts
generated
vendored
|
|
@ -1,10 +1,10 @@
|
|||
import { FileTransformer } from "builder-util/out/fs";
|
||||
import { FileTransformer } from "builder-util";
|
||||
import { Platform } from "./core";
|
||||
import { LibUiFramework } from "./frameworks/LibUiFramework";
|
||||
export declare class ProtonFramework extends LibUiFramework {
|
||||
readonly name = "proton";
|
||||
readonly defaultAppIdPrefix = "com.proton-native.";
|
||||
constructor(version: string, distMacOsAppName: string, isUseLaunchUi: boolean);
|
||||
constructor(version: string, macOsProductName: string, isUseLaunchUi: boolean);
|
||||
getDefaultIcon(platform: Platform): string;
|
||||
createTransformer(): FileTransformer | null;
|
||||
}
|
||||
|
|
|
|||
15
electron/node_modules/app-builder-lib/out/ProtonFramework.js
generated
vendored
15
electron/node_modules/app-builder-lib/out/ProtonFramework.js
generated
vendored
|
|
@ -8,21 +8,21 @@ const fileTransformer_1 = require("./fileTransformer");
|
|||
const LibUiFramework_1 = require("./frameworks/LibUiFramework");
|
||||
const pathManager_1 = require("./util/pathManager");
|
||||
class ProtonFramework extends LibUiFramework_1.LibUiFramework {
|
||||
constructor(version, distMacOsAppName, isUseLaunchUi) {
|
||||
super(version, distMacOsAppName, isUseLaunchUi);
|
||||
constructor(version, macOsProductName, isUseLaunchUi) {
|
||||
super(version, macOsProductName, isUseLaunchUi);
|
||||
this.name = "proton";
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
this.defaultAppIdPrefix = "com.proton-native.";
|
||||
}
|
||||
getDefaultIcon(platform) {
|
||||
if (platform === core_1.Platform.WINDOWS) {
|
||||
return pathManager_1.getTemplatePath("icons/proton-native/proton-native.ico");
|
||||
return (0, pathManager_1.getTemplatePath)("icons/proton-native/proton-native.ico");
|
||||
}
|
||||
else if (platform === core_1.Platform.LINUX) {
|
||||
return pathManager_1.getTemplatePath("icons/proton-native/linux");
|
||||
return (0, pathManager_1.getTemplatePath)("icons/proton-native/linux");
|
||||
}
|
||||
else {
|
||||
return pathManager_1.getTemplatePath("icons/proton-native/proton-native.icns");
|
||||
return (0, pathManager_1.getTemplatePath)("icons/proton-native/proton-native.icns");
|
||||
}
|
||||
}
|
||||
createTransformer() {
|
||||
|
|
@ -30,21 +30,20 @@ class ProtonFramework extends LibUiFramework_1.LibUiFramework {
|
|||
const babelOptions = { ast: false, sourceMaps: "inline" };
|
||||
if (process.env.TEST_SET_BABEL_PRESET === "true") {
|
||||
babel = require("@babel/core");
|
||||
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
||||
babel = testOnlyBabel(babel, babelOptions, this.version);
|
||||
}
|
||||
else {
|
||||
try {
|
||||
babel = require("babel-core");
|
||||
}
|
||||
catch (e) {
|
||||
catch (_e) {
|
||||
// babel isn't installed
|
||||
builder_util_1.log.debug(null, "don't transpile source code using Babel");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
builder_util_1.log.info({
|
||||
options: builder_util_runtime_1.safeStringifyJson(babelOptions, new Set(["presets"])),
|
||||
options: (0, builder_util_runtime_1.safeStringifyJson)(babelOptions, new Set(["presets"])),
|
||||
}, "transpile source code using Babel");
|
||||
return (file) => {
|
||||
if (!(file.endsWith(".js") || file.endsWith(".jsx")) || file.includes(fileTransformer_1.NODE_MODULES_PATTERN)) {
|
||||
|
|
|
|||
2
electron/node_modules/app-builder-lib/out/ProtonFramework.js.map
generated
vendored
2
electron/node_modules/app-builder-lib/out/ProtonFramework.js.map
generated
vendored
File diff suppressed because one or more lines are too long
4
electron/node_modules/app-builder-lib/out/appInfo.d.ts
generated
vendored
4
electron/node_modules/app-builder-lib/out/appInfo.d.ts
generated
vendored
|
|
@ -1,3 +1,4 @@
|
|||
import { Nullish } from "builder-util-runtime";
|
||||
import { PlatformSpecificBuildOptions } from "./options/PlatformSpecificBuildOptions";
|
||||
import { Packager } from "./packager";
|
||||
export declare function smarten(s: string): string;
|
||||
|
|
@ -6,6 +7,7 @@ export declare class AppInfo {
|
|||
private readonly platformSpecificOptions;
|
||||
readonly description: string;
|
||||
readonly version: string;
|
||||
readonly type: string | undefined;
|
||||
readonly shortVersion: string | undefined;
|
||||
readonly shortVersionWindows: string | undefined;
|
||||
readonly buildNumber: string | undefined;
|
||||
|
|
@ -13,7 +15,7 @@ export declare class AppInfo {
|
|||
readonly productName: string;
|
||||
readonly sanitizedProductName: string;
|
||||
readonly productFilename: string;
|
||||
constructor(info: Packager, buildVersion: string | null | undefined, platformSpecificOptions?: PlatformSpecificBuildOptions | null);
|
||||
constructor(info: Packager, buildVersion: string | Nullish, platformSpecificOptions?: PlatformSpecificBuildOptions | null, normalizeNfd?: boolean);
|
||||
get channel(): string | null;
|
||||
getVersionInWeirdWindowsForm(isSetBuildNumber?: boolean): string;
|
||||
private get notNullDevMetadata();
|
||||
|
|
|
|||
43
electron/node_modules/app-builder-lib/out/appInfo.js
generated
vendored
43
electron/node_modules/app-builder-lib/out/appInfo.js
generated
vendored
|
|
@ -1,10 +1,12 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.filterCFBundleIdentifier = exports.AppInfo = exports.smarten = void 0;
|
||||
exports.AppInfo = void 0;
|
||||
exports.smarten = smarten;
|
||||
exports.filterCFBundleIdentifier = filterCFBundleIdentifier;
|
||||
const builder_util_1 = require("builder-util");
|
||||
const filename_1 = require("builder-util/out/filename");
|
||||
const semver_1 = require("semver");
|
||||
const macroExpander_1 = require("./util/macroExpander");
|
||||
const filename_1 = require("./util/filename");
|
||||
// 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) {
|
||||
|
|
@ -18,13 +20,14 @@ function smarten(s) {
|
|||
s = s.replace(/"/g, "\u201d");
|
||||
return s;
|
||||
}
|
||||
exports.smarten = smarten;
|
||||
class AppInfo {
|
||||
constructor(info, buildVersion, platformSpecificOptions = null) {
|
||||
constructor(info, buildVersion, platformSpecificOptions = null, normalizeNfd = false) {
|
||||
var _a;
|
||||
this.info = info;
|
||||
this.platformSpecificOptions = platformSpecificOptions;
|
||||
this.description = smarten(this.info.metadata.description || "");
|
||||
this.version = info.metadata.version;
|
||||
this.type = info.metadata.type;
|
||||
if (buildVersion == null) {
|
||||
buildVersion = info.config.buildVersion;
|
||||
}
|
||||
|
|
@ -37,7 +40,7 @@ class AppInfo {
|
|||
this.buildNumber = info.config.buildNumber || buildNumberEnvs;
|
||||
if (buildVersion == null) {
|
||||
buildVersion = this.version;
|
||||
if (!builder_util_1.isEmptyOrSpaces(this.buildNumber)) {
|
||||
if (!(0, builder_util_1.isEmptyOrSpaces)(this.buildNumber)) {
|
||||
buildVersion += `.${this.buildNumber}`;
|
||||
}
|
||||
}
|
||||
|
|
@ -49,24 +52,37 @@ class AppInfo {
|
|||
this.shortVersionWindows = info.metadata.shortVersionWindows;
|
||||
}
|
||||
this.productName = info.config.productName || info.metadata.productName || info.metadata.name;
|
||||
this.sanitizedProductName = filename_1.sanitizeFileName(this.productName);
|
||||
this.productFilename = (platformSpecificOptions === null || platformSpecificOptions === void 0 ? void 0 : platformSpecificOptions.executableName) != null ? filename_1.sanitizeFileName(platformSpecificOptions.executableName) : this.sanitizedProductName;
|
||||
this.sanitizedProductName = (0, filename_1.sanitizeFileName)(this.productName, normalizeNfd);
|
||||
const executableName = (_a = platformSpecificOptions === null || platformSpecificOptions === void 0 ? void 0 : platformSpecificOptions.executableName) !== null && _a !== void 0 ? _a : info.config.executableName;
|
||||
this.productFilename = executableName != null ? (0, filename_1.sanitizeFileName)(executableName, normalizeNfd) : this.sanitizedProductName;
|
||||
}
|
||||
get channel() {
|
||||
const prereleaseInfo = semver_1.prerelease(this.version);
|
||||
const prereleaseInfo = (0, semver_1.prerelease)(this.version);
|
||||
if (prereleaseInfo != null && prereleaseInfo.length > 0) {
|
||||
return prereleaseInfo[0];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
getVersionInWeirdWindowsForm(isSetBuildNumber = true) {
|
||||
const parsedVersion = new semver_1.SemVer(this.version);
|
||||
const [major, maybe_minor, maybe_patch] = this.version.split(".").map(versionPart => parseInt(versionPart));
|
||||
// The major component must be present. Here it can be either NaN or undefined, which
|
||||
// both returns true from isNaN.
|
||||
if (isNaN(major)) {
|
||||
throw new Error(`Invalid major number in: ${this.version}`);
|
||||
}
|
||||
// Allow missing version parts. Minor and patch can be left out and default to zero
|
||||
const minor = maybe_minor !== null && maybe_minor !== void 0 ? maybe_minor : 0;
|
||||
const patch = maybe_patch !== null && maybe_patch !== void 0 ? maybe_patch : 0;
|
||||
// ... but reject non-integer version parts. '1.a' is not going to fly
|
||||
if (isNaN(minor) || isNaN(patch)) {
|
||||
throw new Error(`Invalid minor or patch number in: ${this.version}`);
|
||||
}
|
||||
// https://github.com/electron-userland/electron-builder/issues/2635#issuecomment-371792272
|
||||
let buildNumber = isSetBuildNumber ? this.buildNumber : null;
|
||||
if (buildNumber == null || !/^\d+$/.test(buildNumber)) {
|
||||
buildNumber = "0";
|
||||
}
|
||||
return `${parsedVersion.major}.${parsedVersion.minor}.${parsedVersion.patch}.${buildNumber}`;
|
||||
return `${major}.${minor}.${patch}.${buildNumber}`;
|
||||
}
|
||||
get notNullDevMetadata() {
|
||||
return this.info.devMetadata || {};
|
||||
|
|
@ -86,7 +102,7 @@ class AppInfo {
|
|||
const info = this.info;
|
||||
return `${info.framework.defaultAppIdPrefix}${info.metadata.name.toLowerCase()}`;
|
||||
};
|
||||
if (appId != null && (appId === "your.id" || builder_util_1.isEmptyOrSpaces(appId))) {
|
||||
if (appId != null && (appId === "your.id" || (0, builder_util_1.isEmptyOrSpaces)(appId))) {
|
||||
const incorrectAppId = appId;
|
||||
appId = generateDefaultAppId();
|
||||
builder_util_1.log.warn(`do not use "${incorrectAppId}" as appId, "${appId}" will be used instead`);
|
||||
|
|
@ -105,7 +121,7 @@ class AppInfo {
|
|||
return name.startsWith("@") ? this.sanitizedProductName : name;
|
||||
}
|
||||
get sanitizedName() {
|
||||
return filename_1.sanitizeFileName(this.name);
|
||||
return (0, filename_1.sanitizeFileName)(this.name);
|
||||
}
|
||||
get updaterCacheDirName() {
|
||||
return this.sanitizedName.toLowerCase() + "-updater";
|
||||
|
|
@ -113,7 +129,7 @@ class AppInfo {
|
|||
get copyright() {
|
||||
const copyright = this.info.config.copyright;
|
||||
if (copyright != null) {
|
||||
return macroExpander_1.expandMacro(copyright, null, this);
|
||||
return (0, macroExpander_1.expandMacro)(copyright, null, this);
|
||||
}
|
||||
return `Copyright © ${new Date().getFullYear()} ${this.companyName || this.productName}`;
|
||||
}
|
||||
|
|
@ -133,5 +149,4 @@ function filterCFBundleIdentifier(identifier) {
|
|||
// Apple documentation: https://developer.apple.com/library/mac/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/20001431-102070
|
||||
return identifier.replace(/ /g, "-").replace(/[^a-zA-Z0-9.-]/g, "");
|
||||
}
|
||||
exports.filterCFBundleIdentifier = filterCFBundleIdentifier;
|
||||
//# sourceMappingURL=appInfo.js.map
|
||||
2
electron/node_modules/app-builder-lib/out/appInfo.js.map
generated
vendored
2
electron/node_modules/app-builder-lib/out/appInfo.js.map
generated
vendored
File diff suppressed because one or more lines are too long
11
electron/node_modules/app-builder-lib/out/asar/asar.d.ts
generated
vendored
11
electron/node_modules/app-builder-lib/out/asar/asar.d.ts
generated
vendored
|
|
@ -1,4 +1,3 @@
|
|||
/// <reference types="node" />
|
||||
import { Stats } from "fs-extra";
|
||||
export interface ReadAsarHeader {
|
||||
readonly header: string;
|
||||
|
|
@ -10,6 +9,15 @@ export interface NodeIntegrity {
|
|||
blockSize: number;
|
||||
blocks: Array<string>;
|
||||
}
|
||||
export declare class Node {
|
||||
files?: Record<string, Node>;
|
||||
unpacked?: boolean;
|
||||
size?: number;
|
||||
offset?: string;
|
||||
executable?: boolean;
|
||||
link?: string;
|
||||
integrity?: NodeIntegrity;
|
||||
}
|
||||
export declare class AsarFilesystem {
|
||||
readonly src: string;
|
||||
readonly header: Node;
|
||||
|
|
@ -23,6 +31,7 @@ export declare class AsarFilesystem {
|
|||
getFile(p: string, followLinks?: boolean): Node;
|
||||
readJson(file: string): Promise<any>;
|
||||
readFile(file: string): Promise<Buffer>;
|
||||
private newNode;
|
||||
}
|
||||
export declare function readAsarHeader(archive: string): Promise<ReadAsarHeader>;
|
||||
export declare function readAsar(archive: string): Promise<AsarFilesystem>;
|
||||
|
|
|
|||
49
electron/node_modules/app-builder-lib/out/asar/asar.js
generated
vendored
49
electron/node_modules/app-builder-lib/out/asar/asar.js
generated
vendored
|
|
@ -1,10 +1,12 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.readAsarJson = exports.readAsar = exports.readAsarHeader = exports.AsarFilesystem = exports.Node = void 0;
|
||||
exports.AsarFilesystem = exports.Node = void 0;
|
||||
exports.readAsarHeader = readAsarHeader;
|
||||
exports.readAsar = readAsar;
|
||||
exports.readAsarJson = readAsarJson;
|
||||
const chromium_pickle_js_1 = require("chromium-pickle-js");
|
||||
const fs_extra_1 = require("fs-extra");
|
||||
const path = require("path");
|
||||
/** @internal */
|
||||
class Node {
|
||||
}
|
||||
exports.Node = Node;
|
||||
|
|
@ -15,20 +17,23 @@ class AsarFilesystem {
|
|||
this.headerSize = headerSize;
|
||||
this.offset = 0;
|
||||
if (this.header.files == null) {
|
||||
this.header.files = {};
|
||||
this.header.files = this.newNode();
|
||||
}
|
||||
}
|
||||
searchNodeFromDirectory(p, isCreate) {
|
||||
let node = this.header;
|
||||
for (const dir of p.split(path.sep)) {
|
||||
if (dir !== ".") {
|
||||
if (node == null) {
|
||||
throw new Error(`Cannot find node for path: ${p} (node is null at ${dir})`);
|
||||
}
|
||||
let child = node.files[dir];
|
||||
if (child == null) {
|
||||
if (!isCreate) {
|
||||
return null;
|
||||
}
|
||||
child = new Node();
|
||||
child.files = {};
|
||||
child.files = this.newNode();
|
||||
node.files[dir] = child;
|
||||
}
|
||||
node = child;
|
||||
|
|
@ -42,8 +47,11 @@ class AsarFilesystem {
|
|||
}
|
||||
const name = path.basename(p);
|
||||
const dirNode = this.searchNodeFromDirectory(path.dirname(p), true);
|
||||
if (dirNode == null) {
|
||||
throw new Error(`Cannot find node for path: ${p} (node is null at ${path.dirname(p)})`);
|
||||
}
|
||||
if (dirNode.files == null) {
|
||||
dirNode.files = {};
|
||||
dirNode.files = this.newNode();
|
||||
}
|
||||
let result = dirNode.files[name];
|
||||
if (result == null) {
|
||||
|
|
@ -74,7 +82,7 @@ class AsarFilesystem {
|
|||
}
|
||||
let children = dirNode.files;
|
||||
if (children == null) {
|
||||
children = {};
|
||||
children = this.newNode();
|
||||
dirNode.files = children;
|
||||
}
|
||||
children[path.basename(file)] = node;
|
||||
|
|
@ -82,6 +90,9 @@ class AsarFilesystem {
|
|||
}
|
||||
getNode(p) {
|
||||
const node = this.searchNodeFromDirectory(path.dirname(p), false);
|
||||
if (node == null) {
|
||||
throw new Error(`Cannot find node for path: ${p} (node is null at ${path.dirname(p)})`);
|
||||
}
|
||||
return node.files[path.basename(p)];
|
||||
}
|
||||
getFile(p, followLinks = true) {
|
||||
|
|
@ -95,41 +106,41 @@ class AsarFilesystem {
|
|||
readFile(file) {
|
||||
return readFileFromAsar(this, file, this.getFile(file));
|
||||
}
|
||||
newNode() {
|
||||
return Object.create(null);
|
||||
}
|
||||
}
|
||||
exports.AsarFilesystem = AsarFilesystem;
|
||||
async function readAsarHeader(archive) {
|
||||
const fd = await fs_extra_1.open(archive, "r");
|
||||
const fd = await (0, fs_extra_1.open)(archive, "r");
|
||||
let size;
|
||||
let headerBuf;
|
||||
try {
|
||||
const sizeBuf = Buffer.allocUnsafe(8);
|
||||
if ((await fs_extra_1.read(fd, sizeBuf, 0, 8, null)).bytesRead !== 8) {
|
||||
if ((await (0, fs_extra_1.read)(fd, sizeBuf, 0, 8, null)).bytesRead !== 8) {
|
||||
throw new Error("Unable to read header size");
|
||||
}
|
||||
const sizePickle = chromium_pickle_js_1.createFromBuffer(sizeBuf);
|
||||
const sizePickle = (0, chromium_pickle_js_1.createFromBuffer)(sizeBuf);
|
||||
size = sizePickle.createIterator().readUInt32();
|
||||
headerBuf = Buffer.allocUnsafe(size);
|
||||
if ((await fs_extra_1.read(fd, headerBuf, 0, size, null)).bytesRead !== size) {
|
||||
if ((await (0, fs_extra_1.read)(fd, headerBuf, 0, size, null)).bytesRead !== size) {
|
||||
throw new Error("Unable to read header");
|
||||
}
|
||||
}
|
||||
finally {
|
||||
await fs_extra_1.close(fd);
|
||||
await (0, fs_extra_1.close)(fd);
|
||||
}
|
||||
const headerPickle = chromium_pickle_js_1.createFromBuffer(headerBuf);
|
||||
const headerPickle = (0, chromium_pickle_js_1.createFromBuffer)(headerBuf);
|
||||
return { header: headerPickle.createIterator().readString(), size };
|
||||
}
|
||||
exports.readAsarHeader = readAsarHeader;
|
||||
async function readAsar(archive) {
|
||||
const { header, size } = await readAsarHeader(archive);
|
||||
return new AsarFilesystem(archive, JSON.parse(header), size);
|
||||
}
|
||||
exports.readAsar = readAsar;
|
||||
async function readAsarJson(archive, file) {
|
||||
const fs = await readAsar(archive);
|
||||
return await fs.readJson(file);
|
||||
}
|
||||
exports.readAsarJson = readAsarJson;
|
||||
async function readFileFromAsar(filesystem, filename, info) {
|
||||
const size = info.size;
|
||||
const buffer = Buffer.allocUnsafe(size);
|
||||
|
|
@ -137,15 +148,15 @@ async function readFileFromAsar(filesystem, filename, info) {
|
|||
return buffer;
|
||||
}
|
||||
if (info.unpacked) {
|
||||
return await fs_extra_1.readFile(path.join(`${filesystem.src}.unpacked`, filename));
|
||||
return await (0, fs_extra_1.readFile)(path.join(`${filesystem.src}.unpacked`, filename));
|
||||
}
|
||||
const fd = await fs_extra_1.open(filesystem.src, "r");
|
||||
const fd = await (0, fs_extra_1.open)(filesystem.src, "r");
|
||||
try {
|
||||
const offset = 8 + filesystem.headerSize + parseInt(info.offset, 10);
|
||||
await fs_extra_1.read(fd, buffer, 0, size, offset);
|
||||
await (0, fs_extra_1.read)(fd, buffer, 0, size, offset);
|
||||
}
|
||||
finally {
|
||||
await fs_extra_1.close(fd);
|
||||
await (0, fs_extra_1.close)(fd);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
|
|
|||
2
electron/node_modules/app-builder-lib/out/asar/asar.js.map
generated
vendored
2
electron/node_modules/app-builder-lib/out/asar/asar.js.map
generated
vendored
File diff suppressed because one or more lines are too long
3
electron/node_modules/app-builder-lib/out/asar/asarFileChecker.d.ts
generated
vendored
3
electron/node_modules/app-builder-lib/out/asar/asarFileChecker.d.ts
generated
vendored
|
|
@ -1 +1,2 @@
|
|||
export {};
|
||||
import type { FilesystemEntry } from "@electron/asar/lib/filesystem";
|
||||
export declare function checkFileInArchive(asarFile: string, relativeFile: string, messagePrefix: string): Promise<FilesystemEntry>;
|
||||
|
|
|
|||
29
electron/node_modules/app-builder-lib/out/asar/asarFileChecker.js
generated
vendored
29
electron/node_modules/app-builder-lib/out/asar/asarFileChecker.js
generated
vendored
|
|
@ -1,38 +1,25 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.checkFileInArchive = void 0;
|
||||
const fs_1 = require("builder-util/out/fs");
|
||||
const asar_1 = require("./asar");
|
||||
/** @internal */
|
||||
exports.checkFileInArchive = checkFileInArchive;
|
||||
const dynamicImport_1 = require("../util/dynamicImport");
|
||||
async function checkFileInArchive(asarFile, relativeFile, messagePrefix) {
|
||||
const asar = await (0, dynamicImport_1.dynamicImport)("@electron/asar");
|
||||
function error(text) {
|
||||
return new Error(`${messagePrefix} "${relativeFile}" in the "${asarFile}" ${text}`);
|
||||
}
|
||||
let fs;
|
||||
try {
|
||||
fs = await asar_1.readAsar(asarFile);
|
||||
}
|
||||
catch (e) {
|
||||
throw error(`is corrupted: ${e}`);
|
||||
}
|
||||
let stat;
|
||||
try {
|
||||
stat = fs.getFile(relativeFile);
|
||||
stat = asar.statFile(asarFile, relativeFile, false);
|
||||
}
|
||||
catch (e) {
|
||||
const fileStat = await fs_1.statOrNull(asarFile);
|
||||
if (fileStat == null) {
|
||||
throw error(`does not exist. Seems like a wrong configuration.`);
|
||||
if (e.message.includes("Cannot read properties of undefined (reading 'link')")) {
|
||||
throw error("does not exist. Seems like a wrong configuration.");
|
||||
}
|
||||
// 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.`);
|
||||
throw error(`is corrupted: ${e}`);
|
||||
}
|
||||
if (stat.size === 0) {
|
||||
throw error(`is corrupted: size 0`);
|
||||
}
|
||||
return stat;
|
||||
}
|
||||
exports.checkFileInArchive = checkFileInArchive;
|
||||
//# sourceMappingURL=asarFileChecker.js.map
|
||||
2
electron/node_modules/app-builder-lib/out/asar/asarFileChecker.js.map
generated
vendored
2
electron/node_modules/app-builder-lib/out/asar/asarFileChecker.js.map
generated
vendored
|
|
@ -1 +1 @@
|
|||
{"version":3,"file":"asarFileChecker.js","sourceRoot":"","sources":["../../src/asar/asarFileChecker.ts"],"names":[],"mappings":";;;AAAA,4CAAgD;AAChD,iCAAuC;AAEvC,gBAAgB;AACT,KAAK,UAAU,kBAAkB,CAAC,QAAgB,EAAE,YAAoB,EAAE,aAAqB;IACpG,SAAS,KAAK,CAAC,IAAY;QACzB,OAAO,IAAI,KAAK,CAAC,GAAG,aAAa,KAAK,YAAY,aAAa,QAAQ,KAAK,IAAI,EAAE,CAAC,CAAA;IACrF,CAAC;IAED,IAAI,EAAE,CAAA;IACN,IAAI;QACF,EAAE,GAAG,MAAM,eAAQ,CAAC,QAAQ,CAAC,CAAA;KAC9B;IAAC,OAAO,CAAC,EAAE;QACV,MAAM,KAAK,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAA;KAClC;IAED,IAAI,IAAiB,CAAA;IACrB,IAAI;QACF,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC,YAAY,CAAC,CAAA;KAChC;IAAC,OAAO,CAAC,EAAE;QACV,MAAM,QAAQ,GAAG,MAAM,eAAU,CAAC,QAAQ,CAAC,CAAA;QAC3C,IAAI,QAAQ,IAAI,IAAI,EAAE;YACpB,MAAM,KAAK,CAAC,mDAAmD,CAAC,CAAA;SACjE;QAED,8DAA8D;QAC9D,IAAI,GAAG,IAAI,CAAA;KACZ;IAED,IAAI,IAAI,IAAI,IAAI,EAAE;QAChB,MAAM,KAAK,CAAC,mDAAmD,CAAC,CAAA;KACjE;IACD,IAAI,IAAI,CAAC,IAAI,KAAK,CAAC,EAAE;QACnB,MAAM,KAAK,CAAC,sBAAsB,CAAC,CAAA;KACpC;AACH,CAAC;AA/BD,gDA+BC","sourcesContent":["import { statOrNull } from \"builder-util/out/fs\"\nimport { Node, readAsar } from \"./asar\"\n\n/** @internal */\nexport async function checkFileInArchive(asarFile: string, relativeFile: string, messagePrefix: string) {\n function error(text: string) {\n return new Error(`${messagePrefix} \"${relativeFile}\" in the \"${asarFile}\" ${text}`)\n }\n\n let fs\n try {\n fs = await readAsar(asarFile)\n } catch (e) {\n throw error(`is corrupted: ${e}`)\n }\n\n let stat: Node | null\n try {\n stat = fs.getFile(relativeFile)\n } catch (e) {\n const fileStat = await statOrNull(asarFile)\n if (fileStat == null) {\n throw error(`does not exist. Seems like a wrong configuration.`)\n }\n\n // asar throws error on access to undefined object (info.link)\n stat = null\n }\n\n if (stat == null) {\n throw error(`does not exist. Seems like a wrong configuration.`)\n }\n if (stat.size === 0) {\n throw error(`is corrupted: size 0`)\n }\n}\n"]}
|
||||
{"version":3,"file":"asarFileChecker.js","sourceRoot":"","sources":["../../src/asar/asarFileChecker.ts"],"names":[],"mappings":";;AAGA,gDAkBC;AApBD,yDAAqD;AAE9C,KAAK,UAAU,kBAAkB,CAAC,QAAgB,EAAE,YAAoB,EAAE,aAAqB;IACpG,MAAM,IAAI,GAAG,MAAM,IAAA,6BAAa,EAAkC,gBAAgB,CAAC,CAAA;IACnF,SAAS,KAAK,CAAC,IAAY;QACzB,OAAO,IAAI,KAAK,CAAC,GAAG,aAAa,KAAK,YAAY,aAAa,QAAQ,KAAK,IAAI,EAAE,CAAC,CAAA;IACrF,CAAC;IACD,IAAI,IAAqB,CAAA;IACzB,IAAI,CAAC;QACH,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,YAAY,EAAE,KAAK,CAAC,CAAA;IACrD,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,IAAI,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,sDAAsD,CAAC,EAAE,CAAC;YAC/E,MAAM,KAAK,CAAC,mDAAmD,CAAC,CAAA;QAClE,CAAC;QACD,MAAM,KAAK,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAA;IACnC,CAAC;IACD,IAAK,IAA4B,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QAC7C,MAAM,KAAK,CAAC,sBAAsB,CAAC,CAAA;IACrC,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC","sourcesContent":["import type { FilesystemEntry, FilesystemFileEntry } from \"@electron/asar/lib/filesystem\"\nimport { dynamicImport } from \"../util/dynamicImport\"\n\nexport async function checkFileInArchive(asarFile: string, relativeFile: string, messagePrefix: string): Promise<FilesystemEntry> {\n const asar = await dynamicImport<typeof import(\"@electron/asar\")>(\"@electron/asar\")\n function error(text: string) {\n return new Error(`${messagePrefix} \"${relativeFile}\" in the \"${asarFile}\" ${text}`)\n }\n let stat: FilesystemEntry\n try {\n stat = asar.statFile(asarFile, relativeFile, false)\n } catch (e: any) {\n if (e.message.includes(\"Cannot read properties of undefined (reading 'link')\")) {\n throw error(\"does not exist. Seems like a wrong configuration.\")\n }\n throw error(`is corrupted: ${e}`)\n }\n if ((stat as FilesystemFileEntry).size === 0) {\n throw error(`is corrupted: size 0`)\n }\n return stat\n}\n"]}
|
||||
480
electron/node_modules/app-builder-lib/out/asar/asarUtil.js
generated
vendored
480
electron/node_modules/app-builder-lib/out/asar/asarUtil.js
generated
vendored
|
|
@ -2,240 +2,284 @@
|
|||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.AsarPackager = void 0;
|
||||
const builder_util_1 = require("builder-util");
|
||||
const dynamicImport_1 = require("../util/dynamicImport");
|
||||
const fs_1 = require("builder-util/out/fs");
|
||||
const fs_2 = require("fs");
|
||||
const promises_1 = require("fs/promises");
|
||||
const fs = require("fs-extra");
|
||||
const fs_extra_1 = require("fs-extra");
|
||||
const path = require("path");
|
||||
const appFileCopier_1 = require("../util/appFileCopier");
|
||||
const asar_1 = require("./asar");
|
||||
const integrity_1 = require("./integrity");
|
||||
const unpackDetector_1 = require("./unpackDetector");
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const pickle = require("chromium-pickle-js");
|
||||
const stream_1 = require("stream");
|
||||
const os = require("os");
|
||||
const resolvePath = async (file) => (file && (await (0, fs_1.exists)(file)) ? fs.realpath(file).catch(() => path.resolve(file)) : undefined);
|
||||
const resolvePaths = async (filepaths) => {
|
||||
return Promise.all(filepaths.map(resolvePath)).then(paths => paths.filter((it) => it != null));
|
||||
};
|
||||
const DENYLIST = resolvePaths([
|
||||
"/usr",
|
||||
"/lib",
|
||||
"/bin",
|
||||
"/sbin",
|
||||
"/etc",
|
||||
"/tmp",
|
||||
"/var", // block whole /var by default. If $HOME is under /var, it's explicitly in ALLOWLIST - https://github.com/electron-userland/electron-builder/issues/9025#issuecomment-3575380041
|
||||
// macOS system directories
|
||||
"/System",
|
||||
"/Library",
|
||||
"/private",
|
||||
// Windows system directories
|
||||
process.env.SystemRoot,
|
||||
process.env.WINDIR,
|
||||
]);
|
||||
const ALLOWLIST = resolvePaths([
|
||||
os.tmpdir(), // always allow temp dir
|
||||
os.homedir(), // always allow home dir
|
||||
]);
|
||||
/** @internal */
|
||||
class AsarPackager {
|
||||
constructor(src, destination, options, unpackPattern) {
|
||||
this.src = src;
|
||||
this.destination = destination;
|
||||
this.options = options;
|
||||
this.unpackPattern = unpackPattern;
|
||||
this.fs = new asar_1.AsarFilesystem(this.src);
|
||||
this.outFile = path.join(destination, "app.asar");
|
||||
this.unpackedDest = `${this.outFile}.unpacked`;
|
||||
constructor(packager, config) {
|
||||
this.packager = packager;
|
||||
this.config = config;
|
||||
this.outFile = path.join(config.resourcePath, `app.asar`);
|
||||
}
|
||||
// sort files to minimize file change (i.e. asar file is not changed dramatically on small change)
|
||||
async pack(fileSets, packager) {
|
||||
if (this.options.ordering != null) {
|
||||
// ordering doesn't support transformed files, but ordering is not used functionality - wait user report to fix it
|
||||
await order(fileSets[0].files, this.options.ordering, fileSets[0].src);
|
||||
}
|
||||
await promises_1.mkdir(path.dirname(this.outFile), { recursive: true });
|
||||
const unpackedFileIndexMap = new Map();
|
||||
for (const fileSet of fileSets) {
|
||||
unpackedFileIndexMap.set(fileSet, await this.createPackageFromFiles(fileSet, packager.info));
|
||||
}
|
||||
await this.writeAsarFile(fileSets, unpackedFileIndexMap);
|
||||
async pack(fileSets) {
|
||||
const orderedFileSets = [
|
||||
// Write dependencies first to minimize offset changes to asar header
|
||||
...fileSets.slice(1),
|
||||
// Finish with the app files that change most often
|
||||
fileSets[0],
|
||||
].map(set => this.orderFileSet(set));
|
||||
const streams = await this.processFileSets(orderedFileSets);
|
||||
await this.executeElectronAsar(streams);
|
||||
}
|
||||
async createPackageFromFiles(fileSet, packager) {
|
||||
const metadata = fileSet.metadata;
|
||||
// search auto unpacked dir
|
||||
const unpackedDirs = new Set();
|
||||
const rootForAppFilesWithoutAsar = path.join(this.destination, "app");
|
||||
if (this.options.smartUnpack !== false) {
|
||||
await unpackDetector_1.detectUnpackedDirs(fileSet, unpackedDirs, this.unpackedDest, rootForAppFilesWithoutAsar);
|
||||
}
|
||||
const dirToCreateForUnpackedFiles = new Set(unpackedDirs);
|
||||
const correctDirNodeUnpackedFlag = async (filePathInArchive, dirNode) => {
|
||||
for (const dir of unpackedDirs) {
|
||||
if (filePathInArchive.length > dir.length + 2 && filePathInArchive[dir.length] === path.sep && filePathInArchive.startsWith(dir)) {
|
||||
dirNode.unpacked = true;
|
||||
unpackedDirs.add(filePathInArchive);
|
||||
// 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
|
||||
await promises_1.mkdir(path.join(this.unpackedDest, filePathInArchive), { recursive: true });
|
||||
break;
|
||||
}
|
||||
async executeElectronAsar(streams) {
|
||||
// override logger temporarily to clean up console (electron/asar does some internal logging that blogs up the default electron-builder logs)
|
||||
const consoleLogger = console.log;
|
||||
console.log = (...args) => {
|
||||
if (args[0] === "Ordering file has 100% coverage.") {
|
||||
return; // no need to log, this means our ordering logic is working correctly
|
||||
}
|
||||
builder_util_1.log.info({ args }, "logging @electron/asar");
|
||||
};
|
||||
const transformedFiles = fileSet.transformedFiles;
|
||||
const taskManager = new builder_util_1.AsyncTaskManager(packager.cancellationToken);
|
||||
const fileCopier = new fs_1.FileCopier();
|
||||
let currentDirNode = null;
|
||||
let currentDirPath = null;
|
||||
const unpackedFileIndexSet = new Set();
|
||||
for (let i = 0, n = fileSet.files.length; i < n; i++) {
|
||||
const file = fileSet.files[i];
|
||||
const stat = metadata.get(file);
|
||||
if (stat == null) {
|
||||
continue;
|
||||
}
|
||||
const pathInArchive = path.relative(rootForAppFilesWithoutAsar, appFileCopier_1.getDestinationPath(file, fileSet));
|
||||
if (stat.isSymbolicLink()) {
|
||||
const s = stat;
|
||||
this.fs.getOrCreateNode(pathInArchive).link = s.relativeLink;
|
||||
s.pathInArchive = pathInArchive;
|
||||
unpackedFileIndexSet.add(i);
|
||||
continue;
|
||||
}
|
||||
let fileParent = path.dirname(pathInArchive);
|
||||
if (fileParent === ".") {
|
||||
fileParent = "";
|
||||
}
|
||||
if (currentDirPath !== fileParent) {
|
||||
if (fileParent.startsWith("..")) {
|
||||
throw new Error(`Internal error: path must not start with "..": ${fileParent}`);
|
||||
}
|
||||
currentDirPath = fileParent;
|
||||
currentDirNode = this.fs.getOrCreateNode(fileParent);
|
||||
// do not check for root
|
||||
if (fileParent !== "" && !currentDirNode.unpacked) {
|
||||
if (unpackedDirs.has(fileParent)) {
|
||||
currentDirNode.unpacked = true;
|
||||
}
|
||||
else {
|
||||
await correctDirNodeUnpackedFlag(fileParent, currentDirNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
const dirNode = currentDirNode;
|
||||
const newData = transformedFiles == null ? undefined : transformedFiles.get(i);
|
||||
const isUnpacked = dirNode.unpacked || (this.unpackPattern != null && this.unpackPattern(file, stat));
|
||||
const integrity = newData === undefined ? await integrity_1.hashFile(file) : integrity_1.hashFileContents(newData);
|
||||
this.fs.addFileNode(file, dirNode, newData == undefined ? stat.size : Buffer.byteLength(newData), isUnpacked, stat, integrity);
|
||||
if (isUnpacked) {
|
||||
if (!dirNode.unpacked && !dirToCreateForUnpackedFiles.has(fileParent)) {
|
||||
dirToCreateForUnpackedFiles.add(fileParent);
|
||||
await promises_1.mkdir(path.join(this.unpackedDest, fileParent), { recursive: true });
|
||||
}
|
||||
const unpackedFile = path.join(this.unpackedDest, pathInArchive);
|
||||
taskManager.addTask(copyFileOrData(fileCopier, newData, file, unpackedFile, stat));
|
||||
if (taskManager.tasks.length > fs_1.MAX_FILE_REQUESTS) {
|
||||
await taskManager.awaitTasks();
|
||||
}
|
||||
unpackedFileIndexSet.add(i);
|
||||
}
|
||||
}
|
||||
if (taskManager.tasks.length > 0) {
|
||||
await taskManager.awaitTasks();
|
||||
}
|
||||
return unpackedFileIndexSet;
|
||||
const { createPackageFromStreams } = await (0, dynamicImport_1.dynamicImport)("@electron/asar");
|
||||
await createPackageFromStreams(this.outFile, streams);
|
||||
console.log = consoleLogger;
|
||||
}
|
||||
writeAsarFile(fileSets, unpackedFileIndexMap) {
|
||||
return new Promise((resolve, reject) => {
|
||||
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 = fs_2.createWriteStream(this.outFile);
|
||||
writeStream.on("error", reject);
|
||||
writeStream.on("close", resolve);
|
||||
writeStream.write(sizeBuf);
|
||||
let fileSetIndex = 0;
|
||||
let files = fileSets[0].files;
|
||||
let metadata = fileSets[0].metadata;
|
||||
let transformedFiles = fileSets[0].transformedFiles;
|
||||
let unpackedFileIndexSet = unpackedFileIndexMap.get(fileSets[0]);
|
||||
const w = (index) => {
|
||||
while (true) {
|
||||
if (index >= files.length) {
|
||||
if (++fileSetIndex >= fileSets.length) {
|
||||
writeStream.end();
|
||||
return;
|
||||
}
|
||||
else {
|
||||
files = fileSets[fileSetIndex].files;
|
||||
metadata = fileSets[fileSetIndex].metadata;
|
||||
transformedFiles = fileSets[fileSetIndex].transformedFiles;
|
||||
unpackedFileIndexSet = unpackedFileIndexMap.get(fileSets[fileSetIndex]);
|
||||
index = 0;
|
||||
}
|
||||
}
|
||||
if (!unpackedFileIndexSet.has(index)) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
const stat = metadata.get(files[index]);
|
||||
if (stat != null && stat.isSymbolicLink()) {
|
||||
fs_2.symlink(stat.linkRelativeToFile, path.join(this.unpackedDest, stat.pathInArchive), () => w(index + 1));
|
||||
return;
|
||||
}
|
||||
}
|
||||
index++;
|
||||
async processFileSets(fileSets) {
|
||||
var _a;
|
||||
const unpackedPaths = new Set();
|
||||
if (this.config.options.smartUnpack !== false) {
|
||||
for (const fileSet of fileSets) {
|
||||
(0, unpackDetector_1.detectUnpackedDirs)(fileSet, unpackedPaths);
|
||||
}
|
||||
}
|
||||
const resultsMap = new Map();
|
||||
const streamOrdering = [];
|
||||
const normalizedUnpackedPaths = Array.from(unpackedPaths).map(p => path.normalize(p));
|
||||
// Check whether a file or directory should be unpacked, using pre-normalized unpacked paths and early returns
|
||||
const isUnpacked = (dir, file, stat) => {
|
||||
var _a, _b;
|
||||
const normalizedDir = path.normalize(dir);
|
||||
// Check file pattern first (most specific)
|
||||
if (!(0, builder_util_1.isEmptyOrSpaces)(file) && stat && ((_b = (_a = this.config).unpackPattern) === null || _b === void 0 ? void 0 : _b.call(_a, file, stat))) {
|
||||
return true;
|
||||
}
|
||||
// Check if path is within any unpacked directory
|
||||
for (const unpackedPath of normalizedUnpackedPaths) {
|
||||
if (normalizedDir === unpackedPath || normalizedDir.startsWith(unpackedPath + path.sep)) {
|
||||
return true;
|
||||
}
|
||||
const data = transformedFiles == null ? null : transformedFiles.get(index);
|
||||
const file = files[index];
|
||||
if (data !== null && data !== undefined) {
|
||||
writeStream.write(data, () => w(index + 1));
|
||||
return;
|
||||
}
|
||||
// https://github.com/yarnpkg/yarn/pull/3539
|
||||
const stat = metadata.get(file);
|
||||
if (stat != null && stat.size < 2 * 1024 * 1024) {
|
||||
promises_1.readFile(file)
|
||||
.then(it => {
|
||||
writeStream.write(it, () => w(index + 1));
|
||||
})
|
||||
.catch(e => reject(`Cannot read file ${file}: ${e.stack || e}`));
|
||||
}
|
||||
else {
|
||||
const readStream = fs_2.createReadStream(file);
|
||||
readStream.on("error", reject);
|
||||
readStream.once("end", () => w(index + 1));
|
||||
readStream.on("open", () => {
|
||||
readStream.pipe(writeStream, {
|
||||
end: false,
|
||||
});
|
||||
});
|
||||
}
|
||||
return false;
|
||||
};
|
||||
// First pass: process all files in order, ensuring parent directories exist
|
||||
for (const fileSet of fileSets) {
|
||||
// Don't use Promise.all, we need to retain order of execution/iteration through the already-ordered fileset
|
||||
for (const [index, file] of fileSet.files.entries()) {
|
||||
const transformedData = (_a = fileSet.transformedFiles) === null || _a === void 0 ? void 0 : _a.get(index);
|
||||
const stat = fileSet.metadata.get(file);
|
||||
const destination = path.relative(this.config.defaultDestination, (0, appFileCopier_1.getDestinationPath)(file, fileSet));
|
||||
// Ensure parent directories exist before processing file
|
||||
this.ensureParentDirectories(destination, resultsMap, streamOrdering);
|
||||
const result = await this.processFileOrSymlink({
|
||||
file,
|
||||
destination,
|
||||
fileSet,
|
||||
transformedData,
|
||||
stat,
|
||||
isUnpacked,
|
||||
});
|
||||
if (result && !resultsMap.has(result.path)) {
|
||||
resultsMap.set(result.path, result);
|
||||
streamOrdering.push(result.path);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Second pass: propagate unpacked flag to parent directories
|
||||
for (const entry of resultsMap.values()) {
|
||||
if (entry.unpacked) {
|
||||
this.markParentDirectoriesAsUnpacked(entry.path, resultsMap, isUnpacked);
|
||||
}
|
||||
}
|
||||
// Build final results array maintaining processing order
|
||||
return streamOrdering.reduce((streams, path) => {
|
||||
const stream = resultsMap.has(path) ? resultsMap.get(path) : null;
|
||||
if (stream != null) {
|
||||
streams.push(stream);
|
||||
}
|
||||
return streams;
|
||||
}, []);
|
||||
}
|
||||
ensureParentDirectories(destination, resultsMap, streamOrdering) {
|
||||
const parents = [];
|
||||
let current = path.dirname(path.normalize(destination));
|
||||
// Collect all parent directories from deepest to root
|
||||
while (current !== ".") {
|
||||
parents.unshift(current);
|
||||
current = path.dirname(current);
|
||||
}
|
||||
// Add parent directories in order (root to deepest)
|
||||
for (const parentPath of parents) {
|
||||
if (!resultsMap.has(parentPath)) {
|
||||
const dir = {
|
||||
type: "directory",
|
||||
path: parentPath,
|
||||
unpacked: false, // Updated in second pass if needed
|
||||
};
|
||||
resultsMap.set(parentPath, dir);
|
||||
streamOrdering.push(parentPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
markParentDirectoriesAsUnpacked(destination, resultsMap, isUnpacked) {
|
||||
let current = path.dirname(path.normalize(destination));
|
||||
while (current !== ".") {
|
||||
const entry = resultsMap.get(current);
|
||||
if (entry && isUnpacked(current)) {
|
||||
entry.unpacked = true;
|
||||
}
|
||||
current = path.dirname(current);
|
||||
}
|
||||
}
|
||||
async processFileOrSymlink(options) {
|
||||
const { isUnpacked, transformedData, file, destination, stat } = options;
|
||||
const unpacked = isUnpacked(destination, file, stat);
|
||||
// Handle directories
|
||||
if (!stat.isFile() && !stat.isSymbolicLink()) {
|
||||
return { path: destination, unpacked, type: "directory" };
|
||||
}
|
||||
// Handle transformed data (pre-processed content)
|
||||
if (transformedData != null) {
|
||||
const size = Buffer.byteLength(transformedData);
|
||||
return {
|
||||
path: destination,
|
||||
streamGenerator: () => new stream_1.Readable({
|
||||
read() {
|
||||
this.push(transformedData);
|
||||
this.push(null);
|
||||
},
|
||||
}),
|
||||
unpacked,
|
||||
type: "file",
|
||||
stat: { mode: stat.mode, size },
|
||||
};
|
||||
writeStream.write(headerBuf, () => w(0));
|
||||
}
|
||||
// verify that the file is not a direct link or symlinked to access/copy a system file
|
||||
await this.protectSystemAndUnsafePaths(file, await this.packager.info.getWorkspaceRoot());
|
||||
const baseConfig = {
|
||||
path: destination,
|
||||
streamGenerator: () => fs.createReadStream(file),
|
||||
unpacked,
|
||||
stat,
|
||||
};
|
||||
// Handle regular files
|
||||
if (!stat.isSymbolicLink()) {
|
||||
return { ...baseConfig, type: "file" };
|
||||
}
|
||||
// Handle symlinks - make relative to source location
|
||||
let link = await (0, fs_extra_1.readlink)(file);
|
||||
if (path.isAbsolute(link)) {
|
||||
link = path.relative(path.dirname(file), link);
|
||||
}
|
||||
return {
|
||||
...baseConfig,
|
||||
type: "link",
|
||||
symlink: link,
|
||||
};
|
||||
}
|
||||
orderFileSet(fileSet) {
|
||||
const sortedFileEntries = Array.from(fileSet.files.entries());
|
||||
sortedFileEntries.sort(([, a], [, b]) => {
|
||||
if (a === b) {
|
||||
return 0;
|
||||
}
|
||||
// Place addons last because their signature changes per build
|
||||
const isAAddon = a.endsWith(".node");
|
||||
const isBAddon = b.endsWith(".node");
|
||||
if (isAAddon && !isBAddon) {
|
||||
return 1;
|
||||
}
|
||||
if (isBAddon && !isAAddon) {
|
||||
return -1;
|
||||
}
|
||||
// Otherwise order by name
|
||||
return a < b ? -1 : 1;
|
||||
});
|
||||
let transformedFiles;
|
||||
if (fileSet.transformedFiles) {
|
||||
transformedFiles = new Map();
|
||||
const indexMap = new Map();
|
||||
for (const [newIndex, [oldIndex]] of sortedFileEntries.entries()) {
|
||||
indexMap.set(oldIndex, newIndex);
|
||||
}
|
||||
for (const [oldIndex, value] of fileSet.transformedFiles) {
|
||||
const newIndex = indexMap.get(oldIndex);
|
||||
if (newIndex === undefined) {
|
||||
throw new Error(`Internal error: ${fileSet.files[oldIndex]} was lost while ordering asar`);
|
||||
}
|
||||
transformedFiles.set(newIndex, value);
|
||||
}
|
||||
}
|
||||
return {
|
||||
src: fileSet.src,
|
||||
destination: fileSet.destination,
|
||||
metadata: fileSet.metadata,
|
||||
files: sortedFileEntries.map(([, file]) => file),
|
||||
transformedFiles,
|
||||
};
|
||||
}
|
||||
async checkAgainstRoots(target, allowRoots) {
|
||||
const resolved = await resolvePath(target);
|
||||
if (resolved == null || (0, builder_util_1.isEmptyOrSpaces)(resolved)) {
|
||||
return false;
|
||||
}
|
||||
for (const root of allowRoots) {
|
||||
if (resolved === root || resolved.startsWith(root + path.sep)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
async protectSystemAndUnsafePaths(file, workspaceRoot) {
|
||||
const resolved = await resolvePath(file);
|
||||
const logFields = { source: file, realPath: resolved };
|
||||
const workspace = await resolvePath(workspaceRoot);
|
||||
// If in workspace, always safe
|
||||
if (workspace && (resolved === null || resolved === void 0 ? void 0 : resolved.startsWith(workspace))) {
|
||||
return;
|
||||
}
|
||||
// Check allowlist (priority)
|
||||
if (await this.checkAgainstRoots(file, await ALLOWLIST)) {
|
||||
return;
|
||||
}
|
||||
// Check denylist
|
||||
if (await this.checkAgainstRoots(file, await DENYLIST)) {
|
||||
builder_util_1.log.error(logFields, `denied access to system or unsafe path`);
|
||||
throw new Error(`Cannot copy file [${file}] symlinked to file [${resolved}] outside the package to a system or unsafe path`);
|
||||
}
|
||||
// Default: outside explicit paths but not explicitly denied
|
||||
builder_util_1.log.debug(logFields, `path is outside of explicit safe paths, defaulting to safe`);
|
||||
}
|
||||
}
|
||||
exports.AsarPackager = AsarPackager;
|
||||
async function order(filenames, orderingFile, src) {
|
||||
const orderingFiles = (await promises_1.readFile(orderingFile, "utf8")).split("\n").map(line => {
|
||||
if (line.indexOf(":") !== -1) {
|
||||
line = line.split(":").pop();
|
||||
}
|
||||
line = line.trim();
|
||||
if (line[0] === "/") {
|
||||
line = line.slice(1);
|
||||
}
|
||||
return line;
|
||||
});
|
||||
const ordering = [];
|
||||
for (const file of orderingFiles) {
|
||||
const pathComponents = file.split(path.sep);
|
||||
for (const pathComponent of pathComponents) {
|
||||
ordering.push(path.join(src, pathComponent));
|
||||
}
|
||||
}
|
||||
const sortedFiles = [];
|
||||
let missing = 0;
|
||||
const total = filenames.length;
|
||||
for (const file of ordering) {
|
||||
if (!sortedFiles.includes(file) && filenames.includes(file)) {
|
||||
sortedFiles.push(file);
|
||||
}
|
||||
}
|
||||
for (const file of filenames) {
|
||||
if (!sortedFiles.includes(file)) {
|
||||
sortedFiles.push(file);
|
||||
missing += 1;
|
||||
}
|
||||
}
|
||||
builder_util_1.log.info({ coverage: ((total - missing) / total) * 100 }, "ordering files in ASAR archive");
|
||||
return sortedFiles;
|
||||
}
|
||||
function copyFileOrData(fileCopier, data, source, destination, stats) {
|
||||
if (data == null) {
|
||||
return fileCopier.copy(source, destination, stats);
|
||||
}
|
||||
else {
|
||||
return promises_1.writeFile(destination, data);
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=asarUtil.js.map
|
||||
2
electron/node_modules/app-builder-lib/out/asar/asarUtil.js.map
generated
vendored
2
electron/node_modules/app-builder-lib/out/asar/asarUtil.js.map
generated
vendored
File diff suppressed because one or more lines are too long
9
electron/node_modules/app-builder-lib/out/asar/integrity.d.ts
generated
vendored
9
electron/node_modules/app-builder-lib/out/asar/integrity.d.ts
generated
vendored
|
|
@ -1,8 +1,9 @@
|
|||
/// <reference types="node" />
|
||||
import { NodeIntegrity } from "./asar";
|
||||
import { FileMatcher } from "../fileMatcher";
|
||||
export interface AsarIntegrityOptions {
|
||||
readonly resourcesPath: string;
|
||||
readonly resourcesRelativePath: string;
|
||||
readonly resourcesDestinationPath: string;
|
||||
readonly extraResourceMatchers: Array<FileMatcher> | null;
|
||||
}
|
||||
export interface HeaderHash {
|
||||
algorithm: "SHA256";
|
||||
|
|
@ -11,6 +12,4 @@ export interface HeaderHash {
|
|||
export interface AsarIntegrity {
|
||||
[key: string]: HeaderHash;
|
||||
}
|
||||
export declare function computeData({ resourcesPath, resourcesRelativePath }: AsarIntegrityOptions): Promise<AsarIntegrity>;
|
||||
export declare function hashFile(file: string, blockSize?: number): Promise<NodeIntegrity>;
|
||||
export declare function hashFileContents(contents: Buffer | string, blockSize?: number): NodeIntegrity;
|
||||
export declare function computeData({ resourcesPath, resourcesRelativePath, resourcesDestinationPath, extraResourceMatchers }: AsarIntegrityOptions): Promise<AsarIntegrity>;
|
||||
|
|
|
|||
117
electron/node_modules/app-builder-lib/out/asar/integrity.js
generated
vendored
117
electron/node_modules/app-builder-lib/out/asar/integrity.js
generated
vendored
|
|
@ -1,89 +1,62 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.hashFileContents = exports.hashFile = exports.computeData = void 0;
|
||||
const bluebird_lst_1 = require("bluebird-lst");
|
||||
exports.computeData = computeData;
|
||||
const builder_util_1 = require("builder-util");
|
||||
const crypto_1 = require("crypto");
|
||||
const fs_1 = require("fs");
|
||||
const promises_1 = require("fs/promises");
|
||||
const path = require("path");
|
||||
const asar_1 = require("./asar");
|
||||
async function computeData({ resourcesPath, resourcesRelativePath }) {
|
||||
async function computeData({ resourcesPath, resourcesRelativePath, resourcesDestinationPath, extraResourceMatchers }) {
|
||||
const isAsar = (filepath) => filepath.endsWith(".asar");
|
||||
const resources = await (0, promises_1.readdir)(resourcesPath);
|
||||
const resourceAsars = resources.filter(isAsar).reduce((prev, filename) => ({
|
||||
...prev,
|
||||
[path.join(resourcesRelativePath, filename)]: path.join(resourcesPath, filename),
|
||||
}), {});
|
||||
const extraResources = await Promise.all((extraResourceMatchers !== null && extraResourceMatchers !== void 0 ? extraResourceMatchers : []).map(async (matcher) => {
|
||||
const { from, to } = matcher;
|
||||
const stat = await (0, builder_util_1.statOrNull)(from);
|
||||
if (stat == null) {
|
||||
builder_util_1.log.warn({ from }, `file source doesn't exist`);
|
||||
return [];
|
||||
}
|
||||
if (stat.isFile()) {
|
||||
return [{ from, to }];
|
||||
}
|
||||
if (matcher.isEmpty() || matcher.containsOnlyIgnore()) {
|
||||
matcher.prependPattern("**/*");
|
||||
}
|
||||
const matcherFilter = matcher.createFilter();
|
||||
const extraResourceMatches = await (0, builder_util_1.walk)(matcher.from, (file, stats) => matcherFilter(file, stats) || stats.isDirectory());
|
||||
return extraResourceMatches.map(from => ({ from, to: matcher.to }));
|
||||
}));
|
||||
const extraResourceAsars = extraResources
|
||||
.flat(1)
|
||||
.filter(match => isAsar(match.from))
|
||||
.reduce((prev, { to, from }) => {
|
||||
const prefix = path.relative(resourcesDestinationPath, to);
|
||||
return {
|
||||
...prev,
|
||||
[path.join(resourcesRelativePath, prefix, path.basename(from))]: from,
|
||||
};
|
||||
}, {});
|
||||
// sort to produce constant result
|
||||
const names = (await promises_1.readdir(resourcesPath)).filter(it => it.endsWith(".asar")).sort();
|
||||
const checksums = await bluebird_lst_1.default.map(names, it => hashHeader(path.join(resourcesPath, it)));
|
||||
const result = {};
|
||||
for (let i = 0; i < names.length; i++) {
|
||||
result[path.join(resourcesRelativePath, names[i])] = checksums[i];
|
||||
const allAsars = [...Object.entries(resourceAsars), ...Object.entries(extraResourceAsars)].sort(([name1], [name2]) => name1.localeCompare(name2));
|
||||
const hashes = await Promise.all(allAsars.map(async ([, from]) => hashHeader(from)));
|
||||
const asarIntegrity = {};
|
||||
for (let i = 0; i < allAsars.length; i++) {
|
||||
const [asar] = allAsars[i];
|
||||
asarIntegrity[asar] = hashes[i];
|
||||
}
|
||||
return result;
|
||||
return asarIntegrity;
|
||||
}
|
||||
exports.computeData = computeData;
|
||||
async function hashHeader(file) {
|
||||
const hash = crypto_1.createHash("sha256");
|
||||
const { header } = await asar_1.readAsarHeader(file);
|
||||
const hash = (0, crypto_1.createHash)("sha256");
|
||||
const { header } = await (0, asar_1.readAsarHeader)(file);
|
||||
hash.update(header);
|
||||
return {
|
||||
algorithm: "SHA256",
|
||||
hash: hash.digest("hex"),
|
||||
};
|
||||
}
|
||||
function hashFile(file, blockSize = 4 * 1024 * 1024) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const hash = crypto_1.createHash("sha256");
|
||||
const blocks = new Array();
|
||||
let blockBytes = 0;
|
||||
let blockHash = crypto_1.createHash("sha256");
|
||||
function updateBlockHash(chunk) {
|
||||
let off = 0;
|
||||
while (off < chunk.length) {
|
||||
const toHash = Math.min(blockSize - blockBytes, chunk.length - off);
|
||||
blockHash.update(chunk.slice(off, off + toHash));
|
||||
off += toHash;
|
||||
blockBytes += toHash;
|
||||
if (blockBytes === blockSize) {
|
||||
blocks.push(blockHash.digest("hex"));
|
||||
blockHash = crypto_1.createHash("sha256");
|
||||
blockBytes = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
fs_1.createReadStream(file)
|
||||
.on("data", it => {
|
||||
// Note that `it` is a Buffer anyway so this cast is a no-op
|
||||
updateBlockHash(Buffer.from(it));
|
||||
hash.update(it);
|
||||
})
|
||||
.on("error", reject)
|
||||
.on("end", () => {
|
||||
if (blockBytes !== 0) {
|
||||
blocks.push(blockHash.digest("hex"));
|
||||
}
|
||||
resolve({
|
||||
algorithm: "SHA256",
|
||||
hash: hash.digest("hex"),
|
||||
blockSize,
|
||||
blocks,
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
exports.hashFile = hashFile;
|
||||
function hashFileContents(contents, blockSize = 4 * 1024 * 1024) {
|
||||
const buffer = Buffer.from(contents);
|
||||
const hash = crypto_1.createHash("sha256");
|
||||
hash.update(buffer);
|
||||
const blocks = new Array();
|
||||
for (let off = 0; off < buffer.length; off += blockSize) {
|
||||
const blockHash = crypto_1.createHash("sha256");
|
||||
blockHash.update(buffer.slice(off, off + blockSize));
|
||||
blocks.push(blockHash.digest("hex"));
|
||||
}
|
||||
return {
|
||||
algorithm: "SHA256",
|
||||
hash: hash.digest("hex"),
|
||||
blockSize,
|
||||
blocks,
|
||||
};
|
||||
}
|
||||
exports.hashFileContents = hashFileContents;
|
||||
//# sourceMappingURL=integrity.js.map
|
||||
2
electron/node_modules/app-builder-lib/out/asar/integrity.js.map
generated
vendored
2
electron/node_modules/app-builder-lib/out/asar/integrity.js.map
generated
vendored
File diff suppressed because one or more lines are too long
95
electron/node_modules/app-builder-lib/out/asar/unpackDetector.js
generated
vendored
95
electron/node_modules/app-builder-lib/out/asar/unpackDetector.js
generated
vendored
|
|
@ -1,108 +1,43 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.detectUnpackedDirs = exports.isLibOrExe = void 0;
|
||||
const bluebird_lst_1 = require("bluebird-lst");
|
||||
exports.isLibOrExe = isLibOrExe;
|
||||
exports.detectUnpackedDirs = detectUnpackedDirs;
|
||||
const builder_util_1 = require("builder-util");
|
||||
const fs_1 = require("builder-util/out/fs");
|
||||
const fs_extra_1 = require("fs-extra");
|
||||
const isbinaryfile_1 = require("isbinaryfile");
|
||||
const path = require("path");
|
||||
const fileTransformer_1 = require("../fileTransformer");
|
||||
const appFileCopier_1 = require("../util/appFileCopier");
|
||||
function addValue(map, key, value) {
|
||||
let list = map.get(key);
|
||||
if (list == null) {
|
||||
list = [value];
|
||||
map.set(key, list);
|
||||
}
|
||||
else {
|
||||
list.push(value);
|
||||
}
|
||||
}
|
||||
function isLibOrExe(file) {
|
||||
return file.endsWith(".dll") || file.endsWith(".exe") || file.endsWith(".dylib") || file.endsWith(".so");
|
||||
// https://github.com/electron-userland/electron-builder/issues/3038
|
||||
return file.endsWith(".dll") || file.endsWith(".exe") || file.endsWith(".dylib") || file.endsWith(".so") || file.endsWith(".node");
|
||||
}
|
||||
exports.isLibOrExe = isLibOrExe;
|
||||
/** @internal */
|
||||
async function detectUnpackedDirs(fileSet, autoUnpackDirs, unpackedDest, rootForAppFilesWithoutAsar) {
|
||||
const dirToCreate = new Map();
|
||||
function detectUnpackedDirs(fileSet, autoUnpackDirs) {
|
||||
const metadata = fileSet.metadata;
|
||||
function addParents(child, root) {
|
||||
child = path.dirname(child);
|
||||
if (autoUnpackDirs.has(child)) {
|
||||
return;
|
||||
}
|
||||
do {
|
||||
autoUnpackDirs.add(child);
|
||||
const p = path.dirname(child);
|
||||
// create parent dir to be able to copy file later without directory existence check
|
||||
addValue(dirToCreate, p, path.basename(child));
|
||||
if (child === root || p === root || autoUnpackDirs.has(p)) {
|
||||
break;
|
||||
}
|
||||
child = p;
|
||||
} while (true);
|
||||
autoUnpackDirs.add(root);
|
||||
}
|
||||
for (let i = 0, n = fileSet.files.length; i < n; i++) {
|
||||
const file = fileSet.files[i];
|
||||
const index = file.lastIndexOf(fileTransformer_1.NODE_MODULES_PATTERN);
|
||||
if (index < 0) {
|
||||
const stat = metadata.get(file);
|
||||
if (!stat.moduleRootPath || autoUnpackDirs.has(stat.moduleRootPath)) {
|
||||
continue;
|
||||
}
|
||||
let nextSlashIndex = file.indexOf(path.sep, index + fileTransformer_1.NODE_MODULES_PATTERN.length + 1);
|
||||
if (nextSlashIndex < 0) {
|
||||
continue;
|
||||
}
|
||||
if (file[index + fileTransformer_1.NODE_MODULES_PATTERN.length] === "@") {
|
||||
nextSlashIndex = file.indexOf(path.sep, nextSlashIndex + 1);
|
||||
}
|
||||
if (!metadata.get(file).isFile()) {
|
||||
continue;
|
||||
}
|
||||
const packageDir = file.substring(0, nextSlashIndex);
|
||||
const packageDirPathInArchive = path.relative(rootForAppFilesWithoutAsar, appFileCopier_1.getDestinationPath(packageDir, fileSet));
|
||||
const pathInArchive = path.relative(rootForAppFilesWithoutAsar, appFileCopier_1.getDestinationPath(file, fileSet));
|
||||
if (autoUnpackDirs.has(packageDirPathInArchive)) {
|
||||
// if package dir is unpacked, any file also unpacked
|
||||
addParents(pathInArchive, packageDirPathInArchive);
|
||||
if (!stat.isFile()) {
|
||||
continue;
|
||||
}
|
||||
// https://github.com/electron-userland/electron-builder/issues/2679
|
||||
let shouldUnpack = false;
|
||||
// ffprobe-static and ffmpeg-static are known packages to always unpack
|
||||
const moduleName = path.basename(packageDir);
|
||||
const moduleName = stat.moduleName;
|
||||
const fileBaseName = path.basename(file);
|
||||
const hasExtension = path.extname(fileBaseName);
|
||||
if (moduleName === "ffprobe-static" || moduleName === "ffmpeg-static" || isLibOrExe(file)) {
|
||||
shouldUnpack = true;
|
||||
}
|
||||
else if (!file.includes(".", nextSlashIndex)) {
|
||||
shouldUnpack = !!isbinaryfile_1.isBinaryFileSync(file);
|
||||
else if (!hasExtension) {
|
||||
shouldUnpack = !!(0, isbinaryfile_1.isBinaryFileSync)(file);
|
||||
}
|
||||
if (!shouldUnpack) {
|
||||
continue;
|
||||
}
|
||||
if (builder_util_1.log.isDebugEnabled) {
|
||||
builder_util_1.log.debug({ file: pathInArchive, reason: "contains executable code" }, "not packed into asar archive");
|
||||
}
|
||||
addParents(pathInArchive, packageDirPathInArchive);
|
||||
}
|
||||
if (dirToCreate.size > 0) {
|
||||
await fs_extra_1.mkdir(`${unpackedDest + path.sep}node_modules`, { recursive: true });
|
||||
// child directories should be not created asynchronously - parent directories should be created first
|
||||
await bluebird_lst_1.default.map(dirToCreate.keys(), async (parentDir) => {
|
||||
const base = unpackedDest + path.sep + parentDir;
|
||||
await fs_extra_1.mkdir(base, { recursive: true });
|
||||
await bluebird_lst_1.default.each(dirToCreate.get(parentDir), (it) => {
|
||||
if (dirToCreate.has(parentDir + path.sep + it)) {
|
||||
// already created
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
return fs_extra_1.mkdir(base + path.sep + it, { recursive: true });
|
||||
}
|
||||
});
|
||||
}, fs_1.CONCURRENCY);
|
||||
builder_util_1.log.debug({ file: stat.moduleFullFilePath, reason: "contains executable code" }, "not packed into asar archive");
|
||||
autoUnpackDirs.add(stat.moduleRootPath);
|
||||
}
|
||||
}
|
||||
exports.detectUnpackedDirs = detectUnpackedDirs;
|
||||
//# sourceMappingURL=unpackDetector.js.map
|
||||
2
electron/node_modules/app-builder-lib/out/asar/unpackDetector.js.map
generated
vendored
2
electron/node_modules/app-builder-lib/out/asar/unpackDetector.js.map
generated
vendored
File diff suppressed because one or more lines are too long
5
electron/node_modules/app-builder-lib/out/binDownload.d.ts
generated
vendored
5
electron/node_modules/app-builder-lib/out/binDownload.d.ts
generated
vendored
|
|
@ -1,4 +1,5 @@
|
|||
import { Nullish } from "builder-util-runtime";
|
||||
export declare function download(url: string, output: string, checksum?: string | null): Promise<void>;
|
||||
export declare function getBinFromCustomLoc(name: string, version: string, binariesLocUrl: string, checksum: string): Promise<string>;
|
||||
export declare function getBinFromUrl(name: string, version: string, checksum: string): Promise<string>;
|
||||
export declare function getBin(name: string, url?: string | null, checksum?: string | null): Promise<string>;
|
||||
export declare function getBinFromUrl(releaseName: string, filenameWithExt: string, checksum: string, githubOrgRepo?: string): Promise<string>;
|
||||
export declare function getBin(cacheKey: string, url?: string | Nullish, checksum?: string | Nullish): Promise<string>;
|
||||
|
|
|
|||
131
electron/node_modules/app-builder-lib/out/binDownload.js
generated
vendored
131
electron/node_modules/app-builder-lib/out/binDownload.js
generated
vendored
|
|
@ -1,64 +1,105 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.getBin = exports.getBinFromUrl = exports.getBinFromCustomLoc = exports.download = void 0;
|
||||
const builder_util_1 = require("builder-util");
|
||||
const versionToPromise = new Map();
|
||||
function download(url, output, checksum) {
|
||||
const args = ["download", "--url", url, "--output", output];
|
||||
if (checksum != null) {
|
||||
args.push("--sha512", checksum);
|
||||
}
|
||||
return builder_util_1.executeAppBuilder(args);
|
||||
}
|
||||
exports.download = download;
|
||||
exports.getBinFromCustomLoc = getBinFromCustomLoc;
|
||||
exports.getBinFromUrl = getBinFromUrl;
|
||||
exports.getBin = getBin;
|
||||
const fs = require("fs/promises");
|
||||
const builder_util_1 = require("builder-util");
|
||||
const dynamicImport_1 = require("./util/dynamicImport");
|
||||
const filename_1 = require("builder-util/out/filename");
|
||||
const path = require("path");
|
||||
const electronGet_1 = require("./util/electronGet");
|
||||
const versionToPromise = new Map();
|
||||
async function download(url, output, checksum) {
|
||||
const filenameWithExt = path.basename(new URL(url).pathname);
|
||||
if (checksum == null) {
|
||||
// Without a checksum, a download intercepted via a rogue mirror, tampered CDN
|
||||
// edge, or DNS spoofing can substitute a malicious payload undetected.
|
||||
// Callers should supply a checksum whenever possible.
|
||||
builder_util_1.log.warn({ url }, "downloading without an integrity checksum — the download is not verified against a known-good hash");
|
||||
}
|
||||
const { downloadArtifact, ElectronDownloadCacheMode } = await (0, dynamicImport_1.dynamicImport)("@electron/get");
|
||||
const downloadedFile = await downloadArtifact({
|
||||
version: "9.9.9",
|
||||
artifactName: filenameWithExt,
|
||||
cacheRoot: path.resolve((0, electronGet_1.getCacheDirectory)({ allowEnvVarOverride: true }), "downloads"),
|
||||
cacheMode: ElectronDownloadCacheMode.ReadWrite,
|
||||
...(checksum != null ? { checksums: { [filenameWithExt]: checksum } } : { unsafelyDisableChecksums: true }),
|
||||
mirrorOptions: { resolveAssetURL: async () => Promise.resolve(url) },
|
||||
isGeneric: true,
|
||||
});
|
||||
await fs.copyFile(downloadedFile, output);
|
||||
}
|
||||
function getBinFromCustomLoc(name, version, binariesLocUrl, checksum) {
|
||||
const dirName = `${name}-${version}`;
|
||||
return getBin(dirName, binariesLocUrl, checksum);
|
||||
}
|
||||
exports.getBinFromCustomLoc = getBinFromCustomLoc;
|
||||
function getBinFromUrl(name, version, checksum) {
|
||||
const dirName = `${name}-${version}`;
|
||||
/**
|
||||
* Validates a binary-download custom-directory value read from an environment
|
||||
* variable. These values are interpolated directly into a download URL; a
|
||||
* malicious value (e.g. set via a postinstall hook in node_modules) could
|
||||
* redirect tool downloads to an attacker-controlled server.
|
||||
*
|
||||
* Allowed: relative path components such as "v1.0.0-custom" or "my-mirror/nsis".
|
||||
* Rejected: anything containing "://", ".." (traversal), or a leading "/" (which
|
||||
* could make the resulting URL protocol-relative or change the host).
|
||||
*/
|
||||
function validateBinaryCustomDir(envVarName, value) {
|
||||
if (value.includes("://") || value.includes("..") || value.startsWith("/")) {
|
||||
throw new Error(`${envVarName} must be a safe relative path component (e.g. "v1.0.0-custom"). Values containing "://", "..", or a leading "/" are not allowed. Got: "${value}"`);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
function getBinFromUrl(releaseName, filenameWithExt, checksum, githubOrgRepo = "electron-userland/electron-builder-binaries") {
|
||||
if (/[/\\]|^\.\./.test(filenameWithExt) || filenameWithExt.includes("..")) {
|
||||
throw new Error(`getBinFromUrl: unsafe filenameWithExt "${filenameWithExt}" — must be a plain filename with no path separators or traversal sequences`);
|
||||
}
|
||||
let url;
|
||||
if (process.env.ELECTRON_BUILDER_BINARIES_DOWNLOAD_OVERRIDE_URL) {
|
||||
url = process.env.ELECTRON_BUILDER_BINARIES_DOWNLOAD_OVERRIDE_URL + "/" + dirName + ".7z";
|
||||
const allowHttp = process.env["ELECTRON_BUILDER_BINARIES_ALLOW_HTTP"] === "true";
|
||||
const overrideUrl = (0, builder_util_1.parseValidEnvVarUrl)("ELECTRON_BUILDER_BINARIES_DOWNLOAD_OVERRIDE_URL", allowHttp);
|
||||
if (overrideUrl != null) {
|
||||
url = overrideUrl + "/" + filenameWithExt;
|
||||
}
|
||||
else {
|
||||
const baseUrl = process.env.NPM_CONFIG_ELECTRON_BUILDER_BINARIES_MIRROR ||
|
||||
process.env.npm_config_electron_builder_binaries_mirror ||
|
||||
process.env.npm_package_config_electron_builder_binaries_mirror ||
|
||||
process.env.ELECTRON_BUILDER_BINARIES_MIRROR ||
|
||||
"https://github.com/electron-userland/electron-builder-binaries/releases/download/";
|
||||
const middleUrl = process.env.NPM_CONFIG_ELECTRON_BUILDER_BINARIES_CUSTOM_DIR ||
|
||||
process.env.npm_config_electron_builder_binaries_custom_dir ||
|
||||
process.env.npm_package_config_electron_builder_binaries_custom_dir ||
|
||||
process.env.ELECTRON_BUILDER_BINARIES_CUSTOM_DIR ||
|
||||
dirName;
|
||||
const urlSuffix = dirName + ".7z";
|
||||
url = `${baseUrl}${middleUrl}/${urlSuffix}`;
|
||||
const baseUrl = (0, electronGet_1.getBinariesMirrorUrl)(githubOrgRepo);
|
||||
// Any of these env vars can redirect downloads to a custom release directory.
|
||||
// Validate each one before interpolating into the URL.
|
||||
const CUSTOM_DIR_ENV_VARS = [
|
||||
"NPM_CONFIG_ELECTRON_BUILDER_BINARIES_CUSTOM_DIR",
|
||||
"npm_config_electron_builder_binaries_custom_dir",
|
||||
"npm_package_config_electron_builder_binaries_custom_dir",
|
||||
"ELECTRON_BUILDER_BINARIES_CUSTOM_DIR",
|
||||
];
|
||||
const customDirEntry = CUSTOM_DIR_ENV_VARS.map(name => ({ name, value: process.env[name] })).find(e => e.value != null);
|
||||
const middleUrl = customDirEntry != null ? validateBinaryCustomDir(customDirEntry.name, customDirEntry.value) : releaseName;
|
||||
url = `${baseUrl}${middleUrl}/${filenameWithExt}`;
|
||||
}
|
||||
return getBin(dirName, url, checksum);
|
||||
const cacheKey = `${releaseName}-${path.basename(filenameWithExt, path.extname(filenameWithExt))}`;
|
||||
return getBin(cacheKey, url, checksum);
|
||||
}
|
||||
exports.getBinFromUrl = getBinFromUrl;
|
||||
function getBin(name, url, checksum) {
|
||||
// Old cache is ignored if cache environment variable changes
|
||||
const cacheName = `${process.env.ELECTRON_BUILDER_CACHE}${name}`;
|
||||
let promise = versionToPromise.get(cacheName); // if rejected, we will try to download again
|
||||
function getBin(cacheKey, url, checksum) {
|
||||
var _a;
|
||||
const cacheName = (0, filename_1.sanitizeFileName)(`${(_a = process.env.ELECTRON_BUILDER_CACHE) !== null && _a !== void 0 ? _a : ""}${cacheKey}`);
|
||||
let promise = versionToPromise.get(cacheName);
|
||||
if (promise != null) {
|
||||
return promise;
|
||||
}
|
||||
promise = doGetBin(name, url, checksum);
|
||||
if (url == null) {
|
||||
throw new Error(`getBin("${cacheKey}"): a download URL is required. ` +
|
||||
`The no-URL legacy path (e.g. winCodeSign "0.0.0") is no longer used — ` +
|
||||
`it now downloads from winCodeSign-2.6.0 automatically.`);
|
||||
}
|
||||
const filenameWithExt = path.basename(url);
|
||||
const overrideUrl = url.substring(0, url.lastIndexOf("/"));
|
||||
const releaseName = path.basename(overrideUrl);
|
||||
promise = (0, electronGet_1.downloadBuilderToolset)({
|
||||
releaseName,
|
||||
filenameWithExt,
|
||||
checksums: checksum != null ? { [filenameWithExt]: checksum } : undefined,
|
||||
overrideUrl,
|
||||
});
|
||||
versionToPromise.set(cacheName, promise);
|
||||
return promise;
|
||||
}
|
||||
exports.getBin = getBin;
|
||||
function doGetBin(name, url, checksum) {
|
||||
const args = ["download-artifact", "--name", name];
|
||||
if (url != null) {
|
||||
args.push("--url", url);
|
||||
}
|
||||
if (checksum != null) {
|
||||
args.push("--sha512", checksum);
|
||||
}
|
||||
return builder_util_1.executeAppBuilder(args);
|
||||
}
|
||||
//# sourceMappingURL=binDownload.js.map
|
||||
2
electron/node_modules/app-builder-lib/out/binDownload.js.map
generated
vendored
2
electron/node_modules/app-builder-lib/out/binDownload.js.map
generated
vendored
File diff suppressed because one or more lines are too long
54
electron/node_modules/app-builder-lib/out/codeSign/certInfo.d.ts
generated
vendored
Normal file
54
electron/node_modules/app-builder-lib/out/codeSign/certInfo.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
/**
|
||||
* Decrypt `data` using RC2-CBC with PKCS#7 padding removal (RFC 2268).
|
||||
*
|
||||
* Used for pbeWithSHAAnd40BitRC2CBC (OID 1.2.840.113549.1.12.1.6) and
|
||||
* pbeWithSHAAnd128BitRC2CBC (OID 1.2.840.113549.1.12.1.5).
|
||||
*
|
||||
* These OIDs are commonly used to encrypt certificate bags in PKCS#12
|
||||
* files produced by OpenSSL and Windows with default settings. Node.js 22+
|
||||
* (OpenSSL 3 default provider) does not support RC2 via `createDecipheriv`.
|
||||
*/
|
||||
declare function rc2CbcDecrypt(key: Buffer, iv: Buffer, data: Buffer, effectiveBits: number): Buffer;
|
||||
/**
|
||||
* PKCS#12 key/IV derivation function from RFC 7292 Appendix B (SHA-1 variant).
|
||||
* id = 1 to derive a key, id = 2 to derive an IV.
|
||||
*
|
||||
* Throws if `iterations` is outside [1, MAX_PKCS12_PBE_ITERATIONS] to prevent
|
||||
* CPU exhaustion from a crafted PFX file.
|
||||
*/
|
||||
declare function pkcs12PbeDeriveKey(password: Buffer, salt: Buffer, iterations: number, id: number, length: number): Buffer;
|
||||
/**
|
||||
* Encode a password as UTF-16 Big Endian with a null terminator, which is the
|
||||
* format required by PKCS#12 PBE key derivation (RFC 7292).
|
||||
* An empty string yields [0x00, 0x00] (just the null terminator).
|
||||
*/
|
||||
declare function pkcs12PasswordToUtf16(password: string): Buffer;
|
||||
/**
|
||||
* Reads certificate info from a PKCS#12 (.pfx) file using pkijs (unobfuscated TypeScript).
|
||||
* Mirrors the `certificate-info` subcommand of app-builder-bin.
|
||||
* https://github.com/develar/app-builder/blob/master/pkg/codesign/p12.go
|
||||
*
|
||||
* Returns { commonName, bloodyMicrosoftSubjectDn } on success.
|
||||
*
|
||||
* Known divergences from the Go binary:
|
||||
* - No OpenSSL fallback when the pure PKCS#12 decoder fails for a non-password reason.
|
||||
* - Unknown OIDs are rendered using the raw numeric OID as the type name (e.g. `2.5.4.100=value`); Go uses `OID=#hexbytes` when ASN.1 marshal succeeds.
|
||||
* - RDN ordering uses DER order; Go normalizes via pkix.Name.ToRDNSequence then reverses via
|
||||
* BloodyMsString. These coincide for pkijs-generated certs (CN-first DER) but may
|
||||
* differ for real CA-issued certs stored in traditional C-first DER order.
|
||||
*/
|
||||
export declare function readCertInfo(file: string, password: string): Promise<{
|
||||
commonName: string;
|
||||
bloodyMicrosoftSubjectDn: string;
|
||||
}>;
|
||||
/**
|
||||
* Internal functions exported exclusively for unit testing.
|
||||
* Not part of the public API — do not use outside of test files.
|
||||
*/
|
||||
export declare const _testingOnly: {
|
||||
pkcs12PbeDeriveKey: typeof pkcs12PbeDeriveKey;
|
||||
pkcs12PasswordToUtf16: typeof pkcs12PasswordToUtf16;
|
||||
rc2CbcDecrypt: typeof rc2CbcDecrypt;
|
||||
MAX_PKCS12_PBE_ITERATIONS: number;
|
||||
};
|
||||
export {};
|
||||
466
electron/node_modules/app-builder-lib/out/codeSign/certInfo.js
generated
vendored
Normal file
466
electron/node_modules/app-builder-lib/out/codeSign/certInfo.js
generated
vendored
Normal file
|
|
@ -0,0 +1,466 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports._testingOnly = void 0;
|
||||
exports.readCertInfo = readCertInfo;
|
||||
const crypto_1 = require("crypto");
|
||||
const asn1js = require("asn1js");
|
||||
const pkijs = require("pkijs");
|
||||
const webcrypto_1 = require("@peculiar/webcrypto");
|
||||
const fs_extra_1 = require("fs-extra");
|
||||
const builder_util_1 = require("builder-util");
|
||||
// OID for codeSigning extended key usage
|
||||
const CODE_SIGNING_OID = "1.3.6.1.5.5.7.3.3";
|
||||
// OID for the PKCS#12 certificate bag type
|
||||
const CERT_BAG_OID = "1.2.840.113549.1.12.10.1.3";
|
||||
// Maps certificate attribute OIDs to their short names.
|
||||
// Matches the attributeTypeNames map in the Go reference implementation exactly:
|
||||
// https://github.com/develar/app-builder/blob/master/pkg/codesign/p12.go
|
||||
const ATTRIBUTE_TYPE_NAMES = {
|
||||
"2.5.4.6": "C",
|
||||
"2.5.4.10": "O",
|
||||
"2.5.4.11": "OU",
|
||||
"2.5.4.3": "CN",
|
||||
"2.5.4.5": "SERIALNUMBER",
|
||||
"2.5.4.7": "L",
|
||||
"2.5.4.8": "ST",
|
||||
"2.5.4.9": "STREET",
|
||||
"2.5.4.17": "POSTALCODE",
|
||||
};
|
||||
// Characters that must be quoted in a DN value to match Go binary BloodyMsString output
|
||||
const NEEDS_DN_ESCAPING = /[,+"\\<>;]/;
|
||||
function escapeDnValue(value) {
|
||||
if (NEEDS_DN_ESCAPING.test(value)) {
|
||||
// Escape embedded double-quotes by doubling them, then wrap entire value in quotes
|
||||
return `"${value.replace(/"/g, '""')}"`;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
// Set up the pkijs WebCrypto engine once. @peculiar/webcrypto supports legacy cipher suites
|
||||
// (RC2, 3DES) used by real-world CA-issued PFX files, unlike native Node.js WebCrypto.
|
||||
const peculiarCrypto = new webcrypto_1.Crypto();
|
||||
pkijs.setEngine("peculiar", new pkijs.CryptoEngine({ name: "peculiar", crypto: peculiarCrypto, subtle: peculiarCrypto.subtle }));
|
||||
function toArrayBuffer(buf) {
|
||||
const ab = new ArrayBuffer(buf.byteLength);
|
||||
new Uint8Array(ab).set(buf);
|
||||
return ab;
|
||||
}
|
||||
// ── PKCS#12 legacy PBE support (RFC 7292 Appendix B) ───────────────────────
|
||||
//
|
||||
// pkijs's CryptoEngine.decryptEncryptedContentInfo only handles PBES2
|
||||
// (OID 1.2.840.113549.1.5.13). Many real-world PFX files use the older
|
||||
// pkcs-12PbeIds ciphers (SHA1+3DES, SHA1+2DES, SHA1+RC2-128, SHA1+RC2-40).
|
||||
// We implement 3DES/2DES using Node.js's built-in `crypto` module and RC2
|
||||
// with a pure-TypeScript RFC 2268 implementation — RC2 was moved to
|
||||
// OpenSSL 3's legacy provider (not loaded by default) and is unavailable
|
||||
// via `createDecipheriv` in Node.js 22+.
|
||||
// ── RFC 2268 RC2-CBC implementation ─────────────────────────────────────────
|
||||
/** Permutation table from RFC 2268. */
|
||||
const RC2_PITABLE = Uint8Array.from([
|
||||
0xd9, 0x78, 0xf9, 0xc4, 0x19, 0xdd, 0xb5, 0xed, 0x28, 0xe9, 0xfd, 0x79, 0x4a, 0xa0, 0xd8, 0x9d, 0xc6, 0x7e, 0x37, 0x83, 0x2b, 0x76, 0x53, 0x8e, 0x62, 0x4c, 0x64, 0x88, 0x44,
|
||||
0x8b, 0xfb, 0xa2, 0x17, 0x9a, 0x59, 0xf5, 0x87, 0xb3, 0x4f, 0x13, 0x61, 0x45, 0x6d, 0x8d, 0x09, 0x81, 0x7d, 0x32, 0xbd, 0x8f, 0x40, 0xeb, 0x86, 0xb7, 0x7b, 0x0b, 0xf0, 0x95,
|
||||
0x21, 0x22, 0x5c, 0x6b, 0x4e, 0x82, 0x54, 0xd6, 0x65, 0x93, 0xce, 0x60, 0xb2, 0x1c, 0x73, 0x56, 0xc0, 0x14, 0xa7, 0x8c, 0xf1, 0xdc, 0x12, 0x75, 0xca, 0x1f, 0x3b, 0xbe, 0xe4,
|
||||
0xd1, 0x42, 0x3d, 0xd4, 0x30, 0xa3, 0x3c, 0xb6, 0x26, 0x6f, 0xbf, 0x0e, 0xda, 0x46, 0x69, 0x07, 0x57, 0x27, 0xf2, 0x1d, 0x9b, 0xbc, 0x94, 0x43, 0x03, 0xf8, 0x11, 0xc7, 0xf6,
|
||||
0x90, 0xef, 0x3e, 0xe7, 0x06, 0xc3, 0xd5, 0x2f, 0xc8, 0x66, 0x1e, 0xd7, 0x08, 0xe8, 0xea, 0xde, 0x80, 0x52, 0xee, 0xf7, 0x84, 0xaa, 0x72, 0xac, 0x35, 0x4d, 0x6a, 0x2a, 0x96,
|
||||
0x1a, 0xd2, 0x71, 0x5a, 0x15, 0x49, 0x74, 0x4b, 0x9f, 0xd0, 0x5e, 0x04, 0x18, 0xa4, 0xec, 0xc2, 0xe0, 0x41, 0x6e, 0x0f, 0x51, 0xcb, 0xcc, 0x24, 0x91, 0xaf, 0x50, 0xa1, 0xf4,
|
||||
0x70, 0x39, 0x99, 0x7c, 0x3a, 0x85, 0x23, 0xb8, 0xb4, 0x7a, 0xfc, 0x02, 0x36, 0x5b, 0x25, 0x55, 0x97, 0x31, 0x2d, 0x5d, 0xfa, 0x98, 0xe3, 0x8a, 0x92, 0xae, 0x05, 0xdf, 0x29,
|
||||
0x10, 0x67, 0x6c, 0xba, 0xc9, 0xd3, 0x00, 0xe6, 0xcf, 0xe1, 0x9e, 0xa8, 0x2c, 0x63, 0x16, 0x01, 0x3f, 0x58, 0xe2, 0x89, 0xa9, 0x0d, 0x38, 0x34, 0x1b, 0xab, 0x33, 0xff, 0xb0,
|
||||
0xbb, 0x48, 0x0c, 0x5f, 0xb9, 0xb1, 0xcd, 0x2e, 0xc5, 0xf3, 0xdb, 0x47, 0xe5, 0xa5, 0x9c, 0x77, 0x0a, 0xa6, 0x20, 0x68, 0xfe, 0x7f, 0xc1, 0xad,
|
||||
]);
|
||||
/** Rotation amounts for R[0], R[1], R[2], R[3] in each mix round. */
|
||||
const RC2_ROT = [1, 2, 3, 5];
|
||||
/**
|
||||
* Expand a variable-length key to 64 sixteen-bit subkeys (RFC 2268 Section 2).
|
||||
* `effectiveBits` controls the effective key length for export-grade keys
|
||||
* (40 = RC2-40, 128 = RC2-128).
|
||||
*/
|
||||
function rc2ExpandKey(key, effectiveBits) {
|
||||
// Guard: effectiveBits = 0 causes T8 = 0, making L[128-0] = L[128] an OOB
|
||||
// access on a 128-element Uint8Array (silently returns undefined, producing
|
||||
// a wrong key schedule). Values > 1024 exceed the RFC 2268 key schedule table.
|
||||
if (!Number.isInteger(effectiveBits) || effectiveBits < 1 || effectiveBits > 1024) {
|
||||
throw new Error(`rc2ExpandKey: effectiveBits must be an integer in [1, 1024], got ${effectiveBits}`);
|
||||
}
|
||||
const T = key.length;
|
||||
const T8 = Math.ceil(effectiveBits / 8);
|
||||
// 0xff >> (effectiveBits & 7) gives 0xff for multiples-of-8 effective lengths
|
||||
// (no masking), and a smaller mask for non-multiples.
|
||||
const TM = 0xff >> (effectiveBits & 7);
|
||||
const L = new Uint8Array(128);
|
||||
for (let i = 0; i < T; i++) {
|
||||
L[i] = key[i];
|
||||
}
|
||||
for (let i = T; i < 128; i++) {
|
||||
L[i] = RC2_PITABLE[(L[i - 1] + L[i - T]) & 0xff];
|
||||
}
|
||||
L[128 - T8] = RC2_PITABLE[L[128 - T8] & TM];
|
||||
for (let i = 127 - T8; i >= 0; i--) {
|
||||
L[i] = RC2_PITABLE[L[i + 1] ^ L[i + T8]];
|
||||
}
|
||||
const K = new Array(64);
|
||||
for (let i = 0; i < 64; i++) {
|
||||
K[i] = L[2 * i] | (L[2 * i + 1] << 8);
|
||||
}
|
||||
return K;
|
||||
}
|
||||
/** Rotate a 16-bit word right by `bits` positions. */
|
||||
function ror16(word, bits) {
|
||||
return ((word & 0xffff) >> bits) | ((word << (16 - bits)) & 0xffff);
|
||||
}
|
||||
/**
|
||||
* Decrypt `data` using RC2-CBC with PKCS#7 padding removal (RFC 2268).
|
||||
*
|
||||
* Used for pbeWithSHAAnd40BitRC2CBC (OID 1.2.840.113549.1.12.1.6) and
|
||||
* pbeWithSHAAnd128BitRC2CBC (OID 1.2.840.113549.1.12.1.5).
|
||||
*
|
||||
* These OIDs are commonly used to encrypt certificate bags in PKCS#12
|
||||
* files produced by OpenSSL and Windows with default settings. Node.js 22+
|
||||
* (OpenSSL 3 default provider) does not support RC2 via `createDecipheriv`.
|
||||
*/
|
||||
function rc2CbcDecrypt(key, iv, data, effectiveBits) {
|
||||
// Guard: a non-multiple-of-8 ciphertext causes the last partial block to be
|
||||
// processed with `undefined` bytes. In JS, `undefined | (undefined << 8)`
|
||||
// produces NaN, and `NaN & 0xffff` produces 0 — so partial blocks silently
|
||||
// produce garbage output rather than throwing.
|
||||
if (data.length === 0 || data.length % 8 !== 0) {
|
||||
throw new Error(`rc2CbcDecrypt: ciphertext length ${data.length} is not a positive multiple of the 8-byte RC2 block size`);
|
||||
}
|
||||
if (iv.length !== 8) {
|
||||
throw new Error(`rc2CbcDecrypt: IV must be exactly 8 bytes, got ${iv.length}`);
|
||||
}
|
||||
const K = rc2ExpandKey(key, effectiveBits);
|
||||
const out = Buffer.alloc(data.length);
|
||||
const prev = Buffer.from(iv); // CBC running state; starts as the IV
|
||||
for (let offset = 0; offset < data.length; offset += 8) {
|
||||
const ct = data.subarray(offset, offset + 8);
|
||||
// Parse ciphertext block as four little-endian 16-bit words
|
||||
const R = [(ct[0] | (ct[1] << 8)) & 0xffff, (ct[2] | (ct[3] << 8)) & 0xffff, (ct[4] | (ct[5] << 8)) & 0xffff, (ct[6] | (ct[7] << 8)) & 0xffff];
|
||||
// Reverse the encryption round plan [5 mix, 1 mash, 6 mix, 1 mash, 5 mix].
|
||||
// For decryption j starts at 63 and decrements in each reverse-mix step.
|
||||
let j = 63;
|
||||
const rMix = () => {
|
||||
for (let i = 3; i >= 0; i--) {
|
||||
R[i] = ror16(R[i], RC2_ROT[i]);
|
||||
const r3 = R[(i + 3) % 4];
|
||||
R[i] = (R[i] - K[j] - (r3 & R[(i + 2) % 4]) - (~r3 & 0xffff & R[(i + 1) % 4])) & 0xffff;
|
||||
j--;
|
||||
}
|
||||
};
|
||||
const rMash = () => {
|
||||
for (let i = 3; i >= 0; i--) {
|
||||
R[i] = (R[i] - K[R[(i + 3) % 4] & 63]) & 0xffff;
|
||||
}
|
||||
};
|
||||
for (let n = 0; n < 5; n++) {
|
||||
rMix();
|
||||
}
|
||||
rMash();
|
||||
for (let n = 0; n < 6; n++) {
|
||||
rMix();
|
||||
}
|
||||
rMash();
|
||||
for (let n = 0; n < 5; n++) {
|
||||
rMix();
|
||||
}
|
||||
// XOR decrypted words with previous ciphertext block (CBC mode)
|
||||
for (let i = 0; i < 4; i++) {
|
||||
out[offset + i * 2] = (R[i] & 0xff) ^ prev[i * 2];
|
||||
out[offset + i * 2 + 1] = (R[i] >> 8) ^ prev[i * 2 + 1];
|
||||
}
|
||||
// Advance CBC state to current ciphertext block
|
||||
ct.copy(prev);
|
||||
}
|
||||
// Validate and strip PKCS#7 padding.
|
||||
// Without this guard, padLen = 0 silently returns the full buffer (no stripping)
|
||||
// and padLen > 8 causes Buffer.subarray(0, negative) → empty buffer, both
|
||||
// silently. A wrong key/IV produces decrypted bytes that fail this check.
|
||||
const padLen = out[out.length - 1];
|
||||
if (padLen < 1 || padLen > 8) {
|
||||
throw new Error(`rc2CbcDecrypt: invalid PKCS#7 pad byte 0x${padLen.toString(16).padStart(2, "0")} — the ciphertext is corrupt or the wrong key/IV was used`);
|
||||
}
|
||||
for (let i = out.length - padLen; i < out.length; i++) {
|
||||
if (out[i] !== padLen) {
|
||||
throw new Error(`rc2CbcDecrypt: invalid PKCS#7 padding — the ciphertext is corrupt or the wrong key/IV was used`);
|
||||
}
|
||||
}
|
||||
return out.subarray(0, out.length - padLen);
|
||||
}
|
||||
/** PKCS#12 legacy PBE OIDs (pkcs-12PbeIds) and their cipher parameters. */
|
||||
const PKCS12_PBE_ALGOS = {
|
||||
"1.2.840.113549.1.12.1.3": { cipher: "des-ede3-cbc", keyLen: 24, ivLen: 8 }, // pbeWithSHAAnd3KeyTripleDESCBC
|
||||
"1.2.840.113549.1.12.1.4": { cipher: "des-ede-cbc", keyLen: 16, ivLen: 8 }, // pbeWithSHAAnd2KeyTripleDESCBC
|
||||
"1.2.840.113549.1.12.1.5": { cipher: "rc2-cbc", keyLen: 16, ivLen: 8, rc2Bits: 128 }, // pbeWithSHAAnd128BitRC2CBC
|
||||
"1.2.840.113549.1.12.1.6": { cipher: "rc2-cbc", keyLen: 5, ivLen: 8, rc2Bits: 40 }, // pbeWithSHAAnd40BitRC2CBC
|
||||
};
|
||||
/**
|
||||
* Maximum PKCS#12 PBE iteration count accepted.
|
||||
*
|
||||
* A maliciously crafted PFX can set iterations to Number.MAX_SAFE_INTEGER,
|
||||
* causing the SHA-1 loop to run for an arbitrary amount of time (DoS).
|
||||
* Real-world PFX files use 1 000–50 000 iterations; this cap is generous
|
||||
* enough to accommodate even unusually high-security certs while blocking
|
||||
* obviously hostile inputs.
|
||||
*/
|
||||
const MAX_PKCS12_PBE_ITERATIONS = 300000;
|
||||
/**
|
||||
* PKCS#12 key/IV derivation function from RFC 7292 Appendix B (SHA-1 variant).
|
||||
* id = 1 to derive a key, id = 2 to derive an IV.
|
||||
*
|
||||
* Throws if `iterations` is outside [1, MAX_PKCS12_PBE_ITERATIONS] to prevent
|
||||
* CPU exhaustion from a crafted PFX file.
|
||||
*/
|
||||
function pkcs12PbeDeriveKey(password, salt, iterations, id, length) {
|
||||
if (!Number.isInteger(iterations) || iterations < 1 || iterations > MAX_PKCS12_PBE_ITERATIONS) {
|
||||
throw new Error(`PKCS#12 PBE iteration count ${iterations} is outside safe range [1, ${MAX_PKCS12_PBE_ITERATIONS}]; refusing to process — the file may be crafted to exhaust CPU`);
|
||||
}
|
||||
// A crafted PFX could supply a multi-megabyte salt, causing Buffer.alloc(sLen) inside
|
||||
// the KDF to allocate gigabytes (sLen = ceil(salt.length / 64) * 64).
|
||||
const MAX_SALT_BYTES = 4096;
|
||||
if (salt.length > MAX_SALT_BYTES) {
|
||||
throw new Error(`PKCS#12 PBE salt length ${salt.length} exceeds the safe maximum of ${MAX_SALT_BYTES} bytes — the file may be crafted to exhaust memory`);
|
||||
}
|
||||
const u = 20; // SHA-1 output bytes
|
||||
const v = 64; // SHA-1 block bytes
|
||||
// Step 1: D = ID byte repeated v times
|
||||
const D = Buffer.alloc(v, id);
|
||||
// Step 2: S = salt bytes repeated to fill ceil(salt.length / v) * v bytes
|
||||
const sLen = salt.length > 0 ? Math.ceil(salt.length / v) * v : 0;
|
||||
const S = Buffer.alloc(sLen);
|
||||
for (let i = 0; i < sLen; i++) {
|
||||
S[i] = salt[i % salt.length];
|
||||
}
|
||||
// Step 3: P = password bytes repeated to fill ceil(password.length / v) * v bytes
|
||||
const pLen = password.length > 0 ? Math.ceil(password.length / v) * v : 0;
|
||||
const P = Buffer.alloc(pLen);
|
||||
for (let i = 0; i < pLen; i++) {
|
||||
P[i] = password[i % password.length];
|
||||
}
|
||||
// Step 4: I = S || P (mutable, updated in step 6C)
|
||||
const I = new Uint8Array(Buffer.concat([S, P]));
|
||||
const c = Math.ceil(length / u);
|
||||
const result = Buffer.alloc(c * u);
|
||||
for (let i = 0; i < c; i++) {
|
||||
// Step 6A: A_i = H^iterations(D || I)
|
||||
let Ai = (0, crypto_1.createHash)("sha1").update(D).update(Buffer.from(I)).digest();
|
||||
for (let j = 1; j < iterations; j++) {
|
||||
Ai = (0, crypto_1.createHash)("sha1").update(Ai).digest();
|
||||
}
|
||||
Ai.copy(result, i * u);
|
||||
// Step 6B: B = A_i repeated to fill v bytes
|
||||
const B = new Uint8Array(v);
|
||||
for (let j = 0; j < v; j++) {
|
||||
B[j] = Ai[j % u];
|
||||
}
|
||||
// Step 6C: each v-byte block of I is incremented by (B + 1) mod 2^(v*8)
|
||||
const blockCount = Math.ceil(I.length / v);
|
||||
for (let j = 0; j < blockCount; j++) {
|
||||
let carry = 1;
|
||||
for (let b = v - 1; b >= 0; b--) {
|
||||
const idx = j * v + b;
|
||||
if (idx < I.length) {
|
||||
const sum = I[idx] + B[b] + carry;
|
||||
I[idx] = sum & 0xff;
|
||||
carry = sum >> 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.subarray(0, length);
|
||||
}
|
||||
/**
|
||||
* Encode a password as UTF-16 Big Endian with a null terminator, which is the
|
||||
* format required by PKCS#12 PBE key derivation (RFC 7292).
|
||||
* An empty string yields [0x00, 0x00] (just the null terminator).
|
||||
*/
|
||||
function pkcs12PasswordToUtf16(password) {
|
||||
const buf = Buffer.alloc((password.length + 1) * 2);
|
||||
for (let i = 0; i < password.length; i++) {
|
||||
const code = password.charCodeAt(i);
|
||||
buf[i * 2] = (code >> 8) & 0xff;
|
||||
buf[i * 2 + 1] = code & 0xff;
|
||||
}
|
||||
// Last two bytes are already 0x00 0x00 (null terminator) from Buffer.alloc.
|
||||
return buf;
|
||||
}
|
||||
/**
|
||||
* Decrypt PKCS#12 legacy PBE encrypted content using Node.js crypto.
|
||||
*
|
||||
* @param algId - OID from PKCS12_PBE_ALGOS
|
||||
* @param algParams - asn1js object for PKCS12PBEParams (SEQUENCE { OCTET STRING, INTEGER })
|
||||
* @param encContent - asn1js object for the encrypted content (Constructed or Primitive [0] IMPLICIT)
|
||||
* @param password - plain-text password string
|
||||
*/
|
||||
function decryptLegacyPkcs12Pbe(algId, algParams, encContent, password) {
|
||||
var _a;
|
||||
const algo = PKCS12_PBE_ALGOS[algId];
|
||||
// PKCS12PBEParams ::= SEQUENCE { salt OCTET STRING, iterations INTEGER }
|
||||
const salt = Buffer.from(algParams.valueBlock.value[0].valueBlock.valueHexView);
|
||||
const iterations = Number(algParams.valueBlock.value[1].valueBlock.valueDec);
|
||||
const pwdBytes = pkcs12PasswordToUtf16(password);
|
||||
const key = pkcs12PbeDeriveKey(pwdBytes, salt, iterations, 1, algo.keyLen);
|
||||
const iv = pkcs12PbeDeriveKey(pwdBytes, salt, iterations, 2, algo.ivLen);
|
||||
// Extract raw encrypted bytes from the [0] IMPLICIT OCTET STRING.
|
||||
// The encryptedContent field can be a Constructed (fragmented) or Primitive tag.
|
||||
let encBytes;
|
||||
if ((_a = encContent.idBlock) === null || _a === void 0 ? void 0 : _a.isConstructed) {
|
||||
encBytes = Buffer.concat(encContent.valueBlock.value.map((p) => Buffer.from(p.valueBlock.valueHexView)));
|
||||
}
|
||||
else {
|
||||
encBytes = Buffer.from(encContent.valueBlock.valueHexView);
|
||||
}
|
||||
if (algo.rc2Bits != null) {
|
||||
// RC2 is not available in Node.js 22+ via createDecipheriv (OpenSSL 3 moved
|
||||
// it to the legacy provider which is not loaded by default). Use our pure-TS
|
||||
// RFC 2268 implementation instead.
|
||||
return rc2CbcDecrypt(key, iv, encBytes, algo.rc2Bits);
|
||||
}
|
||||
const decipher = (0, crypto_1.createDecipheriv)(algo.cipher, key, iv);
|
||||
return Buffer.concat([decipher.update(encBytes), decipher.final()]);
|
||||
}
|
||||
/**
|
||||
* Reads certificate info from a PKCS#12 (.pfx) file using pkijs (unobfuscated TypeScript).
|
||||
* Mirrors the `certificate-info` subcommand of app-builder-bin.
|
||||
* https://github.com/develar/app-builder/blob/master/pkg/codesign/p12.go
|
||||
*
|
||||
* Returns { commonName, bloodyMicrosoftSubjectDn } on success.
|
||||
*
|
||||
* Known divergences from the Go binary:
|
||||
* - No OpenSSL fallback when the pure PKCS#12 decoder fails for a non-password reason.
|
||||
* - Unknown OIDs are rendered using the raw numeric OID as the type name (e.g. `2.5.4.100=value`); Go uses `OID=#hexbytes` when ASN.1 marshal succeeds.
|
||||
* - RDN ordering uses DER order; Go normalizes via pkix.Name.ToRDNSequence then reverses via
|
||||
* BloodyMsString. These coincide for pkijs-generated certs (CN-first DER) but may
|
||||
* differ for real CA-issued certs stored in traditional C-first DER order.
|
||||
*/
|
||||
async function readCertInfo(file, password) {
|
||||
var _a, _b;
|
||||
const pfxDer = await (0, fs_extra_1.readFile)(file);
|
||||
// asn1js requires a plain ArrayBuffer
|
||||
const pfxBuf = toArrayBuffer(pfxDer);
|
||||
let asn1;
|
||||
try {
|
||||
asn1 = asn1js.fromBER(pfxBuf);
|
||||
if (asn1.offset === -1) {
|
||||
throw new Error("offset -1: invalid BER encoding");
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
throw new Error(`PKCS#12 file "${file}" contains invalid ASN.1/DER data: ${err instanceof Error ? err.message : String(err)}`);
|
||||
}
|
||||
const pfx = new pkijs.PFX({ schema: asn1.result });
|
||||
const pwBuf = toArrayBuffer(Buffer.from(password, "utf-8"));
|
||||
// Step 1: Verify MAC (or signature) integrity and parse the AuthenticatedSafe container.
|
||||
// pkijs throws "Integrity for the PKCS#12 data is broken!" on wrong password.
|
||||
try {
|
||||
await pfx.parseInternalValues({ password: pwBuf, checkIntegrity: true });
|
||||
}
|
||||
catch (err) {
|
||||
const detail = err instanceof Error ? err.message : String(err);
|
||||
const lower = detail.toLowerCase();
|
||||
if (lower.includes("integrity") || lower.includes("mac") || lower.includes("password") || lower.includes("pkcs#12")) {
|
||||
throw new Error(`password incorrect for certificate file "${file}" — verify the password matches the PFX. pkijs detail: ${detail}`);
|
||||
}
|
||||
builder_util_1.log.debug({ file, error: detail }, "pkijs failed to decode PKCS#12; no OpenSSL fallback available in Node.js");
|
||||
throw new Error(`Failed to decode PKCS#12 file "${file}" — the file may be corrupt, use an unsupported cipher, or require OpenSSL. pkijs detail: ${detail}`);
|
||||
}
|
||||
const authSafe = (_a = pfx.parsedValue) === null || _a === void 0 ? void 0 : _a.authenticatedSafe;
|
||||
if (authSafe == null) {
|
||||
throw new Error(`Failed to parse AuthenticatedSafe in PKCS#12 file "${file}"`);
|
||||
}
|
||||
// Step 2: Iterate over the authenticated-safe ContentInfos and extract all certificates.
|
||||
//
|
||||
// We do NOT call authSafe.parseInternalValues() because pkijs's CryptoEngine only handles
|
||||
// PBES2 (OID 1.2.840.113549.1.5.13) for EncryptedData. Real-world PFX files (including
|
||||
// CA-issued and electron-builder-generated certs) often use the older pkcs-12PbeIds ciphers
|
||||
// (e.g. pbeWithSHAAnd3KeyTripleDESCBC). We handle those with our own Node.js crypto path.
|
||||
const certs = [];
|
||||
for (const ci of authSafe.safeContents) {
|
||||
let safeBER;
|
||||
if (ci.contentType === pkijs.id_ContentType_Data) {
|
||||
// Data: content is an OCTET STRING containing DER-encoded SafeContents.
|
||||
safeBER = ci.content.getValue();
|
||||
}
|
||||
else if (ci.contentType === pkijs.id_ContentType_EncryptedData) {
|
||||
// EncryptedData: decrypt the SafeContents, routing by algorithm OID.
|
||||
const encData = new pkijs.EncryptedData({ schema: ci.content });
|
||||
const algId = encData.encryptedContentInfo.contentEncryptionAlgorithm.algorithmId;
|
||||
if (Object.prototype.hasOwnProperty.call(PKCS12_PBE_ALGOS, algId)) {
|
||||
// Legacy PKCS#12 PBE (pbeWithSHAAnd*) — use our RFC 7292 implementation.
|
||||
const decrypted = decryptLegacyPkcs12Pbe(algId, encData.encryptedContentInfo.contentEncryptionAlgorithm.algorithmParams, encData.encryptedContentInfo.encryptedContent, password);
|
||||
safeBER = toArrayBuffer(decrypted);
|
||||
}
|
||||
else {
|
||||
// PBES2 or other modern OID — delegate to the pkijs engine.
|
||||
safeBER = await encData.decrypt({ password: pwBuf });
|
||||
}
|
||||
}
|
||||
else {
|
||||
// EnvelopedData or other types — skip (not needed for cert extraction).
|
||||
continue;
|
||||
}
|
||||
// Parse SafeContents and collect X.509 certificates from cert bags.
|
||||
const sc = pkijs.SafeContents.fromBER(safeBER);
|
||||
for (const bag of sc.safeBags) {
|
||||
if (bag.bagId === CERT_BAG_OID) {
|
||||
const certBag = bag.bagValue;
|
||||
if (certBag.parsedValue instanceof pkijs.Certificate) {
|
||||
certs.push(certBag.parsedValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (certs.length === 0) {
|
||||
throw new Error(`No certificates found in PKCS#12 file "${file}" — the file may be a key-only PFX or be empty`);
|
||||
}
|
||||
// Find the certificate with the codeSigning Extended Key Usage.
|
||||
// pkijs auto-parses known extensions via ExtensionValueFactory (registered at module init).
|
||||
const signingCert = certs.find(cert => {
|
||||
var _a;
|
||||
const ekuExt = (_a = cert.extensions) === null || _a === void 0 ? void 0 : _a.find(e => e.extnID === pkijs.id_ExtKeyUsage);
|
||||
if (ekuExt == null) {
|
||||
return false;
|
||||
}
|
||||
if (ekuExt.parsedValue instanceof pkijs.ExtKeyUsage) {
|
||||
return ekuExt.parsedValue.keyPurposes.includes(CODE_SIGNING_OID);
|
||||
}
|
||||
// Fallback: manually parse the extension OctetString value.
|
||||
try {
|
||||
const inner = asn1js.fromBER(ekuExt.extnValue.valueBlock.valueHexView);
|
||||
if (inner.offset === -1) {
|
||||
return false;
|
||||
}
|
||||
const eku = new pkijs.ExtKeyUsage({ schema: inner.result });
|
||||
return eku.keyPurposes.includes(CODE_SIGNING_OID);
|
||||
}
|
||||
catch {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
if (signingCert == null) {
|
||||
throw new Error(`No certificate with ExtKeyUsageCodeSigning found in "${file}" — ${certs.length} certificate(s) present but none have the codeSigning extended key usage. ` +
|
||||
`Ensure the PFX contains a code-signing certificate, not just a CA or TLS certificate.`);
|
||||
}
|
||||
const cnAttr = signingCert.subject.typesAndValues.find(a => a.type === "2.5.4.3");
|
||||
const commonName = String((_b = cnAttr === null || cnAttr === void 0 ? void 0 : cnAttr.value.valueBlock.value) !== null && _b !== void 0 ? _b : "");
|
||||
// Format DN as "CN=X,O=X,..." matching Go's BloodyMsString output.
|
||||
// Uses ATTRIBUTE_TYPE_NAMES to mirror Go's attributeTypeNames map exactly, so STREET,
|
||||
// POSTALCODE, and SERIALNUMBER (present in EV code-signing certs) are handled correctly.
|
||||
// Unknown OIDs fall back to the bare OID string as the type name.
|
||||
const bloodyMicrosoftSubjectDn = signingCert.subject.typesAndValues
|
||||
.map(a => {
|
||||
var _a;
|
||||
const typeName = (_a = ATTRIBUTE_TYPE_NAMES[a.type]) !== null && _a !== void 0 ? _a : a.type;
|
||||
return `${typeName}=${escapeDnValue(String(a.value.valueBlock.value))}`;
|
||||
})
|
||||
.join(",");
|
||||
return { commonName, bloodyMicrosoftSubjectDn };
|
||||
}
|
||||
/**
|
||||
* Internal functions exported exclusively for unit testing.
|
||||
* Not part of the public API — do not use outside of test files.
|
||||
*/
|
||||
exports._testingOnly = {
|
||||
pkcs12PbeDeriveKey,
|
||||
pkcs12PasswordToUtf16,
|
||||
rc2CbcDecrypt,
|
||||
MAX_PKCS12_PBE_ITERATIONS,
|
||||
};
|
||||
//# sourceMappingURL=certInfo.js.map
|
||||
1
electron/node_modules/app-builder-lib/out/codeSign/certInfo.js.map
generated
vendored
Normal file
1
electron/node_modules/app-builder-lib/out/codeSign/certInfo.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
40
electron/node_modules/app-builder-lib/out/codeSign/codesign.js
generated
vendored
40
electron/node_modules/app-builder-lib/out/codeSign/codesign.js
generated
vendored
|
|
@ -1,42 +1,25 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.importCertificate = void 0;
|
||||
const fs_extra_1 = require("fs-extra");
|
||||
const os_1 = require("os");
|
||||
const path = require("path");
|
||||
exports.importCertificate = importCertificate;
|
||||
const builder_util_1 = require("builder-util");
|
||||
const fs_1 = require("builder-util/out/fs");
|
||||
const fs_extra_1 = require("fs-extra");
|
||||
const binDownload_1 = require("../binDownload");
|
||||
/** @private */
|
||||
async function importCertificate(cscLink, tmpDir, currentDir) {
|
||||
var _a, _b;
|
||||
cscLink = cscLink.trim();
|
||||
let file = null;
|
||||
if ((cscLink.length > 3 && cscLink[1] === ":") || cscLink.startsWith("/") || cscLink.startsWith(".")) {
|
||||
file = cscLink;
|
||||
}
|
||||
else if (cscLink.startsWith("file://")) {
|
||||
file = cscLink.substring("file://".length);
|
||||
}
|
||||
else if (cscLink.startsWith("~/")) {
|
||||
file = path.join(os_1.homedir(), cscLink.substring("~/".length));
|
||||
}
|
||||
else if (cscLink.startsWith("https://")) {
|
||||
if (cscLink.startsWith("https://")) {
|
||||
const tempFile = await tmpDir.getTempFile({ suffix: ".p12" });
|
||||
await binDownload_1.download(cscLink, tempFile);
|
||||
await (0, binDownload_1.download)(cscLink, tempFile);
|
||||
return tempFile;
|
||||
}
|
||||
else {
|
||||
const mimeType = (_a = /data:.*;base64,/.exec(cscLink)) === null || _a === void 0 ? void 0 : _a[0];
|
||||
if (mimeType || cscLink.length > 2048 || cscLink.endsWith("=")) {
|
||||
const tempFile = await tmpDir.getTempFile({ suffix: ".p12" });
|
||||
await fs_extra_1.outputFile(tempFile, Buffer.from(cscLink.substring((_b = mimeType === null || mimeType === void 0 ? void 0 : mimeType.length) !== null && _b !== void 0 ? _b : 0), "base64"));
|
||||
return tempFile;
|
||||
}
|
||||
file = cscLink;
|
||||
const decoded = (0, builder_util_1.decodeCscLinkBase64)(cscLink);
|
||||
if (decoded) {
|
||||
const tempFile = await tmpDir.getTempFile({ suffix: ".p12" });
|
||||
await (0, fs_extra_1.outputFile)(tempFile, decoded);
|
||||
return tempFile;
|
||||
}
|
||||
file = path.resolve(currentDir, file);
|
||||
const stat = await fs_1.statOrNull(file);
|
||||
const file = (0, builder_util_1.resolveCscLinkPath)(cscLink, currentDir);
|
||||
const stat = await (0, builder_util_1.statOrNull)(file);
|
||||
if (stat == null) {
|
||||
throw new builder_util_1.InvalidConfigurationError(`${file} doesn't exist`);
|
||||
}
|
||||
|
|
@ -47,5 +30,4 @@ async function importCertificate(cscLink, tmpDir, currentDir) {
|
|||
return file;
|
||||
}
|
||||
}
|
||||
exports.importCertificate = importCertificate;
|
||||
//# sourceMappingURL=codesign.js.map
|
||||
2
electron/node_modules/app-builder-lib/out/codeSign/codesign.js.map
generated
vendored
2
electron/node_modules/app-builder-lib/out/codeSign/codesign.js.map
generated
vendored
|
|
@ -1 +1 @@
|
|||
{"version":3,"file":"codesign.js","sourceRoot":"","sources":["../../src/codeSign/codesign.ts"],"names":[],"mappings":";;;AAAA,uCAAqC;AACrC,2BAA4B;AAC5B,6BAA4B;AAE5B,+CAAwD;AACxD,4CAAgD;AAChD,gDAAyC;AAEzC,eAAe;AACR,KAAK,UAAU,iBAAiB,CAAC,OAAe,EAAE,MAAc,EAAE,UAAkB;;IACzF,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAA;IAExB,IAAI,IAAI,GAAkB,IAAI,CAAA;IAC9B,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE;QACpG,IAAI,GAAG,OAAO,CAAA;KACf;SAAM,IAAI,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE;QACxC,IAAI,GAAG,OAAO,CAAC,SAAS,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;KAC3C;SAAM,IAAI,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE;QACnC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,YAAO,EAAE,EAAE,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAA;KAC5D;SAAM,IAAI,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE;QACzC,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;QAC7D,MAAM,sBAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAA;QACjC,OAAO,QAAQ,CAAA;KAChB;SAAM;QACL,MAAM,QAAQ,GAAG,MAAA,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,0CAAG,CAAC,CAAC,CAAA;QACrD,IAAI,QAAQ,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;YAC9D,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;YAC7D,MAAM,qBAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,MAAA,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,MAAM,mCAAI,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAA;YAC3F,OAAO,QAAQ,CAAA;SAChB;QACD,IAAI,GAAG,OAAO,CAAA;KACf;IAED,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,IAAI,CAAC,CAAA;IACrC,MAAM,IAAI,GAAG,MAAM,eAAU,CAAC,IAAI,CAAC,CAAA;IACnC,IAAI,IAAI,IAAI,IAAI,EAAE;QAChB,MAAM,IAAI,wCAAyB,CAAC,GAAG,IAAI,gBAAgB,CAAC,CAAA;KAC7D;SAAM,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE;QACzB,MAAM,IAAI,wCAAyB,CAAC,GAAG,IAAI,aAAa,CAAC,CAAA;KAC1D;SAAM;QACL,OAAO,IAAI,CAAA;KACZ;AACH,CAAC;AAjCD,8CAiCC","sourcesContent":["import { outputFile } from \"fs-extra\"\nimport { homedir } from \"os\"\nimport * as path from \"path\"\nimport { TmpDir } from \"temp-file\"\nimport { InvalidConfigurationError } from \"builder-util\"\nimport { statOrNull } from \"builder-util/out/fs\"\nimport { download } from \"../binDownload\"\n\n/** @private */\nexport async function importCertificate(cscLink: string, tmpDir: TmpDir, currentDir: string): Promise<string> {\n cscLink = cscLink.trim()\n\n let file: string | null = null\n if ((cscLink.length > 3 && cscLink[1] === \":\") || cscLink.startsWith(\"/\") || cscLink.startsWith(\".\")) {\n file = cscLink\n } else if (cscLink.startsWith(\"file://\")) {\n file = cscLink.substring(\"file://\".length)\n } else if (cscLink.startsWith(\"~/\")) {\n file = path.join(homedir(), cscLink.substring(\"~/\".length))\n } else if (cscLink.startsWith(\"https://\")) {\n const tempFile = await tmpDir.getTempFile({ suffix: \".p12\" })\n await download(cscLink, tempFile)\n return tempFile\n } else {\n const mimeType = /data:.*;base64,/.exec(cscLink)?.[0]\n if (mimeType || cscLink.length > 2048 || cscLink.endsWith(\"=\")) {\n const tempFile = await tmpDir.getTempFile({ suffix: \".p12\" })\n await outputFile(tempFile, Buffer.from(cscLink.substring(mimeType?.length ?? 0), \"base64\"))\n return tempFile\n }\n file = cscLink\n }\n\n file = path.resolve(currentDir, file)\n const stat = await statOrNull(file)\n if (stat == null) {\n throw new InvalidConfigurationError(`${file} doesn't exist`)\n } else if (!stat.isFile()) {\n throw new InvalidConfigurationError(`${file} not a file`)\n } else {\n return file\n }\n}\n"]}
|
||||
{"version":3,"file":"codesign.js","sourceRoot":"","sources":["../../src/codeSign/codesign.ts"],"names":[],"mappings":";;AAMA,8CAyBC;AA/BD,+CAA6G;AAC7G,uCAAqC;AAErC,gDAAyC;AAEzC,eAAe;AACR,KAAK,UAAU,iBAAiB,CAAC,OAAe,EAAE,MAAc,EAAE,UAAkB;IACzF,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAA;IAExB,IAAI,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QACnC,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;QAC7D,MAAM,IAAA,sBAAQ,EAAC,OAAO,EAAE,QAAQ,CAAC,CAAA;QACjC,OAAO,QAAQ,CAAA;IACjB,CAAC;IAED,MAAM,OAAO,GAAG,IAAA,kCAAmB,EAAC,OAAO,CAAC,CAAA;IAC5C,IAAI,OAAO,EAAE,CAAC;QACZ,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;QAC7D,MAAM,IAAA,qBAAU,EAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;QACnC,OAAO,QAAQ,CAAA;IACjB,CAAC;IAED,MAAM,IAAI,GAAG,IAAA,iCAAkB,EAAC,OAAO,EAAE,UAAU,CAAC,CAAA;IACpD,MAAM,IAAI,GAAG,MAAM,IAAA,yBAAU,EAAC,IAAI,CAAC,CAAA;IACnC,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC;QACjB,MAAM,IAAI,wCAAyB,CAAC,GAAG,IAAI,gBAAgB,CAAC,CAAA;IAC9D,CAAC;SAAM,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;QAC1B,MAAM,IAAI,wCAAyB,CAAC,GAAG,IAAI,aAAa,CAAC,CAAA;IAC3D,CAAC;SAAM,CAAC;QACN,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC","sourcesContent":["import { decodeCscLinkBase64, InvalidConfigurationError, resolveCscLinkPath, statOrNull } from \"builder-util\"\nimport { outputFile } from \"fs-extra\"\nimport { TmpDir } from \"temp-file\"\nimport { download } from \"../binDownload\"\n\n/** @private */\nexport async function importCertificate(cscLink: string, tmpDir: TmpDir, currentDir: string): Promise<string> {\n cscLink = cscLink.trim()\n\n if (cscLink.startsWith(\"https://\")) {\n const tempFile = await tmpDir.getTempFile({ suffix: \".p12\" })\n await download(cscLink, tempFile)\n return tempFile\n }\n\n const decoded = decodeCscLinkBase64(cscLink)\n if (decoded) {\n const tempFile = await tmpDir.getTempFile({ suffix: \".p12\" })\n await outputFile(tempFile, decoded)\n return tempFile\n }\n\n const file = resolveCscLinkPath(cscLink, currentDir)\n const stat = await statOrNull(file)\n if (stat == null) {\n throw new InvalidConfigurationError(`${file} doesn't exist`)\n } else if (!stat.isFile()) {\n throw new InvalidConfigurationError(`${file} not a file`)\n } else {\n return file\n }\n}\n"]}
|
||||
15
electron/node_modules/app-builder-lib/out/codeSign/macCodeSign.d.ts
generated
vendored
15
electron/node_modules/app-builder-lib/out/codeSign/macCodeSign.d.ts
generated
vendored
|
|
@ -1,11 +1,13 @@
|
|||
import { TmpDir } from "builder-util/out/util";
|
||||
import type { SignOptions } from "@electron/osx-sign/dist/cjs/types";
|
||||
import { TmpDir } from "builder-util";
|
||||
import { Nullish } from "builder-util-runtime";
|
||||
export declare const appleCertificatePrefixes: string[];
|
||||
export declare type CertType = "Developer ID Application" | "Developer ID Installer" | "3rd Party Mac Developer Application" | "3rd Party Mac Developer Installer" | "Mac Developer" | "Apple Development" | "Apple Distribution";
|
||||
export type CertType = "Developer ID Application" | "Developer ID Installer" | "3rd Party Mac Developer Application" | "3rd Party Mac Developer Installer" | "Mac Developer" | "Apple Development" | "Apple Distribution";
|
||||
export interface CodeSigningInfo {
|
||||
keychainFile?: string | null;
|
||||
}
|
||||
export declare function isSignAllowed(isPrintWarn?: boolean): boolean;
|
||||
export declare function reportError(isMas: boolean, certificateTypes: CertType[], qualifier: string | null | undefined, keychainFile: string | null | undefined, isForceCodeSigning: boolean): Promise<void>;
|
||||
export declare function reportError(isMas: boolean, certificateTypes: CertType[], qualifier: string | Nullish, keychainFile: string | Nullish, isForceCodeSigning: boolean): Promise<void>;
|
||||
export interface CreateKeychainOptions {
|
||||
tmpDir: TmpDir;
|
||||
cscLink: string;
|
||||
|
|
@ -16,12 +18,11 @@ export interface CreateKeychainOptions {
|
|||
}
|
||||
export declare function removeKeychain(keychainFile: string, printWarn?: boolean): Promise<any>;
|
||||
export declare function createKeychain({ tmpDir, cscLink, cscKeyPassword, cscILink, cscIKeyPassword, currentDir }: CreateKeychainOptions): Promise<CodeSigningInfo>;
|
||||
/** @private */
|
||||
export declare function sign(path: string, name: string, keychain: string): Promise<any>;
|
||||
export declare function sign(opts: SignOptions): Promise<void>;
|
||||
export declare let findIdentityRawResult: Promise<Array<string>> | null;
|
||||
export declare class Identity {
|
||||
readonly name: string;
|
||||
readonly hash: string;
|
||||
constructor(name: string, hash: string);
|
||||
readonly hash?: string;
|
||||
constructor(name: string, hash?: string);
|
||||
}
|
||||
export declare function findIdentity(certType: CertType, qualifier?: string | null, keychain?: string | null): Promise<Identity | null>;
|
||||
|
|
|
|||
120
electron/node_modules/app-builder-lib/out/codeSign/macCodeSign.js
generated
vendored
120
electron/node_modules/app-builder-lib/out/codeSign/macCodeSign.js
generated
vendored
|
|
@ -1,10 +1,14 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.findIdentity = exports.findIdentityRawResult = exports.sign = exports.createKeychain = exports.removeKeychain = exports.reportError = exports.isSignAllowed = exports.appleCertificatePrefixes = void 0;
|
||||
const bluebird_lst_1 = require("bluebird-lst");
|
||||
const util_1 = require("builder-util/out/util");
|
||||
const fs_1 = require("builder-util/out/fs");
|
||||
const log_1 = require("builder-util/out/log");
|
||||
exports.findIdentityRawResult = exports.appleCertificatePrefixes = void 0;
|
||||
exports.isSignAllowed = isSignAllowed;
|
||||
exports.reportError = reportError;
|
||||
exports.removeKeychain = removeKeychain;
|
||||
exports.createKeychain = createKeychain;
|
||||
exports.sign = sign;
|
||||
exports.findIdentity = findIdentity;
|
||||
const builder_util_1 = require("builder-util");
|
||||
const dynamicImport_1 = require("../util/dynamicImport");
|
||||
const crypto_1 = require("crypto");
|
||||
const promises_1 = require("fs/promises");
|
||||
const lazy_val_1 = require("lazy-val");
|
||||
|
|
@ -17,38 +21,37 @@ exports.appleCertificatePrefixes = ["Developer ID Application:", "Developer ID I
|
|||
function isSignAllowed(isPrintWarn = true) {
|
||||
if (process.platform !== "darwin") {
|
||||
if (isPrintWarn) {
|
||||
util_1.log.warn({ reason: "supported only on macOS" }, "skipped macOS application code signing");
|
||||
builder_util_1.log.warn({ reason: "supported only on macOS" }, "skipped macOS application code signing");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
const buildForPrWarning = "There are serious security concerns with CSC_FOR_PULL_REQUEST=true (see the CircleCI documentation (https://circleci.com/docs/1.0/fork-pr-builds/) for details)" +
|
||||
"\nIf you have SSH keys, sensitive env vars or AWS credentials stored in your project settings and untrusted forks can make pull requests against your repo, then this option isn't for you.";
|
||||
if (util_1.isPullRequest()) {
|
||||
if (util_1.isEnvTrue(process.env.CSC_FOR_PULL_REQUEST)) {
|
||||
if ((0, builder_util_1.isPullRequest)()) {
|
||||
const buildForPrWarning = "There are serious security concerns with CSC_FOR_PULL_REQUEST=true (see the CircleCI documentation (https://circleci.com/docs/1.0/fork-pr-builds/) for details)" +
|
||||
"\nIf you have SSH keys, sensitive env vars or AWS credentials stored in your project settings and untrusted forks can make pull requests against your repo, then this option isn't for you.";
|
||||
if ((0, builder_util_1.isEnvTrue)(process.env.CSC_FOR_PULL_REQUEST)) {
|
||||
if (isPrintWarn) {
|
||||
util_1.log.warn(buildForPrWarning);
|
||||
builder_util_1.log.warn(buildForPrWarning);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (isPrintWarn) {
|
||||
// https://github.com/electron-userland/electron-builder/issues/1524
|
||||
util_1.log.warn("Current build is a part of pull request, code signing will be skipped." + "\nSet env CSC_FOR_PULL_REQUEST to true to force code signing." + `\n${buildForPrWarning}`);
|
||||
builder_util_1.log.warn("Current build is a part of pull request, code signing will be skipped." + "\nSet env CSC_FOR_PULL_REQUEST to true to force code signing." + `\n${buildForPrWarning}`);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
exports.isSignAllowed = isSignAllowed;
|
||||
async function reportError(isMas, certificateTypes, qualifier, keychainFile, isForceCodeSigning) {
|
||||
const logFields = {};
|
||||
if (qualifier == null) {
|
||||
logFields.reason = "";
|
||||
if (flags_1.isAutoDiscoveryCodeSignIdentity()) {
|
||||
if ((0, flags_1.isAutoDiscoveryCodeSignIdentity)()) {
|
||||
logFields.reason += `cannot find valid "${certificateTypes.join(", ")}" identity${isMas ? "" : ` or custom non-Apple code signing certificate, it could cause some undefined behaviour, e.g. macOS localized description not visible`}`;
|
||||
}
|
||||
logFields.reason += ", see https://electron.build/code-signing";
|
||||
if (!flags_1.isAutoDiscoveryCodeSignIdentity()) {
|
||||
if (!(0, flags_1.isAutoDiscoveryCodeSignIdentity)()) {
|
||||
logFields.CSC_IDENTITY_AUTO_DISCOVERY = false;
|
||||
}
|
||||
}
|
||||
|
|
@ -60,21 +63,21 @@ async function reportError(isMas, certificateTypes, qualifier, keychainFile, isF
|
|||
if (keychainFile != null) {
|
||||
args.push(keychainFile);
|
||||
}
|
||||
if (qualifier != null || flags_1.isAutoDiscoveryCodeSignIdentity()) {
|
||||
logFields.allIdentities = (await util_1.exec("security", args))
|
||||
if (qualifier != null || (0, flags_1.isAutoDiscoveryCodeSignIdentity)()) {
|
||||
logFields.allIdentities = (await (0, builder_util_1.exec)("/usr/bin/security", args))
|
||||
.trim()
|
||||
.split("\n")
|
||||
.filter(it => !(it.includes("Policy: X.509 Basic") || it.includes("Matching identities")))
|
||||
.join("\n");
|
||||
}
|
||||
const skipMessage = "skipped macOS application code signing";
|
||||
if (isMas || isForceCodeSigning) {
|
||||
throw new Error(log_1.Logger.createMessage("skipped macOS application code signing", logFields, "error", it => it));
|
||||
throw new Error(builder_util_1.Logger.createMessage(skipMessage, logFields, "error", it => it));
|
||||
}
|
||||
else {
|
||||
util_1.log.warn(logFields, "skipped macOS application code signing");
|
||||
builder_util_1.log.warn(logFields, skipMessage);
|
||||
}
|
||||
}
|
||||
exports.reportError = reportError;
|
||||
// "Note that filename will not be searched to resolve the signing identity's certificate chain unless it is also on the user's keychain search list."
|
||||
// but "security list-keychains" doesn't support add - we should 1) get current list 2) set new list - it is very bad http://stackoverflow.com/questions/10538942/add-a-keychain-to-search-list
|
||||
// "overly complicated and introduces a race condition."
|
||||
|
|
@ -82,23 +85,23 @@ exports.reportError = reportError;
|
|||
const bundledCertKeychainAdded = new lazy_val_1.Lazy(async () => {
|
||||
// copy to temp and then atomic rename to final path
|
||||
const cacheDir = getCacheDirectory();
|
||||
const tmpKeychainPath = path.join(cacheDir, temp_file_1.getTempName("electron-builder-root-certs"));
|
||||
const tmpKeychainPath = path.join(cacheDir, (0, temp_file_1.getTempName)("electron-builder-root-certs"));
|
||||
const keychainPath = path.join(cacheDir, "electron-builder-root-certs.keychain");
|
||||
const results = await Promise.all([
|
||||
listUserKeychains(),
|
||||
fs_1.copyFile(path.join(__dirname, "..", "..", "certs", "root_certs.keychain"), tmpKeychainPath).then(() => promises_1.rename(tmpKeychainPath, keychainPath)),
|
||||
(0, builder_util_1.copyFile)(path.join(__dirname, "..", "..", "certs", "root_certs.keychain"), tmpKeychainPath).then(() => (0, promises_1.rename)(tmpKeychainPath, keychainPath)),
|
||||
]);
|
||||
const list = results[0];
|
||||
if (!list.includes(keychainPath)) {
|
||||
await util_1.exec("security", ["list-keychains", "-d", "user", "-s", keychainPath].concat(list));
|
||||
await (0, builder_util_1.exec)("/usr/bin/security", ["list-keychains", "-d", "user", "-s", keychainPath].concat(list));
|
||||
}
|
||||
});
|
||||
function getCacheDirectory() {
|
||||
const env = process.env.ELECTRON_BUILDER_CACHE;
|
||||
return util_1.isEmptyOrSpaces(env) ? path.join(os_1.homedir(), "Library", "Caches", "electron-builder") : path.resolve(env);
|
||||
return (0, builder_util_1.isEmptyOrSpaces)(env) ? path.join((0, os_1.homedir)(), "Library", "Caches", "electron-builder") : path.resolve(env);
|
||||
}
|
||||
function listUserKeychains() {
|
||||
return util_1.exec("security", ["list-keychains", "-d", "user"]).then(it => it
|
||||
return (0, builder_util_1.exec)("/usr/bin/security", ["list-keychains", "-d", "user"]).then(it => it
|
||||
.split("\n")
|
||||
.map(it => {
|
||||
const r = it.trim();
|
||||
|
|
@ -107,14 +110,13 @@ function listUserKeychains() {
|
|||
.filter(it => it.length > 0));
|
||||
}
|
||||
function removeKeychain(keychainFile, printWarn = true) {
|
||||
return util_1.exec("security", ["delete-keychain", keychainFile]).catch(e => {
|
||||
return (0, builder_util_1.exec)("/usr/bin/security", ["delete-keychain", keychainFile]).catch((e) => {
|
||||
if (printWarn) {
|
||||
util_1.log.warn({ file: keychainFile, error: e.stack || e }, "cannot delete keychain");
|
||||
builder_util_1.log.warn({ file: keychainFile, error: e.stack || e }, "cannot delete keychain");
|
||||
}
|
||||
return fs_1.unlinkIfExists(keychainFile);
|
||||
return (0, builder_util_1.unlinkIfExists)(keychainFile);
|
||||
});
|
||||
}
|
||||
exports.removeKeychain = removeKeychain;
|
||||
async function createKeychain({ tmpDir, cscLink, cscKeyPassword, cscILink, cscIKeyPassword, currentDir }) {
|
||||
// travis has correct AppleWWDRCA cert
|
||||
if (process.env.TRAVIS !== "true") {
|
||||
|
|
@ -122,9 +124,8 @@ async function createKeychain({ tmpDir, cscLink, cscKeyPassword, cscILink, cscIK
|
|||
}
|
||||
// https://github.com/electron-userland/electron-builder/issues/3685
|
||||
// use constant file
|
||||
const keychainFile = path.join(process.env.APP_BUILDER_TMP_DIR || os_1.tmpdir(), `${crypto_1.createHash("sha256").update(currentDir).update("app-builder").digest("hex")}.keychain`);
|
||||
const keychainFile = path.join(process.env.APP_BUILDER_TMP_DIR || (0, os_1.tmpdir)(), `${(0, crypto_1.createHash)("sha256").update(currentDir).update("app-builder").digest("hex")}.keychain`);
|
||||
// noinspection JSUnusedLocalSymbols
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
await removeKeychain(keychainFile, false).catch(_ => {
|
||||
/* ignore*/
|
||||
});
|
||||
|
|
@ -133,7 +134,7 @@ async function createKeychain({ tmpDir, cscLink, cscKeyPassword, cscILink, cscIK
|
|||
certLinks.push(cscILink);
|
||||
}
|
||||
const certPaths = new Array(certLinks.length);
|
||||
const keychainPassword = crypto_1.randomBytes(32).toString("base64");
|
||||
const keychainPassword = (0, crypto_1.randomBytes)(32).toString("base64");
|
||||
const securityCommands = [
|
||||
["create-keychain", "-p", keychainPassword, keychainFile],
|
||||
["unlock-keychain", "-p", keychainPassword, keychainFile],
|
||||
|
|
@ -147,33 +148,37 @@ async function createKeychain({ tmpDir, cscLink, cscKeyPassword, cscILink, cscIK
|
|||
}
|
||||
await Promise.all([
|
||||
// we do not clear downloaded files - will be removed on tmpDir cleanup automatically. not a security issue since in any case data is available as env variables and protected by password.
|
||||
bluebird_lst_1.default.map(certLinks, (link, i) => codesign_1.importCertificate(link, tmpDir, currentDir).then(it => (certPaths[i] = it))),
|
||||
bluebird_lst_1.default.mapSeries(securityCommands, it => util_1.exec("security", it)),
|
||||
...certLinks.map((link, i) => (0, codesign_1.importCertificate)(link, tmpDir, currentDir).then(it => (certPaths[i] = it))),
|
||||
// queue each security command
|
||||
securityCommands.reduce((promise, cmd) => promise.then(() => (0, builder_util_1.exec)("/usr/bin/security", cmd)), new Promise(resolve => resolve(null))),
|
||||
]);
|
||||
return await importCerts(keychainFile, certPaths, [cscKeyPassword, cscIKeyPassword].filter(it => it != null));
|
||||
const cscPasswords = [cscKeyPassword];
|
||||
if (cscIKeyPassword != null) {
|
||||
cscPasswords.push(cscIKeyPassword);
|
||||
}
|
||||
return await importCerts(keychainFile, certPaths, cscPasswords);
|
||||
}
|
||||
exports.createKeychain = createKeychain;
|
||||
async function importCerts(keychainFile, paths, keyPasswords) {
|
||||
var _a;
|
||||
for (let i = 0; i < paths.length; i++) {
|
||||
const password = keyPasswords[i];
|
||||
await util_1.exec("security", ["import", paths[i], "-k", keychainFile, "-T", "/usr/bin/codesign", "-T", "/usr/bin/productbuild", "-P", password]);
|
||||
const password = (_a = keyPasswords[i]) !== null && _a !== void 0 ? _a : "";
|
||||
await (0, builder_util_1.exec)("/usr/bin/security", ["import", paths[i], "-k", keychainFile, "-T", "/usr/bin/codesign", "-T", "/usr/bin/productbuild", "-P", password]);
|
||||
// https://stackoverflow.com/questions/39868578/security-codesign-in-sierra-keychain-ignores-access-control-settings-and-ui-p
|
||||
// https://github.com/electron-userland/electron-packager/issues/701#issuecomment-322315996
|
||||
await util_1.exec("security", ["set-key-partition-list", "-S", "apple-tool:,apple:", "-s", "-k", password, keychainFile]);
|
||||
await (0, builder_util_1.exec)("/usr/bin/security", ["set-key-partition-list", "-S", "apple-tool:,apple:", "-s", "-k", password, keychainFile]);
|
||||
}
|
||||
return {
|
||||
keychainFile,
|
||||
};
|
||||
}
|
||||
/** @private */
|
||||
function sign(path, name, keychain) {
|
||||
const args = ["--deep", "--force", "--sign", name, path];
|
||||
if (keychain != null) {
|
||||
args.push("--keychain", keychain);
|
||||
}
|
||||
return util_1.exec("codesign", args);
|
||||
async function sign(opts) {
|
||||
const { signAsync } = await (0, dynamicImport_1.dynamicImport)("@electron/osx-sign");
|
||||
return (0, builder_util_1.retry)(() => signAsync(opts), {
|
||||
retries: 3,
|
||||
interval: 5000,
|
||||
backoff: 5000,
|
||||
});
|
||||
}
|
||||
exports.sign = sign;
|
||||
exports.findIdentityRawResult = null;
|
||||
async function getValidIdentities(keychain) {
|
||||
function addKeychain(args) {
|
||||
|
|
@ -187,7 +192,7 @@ async function getValidIdentities(keychain) {
|
|||
// https://github.com/electron-userland/electron-builder/issues/481
|
||||
// https://github.com/electron-userland/electron-builder/issues/535
|
||||
result = Promise.all([
|
||||
util_1.exec("security", addKeychain(["find-identity", "-v"])).then(it => it
|
||||
(0, builder_util_1.exec)("/usr/bin/security", addKeychain(["find-identity", "-v"])).then(it => it
|
||||
.trim()
|
||||
.split("\n")
|
||||
.filter(it => {
|
||||
|
|
@ -198,7 +203,7 @@ async function getValidIdentities(keychain) {
|
|||
}
|
||||
return false;
|
||||
})),
|
||||
util_1.exec("security", addKeychain(["find-identity", "-v", "-p", "codesigning"])).then(it => it.trim().split("\n")),
|
||||
(0, builder_util_1.exec)("/usr/bin/security", addKeychain(["find-identity", "-v", "-p", "codesigning"])).then(it => it.trim().split("\n")),
|
||||
]).then(it => {
|
||||
const array = it[0]
|
||||
.concat(it[1])
|
||||
|
|
@ -223,7 +228,7 @@ async function _findIdentity(type, qualifier, keychain) {
|
|||
continue;
|
||||
}
|
||||
if (line.includes(namePrefix)) {
|
||||
return parseIdentity(line);
|
||||
return await parseIdentity(line);
|
||||
}
|
||||
}
|
||||
if (type === "Developer ID Application") {
|
||||
|
|
@ -241,22 +246,22 @@ async function _findIdentity(type, qualifier, keychain) {
|
|||
continue l;
|
||||
}
|
||||
}
|
||||
return parseIdentity(line);
|
||||
return await parseIdentity(line);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
const _Identity = require("electron-osx-sign/util-identities").Identity;
|
||||
function parseIdentity(line) {
|
||||
async function parseIdentity(line) {
|
||||
const firstQuoteIndex = line.indexOf('"');
|
||||
const name = line.substring(firstQuoteIndex + 1, line.lastIndexOf('"'));
|
||||
const hash = line.substring(0, firstQuoteIndex - 1);
|
||||
return new _Identity(name, hash);
|
||||
const { Identity: IdentityClass } = await (0, dynamicImport_1.dynamicImport)("@electron/osx-sign/dist/cjs/util-identities");
|
||||
return new IdentityClass(name, hash);
|
||||
}
|
||||
function findIdentity(certType, qualifier, keychain) {
|
||||
let identity = qualifier || process.env.CSC_NAME;
|
||||
if (util_1.isEmptyOrSpaces(identity)) {
|
||||
if (flags_1.isAutoDiscoveryCodeSignIdentity()) {
|
||||
if ((0, builder_util_1.isEmptyOrSpaces)(identity)) {
|
||||
if ((0, flags_1.isAutoDiscoveryCodeSignIdentity)()) {
|
||||
return _findIdentity(certType, null, keychain);
|
||||
}
|
||||
else {
|
||||
|
|
@ -271,10 +276,9 @@ function findIdentity(certType, qualifier, keychain) {
|
|||
return _findIdentity(certType, identity, keychain);
|
||||
}
|
||||
}
|
||||
exports.findIdentity = findIdentity;
|
||||
function checkPrefix(name, prefix) {
|
||||
if (name.startsWith(prefix)) {
|
||||
throw new util_1.InvalidConfigurationError(`Please remove prefix "${prefix}" from the specified name — appropriate certificate will be chosen automatically`);
|
||||
throw new builder_util_1.InvalidConfigurationError(`Please remove prefix "${prefix}" from the specified name — appropriate certificate will be chosen automatically`);
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=macCodeSign.js.map
|
||||
2
electron/node_modules/app-builder-lib/out/codeSign/macCodeSign.js.map
generated
vendored
2
electron/node_modules/app-builder-lib/out/codeSign/macCodeSign.js.map
generated
vendored
File diff suppressed because one or more lines are too long
13
electron/node_modules/app-builder-lib/out/codeSign/signManager.d.ts
generated
vendored
Normal file
13
electron/node_modules/app-builder-lib/out/codeSign/signManager.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
import { MemoLazy, Nullish } from "builder-util-runtime";
|
||||
import { Lazy } from "lazy-val";
|
||||
import { Target } from "../core";
|
||||
import { WindowsConfiguration } from "../options/winOptions";
|
||||
import { WindowsSignOptions } from "./windowsCodeSign";
|
||||
import { CertificateFromStoreInfo, FileCodeSigningInfo } from "./windowsSignToolManager";
|
||||
export interface SignManager {
|
||||
readonly computedPublisherName: Lazy<Array<string> | null>;
|
||||
readonly cscInfo: MemoLazy<WindowsConfiguration, FileCodeSigningInfo | CertificateFromStoreInfo | null>;
|
||||
computePublisherName(target: Target, publisherName: string | Nullish): Promise<string>;
|
||||
initialize(): Promise<void>;
|
||||
signFile(options: WindowsSignOptions): Promise<boolean>;
|
||||
}
|
||||
3
electron/node_modules/app-builder-lib/out/codeSign/signManager.js
generated
vendored
Normal file
3
electron/node_modules/app-builder-lib/out/codeSign/signManager.js
generated
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
//# sourceMappingURL=signManager.js.map
|
||||
1
electron/node_modules/app-builder-lib/out/codeSign/signManager.js.map
generated
vendored
Normal file
1
electron/node_modules/app-builder-lib/out/codeSign/signManager.js.map
generated
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"signManager.js","sourceRoot":"","sources":["../../src/codeSign/signManager.ts"],"names":[],"mappings":"","sourcesContent":["import { MemoLazy, Nullish } from \"builder-util-runtime\"\nimport { Lazy } from \"lazy-val\"\nimport { Target } from \"../core\"\nimport { WindowsConfiguration } from \"../options/winOptions\"\nimport { WindowsSignOptions } from \"./windowsCodeSign\"\nimport { CertificateFromStoreInfo, FileCodeSigningInfo } from \"./windowsSignToolManager\"\n\nexport interface SignManager {\n readonly computedPublisherName: Lazy<Array<string> | null>\n readonly cscInfo: MemoLazy<WindowsConfiguration, FileCodeSigningInfo | CertificateFromStoreInfo | null>\n computePublisherName(target: Target, publisherName: string | Nullish): Promise<string>\n initialize(): Promise<void>\n signFile(options: WindowsSignOptions): Promise<boolean>\n}\n"]}
|
||||
33
electron/node_modules/app-builder-lib/out/codeSign/windowsCodeSign.d.ts
generated
vendored
33
electron/node_modules/app-builder-lib/out/codeSign/windowsCodeSign.d.ts
generated
vendored
|
|
@ -1,38 +1,7 @@
|
|||
import { WindowsConfiguration } from "../options/winOptions";
|
||||
import { VmManager } from "../vm/vm";
|
||||
import { WinPackager } from "../winPackager";
|
||||
export declare function getSignVendorPath(): Promise<string>;
|
||||
export declare type CustomWindowsSign = (configuration: CustomWindowsSignTaskConfiguration, packager?: WinPackager) => Promise<any>;
|
||||
export interface WindowsSignOptions {
|
||||
readonly path: string;
|
||||
readonly name?: string | null;
|
||||
readonly cscInfo?: FileCodeSigningInfo | CertificateFromStoreInfo | null;
|
||||
readonly site?: string | null;
|
||||
readonly options: WindowsConfiguration;
|
||||
}
|
||||
export interface WindowsSignTaskConfiguration extends WindowsSignOptions {
|
||||
resultOutputPath?: string;
|
||||
hash: string;
|
||||
isNest: boolean;
|
||||
}
|
||||
export interface CustomWindowsSignTaskConfiguration extends WindowsSignTaskConfiguration {
|
||||
computeSignToolArgs(isWin: boolean): Array<string>;
|
||||
}
|
||||
export declare function sign(options: WindowsSignOptions, packager: WinPackager): Promise<void>;
|
||||
export interface FileCodeSigningInfo {
|
||||
readonly file: string;
|
||||
readonly password: string | null;
|
||||
}
|
||||
export declare function getCertInfo(file: string, password: string): Promise<CertificateInfo>;
|
||||
export interface CertificateInfo {
|
||||
readonly commonName: string;
|
||||
readonly bloodyMicrosoftSubjectDn: string;
|
||||
}
|
||||
export interface CertificateFromStoreInfo {
|
||||
thumbprint: string;
|
||||
subject: string;
|
||||
store: string;
|
||||
isLocalMachineStore: boolean;
|
||||
}
|
||||
export declare function getCertificateFromStoreInfo(options: WindowsConfiguration, vm: VmManager): Promise<CertificateFromStoreInfo>;
|
||||
export declare function doSign(configuration: CustomWindowsSignTaskConfiguration, packager: WinPackager): Promise<void>;
|
||||
export declare function signWindows(options: WindowsSignOptions, packager: WinPackager): Promise<boolean>;
|
||||
|
|
|
|||
273
electron/node_modules/app-builder-lib/out/codeSign/windowsCodeSign.js
generated
vendored
273
electron/node_modules/app-builder-lib/out/codeSign/windowsCodeSign.js
generated
vendored
|
|
@ -1,251 +1,38 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.isOldWin6 = exports.doSign = exports.getCertificateFromStoreInfo = exports.getCertInfo = exports.sign = exports.getSignVendorPath = void 0;
|
||||
const util_1 = require("builder-util/out/util");
|
||||
const binDownload_1 = require("../binDownload");
|
||||
const appBuilder_1 = require("../util/appBuilder");
|
||||
const bundledTool_1 = require("../util/bundledTool");
|
||||
const fs_extra_1 = require("fs-extra");
|
||||
const os = require("os");
|
||||
const path = require("path");
|
||||
const platformPackager_1 = require("../platformPackager");
|
||||
const flags_1 = require("../util/flags");
|
||||
const vm_1 = require("../vm/vm");
|
||||
function getSignVendorPath() {
|
||||
return binDownload_1.getBin("winCodeSign");
|
||||
}
|
||||
exports.getSignVendorPath = getSignVendorPath;
|
||||
async function sign(options, packager) {
|
||||
let hashes = options.options.signingHashAlgorithms;
|
||||
// msi does not support dual-signing
|
||||
if (options.path.endsWith(".msi")) {
|
||||
hashes = [hashes != null && !hashes.includes("sha1") ? "sha256" : "sha1"];
|
||||
}
|
||||
else if (options.path.endsWith(".appx")) {
|
||||
hashes = ["sha256"];
|
||||
}
|
||||
else if (hashes == null) {
|
||||
hashes = ["sha1", "sha256"];
|
||||
exports.signWindows = signWindows;
|
||||
const builder_util_1 = require("builder-util");
|
||||
async function signWindows(options, packager) {
|
||||
if (options.options.azureSignOptions) {
|
||||
if (options.options.signtoolOptions) {
|
||||
builder_util_1.log.warn(null, "ignoring signtool options, using Azure Trusted Signing; please only configure one");
|
||||
}
|
||||
builder_util_1.log.info({ path: builder_util_1.log.filePath(options.path) }, "signing with Azure Trusted Signing");
|
||||
}
|
||||
else {
|
||||
hashes = Array.isArray(hashes) ? hashes : [hashes];
|
||||
}
|
||||
const executor = platformPackager_1.resolveFunction(options.options.sign, "sign") || doSign;
|
||||
let isNest = false;
|
||||
for (const hash of hashes) {
|
||||
const taskConfiguration = { ...options, hash, isNest };
|
||||
await Promise.resolve(executor({
|
||||
...taskConfiguration,
|
||||
computeSignToolArgs: isWin => computeSignToolArgs(taskConfiguration, isWin),
|
||||
}, packager));
|
||||
isNest = true;
|
||||
if (taskConfiguration.resultOutputPath != null) {
|
||||
await fs_extra_1.rename(taskConfiguration.resultOutputPath, options.path);
|
||||
}
|
||||
builder_util_1.log.info({ path: builder_util_1.log.filePath(options.path) }, "signing with signtool.exe");
|
||||
}
|
||||
const packageManager = await packager.signingManager.value;
|
||||
return signWithRetry(async () => packageManager.signFile(options));
|
||||
}
|
||||
exports.sign = sign;
|
||||
async function getCertInfo(file, password) {
|
||||
let result = null;
|
||||
const errorMessagePrefix = "Cannot extract publisher name from code signing certificate. As workaround, set win.publisherName. Error: ";
|
||||
try {
|
||||
result = await appBuilder_1.executeAppBuilderAsJson(["certificate-info", "--input", file, "--password", password]);
|
||||
}
|
||||
catch (e) {
|
||||
throw new Error(`${errorMessagePrefix}${e.stack || e}`);
|
||||
}
|
||||
if (result.error != null) {
|
||||
// noinspection ExceptionCaughtLocallyJS
|
||||
throw new util_1.InvalidConfigurationError(`${errorMessagePrefix}${result.error}`);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
exports.getCertInfo = getCertInfo;
|
||||
async function getCertificateFromStoreInfo(options, vm) {
|
||||
const certificateSubjectName = options.certificateSubjectName;
|
||||
const certificateSha1 = options.certificateSha1 ? options.certificateSha1.toUpperCase() : options.certificateSha1;
|
||||
// ExcludeProperty doesn't work, so, we cannot exclude RawData, it is ok
|
||||
// powershell can return object if the only item
|
||||
const rawResult = await vm.exec("powershell.exe", [
|
||||
"-NoProfile",
|
||||
"-NonInteractive",
|
||||
"-Command",
|
||||
"Get-ChildItem -Recurse Cert: -CodeSigningCert | Select-Object -Property Subject,PSParentPath,Thumbprint | ConvertTo-Json -Compress",
|
||||
]);
|
||||
const certList = rawResult.length === 0 ? [] : util_1.asArray(JSON.parse(rawResult));
|
||||
for (const certInfo of certList) {
|
||||
if ((certificateSubjectName != null && !certInfo.Subject.includes(certificateSubjectName)) ||
|
||||
(certificateSha1 != null && certInfo.Thumbprint.toUpperCase() !== certificateSha1)) {
|
||||
continue;
|
||||
}
|
||||
const parentPath = certInfo.PSParentPath;
|
||||
const store = parentPath.substring(parentPath.lastIndexOf("\\") + 1);
|
||||
util_1.log.debug({ store, PSParentPath: parentPath }, "auto-detect certificate store");
|
||||
// https://github.com/electron-userland/electron-builder/issues/1717
|
||||
const isLocalMachineStore = parentPath.includes("Certificate::LocalMachine");
|
||||
util_1.log.debug(null, "auto-detect using of LocalMachine store");
|
||||
return {
|
||||
thumbprint: certInfo.Thumbprint,
|
||||
subject: certInfo.Subject,
|
||||
store,
|
||||
isLocalMachineStore,
|
||||
};
|
||||
}
|
||||
throw new Error(`Cannot find certificate ${certificateSubjectName || certificateSha1}, all certs: ${rawResult}`);
|
||||
}
|
||||
exports.getCertificateFromStoreInfo = getCertificateFromStoreInfo;
|
||||
async function doSign(configuration, packager) {
|
||||
// https://github.com/electron-userland/electron-builder/pull/1944
|
||||
const timeout = parseInt(process.env.SIGNTOOL_TIMEOUT, 10) || 10 * 60 * 1000;
|
||||
// unify logic of signtool path location
|
||||
const toolInfo = await getToolPath();
|
||||
const tool = toolInfo.path;
|
||||
// decide runtime argument by cases
|
||||
let args;
|
||||
let env = process.env;
|
||||
let vm;
|
||||
if (configuration.path.endsWith(".appx") || !("file" in configuration.cscInfo) /* certificateSubjectName and other such options */) {
|
||||
vm = await packager.vm.value;
|
||||
args = computeSignToolArgs(configuration, true, vm);
|
||||
}
|
||||
else {
|
||||
vm = new vm_1.VmManager();
|
||||
args = configuration.computeSignToolArgs(process.platform === "win32");
|
||||
if (toolInfo.env != null) {
|
||||
env = toolInfo.env;
|
||||
}
|
||||
}
|
||||
try {
|
||||
await vm.exec(tool, args, { timeout, env });
|
||||
}
|
||||
catch (e) {
|
||||
if (e.message.includes("The file is being used by another process") || e.message.includes("The specified timestamp server either could not be reached")) {
|
||||
util_1.log.warn(`First attempt to code sign failed, another attempt will be made in 15 seconds: ${e.message}`);
|
||||
await new Promise((resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
vm.exec(tool, args, { timeout, env }).then(resolve).catch(reject);
|
||||
}, 15000);
|
||||
});
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
exports.doSign = doSign;
|
||||
// on windows be aware of http://stackoverflow.com/a/32640183/1910191
|
||||
function computeSignToolArgs(options, isWin, vm = new vm_1.VmManager()) {
|
||||
const inputFile = vm.toVmFile(options.path);
|
||||
const outputPath = isWin ? inputFile : getOutputPath(inputFile, options.hash);
|
||||
if (!isWin) {
|
||||
options.resultOutputPath = outputPath;
|
||||
}
|
||||
const args = isWin ? ["sign"] : ["-in", inputFile, "-out", outputPath];
|
||||
if (process.env.ELECTRON_BUILDER_OFFLINE !== "true") {
|
||||
const timestampingServiceUrl = options.options.timeStampServer || "http://timestamp.digicert.com";
|
||||
if (isWin) {
|
||||
args.push(options.isNest || options.hash === "sha256" ? "/tr" : "/t", options.isNest || options.hash === "sha256" ? options.options.rfc3161TimeStampServer || "http://timestamp.digicert.com" : timestampingServiceUrl);
|
||||
}
|
||||
else {
|
||||
args.push("-t", timestampingServiceUrl);
|
||||
}
|
||||
}
|
||||
const certificateFile = options.cscInfo.file;
|
||||
if (certificateFile == null) {
|
||||
const cscInfo = options.cscInfo;
|
||||
const subjectName = cscInfo.thumbprint;
|
||||
if (!isWin) {
|
||||
throw new Error(`${subjectName == null ? "certificateSha1" : "certificateSubjectName"} supported only on Windows`);
|
||||
}
|
||||
args.push("/sha1", cscInfo.thumbprint);
|
||||
args.push("/s", cscInfo.store);
|
||||
if (cscInfo.isLocalMachineStore) {
|
||||
args.push("/sm");
|
||||
}
|
||||
}
|
||||
else {
|
||||
const certExtension = path.extname(certificateFile);
|
||||
if (certExtension === ".p12" || certExtension === ".pfx") {
|
||||
args.push(isWin ? "/f" : "-pkcs12", vm.toVmFile(certificateFile));
|
||||
}
|
||||
else {
|
||||
throw new Error(`Please specify pkcs12 (.p12/.pfx) file, ${certificateFile} is not correct`);
|
||||
}
|
||||
}
|
||||
if (!isWin || options.hash !== "sha1") {
|
||||
args.push(isWin ? "/fd" : "-h", options.hash);
|
||||
if (isWin && process.env.ELECTRON_BUILDER_OFFLINE !== "true") {
|
||||
args.push("/td", "sha256");
|
||||
}
|
||||
}
|
||||
if (options.name) {
|
||||
args.push(isWin ? "/d" : "-n", options.name);
|
||||
}
|
||||
if (options.site) {
|
||||
args.push(isWin ? "/du" : "-i", options.site);
|
||||
}
|
||||
// msi does not support dual-signing
|
||||
if (options.isNest) {
|
||||
args.push(isWin ? "/as" : "-nest");
|
||||
}
|
||||
const password = options.cscInfo == null ? null : options.cscInfo.password;
|
||||
if (password) {
|
||||
args.push(isWin ? "/p" : "-pass", password);
|
||||
}
|
||||
if (options.options.additionalCertificateFile) {
|
||||
args.push(isWin ? "/ac" : "-ac", vm.toVmFile(options.options.additionalCertificateFile));
|
||||
}
|
||||
const httpsProxyFromEnv = process.env.HTTPS_PROXY;
|
||||
if (!isWin && httpsProxyFromEnv != null && httpsProxyFromEnv.length) {
|
||||
args.push("-p", httpsProxyFromEnv);
|
||||
}
|
||||
if (isWin) {
|
||||
// https://github.com/electron-userland/electron-builder/issues/2875#issuecomment-387233610
|
||||
args.push("/debug");
|
||||
// must be last argument
|
||||
args.push(inputFile);
|
||||
}
|
||||
return args;
|
||||
}
|
||||
function getOutputPath(inputPath, hash) {
|
||||
const extension = path.extname(inputPath);
|
||||
return path.join(path.dirname(inputPath), `${path.basename(inputPath, extension)}-signed-${hash}${extension}`);
|
||||
}
|
||||
/** @internal */
|
||||
function isOldWin6() {
|
||||
const winVersion = os.release();
|
||||
return winVersion.startsWith("6.") && !winVersion.startsWith("6.3");
|
||||
}
|
||||
exports.isOldWin6 = isOldWin6;
|
||||
function getWinSignTool(vendorPath) {
|
||||
// use modern signtool on Windows Server 2012 R2 to be able to sign AppX
|
||||
if (isOldWin6()) {
|
||||
return path.join(vendorPath, "windows-6", "signtool.exe");
|
||||
}
|
||||
else {
|
||||
return path.join(vendorPath, "windows-10", process.arch, "signtool.exe");
|
||||
}
|
||||
}
|
||||
async function getToolPath() {
|
||||
if (flags_1.isUseSystemSigncode()) {
|
||||
return { path: "osslsigncode" };
|
||||
}
|
||||
const result = process.env.SIGNTOOL_PATH;
|
||||
if (result) {
|
||||
return { path: result };
|
||||
}
|
||||
const vendorPath = await getSignVendorPath();
|
||||
if (process.platform === "win32") {
|
||||
// use modern signtool on Windows Server 2012 R2 to be able to sign AppX
|
||||
return { path: getWinSignTool(vendorPath) };
|
||||
}
|
||||
else if (process.platform === "darwin") {
|
||||
const toolDirPath = path.join(vendorPath, process.platform, "10.12");
|
||||
return {
|
||||
path: path.join(toolDirPath, "osslsigncode"),
|
||||
env: bundledTool_1.computeToolEnv([path.join(toolDirPath, "lib")]),
|
||||
};
|
||||
}
|
||||
else {
|
||||
return { path: path.join(vendorPath, process.platform, "osslsigncode") };
|
||||
}
|
||||
function signWithRetry(signer) {
|
||||
return (0, builder_util_1.retry)(signer, {
|
||||
retries: 3,
|
||||
interval: 1000,
|
||||
backoff: 1000,
|
||||
shouldRetry: (e) => {
|
||||
const message = e.message;
|
||||
if (
|
||||
// https://github.com/electron-userland/electron-builder/issues/1414
|
||||
(message === null || message === void 0 ? void 0 : message.includes("Couldn't resolve host name")) ||
|
||||
(
|
||||
// https://github.com/electron-userland/electron-builder/issues/8615
|
||||
message === null || message === void 0 ? void 0 : message.includes("being used by another process."))) {
|
||||
builder_util_1.log.warn({ error: message }, "attempt to sign failed, another attempt will be made");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
});
|
||||
}
|
||||
//# sourceMappingURL=windowsCodeSign.js.map
|
||||
2
electron/node_modules/app-builder-lib/out/codeSign/windowsCodeSign.js.map
generated
vendored
2
electron/node_modules/app-builder-lib/out/codeSign/windowsCodeSign.js.map
generated
vendored
File diff suppressed because one or more lines are too long
17
electron/node_modules/app-builder-lib/out/codeSign/windowsSignAzureManager.d.ts
generated
vendored
Normal file
17
electron/node_modules/app-builder-lib/out/codeSign/windowsSignAzureManager.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
import { MemoLazy } from "builder-util-runtime";
|
||||
import { Lazy } from "lazy-val";
|
||||
import { WindowsConfiguration } from "../options/winOptions";
|
||||
import { WinPackager } from "../winPackager";
|
||||
import { SignManager } from "./signManager";
|
||||
import { WindowsSignOptions } from "./windowsCodeSign";
|
||||
import { CertificateFromStoreInfo, FileCodeSigningInfo } from "./windowsSignToolManager";
|
||||
export declare class WindowsSignAzureManager implements SignManager {
|
||||
private readonly packager;
|
||||
private readonly platformSpecificBuildOptions;
|
||||
readonly computedPublisherName: Lazy<string[] | null>;
|
||||
constructor(packager: WinPackager);
|
||||
initialize(): Promise<void>;
|
||||
computePublisherName(): Promise<string>;
|
||||
readonly cscInfo: MemoLazy<WindowsConfiguration, FileCodeSigningInfo | CertificateFromStoreInfo | null>;
|
||||
signFile(options: WindowsSignOptions): Promise<boolean>;
|
||||
}
|
||||
73
electron/node_modules/app-builder-lib/out/codeSign/windowsSignAzureManager.js
generated
vendored
Normal file
73
electron/node_modules/app-builder-lib/out/codeSign/windowsSignAzureManager.js
generated
vendored
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.WindowsSignAzureManager = void 0;
|
||||
const builder_util_1 = require("builder-util");
|
||||
const builder_util_runtime_1 = require("builder-util-runtime");
|
||||
const lazy_val_1 = require("lazy-val");
|
||||
class WindowsSignAzureManager {
|
||||
constructor(packager) {
|
||||
this.packager = packager;
|
||||
this.computedPublisherName = new lazy_val_1.Lazy(() => {
|
||||
var _a;
|
||||
const publisherName = (_a = this.platformSpecificBuildOptions.azureSignOptions) === null || _a === void 0 ? void 0 : _a.publisherName;
|
||||
if (publisherName === null) {
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
else if (publisherName != null) {
|
||||
return Promise.resolve((0, builder_util_1.asArray)(publisherName));
|
||||
}
|
||||
// TODO: Is there another way to automatically pull Publisher Name from AzureTrusted service?
|
||||
// For now return null.
|
||||
return Promise.resolve(null);
|
||||
});
|
||||
this.cscInfo = new builder_util_runtime_1.MemoLazy(() => this.packager.platformSpecificBuildOptions, _selected => Promise.resolve(null));
|
||||
this.platformSpecificBuildOptions = packager.platformSpecificBuildOptions;
|
||||
}
|
||||
async initialize() {
|
||||
const vm = await this.packager.vm.value;
|
||||
const ps = await vm.powershellCommand.value;
|
||||
builder_util_1.log.info(null, "installing required module (TrustedSigning) with scope CurrentUser");
|
||||
try {
|
||||
await vm.exec(ps, ["-NoProfile", "-NonInteractive", "-Command", "Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force -Scope CurrentUser"]);
|
||||
}
|
||||
catch (error) {
|
||||
// Might not be needed, seems GH runners already have NuGet set up.
|
||||
// Logging to debug just in case users run into this. If NuGet isn't present, Install-Module -Name TrustedSigning will fail, so we'll get the logs at that point
|
||||
builder_util_1.log.debug({ message: error.message || error.stack }, "unable to install PackageProvider Nuget. Might be a false alarm though as some systems already have it installed");
|
||||
}
|
||||
await vm.exec(ps, ["-NoProfile", "-NonInteractive", "-Command", "Install-Module -Name TrustedSigning -MinimumVersion 0.5.0 -Force -Repository PSGallery -Scope CurrentUser"]);
|
||||
// If signing has been misconfigured it, the error from the TrustedSigning module should be descriptive enough to help them fix their configuration.
|
||||
// Options: https://learn.microsoft.com/en-us/dotnet/api/azure.identity.environmentcredential?view=azure-dotnet#definition
|
||||
}
|
||||
computePublisherName() {
|
||||
return Promise.resolve(this.packager.platformSpecificBuildOptions.azureSignOptions.publisherName);
|
||||
}
|
||||
// prerequisite: requires `initializeProviderModules` to already have been executed
|
||||
async signFile(options) {
|
||||
const vm = await this.packager.vm.value;
|
||||
const ps = await vm.powershellCommand.value;
|
||||
const { publisherName: _publisher, // extract from `extraSigningArgs`
|
||||
endpoint, certificateProfileName, codeSigningAccountName, fileDigest, timestampRfc3161, timestampDigest, ...extraSigningArgs } = options.options.azureSignOptions;
|
||||
const params = {
|
||||
...extraSigningArgs,
|
||||
Endpoint: endpoint,
|
||||
CertificateProfileName: certificateProfileName,
|
||||
CodeSigningAccountName: codeSigningAccountName,
|
||||
TimestampRfc3161: timestampRfc3161 || "http://timestamp.acs.microsoft.com",
|
||||
TimestampDigest: timestampDigest || "SHA256",
|
||||
FileDigest: fileDigest || "SHA256",
|
||||
Files: vm.toVmFile(options.path),
|
||||
};
|
||||
const paramsString = Object.entries(params)
|
||||
.filter(([_, value]) => value != null)
|
||||
.reduce((res, [field, value]) => {
|
||||
const escapedValue = String(value).replace(/'/g, "''");
|
||||
return [...res, `-${field}`, `'${escapedValue}'`];
|
||||
}, [])
|
||||
.join(" ");
|
||||
await vm.exec(ps, ["-NoProfile", "-NonInteractive", "-Command", `Invoke-TrustedSigning ${paramsString}`]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
exports.WindowsSignAzureManager = WindowsSignAzureManager;
|
||||
//# sourceMappingURL=windowsSignAzureManager.js.map
|
||||
1
electron/node_modules/app-builder-lib/out/codeSign/windowsSignAzureManager.js.map
generated
vendored
Normal file
1
electron/node_modules/app-builder-lib/out/codeSign/windowsSignAzureManager.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
58
electron/node_modules/app-builder-lib/out/codeSign/windowsSignToolManager.d.ts
generated
vendored
Normal file
58
electron/node_modules/app-builder-lib/out/codeSign/windowsSignToolManager.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
import { MemoLazy } from "builder-util-runtime";
|
||||
import { Lazy } from "lazy-val";
|
||||
import { Target } from "../core";
|
||||
import { WindowsConfiguration } from "../options/winOptions";
|
||||
import { ToolInfo } from "../util/bundledTool";
|
||||
import { VmManager } from "../vm/vm";
|
||||
import { WinPackager } from "../winPackager";
|
||||
import { SignManager } from "./signManager";
|
||||
import { WindowsSignOptions } from "./windowsCodeSign";
|
||||
export type CustomWindowsSign = (configuration: CustomWindowsSignTaskConfiguration, packager?: WinPackager) => Promise<any>;
|
||||
export interface WindowsSignToolOptions extends WindowsSignOptions {
|
||||
readonly name: string;
|
||||
readonly site: string | null;
|
||||
}
|
||||
export interface FileCodeSigningInfo {
|
||||
readonly file: string;
|
||||
readonly password: string | null;
|
||||
}
|
||||
export interface WindowsSignTaskConfiguration extends WindowsSignToolOptions {
|
||||
readonly cscInfo: FileCodeSigningInfo | CertificateFromStoreInfo | null;
|
||||
resultOutputPath?: string;
|
||||
hash: string;
|
||||
isNest: boolean;
|
||||
}
|
||||
export interface CustomWindowsSignTaskConfiguration extends WindowsSignTaskConfiguration {
|
||||
computeSignToolArgs(isWin: boolean): Array<string>;
|
||||
}
|
||||
export interface CertificateInfo {
|
||||
readonly commonName: string;
|
||||
readonly bloodyMicrosoftSubjectDn: string;
|
||||
}
|
||||
export interface CertificateFromStoreInfo {
|
||||
thumbprint: string;
|
||||
subject: string;
|
||||
store: string;
|
||||
isLocalMachineStore: boolean;
|
||||
}
|
||||
export declare class WindowsSignToolManager implements SignManager {
|
||||
private readonly packager;
|
||||
private readonly platformSpecificBuildOptions;
|
||||
constructor(packager: WinPackager);
|
||||
readonly computedPublisherName: Lazy<string[] | null>;
|
||||
readonly lazyCertInfo: MemoLazy<MemoLazy<WindowsConfiguration, FileCodeSigningInfo | CertificateFromStoreInfo | null>, CertificateInfo | null>;
|
||||
readonly cscInfo: MemoLazy<WindowsConfiguration, FileCodeSigningInfo | CertificateFromStoreInfo | null>;
|
||||
initialize(): Promise<void>;
|
||||
computePublisherName(target: Target, publisherName: string): Promise<string>;
|
||||
signFile(options: WindowsSignOptions): Promise<boolean>;
|
||||
getCertInfo(file: string, password: string): Promise<CertificateInfo>;
|
||||
computeSignToolArgs(options: WindowsSignTaskConfiguration, isWin: boolean, vm?: VmManager): Array<string>;
|
||||
private computeWindowsSignArgs;
|
||||
private computeOsslsigncodeArgs;
|
||||
private addCertificateArgs;
|
||||
private addCommonSigningArgs;
|
||||
getOutputPath(inputPath: string, hash: string): string;
|
||||
getCertificateFromStoreInfo(options: WindowsConfiguration, vm: VmManager): Promise<CertificateFromStoreInfo>;
|
||||
getToolPath(isWin?: boolean): Promise<ToolInfo>;
|
||||
doSign(configuration: CustomWindowsSignTaskConfiguration, packager: WinPackager): Promise<void>;
|
||||
}
|
||||
376
electron/node_modules/app-builder-lib/out/codeSign/windowsSignToolManager.js
generated
vendored
Normal file
376
electron/node_modules/app-builder-lib/out/codeSign/windowsSignToolManager.js
generated
vendored
Normal file
|
|
@ -0,0 +1,376 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.WindowsSignToolManager = void 0;
|
||||
const builder_util_1 = require("builder-util");
|
||||
const builder_util_runtime_1 = require("builder-util-runtime");
|
||||
const fs_extra_1 = require("fs-extra");
|
||||
const lazy_val_1 = require("lazy-val");
|
||||
const path = require("path");
|
||||
const AppxTarget_1 = require("../targets/AppxTarget");
|
||||
const windows_1 = require("../toolsets/windows");
|
||||
const resolve_1 = require("../util/resolve");
|
||||
const certInfo_1 = require("./certInfo");
|
||||
const vm_1 = require("../vm/vm");
|
||||
const codesign_1 = require("./codesign");
|
||||
class WindowsSignToolManager {
|
||||
constructor(packager) {
|
||||
this.packager = packager;
|
||||
this.computedPublisherName = new lazy_val_1.Lazy(async () => {
|
||||
var _a;
|
||||
const publisherName = (_a = this.platformSpecificBuildOptions.signtoolOptions) === null || _a === void 0 ? void 0 : _a.publisherName;
|
||||
if (publisherName === null) {
|
||||
return null;
|
||||
}
|
||||
else if (publisherName != null) {
|
||||
return (0, builder_util_1.asArray)(publisherName);
|
||||
}
|
||||
const certInfo = await this.lazyCertInfo.value;
|
||||
return certInfo == null ? null : [certInfo.commonName];
|
||||
});
|
||||
this.lazyCertInfo = new builder_util_runtime_1.MemoLazy(() => this.cscInfo, async (csc) => {
|
||||
const cscInfo = await csc.value;
|
||||
if (cscInfo == null) {
|
||||
return null;
|
||||
}
|
||||
if ("subject" in cscInfo) {
|
||||
const bloodyMicrosoftSubjectDn = cscInfo.subject;
|
||||
return {
|
||||
commonName: (0, builder_util_runtime_1.parseDn)(bloodyMicrosoftSubjectDn).get("CN"),
|
||||
bloodyMicrosoftSubjectDn,
|
||||
};
|
||||
}
|
||||
const cscFile = cscInfo.file;
|
||||
if (cscFile == null) {
|
||||
return null;
|
||||
}
|
||||
return await this.getCertInfo(cscFile, cscInfo.password || "");
|
||||
});
|
||||
this.cscInfo = new builder_util_runtime_1.MemoLazy(() => this.platformSpecificBuildOptions, platformSpecificBuildOptions => {
|
||||
var _a, _b, _c;
|
||||
const subjectName = (_a = platformSpecificBuildOptions.signtoolOptions) === null || _a === void 0 ? void 0 : _a.certificateSubjectName;
|
||||
const shaType = (_b = platformSpecificBuildOptions.signtoolOptions) === null || _b === void 0 ? void 0 : _b.certificateSha1;
|
||||
if (subjectName != null || shaType != null) {
|
||||
return this.packager.vm.value
|
||||
.then(vm => this.getCertificateFromStoreInfo(platformSpecificBuildOptions, vm))
|
||||
.catch((e) => {
|
||||
var _a;
|
||||
// https://github.com/electron-userland/electron-builder/pull/2397
|
||||
if (((_a = platformSpecificBuildOptions.signtoolOptions) === null || _a === void 0 ? void 0 : _a.sign) == null) {
|
||||
throw e;
|
||||
}
|
||||
else {
|
||||
builder_util_1.log.debug({ error: e }, "getCertificateFromStoreInfo error");
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
const certificateFile = (_c = platformSpecificBuildOptions.signtoolOptions) === null || _c === void 0 ? void 0 : _c.certificateFile;
|
||||
if (certificateFile != null) {
|
||||
const certificatePassword = this.packager.getCscPassword();
|
||||
return Promise.resolve({
|
||||
file: certificateFile,
|
||||
password: certificatePassword == null ? null : certificatePassword.trim(),
|
||||
});
|
||||
}
|
||||
const cscLink = this.packager.getCscLink("WIN_CSC_LINK");
|
||||
if (cscLink == null || cscLink === "") {
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
return ((0, codesign_1.importCertificate)(cscLink, this.packager.info.tempDirManager, this.packager.projectDir)
|
||||
// before then
|
||||
.catch((e) => {
|
||||
if (e instanceof builder_util_1.InvalidConfigurationError) {
|
||||
throw new builder_util_1.InvalidConfigurationError(`Env WIN_CSC_LINK is not correct, cannot resolve: ${e.message}`);
|
||||
}
|
||||
else {
|
||||
throw e;
|
||||
}
|
||||
})
|
||||
.then(path => {
|
||||
return {
|
||||
file: path,
|
||||
password: this.packager.getCscPassword(),
|
||||
};
|
||||
}));
|
||||
});
|
||||
this.platformSpecificBuildOptions = packager.platformSpecificBuildOptions;
|
||||
}
|
||||
initialize() {
|
||||
return Promise.resolve();
|
||||
}
|
||||
// https://github.com/electron-userland/electron-builder/issues/2108#issuecomment-333200711
|
||||
async computePublisherName(target, publisherName) {
|
||||
if (target instanceof AppxTarget_1.default && (await this.cscInfo.value) == null) {
|
||||
builder_util_1.log.info({ reason: "Windows Store only build" }, "AppX is not signed");
|
||||
return publisherName || "CN=ms";
|
||||
}
|
||||
const certInfo = await this.lazyCertInfo.value;
|
||||
const publisher = publisherName || (certInfo == null ? null : certInfo.bloodyMicrosoftSubjectDn);
|
||||
if (publisher == null) {
|
||||
throw new Error("Internal error: cannot compute subject using certificate info");
|
||||
}
|
||||
return publisher;
|
||||
}
|
||||
async signFile(options) {
|
||||
var _a, _b;
|
||||
let hashes = (_a = options.options.signtoolOptions) === null || _a === void 0 ? void 0 : _a.signingHashAlgorithms;
|
||||
// msi does not support dual-signing
|
||||
if (options.path.endsWith(".msi")) {
|
||||
hashes = [hashes != null && !hashes.includes("sha1") ? "sha256" : "sha1"];
|
||||
}
|
||||
else if (options.path.endsWith(".appx")) {
|
||||
hashes = ["sha256"];
|
||||
}
|
||||
else if (hashes == null) {
|
||||
hashes = ["sha1", "sha256"];
|
||||
}
|
||||
else {
|
||||
hashes = Array.isArray(hashes) ? hashes : [hashes];
|
||||
}
|
||||
const name = this.packager.appInfo.productName;
|
||||
const site = await this.packager.appInfo.computePackageUrl();
|
||||
const customSign = await (0, resolve_1.resolveFunction)(this.packager.appInfo.type, (_b = options.options.signtoolOptions) === null || _b === void 0 ? void 0 : _b.sign, "sign", await this.packager.info.getWorkspaceRoot());
|
||||
const cscInfo = await this.cscInfo.value;
|
||||
if (cscInfo) {
|
||||
let logInfo = {
|
||||
file: builder_util_1.log.filePath(options.path),
|
||||
};
|
||||
if ("file" in cscInfo) {
|
||||
logInfo = {
|
||||
...logInfo,
|
||||
certificateFile: cscInfo.file,
|
||||
};
|
||||
}
|
||||
else {
|
||||
logInfo = {
|
||||
...logInfo,
|
||||
subject: cscInfo.subject,
|
||||
thumbprint: cscInfo.thumbprint,
|
||||
store: cscInfo.store,
|
||||
user: cscInfo.isLocalMachineStore ? "local machine" : "current user",
|
||||
};
|
||||
}
|
||||
builder_util_1.log.info(logInfo, "signing");
|
||||
}
|
||||
else if (!customSign) {
|
||||
builder_util_1.log.debug({ signHook: !!customSign, cscInfo }, "no signing info identified, signing is skipped");
|
||||
return false;
|
||||
}
|
||||
const executor = customSign || ((config, packager) => this.doSign(config, packager));
|
||||
let isNest = false;
|
||||
for (const hash of hashes) {
|
||||
const taskConfiguration = { ...options, name, site, cscInfo, hash, isNest };
|
||||
await Promise.resolve(executor({
|
||||
...taskConfiguration,
|
||||
computeSignToolArgs: isWin => this.computeSignToolArgs(taskConfiguration, isWin),
|
||||
}, this.packager));
|
||||
isNest = true;
|
||||
if (taskConfiguration.resultOutputPath != null) {
|
||||
await (0, fs_extra_1.rename)(taskConfiguration.resultOutputPath, options.path);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
async getCertInfo(file, password) {
|
||||
const errorMessagePrefix = "Cannot extract publisher name from code signing certificate. As workaround, set win.publisherName. Error: ";
|
||||
try {
|
||||
return await (0, certInfo_1.readCertInfo)(file, password);
|
||||
}
|
||||
catch (e) {
|
||||
throw new builder_util_1.InvalidConfigurationError(`${errorMessagePrefix}${e.message || e}`);
|
||||
}
|
||||
}
|
||||
// on windows be aware of http://stackoverflow.com/a/32640183/1910191
|
||||
computeSignToolArgs(options, isWin, vm = new vm_1.VmManager()) {
|
||||
return isWin ? this.computeWindowsSignArgs(options, vm) : this.computeOsslsigncodeArgs(options, vm);
|
||||
}
|
||||
computeWindowsSignArgs(options, vm) {
|
||||
var _a, _b, _c, _d;
|
||||
const inputFile = vm.toVmFile(options.path);
|
||||
const args = ["sign"];
|
||||
// Timestamping
|
||||
if (process.env.ELECTRON_BUILDER_OFFLINE !== "true") {
|
||||
const isRfc3161 = options.isNest || options.hash === "sha256";
|
||||
args.push(isRfc3161 ? "/tr" : "/t");
|
||||
const timestampUrl = isRfc3161
|
||||
? ((_a = options.options.signtoolOptions) === null || _a === void 0 ? void 0 : _a.rfc3161TimeStampServer) || "http://timestamp.digicert.com"
|
||||
: ((_b = options.options.signtoolOptions) === null || _b === void 0 ? void 0 : _b.timeStampServer) || "http://timestamp.digicert.com";
|
||||
args.push(timestampUrl);
|
||||
}
|
||||
// Certificate
|
||||
this.addCertificateArgs(args, options, vm, true);
|
||||
// Hash algorithm
|
||||
const isLegacyToolset = ((_c = this.packager.config.toolsets) === null || _c === void 0 ? void 0 : _c.winCodeSign) === "0.0.0" || ((_d = this.packager.config.toolsets) === null || _d === void 0 ? void 0 : _d.winCodeSign) == null;
|
||||
if (isLegacyToolset) {
|
||||
// Legacy || v0.0.0: Only add /fd for non-SHA1 (original behavior)
|
||||
if (options.hash !== "sha1") {
|
||||
args.push("/fd", options.hash);
|
||||
if (process.env.ELECTRON_BUILDER_OFFLINE !== "true") {
|
||||
args.push("/td", "sha256");
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Modern: Always add /fd (required by new Windows Kits)
|
||||
args.push("/fd", options.hash.toLowerCase());
|
||||
// Only add /td for RFC3161 timestamps (incompatible with /t)
|
||||
if (process.env.ELECTRON_BUILDER_OFFLINE !== "true" && (options.isNest || options.hash === "sha256")) {
|
||||
args.push("/td", "sha256");
|
||||
}
|
||||
}
|
||||
// Optional parameters
|
||||
this.addCommonSigningArgs(args, options, vm, true);
|
||||
// Windows-specific
|
||||
args.push("/debug");
|
||||
args.push(inputFile); // Must be last
|
||||
return args;
|
||||
}
|
||||
computeOsslsigncodeArgs(options, vm) {
|
||||
var _a;
|
||||
const inputFile = vm.toVmFile(options.path);
|
||||
const outputPath = this.getOutputPath(inputFile, options.hash);
|
||||
options.resultOutputPath = outputPath;
|
||||
const args = ["sign", "-in", inputFile, "-out", outputPath];
|
||||
// Timestamping
|
||||
if (process.env.ELECTRON_BUILDER_OFFLINE !== "true") {
|
||||
const timestampUrl = ((_a = options.options.signtoolOptions) === null || _a === void 0 ? void 0 : _a.timeStampServer) || "http://timestamp.digicert.com";
|
||||
args.push("-t", timestampUrl);
|
||||
}
|
||||
// Certificate
|
||||
this.addCertificateArgs(args, options, vm, false);
|
||||
// Hash algorithm
|
||||
args.push("-h", options.hash.toLowerCase());
|
||||
// Optional parameters
|
||||
this.addCommonSigningArgs(args, options, vm, false);
|
||||
// Proxy support
|
||||
const httpsProxy = process.env.HTTPS_PROXY;
|
||||
if (httpsProxy === null || httpsProxy === void 0 ? void 0 : httpsProxy.length) {
|
||||
args.push("-p", httpsProxy);
|
||||
}
|
||||
return args;
|
||||
}
|
||||
addCertificateArgs(args, options, vm, isWin) {
|
||||
if (options.cscInfo == null) {
|
||||
throw new Error("No code signing certificate configured. Provide certificateFile, certificateSha1, or certificateSubjectName.");
|
||||
}
|
||||
const certificateFile = options.cscInfo.file;
|
||||
if (certificateFile == null) {
|
||||
// Certificate from store (Windows only)
|
||||
if (!isWin) {
|
||||
throw new Error("certificateSha1/certificateSubjectName supported only on Windows");
|
||||
}
|
||||
const cscInfo = options.cscInfo;
|
||||
args.push("/sha1", cscInfo.thumbprint);
|
||||
args.push("/s", cscInfo.store);
|
||||
if (cscInfo.isLocalMachineStore) {
|
||||
args.push("/sm");
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Certificate file
|
||||
const certExtension = path.extname(certificateFile);
|
||||
if (certExtension === ".p12" || certExtension === ".pfx") {
|
||||
args.push(isWin ? "/f" : "-pkcs12", vm.toVmFile(certificateFile));
|
||||
}
|
||||
else {
|
||||
throw new Error(`Please specify pkcs12 (.p12/.pfx) file, ${certificateFile} is not correct`);
|
||||
}
|
||||
}
|
||||
}
|
||||
addCommonSigningArgs(args, options, vm, isWin) {
|
||||
var _a, _b;
|
||||
if (options.name) {
|
||||
args.push(isWin ? "/d" : "-n", options.name);
|
||||
}
|
||||
if (options.site) {
|
||||
args.push(isWin ? "/du" : "-i", options.site);
|
||||
}
|
||||
if (options.isNest) {
|
||||
args.push(isWin ? "/as" : "-nest");
|
||||
}
|
||||
const password = (_a = options.cscInfo) === null || _a === void 0 ? void 0 : _a.password;
|
||||
if (password) {
|
||||
args.push(isWin ? "/p" : "-pass", password);
|
||||
}
|
||||
const additionalCert = (_b = options.options.signtoolOptions) === null || _b === void 0 ? void 0 : _b.additionalCertificateFile;
|
||||
if (additionalCert) {
|
||||
args.push(isWin ? "/ac" : "-ac", vm.toVmFile(additionalCert));
|
||||
}
|
||||
}
|
||||
getOutputPath(inputPath, hash) {
|
||||
const extension = path.extname(inputPath);
|
||||
return path.join(path.dirname(inputPath), `${path.basename(inputPath, extension)}-signed-${hash}${extension}`);
|
||||
}
|
||||
async getCertificateFromStoreInfo(options, vm) {
|
||||
var _a, _b, _c;
|
||||
const certificateSubjectName = (_a = options.signtoolOptions) === null || _a === void 0 ? void 0 : _a.certificateSubjectName;
|
||||
const certificateSha1 = (_c = (_b = options.signtoolOptions) === null || _b === void 0 ? void 0 : _b.certificateSha1) === null || _c === void 0 ? void 0 : _c.toUpperCase();
|
||||
const ps = await vm.powershellCommand.value;
|
||||
const rawResult = await vm.exec(ps, [
|
||||
"-NoProfile",
|
||||
"-NonInteractive",
|
||||
"-Command",
|
||||
"Get-ChildItem -Recurse Cert: -CodeSigningCert | Select-Object -Property Subject,PSParentPath,Thumbprint | ConvertTo-Json -Compress",
|
||||
]);
|
||||
const certList = rawResult.length === 0 ? [] : (0, builder_util_1.asArray)(JSON.parse(rawResult));
|
||||
for (const certInfo of certList) {
|
||||
if ((certificateSubjectName != null && !certInfo.Subject.includes(certificateSubjectName)) ||
|
||||
(certificateSha1 != null && certInfo.Thumbprint.toUpperCase() !== certificateSha1)) {
|
||||
continue;
|
||||
}
|
||||
const parentPath = certInfo.PSParentPath;
|
||||
const store = parentPath.substring(parentPath.lastIndexOf("\\") + 1);
|
||||
builder_util_1.log.debug({ store, PSParentPath: parentPath }, "auto-detect certificate store");
|
||||
// https://github.com/electron-userland/electron-builder/issues/1717
|
||||
const isLocalMachineStore = parentPath.includes("Certificate::LocalMachine");
|
||||
builder_util_1.log.debug(null, "auto-detect using of LocalMachine store");
|
||||
return {
|
||||
thumbprint: certInfo.Thumbprint,
|
||||
subject: certInfo.Subject,
|
||||
store,
|
||||
isLocalMachineStore,
|
||||
};
|
||||
}
|
||||
throw new Error(`Cannot find certificate ${certificateSubjectName || certificateSha1}, all certs: ${rawResult}`);
|
||||
}
|
||||
async getToolPath(isWin = process.platform === "win32") {
|
||||
var _a;
|
||||
return (0, windows_1.getSignToolPath)((_a = this.packager.config.toolsets) === null || _a === void 0 ? void 0 : _a.winCodeSign, isWin);
|
||||
}
|
||||
async doSign(configuration, packager) {
|
||||
var _a;
|
||||
// https://github.com/electron-userland/electron-builder/pull/1944
|
||||
const timeout = parseInt(process.env.SIGNTOOL_TIMEOUT, 10) || 10 * 60 * 1000;
|
||||
// decide runtime argument by cases
|
||||
let args;
|
||||
let vm;
|
||||
const useVmIfNotOnWin = configuration.path.endsWith(".appx") || !("file" in configuration.cscInfo); /* certificateSubjectName and other such options */
|
||||
const isWin = process.platform === "win32" || useVmIfNotOnWin;
|
||||
const toolInfo = await (0, windows_1.getSignToolPath)((_a = this.packager.config.toolsets) === null || _a === void 0 ? void 0 : _a.winCodeSign, isWin);
|
||||
const tool = toolInfo.path;
|
||||
if (useVmIfNotOnWin) {
|
||||
vm = await packager.vm.value;
|
||||
args = this.computeSignToolArgs(configuration, isWin, vm);
|
||||
}
|
||||
else {
|
||||
vm = new vm_1.VmManager();
|
||||
args = configuration.computeSignToolArgs(isWin);
|
||||
}
|
||||
await (0, builder_util_1.retry)(() => vm.exec(tool, args, { timeout, env: { ...process.env, ...(toolInfo.env || {}) } }), {
|
||||
retries: 2,
|
||||
interval: 15000,
|
||||
backoff: 10000,
|
||||
shouldRetry: (e) => {
|
||||
if (e.message.includes("The file is being used by another process") ||
|
||||
e.message.includes("The specified timestamp server either could not be reached") ||
|
||||
e.message.includes("No certificates were found that met all the given criteria.")) {
|
||||
builder_util_1.log.warn(`Attempt to code sign failed, another attempt will be made in 15 seconds: ${e.message}`);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.WindowsSignToolManager = WindowsSignToolManager;
|
||||
//# sourceMappingURL=windowsSignToolManager.js.map
|
||||
1
electron/node_modules/app-builder-lib/out/codeSign/windowsSignToolManager.js.map
generated
vendored
Normal file
1
electron/node_modules/app-builder-lib/out/codeSign/windowsSignToolManager.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
478
electron/node_modules/app-builder-lib/out/configuration.d.ts
generated
vendored
478
electron/node_modules/app-builder-lib/out/configuration.d.ts
generated
vendored
|
|
@ -1,24 +1,26 @@
|
|||
import { Arch } from "builder-util";
|
||||
import { BeforeBuildContext, Target } from "./core";
|
||||
import { ElectronBrandingOptions, ElectronDownloadOptions } from "./electron/ElectronFramework";
|
||||
import { ElectronBrandingOptions } from "./electron/ElectronFramework";
|
||||
import { PrepareApplicationStageDirectoryOptions } from "./Framework";
|
||||
import { AppXOptions } from "./options/AppXOptions";
|
||||
import { AppImageOptions, DebOptions, FlatpakOptions, LinuxConfiguration, LinuxTargetSpecificOptions } from "./options/linuxOptions";
|
||||
import { AppImageOptions, DebOptions, FlatpakOptions, LinuxConfiguration, LinuxTargetSpecificOptions, PacmanOptions, RpmOptions } from "./options/linuxOptions";
|
||||
import { DmgOptions, MacConfiguration, MasConfiguration } from "./options/macOptions";
|
||||
import { MsiOptions } from "./options/MsiOptions";
|
||||
import { MsiWrappedOptions } from "./options/MsiWrappedOptions";
|
||||
import { PkgOptions } from "./options/pkgOptions";
|
||||
import { PlatformSpecificBuildOptions } from "./options/PlatformSpecificBuildOptions";
|
||||
import { SnapOptions } from "./options/SnapOptions";
|
||||
import { SnapcraftOptions, SnapOptions } from "./options/SnapOptions";
|
||||
import { SquirrelWindowsOptions } from "./options/SquirrelWindowsOptions";
|
||||
import { WindowsConfiguration } from "./options/winOptions";
|
||||
import { BuildResult } from "./packager";
|
||||
import { ArtifactBuildStarted, ArtifactCreated } from "./packagerApi";
|
||||
import { PlatformPackager } from "./platformPackager";
|
||||
import { NsisOptions, NsisWebOptions, PortableOptions } from "./targets/nsis/nsisOptions";
|
||||
import { ElectronDownloadOptions, ElectronGetOptions } from "./util/electronGet";
|
||||
/**
|
||||
* Configuration Options
|
||||
*/
|
||||
export interface Configuration extends PlatformSpecificBuildOptions {
|
||||
export interface CommonConfiguration {
|
||||
/**
|
||||
* The application id. Used as [CFBundleIdentifier](https://developer.apple.com/library/ios/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/20001431-102070) for MacOS and as
|
||||
* [Application User Model ID](https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx) for Windows (NSIS target only, Squirrel.Windows not supported). It is strongly recommended that an explicit ID is set.
|
||||
|
|
@ -26,7 +28,7 @@ export interface Configuration extends PlatformSpecificBuildOptions {
|
|||
*/
|
||||
readonly appId?: string | null;
|
||||
/**
|
||||
* As [name](#Metadata-name), but allows you to specify a product name for your executable which contains spaces and other special characters not allowed in the [name property](https://docs.npmjs.com/files/package.json#name).
|
||||
* As [name](#metadata), but allows you to specify a product name for your executable which contains spaces and other special characters not allowed in the [name property](https://docs.npmjs.com/files/package.json#name).
|
||||
* If not specified inside of the `build` configuration, `productName` property defined at the top level of `package.json` is used. If not specified at the top level of `package.json`, [name property](https://docs.npmjs.com/files/package.json#name) is used.
|
||||
*/
|
||||
readonly productName?: string | null;
|
||||
|
|
@ -35,7 +37,14 @@ export interface Configuration extends PlatformSpecificBuildOptions {
|
|||
* @default Copyright © year ${author}
|
||||
*/
|
||||
readonly copyright?: string | null;
|
||||
/**
|
||||
* Directories for build resources
|
||||
*/
|
||||
readonly directories?: MetadataDirectories | null;
|
||||
/**
|
||||
* Configuration of toolsets utilized by electron-builder
|
||||
*/
|
||||
readonly toolsets?: ToolsetConfig | null;
|
||||
/**
|
||||
* Options related to how build macOS targets.
|
||||
*/
|
||||
|
|
@ -60,43 +69,99 @@ export interface Configuration extends PlatformSpecificBuildOptions {
|
|||
* Options related to how build Windows targets.
|
||||
*/
|
||||
readonly win?: WindowsConfiguration | null;
|
||||
/** NSIS installer options. */
|
||||
readonly nsis?: NsisOptions | null;
|
||||
/** NSIS web installer options (downloads app package at install time). */
|
||||
readonly nsisWeb?: NsisWebOptions | null;
|
||||
/** Portable executable options (no installation required). */
|
||||
readonly portable?: PortableOptions | null;
|
||||
/** Windows Store (AppX) package options. */
|
||||
readonly appx?: AppXOptions | null;
|
||||
/** @private */
|
||||
/**
|
||||
* MSI package options.
|
||||
*/
|
||||
readonly msi?: MsiOptions | null;
|
||||
/**
|
||||
* MSI-wrapped installer options.
|
||||
*/
|
||||
readonly msiWrapped?: MsiWrappedOptions | null;
|
||||
/**
|
||||
* Squirrel.Windows installer options. Requires the `electron-builder-squirrel-windows` dependency.
|
||||
*/
|
||||
readonly squirrelWindows?: SquirrelWindowsOptions | null;
|
||||
/**
|
||||
* Options related to how build Linux targets.
|
||||
* General Linux build options shared across all Linux targets (icon, category, desktop entry,
|
||||
* executable name, etc.). Target-specific compression and packaging options live in the
|
||||
* per-format interfaces (`DebOptions`, `RpmOptions`, `PacmanOptions`, etc.).
|
||||
*/
|
||||
readonly linux?: LinuxConfiguration | null;
|
||||
/**
|
||||
* Debian package options.
|
||||
* Debian package options. Targets Debian, Ubuntu, and Debian-based distributions.
|
||||
* Produces a `.deb` archive installable via `dpkg -i` or `apt install`.
|
||||
*/
|
||||
readonly deb?: DebOptions | null;
|
||||
/**
|
||||
* Snap options.
|
||||
* Flat snap configuration targeting core22 and older snap bases.
|
||||
*
|
||||
* @deprecated Use `snapcraft` instead — it supersedes `snap` when both are present and supports
|
||||
* all snap bases including core24. `snap` will be removed in a future major release.
|
||||
* See {@link SnapOptions} for available properties.
|
||||
*/
|
||||
readonly snap?: SnapOptions | null;
|
||||
/**
|
||||
* AppImage options.
|
||||
* Snapcraft configuration. Prefer this over the deprecated `snap` field.
|
||||
*
|
||||
* Selects the snapcraft base and provides per-core options:
|
||||
* - `base: "core18" | "core20" | "core22"` — legacy builds; accepts the same options as `snap`
|
||||
* - `base: "core24"` — modern builds with the GNOME extension (recommended for new apps, requires Electron 25+)
|
||||
* - `base: "custom"` — pass an existing `snapcraft.yaml` through unchanged; no plugs, extensions,
|
||||
* or desktop files are injected
|
||||
*
|
||||
* When both `snapcraft` and `snap` are set, `snapcraft` takes precedence.
|
||||
*
|
||||
* @example
|
||||
* ```json
|
||||
* { "snapcraft": { "base": "core24", "core24": { "useLXD": true } } }
|
||||
* ```
|
||||
*
|
||||
* See {@link SnapcraftOptions} for all available properties.
|
||||
*/
|
||||
readonly snapcraft?: SnapcraftOptions | null;
|
||||
/**
|
||||
* AppImage options. AppImage is a portable application format that bundles the app
|
||||
* and its dependencies into a single self-contained executable that runs on most
|
||||
* Linux distributions without installation.
|
||||
*/
|
||||
readonly appImage?: AppImageOptions | null;
|
||||
/**
|
||||
* Flatpak options.
|
||||
* Flatpak options. Flatpak is a sandboxed application distribution format for Linux
|
||||
* that runs in a controlled environment and is distributed via [Flathub](https://flathub.org/)
|
||||
* or other Flatpak repositories.
|
||||
*/
|
||||
readonly flatpak?: FlatpakOptions | null;
|
||||
readonly pacman?: LinuxTargetSpecificOptions | null;
|
||||
readonly rpm?: LinuxTargetSpecificOptions | null;
|
||||
readonly freebsd?: LinuxTargetSpecificOptions | null;
|
||||
readonly p5p?: LinuxTargetSpecificOptions | null;
|
||||
readonly apk?: LinuxTargetSpecificOptions | null;
|
||||
/**
|
||||
* Whether to include *all* of the submodules node_modules directories
|
||||
* @default false
|
||||
* Pacman package options. Targets Arch Linux and Arch-based distributions
|
||||
* (Manjaro, EndeavourOS, etc.). Produces a `.pacman` archive installable via `pacman -U`.
|
||||
*/
|
||||
includeSubNodeModules?: boolean;
|
||||
readonly pacman?: PacmanOptions | null;
|
||||
/**
|
||||
* RPM package options. Targets Fedora, Red Hat Enterprise Linux, SUSE, and related
|
||||
* distributions. Produces a `.rpm` archive installable via `rpm` or `dnf`.
|
||||
*/
|
||||
readonly rpm?: RpmOptions | null;
|
||||
/**
|
||||
* FreeBSD package options. Produces a `.pkg` archive for the FreeBSD `pkg` package manager.
|
||||
*/
|
||||
readonly freebsd?: LinuxTargetSpecificOptions | null;
|
||||
/**
|
||||
* Solaris IPS package options. Produces a `.p5p` archive for the Solaris Image Packaging
|
||||
* System (`pkg`).
|
||||
*/
|
||||
readonly p5p?: LinuxTargetSpecificOptions | null;
|
||||
/**
|
||||
* Alpine Linux APK package options. Produces an `.apk` archive installable via `apk add`.
|
||||
*/
|
||||
readonly apk?: LinuxTargetSpecificOptions | null;
|
||||
/**
|
||||
* Whether to build the application native dependencies from source.
|
||||
* @default false
|
||||
|
|
@ -118,6 +183,11 @@ export interface Configuration extends PlatformSpecificBuildOptions {
|
|||
* @default true
|
||||
*/
|
||||
readonly npmRebuild?: boolean;
|
||||
/**
|
||||
* Use `legacy` app-builder binary for installing native dependencies, or `@electron/rebuild` in `sequential` or `parallel` compilation modes.
|
||||
* @default sequential
|
||||
*/
|
||||
readonly nativeRebuilder?: "legacy" | "sequential" | "parallel" | null;
|
||||
/**
|
||||
* The build number. Maps to the `--iteration` flag for builds using FPM on Linux.
|
||||
* If not defined, then it will fallback to `BUILD_NUMBER` or `TRAVIS_BUILD_NUMBER` or `APPVEYOR_BUILD_NUMBER` or `CIRCLE_BUILD_NUM` or `BUILD_BUILDNUMBER` or `CI_PIPELINE_IID` env.
|
||||
|
|
@ -129,33 +199,9 @@ export interface Configuration extends PlatformSpecificBuildOptions {
|
|||
*/
|
||||
readonly buildVersion?: string | null;
|
||||
/**
|
||||
* Whether to use [electron-compile](http://github.com/electron/electron-compile) to compile app. Defaults to `true` if `electron-compile` in the dependencies. And `false` if in the `devDependencies` or doesn't specified.
|
||||
* Whether to download the alternate FFmpeg library from Electron's release assets and replace the default FFmpeg library prior to signing
|
||||
*/
|
||||
readonly electronCompile?: boolean;
|
||||
/**
|
||||
* Returns the path to custom Electron build (e.g. `~/electron/out/R`). Zip files must follow the pattern `electron-v${version}-${platformName}-${arch}.zip`, otherwise it will be assumed to be an unpacked Electron app directory
|
||||
*/
|
||||
readonly electronDist?: string | ((options: PrepareApplicationStageDirectoryOptions) => string);
|
||||
/**
|
||||
* The [electron-download](https://github.com/electron-userland/electron-download#usage) options.
|
||||
*/
|
||||
readonly electronDownload?: ElectronDownloadOptions;
|
||||
/**
|
||||
* The branding used by Electron's distributables. This is needed if a fork has modified Electron's BRANDING.json file.
|
||||
*/
|
||||
readonly electronBranding?: ElectronBrandingOptions;
|
||||
/**
|
||||
* The version of electron you are packaging for. Defaults to version of `electron`, `electron-prebuilt` or `electron-prebuilt-compile` dependency.
|
||||
*/
|
||||
electronVersion?: string | null;
|
||||
/**
|
||||
* The name of a built-in configuration preset (currently, only `react-cra` is supported) or any number of paths to config files (relative to project dir).
|
||||
*
|
||||
* The latter allows to mixin a config from multiple other configs, as if you `Object.assign` them, but properly combine `files` glob patterns.
|
||||
*
|
||||
* If `react-scripts` in the app dependencies, `react-cra` will be set automatically. Set to `null` to disable automatic detection.
|
||||
*/
|
||||
extends?: Array<string> | string | null;
|
||||
readonly downloadAlternateFFmpeg?: boolean;
|
||||
/**
|
||||
* Inject properties to `package.json`.
|
||||
*/
|
||||
|
|
@ -165,66 +211,6 @@ export interface Configuration extends PlatformSpecificBuildOptions {
|
|||
* @default false
|
||||
*/
|
||||
readonly forceCodeSigning?: boolean;
|
||||
/**
|
||||
* *libui-based frameworks only* The version of NodeJS you are packaging for.
|
||||
* You can set it to `current` to set the Node.js version that you use to run.
|
||||
*/
|
||||
readonly nodeVersion?: string | null;
|
||||
/**
|
||||
* *libui-based frameworks only* The version of LaunchUI you are packaging for. Applicable for Windows only. Defaults to version suitable for used framework version.
|
||||
*/
|
||||
readonly launchUiVersion?: boolean | string | null;
|
||||
/**
|
||||
* The framework name. One of `electron`, `proton`, `libui`. Defaults to `electron`.
|
||||
*/
|
||||
readonly framework?: string | null;
|
||||
/**
|
||||
* The function (or path to file or module id) to be [run before pack](#beforepack)
|
||||
*/
|
||||
readonly beforePack?: ((context: BeforePackContext) => Promise<any> | any) | string | null;
|
||||
/**
|
||||
* The function (or path to file or module id) to be [run after pack](#afterpack) (but before pack into distributable format and sign).
|
||||
*/
|
||||
readonly afterPack?: ((context: AfterPackContext) => Promise<any> | any) | string | null;
|
||||
/**
|
||||
* The function (or path to file or module id) to be [run after pack and sign](#aftersign) (but before pack into distributable format).
|
||||
*/
|
||||
readonly afterSign?: ((context: AfterPackContext) => Promise<any> | any) | string | null;
|
||||
/**
|
||||
* The function (or path to file or module id) to be run on artifact build start.
|
||||
*/
|
||||
readonly artifactBuildStarted?: ((context: ArtifactBuildStarted) => Promise<any> | any) | string | null;
|
||||
/**
|
||||
* The function (or path to file or module id) to be run on artifact build completed.
|
||||
*/
|
||||
readonly artifactBuildCompleted?: ((context: ArtifactCreated) => Promise<any> | any) | string | null;
|
||||
/**
|
||||
* The function (or path to file or module id) to be [run after all artifacts are build](#afterAllArtifactBuild).
|
||||
*/
|
||||
readonly afterAllArtifactBuild?: ((context: BuildResult) => Promise<Array<string>> | Array<string>) | string | null;
|
||||
/**
|
||||
* MSI project created on disk - not packed into .msi package yet.
|
||||
*/
|
||||
readonly msiProjectCreated?: ((path: string) => Promise<any> | any) | string | null;
|
||||
/**
|
||||
* Appx manifest created on disk - not packed into .appx package yet.
|
||||
*/
|
||||
readonly appxManifestCreated?: ((path: string) => Promise<any> | any) | string | null;
|
||||
/**
|
||||
* The function (or path to file or module id) to be [run on each node module](#onnodemodulefile) file.
|
||||
*/
|
||||
readonly onNodeModuleFile?: ((file: string) => void) | string | null;
|
||||
/**
|
||||
* The function (or path to file or module id) to be run before dependencies are installed or rebuilt. Works when `npmRebuild` is set to `true`. Resolving to `false` will skip dependencies install or rebuild.
|
||||
*
|
||||
* If provided and `node_modules` are missing, it will not invoke production dependencies check.
|
||||
*/
|
||||
readonly beforeBuild?: ((context: BeforeBuildContext) => Promise<any>) | string | null;
|
||||
/**
|
||||
* Whether to build using Electron Build Service if target not supported on current OS.
|
||||
* @default true
|
||||
*/
|
||||
readonly remoteBuild?: boolean;
|
||||
/**
|
||||
* Whether to include PDB files.
|
||||
* @default false
|
||||
|
|
@ -242,8 +228,72 @@ export interface Configuration extends PlatformSpecificBuildOptions {
|
|||
* @default true
|
||||
*/
|
||||
readonly removePackageKeywords?: boolean;
|
||||
/**
|
||||
* Options to pass to `@electron/fuses`
|
||||
* Ref: https://github.com/electron/fuses
|
||||
*/
|
||||
readonly electronFuses?: FuseOptionsV1 | null;
|
||||
/**
|
||||
* [Experimental] Configuration for concurrent builds.
|
||||
*/
|
||||
readonly concurrency?: Concurrency | null;
|
||||
}
|
||||
interface PackContext {
|
||||
export interface Configuration extends CommonConfiguration, PlatformSpecificBuildOptions, Hooks {
|
||||
/**
|
||||
* Whether to use [electron-compile](http://github.com/electron/electron-compile) to compile app. Defaults to `true` if `electron-compile` in the dependencies. And `false` if in the `devDependencies` or doesn't specified.
|
||||
* @deprecated `electron-compile` is no longer maintained. Compile your app with a modern bundler (webpack, vite, etc.) instead.
|
||||
*/
|
||||
readonly electronCompile?: boolean;
|
||||
/**
|
||||
* The [electron-download](https://github.com/electron-userland/electron-download#usage) options. (legacy)
|
||||
* Alternatively, you can use [electron/get](https://github.com/electron/get#usage) options.
|
||||
*/
|
||||
readonly electronDownload?: ElectronDownloadOptions | ElectronGetOptions | null;
|
||||
/**
|
||||
* The branding used by Electron's distributables. This is needed if a fork has modified Electron's BRANDING.json file.
|
||||
*/
|
||||
readonly electronBranding?: ElectronBrandingOptions;
|
||||
/**
|
||||
* The version of electron you are packaging for. Defaults to version of `electron`, `electron-prebuilt` or `electron-prebuilt-compile` dependency.
|
||||
*/
|
||||
electronVersion?: string | null;
|
||||
/**
|
||||
* The name of a built-in configuration preset (currently, only `react-cra` is supported) or any number of paths to config files (relative to project dir).
|
||||
*
|
||||
* The latter allows to mixin a config from multiple other configs, as if you `Object.assign` them, but properly combine `files` glob patterns.
|
||||
*
|
||||
* If `react-scripts` in the app dependencies, `react-cra` will be set automatically. Set to `null` to disable automatic detection.
|
||||
*/
|
||||
extends?: Array<string> | string | null;
|
||||
/**
|
||||
* *libui-based frameworks only* The version of NodeJS you are packaging for.
|
||||
* You can set it to `current` to set the Node.js version that you use to run.
|
||||
* @deprecated libui-based frameworks (proton-native, etc.) are no longer actively maintained. This option has no effect when using Electron.
|
||||
*/
|
||||
readonly nodeVersion?: string | null;
|
||||
/**
|
||||
* *libui-based frameworks only* The version of LaunchUI you are packaging for. Applicable for Windows only. Defaults to version suitable for used framework version.
|
||||
* @deprecated libui-based frameworks (proton-native, etc.) are no longer actively maintained. This option has no effect when using Electron.
|
||||
*/
|
||||
readonly launchUiVersion?: boolean | string | null;
|
||||
/**
|
||||
* The framework name. One of `electron`, `proton`, `libui`. Defaults to `electron`.
|
||||
* @deprecated `proton` and `libui` framework support is no longer actively maintained. Use `electron` (the default).
|
||||
*/
|
||||
readonly framework?: string | null;
|
||||
/**
|
||||
* Whether to disable sanity check asar package (useful for custom electron forks that implement their own encrypted integrity validation)
|
||||
* @default false
|
||||
*/
|
||||
readonly disableSanityCheckAsar?: boolean;
|
||||
/**
|
||||
* Whether to skip ASAR integrity hash computation. Useful for custom electron forks with encrypted ASAR support where the header is not readable by standard tools.
|
||||
* @default false
|
||||
*/
|
||||
readonly disableAsarIntegrity?: boolean;
|
||||
}
|
||||
export type Hook<T, V> = (contextOrPath: T) => Promise<V> | V;
|
||||
export interface PackContext {
|
||||
readonly outDir: string;
|
||||
readonly appOutDir: string;
|
||||
readonly packager: PlatformPackager<any>;
|
||||
|
|
@ -251,8 +301,155 @@ interface PackContext {
|
|||
readonly arch: Arch;
|
||||
readonly targets: Array<Target>;
|
||||
}
|
||||
export declare type AfterPackContext = PackContext;
|
||||
export declare type BeforePackContext = PackContext;
|
||||
export type AfterPackContext = PackContext;
|
||||
export type BeforePackContext = PackContext;
|
||||
export type AfterExtractContext = PackContext;
|
||||
/**
|
||||
* Configuration of toolsets utilized by electron-builder
|
||||
*/
|
||||
export interface ToolsetConfig {
|
||||
/**
|
||||
* `win-codesign` version to use for signing Windows artifacts.
|
||||
* Located at https://github.com/electron-userland/electron-builder-binaries/releases?q=win-codesign&expanded=true
|
||||
*
|
||||
* Stable:
|
||||
* v0.0.0 (winCodeSign)
|
||||
*
|
||||
* Beta:
|
||||
* Windows Kits 10.0.26100.0
|
||||
* v1.0.0, v1.1.0
|
||||
*
|
||||
* @default "0.0.0"
|
||||
*/
|
||||
readonly winCodeSign?: "0.0.0" | "1.0.0" | "1.1.0" | null;
|
||||
/**
|
||||
* `appimage` bundle version to use for Appimage packaging and runtime.
|
||||
* Located at https://github.com/electron-userland/electron-builder-binaries/releases?q=appimage&expanded=true
|
||||
* 0.0.0 - legacy toolset (appimage)
|
||||
*
|
||||
* Betas:
|
||||
* 1.0.2 - Runtime 20251108
|
||||
* 1.0.3 - Runtime 20251108 (Resolves GH issue #9598)
|
||||
*
|
||||
* @default "0.0.0"
|
||||
*/
|
||||
readonly appimage?: "0.0.0" | "1.0.2" | "1.0.3" | null;
|
||||
/**
|
||||
* `nsis` bundle version to use for NSIS installer compilation.
|
||||
* Located at https://github.com/electron-userland/electron-builder-binaries/releases?q=nsis&expanded=true
|
||||
* 0.0.0 - legacy toolset (nsis-3.0.4.1 + nsis-resources-3.4.1)
|
||||
*
|
||||
* Betas:
|
||||
* 1.2.1 - unified bundle (makensis 3.12 + plugins in one archive, entrypoint scripts auto-set NSISDIR)
|
||||
*
|
||||
* @default "0.0.0"
|
||||
*/
|
||||
readonly nsis?: "0.0.0" | "1.2.1" | null;
|
||||
/**
|
||||
* `wine` bundle version to use for running Windows tools on non-Windows platforms.
|
||||
* Located at https://github.com/electron-userland/electron-builder-binaries/releases?q=wine&expanded=true
|
||||
* 0.0.0 - legacy toolset (wine 4.0.1 portable; mac-only support)
|
||||
*
|
||||
* Beta:
|
||||
* 1.0.1 - Wine 11 bundle (unified wine binary, ia32 via WoW64)
|
||||
*
|
||||
* @default "0.0.0"
|
||||
*/
|
||||
readonly wine?: "0.0.0" | "1.0.1" | null;
|
||||
}
|
||||
export interface Hooks {
|
||||
/**
|
||||
* The function (or path to file or module id) to be run before pack.
|
||||
* Receives a {@link BeforePackContext}.
|
||||
*
|
||||
* Can be specified inline as a function in JavaScript configs:
|
||||
* ```js
|
||||
* // electron-builder.config.js
|
||||
* module.exports = {
|
||||
* beforePack: async (context) => {
|
||||
* // your code
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Or as a path to a module that exports the function as its default export:
|
||||
* ```json
|
||||
* { "build": { "beforePack": "./myBeforePackHook.js" } }
|
||||
* ```
|
||||
* ```js
|
||||
* // myBeforePackHook.js
|
||||
* exports.default = async function(context) {
|
||||
* // your custom code
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
readonly beforePack?: Hook<BeforePackContext, void> | string | null;
|
||||
/**
|
||||
* The function (or path to file or module id) to be run after the prebuilt Electron binary has been extracted to the output directory.
|
||||
* Receives an {@link AfterExtractContext}. For file/module setup, see {@link beforePack}.
|
||||
*/
|
||||
readonly afterExtract?: Hook<AfterExtractContext, void> | string | null;
|
||||
/**
|
||||
* The function (or path to file or module id) to be run after pack but before pack into distributable format and sign.
|
||||
* Receives an {@link AfterPackContext}. For file/module setup, see {@link beforePack}.
|
||||
*/
|
||||
readonly afterPack?: Hook<AfterPackContext, void> | string | null;
|
||||
/**
|
||||
* The function (or path to file or module id) to be run after pack and sign but before pack into distributable format.
|
||||
* Receives an {@link AfterPackContext}. For file/module setup, see {@link beforePack}.
|
||||
*/
|
||||
readonly afterSign?: Hook<AfterPackContext, void> | string | null;
|
||||
/**
|
||||
* The function (or path to file or module id) to be run when an individual artifact build starts.
|
||||
* Receives an {@link ArtifactBuildStarted}. For file/module setup, see {@link beforePack}.
|
||||
*/
|
||||
readonly artifactBuildStarted?: Hook<ArtifactBuildStarted, void> | string | null;
|
||||
/**
|
||||
* The function (or path to file or module id) to be run when an individual artifact build completes.
|
||||
* Receives an {@link ArtifactCreated}. For file/module setup, see {@link beforePack}.
|
||||
*/
|
||||
readonly artifactBuildCompleted?: Hook<ArtifactCreated, void> | string | null;
|
||||
/**
|
||||
* The function (or path to file or module id) to be run after all artifacts are built.
|
||||
* Receives a {@link BuildResult}. May return an array of additional file paths to publish.
|
||||
*
|
||||
* For file/module setup, see {@link beforePack}.
|
||||
*
|
||||
* @example
|
||||
* ```js
|
||||
* exports.default = function () {
|
||||
* // return additional files to publish
|
||||
* return ["/path/to/additional/result/file"]
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
readonly afterAllArtifactBuild?: Hook<BuildResult, Array<string>> | string | null;
|
||||
/**
|
||||
* The function (or path to file or module id) to be run after MSI project created on disk - not packed into .msi package yet.
|
||||
*/
|
||||
readonly msiProjectCreated?: Hook<string, void> | string | null;
|
||||
/**
|
||||
* The function (or path to file or module id) to be run after Appx manifest created on disk - not packed into .appx package yet.
|
||||
*/
|
||||
readonly appxManifestCreated?: Hook<string, void> | string | null;
|
||||
/**
|
||||
* The function (or path to file or module id) to be [run on each node module](#onnodemodulefile) file. Returning `true`/`false` will determine whether to force include or to use the default copier logic
|
||||
*/
|
||||
readonly onNodeModuleFile?: Hook<string, void | boolean> | string | null;
|
||||
/**
|
||||
* The function (or path to file or module id) to be run before dependencies are installed or rebuilt. Works when `npmRebuild` is set to `true`. Resolving to `false` will skip dependencies install or rebuild.
|
||||
*
|
||||
* If provided and `node_modules` are missing, it will not invoke production dependencies check.
|
||||
*/
|
||||
readonly beforeBuild?: Hook<BeforeBuildContext, boolean | void> | string | null;
|
||||
/**
|
||||
* The function (or path to file or module id) to be run when staging the electron artifact environment.
|
||||
* Returns the path to custom Electron build (e.g. `~/electron/out/R`) or folder of electron zips.
|
||||
*
|
||||
* Zip files must follow the pattern `electron-v${version}-${platformName}-${arch}.zip`, otherwise it will be assumed to be an unpacked Electron app directory
|
||||
*/
|
||||
readonly electronDist?: Hook<PrepareApplicationStageDirectoryOptions, string> | string | null;
|
||||
}
|
||||
export interface MetadataDirectories {
|
||||
/**
|
||||
* The path to build resources.
|
||||
|
|
@ -262,7 +459,7 @@ export interface MetadataDirectories {
|
|||
*/
|
||||
readonly buildResources?: string | null;
|
||||
/**
|
||||
* The output directory. [File macros](/file-patterns#file-macros) are supported.
|
||||
* The output directory. [File macros](https://www.electron.build/file-patterns#file-macros) are supported.
|
||||
* @default dist
|
||||
*/
|
||||
readonly output?: string | null;
|
||||
|
|
@ -271,4 +468,65 @@ export interface MetadataDirectories {
|
|||
*/
|
||||
readonly app?: string | null;
|
||||
}
|
||||
export {};
|
||||
/**
|
||||
* All options come from [@electron/fuses](https://github.com/electron/fuses)
|
||||
* Ref: https://raw.githubusercontent.com/electron/electron/refs/heads/main/docs/tutorial/fuses.md
|
||||
*/
|
||||
export interface FuseOptionsV1 {
|
||||
/**
|
||||
*The runAsNode fuse toggles whether the `ELECTRON_RUN_AS_NODE` environment variable is respected or not. Please note that if this fuse is disabled then `process.fork` in the main process will not function as expected as it depends on this environment variable to function. Instead, we recommend that you use [Utility Processes](https://github.com/electron/electron/blob/main/docs/api/utility-process.md), which work for many use cases where you need a standalone Node.js process (like a Sqlite server process or similar scenarios).
|
||||
*/
|
||||
runAsNode?: boolean;
|
||||
/**
|
||||
* The cookieEncryption fuse toggles whether the cookie store on disk is encrypted using OS level cryptography keys. By default the sqlite database that Chromium uses to store cookies stores the values in plaintext. If you wish to ensure your apps cookies are encrypted in the same way Chrome does then you should enable this fuse. Please note it is a one-way transition, if you enable this fuse existing unencrypted cookies will be encrypted-on-write but if you then disable the fuse again your cookie store will effectively be corrupt and useless. Most apps can safely enable this fuse.
|
||||
*/
|
||||
enableCookieEncryption?: boolean;
|
||||
/**
|
||||
* The nodeOptions fuse toggles whether the [`NODE_OPTIONS`](https://nodejs.org/api/cli.html#node_optionsoptions) and [`NODE_EXTRA_CA_CERTS`](https://github.com/nodejs/node/blob/main/doc/api/cli.md#node_extra_ca_certsfile) environment variables are respected. The `NODE_OPTIONS` environment variable can be used to pass all kinds of custom options to the Node.js runtime and isn't typically used by apps in production. Most apps can safely disable this fuse.
|
||||
*/
|
||||
enableNodeOptionsEnvironmentVariable?: boolean;
|
||||
/**
|
||||
* The nodeCliInspect fuse toggles whether the `--inspect`, `--inspect-brk`, etc. flags are respected or not. When disabled it also ensures that `SIGUSR1` signal does not initialize the main process inspector. Most apps can safely disable this fuse.
|
||||
*/
|
||||
enableNodeCliInspectArguments?: boolean;
|
||||
/**
|
||||
* The embeddedAsarIntegrityValidation fuse toggles an experimental feature on macOS that validates the content of the `app.asar` file when it is loaded. This feature is designed to have a minimal performance impact but may marginally slow down file reads from inside the `app.asar` archive.
|
||||
* Currently, ASAR integrity checking is supported on:
|
||||
*
|
||||
* - macOS as of electron>=16.0.0
|
||||
* - Windows as of electron>=30.0.0
|
||||
*
|
||||
* For more information on how to use asar integrity validation please read the [Asar Integrity](https://github.com/electron/electron/blob/main/docs/tutorial/asar-integrity.md) documentation.
|
||||
*/
|
||||
enableEmbeddedAsarIntegrityValidation?: boolean;
|
||||
/**
|
||||
* The onlyLoadAppFromAsar fuse changes the search system that Electron uses to locate your app code. By default Electron will search in the following order `app.asar` -> `app` -> `default_app.asar`. When this fuse is enabled the search order becomes a single entry `app.asar` thus ensuring that when combined with the `embeddedAsarIntegrityValidation` fuse it is impossible to load non-validated code.
|
||||
*/
|
||||
onlyLoadAppFromAsar?: boolean;
|
||||
/**
|
||||
* The loadBrowserProcessSpecificV8Snapshot fuse changes which V8 snapshot file is used for the browser process. By default Electron's processes will all use the same V8 snapshot file. When this fuse is enabled the browser process uses the file called `browser_v8_context_snapshot.bin` for its V8 snapshot. The other processes will use the V8 snapshot file that they normally do.
|
||||
*/
|
||||
loadBrowserProcessSpecificV8Snapshot?: boolean;
|
||||
/**
|
||||
* The grantFileProtocolExtraPrivileges fuse changes whether pages loaded from the `file://` protocol are given privileges beyond what they would receive in a traditional web browser. This behavior was core to Electron apps in original versions of Electron but is no longer required as apps should be [serving local files from custom protocols](https://github.com/electron/electron/blob/main/docs/tutorial/security.md#18-avoid-usage-of-the-file-protocol-and-prefer-usage-of-custom-protocols) now instead. If you aren't serving pages from `file://` you should disable this fuse.
|
||||
* The extra privileges granted to the `file://` protocol by this fuse are incompletely documented below:
|
||||
*
|
||||
* - `file://` protocol pages can use `fetch` to load other assets over `file://`
|
||||
* - `file://` protocol pages can use service workers
|
||||
* - `file://` protocol pages have universal access granted to child frames also running on `file://` protocols regardless of sandbox settings
|
||||
*/
|
||||
grantFileProtocolExtraPrivileges?: boolean;
|
||||
/**
|
||||
* Resets the app signature, specifically used for macOS.
|
||||
* Note: This should be unneeded since electron-builder signs the app directly after flipping the fuses.
|
||||
* Ref: https://github.com/electron/fuses?tab=readme-ov-file#apple-silicon
|
||||
*/
|
||||
resetAdHocDarwinSignature?: boolean;
|
||||
}
|
||||
export interface Concurrency {
|
||||
/**
|
||||
* The maximum number of concurrent jobs to run.
|
||||
* @default 1
|
||||
*/
|
||||
jobs: number;
|
||||
}
|
||||
|
|
|
|||
2
electron/node_modules/app-builder-lib/out/configuration.js.map
generated
vendored
2
electron/node_modules/app-builder-lib/out/configuration.js.map
generated
vendored
File diff suppressed because one or more lines are too long
18
electron/node_modules/app-builder-lib/out/core.d.ts
generated
vendored
18
electron/node_modules/app-builder-lib/out/core.d.ts
generated
vendored
|
|
@ -1,8 +1,7 @@
|
|||
/// <reference types="node" />
|
||||
import { Arch, ArchType } from "builder-util";
|
||||
import { AllPublishOptions } from "builder-util-runtime";
|
||||
export declare type Publish = AllPublishOptions | Array<AllPublishOptions> | null;
|
||||
export declare type TargetConfigType = Array<string | TargetConfiguration> | string | TargetConfiguration | null;
|
||||
import { Arch, ArchType, AsyncTaskManager } from "builder-util";
|
||||
import { AllPublishOptions, Nullish } from "builder-util-runtime";
|
||||
export type Publish = AllPublishOptions | Array<AllPublishOptions> | null;
|
||||
export type TargetConfigType = Array<string | TargetConfiguration> | string | TargetConfiguration | null;
|
||||
export interface TargetConfiguration {
|
||||
/**
|
||||
* The target name. e.g. `snap`.
|
||||
|
|
@ -30,22 +29,23 @@ export declare abstract class Target {
|
|||
readonly name: string;
|
||||
readonly isAsyncSupported: boolean;
|
||||
abstract readonly outDir: string;
|
||||
abstract readonly options: TargetSpecificOptions | null | undefined;
|
||||
protected constructor(name: string, isAsyncSupported?: boolean);
|
||||
abstract readonly options: TargetSpecificOptions | Nullish;
|
||||
readonly buildQueueManager: AsyncTaskManager;
|
||||
constructor(name: string, isAsyncSupported?: boolean);
|
||||
checkOptions(): Promise<any>;
|
||||
abstract build(appOutDir: string, arch: Arch): Promise<any>;
|
||||
finishBuild(): Promise<any>;
|
||||
}
|
||||
export interface TargetSpecificOptions {
|
||||
/**
|
||||
The [artifact file name template](/configuration/configuration#artifact-file-name-template).
|
||||
The [artifact file name template](https://www.electron.build/configuration#artifact-file-name-template).
|
||||
*/
|
||||
readonly artifactName?: string | null;
|
||||
publish?: Publish;
|
||||
}
|
||||
export declare const DEFAULT_TARGET = "default";
|
||||
export declare const DIR_TARGET = "dir";
|
||||
export declare type CompressionLevel = "store" | "normal" | "maximum";
|
||||
export type CompressionLevel = "store" | "normal" | "maximum";
|
||||
export interface BeforeBuildContext {
|
||||
readonly appDir: string;
|
||||
readonly electronVersion: string;
|
||||
|
|
|
|||
9
electron/node_modules/app-builder-lib/out/core.js
generated
vendored
9
electron/node_modules/app-builder-lib/out/core.js
generated
vendored
|
|
@ -2,6 +2,7 @@
|
|||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.DIR_TARGET = exports.DEFAULT_TARGET = exports.Target = exports.Platform = void 0;
|
||||
const builder_util_1 = require("builder-util");
|
||||
const builder_util_runtime_1 = require("builder-util-runtime");
|
||||
class Platform {
|
||||
constructor(name, buildConfigurationKey, nodeName) {
|
||||
this.name = name;
|
||||
|
|
@ -16,7 +17,7 @@ class Platform {
|
|||
return new Map([[this, new Map()]]);
|
||||
}
|
||||
const archToType = new Map();
|
||||
for (const arch of archs == null || archs.length === 0 ? [builder_util_1.archFromString(process.arch)] : archs) {
|
||||
for (const arch of archs == null || archs.length === 0 ? [(0, builder_util_1.archFromString)(process.arch)] : archs) {
|
||||
archToType.set(arch, type == null ? [] : Array.isArray(type) ? type : [type]);
|
||||
}
|
||||
return new Map([[this, archToType]]);
|
||||
|
|
@ -49,12 +50,14 @@ class Target {
|
|||
constructor(name, isAsyncSupported = true) {
|
||||
this.name = name;
|
||||
this.isAsyncSupported = isAsyncSupported;
|
||||
// use only for tasks that cannot be executed in parallel (such as signing on windows and hdiutil on macOS due to file locking)
|
||||
this.buildQueueManager = new builder_util_1.AsyncTaskManager(new builder_util_runtime_1.CancellationToken());
|
||||
}
|
||||
async checkOptions() {
|
||||
// ignore
|
||||
}
|
||||
finishBuild() {
|
||||
return Promise.resolve();
|
||||
async finishBuild() {
|
||||
await this.buildQueueManager.awaitTasks();
|
||||
}
|
||||
}
|
||||
exports.Target = Target;
|
||||
|
|
|
|||
2
electron/node_modules/app-builder-lib/out/core.js.map
generated
vendored
2
electron/node_modules/app-builder-lib/out/core.js.map
generated
vendored
File diff suppressed because one or more lines are too long
23
electron/node_modules/app-builder-lib/out/electron/ElectronFramework.d.ts
generated
vendored
23
electron/node_modules/app-builder-lib/out/electron/ElectronFramework.d.ts
generated
vendored
|
|
@ -1,7 +1,9 @@
|
|||
import { Configuration } from "../configuration";
|
||||
import { Framework } from "../Framework";
|
||||
import { Packager } from "../index";
|
||||
export declare type ElectronPlatformName = "darwin" | "linux" | "win32" | "mas";
|
||||
import { ElectronDownloadOptions } from "../util/electronGet";
|
||||
export { ElectronDownloadOptions };
|
||||
export type ElectronPlatformName = "darwin" | "linux" | "win32" | "mas";
|
||||
/**
|
||||
* Electron distributables branding options.
|
||||
* @see [Electron BRANDING.json](https://github.com/electron/electron/blob/master/shell/app/BRANDING.json).
|
||||
|
|
@ -11,23 +13,4 @@ export interface ElectronBrandingOptions {
|
|||
productName?: string;
|
||||
}
|
||||
export declare function createBrandingOpts(opts: Configuration): Required<ElectronBrandingOptions>;
|
||||
export interface ElectronDownloadOptions {
|
||||
version?: string;
|
||||
/**
|
||||
* The [cache location](https://github.com/electron-userland/electron-download#cache-location).
|
||||
*/
|
||||
cache?: string | null;
|
||||
/**
|
||||
* The mirror.
|
||||
*/
|
||||
mirror?: string | null;
|
||||
/** @private */
|
||||
customDir?: string | null;
|
||||
/** @private */
|
||||
customFilename?: string | null;
|
||||
strictSSL?: boolean;
|
||||
isVerifyChecksum?: boolean;
|
||||
platform?: ElectronPlatformName;
|
||||
arch?: string;
|
||||
}
|
||||
export declare function createElectronFrameworkSupport(configuration: Configuration, packager: Packager): Promise<Framework>;
|
||||
|
|
|
|||
223
electron/node_modules/app-builder-lib/out/electron/ElectronFramework.js
generated
vendored
223
electron/node_modules/app-builder-lib/out/electron/ElectronFramework.js
generated
vendored
|
|
@ -1,18 +1,19 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createElectronFrameworkSupport = exports.createBrandingOpts = void 0;
|
||||
const bluebird_lst_1 = require("bluebird-lst");
|
||||
exports.createBrandingOpts = createBrandingOpts;
|
||||
exports.createElectronFrameworkSupport = createElectronFrameworkSupport;
|
||||
const builder_util_1 = require("builder-util");
|
||||
const fs_1 = require("builder-util/out/fs");
|
||||
const fs_extra_1 = require("fs-extra");
|
||||
const lazy_val_1 = require("lazy-val");
|
||||
const path = require("path");
|
||||
const tiny_async_pool_1 = require("tiny-async-pool");
|
||||
const index_1 = require("../index");
|
||||
const platformPackager_1 = require("../platformPackager");
|
||||
const pathManager_1 = require("../util/pathManager");
|
||||
const resolve_1 = require("../util/resolve");
|
||||
const electronGet_1 = require("../util/electronGet");
|
||||
const electronMac_1 = require("./electronMac");
|
||||
const electronVersion_1 = require("./electronVersion");
|
||||
const fs = require("fs/promises");
|
||||
const electronWin_1 = require("./electronWin");
|
||||
const injectFFMPEG_1 = require("./injectFFMPEG");
|
||||
function createBrandingOpts(opts) {
|
||||
var _a, _b;
|
||||
return {
|
||||
|
|
@ -20,56 +21,89 @@ function createBrandingOpts(opts) {
|
|||
productName: ((_b = opts.electronBranding) === null || _b === void 0 ? void 0 : _b.productName) || "Electron",
|
||||
};
|
||||
}
|
||||
exports.createBrandingOpts = createBrandingOpts;
|
||||
function createDownloadOpts(opts, platform, arch, electronVersion) {
|
||||
return {
|
||||
platform,
|
||||
arch,
|
||||
version: electronVersion,
|
||||
...opts.electronDownload,
|
||||
};
|
||||
var _a;
|
||||
const base = { platform, arch, version: electronVersion };
|
||||
const dl = opts.electronDownload;
|
||||
if (dl == null) {
|
||||
return base;
|
||||
}
|
||||
if (Object.hasOwnProperty.call(dl, "mirrorOptions")) {
|
||||
// ElectronGetOptions: flatten mirrorOptions.mirror for the app-builder binary
|
||||
const { mirrorOptions } = dl;
|
||||
return { ...base, mirror: (_a = mirrorOptions === null || mirrorOptions === void 0 ? void 0 : mirrorOptions.mirror) !== null && _a !== void 0 ? _a : undefined };
|
||||
}
|
||||
return { ...base, ...dl };
|
||||
}
|
||||
async function beforeCopyExtraFiles(options) {
|
||||
const packager = options.packager;
|
||||
const appOutDir = options.appOutDir;
|
||||
const { appOutDir, packager } = options;
|
||||
const electronBranding = createBrandingOpts(packager.config);
|
||||
if (packager.platform === index_1.Platform.LINUX) {
|
||||
if (!platformPackager_1.isSafeToUnpackElectronOnRemoteBuildServer(packager)) {
|
||||
const linuxPackager = packager;
|
||||
const executable = path.join(appOutDir, linuxPackager.executableName);
|
||||
await fs_extra_1.rename(path.join(appOutDir, electronBranding.projectName), executable);
|
||||
}
|
||||
const linuxPackager = packager;
|
||||
const executable = path.join(appOutDir, linuxPackager.executableName);
|
||||
await (0, fs_extra_1.rename)(path.join(appOutDir, electronBranding.projectName), executable);
|
||||
}
|
||||
else if (packager.platform === index_1.Platform.WINDOWS) {
|
||||
const executable = path.join(appOutDir, `${packager.appInfo.productFilename}.exe`);
|
||||
await fs_extra_1.rename(path.join(appOutDir, `${electronBranding.projectName}.exe`), executable);
|
||||
await (0, fs_extra_1.rename)(path.join(appOutDir, `${electronBranding.projectName}.exe`), executable);
|
||||
if (options.asarIntegrity) {
|
||||
await (0, electronWin_1.addWinAsarIntegrity)(executable, options.asarIntegrity);
|
||||
}
|
||||
}
|
||||
else {
|
||||
await electronMac_1.createMacApp(packager, appOutDir, options.asarIntegrity, options.platformName === "mas");
|
||||
const wantedLanguages = builder_util_1.asArray(packager.platformSpecificBuildOptions.electronLanguages);
|
||||
if (wantedLanguages.length === 0) {
|
||||
return;
|
||||
await (0, electronMac_1.createMacApp)(packager, appOutDir, options.asarIntegrity, options.platformName === "mas");
|
||||
}
|
||||
await removeUnusedLanguagesIfNeeded(options);
|
||||
}
|
||||
async function removeUnusedLanguagesIfNeeded(options) {
|
||||
const { packager, appOutDir } = options;
|
||||
const { config, platformSpecificBuildOptions, platform } = packager;
|
||||
const getLocalesConfig = () => {
|
||||
if (platform === index_1.Platform.MAC) {
|
||||
return { dirs: [packager.getResourcesDir(appOutDir), packager.getMacOsElectronFrameworkResourcesDir(appOutDir)], langFileExt: ".lproj" };
|
||||
}
|
||||
// noinspection SpellCheckingInspection
|
||||
const langFileExt = ".lproj";
|
||||
const resourcesDir = packager.getResourcesDir(appOutDir);
|
||||
await bluebird_lst_1.default.map(fs_extra_1.readdir(resourcesDir), file => {
|
||||
if (!file.endsWith(langFileExt)) {
|
||||
return { dirs: [path.join(packager.getResourcesDir(appOutDir), "..", "locales")], langFileExt: ".pak" };
|
||||
};
|
||||
const wantedLanguages = (0, builder_util_1.asArray)(platformSpecificBuildOptions.electronLanguages || config.electronLanguages)
|
||||
.map(it => it.trim().toLowerCase())
|
||||
.filter(it => it.length > 0);
|
||||
if (!wantedLanguages.length) {
|
||||
return;
|
||||
}
|
||||
const { dirs, langFileExt } = getLocalesConfig();
|
||||
// noinspection SpellCheckingInspection
|
||||
const deleteNonMatchedLanguages = async (dir) => {
|
||||
const files = await (0, fs_extra_1.readdir)(dir);
|
||||
return files.map(async (file) => {
|
||||
if (path.extname(file) !== langFileExt) {
|
||||
return;
|
||||
}
|
||||
const language = file.substring(0, file.length - langFileExt.length);
|
||||
if (!wantedLanguages.includes(language)) {
|
||||
return fs.rm(path.join(resourcesDir, file), { recursive: true, force: true });
|
||||
const language = path.basename(file, langFileExt).toLowerCase();
|
||||
const isWantedLocale = wantedLanguages.some(wantedLanguage =>
|
||||
// exact file
|
||||
wantedLanguage === language ||
|
||||
// prefix (e.g. "en" matches "en-US")
|
||||
wantedLanguage.startsWith(`${language}-`) ||
|
||||
// prefix (e.g. "en" matches "en_US")
|
||||
wantedLanguage.startsWith(`${language}_`));
|
||||
if (isWantedLocale) {
|
||||
return undefined;
|
||||
}
|
||||
return;
|
||||
}, fs_1.CONCURRENCY);
|
||||
return (0, fs_extra_1.rm)(path.join(dir, file), { recursive: true, force: true });
|
||||
});
|
||||
};
|
||||
const allDeletedFiles = (await Promise.all(dirs.map(deleteNonMatchedLanguages))).flat().filter((it) => it != null);
|
||||
if (allDeletedFiles.length === 0) {
|
||||
builder_util_1.log.warn({ electronLanguages: wantedLanguages }, "no locales found matching wanted languages, skipping cleanup");
|
||||
return;
|
||||
}
|
||||
await (0, tiny_async_pool_1.default)(builder_util_1.MAX_FILE_REQUESTS, allDeletedFiles, it => it);
|
||||
}
|
||||
class ElectronFramework {
|
||||
constructor(name, version, distMacOsAppName) {
|
||||
constructor(name, version, macOsProductName) {
|
||||
this.name = name;
|
||||
this.version = version;
|
||||
this.distMacOsAppName = distMacOsAppName;
|
||||
this.macOsProductName = macOsProductName;
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
this.macOsDefaultTargets = ["zip", "dmg"];
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
|
|
@ -79,17 +113,26 @@ class ElectronFramework {
|
|||
// noinspection JSUnusedGlobalSymbols
|
||||
this.isNpmRebuildRequired = true;
|
||||
}
|
||||
get distMacOsAppName() {
|
||||
return `${this.macOsProductName}.app`;
|
||||
}
|
||||
getDefaultIcon(platform) {
|
||||
if (platform === index_1.Platform.LINUX) {
|
||||
return path.join(pathManager_1.getTemplatePath("icons"), "electron-linux");
|
||||
return path.join((0, pathManager_1.getTemplatePath)("icons"), "electron-linux");
|
||||
}
|
||||
else {
|
||||
// default icon is embedded into app skeleton
|
||||
return null;
|
||||
}
|
||||
}
|
||||
prepareApplicationStageDirectory(options) {
|
||||
return unpack(options, createDownloadOpts(options.packager.config, options.platformName, options.arch, this.version), this.distMacOsAppName);
|
||||
async prepareApplicationStageDirectory(options) {
|
||||
const downloadOptions = createDownloadOpts(options.packager.config, options.platformName, options.arch, this.version);
|
||||
const shouldCleanup = await unpack(options, downloadOptions, this.distMacOsAppName);
|
||||
await cleanupAfterUnpack(options, this.distMacOsAppName, shouldCleanup);
|
||||
if (options.packager.config.downloadAlternateFFmpeg) {
|
||||
const injector = new injectFFMPEG_1.FFMPEGInjector(options, this.version, createBrandingOpts(options.packager.config));
|
||||
await injector.inject();
|
||||
}
|
||||
}
|
||||
beforeCopyExtraFiles(options) {
|
||||
return beforeCopyExtraFiles(options);
|
||||
|
|
@ -100,62 +143,98 @@ async function createElectronFrameworkSupport(configuration, packager) {
|
|||
if (version == null) {
|
||||
// for prepacked app asar no dev deps in the app.asar
|
||||
if (packager.isPrepackedAppAsar) {
|
||||
version = await electronVersion_1.getElectronVersionFromInstalled(packager.projectDir);
|
||||
version = await (0, electronVersion_1.getElectronVersionFromInstalled)(packager.projectDir);
|
||||
if (version == null) {
|
||||
throw new Error(`Cannot compute electron version for prepacked asar`);
|
||||
}
|
||||
}
|
||||
else {
|
||||
version = await electronVersion_1.computeElectronVersion(packager.projectDir, new lazy_val_1.Lazy(() => Promise.resolve(packager.metadata)));
|
||||
version = await (0, electronVersion_1.computeElectronVersion)(packager.projectDir);
|
||||
}
|
||||
configuration.electronVersion = version;
|
||||
}
|
||||
const branding = createBrandingOpts(configuration);
|
||||
return new ElectronFramework(branding.projectName, version, `${branding.productName}.app`);
|
||||
return new ElectronFramework(branding.projectName, version, branding.productName);
|
||||
}
|
||||
exports.createElectronFrameworkSupport = createElectronFrameworkSupport;
|
||||
async function unpack(prepareOptions, options, distMacOsAppName) {
|
||||
/**
|
||||
* Unpacks a custom or default Electron distribution into the app output directory.
|
||||
*/
|
||||
async function unpack(prepareOptions, downloadOptions, _distMacOsAppName) {
|
||||
var _a, _b, _c;
|
||||
async function selectElectron(filepath) {
|
||||
const resolvedDist = path.isAbsolute(filepath) ? filepath : path.resolve(packager.projectDir, filepath);
|
||||
const electronDistStats = await (0, builder_util_1.statOrNull)(resolvedDist);
|
||||
if (!electronDistStats) {
|
||||
throw new Error(`The specified electronDist does not exist: ${resolvedDist}. Please provide a valid path to the Electron zip file, cache directory, or electron build directory.`);
|
||||
}
|
||||
if (resolvedDist.endsWith(".zip")) {
|
||||
builder_util_1.log.info({ zipFile: resolvedDist }, "using custom electronDist zip file");
|
||||
await (0, electronGet_1.extractArchive)(resolvedDist, appOutDir);
|
||||
return false; // do not clean up after unpacking, it's a custom bundle and we should respect its configuration/contents as required
|
||||
}
|
||||
if (electronDistStats.isDirectory()) {
|
||||
// backward compatibility: if electronDist is a directory, check for the default zip file inside it
|
||||
const files = await (0, fs_extra_1.readdir)(resolvedDist);
|
||||
if (files.includes(defaultZipName)) {
|
||||
builder_util_1.log.info({ electronDist: builder_util_1.log.filePath(resolvedDist) }, "using custom electronDist directory");
|
||||
await (0, electronGet_1.extractArchive)(path.join(resolvedDist, defaultZipName), appOutDir);
|
||||
return false; // do not clean up after unpacking, it's a custom bundle and we should respect its configuration/contents as required
|
||||
}
|
||||
// if we reach here, it means the provided electronDist is neither a zip file nor a directory with the default zip file
|
||||
// e.g. we treat it as a custom already-unpacked Electron distribution
|
||||
builder_util_1.log.info({ electronDist: builder_util_1.log.filePath(resolvedDist) }, "using custom unpacked Electron distribution");
|
||||
const source = packager.getElectronSrcDir(resolvedDist);
|
||||
const destination = packager.getElectronDestinationDir(prepareOptions.appOutDir);
|
||||
builder_util_1.log.info({ source, destination }, "copying unpacked Electron");
|
||||
await (0, fs_extra_1.emptyDir)(prepareOptions.appOutDir);
|
||||
await (0, builder_util_1.copyDir)(source, destination, {
|
||||
isUseHardLink: builder_util_1.DO_NOT_USE_HARD_LINKS,
|
||||
});
|
||||
return false;
|
||||
}
|
||||
throw new Error(`The specified electronDist is neither a zip file nor a directory: ${resolvedDist}. Please provide a valid path to the Electron zip file or cache directory.`);
|
||||
}
|
||||
const { packager, appOutDir, platformName } = prepareOptions;
|
||||
const { version, arch } = downloadOptions;
|
||||
const defaultZipName = `electron-v${version}-${platformName}-${arch}.zip`;
|
||||
const electronDist = packager.config.electronDist;
|
||||
let dist = typeof electronDist === "function" ? electronDist(prepareOptions) : electronDist;
|
||||
if (dist != null) {
|
||||
const zipFile = `electron-v${options.version}-${platformName}-${options.arch}.zip`;
|
||||
const resolvedDist = path.isAbsolute(dist) ? dist : path.resolve(packager.projectDir, dist);
|
||||
if ((await fs_1.statOrNull(path.join(resolvedDist, zipFile))) != null) {
|
||||
builder_util_1.log.info({ resolvedDist, zipFile }, "Resolved electronDist");
|
||||
options.cache = resolvedDist;
|
||||
dist = null;
|
||||
}
|
||||
if (typeof electronDist === "string" && !(0, builder_util_1.isEmptyOrSpaces)(electronDist)) {
|
||||
return selectElectron(electronDist);
|
||||
}
|
||||
let isFullCleanup = false;
|
||||
if (dist == null) {
|
||||
if (platformPackager_1.isSafeToUnpackElectronOnRemoteBuildServer(packager)) {
|
||||
return;
|
||||
}
|
||||
await builder_util_1.executeAppBuilder(["unpack-electron", "--configuration", JSON.stringify([options]), "--output", appOutDir, "--distMacOsAppName", distMacOsAppName]);
|
||||
let resolvedDist = null;
|
||||
try {
|
||||
const electronDistHook = await (0, resolve_1.resolveFunction)(packager.appInfo.type, electronDist, "electronDist", await packager.info.getWorkspaceRoot());
|
||||
resolvedDist = typeof electronDistHook === "function" ? await Promise.resolve(electronDistHook(prepareOptions)) : electronDistHook;
|
||||
}
|
||||
else {
|
||||
isFullCleanup = true;
|
||||
const source = packager.getElectronSrcDir(dist);
|
||||
const destination = packager.getElectronDestinationDir(appOutDir);
|
||||
builder_util_1.log.info({ source, destination }, "copying Electron");
|
||||
await fs_extra_1.emptyDir(appOutDir);
|
||||
await fs_1.copyDir(source, destination, {
|
||||
isUseHardLink: fs_1.DO_NOT_USE_HARD_LINKS,
|
||||
catch (error) {
|
||||
builder_util_1.log.warn({ error }, "Failed to resolve electronDist, using default unpack logic");
|
||||
}
|
||||
if (resolvedDist == null) {
|
||||
// if no custom electronDist is provided, use the default unpack logic
|
||||
builder_util_1.log.debug(null, "no custom electronDist provided, unpacking default Electron distribution");
|
||||
const zipPath = await (0, electronGet_1.downloadElectronArtifactZip)({
|
||||
electronDownload: downloadOptions,
|
||||
artifactName: "electron",
|
||||
platformName: (_a = downloadOptions.platform) !== null && _a !== void 0 ? _a : prepareOptions.platformName,
|
||||
arch: (_b = downloadOptions.arch) !== null && _b !== void 0 ? _b : prepareOptions.arch,
|
||||
version: (_c = downloadOptions.version) !== null && _c !== void 0 ? _c : prepareOptions.version,
|
||||
});
|
||||
await (0, electronGet_1.extractArchive)(zipPath, appOutDir);
|
||||
builder_util_1.log.info({ output: appOutDir }, "downloaded electron zip extracted successfully");
|
||||
return true; // indicates that we should clean up after unpacking
|
||||
}
|
||||
await cleanupAfterUnpack(prepareOptions, distMacOsAppName, isFullCleanup);
|
||||
return selectElectron(resolvedDist);
|
||||
}
|
||||
function cleanupAfterUnpack(prepareOptions, distMacOsAppName, isFullCleanup) {
|
||||
const out = prepareOptions.appOutDir;
|
||||
const isMac = prepareOptions.packager.platform === index_1.Platform.MAC;
|
||||
const resourcesPath = isMac ? path.join(out, distMacOsAppName, "Contents", "Resources") : path.join(out, "resources");
|
||||
return Promise.all([
|
||||
isFullCleanup ? fs_1.unlinkIfExists(path.join(resourcesPath, "default_app.asar")) : Promise.resolve(),
|
||||
isFullCleanup ? fs_1.unlinkIfExists(path.join(out, "version")) : Promise.resolve(),
|
||||
isFullCleanup ? (0, builder_util_1.unlinkIfExists)(path.join(resourcesPath, "default_app.asar")) : Promise.resolve(),
|
||||
isFullCleanup ? (0, builder_util_1.unlinkIfExists)(path.join(out, "version")) : Promise.resolve(),
|
||||
isMac
|
||||
? Promise.resolve()
|
||||
: fs_extra_1.rename(path.join(out, "LICENSE"), path.join(out, "LICENSE.electron.txt")).catch(() => {
|
||||
: (0, fs_extra_1.rename)(path.join(out, "LICENSE"), path.join(out, "LICENSE.electron.txt")).catch(() => {
|
||||
/* ignore */
|
||||
}),
|
||||
]);
|
||||
|
|
|
|||
2
electron/node_modules/app-builder-lib/out/electron/ElectronFramework.js.map
generated
vendored
2
electron/node_modules/app-builder-lib/out/electron/ElectronFramework.js.map
generated
vendored
File diff suppressed because one or more lines are too long
153
electron/node_modules/app-builder-lib/out/electron/electronMac.js
generated
vendored
153
electron/node_modules/app-builder-lib/out/electron/electronMac.js
generated
vendored
|
|
@ -1,23 +1,22 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createMacApp = void 0;
|
||||
const bluebird_lst_1 = require("bluebird-lst");
|
||||
exports.createMacApp = createMacApp;
|
||||
const builder_util_1 = require("builder-util");
|
||||
const fs_1 = require("builder-util/out/fs");
|
||||
const promises_1 = require("fs/promises");
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
const appInfo_1 = require("../appInfo");
|
||||
const platformPackager_1 = require("../platformPackager");
|
||||
const appBuilder_1 = require("../util/appBuilder");
|
||||
const plist_1 = require("../util/plist");
|
||||
const ElectronFramework_1 = require("./ElectronFramework");
|
||||
function doRename(basePath, oldName, newName) {
|
||||
return promises_1.rename(path.join(basePath, oldName), path.join(basePath, newName));
|
||||
return (0, promises_1.rename)(path.join(basePath, oldName), path.join(basePath, newName));
|
||||
}
|
||||
function moveHelpers(helperSuffixes, frameworksPath, appName, prefix) {
|
||||
return bluebird_lst_1.default.map(helperSuffixes, suffix => {
|
||||
return Promise.all(helperSuffixes.map(suffix => {
|
||||
const executableBasePath = path.join(frameworksPath, `${prefix}${suffix}.app`, "Contents", "MacOS");
|
||||
return doRename(executableBasePath, `${prefix}${suffix}`, appName + suffix).then(() => doRename(frameworksPath, `${prefix}${suffix}.app`, `${appName}${suffix}.app`));
|
||||
});
|
||||
}));
|
||||
}
|
||||
function getAvailableHelperSuffixes(helperEHPlist, helperNPPlist, helperRendererPlist, helperPluginPlist, helperGPUPlist) {
|
||||
const result = [" Helper"];
|
||||
|
|
@ -40,9 +39,13 @@ function getAvailableHelperSuffixes(helperEHPlist, helperNPPlist, helperRenderer
|
|||
}
|
||||
/** @internal */
|
||||
async function createMacApp(packager, appOutDir, asarIntegrity, isMas) {
|
||||
var _a, _b;
|
||||
const appInfo = packager.appInfo;
|
||||
const appFilename = appInfo.productFilename;
|
||||
const electronBranding = ElectronFramework_1.createBrandingOpts(packager.config);
|
||||
// Electon uses the application name (CFBundleName) to resolve helper apps
|
||||
// https://github.com/electron/electron/blob/main/shell/app/electron_main_delegate_mac.mm
|
||||
// https://github.com/electron-userland/electron-builder/issues/6962
|
||||
const appFilename = appInfo.sanitizedProductName;
|
||||
const electronBranding = (0, ElectronFramework_1.createBrandingOpts)(packager.config);
|
||||
const contentsPath = path.join(appOutDir, packager.info.framework.distMacOsAppName, "Contents");
|
||||
const frameworksPath = path.join(contentsPath, "Frameworks");
|
||||
const loginItemPath = path.join(contentsPath, "Library", "LoginItems");
|
||||
|
|
@ -54,40 +57,24 @@ async function createMacApp(packager, appOutDir, asarIntegrity, isMas) {
|
|||
const helperPluginPlistFilename = path.join(frameworksPath, `${electronBranding.productName} Helper (Plugin).app`, "Contents", "Info.plist");
|
||||
const helperGPUPlistFilename = path.join(frameworksPath, `${electronBranding.productName} Helper (GPU).app`, "Contents", "Info.plist");
|
||||
const helperLoginPlistFilename = path.join(loginItemPath, `${electronBranding.productName} Login Helper.app`, "Contents", "Info.plist");
|
||||
const plistContent = await appBuilder_1.executeAppBuilderAsJson([
|
||||
"decode-plist",
|
||||
"-f",
|
||||
appPlistFilename,
|
||||
"-f",
|
||||
helperPlistFilename,
|
||||
"-f",
|
||||
helperEHPlistFilename,
|
||||
"-f",
|
||||
helperNPPlistFilename,
|
||||
"-f",
|
||||
helperRendererPlistFilename,
|
||||
"-f",
|
||||
helperPluginPlistFilename,
|
||||
"-f",
|
||||
helperGPUPlistFilename,
|
||||
"-f",
|
||||
helperLoginPlistFilename,
|
||||
]);
|
||||
if (plistContent[0] == null) {
|
||||
const safeParsePlistFile = async (filePath) => {
|
||||
if (!fs.existsSync(filePath)) {
|
||||
return null;
|
||||
}
|
||||
return await (0, plist_1.parsePlistFile)(filePath);
|
||||
};
|
||||
const appPlist = (await safeParsePlistFile(appPlistFilename));
|
||||
if (appPlist == null) {
|
||||
throw new Error("corrupted Electron dist");
|
||||
}
|
||||
const appPlist = plistContent[0];
|
||||
const helperPlist = plistContent[1];
|
||||
const helperEHPlist = plistContent[2];
|
||||
const helperNPPlist = plistContent[3];
|
||||
const helperRendererPlist = plistContent[4];
|
||||
const helperPluginPlist = plistContent[5];
|
||||
const helperGPUPlist = plistContent[6];
|
||||
const helperLoginPlist = plistContent[7];
|
||||
// if an extend-info file was supplied, copy its contents in first
|
||||
if (plistContent[8] != null) {
|
||||
Object.assign(appPlist, plistContent[8]);
|
||||
}
|
||||
// Replace the multiple parsePlistFile calls with:
|
||||
const helperPlist = await safeParsePlistFile(helperPlistFilename);
|
||||
const helperEHPlist = await safeParsePlistFile(helperEHPlistFilename);
|
||||
const helperNPPlist = await safeParsePlistFile(helperNPPlistFilename);
|
||||
const helperRendererPlist = await safeParsePlistFile(helperRendererPlistFilename);
|
||||
const helperPluginPlist = await safeParsePlistFile(helperPluginPlistFilename);
|
||||
const helperGPUPlist = await safeParsePlistFile(helperGPUPlistFilename);
|
||||
const helperLoginPlist = await safeParsePlistFile(helperLoginPlistFilename);
|
||||
const buildMetadata = packager.config;
|
||||
/**
|
||||
* Configure bundleIdentifier for the generic Electron Helper process
|
||||
|
|
@ -99,16 +86,22 @@ async function createMacApp(packager, appOutDir, asarIntegrity, isMas) {
|
|||
if (oldHelperBundleId != null) {
|
||||
builder_util_1.log.warn("build.helper-bundle-id is deprecated, please set as build.mac.helperBundleId");
|
||||
}
|
||||
const helperBundleIdentifier = appInfo_1.filterCFBundleIdentifier(packager.platformSpecificBuildOptions.helperBundleId || oldHelperBundleId || `${appInfo.macBundleIdentifier}.helper`);
|
||||
const defaultAppId = packager.platformSpecificBuildOptions.appId;
|
||||
const cfBundleIdentifier = (0, appInfo_1.filterCFBundleIdentifier)((isMas ? (_a = packager.config.mas) === null || _a === void 0 ? void 0 : _a.appId : defaultAppId) || defaultAppId || appInfo.macBundleIdentifier);
|
||||
const defaultHelperId = packager.platformSpecificBuildOptions.helperBundleId;
|
||||
const helperBundleIdentifier = (0, appInfo_1.filterCFBundleIdentifier)((isMas ? (_b = packager.config.mas) === null || _b === void 0 ? void 0 : _b.helperBundleId : defaultHelperId) || defaultHelperId || oldHelperBundleId || `${cfBundleIdentifier}.helper`);
|
||||
appPlist.CFBundleIdentifier = cfBundleIdentifier;
|
||||
await packager.applyCommonInfo(appPlist, contentsPath);
|
||||
// required for electron-updater proxy
|
||||
if (!isMas) {
|
||||
configureLocalhostAts(appPlist);
|
||||
}
|
||||
helperPlist.CFBundleExecutable = `${appFilename} Helper`;
|
||||
helperPlist.CFBundleDisplayName = `${appInfo.productName} Helper`;
|
||||
helperPlist.CFBundleIdentifier = helperBundleIdentifier;
|
||||
helperPlist.CFBundleVersion = appPlist.CFBundleVersion;
|
||||
if (helperPlist != null) {
|
||||
helperPlist.CFBundleExecutable = `${appFilename} Helper`;
|
||||
helperPlist.CFBundleDisplayName = `${appInfo.productName} Helper`;
|
||||
helperPlist.CFBundleIdentifier = helperBundleIdentifier;
|
||||
helperPlist.CFBundleVersion = appPlist.CFBundleVersion;
|
||||
}
|
||||
/**
|
||||
* Configure bundleIdentifier for Electron 5+ Helper processes
|
||||
*
|
||||
|
|
@ -121,8 +114,8 @@ async function createMacApp(packager, appOutDir, asarIntegrity, isMas) {
|
|||
helper.CFBundleExecutable = `${appFilename} Helper ${postfix}`;
|
||||
helper.CFBundleDisplayName = `${appInfo.productName} Helper ${postfix}`;
|
||||
helper.CFBundleIdentifier = userProvidedBundleIdentifier
|
||||
? appInfo_1.filterCFBundleIdentifier(userProvidedBundleIdentifier)
|
||||
: appInfo_1.filterCFBundleIdentifier(`${helperBundleIdentifier}.${postfix}`);
|
||||
? (0, appInfo_1.filterCFBundleIdentifier)(userProvidedBundleIdentifier)
|
||||
: (0, appInfo_1.filterCFBundleIdentifier)(`${helperBundleIdentifier}.${postfix}`);
|
||||
helper.CFBundleVersion = appPlist.CFBundleVersion;
|
||||
}
|
||||
if (helperRendererPlist != null) {
|
||||
|
|
@ -144,13 +137,13 @@ async function createMacApp(packager, appOutDir, asarIntegrity, isMas) {
|
|||
helperLoginPlist.CFBundleExecutable = `${appFilename} Login Helper`;
|
||||
helperLoginPlist.CFBundleDisplayName = `${appInfo.productName} Login Helper`;
|
||||
// noinspection SpellCheckingInspection
|
||||
helperLoginPlist.CFBundleIdentifier = `${appInfo.macBundleIdentifier}.loginhelper`;
|
||||
helperLoginPlist.CFBundleIdentifier = `${cfBundleIdentifier}.loginhelper`;
|
||||
helperLoginPlist.CFBundleVersion = appPlist.CFBundleVersion;
|
||||
}
|
||||
const protocols = builder_util_1.asArray(buildMetadata.protocols).concat(builder_util_1.asArray(packager.platformSpecificBuildOptions.protocols));
|
||||
const protocols = (0, builder_util_1.asArray)(buildMetadata.protocols).concat((0, builder_util_1.asArray)(packager.platformSpecificBuildOptions.protocols));
|
||||
if (protocols.length > 0) {
|
||||
appPlist.CFBundleURLTypes = protocols.map(protocol => {
|
||||
const schemes = builder_util_1.asArray(protocol.schemes);
|
||||
const schemes = (0, builder_util_1.asArray)(protocol.schemes);
|
||||
if (schemes.length === 0) {
|
||||
throw new builder_util_1.InvalidConfigurationError(`Protocol "${protocol.name}": must be at least one scheme specified`);
|
||||
}
|
||||
|
|
@ -163,13 +156,13 @@ async function createMacApp(packager, appOutDir, asarIntegrity, isMas) {
|
|||
}
|
||||
const fileAssociations = packager.fileAssociations;
|
||||
if (fileAssociations.length > 0) {
|
||||
appPlist.CFBundleDocumentTypes = await bluebird_lst_1.default.map(fileAssociations, async (fileAssociation) => {
|
||||
const extensions = builder_util_1.asArray(fileAssociation.ext).map(platformPackager_1.normalizeExt);
|
||||
const customIcon = await packager.getResource(builder_util_1.getPlatformIconFileName(fileAssociation.icon, true), `${extensions[0]}.icns`);
|
||||
const documentTypes = await Promise.all(fileAssociations.map(async (fileAssociation) => {
|
||||
const extensions = (0, builder_util_1.asArray)(fileAssociation.ext).map(platformPackager_1.normalizeExt);
|
||||
const customIcon = await packager.getResource((0, builder_util_1.getPlatformIconFileName)(fileAssociation.icon, true), `${extensions[0]}.icns`);
|
||||
let iconFile = appPlist.CFBundleIconFile;
|
||||
if (customIcon != null) {
|
||||
iconFile = path.basename(customIcon);
|
||||
await fs_1.copyOrLinkFile(customIcon, path.join(path.join(contentsPath, "Resources"), iconFile));
|
||||
await (0, builder_util_1.copyOrLinkFile)(customIcon, path.join(path.join(contentsPath, "Resources"), iconFile));
|
||||
}
|
||||
const result = {
|
||||
CFBundleTypeExtensions: extensions,
|
||||
|
|
@ -182,38 +175,49 @@ async function createMacApp(packager, appOutDir, asarIntegrity, isMas) {
|
|||
result.LSTypeIsPackage = true;
|
||||
}
|
||||
return result;
|
||||
});
|
||||
}));
|
||||
// `CFBundleDocumentTypes` may be defined in `mac.extendInfo`, so we need to merge it in that case
|
||||
appPlist.CFBundleDocumentTypes = [...(appPlist.CFBundleDocumentTypes || []), ...documentTypes];
|
||||
}
|
||||
if (asarIntegrity != null) {
|
||||
appPlist.ElectronAsarIntegrity = asarIntegrity;
|
||||
}
|
||||
const plistDataToWrite = {
|
||||
[appPlistFilename]: appPlist,
|
||||
[helperPlistFilename]: helperPlist,
|
||||
const toPlistObject = (asarIntegrity) => {
|
||||
const result = {};
|
||||
for (const [filePath, headerHash] of Object.entries(asarIntegrity)) {
|
||||
result[filePath] = {
|
||||
algorithm: headerHash.algorithm,
|
||||
hash: headerHash.hash,
|
||||
};
|
||||
}
|
||||
return result;
|
||||
};
|
||||
if (asarIntegrity != null) {
|
||||
appPlist.ElectronAsarIntegrity = toPlistObject(asarIntegrity);
|
||||
}
|
||||
if (helperEHPlist != null) {
|
||||
plistDataToWrite[helperEHPlistFilename] = helperEHPlist;
|
||||
await (0, plist_1.savePlistFile)(helperEHPlistFilename, helperEHPlist);
|
||||
}
|
||||
if (helperNPPlist != null) {
|
||||
plistDataToWrite[helperNPPlistFilename] = helperNPPlist;
|
||||
await (0, plist_1.savePlistFile)(helperNPPlistFilename, helperNPPlist);
|
||||
}
|
||||
if (helperRendererPlist != null) {
|
||||
plistDataToWrite[helperRendererPlistFilename] = helperRendererPlist;
|
||||
await (0, plist_1.savePlistFile)(helperRendererPlistFilename, helperRendererPlist);
|
||||
}
|
||||
if (helperPluginPlist != null) {
|
||||
plistDataToWrite[helperPluginPlistFilename] = helperPluginPlist;
|
||||
await (0, plist_1.savePlistFile)(helperPluginPlistFilename, helperPluginPlist);
|
||||
}
|
||||
if (helperGPUPlist != null) {
|
||||
plistDataToWrite[helperGPUPlistFilename] = helperGPUPlist;
|
||||
await (0, plist_1.savePlistFile)(helperGPUPlistFilename, helperGPUPlist);
|
||||
}
|
||||
if (helperLoginPlist != null) {
|
||||
plistDataToWrite[helperLoginPlistFilename] = helperLoginPlist;
|
||||
await (0, plist_1.savePlistFile)(helperLoginPlistFilename, helperLoginPlist);
|
||||
}
|
||||
await (0, plist_1.savePlistFile)(appPlistFilename, appPlist);
|
||||
if (helperPlist != null) {
|
||||
await (0, plist_1.savePlistFile)(helperPlistFilename, helperPlist);
|
||||
}
|
||||
await Promise.all([
|
||||
appBuilder_1.executeAppBuilderAndWriteJson(["encode-plist"], plistDataToWrite),
|
||||
doRename(path.join(contentsPath, "MacOS"), electronBranding.productName, appPlist.CFBundleExecutable),
|
||||
fs_1.unlinkIfExists(path.join(appOutDir, "LICENSE")),
|
||||
fs_1.unlinkIfExists(path.join(appOutDir, "LICENSES.chromium.html")),
|
||||
(0, builder_util_1.unlinkIfExists)(path.join(appOutDir, "LICENSE")),
|
||||
(0, builder_util_1.unlinkIfExists)(path.join(appOutDir, "LICENSES.chromium.html")),
|
||||
]);
|
||||
await moveHelpers(getAvailableHelperSuffixes(helperEHPlist, helperNPPlist, helperRendererPlist, helperPluginPlist, helperGPUPlist), frameworksPath, appFilename, electronBranding.productName);
|
||||
if (helperLoginPlist != null) {
|
||||
|
|
@ -222,13 +226,12 @@ async function createMacApp(packager, appOutDir, asarIntegrity, isMas) {
|
|||
const executableBasePath = path.join(loginItemPath, `${prefix}${suffix}.app`, "Contents", "MacOS");
|
||||
await doRename(executableBasePath, `${prefix}${suffix}`, appFilename + suffix).then(() => doRename(loginItemPath, `${prefix}${suffix}.app`, `${appFilename}${suffix}.app`));
|
||||
}
|
||||
const appPath = path.join(appOutDir, `${appFilename}.app`);
|
||||
await promises_1.rename(path.dirname(contentsPath), appPath);
|
||||
const appPath = path.join(appOutDir, `${appInfo.productFilename}.app`);
|
||||
await (0, promises_1.rename)(path.dirname(contentsPath), appPath);
|
||||
// https://github.com/electron-userland/electron-builder/issues/840
|
||||
const now = Date.now() / 1000;
|
||||
await promises_1.utimes(appPath, now, now);
|
||||
await (0, promises_1.utimes)(appPath, now, now);
|
||||
}
|
||||
exports.createMacApp = createMacApp;
|
||||
function configureLocalhostAts(appPlist) {
|
||||
// https://bencoding.com/2015/07/20/app-transport-security-and-localhost/
|
||||
let ats = appPlist.NSAppTransportSecurity;
|
||||
|
|
|
|||
2
electron/node_modules/app-builder-lib/out/electron/electronMac.js.map
generated
vendored
2
electron/node_modules/app-builder-lib/out/electron/electronMac.js.map
generated
vendored
File diff suppressed because one or more lines are too long
8
electron/node_modules/app-builder-lib/out/electron/electronVersion.d.ts
generated
vendored
8
electron/node_modules/app-builder-lib/out/electron/electronVersion.d.ts
generated
vendored
|
|
@ -1,8 +1,6 @@
|
|||
import { Lazy } from "lazy-val";
|
||||
import { Configuration } from "../configuration";
|
||||
export declare type MetadataValue = Lazy<{
|
||||
[key: string]: any;
|
||||
} | null>;
|
||||
export declare function getElectronVersion(projectDir: string, config?: Configuration, projectMetadata?: MetadataValue): Promise<string>;
|
||||
export declare function getElectronVersionFromInstalled(projectDir: string): Promise<any>;
|
||||
export type MetadataValue = Lazy<Record<string, any> | null>;
|
||||
export declare function getElectronVersion(projectDir: string, config?: Configuration): Promise<string>;
|
||||
export declare function getElectronVersionFromInstalled(projectDir: string): Promise<string | null>;
|
||||
export declare function getElectronPackage(projectDir: string): Promise<any>;
|
||||
|
|
|
|||
57
electron/node_modules/app-builder-lib/out/electron/electronVersion.js
generated
vendored
57
electron/node_modules/app-builder-lib/out/electron/electronVersion.js
generated
vendored
|
|
@ -1,30 +1,31 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.computeElectronVersion = exports.getElectronPackage = exports.getElectronVersionFromInstalled = exports.getElectronVersion = void 0;
|
||||
exports.getElectronVersion = getElectronVersion;
|
||||
exports.getElectronVersionFromInstalled = getElectronVersionFromInstalled;
|
||||
exports.getElectronPackage = getElectronPackage;
|
||||
exports.computeElectronVersion = computeElectronVersion;
|
||||
const builder_util_1 = require("builder-util");
|
||||
const builder_util_runtime_1 = require("builder-util-runtime");
|
||||
const nodeHttpExecutor_1 = require("builder-util/out/nodeHttpExecutor");
|
||||
const fs_extra_1 = require("fs-extra");
|
||||
const lazy_val_1 = require("lazy-val");
|
||||
const path = require("path");
|
||||
const read_config_file_1 = require("read-config-file");
|
||||
const semver = require("semver");
|
||||
const config_1 = require("../util/config");
|
||||
const config_1 = require("../util/config/config");
|
||||
const load_1 = require("../util/config/load");
|
||||
const search_module_1 = require("./search-module");
|
||||
const electronPackages = ["electron", "electron-prebuilt", "electron-prebuilt-compile", "electron-nightly"];
|
||||
async function getElectronVersion(projectDir, config, projectMetadata = new lazy_val_1.Lazy(() => read_config_file_1.orNullIfFileNotExist(fs_extra_1.readJson(path.join(projectDir, "package.json"))))) {
|
||||
async function getElectronVersion(projectDir, config) {
|
||||
if (config == null) {
|
||||
config = await config_1.getConfig(projectDir, null, null);
|
||||
config = await (0, config_1.getConfig)(projectDir, null, null);
|
||||
}
|
||||
if (config.electronVersion != null) {
|
||||
return config.electronVersion;
|
||||
}
|
||||
return await computeElectronVersion(projectDir, projectMetadata);
|
||||
return computeElectronVersion(projectDir);
|
||||
}
|
||||
exports.getElectronVersion = getElectronVersion;
|
||||
async function getElectronVersionFromInstalled(projectDir) {
|
||||
for (const name of electronPackages) {
|
||||
try {
|
||||
return (await fs_extra_1.readJson(path.join(projectDir, "node_modules", name, "package.json"))).version;
|
||||
return (await (0, fs_extra_1.readJson)(path.join(projectDir, "node_modules", name, "package.json"))).version;
|
||||
}
|
||||
catch (e) {
|
||||
if (e.code !== "ENOENT") {
|
||||
|
|
@ -34,11 +35,10 @@ async function getElectronVersionFromInstalled(projectDir) {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
exports.getElectronVersionFromInstalled = getElectronVersionFromInstalled;
|
||||
async function getElectronPackage(projectDir) {
|
||||
for (const name of electronPackages) {
|
||||
try {
|
||||
return await fs_extra_1.readJson(path.join(projectDir, "node_modules", name, "package.json"));
|
||||
return await (0, fs_extra_1.readJson)(path.join(projectDir, "node_modules", name, "package.json"));
|
||||
}
|
||||
catch (e) {
|
||||
if (e.code !== "ENOENT") {
|
||||
|
|
@ -48,24 +48,31 @@ async function getElectronPackage(projectDir) {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
exports.getElectronPackage = getElectronPackage;
|
||||
/** @internal */
|
||||
async function computeElectronVersion(projectDir, projectMetadata) {
|
||||
async function computeElectronVersion(projectDir) {
|
||||
const result = await getElectronVersionFromInstalled(projectDir);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
const dependency = findFromPackageMetadata(await projectMetadata.value);
|
||||
const potentialRootDirs = [projectDir, await (0, search_module_1.getProjectRootPath)(projectDir)];
|
||||
let dependency = null;
|
||||
for (const dir of potentialRootDirs) {
|
||||
const metadata = await (0, load_1.orNullIfFileNotExist)((0, fs_extra_1.readJson)(path.join(dir, "package.json")));
|
||||
dependency = metadata ? findFromPackageMetadata(metadata) : null;
|
||||
if (dependency) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((dependency === null || dependency === void 0 ? void 0 : dependency.name) === "electron-nightly") {
|
||||
builder_util_1.log.info("You are using a nightly version of electron, be warned that those builds are highly unstable.");
|
||||
const feedXml = await nodeHttpExecutor_1.httpExecutor.request({
|
||||
const feedXml = await builder_util_1.httpExecutor.request({
|
||||
hostname: "github.com",
|
||||
path: `/electron/nightlies/releases.atom`,
|
||||
headers: {
|
||||
accept: "application/xml, application/atom+xml, text/xml, */*",
|
||||
},
|
||||
});
|
||||
const feed = builder_util_runtime_1.parseXml(feedXml);
|
||||
const feed = (0, builder_util_runtime_1.parseXml)(feedXml);
|
||||
const latestRelease = feed.element("entry", false, `No published versions on GitHub`);
|
||||
const v = /\/tag\/v?([^/]+)$/.exec(latestRelease.element("link").attribute("href"))[1];
|
||||
return v.startsWith("v") ? v.substring(1) : v;
|
||||
|
|
@ -73,7 +80,7 @@ async function computeElectronVersion(projectDir, projectMetadata) {
|
|||
else if ((dependency === null || dependency === void 0 ? void 0 : dependency.version) === "latest") {
|
||||
builder_util_1.log.warn('Electron version is set to "latest", but it is recommended to set it to some more restricted version range.');
|
||||
try {
|
||||
const releaseInfo = JSON.parse((await nodeHttpExecutor_1.httpExecutor.request({
|
||||
const releaseInfo = JSON.parse((await builder_util_1.httpExecutor.request({
|
||||
hostname: "github.com",
|
||||
path: `/electron/${dependency.name === "electron-nightly" ? "nightlies" : "electron"}/releases/latest`,
|
||||
headers: {
|
||||
|
|
@ -90,13 +97,17 @@ async function computeElectronVersion(projectDir, projectMetadata) {
|
|||
throw new builder_util_1.InvalidConfigurationError(`Cannot find electron dependency to get electron version in the '${path.join(projectDir, "package.json")}'`);
|
||||
}
|
||||
const version = dependency === null || dependency === void 0 ? void 0 : dependency.version;
|
||||
if (version == null || !/^\d/.test(version)) {
|
||||
const versionMessage = version == null ? "" : ` and version ("${version}") is not fixed in project`;
|
||||
throw new builder_util_1.InvalidConfigurationError(`Cannot compute electron version from installed node modules - none of the possible electron modules are installed${versionMessage}.\nSee https://github.com/electron-userland/electron-builder/issues/3984#issuecomment-504968246`);
|
||||
if (version == null) {
|
||||
throw new builder_util_1.InvalidConfigurationError(`Cannot compute electron version from installed node modules - none of the possible electron modules are installed.\nSee https://github.com/electron-userland/electron-builder/issues/3984#issuecomment-504968246`);
|
||||
}
|
||||
return semver.coerce(version).toString();
|
||||
const pinnedVersion = semver.valid(version);
|
||||
if (pinnedVersion === null) {
|
||||
builder_util_1.log.error({ version }, `Electron version "${version}" is a range, not a fixed version. electron-builder requires an exact version because it downloads platform-specific binaries for a specific release — a range cannot be resolved without electron installed in node_modules. ` +
|
||||
`Pin the version in package.json (e.g. "15.3.0" instead of "^15.3.0") or set "electronVersion" explicitly in your electron-builder config.`);
|
||||
throw new builder_util_1.InvalidConfigurationError(`Cannot compute electron version from installed node modules - version ("${version}") is not fixed in project.\nSee https://github.com/electron-userland/electron-builder/issues/3984#issuecomment-504968246`);
|
||||
}
|
||||
return pinnedVersion;
|
||||
}
|
||||
exports.computeElectronVersion = computeElectronVersion;
|
||||
function findFromPackageMetadata(packageData) {
|
||||
for (const name of electronPackages) {
|
||||
const devDependencies = packageData.devDependencies;
|
||||
|
|
|
|||
2
electron/node_modules/app-builder-lib/out/electron/electronVersion.js.map
generated
vendored
2
electron/node_modules/app-builder-lib/out/electron/electronVersion.js.map
generated
vendored
File diff suppressed because one or more lines are too long
38
electron/node_modules/app-builder-lib/out/electron/electronWin.js
generated
vendored
Normal file
38
electron/node_modules/app-builder-lib/out/electron/electronWin.js
generated
vendored
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.addWinAsarIntegrity = addWinAsarIntegrity;
|
||||
const builder_util_1 = require("builder-util");
|
||||
const promises_1 = require("fs/promises");
|
||||
const path = require("path");
|
||||
const resedit_1 = require("resedit");
|
||||
/** @internal */
|
||||
async function addWinAsarIntegrity(executablePath, asarIntegrity) {
|
||||
const buffer = await (0, promises_1.readFile)(executablePath);
|
||||
const executable = resedit_1.NtExecutable.from(buffer);
|
||||
const resource = resedit_1.NtExecutableResource.from(executable);
|
||||
const versionInfo = resedit_1.Resource.VersionInfo.fromEntries(resource.entries);
|
||||
if (versionInfo.length !== 1) {
|
||||
throw new Error(`Failed to parse version info in ${executablePath}`);
|
||||
}
|
||||
const languages = versionInfo[0].getAllLanguagesForStringValues();
|
||||
if (languages.length !== 1) {
|
||||
throw new Error(`Failed to locate languages in ${executablePath}`);
|
||||
}
|
||||
// See: https://github.com/electron/packager/blob/00d20b99cf4aa4621103dbbd09ff7de7d2f7f539/src/resedit.ts#L124
|
||||
const integrityList = Array.from(Object.entries(asarIntegrity)).map(([file, { algorithm: alg, hash: value }]) => ({
|
||||
file: path.win32.normalize(file),
|
||||
alg,
|
||||
value,
|
||||
}));
|
||||
resource.entries.push({
|
||||
type: "INTEGRITY",
|
||||
id: "ELECTRONASAR",
|
||||
bin: Buffer.from(JSON.stringify(integrityList)),
|
||||
lang: languages[0].lang,
|
||||
codepage: languages[0].codepage,
|
||||
});
|
||||
resource.outputResource(executable);
|
||||
await (0, promises_1.writeFile)(executablePath, Buffer.from(executable.generate()));
|
||||
builder_util_1.log.info({ executablePath: builder_util_1.log.filePath(executablePath) }, "updating asar integrity executable resource");
|
||||
}
|
||||
//# sourceMappingURL=electronWin.js.map
|
||||
1
electron/node_modules/app-builder-lib/out/electron/electronWin.js.map
generated
vendored
Normal file
1
electron/node_modules/app-builder-lib/out/electron/electronWin.js.map
generated
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"electronWin.js","sourceRoot":"","sources":["../../src/electron/electronWin.ts"],"names":[],"mappings":";;AAOA,kDAkCC;AAzCD,+CAAkC;AAClC,0CAAiD;AACjD,6BAA4B;AAC5B,qCAAsE;AAGtE,gBAAgB;AACT,KAAK,UAAU,mBAAmB,CAAC,cAAsB,EAAE,aAA4B;IAC5F,MAAM,MAAM,GAAG,MAAM,IAAA,mBAAQ,EAAC,cAAc,CAAC,CAAA;IAC7C,MAAM,UAAU,GAAG,sBAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IAC5C,MAAM,QAAQ,GAAG,8BAAoB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;IAEtD,MAAM,WAAW,GAAG,kBAAQ,CAAC,WAAW,CAAC,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;IACtE,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,mCAAmC,cAAc,EAAE,CAAC,CAAA;IACtE,CAAC;IAED,MAAM,SAAS,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,8BAA8B,EAAE,CAAA;IACjE,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,iCAAiC,cAAc,EAAE,CAAC,CAAA;IACpE,CAAC;IAED,8GAA8G;IAC9G,MAAM,aAAa,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QAChH,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC;QAChC,GAAG;QACH,KAAK;KACN,CAAC,CAAC,CAAA;IAEH,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC;QACpB,IAAI,EAAE,WAAW;QACjB,EAAE,EAAE,cAAc;QAClB,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;QAC/C,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI;QACvB,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,QAAQ;KAChC,CAAC,CAAA;IAEF,QAAQ,CAAC,cAAc,CAAC,UAAU,CAAC,CAAA;IAEnC,MAAM,IAAA,oBAAS,EAAC,cAAc,EAAE,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAA;IACnE,kBAAG,CAAC,IAAI,CAAC,EAAE,cAAc,EAAE,kBAAG,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,EAAE,6CAA6C,CAAC,CAAA;AAC3G,CAAC","sourcesContent":["import { log } from \"builder-util\"\nimport { readFile, writeFile } from \"fs/promises\"\nimport * as path from \"path\"\nimport { NtExecutable, NtExecutableResource, Resource } from \"resedit\"\nimport { AsarIntegrity } from \"../asar/integrity\"\n\n/** @internal */\nexport async function addWinAsarIntegrity(executablePath: string, asarIntegrity: AsarIntegrity) {\n const buffer = await readFile(executablePath)\n const executable = NtExecutable.from(buffer)\n const resource = NtExecutableResource.from(executable)\n\n const versionInfo = Resource.VersionInfo.fromEntries(resource.entries)\n if (versionInfo.length !== 1) {\n throw new Error(`Failed to parse version info in ${executablePath}`)\n }\n\n const languages = versionInfo[0].getAllLanguagesForStringValues()\n if (languages.length !== 1) {\n throw new Error(`Failed to locate languages in ${executablePath}`)\n }\n\n // See: https://github.com/electron/packager/blob/00d20b99cf4aa4621103dbbd09ff7de7d2f7f539/src/resedit.ts#L124\n const integrityList = Array.from(Object.entries(asarIntegrity)).map(([file, { algorithm: alg, hash: value }]) => ({\n file: path.win32.normalize(file),\n alg,\n value,\n }))\n\n resource.entries.push({\n type: \"INTEGRITY\",\n id: \"ELECTRONASAR\",\n bin: Buffer.from(JSON.stringify(integrityList)),\n lang: languages[0].lang,\n codepage: languages[0].codepage,\n })\n\n resource.outputResource(executable)\n\n await writeFile(executablePath, Buffer.from(executable.generate()))\n log.info({ executablePath: log.filePath(executablePath) }, \"updating asar integrity executable resource\")\n}\n"]}
|
||||
11
electron/node_modules/app-builder-lib/out/electron/injectFFMPEG.d.ts
generated
vendored
Normal file
11
electron/node_modules/app-builder-lib/out/electron/injectFFMPEG.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
import { PrepareApplicationStageDirectoryOptions } from "../Framework";
|
||||
import { ElectronBrandingOptions } from "./ElectronFramework";
|
||||
export declare class FFMPEGInjector {
|
||||
private readonly options;
|
||||
private readonly electronVersion;
|
||||
private readonly branding;
|
||||
constructor(options: PrepareApplicationStageDirectoryOptions, electronVersion: string, branding: Required<ElectronBrandingOptions>);
|
||||
inject(): Promise<string>;
|
||||
private downloadFFMPEG;
|
||||
private copyFFMPEG;
|
||||
}
|
||||
57
electron/node_modules/app-builder-lib/out/electron/injectFFMPEG.js
generated
vendored
Normal file
57
electron/node_modules/app-builder-lib/out/electron/injectFFMPEG.js
generated
vendored
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.FFMPEGInjector = void 0;
|
||||
const builder_util_1 = require("builder-util");
|
||||
const fs = require("fs-extra");
|
||||
const path = require("path");
|
||||
const core_1 = require("../core");
|
||||
const electronGet_1 = require("../util/electronGet");
|
||||
class FFMPEGInjector {
|
||||
constructor(options, electronVersion, branding) {
|
||||
this.options = options;
|
||||
this.electronVersion = electronVersion;
|
||||
this.branding = branding;
|
||||
}
|
||||
async inject() {
|
||||
const libPath = this.options.platformName === core_1.Platform.MAC.nodeName
|
||||
? path.join(this.options.appOutDir, `${this.branding.productName}.app`, "Contents", "Frameworks", `${this.branding.productName} Framework.framework`, "Versions", "A", "Libraries")
|
||||
: this.options.appOutDir;
|
||||
const ffmpegDir = await this.downloadFFMPEG();
|
||||
return this.copyFFMPEG(libPath, ffmpegDir);
|
||||
}
|
||||
async downloadFFMPEG() {
|
||||
const ffmpegFileName = `ffmpeg-v${this.electronVersion}-${this.options.platformName}-${this.options.arch}`;
|
||||
builder_util_1.log.info({ ffmpegFileName }, "downloading");
|
||||
const { packager: { config: { electronDownload }, }, platformName, arch, } = this.options;
|
||||
return (0, electronGet_1.downloadElectronArtifact)({
|
||||
electronDownload,
|
||||
artifactName: "ffmpeg",
|
||||
platformName,
|
||||
arch,
|
||||
version: this.electronVersion,
|
||||
});
|
||||
}
|
||||
async copyFFMPEG(targetPath, sourcePath) {
|
||||
let fileName = "ffmpeg.dll";
|
||||
if (["darwin", "mas"].includes(this.options.platformName)) {
|
||||
fileName = "libffmpeg.dylib";
|
||||
}
|
||||
else if (this.options.platformName === "linux") {
|
||||
fileName = "libffmpeg.so";
|
||||
}
|
||||
const libPath = path.resolve(sourcePath, fileName);
|
||||
const libTargetPath = path.resolve(targetPath, fileName);
|
||||
builder_util_1.log.info({ lib: builder_util_1.log.filePath(libPath), target: libTargetPath }, "copying non-proprietary FFMPEG");
|
||||
// If the source doesn't exist we have a problem
|
||||
if (!fs.existsSync(libPath)) {
|
||||
throw new Error(`Failed to find FFMPEG library file at path: ${libPath}`);
|
||||
}
|
||||
// If we are copying to the source we can stop immediately
|
||||
if (libPath !== libTargetPath) {
|
||||
await fs.copyFile(libPath, libTargetPath);
|
||||
}
|
||||
return libTargetPath;
|
||||
}
|
||||
}
|
||||
exports.FFMPEGInjector = FFMPEGInjector;
|
||||
//# sourceMappingURL=injectFFMPEG.js.map
|
||||
1
electron/node_modules/app-builder-lib/out/electron/injectFFMPEG.js.map
generated
vendored
Normal file
1
electron/node_modules/app-builder-lib/out/electron/injectFFMPEG.js.map
generated
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"injectFFMPEG.js","sourceRoot":"","sources":["../../src/electron/injectFFMPEG.ts"],"names":[],"mappings":";;;AAAA,+CAAkC;AAClC,+BAA8B;AAC9B,6BAA4B;AAC5B,kCAAkC;AAElC,qDAA8D;AAG9D,MAAa,cAAc;IACzB,YACmB,OAAgD,EAChD,eAAuB,EACvB,QAA2C;QAF3C,YAAO,GAAP,OAAO,CAAyC;QAChD,oBAAe,GAAf,eAAe,CAAQ;QACvB,aAAQ,GAAR,QAAQ,CAAmC;IAC3D,CAAC;IAEJ,KAAK,CAAC,MAAM;QACV,MAAM,OAAO,GACX,IAAI,CAAC,OAAO,CAAC,YAAY,KAAK,eAAQ,CAAC,GAAG,CAAC,QAAQ;YACjD,CAAC,CAAC,IAAI,CAAC,IAAI,CACP,IAAI,CAAC,OAAO,CAAC,SAAS,EACtB,GAAG,IAAI,CAAC,QAAQ,CAAC,WAAW,MAAM,EAClC,UAAU,EACV,YAAY,EACZ,GAAG,IAAI,CAAC,QAAQ,CAAC,WAAW,sBAAsB,EAClD,UAAU,EACV,GAAG,EACH,WAAW,CACZ;YACH,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAA;QAE5B,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,cAAc,EAAE,CAAA;QAC7C,OAAO,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,SAAS,CAAC,CAAA;IAC5C,CAAC;IAEO,KAAK,CAAC,cAAc;QAC1B,MAAM,cAAc,GAAG,WAAW,IAAI,CAAC,eAAe,IAAI,IAAI,CAAC,OAAO,CAAC,YAAY,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAA;QAE1G,kBAAG,CAAC,IAAI,CAAC,EAAE,cAAc,EAAE,EAAE,aAAa,CAAC,CAAA;QAE3C,MAAM,EACJ,QAAQ,EAAE,EACR,MAAM,EAAE,EAAE,gBAAgB,EAAE,GAC7B,EACD,YAAY,EACZ,IAAI,GACL,GAAG,IAAI,CAAC,OAAO,CAAA;QAEhB,OAAO,IAAA,sCAAwB,EAAC;YAC9B,gBAAgB;YAChB,YAAY,EAAE,QAAQ;YACtB,YAAY;YACZ,IAAI;YACJ,OAAO,EAAE,IAAI,CAAC,eAAe;SAC9B,CAAC,CAAA;IACJ,CAAC;IAEO,KAAK,CAAC,UAAU,CAAC,UAAkB,EAAE,UAAkB;QAC7D,IAAI,QAAQ,GAAG,YAAY,CAAA;QAC3B,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;YAC1D,QAAQ,GAAG,iBAAiB,CAAA;QAC9B,CAAC;aAAM,IAAI,IAAI,CAAC,OAAO,CAAC,YAAY,KAAK,OAAO,EAAE,CAAC;YACjD,QAAQ,GAAG,cAAc,CAAA;QAC3B,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAA;QAClD,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAA;QACxD,kBAAG,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,kBAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,aAAa,EAAE,EAAE,gCAAgC,CAAC,CAAA;QAEjG,gDAAgD;QAChD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,+CAA+C,OAAO,EAAE,CAAC,CAAA;QAC3E,CAAC;QAED,0DAA0D;QAC1D,IAAI,OAAO,KAAK,aAAa,EAAE,CAAC;YAC9B,MAAM,EAAE,CAAC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,CAAA;QAC3C,CAAC;QACD,OAAO,aAAa,CAAA;IACtB,CAAC;CACF;AAvED,wCAuEC","sourcesContent":["import { log } from \"builder-util\"\nimport * as fs from \"fs-extra\"\nimport * as path from \"path\"\nimport { Platform } from \"../core\"\nimport { PrepareApplicationStageDirectoryOptions } from \"../Framework\"\nimport { downloadElectronArtifact } from \"../util/electronGet\"\nimport { ElectronBrandingOptions } from \"./ElectronFramework\"\n\nexport class FFMPEGInjector {\n constructor(\n private readonly options: PrepareApplicationStageDirectoryOptions,\n private readonly electronVersion: string,\n private readonly branding: Required<ElectronBrandingOptions>\n ) {}\n\n async inject() {\n const libPath =\n this.options.platformName === Platform.MAC.nodeName\n ? path.join(\n this.options.appOutDir,\n `${this.branding.productName}.app`,\n \"Contents\",\n \"Frameworks\",\n `${this.branding.productName} Framework.framework`,\n \"Versions\",\n \"A\",\n \"Libraries\"\n )\n : this.options.appOutDir\n\n const ffmpegDir = await this.downloadFFMPEG()\n return this.copyFFMPEG(libPath, ffmpegDir)\n }\n\n private async downloadFFMPEG(): Promise<string> {\n const ffmpegFileName = `ffmpeg-v${this.electronVersion}-${this.options.platformName}-${this.options.arch}`\n\n log.info({ ffmpegFileName }, \"downloading\")\n\n const {\n packager: {\n config: { electronDownload },\n },\n platformName,\n arch,\n } = this.options\n\n return downloadElectronArtifact({\n electronDownload,\n artifactName: \"ffmpeg\",\n platformName,\n arch,\n version: this.electronVersion,\n })\n }\n\n private async copyFFMPEG(targetPath: string, sourcePath: string) {\n let fileName = \"ffmpeg.dll\"\n if ([\"darwin\", \"mas\"].includes(this.options.platformName)) {\n fileName = \"libffmpeg.dylib\"\n } else if (this.options.platformName === \"linux\") {\n fileName = \"libffmpeg.so\"\n }\n\n const libPath = path.resolve(sourcePath, fileName)\n const libTargetPath = path.resolve(targetPath, fileName)\n log.info({ lib: log.filePath(libPath), target: libTargetPath }, \"copying non-proprietary FFMPEG\")\n\n // If the source doesn't exist we have a problem\n if (!fs.existsSync(libPath)) {\n throw new Error(`Failed to find FFMPEG library file at path: ${libPath}`)\n }\n\n // If we are copying to the source we can stop immediately\n if (libPath !== libTargetPath) {\n await fs.copyFile(libPath, libTargetPath)\n }\n return libTargetPath\n }\n}\n"]}
|
||||
23
electron/node_modules/app-builder-lib/out/electron/search-module.d.ts
generated
vendored
Normal file
23
electron/node_modules/app-builder-lib/out/electron/search-module.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/**
|
||||
* Find all instances of a given module in node_modules subdirectories while traversing up
|
||||
* ancestor directories.
|
||||
*
|
||||
* @param cwd the initial directory to traverse
|
||||
* @param moduleName the Node module name (should work for scoped modules as well)
|
||||
* @param rootPath the project's root path. If provided, the traversal will stop at this path.
|
||||
*/
|
||||
export declare function searchForModule(cwd: string, moduleName: string, rootPath?: string): Promise<string[]>;
|
||||
/**
|
||||
* Find all instances of node_modules subdirectories while traversing up ancestor directories.
|
||||
*
|
||||
* @param cwd the initial directory to traverse
|
||||
* @param rootPath the project's root path. If provided, the traversal will stop at this path.
|
||||
*/
|
||||
export declare function searchForNodeModules(cwd: string, rootPath?: string): Promise<string[]>;
|
||||
/**
|
||||
* Determine the root directory of a given project, by looking for a directory with an
|
||||
* NPM or yarn lockfile or pnpm lockfile.
|
||||
*
|
||||
* @param cwd the initial directory to traverse
|
||||
*/
|
||||
export declare function getProjectRootPath(cwd: string): Promise<string>;
|
||||
73
electron/node_modules/app-builder-lib/out/electron/search-module.js
generated
vendored
Normal file
73
electron/node_modules/app-builder-lib/out/electron/search-module.js
generated
vendored
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.searchForModule = searchForModule;
|
||||
exports.searchForNodeModules = searchForNodeModules;
|
||||
exports.getProjectRootPath = getProjectRootPath;
|
||||
const fs = require("fs-extra");
|
||||
const path = require("node:path");
|
||||
async function shouldContinueSearch(traversedPath, rootPath, stopAtPackageJSON) {
|
||||
if (rootPath) {
|
||||
return Promise.resolve(traversedPath !== path.dirname(rootPath));
|
||||
}
|
||||
else if (stopAtPackageJSON) {
|
||||
return fs.existsSync(path.join(traversedPath, "package.json"));
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
async function traverseAncestorDirectories(cwd, pathGenerator, rootPath, maxItems, stopAtPackageJSON) {
|
||||
const paths = [];
|
||||
let traversedPath = path.resolve(cwd);
|
||||
while (await shouldContinueSearch(traversedPath, rootPath, stopAtPackageJSON)) {
|
||||
const generatedPath = pathGenerator(traversedPath);
|
||||
if (fs.existsSync(generatedPath)) {
|
||||
paths.push(generatedPath);
|
||||
}
|
||||
const parentPath = path.dirname(traversedPath);
|
||||
if (parentPath === traversedPath || (maxItems && paths.length >= maxItems)) {
|
||||
break;
|
||||
}
|
||||
traversedPath = parentPath;
|
||||
}
|
||||
return paths;
|
||||
}
|
||||
/**
|
||||
* Find all instances of a given module in node_modules subdirectories while traversing up
|
||||
* ancestor directories.
|
||||
*
|
||||
* @param cwd the initial directory to traverse
|
||||
* @param moduleName the Node module name (should work for scoped modules as well)
|
||||
* @param rootPath the project's root path. If provided, the traversal will stop at this path.
|
||||
*/
|
||||
async function searchForModule(cwd, moduleName, rootPath) {
|
||||
const pathGenerator = traversedPath => path.join(traversedPath, "node_modules", moduleName);
|
||||
return traverseAncestorDirectories(cwd, pathGenerator, rootPath, undefined, true);
|
||||
}
|
||||
/**
|
||||
* Find all instances of node_modules subdirectories while traversing up ancestor directories.
|
||||
*
|
||||
* @param cwd the initial directory to traverse
|
||||
* @param rootPath the project's root path. If provided, the traversal will stop at this path.
|
||||
*/
|
||||
async function searchForNodeModules(cwd, rootPath) {
|
||||
const pathGenerator = traversedPath => path.join(traversedPath, "node_modules");
|
||||
return traverseAncestorDirectories(cwd, pathGenerator, rootPath, undefined, true);
|
||||
}
|
||||
/**
|
||||
* Determine the root directory of a given project, by looking for a directory with an
|
||||
* NPM or yarn lockfile or pnpm lockfile.
|
||||
*
|
||||
* @param cwd the initial directory to traverse
|
||||
*/
|
||||
async function getProjectRootPath(cwd) {
|
||||
for (const lockFilename of ["yarn.lock", "package-lock.json", "pnpm-lock.yaml", "bun.lock", "bun.lockb"]) {
|
||||
const pathGenerator = traversedPath => path.join(traversedPath, lockFilename);
|
||||
const lockPaths = await traverseAncestorDirectories(cwd, pathGenerator, undefined, 1);
|
||||
if (lockPaths.length > 0) {
|
||||
return path.dirname(lockPaths[0]);
|
||||
}
|
||||
}
|
||||
return cwd;
|
||||
}
|
||||
//# sourceMappingURL=search-module.js.map
|
||||
1
electron/node_modules/app-builder-lib/out/electron/search-module.js.map
generated
vendored
Normal file
1
electron/node_modules/app-builder-lib/out/electron/search-module.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
2
electron/node_modules/app-builder-lib/out/errorMessages.d.ts
generated
vendored
2
electron/node_modules/app-builder-lib/out/errorMessages.d.ts
generated
vendored
|
|
@ -1 +1 @@
|
|||
export declare const authorEmailIsMissed = "Please specify author 'email' in the application package.json\n\nSee https://docs.npmjs.com/files/package.json#people-fields-author-contributors\n\nIt is required to set Linux .deb package maintainer. Or you can set maintainer in the custom linux options.\n(see https://www.electron.build/configuration/linux).\n";
|
||||
export declare const authorEmailIsMissed = "Please specify author 'email' in the application package.json\n\nSee https://docs.npmjs.com/files/package.json#people-fields-author-contributors\n\nIt is required to set Linux .deb package maintainer. Or you can set maintainer in the custom linux options.\n(see https://www.electron.build/linux).\n";
|
||||
|
|
|
|||
2
electron/node_modules/app-builder-lib/out/errorMessages.js
generated
vendored
2
electron/node_modules/app-builder-lib/out/errorMessages.js
generated
vendored
|
|
@ -6,6 +6,6 @@ exports.authorEmailIsMissed = `Please specify author 'email' in the application
|
|||
See https://docs.npmjs.com/files/package.json#people-fields-author-contributors
|
||||
|
||||
It is required to set Linux .deb package maintainer. Or you can set maintainer in the custom linux options.
|
||||
(see https://www.electron.build/configuration/linux).
|
||||
(see https://www.electron.build/linux).
|
||||
`;
|
||||
//# sourceMappingURL=errorMessages.js.map
|
||||
2
electron/node_modules/app-builder-lib/out/errorMessages.js.map
generated
vendored
2
electron/node_modules/app-builder-lib/out/errorMessages.js.map
generated
vendored
|
|
@ -1 +1 @@
|
|||
{"version":3,"file":"errorMessages.js","sourceRoot":"","sources":["../src/errorMessages.ts"],"names":[],"mappings":";;;AAAa,QAAA,mBAAmB,GAAG;;;;;;CAMlC,CAAA","sourcesContent":["export const authorEmailIsMissed = `Please specify author 'email' in the application package.json\n\nSee https://docs.npmjs.com/files/package.json#people-fields-author-contributors\n\nIt is required to set Linux .deb package maintainer. Or you can set maintainer in the custom linux options.\n(see https://www.electron.build/configuration/linux).\n`\n"]}
|
||||
{"version":3,"file":"errorMessages.js","sourceRoot":"","sources":["../src/errorMessages.ts"],"names":[],"mappings":";;;AAAa,QAAA,mBAAmB,GAAG;;;;;;CAMlC,CAAA","sourcesContent":["export const authorEmailIsMissed = `Please specify author 'email' in the application package.json\n\nSee https://docs.npmjs.com/files/package.json#people-fields-author-contributors\n\nIt is required to set Linux .deb package maintainer. Or you can set maintainer in the custom linux options.\n(see https://www.electron.build/linux).\n`\n"]}
|
||||
24
electron/node_modules/app-builder-lib/out/fileMatcher.d.ts
generated
vendored
24
electron/node_modules/app-builder-lib/out/fileMatcher.d.ts
generated
vendored
|
|
@ -1,9 +1,29 @@
|
|||
import { PlatformSpecificBuildOptions } from "./index";
|
||||
import { Filter } from "builder-util";
|
||||
import { Minimatch } from "minimatch";
|
||||
import { Configuration, PlatformSpecificBuildOptions } from "./index";
|
||||
export declare const excludedNames: string;
|
||||
export declare const excludedExts = "iml,hprof,orig,pyc,pyo,rbc,swp,csproj,sln,suo,xproj,cc,d.ts";
|
||||
export declare const excludedExts: string;
|
||||
export declare class FileMatcher {
|
||||
readonly macroExpander: (pattern: string) => string;
|
||||
readonly from: string;
|
||||
readonly to: string;
|
||||
readonly patterns: Array<string>;
|
||||
excludePatterns: Array<Minimatch> | null;
|
||||
readonly isSpecifiedAsEmptyArray: boolean;
|
||||
constructor(from: string, to: string, macroExpander: (pattern: string) => string, patterns?: Array<string> | string | null);
|
||||
normalizePattern(pattern: string): string;
|
||||
addPattern(pattern: string): void;
|
||||
prependPattern(pattern: string): void;
|
||||
isEmpty(): boolean;
|
||||
containsOnlyIgnore(): boolean;
|
||||
computeParsedPatterns(result: Array<Minimatch>, fromDir?: string): void;
|
||||
createFilter(): Filter;
|
||||
toString(): string;
|
||||
}
|
||||
export interface GetFileMatchersOptions {
|
||||
readonly macroExpander: (pattern: string) => string;
|
||||
readonly customBuildOptions: PlatformSpecificBuildOptions;
|
||||
readonly globalOutDir: string;
|
||||
readonly defaultSrc: string;
|
||||
}
|
||||
export declare function getFileMatchers(config: Configuration, name: "files" | "extraFiles" | "extraResources" | "asarUnpack" | "extraDistFiles", defaultDestination: string, options: GetFileMatchersOptions): Array<FileMatcher> | null;
|
||||
|
|
|
|||
62
electron/node_modules/app-builder-lib/out/fileMatcher.js
generated
vendored
62
electron/node_modules/app-builder-lib/out/fileMatcher.js
generated
vendored
|
|
@ -1,9 +1,11 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.copyFiles = exports.getFileMatchers = exports.getNodeModuleFileMatcher = exports.getMainFileMatchers = exports.FileMatcher = exports.excludedExts = exports.excludedNames = void 0;
|
||||
const bluebird_lst_1 = require("bluebird-lst");
|
||||
exports.FileMatcher = exports.excludedExts = exports.excludedNames = void 0;
|
||||
exports.getMainFileMatchers = getMainFileMatchers;
|
||||
exports.getNodeModuleFileMatcher = getNodeModuleFileMatcher;
|
||||
exports.getFileMatchers = getFileMatchers;
|
||||
exports.copyFiles = copyFiles;
|
||||
const builder_util_1 = require("builder-util");
|
||||
const fs_1 = require("builder-util/out/fs");
|
||||
const promises_1 = require("fs/promises");
|
||||
const minimatch_1 = require("minimatch");
|
||||
const path = require("path");
|
||||
|
|
@ -14,9 +16,11 @@ const minimatchOptions = { dot: true };
|
|||
exports.excludedNames = ".git,.hg,.svn,CVS,RCS,SCCS," +
|
||||
"__pycache__,.DS_Store,thumbs.db,.gitignore,.gitkeep,.gitattributes,.npmignore," +
|
||||
".idea,.vs,.flowconfig,.jshintrc,.eslintrc,.circleci," +
|
||||
".yarn-integrity,.yarn-metadata.json,yarn-error.log,yarn.lock,package-lock.json,npm-debug.log," +
|
||||
"appveyor.yml,.travis.yml,circle.yml,.nyc_output";
|
||||
exports.excludedExts = "iml,hprof,orig,pyc,pyo,rbc,swp,csproj,sln,suo,xproj,cc,d.ts";
|
||||
".yarn-integrity,.yarn-metadata.json,yarn-error.log,yarn.lock,package-lock.json,npm-debug.log,pnpm-lock.yaml,bun.lock,bun.lockb," +
|
||||
"appveyor.yml,.travis.yml,circle.yml,.nyc_output,.husky,.github,electron-builder.env";
|
||||
exports.excludedExts = "iml,hprof,orig,pyc,pyo,rbc,swp,csproj,sln,suo,xproj,cc,d.ts," +
|
||||
// https://github.com/electron-userland/electron-builder/issues/7512
|
||||
"mk,a,o,obj,forge-meta";
|
||||
function ensureNoEndSlash(file) {
|
||||
if (path.sep !== "/") {
|
||||
file = file.replace(/\//g, path.sep);
|
||||
|
|
@ -31,14 +35,13 @@ function ensureNoEndSlash(file) {
|
|||
return file;
|
||||
}
|
||||
}
|
||||
/** @internal */
|
||||
class FileMatcher {
|
||||
constructor(from, to, macroExpander, patterns) {
|
||||
this.macroExpander = macroExpander;
|
||||
this.excludePatterns = null;
|
||||
this.from = ensureNoEndSlash(macroExpander(from));
|
||||
this.to = ensureNoEndSlash(macroExpander(to));
|
||||
this.patterns = builder_util_1.asArray(patterns).map(it => this.normalizePattern(it));
|
||||
this.patterns = (0, builder_util_1.asArray)(patterns).map(it => this.normalizePattern(it));
|
||||
this.isSpecifiedAsEmptyArray = Array.isArray(patterns) && patterns.length === 0;
|
||||
}
|
||||
normalizePattern(pattern) {
|
||||
|
|
@ -73,7 +76,7 @@ class FileMatcher {
|
|||
const parsedPattern = new minimatch_1.Minimatch(pattern, minimatchOptions);
|
||||
result.push(parsedPattern);
|
||||
// do not add if contains dot (possibly file if has extension)
|
||||
if (!pattern.includes(".") && !filter_1.hasMagic(parsedPattern)) {
|
||||
if (!pattern.includes(".") && !(0, filter_1.hasMagic)(parsedPattern)) {
|
||||
// https://github.com/electron-userland/electron-builder/issues/545
|
||||
// add **/*
|
||||
result.push(new minimatch_1.Minimatch(`${pattern}/**/*`, minimatchOptions));
|
||||
|
|
@ -83,7 +86,7 @@ class FileMatcher {
|
|||
createFilter() {
|
||||
const parsedPatterns = [];
|
||||
this.computeParsedPatterns(parsedPatterns);
|
||||
return filter_1.createFilter(this.from, parsedPatterns, this.excludePatterns);
|
||||
return (0, filter_1.createFilter)(this.from, parsedPatterns, this.excludePatterns);
|
||||
}
|
||||
toString() {
|
||||
return `from: ${this.from}, to: ${this.to}, patterns: ${this.patterns.join(", ")}`;
|
||||
|
|
@ -120,7 +123,19 @@ function getMainFileMatchers(appDir, destination, macroExpander, platformSpecifi
|
|||
else if (!patterns.includes("package.json")) {
|
||||
patterns.push("package.json");
|
||||
}
|
||||
customFirstPatterns.push("!**/node_modules");
|
||||
let insertExculdeNodeModulesIndex = -1;
|
||||
for (let i = 0; i < patterns.length; i++) {
|
||||
if (!patterns[i].startsWith("!") && (patterns[i].includes("/node_modules") || patterns[i].includes("node_modules/"))) {
|
||||
insertExculdeNodeModulesIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (insertExculdeNodeModulesIndex !== -1) {
|
||||
patterns.splice(insertExculdeNodeModulesIndex, 0, ...["!**/node_modules/**"]);
|
||||
}
|
||||
else {
|
||||
customFirstPatterns.push("!**/node_modules/**");
|
||||
}
|
||||
// https://github.com/electron-userland/electron-builder/issues/1482
|
||||
const relativeBuildResourceDir = path.relative(matcher.from, buildResourceDir);
|
||||
if (relativeBuildResourceDir.length !== 0 && !relativeBuildResourceDir.startsWith(".")) {
|
||||
|
|
@ -141,7 +156,7 @@ function getMainFileMatchers(appDir, destination, macroExpander, platformSpecifi
|
|||
patterns.splice(insertIndex, 0, ...customFirstPatterns);
|
||||
patterns.push(`!**/*.{${exports.excludedExts}${packager.config.includePdb === true ? "" : ",pdb"}}`);
|
||||
patterns.push("!**/._*");
|
||||
patterns.push("!**/electron-builder.{yaml,yml,json,json5,toml}");
|
||||
patterns.push("!**/electron-builder.{yaml,yml,json,json5,toml,ts}");
|
||||
patterns.push(`!**/{${exports.excludedNames}}`);
|
||||
if (isElectronCompile) {
|
||||
patterns.push("!.cache{,/**/*}");
|
||||
|
|
@ -158,7 +173,6 @@ function getMainFileMatchers(appDir, destination, macroExpander, platformSpecifi
|
|||
}
|
||||
return matchers;
|
||||
}
|
||||
exports.getMainFileMatchers = getMainFileMatchers;
|
||||
/** @internal */
|
||||
function getNodeModuleFileMatcher(appDir, destination, macroExpander, platformSpecificBuildOptions, packager) {
|
||||
// https://github.com/electron-userland/electron-builder/pull/2948#issuecomment-392241632
|
||||
|
|
@ -185,7 +199,7 @@ function getNodeModuleFileMatcher(appDir, destination, macroExpander, platformSp
|
|||
else {
|
||||
const fileSet = pattern;
|
||||
if (fileSet.from == null || fileSet.from === ".") {
|
||||
for (const p of builder_util_1.asArray(fileSet.filter)) {
|
||||
for (const p of (0, builder_util_1.asArray)(fileSet.filter)) {
|
||||
matcher.addPattern(p);
|
||||
}
|
||||
}
|
||||
|
|
@ -204,8 +218,6 @@ function getNodeModuleFileMatcher(appDir, destination, macroExpander, platformSp
|
|||
}
|
||||
return matcher;
|
||||
}
|
||||
exports.getNodeModuleFileMatcher = getNodeModuleFileMatcher;
|
||||
/** @internal */
|
||||
function getFileMatchers(config, name, defaultDestination, options) {
|
||||
const defaultMatcher = new FileMatcher(options.defaultSrc, defaultDestination, options.macroExpander);
|
||||
const fileMatchers = [];
|
||||
|
|
@ -250,33 +262,31 @@ function getFileMatchers(config, name, defaultDestination, options) {
|
|||
}
|
||||
return fileMatchers.length === 0 ? null : fileMatchers;
|
||||
}
|
||||
exports.getFileMatchers = getFileMatchers;
|
||||
/** @internal */
|
||||
function copyFiles(matchers, transformer, isUseHardLink) {
|
||||
if (matchers == null || matchers.length === 0) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
return bluebird_lst_1.default.map(matchers, async (matcher) => {
|
||||
const fromStat = await fs_1.statOrNull(matcher.from);
|
||||
return Promise.all(matchers.map(async (matcher) => {
|
||||
const fromStat = await (0, builder_util_1.statOrNull)(matcher.from);
|
||||
if (fromStat == null) {
|
||||
builder_util_1.log.warn({ from: matcher.from }, `file source doesn't exist`);
|
||||
return;
|
||||
}
|
||||
if (fromStat.isFile()) {
|
||||
const toStat = await fs_1.statOrNull(matcher.to);
|
||||
const toStat = await (0, builder_util_1.statOrNull)(matcher.to);
|
||||
// https://github.com/electron-userland/electron-builder/issues/1245
|
||||
if (toStat != null && toStat.isDirectory()) {
|
||||
return await fs_1.copyOrLinkFile(matcher.from, path.join(matcher.to, path.basename(matcher.from)), fromStat, isUseHardLink);
|
||||
return await (0, builder_util_1.copyOrLinkFile)(matcher.from, path.join(matcher.to, path.basename(matcher.from)), fromStat, isUseHardLink);
|
||||
}
|
||||
await promises_1.mkdir(path.dirname(matcher.to), { recursive: true });
|
||||
return await fs_1.copyOrLinkFile(matcher.from, matcher.to, fromStat);
|
||||
await (0, promises_1.mkdir)(path.dirname(matcher.to), { recursive: true });
|
||||
return await (0, builder_util_1.copyOrLinkFile)(matcher.from, matcher.to, fromStat);
|
||||
}
|
||||
if (matcher.isEmpty() || matcher.containsOnlyIgnore()) {
|
||||
matcher.prependPattern("**/*");
|
||||
}
|
||||
builder_util_1.log.debug({ matcher }, "copying files using pattern");
|
||||
return await fs_1.copyDir(matcher.from, matcher.to, { filter: matcher.createFilter(), transformer, isUseHardLink: isUseHardLink ? fs_1.USE_HARD_LINKS : null });
|
||||
});
|
||||
return await (0, builder_util_1.copyDir)(matcher.from, matcher.to, { filter: matcher.createFilter(), transformer, isUseHardLink: isUseHardLink ? builder_util_1.USE_HARD_LINKS : null });
|
||||
}));
|
||||
}
|
||||
exports.copyFiles = copyFiles;
|
||||
//# sourceMappingURL=fileMatcher.js.map
|
||||
2
electron/node_modules/app-builder-lib/out/fileMatcher.js.map
generated
vendored
2
electron/node_modules/app-builder-lib/out/fileMatcher.js.map
generated
vendored
File diff suppressed because one or more lines are too long
21
electron/node_modules/app-builder-lib/out/fileTransformer.js
generated
vendored
21
electron/node_modules/app-builder-lib/out/fileTransformer.js
generated
vendored
|
|
@ -1,9 +1,14 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createElectronCompilerHost = exports.createTransformer = exports.hasDep = exports.isElectronCompileUsed = exports.NODE_MODULES_PATTERN = void 0;
|
||||
exports.NODE_MODULES_PATTERN = void 0;
|
||||
exports.isElectronCompileUsed = isElectronCompileUsed;
|
||||
exports.hasDep = hasDep;
|
||||
exports.createTransformer = createTransformer;
|
||||
exports.createElectronCompilerHost = createElectronCompilerHost;
|
||||
const builder_util_1 = require("builder-util");
|
||||
const promises_1 = require("fs/promises");
|
||||
const path = require("path");
|
||||
const builder_util_runtime_1 = require("builder-util-runtime");
|
||||
/** @internal */
|
||||
exports.NODE_MODULES_PATTERN = `${path.sep}node_modules${path.sep}`;
|
||||
/** @internal */
|
||||
|
|
@ -14,13 +19,11 @@ function isElectronCompileUsed(info) {
|
|||
// if in devDependencies - it means that babel is used for precompilation or for some reason user decided to not use electron-compile for production
|
||||
return hasDep("electron-compile", info);
|
||||
}
|
||||
exports.isElectronCompileUsed = isElectronCompileUsed;
|
||||
/** @internal */
|
||||
function hasDep(name, info) {
|
||||
const deps = info.metadata.dependencies;
|
||||
return deps != null && name in deps;
|
||||
}
|
||||
exports.hasDep = hasDep;
|
||||
/** @internal */
|
||||
function createTransformer(srcDir, configuration, extraMetadata, extraTransformer) {
|
||||
const mainPackageJson = path.join(srcDir, "package.json");
|
||||
|
|
@ -32,13 +35,13 @@ function createTransformer(srcDir, configuration, extraMetadata, extraTransforme
|
|||
return modifyMainPackageJson(file, extraMetadata, isRemovePackageScripts, isRemovePackageKeywords);
|
||||
}
|
||||
if (file.endsWith(packageJson) && file.includes(exports.NODE_MODULES_PATTERN)) {
|
||||
return promises_1.readFile(file, "utf-8")
|
||||
return (0, promises_1.readFile)(file, "utf-8")
|
||||
.then(it => cleanupPackageJson(JSON.parse(it), {
|
||||
isMain: false,
|
||||
isRemovePackageScripts,
|
||||
isRemovePackageKeywords,
|
||||
}))
|
||||
.catch(e => builder_util_1.log.warn(e));
|
||||
.catch((e) => builder_util_1.log.warn(e));
|
||||
}
|
||||
else if (extraTransformer != null) {
|
||||
return extraTransformer(file);
|
||||
|
|
@ -48,13 +51,11 @@ function createTransformer(srcDir, configuration, extraMetadata, extraTransforme
|
|||
}
|
||||
};
|
||||
}
|
||||
exports.createTransformer = createTransformer;
|
||||
/** @internal */
|
||||
function createElectronCompilerHost(projectDir, cacheDir) {
|
||||
const electronCompilePath = path.join(projectDir, "node_modules", "electron-compile", "lib");
|
||||
return require(path.join(electronCompilePath, "config-parser")).createCompilerHostFromProjectRoot(projectDir, cacheDir);
|
||||
}
|
||||
exports.createElectronCompilerHost = createElectronCompilerHost;
|
||||
const ignoredPackageMetadataProperties = new Set(["dist", "gitHead", "build", "jspm", "ava", "xo", "nyc", "eslintConfig", "contributors", "bundleDependencies", "tags"]);
|
||||
function cleanupPackageJson(data, options) {
|
||||
const deps = data.dependencies;
|
||||
|
|
@ -80,14 +81,14 @@ function cleanupPackageJson(data, options) {
|
|||
}
|
||||
}
|
||||
catch (e) {
|
||||
builder_util_1.debug(e);
|
||||
(0, builder_util_1.debug)(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
async function modifyMainPackageJson(file, extraMetadata, isRemovePackageScripts, isRemovePackageKeywords) {
|
||||
const mainPackageData = JSON.parse(await promises_1.readFile(file, "utf-8"));
|
||||
const mainPackageData = JSON.parse(await (0, promises_1.readFile)(file, "utf-8"));
|
||||
if (extraMetadata != null) {
|
||||
builder_util_1.deepAssign(mainPackageData, extraMetadata);
|
||||
(0, builder_util_runtime_1.deepAssign)(mainPackageData, extraMetadata);
|
||||
}
|
||||
// https://github.com/electron-userland/electron-builder/issues/1212
|
||||
const serializedDataIfChanged = cleanupPackageJson(mainPackageData, {
|
||||
|
|
|
|||
2
electron/node_modules/app-builder-lib/out/fileTransformer.js.map
generated
vendored
2
electron/node_modules/app-builder-lib/out/fileTransformer.js.map
generated
vendored
File diff suppressed because one or more lines are too long
13
electron/node_modules/app-builder-lib/out/forge-maker.js
generated
vendored
13
electron/node_modules/app-builder-lib/out/forge-maker.js
generated
vendored
|
|
@ -1,20 +1,23 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.buildForge = void 0;
|
||||
exports.buildForge = buildForge;
|
||||
const path = require("path");
|
||||
const index_1 = require("./index");
|
||||
function buildForge(forgeOptions, options) {
|
||||
const appDir = forgeOptions.dir;
|
||||
return index_1.build({
|
||||
// Resolve appDir to an absolute canonical path before deriving any sibling
|
||||
// directories from it. Using path.dirname avoids embedding ".." in the
|
||||
// resolved path, which keeps downstream path comparisons and CodeQL taint
|
||||
// tracking straightforward.
|
||||
const appDir = path.resolve(forgeOptions.dir);
|
||||
return (0, index_1.build)({
|
||||
prepackaged: appDir,
|
||||
config: {
|
||||
directories: {
|
||||
// https://github.com/electron-userland/electron-forge/blob/master/src/makers/generic/zip.js
|
||||
output: path.resolve(appDir, "..", "make"),
|
||||
output: path.join(path.dirname(appDir), "make"),
|
||||
},
|
||||
},
|
||||
...options,
|
||||
});
|
||||
}
|
||||
exports.buildForge = buildForge;
|
||||
//# sourceMappingURL=forge-maker.js.map
|
||||
2
electron/node_modules/app-builder-lib/out/forge-maker.js.map
generated
vendored
2
electron/node_modules/app-builder-lib/out/forge-maker.js.map
generated
vendored
|
|
@ -1 +1 @@
|
|||
{"version":3,"file":"forge-maker.js","sourceRoot":"","sources":["../src/forge-maker.ts"],"names":[],"mappings":";;;AAAA,6BAA4B;AAC5B,mCAA+B;AAO/B,SAAgB,UAAU,CAAC,YAA0B,EAAE,OAAwB;IAC7E,MAAM,MAAM,GAAG,YAAY,CAAC,GAAG,CAAA;IAC/B,OAAO,aAAK,CAAC;QACX,WAAW,EAAE,MAAM;QACnB,MAAM,EAAE;YACN,WAAW,EAAE;gBACX,4FAA4F;gBAC5F,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC;aAC3C;SACF;QACD,GAAG,OAAO;KACX,CAAC,CAAA;AACJ,CAAC;AAZD,gCAYC","sourcesContent":["import * as path from \"path\"\nimport { build } from \"./index\"\nimport { PackagerOptions } from \"./packagerApi\"\n\nexport interface ForgeOptions {\n readonly dir: string\n}\n\nexport function buildForge(forgeOptions: ForgeOptions, options: PackagerOptions) {\n const appDir = forgeOptions.dir\n return build({\n prepackaged: appDir,\n config: {\n directories: {\n // https://github.com/electron-userland/electron-forge/blob/master/src/makers/generic/zip.js\n output: path.resolve(appDir, \"..\", \"make\"),\n },\n },\n ...options,\n })\n}\n"]}
|
||||
{"version":3,"file":"forge-maker.js","sourceRoot":"","sources":["../src/forge-maker.ts"],"names":[],"mappings":";;AAQA,gCAgBC;AAxBD,6BAA4B;AAC5B,mCAA+B;AAO/B,SAAgB,UAAU,CAAC,YAA0B,EAAE,OAAwB;IAC7E,2EAA2E;IAC3E,wEAAwE;IACxE,0EAA0E;IAC1E,4BAA4B;IAC5B,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,CAAA;IAC7C,OAAO,IAAA,aAAK,EAAC;QACX,WAAW,EAAE,MAAM;QACnB,MAAM,EAAE;YACN,WAAW,EAAE;gBACX,4FAA4F;gBAC5F,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;aAChD;SACF;QACD,GAAG,OAAO;KACX,CAAC,CAAA;AACJ,CAAC","sourcesContent":["import * as path from \"path\"\nimport { build } from \"./index\"\nimport { PackagerOptions } from \"./packagerApi\"\n\nexport interface ForgeOptions {\n readonly dir: string\n}\n\nexport function buildForge(forgeOptions: ForgeOptions, options: PackagerOptions) {\n // Resolve appDir to an absolute canonical path before deriving any sibling\n // directories from it. Using path.dirname avoids embedding \"..\" in the\n // resolved path, which keeps downstream path comparisons and CodeQL taint\n // tracking straightforward.\n const appDir = path.resolve(forgeOptions.dir)\n return build({\n prepackaged: appDir,\n config: {\n directories: {\n // https://github.com/electron-userland/electron-forge/blob/master/src/makers/generic/zip.js\n output: path.join(path.dirname(appDir), \"make\"),\n },\n },\n ...options,\n })\n}\n"]}
|
||||
30
electron/node_modules/app-builder-lib/out/frameworks/LibUiFramework.d.ts
generated
vendored
30
electron/node_modules/app-builder-lib/out/frameworks/LibUiFramework.d.ts
generated
vendored
|
|
@ -1,16 +1,21 @@
|
|||
import { AfterPackContext } from "../configuration";
|
||||
import { Platform } from "../core";
|
||||
import { Framework, PrepareApplicationStageDirectoryOptions } from "../Framework";
|
||||
/** Validates that a value is safe to embed in a double-quoted shell string (no metacharacters). */
|
||||
export declare function validateShellEmbeddable(value: string, fieldName: string): void;
|
||||
export declare const LAUNCHUI_DEFAULT_VERSION = "0.1.4-10.13.0";
|
||||
export declare class LibUiFramework implements Framework {
|
||||
readonly version: string;
|
||||
readonly distMacOsAppName: string;
|
||||
readonly macOsProductName: string;
|
||||
protected readonly isUseLaunchUi: boolean;
|
||||
readonly name: string;
|
||||
readonly macOsDefaultTargets: string[];
|
||||
readonly defaultAppIdPrefix: string;
|
||||
readonly isCopyElevateHelper = false;
|
||||
readonly isNpmRebuildRequired = false;
|
||||
constructor(version: string, distMacOsAppName: string, isUseLaunchUi: boolean);
|
||||
readonly launchUiVersion: string;
|
||||
constructor(version: string, macOsProductName: string, isUseLaunchUi: boolean);
|
||||
get distMacOsAppName(): string;
|
||||
prepareApplicationStageDirectory(options: PrepareApplicationStageDirectoryOptions): Promise<void>;
|
||||
private prepareMacosApplicationStageDirectory;
|
||||
private prepareLinuxApplicationStageDirectory;
|
||||
|
|
@ -19,3 +24,24 @@ export declare class LibUiFramework implements Framework {
|
|||
private isUseLaunchUiForPlatform;
|
||||
getExcludedDependencies(platform: Platform): Array<string> | null;
|
||||
}
|
||||
export type NodeJsDownloadParams = {
|
||||
releaseName: string;
|
||||
filenameWithExt: string;
|
||||
overrideUrl: string;
|
||||
binaryRelPath: string;
|
||||
};
|
||||
export declare function getNodeJsDownloadParams(version: string, platform: Platform, arch: string): NodeJsDownloadParams;
|
||||
export declare function downloadNodeJsBinary(version: string, platform: Platform, arch: string): Promise<string>;
|
||||
/**
|
||||
* Fetches the SHA-256 hex digest for a specific Node.js distribution file from
|
||||
* the official nodejs.org SHASUMS256.txt, preventing MITM substitution attacks.
|
||||
*/
|
||||
export declare function fetchNodeJsChecksum(version: string, filename: string): Promise<string>;
|
||||
export type LaunchUiDownloadParams = {
|
||||
releaseName: string;
|
||||
filenameWithExt: string;
|
||||
githubOrgRepo: string;
|
||||
checksums: Record<string, string>;
|
||||
};
|
||||
export declare function getLaunchUiDownloadParams(version: string, platform: Platform, arch: string): LaunchUiDownloadParams;
|
||||
export declare function downloadLaunchUiDir(version: string, platform: Platform, arch: string): Promise<string>;
|
||||
|
|
|
|||
157
electron/node_modules/app-builder-lib/out/frameworks/LibUiFramework.js
generated
vendored
157
electron/node_modules/app-builder-lib/out/frameworks/LibUiFramework.js
generated
vendored
|
|
@ -1,16 +1,42 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.LibUiFramework = void 0;
|
||||
exports.LibUiFramework = exports.LAUNCHUI_DEFAULT_VERSION = void 0;
|
||||
exports.validateShellEmbeddable = validateShellEmbeddable;
|
||||
exports.getNodeJsDownloadParams = getNodeJsDownloadParams;
|
||||
exports.downloadNodeJsBinary = downloadNodeJsBinary;
|
||||
exports.fetchNodeJsChecksum = fetchNodeJsChecksum;
|
||||
exports.getLaunchUiDownloadParams = getLaunchUiDownloadParams;
|
||||
exports.downloadLaunchUiDir = downloadLaunchUiDir;
|
||||
const builder_util_1 = require("builder-util");
|
||||
const fs_extra_1 = require("fs-extra");
|
||||
const promises_1 = require("fs/promises");
|
||||
const https = require("https");
|
||||
const path = require("path");
|
||||
const builder_util_1 = require("builder-util");
|
||||
const core_1 = require("../core");
|
||||
const appBuilder_1 = require("../util/appBuilder");
|
||||
const electronGet_1 = require("../util/electronGet");
|
||||
const plist_1 = require("../util/plist");
|
||||
/** Validates that a value is safe to embed in a double-quoted shell string (no metacharacters). */
|
||||
function validateShellEmbeddable(value, fieldName) {
|
||||
// Allow letters, digits, dots, underscores, hyphens, forward slashes, and spaces.
|
||||
// Reject anything that could be interpreted as a shell metacharacter when embedded
|
||||
// inside a double-quoted string: $, `, ", \, and newlines.
|
||||
if (/[$`"\\\n]/.test(value)) {
|
||||
throw new builder_util_1.InvalidConfigurationError(`${fieldName} contains characters that are not safe in shell scripts: ${JSON.stringify(value)}. ` + `Avoid $, backtick, double-quote, backslash, and newline characters.`);
|
||||
}
|
||||
}
|
||||
// LaunchUI version is independent of the Node.js version; this was the hardcoded default in the Go binary.
|
||||
// https://github.com/develar/app-builder/blob/master/pkg/package-format/proton-native/protonNative.go#L105-L136
|
||||
exports.LAUNCHUI_DEFAULT_VERSION = "0.1.4-10.13.0";
|
||||
// https://github.com/develar/launchui/releases/tag/v0.1.4-10.13.0
|
||||
const launchUiChecksums = {
|
||||
"launchui-v0.1.4-10.13.0-linux-x64.7z": "4fb5cd8ed79e1e24e0f5cf4b26107f2fa6f6fd8dc48ecd18fb6f48f3ccfe9ee6",
|
||||
"launchui-v0.1.4-10.13.0-win32-ia32.7z": "682734da3d817ac365093c6c8ef3d9a70cc3f2a809e4588cb12a311358a68a2d",
|
||||
"launchui-v0.1.4-10.13.0-win32-x64.7z": "2f26629c5f5c12baeff272ac7855a1df7f27621cce782b79965f9a9b5eccc359",
|
||||
};
|
||||
class LibUiFramework {
|
||||
constructor(version, distMacOsAppName, isUseLaunchUi) {
|
||||
constructor(version, macOsProductName, isUseLaunchUi) {
|
||||
this.version = version;
|
||||
this.distMacOsAppName = distMacOsAppName;
|
||||
this.macOsProductName = macOsProductName;
|
||||
this.isUseLaunchUi = isUseLaunchUi;
|
||||
this.name = "libui";
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
|
|
@ -20,27 +46,22 @@ class LibUiFramework {
|
|||
this.isCopyElevateHelper = false;
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
this.isNpmRebuildRequired = false;
|
||||
this.launchUiVersion = exports.LAUNCHUI_DEFAULT_VERSION;
|
||||
}
|
||||
get distMacOsAppName() {
|
||||
return `${this.macOsProductName}.app`;
|
||||
}
|
||||
async prepareApplicationStageDirectory(options) {
|
||||
await fs_extra_1.emptyDir(options.appOutDir);
|
||||
await (0, fs_extra_1.emptyDir)(options.appOutDir);
|
||||
const packager = options.packager;
|
||||
const platform = packager.platform;
|
||||
if (this.isUseLaunchUiForPlatform(platform)) {
|
||||
const appOutDir = options.appOutDir;
|
||||
await builder_util_1.executeAppBuilder([
|
||||
"proton-native",
|
||||
"--node-version",
|
||||
this.version,
|
||||
"--use-launch-ui",
|
||||
"--platform",
|
||||
platform.nodeName,
|
||||
"--arch",
|
||||
options.arch,
|
||||
"--stage",
|
||||
appOutDir,
|
||||
"--executable",
|
||||
`${packager.appInfo.productFilename}${platform === core_1.Platform.WINDOWS ? ".exe" : ""}`,
|
||||
]);
|
||||
const launchUiDir = await downloadLaunchUiDir(this.launchUiVersion, platform, options.arch);
|
||||
await (0, fs_extra_1.copy)(launchUiDir, appOutDir);
|
||||
const skeletonExe = `launchui${platform === core_1.Platform.WINDOWS ? ".exe" : ""}`;
|
||||
const executableName = `${packager.appInfo.productFilename}${platform === core_1.Platform.WINDOWS ? ".exe" : ""}`;
|
||||
await (0, promises_1.rename)(path.join(appOutDir, skeletonExe), path.join(appOutDir, executableName));
|
||||
return;
|
||||
}
|
||||
if (platform === core_1.Platform.MAC) {
|
||||
|
|
@ -52,29 +73,35 @@ class LibUiFramework {
|
|||
}
|
||||
async prepareMacosApplicationStageDirectory(packager, options) {
|
||||
const appContentsDir = path.join(options.appOutDir, this.distMacOsAppName, "Contents");
|
||||
await promises_1.mkdir(path.join(appContentsDir, "Resources"), { recursive: true });
|
||||
await promises_1.mkdir(path.join(appContentsDir, "MacOS"), { recursive: true });
|
||||
await builder_util_1.executeAppBuilder(["proton-native", "--node-version", this.version, "--platform", "darwin", "--stage", path.join(appContentsDir, "MacOS")]);
|
||||
await (0, promises_1.mkdir)(path.join(appContentsDir, "Resources"), { recursive: true });
|
||||
await (0, promises_1.mkdir)(path.join(appContentsDir, "MacOS"), { recursive: true });
|
||||
const nodeBinaryMac = await downloadNodeJsBinary(this.version, core_1.Platform.MAC, "x64");
|
||||
await (0, promises_1.copyFile)(nodeBinaryMac, path.join(appContentsDir, "MacOS", "node"));
|
||||
await (0, promises_1.chmod)(path.join(appContentsDir, "MacOS", "node"), 0o755);
|
||||
const appPlist = {
|
||||
// https://github.com/albe-rosado/create-proton-app/issues/13
|
||||
NSHighResolutionCapable: true,
|
||||
};
|
||||
await packager.applyCommonInfo(appPlist, appContentsDir);
|
||||
await Promise.all([
|
||||
appBuilder_1.executeAppBuilderAndWriteJson(["encode-plist"], { [path.join(appContentsDir, "Info.plist")]: appPlist }),
|
||||
writeExecutableMain(path.join(appContentsDir, "MacOS", appPlist.CFBundleExecutable), `#!/bin/sh
|
||||
await (0, plist_1.savePlistFile)(path.join(appContentsDir, "Info.plist"), appPlist);
|
||||
const macMain = options.packager.info.metadata.main || "index.js";
|
||||
validateShellEmbeddable(macMain, "package.json main");
|
||||
await writeExecutableMain(path.join(appContentsDir, "MacOS", appPlist.CFBundleExecutable), `#!/bin/sh
|
||||
DIR=$(dirname "$0")
|
||||
"$DIR/node" "$DIR/../Resources/app/${options.packager.info.metadata.main || "index.js"}"
|
||||
`),
|
||||
]);
|
||||
"$DIR/node" "$DIR/../Resources/app/${macMain}"
|
||||
`);
|
||||
}
|
||||
async prepareLinuxApplicationStageDirectory(options) {
|
||||
const appOutDir = options.appOutDir;
|
||||
await builder_util_1.executeAppBuilder(["proton-native", "--node-version", this.version, "--platform", "linux", "--arch", options.arch, "--stage", appOutDir]);
|
||||
const nodeBinaryLinux = await downloadNodeJsBinary(this.version, core_1.Platform.LINUX, options.arch);
|
||||
await (0, promises_1.copyFile)(nodeBinaryLinux, path.join(appOutDir, "node"));
|
||||
await (0, promises_1.chmod)(path.join(appOutDir, "node"), 0o755);
|
||||
const mainPath = path.join(appOutDir, options.packager.executableName);
|
||||
const linuxMain = options.packager.info.metadata.main || "index.js";
|
||||
validateShellEmbeddable(linuxMain, "package.json main");
|
||||
await writeExecutableMain(mainPath, `#!/bin/sh
|
||||
DIR=$(dirname "$0")
|
||||
"$DIR/node" "$DIR/app/${options.packager.info.metadata.main || "index.js"}"
|
||||
"$DIR/node" "$DIR/app/${linuxMain}"
|
||||
`);
|
||||
}
|
||||
async afterPack(context) {
|
||||
|
|
@ -87,7 +114,7 @@ class LibUiFramework {
|
|||
if (userMain === "main.js") {
|
||||
return;
|
||||
}
|
||||
await promises_1.rename(path.join(context.appOutDir, "app", userMain), path.join(context.appOutDir, "app", "main.js"));
|
||||
await (0, promises_1.rename)(path.join(context.appOutDir, "app", userMain), path.join(context.appOutDir, "app", "main.js"));
|
||||
}
|
||||
getMainFile(platform) {
|
||||
return this.isUseLaunchUiForPlatform(platform) ? "main.js" : null;
|
||||
|
|
@ -102,7 +129,69 @@ class LibUiFramework {
|
|||
}
|
||||
exports.LibUiFramework = LibUiFramework;
|
||||
async function writeExecutableMain(file, content) {
|
||||
await promises_1.writeFile(file, content, { mode: 0o755 });
|
||||
await promises_1.chmod(file, 0o755);
|
||||
await (0, promises_1.writeFile)(file, content, { mode: 0o755 });
|
||||
await (0, promises_1.chmod)(file, 0o755);
|
||||
}
|
||||
function getNodeJsDownloadParams(version, platform, arch) {
|
||||
const isWindows = platform === core_1.Platform.WINDOWS;
|
||||
const nodePlatform = isWindows ? "win" : platform === core_1.Platform.MAC ? "darwin" : "linux";
|
||||
const nodeArch = isWindows && arch === "ia32" ? "x86" : arch;
|
||||
const format = isWindows ? "zip" : "tar.gz";
|
||||
const filenameWithExt = `node-v${version}-${nodePlatform}-${nodeArch}.${format}`;
|
||||
// tar.gz: strip:1 moves node-v.../bin/node → bin/node in extractDir
|
||||
// zip: no strip, node.exe lives under the top-level dir node-v{version}-win-{arch}/
|
||||
const binaryRelPath = isWindows ? path.join(`node-v${version}-win-${nodeArch}`, "node.exe") : path.join("bin", "node");
|
||||
return { releaseName: `nodejs-v${version}`, filenameWithExt, overrideUrl: `https://nodejs.org/dist/v${version}`, binaryRelPath };
|
||||
}
|
||||
async function downloadNodeJsBinary(version, platform, arch) {
|
||||
const { releaseName, filenameWithExt, overrideUrl, binaryRelPath } = getNodeJsDownloadParams(version, platform, arch);
|
||||
const sha256 = await fetchNodeJsChecksum(version, filenameWithExt);
|
||||
const checksums = { [filenameWithExt]: sha256 };
|
||||
const extractDir = await (0, electronGet_1.downloadBuilderToolset)({ releaseName, filenameWithExt, overrideUrl, checksums });
|
||||
return path.join(extractDir, binaryRelPath);
|
||||
}
|
||||
/**
|
||||
* Fetches the SHA-256 hex digest for a specific Node.js distribution file from
|
||||
* the official nodejs.org SHASUMS256.txt, preventing MITM substitution attacks.
|
||||
*/
|
||||
async function fetchNodeJsChecksum(version, filename) {
|
||||
const url = `https://nodejs.org/dist/v${version}/SHASUMS256.txt`;
|
||||
return new Promise((resolve, reject) => {
|
||||
https
|
||||
.get(url, { headers: { "User-Agent": "electron-builder" } }, res => {
|
||||
if (res.statusCode !== 200) {
|
||||
res.resume();
|
||||
reject(new Error(`HTTP ${res.statusCode} fetching Node.js SHASUMS256.txt for v${version}`));
|
||||
return;
|
||||
}
|
||||
const chunks = [];
|
||||
res.on("data", (c) => chunks.push(c));
|
||||
res.on("end", () => {
|
||||
const text = Buffer.concat(chunks).toString("utf8");
|
||||
for (const line of text.split("\n")) {
|
||||
const m = line.match(/^([0-9a-f]{64})\s+(.+)$/);
|
||||
if (m != null && m[2].trim() === filename) {
|
||||
resolve(m[1]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
reject(new Error(`No checksum for ${filename} in Node.js v${version} SHASUMS256.txt`));
|
||||
});
|
||||
res.on("error", reject);
|
||||
})
|
||||
.on("error", reject);
|
||||
});
|
||||
}
|
||||
function getLaunchUiDownloadParams(version, platform, arch) {
|
||||
const launchPlatform = platform === core_1.Platform.MAC ? "mac" : platform === core_1.Platform.WINDOWS ? "win32" : "linux";
|
||||
return {
|
||||
releaseName: `v${version}`,
|
||||
filenameWithExt: `launchui-v${version}-${launchPlatform}-${arch}.7z`,
|
||||
githubOrgRepo: "develar/launchui",
|
||||
checksums: launchUiChecksums,
|
||||
};
|
||||
}
|
||||
async function downloadLaunchUiDir(version, platform, arch) {
|
||||
return (0, electronGet_1.downloadBuilderToolset)(getLaunchUiDownloadParams(version, platform, arch));
|
||||
}
|
||||
//# sourceMappingURL=LibUiFramework.js.map
|
||||
2
electron/node_modules/app-builder-lib/out/frameworks/LibUiFramework.js.map
generated
vendored
2
electron/node_modules/app-builder-lib/out/frameworks/LibUiFramework.js.map
generated
vendored
File diff suppressed because one or more lines are too long
53
electron/node_modules/app-builder-lib/out/index.d.ts
generated
vendored
53
electron/node_modules/app-builder-lib/out/index.d.ts
generated
vendored
|
|
@ -1,32 +1,39 @@
|
|||
import { PublishOptions } from "electron-publish/out/publisher";
|
||||
import { PublishOptions } from "electron-publish";
|
||||
import { Packager } from "./packager";
|
||||
import { PackagerOptions } from "./packagerApi";
|
||||
export { Packager, BuildResult } from "./packager";
|
||||
export { PackagerOptions, ArtifactCreated, ArtifactBuildStarted } from "./packagerApi";
|
||||
export { TargetConfiguration, Platform, Target, DIR_TARGET, BeforeBuildContext, SourceRepositoryInfo, TargetSpecificOptions, TargetConfigType, DEFAULT_TARGET, CompressionLevel, } from "./core";
|
||||
export { getArchSuffix, Arch, archFromString } from "builder-util";
|
||||
export { Configuration, AfterPackContext, MetadataDirectories } from "./configuration";
|
||||
export { ElectronBrandingOptions, ElectronDownloadOptions, ElectronPlatformName } from "./electron/ElectronFramework";
|
||||
export { PlatformSpecificBuildOptions, AsarOptions, FileSet, Protocol, ReleaseInfo } from "./options/PlatformSpecificBuildOptions";
|
||||
export { FileAssociation } from "./options/FileAssociation";
|
||||
export { MacConfiguration, DmgOptions, MasConfiguration, MacOsTargetName, DmgContent, DmgWindow } from "./options/macOptions";
|
||||
export { PkgOptions, PkgBackgroundOptions, BackgroundAlignment, BackgroundScaling } from "./options/pkgOptions";
|
||||
export { WindowsConfiguration } from "./options/winOptions";
|
||||
export { AppXOptions } from "./options/AppXOptions";
|
||||
export { MsiOptions } from "./options/MsiOptions";
|
||||
export { CommonWindowsInstallerConfiguration } from "./options/CommonWindowsInstallerConfiguration";
|
||||
export { NsisOptions, NsisWebOptions, PortableOptions, CommonNsisOptions } from "./targets/nsis/nsisOptions";
|
||||
export { LinuxConfiguration, DebOptions, CommonLinuxOptions, LinuxTargetSpecificOptions, AppImageOptions, FlatpakOptions } from "./options/linuxOptions";
|
||||
export { SnapOptions } from "./options/SnapOptions";
|
||||
export { Metadata, AuthorMetadata, RepositoryInfo } from "./options/metadata";
|
||||
export { Arch, archFromString, getArchSuffix } from "builder-util";
|
||||
export { AppInfo } from "./appInfo";
|
||||
export { AfterExtractContext, AfterPackContext, BeforePackContext, CommonConfiguration, Configuration, FuseOptionsV1, Hook, Hooks, MetadataDirectories, PackContext, ToolsetConfig, } from "./configuration";
|
||||
export { BeforeBuildContext, CompressionLevel, DEFAULT_TARGET, DIR_TARGET, Platform, SourceRepositoryInfo, Target, TargetConfigType, TargetConfiguration, TargetSpecificOptions, } from "./core";
|
||||
export { ElectronBrandingOptions, ElectronPlatformName } from "./electron/ElectronFramework";
|
||||
export { ElectronDownloadOptions } from "./util/electronGet";
|
||||
export { AppXOptions } from "./options/AppXOptions";
|
||||
export { CommonWindowsInstallerConfiguration } from "./options/CommonWindowsInstallerConfiguration";
|
||||
export { FileAssociation } from "./options/FileAssociation";
|
||||
export { AppImageOptions, CommonLinuxOptions, DebOptions, FlatpakOptions, LinuxConfiguration, LinuxDesktopFile, LinuxTargetSpecificOptions, PacmanOptions, RpmOptions, } from "./options/linuxOptions";
|
||||
export { DmgContent, DmgOptions, DmgWindow, MacConfiguration, MacOsTargetName, MasConfiguration } from "./options/macOptions";
|
||||
export { AuthorMetadata, Metadata, RepositoryInfo } from "./options/metadata";
|
||||
export { MsiOptions } from "./options/MsiOptions";
|
||||
export { MsiWrappedOptions } from "./options/MsiWrappedOptions";
|
||||
export { BackgroundAlignment, BackgroundScaling, PkgBackgroundOptions, PkgOptions } from "./options/pkgOptions";
|
||||
export { AsarOptions, FileSet, FilesBuildOptions, PlatformSpecificBuildOptions, Protocol, ReleaseInfo } from "./options/PlatformSpecificBuildOptions";
|
||||
export { PlugDescriptor, SlotDescriptor, SnapcraftOptions, SnapOptions } from "./options/SnapOptions";
|
||||
export { SquirrelWindowsOptions } from "./options/SquirrelWindowsOptions";
|
||||
export { WindowsSignOptions, CustomWindowsSignTaskConfiguration, WindowsSignTaskConfiguration, CustomWindowsSign, FileCodeSigningInfo, CertificateFromStoreInfo, } from "./codeSign/windowsCodeSign";
|
||||
export { WindowsAzureSigningConfiguration, WindowsConfiguration, WindowsSigntoolConfiguration } from "./options/winOptions";
|
||||
export { BuildResult, Packager } from "./packager";
|
||||
export { ArtifactBuildStarted, ArtifactCreated, PackagerOptions } from "./packagerApi";
|
||||
export { CommonNsisOptions, CustomNsisBinary, NsisOptions, NsisWebOptions, PortableOptions } from "./targets/nsis/nsisOptions";
|
||||
export { CancellationToken, ProgressInfo } from "builder-util-runtime";
|
||||
export { PublishOptions, UploadTask } from "electron-publish";
|
||||
export { PublishManager } from "./publish/PublishManager";
|
||||
export { PlatformPackager } from "./platformPackager";
|
||||
export { WindowsSignOptions } from "./codeSign/windowsCodeSign";
|
||||
export { CertificateFromStoreInfo, CustomWindowsSign, CustomWindowsSignTaskConfiguration, FileCodeSigningInfo, WindowsSignTaskConfiguration, WindowsSignToolManager, } from "./codeSign/windowsSignToolManager";
|
||||
export { ToolInfo } from "./util/bundledTool";
|
||||
export { ForgeOptions, buildForge } from "./forge-maker";
|
||||
export { Framework, PrepareApplicationStageDirectoryOptions } from "./Framework";
|
||||
export { buildForge, ForgeOptions } from "./forge-maker";
|
||||
export { LinuxPackager } from "./linuxPackager";
|
||||
export { CustomMacSign, CustomMacSignOptions, MacPackager } from "./macPackager";
|
||||
export { PlatformPackager } from "./platformPackager";
|
||||
export { PublishManager } from "./publish/PublishManager";
|
||||
export { WinPackager } from "./winPackager";
|
||||
export declare function checkBuildRequestOptions(options: PackagerOptions & PublishOptions): void;
|
||||
export declare function build(options: PackagerOptions & PublishOptions, packager?: Packager): Promise<Array<string>>;
|
||||
|
|
|
|||
58
electron/node_modules/app-builder-lib/out/index.js
generated
vendored
58
electron/node_modules/app-builder-lib/out/index.js
generated
vendored
|
|
@ -1,33 +1,42 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.build = exports.checkBuildRequestOptions = exports.buildForge = exports.PlatformPackager = exports.PublishManager = exports.CancellationToken = exports.AppInfo = exports.archFromString = exports.Arch = exports.getArchSuffix = exports.DEFAULT_TARGET = exports.DIR_TARGET = exports.Target = exports.Platform = exports.Packager = void 0;
|
||||
const promise_1 = require("builder-util/out/promise");
|
||||
exports.WinPackager = exports.PublishManager = exports.PlatformPackager = exports.MacPackager = exports.LinuxPackager = exports.buildForge = exports.WindowsSignToolManager = exports.CancellationToken = exports.Packager = exports.Target = exports.Platform = exports.DIR_TARGET = exports.DEFAULT_TARGET = exports.AppInfo = exports.getArchSuffix = exports.archFromString = exports.Arch = void 0;
|
||||
exports.checkBuildRequestOptions = checkBuildRequestOptions;
|
||||
exports.build = build;
|
||||
const builder_util_1 = require("builder-util");
|
||||
const builder_util_runtime_1 = require("builder-util-runtime");
|
||||
const packager_1 = require("./packager");
|
||||
const platformPackager_1 = require("./platformPackager");
|
||||
const PublishManager_1 = require("./publish/PublishManager");
|
||||
var packager_2 = require("./packager");
|
||||
Object.defineProperty(exports, "Packager", { enumerable: true, get: function () { return packager_2.Packager; } });
|
||||
var core_1 = require("./core");
|
||||
Object.defineProperty(exports, "Platform", { enumerable: true, get: function () { return core_1.Platform; } });
|
||||
Object.defineProperty(exports, "Target", { enumerable: true, get: function () { return core_1.Target; } });
|
||||
Object.defineProperty(exports, "DIR_TARGET", { enumerable: true, get: function () { return core_1.DIR_TARGET; } });
|
||||
Object.defineProperty(exports, "DEFAULT_TARGET", { enumerable: true, get: function () { return core_1.DEFAULT_TARGET; } });
|
||||
const resolve_1 = require("./util/resolve");
|
||||
var builder_util_2 = require("builder-util");
|
||||
Object.defineProperty(exports, "getArchSuffix", { enumerable: true, get: function () { return builder_util_2.getArchSuffix; } });
|
||||
Object.defineProperty(exports, "Arch", { enumerable: true, get: function () { return builder_util_2.Arch; } });
|
||||
Object.defineProperty(exports, "archFromString", { enumerable: true, get: function () { return builder_util_2.archFromString; } });
|
||||
Object.defineProperty(exports, "getArchSuffix", { enumerable: true, get: function () { return builder_util_2.getArchSuffix; } });
|
||||
var appInfo_1 = require("./appInfo");
|
||||
Object.defineProperty(exports, "AppInfo", { enumerable: true, get: function () { return appInfo_1.AppInfo; } });
|
||||
var core_1 = require("./core");
|
||||
Object.defineProperty(exports, "DEFAULT_TARGET", { enumerable: true, get: function () { return core_1.DEFAULT_TARGET; } });
|
||||
Object.defineProperty(exports, "DIR_TARGET", { enumerable: true, get: function () { return core_1.DIR_TARGET; } });
|
||||
Object.defineProperty(exports, "Platform", { enumerable: true, get: function () { return core_1.Platform; } });
|
||||
Object.defineProperty(exports, "Target", { enumerable: true, get: function () { return core_1.Target; } });
|
||||
var packager_2 = require("./packager");
|
||||
Object.defineProperty(exports, "Packager", { enumerable: true, get: function () { return packager_2.Packager; } });
|
||||
var builder_util_runtime_2 = require("builder-util-runtime");
|
||||
Object.defineProperty(exports, "CancellationToken", { enumerable: true, get: function () { return builder_util_runtime_2.CancellationToken; } });
|
||||
var PublishManager_2 = require("./publish/PublishManager");
|
||||
Object.defineProperty(exports, "PublishManager", { enumerable: true, get: function () { return PublishManager_2.PublishManager; } });
|
||||
var platformPackager_2 = require("./platformPackager");
|
||||
Object.defineProperty(exports, "PlatformPackager", { enumerable: true, get: function () { return platformPackager_2.PlatformPackager; } });
|
||||
var windowsSignToolManager_1 = require("./codeSign/windowsSignToolManager");
|
||||
Object.defineProperty(exports, "WindowsSignToolManager", { enumerable: true, get: function () { return windowsSignToolManager_1.WindowsSignToolManager; } });
|
||||
var forge_maker_1 = require("./forge-maker");
|
||||
Object.defineProperty(exports, "buildForge", { enumerable: true, get: function () { return forge_maker_1.buildForge; } });
|
||||
var linuxPackager_1 = require("./linuxPackager");
|
||||
Object.defineProperty(exports, "LinuxPackager", { enumerable: true, get: function () { return linuxPackager_1.LinuxPackager; } });
|
||||
var macPackager_1 = require("./macPackager");
|
||||
Object.defineProperty(exports, "MacPackager", { enumerable: true, get: function () { return macPackager_1.MacPackager; } });
|
||||
var platformPackager_1 = require("./platformPackager");
|
||||
Object.defineProperty(exports, "PlatformPackager", { enumerable: true, get: function () { return platformPackager_1.PlatformPackager; } });
|
||||
var PublishManager_2 = require("./publish/PublishManager");
|
||||
Object.defineProperty(exports, "PublishManager", { enumerable: true, get: function () { return PublishManager_2.PublishManager; } });
|
||||
var winPackager_1 = require("./winPackager");
|
||||
Object.defineProperty(exports, "WinPackager", { enumerable: true, get: function () { return winPackager_1.WinPackager; } });
|
||||
const expectedOptions = new Set(["publish", "targets", "mac", "win", "linux", "projectDir", "platformPackagerFactory", "config", "effectiveOptionComputed", "prepackaged"]);
|
||||
function checkBuildRequestOptions(options) {
|
||||
for (const optionName of Object.keys(options)) {
|
||||
|
|
@ -36,7 +45,6 @@ function checkBuildRequestOptions(options) {
|
|||
}
|
||||
}
|
||||
}
|
||||
exports.checkBuildRequestOptions = checkBuildRequestOptions;
|
||||
function build(options, packager = new packager_1.Packager(options)) {
|
||||
checkBuildRequestOptions(options);
|
||||
const publishManager = new PublishManager_1.PublishManager(packager, options);
|
||||
|
|
@ -47,9 +55,9 @@ function build(options, packager = new packager_1.Packager(options)) {
|
|||
};
|
||||
process.once("SIGINT", sigIntHandler);
|
||||
const promise = packager.build().then(async (buildResult) => {
|
||||
const afterAllArtifactBuild = platformPackager_1.resolveFunction(buildResult.configuration.afterAllArtifactBuild, "afterAllArtifactBuild");
|
||||
const afterAllArtifactBuild = await (0, resolve_1.resolveFunction)(packager.appInfo.type, buildResult.configuration.afterAllArtifactBuild, "afterAllArtifactBuild", await packager.getWorkspaceRoot());
|
||||
if (afterAllArtifactBuild != null) {
|
||||
const newArtifacts = builder_util_runtime_1.asArray(await Promise.resolve(afterAllArtifactBuild(buildResult)));
|
||||
const newArtifacts = (0, builder_util_runtime_1.asArray)(await Promise.resolve(afterAllArtifactBuild(buildResult)));
|
||||
if (newArtifacts.length === 0 || !publishManager.isPublish) {
|
||||
return buildResult.artifactPaths;
|
||||
}
|
||||
|
|
@ -58,9 +66,13 @@ function build(options, packager = new packager_1.Packager(options)) {
|
|||
return buildResult.artifactPaths;
|
||||
}
|
||||
for (const newArtifact of newArtifacts) {
|
||||
if (buildResult.artifactPaths.includes(newArtifact)) {
|
||||
builder_util_1.log.warn({ newArtifact }, "skipping publish of artifact, already published");
|
||||
continue;
|
||||
}
|
||||
buildResult.artifactPaths.push(newArtifact);
|
||||
for (const publishConfiguration of publishConfigurations) {
|
||||
publishManager.scheduleUpload(publishConfiguration, {
|
||||
await publishManager.scheduleUpload(publishConfiguration, {
|
||||
file: newArtifact,
|
||||
arch: null,
|
||||
}, packager.appInfo);
|
||||
|
|
@ -69,7 +81,7 @@ function build(options, packager = new packager_1.Packager(options)) {
|
|||
}
|
||||
return buildResult.artifactPaths;
|
||||
});
|
||||
return promise_1.executeFinally(promise, isErrorOccurred => {
|
||||
return (0, builder_util_1.executeFinally)(promise, isErrorOccurred => {
|
||||
let promise;
|
||||
if (isErrorOccurred) {
|
||||
publishManager.cancelTasks();
|
||||
|
|
@ -78,8 +90,10 @@ function build(options, packager = new packager_1.Packager(options)) {
|
|||
else {
|
||||
promise = publishManager.awaitTasks();
|
||||
}
|
||||
return promise.then(() => process.removeListener("SIGINT", sigIntHandler));
|
||||
return promise.then(() => {
|
||||
packager.clearPackagerEventListeners();
|
||||
process.removeListener("SIGINT", sigIntHandler);
|
||||
});
|
||||
});
|
||||
}
|
||||
exports.build = build;
|
||||
//# sourceMappingURL=index.js.map
|
||||
2
electron/node_modules/app-builder-lib/out/index.js.map
generated
vendored
2
electron/node_modules/app-builder-lib/out/index.js.map
generated
vendored
File diff suppressed because one or more lines are too long
59
electron/node_modules/app-builder-lib/out/linuxPackager.js
generated
vendored
59
electron/node_modules/app-builder-lib/out/linuxPackager.js
generated
vendored
|
|
@ -1,18 +1,19 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.toAppImageOrSnapArch = exports.LinuxPackager = void 0;
|
||||
exports.LinuxPackager = void 0;
|
||||
exports.toAppImageOrSnapArch = toAppImageOrSnapArch;
|
||||
const builder_util_1 = require("builder-util");
|
||||
const filename_1 = require("builder-util/out/filename");
|
||||
const core_1 = require("./core");
|
||||
const platformPackager_1 = require("./platformPackager");
|
||||
const RemoteBuilder_1 = require("./remoteBuilder/RemoteBuilder");
|
||||
const LinuxTargetHelper_1 = require("./targets/LinuxTargetHelper");
|
||||
const targetFactory_1 = require("./targets/targetFactory");
|
||||
const filename_1 = require("./util/filename");
|
||||
class LinuxPackager extends platformPackager_1.PlatformPackager {
|
||||
constructor(info) {
|
||||
var _a;
|
||||
super(info, core_1.Platform.LINUX);
|
||||
const executableName = this.platformSpecificBuildOptions.executableName;
|
||||
this.executableName = executableName == null ? this.appInfo.sanitizedName.toLowerCase() : filename_1.sanitizeFileName(executableName);
|
||||
const executableName = (_a = this.platformSpecificBuildOptions.executableName) !== null && _a !== void 0 ? _a : info.config.executableName;
|
||||
this.executableName = executableName == null ? this.appInfo.sanitizedName.toLowerCase() : (0, filename_1.sanitizeFileName)(executableName);
|
||||
}
|
||||
get defaultTarget() {
|
||||
return ["snap", "appimage"];
|
||||
|
|
@ -25,7 +26,6 @@ class LinuxPackager extends platformPackager_1.PlatformPackager {
|
|||
}
|
||||
return helper;
|
||||
};
|
||||
let remoteBuilder = null;
|
||||
for (const name of targets) {
|
||||
if (name === core_1.DIR_TARGET) {
|
||||
continue;
|
||||
|
|
@ -33,9 +33,9 @@ class LinuxPackager extends platformPackager_1.PlatformPackager {
|
|||
const targetClass = (() => {
|
||||
switch (name) {
|
||||
case "appimage":
|
||||
return require("./targets/AppImageTarget").default;
|
||||
return require("./targets/appimage/AppImageTarget").default;
|
||||
case "snap":
|
||||
return require("./targets/snap").default;
|
||||
return require("./targets/snap/SnapTarget").default;
|
||||
case "flatpak":
|
||||
return require("./targets/FlatpakTarget").default;
|
||||
case "deb":
|
||||
|
|
@ -45,57 +45,21 @@ class LinuxPackager extends platformPackager_1.PlatformPackager {
|
|||
case "pacman":
|
||||
case "apk":
|
||||
case "p5p":
|
||||
return require("./targets/fpm").default;
|
||||
return require("./targets/FpmTarget").default;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
})();
|
||||
mapper(name, outDir => {
|
||||
if (targetClass === null) {
|
||||
return targetFactory_1.createCommonTarget(name, outDir, this);
|
||||
return (0, targetFactory_1.createCommonTarget)(name, outDir, this);
|
||||
}
|
||||
const target = new targetClass(name, this, getHelper(), outDir);
|
||||
if (process.platform === "win32" || process.env._REMOTE_BUILD) {
|
||||
if (remoteBuilder == null) {
|
||||
remoteBuilder = new RemoteBuilder_1.RemoteBuilder(this);
|
||||
}
|
||||
// return remoteBuilder.buildTarget(this, arch, appOutDir, this.packager)
|
||||
return new RemoteTarget(target, remoteBuilder);
|
||||
}
|
||||
return target;
|
||||
return new targetClass(name, this, getHelper(), outDir);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.LinuxPackager = LinuxPackager;
|
||||
class RemoteTarget extends core_1.Target {
|
||||
constructor(target, remoteBuilder) {
|
||||
super(target.name, true /* all must be scheduled in time (so, on finishBuild RemoteBuilder will have all targets added - so, we must set isAsyncSupported to true (resolved promise is returned)) */);
|
||||
this.target = target;
|
||||
this.remoteBuilder = remoteBuilder;
|
||||
this.buildTaskManager = new builder_util_1.AsyncTaskManager(this.remoteBuilder.packager.info.cancellationToken);
|
||||
}
|
||||
get options() {
|
||||
return this.target.options;
|
||||
}
|
||||
get outDir() {
|
||||
return this.target.outDir;
|
||||
}
|
||||
async finishBuild() {
|
||||
await this.buildTaskManager.awaitTasks();
|
||||
await this.remoteBuilder.build();
|
||||
}
|
||||
build(appOutDir, arch) {
|
||||
const promise = this.doBuild(appOutDir, arch);
|
||||
this.buildTaskManager.addTask(promise);
|
||||
return promise;
|
||||
}
|
||||
async doBuild(appOutDir, arch) {
|
||||
builder_util_1.log.info({ target: this.target.name, arch: builder_util_1.Arch[arch] }, "scheduling remote build");
|
||||
await this.target.checkOptions();
|
||||
this.remoteBuilder.scheduleBuild(this.target, arch, appOutDir);
|
||||
}
|
||||
}
|
||||
function toAppImageOrSnapArch(arch) {
|
||||
switch (arch) {
|
||||
case builder_util_1.Arch.x64:
|
||||
|
|
@ -110,5 +74,4 @@ function toAppImageOrSnapArch(arch) {
|
|||
throw new Error(`Unsupported arch ${arch}`);
|
||||
}
|
||||
}
|
||||
exports.toAppImageOrSnapArch = toAppImageOrSnapArch;
|
||||
//# sourceMappingURL=linuxPackager.js.map
|
||||
2
electron/node_modules/app-builder-lib/out/linuxPackager.js.map
generated
vendored
2
electron/node_modules/app-builder-lib/out/linuxPackager.js.map
generated
vendored
File diff suppressed because one or more lines are too long
29
electron/node_modules/app-builder-lib/out/mac/MacTargetHelper.d.ts
generated
vendored
Normal file
29
electron/node_modules/app-builder-lib/out/mac/MacTargetHelper.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
import type { NotarizeOptionsNotaryTool } from "@electron/notarize/lib/types";
|
||||
import type { PerFileSignOptions, SigningDistributionType, SignOptions } from "@electron/osx-sign/dist/cjs/types";
|
||||
import type { Identity } from "@electron/osx-sign/dist/cjs/util-identities";
|
||||
import { Arch } from "builder-util";
|
||||
import { Nullish } from "builder-util-runtime";
|
||||
import { CertType } from "../codeSign/macCodeSign";
|
||||
import type { MacPackager } from "../macPackager";
|
||||
import { MacConfiguration, MasConfiguration } from "../options/macOptions";
|
||||
export type PlatformType = "mas" | "mas-dev" | "mac";
|
||||
export declare class MacTargetHelper {
|
||||
private packager;
|
||||
constructor(packager: MacPackager);
|
||||
handleNullIdentity(): boolean;
|
||||
findSigningIdentity(isMas: boolean, isDevelopment: boolean, qualifier: string | undefined, keychainFile: string | Nullish, config: MacConfiguration | MasConfiguration): Promise<Identity | null>;
|
||||
buildSignOptions(appPath: string, identity: Identity, type: SigningDistributionType, isMas: boolean, config: MacConfiguration | MasConfiguration, keychainFile: string | Nullish, arch: Arch): Promise<SignOptions>;
|
||||
createMasInstaller(appPath: string, outDir: string, masOptions: MasConfiguration, keychainFile: string | Nullish, isDevelopment: boolean, arch: Arch): Promise<void>;
|
||||
getOptionsForFile(appPath: string, isMas: boolean, customSignOptions: MacConfiguration | MasConfiguration): Promise<(filePath: string) => PerFileSignOptions>;
|
||||
static getCertificateTypes(isMas: boolean, isDevelopment: boolean): CertType[];
|
||||
static isMasTarget(targetName: string): boolean;
|
||||
static getPlatformTypeFromTarget(targetName: string): PlatformType;
|
||||
/**
|
||||
* Returns true when hardened runtime will be active for signing.
|
||||
* For non-MAS builds it defaults to on; for MAS it defaults to off.
|
||||
*/
|
||||
static isHardenedRuntimeEnabledForSigning(isMas: boolean, config: Pick<MacConfiguration | MasConfiguration, "hardenedRuntime">): boolean;
|
||||
static assertSafePathForCommandUsage(pathValue: string, description: string): void;
|
||||
static getNotarizeOptions(appPath: string): NotarizeOptionsNotaryTool | undefined;
|
||||
notarizeIfProvided(appPath: string): Promise<void>;
|
||||
}
|
||||
273
electron/node_modules/app-builder-lib/out/mac/MacTargetHelper.js
generated
vendored
Normal file
273
electron/node_modules/app-builder-lib/out/mac/MacTargetHelper.js
generated
vendored
Normal file
|
|
@ -0,0 +1,273 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.MacTargetHelper = void 0;
|
||||
const builder_util_1 = require("builder-util");
|
||||
const dynamicImport_1 = require("../util/dynamicImport");
|
||||
const path = require("path");
|
||||
const macCodeSign_1 = require("../codeSign/macCodeSign");
|
||||
const pathManager_1 = require("../util/pathManager");
|
||||
class MacTargetHelper {
|
||||
constructor(packager) {
|
||||
this.packager = packager;
|
||||
}
|
||||
handleNullIdentity() {
|
||||
if (this.packager.forceCodeSigning) {
|
||||
throw new builder_util_1.InvalidConfigurationError("identity explicitly is set to null, but forceCodeSigning is set to true");
|
||||
}
|
||||
builder_util_1.log.info({ reason: "identity explicitly is set to null" }, "skipped macOS code signing");
|
||||
return false;
|
||||
}
|
||||
async findSigningIdentity(isMas, isDevelopment, qualifier, keychainFile, config) {
|
||||
const certificateTypes = MacTargetHelper.getCertificateTypes(isMas, isDevelopment);
|
||||
let identity = null;
|
||||
for (const certificateType of certificateTypes) {
|
||||
identity = await (0, macCodeSign_1.findIdentity)(certificateType, qualifier, keychainFile);
|
||||
if (identity != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (identity == null) {
|
||||
if (!isMas && !isDevelopment && config.type !== "distribution") {
|
||||
identity = await (0, macCodeSign_1.findIdentity)("Mac Developer", qualifier, keychainFile);
|
||||
if (identity != null) {
|
||||
builder_util_1.log.warn("Mac Developer is used to sign app — it is only for development and testing, not for production");
|
||||
}
|
||||
}
|
||||
const noIdentity = !config.sign && identity == null;
|
||||
if (qualifier === "-") {
|
||||
if (MacTargetHelper.isHardenedRuntimeEnabledForSigning(isMas, config)) {
|
||||
builder_util_1.log.warn(null, "ad-hoc signing with hardenedRuntime enabled requires the com.apple.security.cs.disable-library-validation entitlement " +
|
||||
"to prevent app launch failures due to library validation. See https://electron.build/code-signing for details.");
|
||||
}
|
||||
const { Identity: IdentityClass } = await (0, dynamicImport_1.dynamicImport)("@electron/osx-sign/dist/cjs/util-identities");
|
||||
identity = new IdentityClass("-", undefined);
|
||||
}
|
||||
else if (noIdentity) {
|
||||
await (0, macCodeSign_1.reportError)(isMas, certificateTypes, qualifier, keychainFile, this.packager.forceCodeSigning);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return identity;
|
||||
}
|
||||
async buildSignOptions(appPath, identity, type, isMas, config, keychainFile, arch) {
|
||||
let filter = config.signIgnore;
|
||||
if (Array.isArray(filter)) {
|
||||
if (filter.length == 0) {
|
||||
filter = null;
|
||||
}
|
||||
}
|
||||
else if (filter != null) {
|
||||
filter = filter.length === 0 ? null : [filter];
|
||||
}
|
||||
const filterRe = filter == null
|
||||
? null
|
||||
: filter.map(it => {
|
||||
try {
|
||||
return new RegExp(it);
|
||||
}
|
||||
catch (e) {
|
||||
throw new builder_util_1.InvalidConfigurationError(`Invalid regex filter pattern: ${it}. ${e.message}`);
|
||||
}
|
||||
});
|
||||
let binaries = config.binaries || undefined;
|
||||
if (binaries) {
|
||||
// Accept absolute paths for external binaries, else resolve relative paths from the artifact's app Contents path.
|
||||
binaries = (await Promise.all(binaries.flatMap(async (destination) => {
|
||||
const expandedDestination = this.packager.expandArch(destination, arch);
|
||||
return await Promise.all(expandedDestination.map(async (d) => {
|
||||
if (await (0, builder_util_1.statOrNull)(d)) {
|
||||
return d;
|
||||
}
|
||||
return path.resolve(appPath, d);
|
||||
}));
|
||||
}))).flat();
|
||||
builder_util_1.log.info({ binaries, arch: arch == null ? null : builder_util_1.Arch[arch] }, "signing additional user-defined binaries for arch");
|
||||
}
|
||||
return {
|
||||
identityValidation: false,
|
||||
// https://github.com/electron-userland/electron-builder/issues/1699
|
||||
// kext are signed by the chipset manufacturers. You need a special certificate (only available on request) from Apple to be able to sign kext.
|
||||
ignore: (file) => {
|
||||
if (filterRe != null) {
|
||||
for (const regExp of filterRe) {
|
||||
if (regExp.test(file)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (file.endsWith(".kext") ||
|
||||
file.startsWith("/Contents/PlugIns", appPath.length) ||
|
||||
file.includes("/node_modules/puppeteer/.local-chromium") ||
|
||||
file.includes("/node_modules/playwright-firefox/.local-browsers") ||
|
||||
file.includes("/node_modules/playwright/.local-browsers"));
|
||||
/* Those are browser automating modules, browser (chromium, nightly) cannot be signed
|
||||
https://github.com/electron-userland/electron-builder/issues/2010
|
||||
https://github.com/electron-userland/electron-builder/issues/5383
|
||||
*/
|
||||
},
|
||||
identity: identity ? identity.hash || identity.name : undefined,
|
||||
type,
|
||||
platform: isMas ? "mas" : "darwin",
|
||||
version: this.packager.config.electronVersion || undefined,
|
||||
app: appPath,
|
||||
keychain: keychainFile || undefined,
|
||||
binaries,
|
||||
// https://github.com/electron-userland/electron-builder/issues/1480
|
||||
strictVerify: config.strictVerify,
|
||||
preAutoEntitlements: config.preAutoEntitlements,
|
||||
optionsForFile: await this.getOptionsForFile(appPath, isMas, config),
|
||||
provisioningProfile: config.provisioningProfile || undefined,
|
||||
};
|
||||
}
|
||||
async createMasInstaller(appPath, outDir, masOptions, keychainFile, isDevelopment, arch) {
|
||||
const certType = isDevelopment ? "Mac Developer" : "3rd Party Mac Developer Installer";
|
||||
const masInstallerIdentity = await (0, macCodeSign_1.findIdentity)(certType, masOptions.identity, keychainFile);
|
||||
if (masInstallerIdentity == null) {
|
||||
throw new builder_util_1.InvalidConfigurationError(`Cannot find valid "${certType}" identity to sign MAS installer, please see https://electron.build/code-signing`);
|
||||
}
|
||||
MacTargetHelper.assertSafePathForCommandUsage(outDir, "output directory");
|
||||
// mas uploaded to AppStore, so, use "-" instead of space for name
|
||||
// path.basename prevents path traversal if a crafted artifactName contains "../"
|
||||
const artifactName = path.basename(this.packager.expandArtifactNamePattern(masOptions, "pkg", arch));
|
||||
MacTargetHelper.assertSafePathForCommandUsage(artifactName, "artifact name");
|
||||
const artifactPath = path.resolve(outDir, artifactName);
|
||||
await this.packager.doFlat(appPath, artifactPath, masInstallerIdentity, keychainFile);
|
||||
await this.packager.info.emitArtifactBuildCompleted({
|
||||
file: artifactPath,
|
||||
target: null,
|
||||
arch: builder_util_1.Arch.x64,
|
||||
safeArtifactName: this.packager.computeSafeArtifactName(artifactName, "pkg", arch, true, this.packager.platformSpecificBuildOptions.defaultArch),
|
||||
packager: this.packager,
|
||||
});
|
||||
}
|
||||
async getOptionsForFile(appPath, isMas, customSignOptions) {
|
||||
const resourceList = await this.packager.resourceList;
|
||||
const entitlementsSuffix = isMas ? "mas" : "mac";
|
||||
const getEntitlements = (filePath) => {
|
||||
if (filePath === appPath) {
|
||||
if (customSignOptions.entitlements) {
|
||||
return customSignOptions.entitlements;
|
||||
}
|
||||
const p = `entitlements.${entitlementsSuffix}.plist`;
|
||||
if (resourceList.includes(p)) {
|
||||
return path.join(this.packager.info.buildResourcesDir, p);
|
||||
}
|
||||
else {
|
||||
return (0, pathManager_1.getTemplatePath)("entitlements.mac.plist");
|
||||
}
|
||||
}
|
||||
if (filePath.includes("Library/LoginItems")) {
|
||||
return customSignOptions.entitlementsLoginHelper;
|
||||
}
|
||||
if (customSignOptions.entitlementsInherit) {
|
||||
return customSignOptions.entitlementsInherit;
|
||||
}
|
||||
const p = `entitlements.${entitlementsSuffix}.inherit.plist`;
|
||||
if (resourceList.includes(p)) {
|
||||
return path.join(this.packager.info.buildResourcesDir, p);
|
||||
}
|
||||
else {
|
||||
return (0, pathManager_1.getTemplatePath)("entitlements.mac.plist");
|
||||
}
|
||||
};
|
||||
const requirements = isMas || this.packager.platformSpecificBuildOptions.requirements == null
|
||||
? undefined
|
||||
: await this.packager.getResource(this.packager.platformSpecificBuildOptions.requirements);
|
||||
// harden by default for mac builds. Only harden mas builds if explicitly true (backward compatibility)
|
||||
const hardenedRuntime = isMas ? customSignOptions.hardenedRuntime === true : customSignOptions.hardenedRuntime !== false;
|
||||
return (filePath) => {
|
||||
const entitlements = getEntitlements(filePath);
|
||||
return {
|
||||
entitlements: entitlements || undefined,
|
||||
hardenedRuntime: hardenedRuntime !== null && hardenedRuntime !== void 0 ? hardenedRuntime : undefined,
|
||||
timestamp: customSignOptions.timestamp || undefined,
|
||||
requirements: requirements || undefined,
|
||||
additionalArguments: customSignOptions.additionalArguments || [],
|
||||
};
|
||||
};
|
||||
}
|
||||
static getCertificateTypes(isMas, isDevelopment) {
|
||||
if (isDevelopment) {
|
||||
return isMas ? ["Mac Developer", "Apple Development"] : ["Mac Developer", "Developer ID Application"];
|
||||
}
|
||||
return isMas ? ["Apple Distribution", "3rd Party Mac Developer Application"] : ["Developer ID Application"];
|
||||
}
|
||||
static isMasTarget(targetName) {
|
||||
return targetName === "mas" || targetName === "mas-dev";
|
||||
}
|
||||
static getPlatformTypeFromTarget(targetName) {
|
||||
if (targetName === "mas") {
|
||||
return "mas";
|
||||
}
|
||||
if (targetName === "mas-dev") {
|
||||
return "mas-dev";
|
||||
}
|
||||
return "mac";
|
||||
}
|
||||
/**
|
||||
* Returns true when hardened runtime will be active for signing.
|
||||
* For non-MAS builds it defaults to on; for MAS it defaults to off.
|
||||
*/
|
||||
static isHardenedRuntimeEnabledForSigning(isMas, config) {
|
||||
return isMas ? config.hardenedRuntime === true : config.hardenedRuntime !== false;
|
||||
}
|
||||
static assertSafePathForCommandUsage(pathValue, description) {
|
||||
if (/[\0\r\n"'`$;&|<>]/.test(pathValue)) {
|
||||
throw new builder_util_1.InvalidConfigurationError(`Invalid ${description}: contains unsupported shell-special characters`);
|
||||
}
|
||||
}
|
||||
static getNotarizeOptions(appPath) {
|
||||
const tool = "notarytool";
|
||||
const teamId = process.env.APPLE_TEAM_ID;
|
||||
const appleId = process.env.APPLE_ID;
|
||||
const appleIdPassword = process.env.APPLE_APP_SPECIFIC_PASSWORD;
|
||||
if (appleId || appleIdPassword) {
|
||||
if (!appleId) {
|
||||
throw new builder_util_1.InvalidConfigurationError(`APPLE_ID env var needs to be set`);
|
||||
}
|
||||
if (!appleIdPassword) {
|
||||
throw new builder_util_1.InvalidConfigurationError(`APPLE_APP_SPECIFIC_PASSWORD env var needs to be set`);
|
||||
}
|
||||
if (!teamId) {
|
||||
throw new builder_util_1.InvalidConfigurationError(`APPLE_TEAM_ID env var needs to be set`);
|
||||
}
|
||||
return { tool, appPath, appleId, appleIdPassword, teamId };
|
||||
}
|
||||
const appleApiKey = process.env.APPLE_API_KEY;
|
||||
const appleApiKeyId = process.env.APPLE_API_KEY_ID;
|
||||
const appleApiIssuer = process.env.APPLE_API_ISSUER;
|
||||
if (appleApiKey || appleApiKeyId || appleApiIssuer) {
|
||||
if (!appleApiKey || !appleApiKeyId || !appleApiIssuer) {
|
||||
throw new builder_util_1.InvalidConfigurationError(`Env vars APPLE_API_KEY, APPLE_API_KEY_ID and APPLE_API_ISSUER need to be set`);
|
||||
}
|
||||
return { tool, appPath, appleApiKey, appleApiKeyId, appleApiIssuer };
|
||||
}
|
||||
const keychain = process.env.APPLE_KEYCHAIN;
|
||||
const keychainProfile = process.env.APPLE_KEYCHAIN_PROFILE;
|
||||
if (keychainProfile) {
|
||||
let args = { keychainProfile };
|
||||
if (keychain) {
|
||||
args = { ...args, keychain };
|
||||
}
|
||||
return { tool, appPath, ...args };
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
async notarizeIfProvided(appPath) {
|
||||
const notarizeOptions = this.packager.platformSpecificBuildOptions.notarize;
|
||||
if (notarizeOptions === false) {
|
||||
builder_util_1.log.info({ reason: "`notarize` options were set explicitly `false`" }, "skipped macOS notarization");
|
||||
return;
|
||||
}
|
||||
const options = MacTargetHelper.getNotarizeOptions(appPath);
|
||||
if (!options) {
|
||||
builder_util_1.log.warn({ reason: "`notarize` options were unable to be generated" }, "skipped macOS notarization");
|
||||
return;
|
||||
}
|
||||
const { notarize } = await (0, dynamicImport_1.dynamicImport)("@electron/notarize");
|
||||
await notarize(options);
|
||||
builder_util_1.log.info(null, "notarization successful");
|
||||
}
|
||||
}
|
||||
exports.MacTargetHelper = MacTargetHelper;
|
||||
//# sourceMappingURL=MacTargetHelper.js.map
|
||||
1
electron/node_modules/app-builder-lib/out/mac/MacTargetHelper.js.map
generated
vendored
Normal file
1
electron/node_modules/app-builder-lib/out/mac/MacTargetHelper.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
48
electron/node_modules/app-builder-lib/out/macPackager.d.ts
generated
vendored
48
electron/node_modules/app-builder-lib/out/macPackager.d.ts
generated
vendored
|
|
@ -1,29 +1,49 @@
|
|||
import { SignOptions } from "@electron/osx-sign/dist/cjs/types";
|
||||
import { Identity } from "@electron/osx-sign/dist/cjs/util-identities";
|
||||
import { Arch, AsyncTaskManager } from "builder-util";
|
||||
import { SignOptions } from "electron-osx-sign";
|
||||
import { Lazy } from "lazy-val";
|
||||
import { MemoLazy, Nullish } from "builder-util-runtime";
|
||||
import { AppInfo } from "./appInfo";
|
||||
import { CodeSigningInfo, Identity } from "./codeSign/macCodeSign";
|
||||
import { CodeSigningInfo, CreateKeychainOptions } from "./codeSign/macCodeSign";
|
||||
import { Target } from "./core";
|
||||
import { AfterPackContext, ElectronPlatformName } from "./index";
|
||||
import { MacConfiguration } from "./options/macOptions";
|
||||
import { AfterPackContext } from "./index";
|
||||
import { MacTargetHelper } from "./mac/MacTargetHelper";
|
||||
import { MacConfiguration, MasConfiguration } from "./options/macOptions";
|
||||
import { Packager } from "./packager";
|
||||
import { PlatformPackager } from "./platformPackager";
|
||||
export default class MacPackager extends PlatformPackager<MacConfiguration> {
|
||||
readonly codeSigningInfo: Lazy<CodeSigningInfo>;
|
||||
import { DoPackOptions, PlatformPackager } from "./platformPackager";
|
||||
export type CustomMacSignOptions = SignOptions;
|
||||
export type CustomMacSign = (configuration: CustomMacSignOptions, packager: MacPackager) => Promise<void>;
|
||||
export declare class MacPackager extends PlatformPackager<MacConfiguration | MasConfiguration> {
|
||||
readonly codeSigningInfo: MemoLazy<CreateKeychainOptions | null, CodeSigningInfo>;
|
||||
private _iconPath;
|
||||
private _activePackConfig;
|
||||
readonly helper: MacTargetHelper;
|
||||
constructor(info: Packager);
|
||||
get defaultTarget(): Array<string>;
|
||||
/**
|
||||
* Get the merged configuration for a specific platform type
|
||||
*/
|
||||
private getPlatformConfig;
|
||||
expandArch(pattern: string, arch?: Arch | null): string[];
|
||||
protected prepareAppInfo(appInfo: AppInfo): AppInfo;
|
||||
getIconPath(): Promise<string | null>;
|
||||
createTargets(targets: Array<string>, mapper: (name: string, factory: (outDir: string) => Target) => void): void;
|
||||
protected doPack(outDir: string, appOutDir: string, platformName: ElectronPlatformName, arch: Arch, platformSpecificBuildOptions: MacConfiguration, targets: Array<Target>): Promise<any>;
|
||||
pack(outDir: string, arch: Arch, targets: Array<Target>, taskManager: AsyncTaskManager): Promise<any>;
|
||||
protected doPack(config: DoPackOptions<MacConfiguration>): Promise<any>;
|
||||
/**
|
||||
* Handle universal build packing
|
||||
*/
|
||||
private doUniversalPack;
|
||||
pack(outDir: string, arch: Arch, targets: Array<Target>, taskManager: AsyncTaskManager): Promise<void>;
|
||||
private packMasTargets;
|
||||
private packMacTargets;
|
||||
private signMas;
|
||||
/**
|
||||
* Main signing method with platform awareness
|
||||
*/
|
||||
private sign;
|
||||
private adjustSignOptions;
|
||||
protected doSign(opts: SignOptions): Promise<any>;
|
||||
protected doFlat(appPath: string, outFile: string, identity: Identity, keychain: string | null | undefined): Promise<any>;
|
||||
protected doSign(opts: SignOptions, customSignOptions: MacConfiguration | MasConfiguration, identity: Identity | null): Promise<void>;
|
||||
doFlat(appPath: string, outFile: string, identity: Identity, keychain: string | Nullish): Promise<any>;
|
||||
getElectronSrcDir(dist: string): string;
|
||||
getElectronDestinationDir(appOutDir: string): string;
|
||||
applyCommonInfo(appPlist: any, contentsPath: string): Promise<void>;
|
||||
protected signApp(packContext: AfterPackContext, isAsar: boolean): Promise<any>;
|
||||
protected signApp(packContext: AfterPackContext, isAsar: boolean): Promise<boolean>;
|
||||
}
|
||||
|
|
|
|||
598
electron/node_modules/app-builder-lib/out/macPackager.js
generated
vendored
598
electron/node_modules/app-builder-lib/out/macPackager.js
generated
vendored
|
|
@ -1,54 +1,103 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const bluebird_lst_1 = require("bluebird-lst");
|
||||
exports.MacPackager = void 0;
|
||||
const builder_util_1 = require("builder-util");
|
||||
const electron_osx_sign_1 = require("electron-osx-sign");
|
||||
const builder_util_runtime_1 = require("builder-util-runtime");
|
||||
const fs = require("fs/promises");
|
||||
const promises_1 = require("fs/promises");
|
||||
const lazy_val_1 = require("lazy-val");
|
||||
const path = require("path");
|
||||
const fs_1 = require("builder-util/out/fs");
|
||||
const promise_1 = require("builder-util/out/promise");
|
||||
const appInfo_1 = require("./appInfo");
|
||||
const macCodeSign_1 = require("./codeSign/macCodeSign");
|
||||
const core_1 = require("./core");
|
||||
const MacTargetHelper_1 = require("./mac/MacTargetHelper");
|
||||
const platformPackager_1 = require("./platformPackager");
|
||||
const ArchiveTarget_1 = require("./targets/ArchiveTarget");
|
||||
const pkg_1 = require("./targets/pkg");
|
||||
const targetFactory_1 = require("./targets/targetFactory");
|
||||
const dynamicImport_1 = require("./util/dynamicImport");
|
||||
const macosVersion_1 = require("./util/macosVersion");
|
||||
const pathManager_1 = require("./util/pathManager");
|
||||
const fs = require("fs/promises");
|
||||
const macroExpander_1 = require("./util/macroExpander");
|
||||
const resolve_1 = require("./util/resolve");
|
||||
class MacPackager extends platformPackager_1.PlatformPackager {
|
||||
constructor(info) {
|
||||
super(info, core_1.Platform.MAC);
|
||||
this.codeSigningInfo = new lazy_val_1.Lazy(() => {
|
||||
this.codeSigningInfo = new builder_util_runtime_1.MemoLazy(() => {
|
||||
const cscLink = this.getCscLink();
|
||||
if (cscLink == null || process.platform !== "darwin") {
|
||||
return Promise.resolve({ keychainFile: process.env.CSC_KEYCHAIN || null });
|
||||
return null;
|
||||
}
|
||||
return macCodeSign_1.createKeychain({
|
||||
const selected = {
|
||||
tmpDir: this.info.tempDirManager,
|
||||
cscLink,
|
||||
cscKeyPassword: this.getCscPassword(),
|
||||
cscILink: platformPackager_1.chooseNotNull(this.platformSpecificBuildOptions.cscInstallerLink, process.env.CSC_INSTALLER_LINK),
|
||||
cscIKeyPassword: platformPackager_1.chooseNotNull(this.platformSpecificBuildOptions.cscInstallerKeyPassword, process.env.CSC_INSTALLER_KEY_PASSWORD),
|
||||
cscILink: (0, platformPackager_1.chooseNotNull)(this.platformSpecificBuildOptions.cscInstallerLink, process.env.CSC_INSTALLER_LINK),
|
||||
cscIKeyPassword: (0, platformPackager_1.chooseNotNull)(this.platformSpecificBuildOptions.cscInstallerKeyPassword, process.env.CSC_INSTALLER_KEY_PASSWORD),
|
||||
currentDir: this.projectDir,
|
||||
}).then(result => {
|
||||
const keychainFile = result.keychainFile;
|
||||
if (keychainFile != null) {
|
||||
this.info.disposeOnBuildFinish(() => macCodeSign_1.removeKeychain(keychainFile));
|
||||
}
|
||||
return result;
|
||||
});
|
||||
};
|
||||
return selected;
|
||||
}, async (selected) => {
|
||||
if (selected) {
|
||||
return (0, macCodeSign_1.createKeychain)(selected).then(result => {
|
||||
const keychainFile = result.keychainFile;
|
||||
if (keychainFile != null) {
|
||||
this.info.disposeOnBuildFinish(() => (0, macCodeSign_1.removeKeychain)(keychainFile));
|
||||
}
|
||||
return result;
|
||||
});
|
||||
}
|
||||
return Promise.resolve({ keychainFile: process.env.CSC_KEYCHAIN || null });
|
||||
});
|
||||
this._iconPath = new lazy_val_1.Lazy(() => this.getOrConvertIcon("icns"));
|
||||
// Set/cleared in doPack so applyCommonInfo can read the per-pack platformSpecificBuildOptions
|
||||
// (the framework call chain doesn't thread it through to applyCommonInfo). Fixes #8909.
|
||||
this._activePackConfig = null;
|
||||
this.helper = new MacTargetHelper_1.MacTargetHelper(this);
|
||||
}
|
||||
get defaultTarget() {
|
||||
return this.info.framework.macOsDefaultTargets;
|
||||
}
|
||||
/**
|
||||
* Get the merged configuration for a specific platform type
|
||||
*/
|
||||
getPlatformConfig(platformType) {
|
||||
let config;
|
||||
let isDevelopment = false;
|
||||
let platformName;
|
||||
switch (platformType) {
|
||||
case "mas":
|
||||
config = (0, builder_util_1.deepAssign)({}, this.platformSpecificBuildOptions, this.config.mas);
|
||||
isDevelopment = false;
|
||||
platformName = "mas";
|
||||
break;
|
||||
case "mas-dev":
|
||||
config = (0, builder_util_1.deepAssign)({}, this.platformSpecificBuildOptions, this.config.mas, this.config.masDev, {
|
||||
type: "development",
|
||||
});
|
||||
isDevelopment = true;
|
||||
platformName = "mas";
|
||||
break;
|
||||
case "mac":
|
||||
default:
|
||||
config = this.platformSpecificBuildOptions;
|
||||
isDevelopment = false;
|
||||
platformName = this.platform.nodeName;
|
||||
break;
|
||||
}
|
||||
return { type: platformType, config, isDevelopment, platformName };
|
||||
}
|
||||
expandArch(pattern, arch) {
|
||||
if (arch === builder_util_1.Arch.universal) {
|
||||
// Universal build has `app-x64.asar.unpacked` & `app-arm64.asar.unpacked`
|
||||
return [(0, macroExpander_1.expandMacro)(pattern, builder_util_1.Arch[builder_util_1.Arch.arm64], this.appInfo, {}, false), (0, macroExpander_1.expandMacro)(pattern, builder_util_1.Arch[builder_util_1.Arch.x64], this.appInfo, {}, false)];
|
||||
}
|
||||
// Every other build keeps the name as `app.asar.unpacked`
|
||||
return [(0, macroExpander_1.expandMacro)(pattern, null, this.appInfo, {}, false)];
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
prepareAppInfo(appInfo) {
|
||||
return new appInfo_1.AppInfo(this.info, this.platformSpecificBuildOptions.bundleVersion, this.platformSpecificBuildOptions);
|
||||
// codesign requires the filename to be normalized to the NFD form
|
||||
return new appInfo_1.AppInfo(this.info, this.platformSpecificBuildOptions.bundleVersion, this.platformSpecificBuildOptions, true);
|
||||
}
|
||||
async getIconPath() {
|
||||
return this._iconPath.value;
|
||||
|
|
@ -59,7 +108,6 @@ class MacPackager extends platformPackager_1.PlatformPackager {
|
|||
case core_1.DIR_TARGET:
|
||||
break;
|
||||
case "dmg": {
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const { DmgTarget } = require("dmg-builder");
|
||||
mapper(name, outDir => new DmgTarget(this, outDir));
|
||||
break;
|
||||
|
|
@ -72,258 +120,229 @@ class MacPackager extends platformPackager_1.PlatformPackager {
|
|||
mapper(name, outDir => new pkg_1.PkgTarget(this, outDir));
|
||||
break;
|
||||
default:
|
||||
mapper(name, outDir => (name === "mas" || name === "mas-dev" ? new targetFactory_1.NoOpTarget(name) : targetFactory_1.createCommonTarget(name, outDir, this)));
|
||||
mapper(name, outDir => (MacTargetHelper_1.MacTargetHelper.isMasTarget(name) ? new targetFactory_1.NoOpTarget(name) : (0, targetFactory_1.createCommonTarget)(name, outDir, this)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
async doPack(outDir, appOutDir, platformName, arch, platformSpecificBuildOptions, targets) {
|
||||
var _a;
|
||||
switch (arch) {
|
||||
default: {
|
||||
return super.doPack(outDir, appOutDir, platformName, arch, platformSpecificBuildOptions, targets);
|
||||
async doPack(config) {
|
||||
if (config.arch === builder_util_1.Arch.universal) {
|
||||
return this.doUniversalPack(config);
|
||||
}
|
||||
// Bridge the per-pack platformSpecificBuildOptions to applyCommonInfo, which is called deep in the
|
||||
// framework stack (doPack → beforeCopyExtraFiles → createMacApp → applyCommonInfo) without it.
|
||||
this._activePackConfig = config.platformSpecificBuildOptions;
|
||||
try {
|
||||
return await super.doPack(config);
|
||||
}
|
||||
finally {
|
||||
this._activePackConfig = null;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Handle universal build packing
|
||||
*/
|
||||
async doUniversalPack(config) {
|
||||
var _a, _b, _c;
|
||||
this._activePackConfig = config.platformSpecificBuildOptions;
|
||||
try {
|
||||
const { outDir, appOutDir, platformName, arch, platformSpecificBuildOptions, targets } = config;
|
||||
const outDirName = (arch) => `${appOutDir}-${builder_util_1.Arch[arch]}-temp`;
|
||||
const options = {
|
||||
...config,
|
||||
options: {
|
||||
sign: false,
|
||||
disableAsarIntegrity: true,
|
||||
disableFuses: true,
|
||||
},
|
||||
};
|
||||
const x64Arch = builder_util_1.Arch.x64;
|
||||
const x64AppOutDir = outDirName(x64Arch);
|
||||
await super.doPack({ ...options, appOutDir: x64AppOutDir, arch: x64Arch });
|
||||
if (this.info.cancellationToken.cancelled) {
|
||||
return;
|
||||
}
|
||||
case builder_util_1.Arch.universal: {
|
||||
const x64Arch = builder_util_1.Arch.x64;
|
||||
const x64AppOutDir = appOutDir + "--" + builder_util_1.Arch[x64Arch];
|
||||
await super.doPack(outDir, x64AppOutDir, platformName, x64Arch, platformSpecificBuildOptions, targets, false, true);
|
||||
const arm64Arch = builder_util_1.Arch.arm64;
|
||||
const arm64AppOutPath = appOutDir + "--" + builder_util_1.Arch[arm64Arch];
|
||||
await super.doPack(outDir, arm64AppOutPath, platformName, arm64Arch, platformSpecificBuildOptions, targets, false, true);
|
||||
const framework = this.info.framework;
|
||||
builder_util_1.log.info({
|
||||
platform: platformName,
|
||||
arch: builder_util_1.Arch[arch],
|
||||
[`${framework.name}`]: framework.version,
|
||||
appOutDir: builder_util_1.log.filePath(appOutDir),
|
||||
}, `packaging`);
|
||||
const appFile = `${this.appInfo.productFilename}.app`;
|
||||
const { makeUniversalApp } = require("@electron/universal");
|
||||
await makeUniversalApp({
|
||||
x64AppPath: path.join(x64AppOutDir, appFile),
|
||||
arm64AppPath: path.join(arm64AppOutPath, appFile),
|
||||
outAppPath: path.join(appOutDir, appFile),
|
||||
force: true,
|
||||
mergeASARs: (_a = platformSpecificBuildOptions.mergeASARs) !== null && _a !== void 0 ? _a : true,
|
||||
singleArchFiles: platformSpecificBuildOptions.singleArchFiles,
|
||||
x64ArchFiles: platformSpecificBuildOptions.x64ArchFiles,
|
||||
});
|
||||
await fs.rm(x64AppOutDir, { recursive: true, force: true });
|
||||
await fs.rm(arm64AppOutPath, { recursive: true, force: true });
|
||||
// Give users a final opportunity to perform things on the combined universal package before signing
|
||||
const packContext = {
|
||||
appOutDir,
|
||||
outDir,
|
||||
arch,
|
||||
targets,
|
||||
packager: this,
|
||||
electronPlatformName: platformName,
|
||||
};
|
||||
await this.info.afterPack(packContext);
|
||||
const arm64Arch = builder_util_1.Arch.arm64;
|
||||
const arm64AppOutPath = outDirName(arm64Arch);
|
||||
await super.doPack({ ...options, appOutDir: arm64AppOutPath, arch: arm64Arch });
|
||||
if (this.info.cancellationToken.cancelled) {
|
||||
return;
|
||||
}
|
||||
const framework = this.info.framework;
|
||||
builder_util_1.log.info({
|
||||
platform: platformName,
|
||||
arch: builder_util_1.Arch[arch],
|
||||
[`${framework.name}`]: framework.version,
|
||||
appOutDir: builder_util_1.log.filePath(appOutDir),
|
||||
}, `packaging`);
|
||||
const appFile = `${this.appInfo.productFilename}.app`;
|
||||
// Make sure the Assets.car file is the same for both architectures
|
||||
const safeX64AppOutDir = (0, builder_util_1.sanitizeDirPath)(x64AppOutDir);
|
||||
const safeArm64AppOutPath = (0, builder_util_1.sanitizeDirPath)(arm64AppOutPath);
|
||||
const safeAppOutDir = (0, builder_util_1.sanitizeDirPath)(appOutDir);
|
||||
const sourceCatalogPath = path.join(safeX64AppOutDir, appFile, "Contents/Resources/Assets.car");
|
||||
if (await (0, builder_util_1.exists)(sourceCatalogPath)) {
|
||||
const targetCatalogPath = path.join(safeArm64AppOutPath, appFile, "Contents/Resources/Assets.car");
|
||||
await fs.copyFile(sourceCatalogPath, targetCatalogPath);
|
||||
}
|
||||
const { makeUniversalApp } = await (0, dynamicImport_1.dynamicImport)("@electron/universal");
|
||||
await makeUniversalApp({
|
||||
x64AppPath: path.join(safeX64AppOutDir, appFile),
|
||||
arm64AppPath: path.join(safeArm64AppOutPath, appFile),
|
||||
outAppPath: path.join(safeAppOutDir, appFile),
|
||||
force: true,
|
||||
mergeASARs: (_a = platformSpecificBuildOptions.mergeASARs) !== null && _a !== void 0 ? _a : true, // must be ?? to allow false
|
||||
singleArchFiles: platformSpecificBuildOptions.singleArchFiles || undefined,
|
||||
x64ArchFiles: platformSpecificBuildOptions.x64ArchFiles || undefined,
|
||||
});
|
||||
await fs.rm(x64AppOutDir, { recursive: true, force: true });
|
||||
await fs.rm(arm64AppOutPath, { recursive: true, force: true });
|
||||
// Give users a final opportunity to perform things on the combined universal package before signing
|
||||
const packContext = {
|
||||
appOutDir,
|
||||
outDir,
|
||||
arch,
|
||||
targets,
|
||||
packager: this,
|
||||
electronPlatformName: platformName,
|
||||
};
|
||||
await this.info.emitAfterPack(packContext);
|
||||
if (this.info.cancellationToken.cancelled) {
|
||||
return;
|
||||
}
|
||||
await this.doAddElectronFuses(packContext);
|
||||
// Mirror the base-class guard: skip signing when the caller explicitly set sign:false
|
||||
// (e.g. packMasTargets passes sign:false so that signMas() is the sole signing step).
|
||||
if ((_c = (_b = config.options) === null || _b === void 0 ? void 0 : _b.sign) !== null && _c !== void 0 ? _c : true) {
|
||||
await this.doSignAfterPack(outDir, appOutDir, platformName, arch, platformSpecificBuildOptions, targets);
|
||||
break;
|
||||
}
|
||||
}
|
||||
finally {
|
||||
this._activePackConfig = null;
|
||||
}
|
||||
}
|
||||
async pack(outDir, arch, targets, taskManager) {
|
||||
let nonMasPromise = null;
|
||||
const hasMas = targets.length !== 0 && targets.some(it => it.name === "mas" || it.name === "mas-dev");
|
||||
const masTargets = targets.filter(it => MacTargetHelper_1.MacTargetHelper.isMasTarget(it.name));
|
||||
const nonMasTargets = targets.filter(it => !MacTargetHelper_1.MacTargetHelper.isMasTarget(it.name));
|
||||
const prepackaged = this.packagerOptions.prepackaged;
|
||||
const hasMas = masTargets.length > 0;
|
||||
// mas always first
|
||||
await this.packMasTargets(outDir, arch, masTargets, prepackaged);
|
||||
// Mirror master's condition: skip the non-MAS darwin pack only when there are exclusively MAS
|
||||
// targets (hasMas=true, targets.length=1). DIR_TARGET passes targets=[] to pack() because
|
||||
// MacPackager.createTargets() doesn't call mapper() for it, so hasMas=false and doPack still runs.
|
||||
if (!hasMas || targets.length > 1) {
|
||||
const appPath = prepackaged == null ? path.join(this.computeAppOutDir(outDir, arch), `${this.appInfo.productFilename}.app`) : prepackaged;
|
||||
nonMasPromise = (prepackaged
|
||||
? Promise.resolve()
|
||||
: this.doPack(outDir, path.dirname(appPath), this.platform.nodeName, arch, this.platformSpecificBuildOptions, targets)).then(() => this.packageInDistributableFormat(appPath, arch, targets, taskManager));
|
||||
}
|
||||
for (const target of targets) {
|
||||
const targetName = target.name;
|
||||
if (!(targetName === "mas" || targetName === "mas-dev")) {
|
||||
continue;
|
||||
}
|
||||
const masBuildOptions = builder_util_1.deepAssign({}, this.platformSpecificBuildOptions, this.config.mas);
|
||||
if (targetName === "mas-dev") {
|
||||
builder_util_1.deepAssign(masBuildOptions, this.config.masDev, {
|
||||
type: "development",
|
||||
});
|
||||
}
|
||||
const targetOutDir = path.join(outDir, `${targetName}${builder_util_1.getArchSuffix(arch)}`);
|
||||
if (prepackaged == null) {
|
||||
await this.doPack(outDir, targetOutDir, "mas", arch, masBuildOptions, [target]);
|
||||
await this.sign(path.join(targetOutDir, `${this.appInfo.productFilename}.app`), targetOutDir, masBuildOptions, arch);
|
||||
}
|
||||
else {
|
||||
await this.sign(prepackaged, targetOutDir, masBuildOptions, arch);
|
||||
}
|
||||
}
|
||||
if (nonMasPromise != null) {
|
||||
await nonMasPromise;
|
||||
await this.packMacTargets(outDir, arch, nonMasTargets, prepackaged, taskManager);
|
||||
}
|
||||
}
|
||||
async sign(appPath, outDir, masOptions, arch) {
|
||||
if (!macCodeSign_1.isSignAllowed()) {
|
||||
return;
|
||||
}
|
||||
const isMas = masOptions != null;
|
||||
const options = masOptions == null ? this.platformSpecificBuildOptions : masOptions;
|
||||
const qualifier = options.identity;
|
||||
if (!isMas && qualifier === null) {
|
||||
if (this.forceCodeSigning) {
|
||||
throw new builder_util_1.InvalidConfigurationError("identity explicitly is set to null, but forceCodeSigning is set to true");
|
||||
async packMasTargets(outDir, arch, targets, prepackaged) {
|
||||
const resolvedOutDir = path.resolve(outDir);
|
||||
MacTargetHelper_1.MacTargetHelper.assertSafePathForCommandUsage(resolvedOutDir, "output directory");
|
||||
for (const target of targets) {
|
||||
const platformType = MacTargetHelper_1.MacTargetHelper.getPlatformTypeFromTarget(target.name);
|
||||
const platformConfig = this.getPlatformConfig(platformType);
|
||||
const targetOutDir = path.resolve(resolvedOutDir, `${target.name}${(0, builder_util_1.getArchSuffix)(arch, this.platformSpecificBuildOptions.defaultArch)}`);
|
||||
MacTargetHelper_1.MacTargetHelper.assertSafePathForCommandUsage(targetOutDir, "target output directory");
|
||||
const relativeTargetOutDir = path.relative(resolvedOutDir, targetOutDir);
|
||||
if (relativeTargetOutDir.startsWith("..") || path.isAbsolute(relativeTargetOutDir)) {
|
||||
throw new builder_util_1.InvalidConfigurationError(`Invalid target output directory: ${targetOutDir}`);
|
||||
}
|
||||
builder_util_1.log.info({ reason: "identity explicitly is set to null" }, "skipped macOS code signing");
|
||||
return;
|
||||
if (prepackaged == null) {
|
||||
await this.doPack({
|
||||
outDir: resolvedOutDir,
|
||||
appOutDir: targetOutDir,
|
||||
platformName: platformConfig.platformName,
|
||||
arch,
|
||||
platformSpecificBuildOptions: platformConfig.config,
|
||||
targets: [target],
|
||||
options: { sign: false },
|
||||
});
|
||||
MacTargetHelper_1.MacTargetHelper.assertSafePathForCommandUsage(this.appInfo.productFilename, "product filename");
|
||||
await this.signMas(path.resolve(targetOutDir, `${path.basename(this.appInfo.productFilename)}.app`), targetOutDir, platformConfig, arch);
|
||||
}
|
||||
else {
|
||||
await this.signMas(prepackaged, targetOutDir, platformConfig, arch);
|
||||
}
|
||||
}
|
||||
}
|
||||
async packMacTargets(outDir, arch, targets, prepackaged, taskManager) {
|
||||
const appPath = prepackaged == null ? path.join(this.computeAppOutDir(outDir, arch), `${path.basename(this.appInfo.productFilename)}.app`) : prepackaged;
|
||||
if (prepackaged == null) {
|
||||
const platformConfig = this.getPlatformConfig("mac");
|
||||
await this.doPack({
|
||||
outDir,
|
||||
appOutDir: path.dirname(appPath),
|
||||
platformName: platformConfig.platformName,
|
||||
arch,
|
||||
platformSpecificBuildOptions: platformConfig.config,
|
||||
targets,
|
||||
});
|
||||
}
|
||||
this.packageInDistributableFormat(appPath, arch, targets, taskManager);
|
||||
}
|
||||
async signMas(appPath, outDir, platformConfig, arch) {
|
||||
const signed = await this.sign(appPath, outDir, platformConfig.config, arch, true);
|
||||
return signed;
|
||||
}
|
||||
/**
|
||||
* Main signing method with platform awareness
|
||||
*/
|
||||
async sign(appPath, outDir, options, arch, isMas = false) {
|
||||
if (!(0, macCodeSign_1.isSignAllowed)()) {
|
||||
return false;
|
||||
}
|
||||
const config = options !== null && options !== void 0 ? options : this.platformSpecificBuildOptions;
|
||||
const qualifier = config.identity;
|
||||
if (qualifier === null) {
|
||||
return this.helper.handleNullIdentity();
|
||||
}
|
||||
const keychainFile = (await this.codeSigningInfo.value).keychainFile;
|
||||
const explicitType = options.type;
|
||||
const explicitType = config.type;
|
||||
const type = explicitType || "distribution";
|
||||
const isDevelopment = type === "development";
|
||||
const certificateTypes = getCertificateTypes(isMas, isDevelopment);
|
||||
let identity = null;
|
||||
for (const certificateType of certificateTypes) {
|
||||
identity = await macCodeSign_1.findIdentity(certificateType, qualifier, keychainFile);
|
||||
if (identity != null) {
|
||||
break;
|
||||
}
|
||||
const identity = await this.helper.findSigningIdentity(isMas, isDevelopment, qualifier, keychainFile, config);
|
||||
if (!identity) {
|
||||
return false;
|
||||
}
|
||||
if (identity == null) {
|
||||
if (!isMas && !isDevelopment && explicitType !== "distribution") {
|
||||
identity = await macCodeSign_1.findIdentity("Mac Developer", qualifier, keychainFile);
|
||||
if (identity != null) {
|
||||
builder_util_1.log.warn("Mac Developer is used to sign app — it is only for development and testing, not for production");
|
||||
}
|
||||
}
|
||||
if (identity == null) {
|
||||
await macCodeSign_1.reportError(isMas, certificateTypes, qualifier, keychainFile, this.forceCodeSigning);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!macosVersion_1.isMacOsHighSierra()) {
|
||||
if (!(0, macosVersion_1.isMacOsHighSierra)()) {
|
||||
throw new builder_util_1.InvalidConfigurationError("macOS High Sierra 10.13.6 is required to sign");
|
||||
}
|
||||
let filter = options.signIgnore;
|
||||
if (Array.isArray(filter)) {
|
||||
if (filter.length == 0) {
|
||||
filter = null;
|
||||
}
|
||||
const signOptions = await this.helper.buildSignOptions(appPath, identity, type, isMas, config, keychainFile, arch);
|
||||
await this.doSign(signOptions, config, identity);
|
||||
// Handle MAS installer creation
|
||||
if (isMas && !isDevelopment && outDir) {
|
||||
await this.helper.createMasInstaller(appPath, outDir, config, keychainFile, isDevelopment, arch);
|
||||
}
|
||||
else if (filter != null) {
|
||||
filter = filter.length === 0 ? null : [filter];
|
||||
// Handle notarization for non-MAS builds
|
||||
if (!isMas) {
|
||||
await this.helper.notarizeIfProvided(appPath);
|
||||
}
|
||||
const filterRe = filter == null ? null : filter.map(it => new RegExp(it));
|
||||
let binaries = options.binaries || undefined;
|
||||
if (binaries) {
|
||||
// Accept absolute paths for external binaries, else resolve relative paths from the artifact's app Contents path.
|
||||
binaries = await Promise.all(binaries.map(async (destination) => {
|
||||
if (await fs_1.statOrNull(destination)) {
|
||||
return destination;
|
||||
}
|
||||
return path.resolve(appPath, destination);
|
||||
}));
|
||||
builder_util_1.log.info("Signing addtional user-defined binaries: " + JSON.stringify(binaries, null, 1));
|
||||
}
|
||||
const signOptions = {
|
||||
"identity-validation": false,
|
||||
// https://github.com/electron-userland/electron-builder/issues/1699
|
||||
// kext are signed by the chipset manufacturers. You need a special certificate (only available on request) from Apple to be able to sign kext.
|
||||
ignore: (file) => {
|
||||
if (filterRe != null) {
|
||||
for (const regExp of filterRe) {
|
||||
if (regExp.test(file)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (file.endsWith(".kext") ||
|
||||
file.startsWith("/Contents/PlugIns", appPath.length) ||
|
||||
file.includes("/node_modules/puppeteer/.local-chromium") ||
|
||||
file.includes("/node_modules/playwright-firefox/.local-browsers") ||
|
||||
file.includes("/node_modules/playwright/.local-browsers"));
|
||||
/* Those are browser automating modules, browser (chromium, nightly) cannot be signed
|
||||
https://github.com/electron-userland/electron-builder/issues/2010
|
||||
https://github.com/electron-userland/electron-builder/issues/5383
|
||||
*/
|
||||
},
|
||||
identity: identity,
|
||||
type,
|
||||
platform: isMas ? "mas" : "darwin",
|
||||
version: this.config.electronVersion,
|
||||
app: appPath,
|
||||
keychain: keychainFile || undefined,
|
||||
binaries,
|
||||
timestamp: isMas ? masOptions === null || masOptions === void 0 ? void 0 : masOptions.timestamp : options.timestamp,
|
||||
requirements: isMas || this.platformSpecificBuildOptions.requirements == null ? undefined : await this.getResource(this.platformSpecificBuildOptions.requirements),
|
||||
// https://github.com/electron-userland/electron-osx-sign/issues/196
|
||||
// will fail on 10.14.5+ because a signed but unnotarized app is also rejected.
|
||||
"gatekeeper-assess": options.gatekeeperAssess === true,
|
||||
// https://github.com/electron-userland/electron-builder/issues/1480
|
||||
"strict-verify": options.strictVerify,
|
||||
hardenedRuntime: isMas ? masOptions && masOptions.hardenedRuntime === true : options.hardenedRuntime !== false,
|
||||
};
|
||||
await this.adjustSignOptions(signOptions, masOptions);
|
||||
builder_util_1.log.info({
|
||||
file: builder_util_1.log.filePath(appPath),
|
||||
identityName: identity.name,
|
||||
identityHash: identity.hash,
|
||||
provisioningProfile: signOptions["provisioning-profile"] || "none",
|
||||
}, "signing");
|
||||
await this.doSign(signOptions);
|
||||
// https://github.com/electron-userland/electron-builder/issues/1196#issuecomment-312310209
|
||||
if (masOptions != null && !isDevelopment) {
|
||||
const certType = isDevelopment ? "Mac Developer" : "3rd Party Mac Developer Installer";
|
||||
const masInstallerIdentity = await macCodeSign_1.findIdentity(certType, masOptions.identity, keychainFile);
|
||||
if (masInstallerIdentity == null) {
|
||||
throw new builder_util_1.InvalidConfigurationError(`Cannot find valid "${certType}" identity to sign MAS installer, please see https://electron.build/code-signing`);
|
||||
}
|
||||
// mas uploaded to AppStore, so, use "-" instead of space for name
|
||||
const artifactName = this.expandArtifactNamePattern(masOptions, "pkg", arch);
|
||||
const artifactPath = path.join(outDir, artifactName);
|
||||
await this.doFlat(appPath, artifactPath, masInstallerIdentity, keychainFile);
|
||||
await this.dispatchArtifactCreated(artifactPath, null, builder_util_1.Arch.x64, this.computeSafeArtifactName(artifactName, "pkg", arch, true, this.platformSpecificBuildOptions.defaultArch));
|
||||
}
|
||||
}
|
||||
async adjustSignOptions(signOptions, masOptions) {
|
||||
const resourceList = await this.resourceList;
|
||||
const customSignOptions = masOptions || this.platformSpecificBuildOptions;
|
||||
const entitlementsSuffix = masOptions == null ? "mac" : "mas";
|
||||
let entitlements = customSignOptions.entitlements;
|
||||
if (entitlements == null) {
|
||||
const p = `entitlements.${entitlementsSuffix}.plist`;
|
||||
if (resourceList.includes(p)) {
|
||||
entitlements = path.join(this.info.buildResourcesDir, p);
|
||||
}
|
||||
else {
|
||||
entitlements = pathManager_1.getTemplatePath("entitlements.mac.plist");
|
||||
}
|
||||
}
|
||||
signOptions.entitlements = entitlements;
|
||||
let entitlementsInherit = customSignOptions.entitlementsInherit;
|
||||
if (entitlementsInherit == null) {
|
||||
const p = `entitlements.${entitlementsSuffix}.inherit.plist`;
|
||||
if (resourceList.includes(p)) {
|
||||
entitlementsInherit = path.join(this.info.buildResourcesDir, p);
|
||||
}
|
||||
else {
|
||||
entitlementsInherit = pathManager_1.getTemplatePath("entitlements.mac.plist");
|
||||
}
|
||||
}
|
||||
signOptions["entitlements-inherit"] = entitlementsInherit;
|
||||
if (customSignOptions.provisioningProfile != null) {
|
||||
signOptions["provisioning-profile"] = customSignOptions.provisioningProfile;
|
||||
}
|
||||
signOptions["entitlements-loginhelper"] = customSignOptions.entitlementsLoginHelper;
|
||||
return true;
|
||||
}
|
||||
//noinspection JSMethodCanBeStatic
|
||||
async doSign(opts) {
|
||||
return electron_osx_sign_1.signAsync(opts);
|
||||
async doSign(opts, customSignOptions, identity) {
|
||||
const customSign = await (0, resolve_1.resolveFunction)(this.appInfo.type, customSignOptions.sign, "sign", await this.info.getWorkspaceRoot());
|
||||
const { app, platform, type, provisioningProfile } = opts;
|
||||
builder_util_1.log.info({
|
||||
file: builder_util_1.log.filePath(app),
|
||||
platform,
|
||||
type,
|
||||
identityName: (identity === null || identity === void 0 ? void 0 : identity.name) || "none",
|
||||
identityHash: (identity === null || identity === void 0 ? void 0 : identity.hash) || "none",
|
||||
provisioningProfile: provisioningProfile || "none",
|
||||
}, customSign ? "executing custom sign" : "signing");
|
||||
return customSign ? Promise.resolve(customSign(opts, this)) : (0, macCodeSign_1.sign)({ ...opts, identity: identity ? identity.name : undefined });
|
||||
}
|
||||
//noinspection JSMethodCanBeStatic
|
||||
async doFlat(appPath, outFile, identity, keychain) {
|
||||
const safeAppPath = (0, builder_util_1.sanitizeDirPath)(appPath);
|
||||
const safeOutFile = (0, builder_util_1.sanitizeDirPath)(outFile);
|
||||
// productbuild doesn't created directory for out file
|
||||
await promises_1.mkdir(path.dirname(outFile), { recursive: true });
|
||||
const args = pkg_1.prepareProductBuildArgs(identity, keychain);
|
||||
args.push("--component", appPath, "/Applications");
|
||||
args.push(outFile);
|
||||
return await builder_util_1.exec("productbuild", args);
|
||||
await (0, promises_1.mkdir)(path.dirname(safeOutFile), { recursive: true });
|
||||
const args = (0, pkg_1.prepareProductBuildArgs)(identity, keychain);
|
||||
args.push("--component", safeAppPath, "/Applications");
|
||||
args.push(safeOutFile);
|
||||
return await (0, builder_util_1.exec)("productbuild", args);
|
||||
}
|
||||
getElectronSrcDir(dist) {
|
||||
return path.resolve(this.projectDir, dist, this.info.framework.distMacOsAppName);
|
||||
|
|
@ -333,67 +352,94 @@ class MacPackager extends platformPackager_1.PlatformPackager {
|
|||
}
|
||||
// todo fileAssociations
|
||||
async applyCommonInfo(appPlist, contentsPath) {
|
||||
var _a;
|
||||
const appInfo = this.appInfo;
|
||||
const appFilename = appInfo.productFilename;
|
||||
// https://github.com/electron-userland/electron-builder/issues/1278
|
||||
appPlist.CFBundleExecutable = appFilename.endsWith(" Helper") ? appFilename.substring(0, appFilename.length - " Helper".length) : appFilename;
|
||||
const icon = await this.getIconPath();
|
||||
if (icon != null) {
|
||||
const resourcesPath = path.join(contentsPath, "Resources");
|
||||
// Support both legacy `.icns` and modern `.icon` (Icon Composer) inputs via `mac.icon`.
|
||||
// Prefer `.icon` if provided; still accept `.icns`.
|
||||
const configuredIcon = this.platformSpecificBuildOptions.icon;
|
||||
const isIconComposer = typeof configuredIcon === "string" && configuredIcon.toLowerCase().endsWith(".icon");
|
||||
// Set the app name
|
||||
appPlist.CFBundleName = appInfo.productName;
|
||||
appPlist.CFBundleDisplayName = appInfo.productName;
|
||||
// Bundle legacy `icns` format - this should also run when `.icon` is provided
|
||||
const setIcnsFile = async (iconPath) => {
|
||||
const oldIcon = appPlist.CFBundleIconFile;
|
||||
const resourcesPath = path.join(contentsPath, "Resources");
|
||||
if (oldIcon != null) {
|
||||
await fs_1.unlinkIfExists(path.join(resourcesPath, oldIcon));
|
||||
await (0, builder_util_1.unlinkIfExists)(path.join(resourcesPath, oldIcon));
|
||||
}
|
||||
const iconFileName = "icon.icns";
|
||||
appPlist.CFBundleIconFile = iconFileName;
|
||||
await fs_1.copyFile(icon, path.join(resourcesPath, iconFileName));
|
||||
await (0, builder_util_1.copyFile)(iconPath, path.join(resourcesPath, iconFileName));
|
||||
};
|
||||
const icnsFilePath = await this.getIconPath();
|
||||
if (icnsFilePath != null) {
|
||||
await setIcnsFile(icnsFilePath);
|
||||
}
|
||||
// Bundle new `icon` format
|
||||
if (isIconComposer && configuredIcon) {
|
||||
const iconComposerPath = await this.getResource(configuredIcon);
|
||||
if (iconComposerPath) {
|
||||
const { assetCatalog } = await this.generateAssetCatalogData(iconComposerPath);
|
||||
// Create and setup the asset catalog
|
||||
appPlist.CFBundleIconName = "Icon";
|
||||
await fs.writeFile(path.join(resourcesPath, "Assets.car"), assetCatalog);
|
||||
}
|
||||
}
|
||||
appPlist.CFBundleName = appInfo.productName;
|
||||
appPlist.CFBundleDisplayName = appInfo.productName;
|
||||
const minimumSystemVersion = this.platformSpecificBuildOptions.minimumSystemVersion;
|
||||
if (minimumSystemVersion != null) {
|
||||
appPlist.LSMinimumSystemVersion = minimumSystemVersion;
|
||||
}
|
||||
appPlist.CFBundleIdentifier = appInfo.macBundleIdentifier;
|
||||
appPlist.CFBundleShortVersionString = this.platformSpecificBuildOptions.bundleShortVersion || appInfo.version;
|
||||
appPlist.CFBundleVersion = appInfo.buildVersion;
|
||||
builder_util_1.use(this.platformSpecificBuildOptions.category || this.config.category, it => (appPlist.LSApplicationCategoryType = it));
|
||||
const activeOpts = (_a = this._activePackConfig) !== null && _a !== void 0 ? _a : this.platformSpecificBuildOptions;
|
||||
appPlist.CFBundleShortVersionString = activeOpts.bundleShortVersion || appInfo.version;
|
||||
appPlist.CFBundleVersion = activeOpts.bundleVersion || appInfo.buildVersion;
|
||||
(0, builder_util_1.use)(this.platformSpecificBuildOptions.category || this.config.category, it => (appPlist.LSApplicationCategoryType = it));
|
||||
appPlist.NSHumanReadableCopyright = appInfo.copyright;
|
||||
if (this.platformSpecificBuildOptions.darkModeSupport) {
|
||||
appPlist.NSRequiresAquaSystemAppearance = false;
|
||||
}
|
||||
const extendInfo = this.platformSpecificBuildOptions.extendInfo;
|
||||
if (extendInfo != null) {
|
||||
Object.assign(appPlist, extendInfo);
|
||||
(0, builder_util_1.deepAssign)(appPlist, extendInfo);
|
||||
}
|
||||
for (const [k, v] of Object.entries(appPlist)) {
|
||||
if (v === null || v === undefined) {
|
||||
delete appPlist[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
async signApp(packContext, isAsar) {
|
||||
var _a;
|
||||
const isMas = packContext.electronPlatformName === "mas";
|
||||
const activeConfig = (_a = this._activePackConfig) !== null && _a !== void 0 ? _a : this.platformSpecificBuildOptions;
|
||||
const readDirectoryAndSign = async (sourceDirectory, directories, shouldSign) => {
|
||||
const normalizedSourceDirectory = path.resolve(sourceDirectory);
|
||||
MacTargetHelper_1.MacTargetHelper.assertSafePathForCommandUsage(normalizedSourceDirectory, "application output directory");
|
||||
await Promise.all(directories.map(async (file) => {
|
||||
if (shouldSign(file)) {
|
||||
const entryName = path.basename(file);
|
||||
if (file !== entryName) {
|
||||
throw new builder_util_1.InvalidConfigurationError(`Invalid entry name in source directory: ${file}`);
|
||||
}
|
||||
const signTarget = path.resolve(normalizedSourceDirectory, entryName);
|
||||
const safeSignTarget = (0, builder_util_1.sanitizeDirPath)(signTarget, normalizedSourceDirectory);
|
||||
await this.sign(safeSignTarget, null, isMas ? activeConfig : null, packContext.arch, isMas);
|
||||
}
|
||||
}));
|
||||
return true;
|
||||
};
|
||||
const appFileName = `${this.appInfo.productFilename}.app`;
|
||||
await bluebird_lst_1.default.map(promises_1.readdir(packContext.appOutDir), (file) => {
|
||||
if (file === appFileName) {
|
||||
return this.sign(path.join(packContext.appOutDir, file), null, null, null);
|
||||
}
|
||||
return null;
|
||||
});
|
||||
await readDirectoryAndSign(packContext.appOutDir, await (0, promises_1.readdir)(packContext.appOutDir), file => file === appFileName);
|
||||
if (!isAsar) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
const outResourcesDir = path.join(packContext.appOutDir, "resources", "app.asar.unpacked");
|
||||
await bluebird_lst_1.default.map(promise_1.orIfFileNotExist(promises_1.readdir(outResourcesDir), []), (file) => {
|
||||
if (file.endsWith(".app")) {
|
||||
return this.sign(path.join(outResourcesDir, file), null, null, null);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
await readDirectoryAndSign(outResourcesDir, await (0, builder_util_1.orIfFileNotExist)((0, promises_1.readdir)(outResourcesDir), []), file => file.endsWith(".app"));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
exports.default = MacPackager;
|
||||
function getCertificateTypes(isMas, isDevelopment) {
|
||||
if (isDevelopment) {
|
||||
return isMas ? ["Mac Developer", "Apple Development"] : ["Mac Developer", "Developer ID Application"];
|
||||
}
|
||||
return isMas ? ["Apple Distribution", "3rd Party Mac Developer Application"] : ["Developer ID Application"];
|
||||
}
|
||||
exports.MacPackager = MacPackager;
|
||||
//# sourceMappingURL=macPackager.js.map
|
||||
2
electron/node_modules/app-builder-lib/out/macPackager.js.map
generated
vendored
2
electron/node_modules/app-builder-lib/out/macPackager.js.map
generated
vendored
File diff suppressed because one or more lines are too long
10
electron/node_modules/app-builder-lib/out/node-module-collector/bunNodeModulesCollector.d.ts
generated
vendored
Normal file
10
electron/node_modules/app-builder-lib/out/node-module-collector/bunNodeModulesCollector.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
import { PM } from "./packageManager";
|
||||
import { TraversedDependency } from "./types";
|
||||
import { TraversalNodeModulesCollector } from "./traversalNodeModulesCollector";
|
||||
export declare class BunNodeModulesCollector extends TraversalNodeModulesCollector {
|
||||
readonly installOptions: {
|
||||
manager: PM;
|
||||
lockfile: string;
|
||||
};
|
||||
protected getDependenciesTree(pm: PM): Promise<TraversedDependency>;
|
||||
}
|
||||
18
electron/node_modules/app-builder-lib/out/node-module-collector/bunNodeModulesCollector.js
generated
vendored
Normal file
18
electron/node_modules/app-builder-lib/out/node-module-collector/bunNodeModulesCollector.js
generated
vendored
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.BunNodeModulesCollector = void 0;
|
||||
const builder_util_1 = require("builder-util");
|
||||
const packageManager_1 = require("./packageManager");
|
||||
const traversalNodeModulesCollector_1 = require("./traversalNodeModulesCollector");
|
||||
class BunNodeModulesCollector extends traversalNodeModulesCollector_1.TraversalNodeModulesCollector {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.installOptions = { manager: packageManager_1.PM.BUN, lockfile: "bun.lock" };
|
||||
}
|
||||
async getDependenciesTree(pm) {
|
||||
builder_util_1.log.info(null, "note: bun does not support any CLI for dependency tree extraction, utilizing file traversal collector instead");
|
||||
return super.getDependenciesTree(pm);
|
||||
}
|
||||
}
|
||||
exports.BunNodeModulesCollector = BunNodeModulesCollector;
|
||||
//# sourceMappingURL=bunNodeModulesCollector.js.map
|
||||
1
electron/node_modules/app-builder-lib/out/node-module-collector/bunNodeModulesCollector.js.map
generated
vendored
Normal file
1
electron/node_modules/app-builder-lib/out/node-module-collector/bunNodeModulesCollector.js.map
generated
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"bunNodeModulesCollector.js","sourceRoot":"","sources":["../../src/node-module-collector/bunNodeModulesCollector.ts"],"names":[],"mappings":";;;AAAA,+CAAkC;AAClC,qDAAqC;AAErC,mFAA+E;AAE/E,MAAa,uBAAwB,SAAQ,6DAA6B;IAA1E;;QACkB,mBAAc,GAAG,EAAE,OAAO,EAAE,mBAAE,CAAC,GAAG,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAA;IAM5E,CAAC;IAJW,KAAK,CAAC,mBAAmB,CAAC,EAAM;QACxC,kBAAG,CAAC,IAAI,CAAC,IAAI,EAAE,+GAA+G,CAAC,CAAA;QAC/H,OAAO,KAAK,CAAC,mBAAmB,CAAC,EAAE,CAAC,CAAA;IACtC,CAAC;CACF;AAPD,0DAOC","sourcesContent":["import { log } from \"builder-util\"\nimport { PM } from \"./packageManager\"\nimport { TraversedDependency } from \"./types\"\nimport { TraversalNodeModulesCollector } from \"./traversalNodeModulesCollector\"\n\nexport class BunNodeModulesCollector extends TraversalNodeModulesCollector {\n public readonly installOptions = { manager: PM.BUN, lockfile: \"bun.lock\" }\n\n protected async getDependenciesTree(pm: PM): Promise<TraversedDependency> {\n log.info(null, \"note: bun does not support any CLI for dependency tree extraction, utilizing file traversal collector instead\")\n return super.getDependenciesTree(pm)\n }\n}\n"]}
|
||||
123
electron/node_modules/app-builder-lib/out/node-module-collector/hoist.d.ts
generated
vendored
Normal file
123
electron/node_modules/app-builder-lib/out/node-module-collector/hoist.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
/**
|
||||
BSD 2-Clause License
|
||||
|
||||
Copyright (c) 2016-present, Yarn Contributors.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**
|
||||
* High-level node_modules hoisting algorithm recipe
|
||||
*
|
||||
* 1. Take input dependency graph and start traversing it,
|
||||
* as you visit new node in the graph - clone it if there can be multiple paths
|
||||
* to access the node from the graph root to the node, e.g. essentially represent
|
||||
* the graph with a tree as you go, to make hoisting possible.
|
||||
* 2. You want to hoist every node possible to the top root node first,
|
||||
* then to each of its children etc, so you need to keep track what is your current
|
||||
* root node into which you are hoisting
|
||||
* 3. Traverse the dependency graph from the current root node and for each package name
|
||||
* that can be potentially hoisted to the current root node build a list of idents
|
||||
* in descending hoisting preference. You will check in next steps whether most preferred ident
|
||||
* for the given package name can be hoisted first, and if not, then you check the
|
||||
* less preferred ident, etc, until either some ident will be hoisted
|
||||
* or you run out of idents to check
|
||||
* (no need to convert the graph to the tree when you build this preference map).
|
||||
* 4. The children of the root node are already "hoisted", so you need to start
|
||||
* from the dependencies of these children. You take some child and
|
||||
* sort its dependencies so that regular dependencies without peer dependencies
|
||||
* will come first and then those dependencies that peer depend on them.
|
||||
* This is needed to make algorithm more efficient and hoist nodes which are easier
|
||||
* to hoist first and then handle peer dependent nodes.
|
||||
* 5. You take this sorted list of dependencies and check if each of them can be
|
||||
* hoisted to the current root node. To answer is the node can be hoisted you check
|
||||
* your constraints - require promise and peer dependency promise.
|
||||
* The possible answers can be: YES - the node is hoistable to the current root,
|
||||
* NO - the node is not hoistable to the current root
|
||||
* and DEPENDS - the node is hoistable to the root if nodes X, Y, Z are hoistable
|
||||
* to the root. The case DEPENDS happens when all the require and other
|
||||
* constraints are met, except peer dependency constraints. Note, that the nodes
|
||||
* that are not package idents currently at the top of preference list are considered
|
||||
* to have the answer NO right away, before doing any other constraint checks.
|
||||
* 6. When you have hoistable answer for each dependency of a node you then build
|
||||
* a list of nodes that are NOT hoistable. These are the nodes that have answer NO
|
||||
* and the nodes that DEPENDS on these nodes. All the other nodes are hoistable,
|
||||
* those that have answer YES and those that have answer DEPENDS,
|
||||
* because they are cyclically dependent on each another
|
||||
* 7. You hoist all the hoistable nodes to the current root and continue traversing
|
||||
* the tree. Note, you need to track newly added nodes to the current root,
|
||||
* because after you finished tree traversal you want to come back to these new nodes
|
||||
* first thing and hoist everything from each of them to the current tree root.
|
||||
* 8. After you have finished traversing newly hoisted current root nodes
|
||||
* it means you cannot hoist anything to the current tree root and you need to pick
|
||||
* the next node as current tree root and run the algorithm again
|
||||
* until you run out of candidates for current tree root.
|
||||
*/
|
||||
type PackageName = string;
|
||||
export declare enum HoisterDependencyKind {
|
||||
REGULAR = 0,
|
||||
WORKSPACE = 1,
|
||||
EXTERNAL_SOFT_LINK = 2
|
||||
}
|
||||
export type HoisterTree = {
|
||||
name: PackageName;
|
||||
identName: PackageName;
|
||||
reference: string;
|
||||
dependencies: Set<HoisterTree>;
|
||||
peerNames: Set<PackageName>;
|
||||
hoistPriority?: number;
|
||||
dependencyKind?: HoisterDependencyKind;
|
||||
};
|
||||
export type HoisterResult = {
|
||||
name: PackageName;
|
||||
identName: PackageName;
|
||||
references: Set<string>;
|
||||
dependencies: Set<HoisterResult>;
|
||||
};
|
||||
type Locator = string;
|
||||
declare enum DebugLevel {
|
||||
NONE = -1,
|
||||
PERF = 0,
|
||||
CHECK = 1,
|
||||
REASONS = 2,
|
||||
INTENSIVE_CHECK = 9
|
||||
}
|
||||
export type HoistOptions = {
|
||||
/** Runs self-checks after hoisting is finished */
|
||||
check?: boolean;
|
||||
/** Debug level */
|
||||
debugLevel?: DebugLevel;
|
||||
/** Hoist borders are defined by parent node locator and its dependency name. The dependency is considered a border, nothing can be hoisted past this dependency, but dependency can be hoisted */
|
||||
hoistingLimits?: Map<Locator, Set<PackageName>>;
|
||||
};
|
||||
/**
|
||||
* Hoists package tree.
|
||||
*
|
||||
* The root node of a tree must has id: '.'.
|
||||
* This function does not mutate its arguments, it hoists and returns tree copy.
|
||||
*
|
||||
* @param tree package tree (cycles in the tree are allowed)
|
||||
*
|
||||
* @returns hoisted tree copy
|
||||
*/
|
||||
export declare const hoist: (tree: HoisterTree, opts?: HoistOptions) => HoisterResult;
|
||||
export {};
|
||||
884
electron/node_modules/app-builder-lib/out/node-module-collector/hoist.js
generated
vendored
Normal file
884
electron/node_modules/app-builder-lib/out/node-module-collector/hoist.js
generated
vendored
Normal file
|
|
@ -0,0 +1,884 @@
|
|||
"use strict";
|
||||
// copy from https://github.com/yarnpkg/berry/blob/master/packages/yarnpkg-nm/sources/hoist.ts
|
||||
/**
|
||||
BSD 2-Clause License
|
||||
|
||||
Copyright (c) 2016-present, Yarn Contributors.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.hoist = exports.HoisterDependencyKind = void 0;
|
||||
var HoisterDependencyKind;
|
||||
(function (HoisterDependencyKind) {
|
||||
HoisterDependencyKind[HoisterDependencyKind["REGULAR"] = 0] = "REGULAR";
|
||||
HoisterDependencyKind[HoisterDependencyKind["WORKSPACE"] = 1] = "WORKSPACE";
|
||||
HoisterDependencyKind[HoisterDependencyKind["EXTERNAL_SOFT_LINK"] = 2] = "EXTERNAL_SOFT_LINK";
|
||||
})(HoisterDependencyKind || (exports.HoisterDependencyKind = HoisterDependencyKind = {}));
|
||||
var Hoistable;
|
||||
(function (Hoistable) {
|
||||
Hoistable[Hoistable["YES"] = 0] = "YES";
|
||||
Hoistable[Hoistable["NO"] = 1] = "NO";
|
||||
Hoistable[Hoistable["DEPENDS"] = 2] = "DEPENDS";
|
||||
})(Hoistable || (Hoistable = {}));
|
||||
const makeLocator = (name, reference) => `${name}@${reference}`;
|
||||
const makeIdent = (name, reference) => {
|
||||
const hashIdx = reference.indexOf(`#`);
|
||||
// Strip virtual reference part, we don't need it for hoisting purposes
|
||||
const realReference = hashIdx >= 0 ? reference.substring(hashIdx + 1) : reference;
|
||||
return makeLocator(name, realReference);
|
||||
};
|
||||
var DebugLevel;
|
||||
(function (DebugLevel) {
|
||||
DebugLevel[DebugLevel["NONE"] = -1] = "NONE";
|
||||
DebugLevel[DebugLevel["PERF"] = 0] = "PERF";
|
||||
DebugLevel[DebugLevel["CHECK"] = 1] = "CHECK";
|
||||
DebugLevel[DebugLevel["REASONS"] = 2] = "REASONS";
|
||||
DebugLevel[DebugLevel["INTENSIVE_CHECK"] = 9] = "INTENSIVE_CHECK";
|
||||
})(DebugLevel || (DebugLevel = {}));
|
||||
/**
|
||||
* Hoists package tree.
|
||||
*
|
||||
* The root node of a tree must has id: '.'.
|
||||
* This function does not mutate its arguments, it hoists and returns tree copy.
|
||||
*
|
||||
* @param tree package tree (cycles in the tree are allowed)
|
||||
*
|
||||
* @returns hoisted tree copy
|
||||
*/
|
||||
const hoist = (tree, opts = {}) => {
|
||||
const debugLevel = opts.debugLevel || Number(process.env.NM_DEBUG_LEVEL || DebugLevel.NONE);
|
||||
const check = opts.check || debugLevel >= DebugLevel.INTENSIVE_CHECK;
|
||||
const hoistingLimits = opts.hoistingLimits || new Map();
|
||||
const options = { check, debugLevel, hoistingLimits, fastLookupPossible: true };
|
||||
let startTime;
|
||||
if (options.debugLevel >= DebugLevel.PERF)
|
||||
startTime = Date.now();
|
||||
const treeCopy = cloneTree(tree, options);
|
||||
let anotherRoundNeeded = false;
|
||||
let round = 0;
|
||||
do {
|
||||
const result = hoistTo(treeCopy, [treeCopy], new Set([treeCopy.locator]), new Map(), options);
|
||||
anotherRoundNeeded = result.anotherRoundNeeded || result.isGraphChanged;
|
||||
options.fastLookupPossible = false;
|
||||
round++;
|
||||
} while (anotherRoundNeeded);
|
||||
if (options.debugLevel >= DebugLevel.PERF)
|
||||
console.log(`hoist time: ${Date.now() - startTime}ms, rounds: ${round}`);
|
||||
if (options.debugLevel >= DebugLevel.CHECK) {
|
||||
const prevTreeDump = dumpDepTree(treeCopy);
|
||||
const isGraphChanged = hoistTo(treeCopy, [treeCopy], new Set([treeCopy.locator]), new Map(), options).isGraphChanged;
|
||||
if (isGraphChanged)
|
||||
throw new Error(`The hoisting result is not terminal, prev tree:\n${prevTreeDump}, next tree:\n${dumpDepTree(treeCopy)}`);
|
||||
const checkLog = selfCheck(treeCopy);
|
||||
if (checkLog) {
|
||||
throw new Error(`${checkLog}, after hoisting finished:\n${dumpDepTree(treeCopy)}`);
|
||||
}
|
||||
}
|
||||
if (options.debugLevel >= DebugLevel.REASONS)
|
||||
console.log(dumpDepTree(treeCopy));
|
||||
return shrinkTree(treeCopy);
|
||||
};
|
||||
exports.hoist = hoist;
|
||||
const getZeroRoundUsedDependencies = (rootNodePath) => {
|
||||
const rootNode = rootNodePath[rootNodePath.length - 1];
|
||||
const usedDependencies = new Map();
|
||||
const seenNodes = new Set();
|
||||
const addUsedDependencies = (node) => {
|
||||
if (seenNodes.has(node))
|
||||
return;
|
||||
seenNodes.add(node);
|
||||
for (const dep of node.hoistedDependencies.values())
|
||||
usedDependencies.set(dep.name, dep);
|
||||
for (const dep of node.dependencies.values()) {
|
||||
if (!node.peerNames.has(dep.name)) {
|
||||
addUsedDependencies(dep);
|
||||
}
|
||||
}
|
||||
};
|
||||
addUsedDependencies(rootNode);
|
||||
return usedDependencies;
|
||||
};
|
||||
const getUsedDependencies = (rootNodePath) => {
|
||||
const rootNode = rootNodePath[rootNodePath.length - 1];
|
||||
const usedDependencies = new Map();
|
||||
const seenNodes = new Set();
|
||||
const hiddenDependencies = new Set();
|
||||
const addUsedDependencies = (node, hiddenDependencies) => {
|
||||
if (seenNodes.has(node))
|
||||
return;
|
||||
seenNodes.add(node);
|
||||
for (const dep of node.hoistedDependencies.values()) {
|
||||
if (!hiddenDependencies.has(dep.name)) {
|
||||
let reachableDependency;
|
||||
for (const node of rootNodePath) {
|
||||
reachableDependency = node.dependencies.get(dep.name);
|
||||
if (reachableDependency) {
|
||||
usedDependencies.set(reachableDependency.name, reachableDependency);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const childrenHiddenDependencies = new Set();
|
||||
for (const dep of node.dependencies.values())
|
||||
childrenHiddenDependencies.add(dep.name);
|
||||
for (const dep of node.dependencies.values()) {
|
||||
if (!node.peerNames.has(dep.name)) {
|
||||
addUsedDependencies(dep, childrenHiddenDependencies);
|
||||
}
|
||||
}
|
||||
};
|
||||
addUsedDependencies(rootNode, hiddenDependencies);
|
||||
return usedDependencies;
|
||||
};
|
||||
/**
|
||||
* This method clones the node and returns cloned node copy, if the node was not previously decoupled.
|
||||
*
|
||||
* The node is considered decoupled if there is no multiple parents to any node
|
||||
* on the path from the dependency graph root up to this node. This means that there are no other
|
||||
* nodes in dependency graph that somehow transitively use this node and hence node can be hoisted without
|
||||
* side effects.
|
||||
*
|
||||
* The process of node decoupling is done by going from root node of the graph up to the node in concern
|
||||
* and decoupling each node on this graph path.
|
||||
*
|
||||
* @param node original node
|
||||
*
|
||||
* @returns decoupled node
|
||||
*/
|
||||
const decoupleGraphNode = (parent, node) => {
|
||||
if (node.decoupled)
|
||||
return node;
|
||||
const { name, references, ident, locator, dependencies, originalDependencies, hoistedDependencies, peerNames, reasons, isHoistBorder, hoistPriority, dependencyKind, hoistedFrom, hoistedTo, } = node;
|
||||
// To perform node hoisting from parent node we must clone parent nodes up to the root node,
|
||||
// because some other package in the tree might depend on the parent package where hoisting
|
||||
// cannot be performed
|
||||
const clone = {
|
||||
name,
|
||||
references: new Set(references),
|
||||
ident,
|
||||
locator,
|
||||
dependencies: new Map(dependencies),
|
||||
originalDependencies: new Map(originalDependencies),
|
||||
hoistedDependencies: new Map(hoistedDependencies),
|
||||
peerNames: new Set(peerNames),
|
||||
reasons: new Map(reasons),
|
||||
decoupled: true,
|
||||
isHoistBorder,
|
||||
hoistPriority,
|
||||
dependencyKind,
|
||||
hoistedFrom: new Map(hoistedFrom),
|
||||
hoistedTo: new Map(hoistedTo),
|
||||
};
|
||||
const selfDep = clone.dependencies.get(name);
|
||||
if (selfDep && selfDep.ident == clone.ident) // Update self-reference
|
||||
{
|
||||
clone.dependencies.set(name, clone);
|
||||
}
|
||||
parent.dependencies.set(clone.name, clone);
|
||||
return clone;
|
||||
};
|
||||
/**
|
||||
* Builds a map of most preferred packages that might be hoisted to the root node.
|
||||
*
|
||||
* The values in the map are idents sorted by preference from most preferred to less preferred.
|
||||
* If the root node has already some version of a package, the value array will contain only
|
||||
* one element, since it is not possible for other versions of a package to be hoisted.
|
||||
*
|
||||
* @param rootNode root node
|
||||
* @param preferenceMap preference map
|
||||
*/
|
||||
const getHoistIdentMap = (rootNode, preferenceMap) => {
|
||||
const identMap = new Map([[rootNode.name, [rootNode.ident]]]);
|
||||
for (const dep of rootNode.dependencies.values()) {
|
||||
if (!rootNode.peerNames.has(dep.name)) {
|
||||
identMap.set(dep.name, [dep.ident]);
|
||||
}
|
||||
}
|
||||
const keyList = Array.from(preferenceMap.keys());
|
||||
keyList.sort((key1, key2) => {
|
||||
const entry1 = preferenceMap.get(key1);
|
||||
const entry2 = preferenceMap.get(key2);
|
||||
if (entry2.hoistPriority !== entry1.hoistPriority) {
|
||||
return entry2.hoistPriority - entry1.hoistPriority;
|
||||
}
|
||||
else {
|
||||
const entry1Usages = entry1.dependents.size + entry1.peerDependents.size;
|
||||
const entry2Usages = entry2.dependents.size + entry2.peerDependents.size;
|
||||
return entry2Usages - entry1Usages;
|
||||
}
|
||||
});
|
||||
for (const key of keyList) {
|
||||
const name = key.substring(0, key.indexOf(`@`, 1));
|
||||
const ident = key.substring(name.length + 1);
|
||||
if (!rootNode.peerNames.has(name)) {
|
||||
let idents = identMap.get(name);
|
||||
if (!idents) {
|
||||
idents = [];
|
||||
identMap.set(name, idents);
|
||||
}
|
||||
if (idents.indexOf(ident) < 0) {
|
||||
idents.push(ident);
|
||||
}
|
||||
}
|
||||
}
|
||||
return identMap;
|
||||
};
|
||||
/**
|
||||
* Gets regular node dependencies only and sorts them in the order so that
|
||||
* peer dependencies come before the dependency that rely on them.
|
||||
*
|
||||
* @param node graph node
|
||||
* @returns sorted regular dependencies
|
||||
*/
|
||||
const getSortedRegularDependencies = (node) => {
|
||||
const dependencies = new Set();
|
||||
const addDep = (dep, seenDeps = new Set()) => {
|
||||
if (seenDeps.has(dep))
|
||||
return;
|
||||
seenDeps.add(dep);
|
||||
for (const peerName of dep.peerNames) {
|
||||
if (!node.peerNames.has(peerName)) {
|
||||
const peerDep = node.dependencies.get(peerName);
|
||||
if (peerDep && !dependencies.has(peerDep)) {
|
||||
addDep(peerDep, seenDeps);
|
||||
}
|
||||
}
|
||||
}
|
||||
dependencies.add(dep);
|
||||
};
|
||||
for (const dep of node.dependencies.values()) {
|
||||
if (!node.peerNames.has(dep.name)) {
|
||||
addDep(dep);
|
||||
}
|
||||
}
|
||||
return dependencies;
|
||||
};
|
||||
/**
|
||||
* Performs hoisting all the dependencies down the tree to the root node.
|
||||
*
|
||||
* The algorithm used here reduces dependency graph by deduplicating
|
||||
* instances of the packages while keeping:
|
||||
* 1. Regular dependency promise: the package should require the exact version of the dependency
|
||||
* that was declared in its `package.json`
|
||||
* 2. Peer dependency promise: the package and its direct parent package
|
||||
* must use the same instance of the peer dependency
|
||||
*
|
||||
* The regular and peer dependency promises are kept while performing transform
|
||||
* on tree branches of packages at a time:
|
||||
* `root package` -> `parent package 1` ... `parent package n` -> `dependency`
|
||||
* We check wether we can hoist `dependency` to `root package`, this boils down basically
|
||||
* to checking:
|
||||
* 1. Wether `root package` does not depend on other version of `dependency`
|
||||
* 2. Wether all the peer dependencies of a `dependency` had already been hoisted from all `parent packages`
|
||||
*
|
||||
* If many versions of the `dependency` can be hoisted to the `root package` we choose the most used
|
||||
* `dependency` version in the project among them.
|
||||
*
|
||||
* This function mutates the tree.
|
||||
*
|
||||
* @param tree package dependencies graph
|
||||
* @param rootNode root node to hoist to
|
||||
* @param rootNodePath root node path in the tree
|
||||
* @param rootNodePathLocators a set of locators for nodes that lead from the top of the tree up to root node
|
||||
* @param options hoisting options
|
||||
*/
|
||||
const hoistTo = (tree, rootNodePath, rootNodePathLocators, parentShadowedNodes, options, seenNodes = new Set()) => {
|
||||
const rootNode = rootNodePath[rootNodePath.length - 1];
|
||||
if (seenNodes.has(rootNode))
|
||||
return { anotherRoundNeeded: false, isGraphChanged: false };
|
||||
seenNodes.add(rootNode);
|
||||
const preferenceMap = buildPreferenceMap(rootNode);
|
||||
const hoistIdentMap = getHoistIdentMap(rootNode, preferenceMap);
|
||||
const usedDependencies = tree == rootNode ? new Map() : options.fastLookupPossible ? getZeroRoundUsedDependencies(rootNodePath) : getUsedDependencies(rootNodePath);
|
||||
let wasStateChanged;
|
||||
let anotherRoundNeeded = false;
|
||||
let isGraphChanged = false;
|
||||
const hoistIdents = new Map(Array.from(hoistIdentMap.entries()).map(([k, v]) => [k, v[0]]));
|
||||
const shadowedNodes = new Map();
|
||||
do {
|
||||
const result = hoistGraph(tree, rootNodePath, rootNodePathLocators, usedDependencies, hoistIdents, hoistIdentMap, parentShadowedNodes, shadowedNodes, options);
|
||||
if (result.isGraphChanged)
|
||||
isGraphChanged = true;
|
||||
if (result.anotherRoundNeeded)
|
||||
anotherRoundNeeded = true;
|
||||
wasStateChanged = false;
|
||||
for (const [name, idents] of hoistIdentMap) {
|
||||
if (idents.length > 1 && !rootNode.dependencies.has(name)) {
|
||||
hoistIdents.delete(name);
|
||||
idents.shift();
|
||||
hoistIdents.set(name, idents[0]);
|
||||
wasStateChanged = true;
|
||||
}
|
||||
}
|
||||
} while (wasStateChanged);
|
||||
for (const dependency of rootNode.dependencies.values()) {
|
||||
if (!rootNode.peerNames.has(dependency.name) && !rootNodePathLocators.has(dependency.locator)) {
|
||||
rootNodePathLocators.add(dependency.locator);
|
||||
const result = hoistTo(tree, [...rootNodePath, dependency], rootNodePathLocators, shadowedNodes, options);
|
||||
if (result.isGraphChanged)
|
||||
isGraphChanged = true;
|
||||
if (result.anotherRoundNeeded)
|
||||
anotherRoundNeeded = true;
|
||||
rootNodePathLocators.delete(dependency.locator);
|
||||
}
|
||||
}
|
||||
return { anotherRoundNeeded, isGraphChanged };
|
||||
};
|
||||
const hasUnhoistedDependencies = (node) => {
|
||||
for (const [subName, subDependency] of node.dependencies) {
|
||||
if (!node.peerNames.has(subName) && subDependency.ident !== node.ident) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
const getNodeHoistInfo = (rootNode, rootNodePathLocators, nodePath, node, usedDependencies, hoistIdents, hoistIdentMap, shadowedNodes, { outputReason, fastLookupPossible }) => {
|
||||
let reasonRoot;
|
||||
let reason = null;
|
||||
let dependsOn = new Set();
|
||||
if (outputReason) {
|
||||
reasonRoot = `${Array.from(rootNodePathLocators)
|
||||
.map(x => prettyPrintLocator(x))
|
||||
.join(`→`)}`;
|
||||
}
|
||||
const parentNode = nodePath[nodePath.length - 1];
|
||||
// We cannot hoist self-references
|
||||
const isSelfReference = node.ident === parentNode.ident;
|
||||
let isHoistable = !isSelfReference;
|
||||
if (outputReason && !isHoistable)
|
||||
reason = `- self-reference`;
|
||||
if (isHoistable) {
|
||||
isHoistable = node.dependencyKind !== HoisterDependencyKind.WORKSPACE;
|
||||
if (outputReason && !isHoistable) {
|
||||
reason = `- workspace`;
|
||||
}
|
||||
}
|
||||
if (isHoistable && node.dependencyKind === HoisterDependencyKind.EXTERNAL_SOFT_LINK) {
|
||||
isHoistable = !hasUnhoistedDependencies(node);
|
||||
if (outputReason && !isHoistable) {
|
||||
reason = `- external soft link with unhoisted dependencies`;
|
||||
}
|
||||
}
|
||||
if (isHoistable) {
|
||||
isHoistable = !rootNode.peerNames.has(node.name);
|
||||
if (outputReason && !isHoistable) {
|
||||
reason = `- cannot shadow peer: ${prettyPrintLocator(rootNode.originalDependencies.get(node.name).locator)} at ${reasonRoot}`;
|
||||
}
|
||||
}
|
||||
if (isHoistable) {
|
||||
let isNameAvailable = false;
|
||||
const usedDep = usedDependencies.get(node.name);
|
||||
isNameAvailable = !usedDep || usedDep.ident === node.ident;
|
||||
if (outputReason && !isNameAvailable)
|
||||
reason = `- filled by: ${prettyPrintLocator(usedDep.locator)} at ${reasonRoot}`;
|
||||
if (isNameAvailable) {
|
||||
for (let idx = nodePath.length - 1; idx >= 1; idx--) {
|
||||
const parent = nodePath[idx];
|
||||
const parentDep = parent.dependencies.get(node.name);
|
||||
if (parentDep && parentDep.ident !== node.ident) {
|
||||
isNameAvailable = false;
|
||||
let shadowedNames = shadowedNodes.get(parentNode);
|
||||
if (!shadowedNames) {
|
||||
shadowedNames = new Set();
|
||||
shadowedNodes.set(parentNode, shadowedNames);
|
||||
}
|
||||
shadowedNames.add(node.name);
|
||||
if (outputReason) {
|
||||
reason = `- filled by ${prettyPrintLocator(parentDep.locator)} at ${nodePath
|
||||
.slice(0, idx)
|
||||
.map(x => prettyPrintLocator(x.locator))
|
||||
.join(`→`)}`;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
isHoistable = isNameAvailable;
|
||||
}
|
||||
if (isHoistable) {
|
||||
const hoistedIdent = hoistIdents.get(node.name);
|
||||
isHoistable = hoistedIdent === node.ident;
|
||||
if (outputReason && !isHoistable) {
|
||||
reason = `- filled by: ${prettyPrintLocator(hoistIdentMap.get(node.name)[0])} at ${reasonRoot}`;
|
||||
}
|
||||
}
|
||||
if (isHoistable) {
|
||||
let arePeerDepsSatisfied = true;
|
||||
const checkList = new Set(node.peerNames);
|
||||
for (let idx = nodePath.length - 1; idx >= 1; idx--) {
|
||||
const parent = nodePath[idx];
|
||||
for (const name of checkList) {
|
||||
if (parent.peerNames.has(name) && parent.originalDependencies.has(name))
|
||||
continue;
|
||||
const parentDepNode = parent.dependencies.get(name);
|
||||
if (parentDepNode && rootNode.dependencies.get(name) !== parentDepNode) {
|
||||
if (idx === nodePath.length - 1) {
|
||||
dependsOn.add(parentDepNode);
|
||||
}
|
||||
else {
|
||||
dependsOn = null;
|
||||
arePeerDepsSatisfied = false;
|
||||
if (outputReason) {
|
||||
reason = `- peer dependency ${prettyPrintLocator(parentDepNode.locator)} from parent ${prettyPrintLocator(parent.locator)} was not hoisted to ${reasonRoot}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
checkList.delete(name);
|
||||
}
|
||||
if (!arePeerDepsSatisfied) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
isHoistable = arePeerDepsSatisfied;
|
||||
}
|
||||
if (isHoistable && !fastLookupPossible) {
|
||||
for (const origDep of node.hoistedDependencies.values()) {
|
||||
const usedDep = usedDependencies.get(origDep.name) || rootNode.dependencies.get(origDep.name);
|
||||
if (!usedDep || origDep.ident !== usedDep.ident) {
|
||||
isHoistable = false;
|
||||
if (outputReason)
|
||||
reason = `- previously hoisted dependency mismatch, needed: ${prettyPrintLocator(origDep.locator)}, available: ${prettyPrintLocator(usedDep === null || usedDep === void 0 ? void 0 : usedDep.locator)}`;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dependsOn !== null && dependsOn.size > 0) {
|
||||
return { isHoistable: Hoistable.DEPENDS, dependsOn, reason };
|
||||
}
|
||||
else {
|
||||
return { isHoistable: isHoistable ? Hoistable.YES : Hoistable.NO, reason };
|
||||
}
|
||||
};
|
||||
const getAliasedLocator = (node) => `${node.name}@${node.locator}`;
|
||||
/**
|
||||
* Performs actual graph transformation, by hoisting packages to the root node.
|
||||
*
|
||||
* @param tree dependency tree
|
||||
* @param rootNodePath root node path in the tree
|
||||
* @param rootNodePathLocators a set of locators for nodes that lead from the top of the tree up to root node
|
||||
* @param usedDependencies map of dependency nodes from parents of root node used by root node and its children via parent lookup
|
||||
* @param hoistIdents idents that should be attempted to be hoisted to the root node
|
||||
*/
|
||||
const hoistGraph = (tree, rootNodePath, rootNodePathLocators, usedDependencies, hoistIdents, hoistIdentMap, parentShadowedNodes, shadowedNodes, options) => {
|
||||
const rootNode = rootNodePath[rootNodePath.length - 1];
|
||||
const seenNodes = new Set();
|
||||
let anotherRoundNeeded = false;
|
||||
let isGraphChanged = false;
|
||||
const hoistNodeDependencies = (nodePath, locatorPath, aliasedLocatorPath, parentNode, newNodes) => {
|
||||
if (seenNodes.has(parentNode))
|
||||
return;
|
||||
const nextLocatorPath = [...locatorPath, getAliasedLocator(parentNode)];
|
||||
const nextAliasedLocatorPath = [...aliasedLocatorPath, getAliasedLocator(parentNode)];
|
||||
const dependantTree = new Map();
|
||||
const hoistInfos = new Map();
|
||||
for (const subDependency of getSortedRegularDependencies(parentNode)) {
|
||||
const hoistInfo = getNodeHoistInfo(rootNode, rootNodePathLocators, [rootNode, ...nodePath, parentNode], subDependency, usedDependencies, hoistIdents, hoistIdentMap, shadowedNodes, { outputReason: options.debugLevel >= DebugLevel.REASONS, fastLookupPossible: options.fastLookupPossible });
|
||||
hoistInfos.set(subDependency, hoistInfo);
|
||||
if (hoistInfo.isHoistable === Hoistable.DEPENDS) {
|
||||
for (const node of hoistInfo.dependsOn) {
|
||||
const nodeDependants = dependantTree.get(node.name) || new Set();
|
||||
nodeDependants.add(subDependency.name);
|
||||
dependantTree.set(node.name, nodeDependants);
|
||||
}
|
||||
}
|
||||
}
|
||||
const unhoistableNodes = new Set();
|
||||
const addUnhoistableNode = (node, hoistInfo, reason) => {
|
||||
if (!unhoistableNodes.has(node)) {
|
||||
unhoistableNodes.add(node);
|
||||
hoistInfos.set(node, { isHoistable: Hoistable.NO, reason });
|
||||
for (const dependantName of dependantTree.get(node.name) || []) {
|
||||
addUnhoistableNode(parentNode.dependencies.get(dependantName), hoistInfo, options.debugLevel >= DebugLevel.REASONS
|
||||
? `- peer dependency ${prettyPrintLocator(node.locator)} from parent ${prettyPrintLocator(parentNode.locator)} was not hoisted`
|
||||
: ``);
|
||||
}
|
||||
}
|
||||
};
|
||||
for (const [node, hoistInfo] of hoistInfos)
|
||||
if (hoistInfo.isHoistable === Hoistable.NO)
|
||||
addUnhoistableNode(node, hoistInfo, hoistInfo.reason);
|
||||
let wereNodesHoisted = false;
|
||||
for (const node of hoistInfos.keys()) {
|
||||
if (!unhoistableNodes.has(node)) {
|
||||
isGraphChanged = true;
|
||||
const shadowedNames = parentShadowedNodes.get(parentNode);
|
||||
if (shadowedNames && shadowedNames.has(node.name))
|
||||
anotherRoundNeeded = true;
|
||||
wereNodesHoisted = true;
|
||||
parentNode.dependencies.delete(node.name);
|
||||
parentNode.hoistedDependencies.set(node.name, node);
|
||||
parentNode.reasons.delete(node.name);
|
||||
const hoistedNode = rootNode.dependencies.get(node.name);
|
||||
if (options.debugLevel >= DebugLevel.REASONS) {
|
||||
const hoistedFrom = Array.from(locatorPath)
|
||||
.concat([parentNode.locator])
|
||||
.map(x => prettyPrintLocator(x))
|
||||
.join(`→`);
|
||||
let hoistedFromArray = rootNode.hoistedFrom.get(node.name);
|
||||
if (!hoistedFromArray) {
|
||||
hoistedFromArray = [];
|
||||
rootNode.hoistedFrom.set(node.name, hoistedFromArray);
|
||||
}
|
||||
hoistedFromArray.push(hoistedFrom);
|
||||
parentNode.hoistedTo.set(node.name, Array.from(rootNodePath)
|
||||
.map(x => prettyPrintLocator(x.locator))
|
||||
.join(`→`));
|
||||
}
|
||||
// Add hoisted node to root node, in case it is not already there
|
||||
if (!hoistedNode) {
|
||||
// Avoid adding other version of root node to itself
|
||||
if (rootNode.ident !== node.ident) {
|
||||
rootNode.dependencies.set(node.name, node);
|
||||
newNodes.add(node);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (const reference of node.references) {
|
||||
hoistedNode.references.add(reference);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (parentNode.dependencyKind === HoisterDependencyKind.EXTERNAL_SOFT_LINK && wereNodesHoisted)
|
||||
anotherRoundNeeded = true;
|
||||
if (options.check) {
|
||||
const checkLog = selfCheck(tree);
|
||||
if (checkLog) {
|
||||
throw new Error(`${checkLog}, after hoisting dependencies of ${[rootNode, ...nodePath, parentNode].map(x => prettyPrintLocator(x.locator)).join(`→`)}:\n${dumpDepTree(tree)}`);
|
||||
}
|
||||
}
|
||||
const children = getSortedRegularDependencies(parentNode);
|
||||
for (const node of children) {
|
||||
if (unhoistableNodes.has(node)) {
|
||||
const hoistInfo = hoistInfos.get(node);
|
||||
const hoistableIdent = hoistIdents.get(node.name);
|
||||
if ((hoistableIdent === node.ident || !parentNode.reasons.has(node.name)) && hoistInfo.isHoistable !== Hoistable.YES)
|
||||
parentNode.reasons.set(node.name, hoistInfo.reason);
|
||||
if (!node.isHoistBorder && nextAliasedLocatorPath.indexOf(getAliasedLocator(node)) < 0) {
|
||||
seenNodes.add(parentNode);
|
||||
const decoupledNode = decoupleGraphNode(parentNode, node);
|
||||
hoistNodeDependencies([...nodePath, parentNode], nextLocatorPath, nextAliasedLocatorPath, decoupledNode, nextNewNodes);
|
||||
seenNodes.delete(parentNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
let newNodes;
|
||||
let nextNewNodes = new Set(getSortedRegularDependencies(rootNode));
|
||||
const aliasedRootNodePathLocators = Array.from(rootNodePath).map(x => getAliasedLocator(x));
|
||||
do {
|
||||
newNodes = nextNewNodes;
|
||||
nextNewNodes = new Set();
|
||||
for (const dep of newNodes) {
|
||||
if (dep.locator === rootNode.locator || dep.isHoistBorder)
|
||||
continue;
|
||||
const decoupledDependency = decoupleGraphNode(rootNode, dep);
|
||||
hoistNodeDependencies([], Array.from(rootNodePathLocators), aliasedRootNodePathLocators, decoupledDependency, nextNewNodes);
|
||||
}
|
||||
} while (nextNewNodes.size > 0);
|
||||
return { anotherRoundNeeded, isGraphChanged };
|
||||
};
|
||||
const selfCheck = (tree) => {
|
||||
const log = [];
|
||||
const seenNodes = new Set();
|
||||
const parents = new Set();
|
||||
const checkNode = (node, parentDeps, parent) => {
|
||||
if (seenNodes.has(node))
|
||||
return;
|
||||
seenNodes.add(node);
|
||||
if (parents.has(node))
|
||||
return;
|
||||
const dependencies = new Map(parentDeps);
|
||||
for (const dep of node.dependencies.values())
|
||||
if (!node.peerNames.has(dep.name))
|
||||
dependencies.set(dep.name, dep);
|
||||
for (const origDep of node.originalDependencies.values()) {
|
||||
const dep = dependencies.get(origDep.name);
|
||||
const prettyPrintTreePath = () => `${Array.from(parents)
|
||||
.concat([node])
|
||||
.map(x => prettyPrintLocator(x.locator))
|
||||
.join(`→`)}`;
|
||||
if (node.peerNames.has(origDep.name)) {
|
||||
const parentDep = parentDeps.get(origDep.name);
|
||||
if (parentDep !== dep || !parentDep || parentDep.ident !== origDep.ident) {
|
||||
log.push(`${prettyPrintTreePath()} - broken peer promise: expected ${origDep.ident} but found ${parentDep ? parentDep.ident : parentDep}`);
|
||||
}
|
||||
}
|
||||
else {
|
||||
const hoistedFrom = parent.hoistedFrom.get(node.name);
|
||||
const originalHoistedTo = node.hoistedTo.get(origDep.name);
|
||||
const prettyHoistedFrom = `${hoistedFrom ? ` hoisted from ${hoistedFrom.join(`, `)}` : ``}`;
|
||||
const prettyOriginalHoistedTo = `${originalHoistedTo ? ` hoisted to ${originalHoistedTo}` : ``}`;
|
||||
const prettyNodePath = `${prettyPrintTreePath()}${prettyHoistedFrom}`;
|
||||
if (!dep) {
|
||||
log.push(`${prettyNodePath} - broken require promise: no required dependency ${origDep.name}${prettyOriginalHoistedTo} found`);
|
||||
}
|
||||
else if (dep.ident !== origDep.ident) {
|
||||
log.push(`${prettyNodePath} - broken require promise for ${origDep.name}${prettyOriginalHoistedTo}: expected ${origDep.ident}, but found: ${dep.ident}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
parents.add(node);
|
||||
for (const dep of node.dependencies.values()) {
|
||||
if (!node.peerNames.has(dep.name)) {
|
||||
checkNode(dep, dependencies, node);
|
||||
}
|
||||
}
|
||||
parents.delete(node);
|
||||
};
|
||||
checkNode(tree, tree.dependencies, tree);
|
||||
return log.join(`\n`);
|
||||
};
|
||||
/**
|
||||
* Creates a clone of package tree with extra fields used for hoisting purposes.
|
||||
*
|
||||
* @param tree package tree clone
|
||||
*/
|
||||
const cloneTree = (tree, options) => {
|
||||
const { identName, name, reference, peerNames } = tree;
|
||||
const treeCopy = {
|
||||
name,
|
||||
references: new Set([reference]),
|
||||
locator: makeLocator(identName, reference),
|
||||
ident: makeIdent(identName, reference),
|
||||
dependencies: new Map(),
|
||||
originalDependencies: new Map(),
|
||||
hoistedDependencies: new Map(),
|
||||
peerNames: new Set(peerNames),
|
||||
reasons: new Map(),
|
||||
decoupled: true,
|
||||
isHoistBorder: true,
|
||||
hoistPriority: 0,
|
||||
dependencyKind: HoisterDependencyKind.WORKSPACE,
|
||||
hoistedFrom: new Map(),
|
||||
hoistedTo: new Map(),
|
||||
};
|
||||
const seenNodes = new Map([[tree, treeCopy]]);
|
||||
const addNode = (node, parentNode) => {
|
||||
let workNode = seenNodes.get(node);
|
||||
const isSeen = !!workNode;
|
||||
if (!workNode) {
|
||||
const { name, identName, reference, peerNames, hoistPriority, dependencyKind } = node;
|
||||
const dependenciesNmHoistingLimits = options.hoistingLimits.get(parentNode.locator);
|
||||
workNode = {
|
||||
name,
|
||||
references: new Set([reference]),
|
||||
locator: makeLocator(identName, reference),
|
||||
ident: makeIdent(identName, reference),
|
||||
dependencies: new Map(),
|
||||
originalDependencies: new Map(),
|
||||
hoistedDependencies: new Map(),
|
||||
peerNames: new Set(peerNames),
|
||||
reasons: new Map(),
|
||||
decoupled: true,
|
||||
isHoistBorder: dependenciesNmHoistingLimits ? dependenciesNmHoistingLimits.has(name) : false,
|
||||
hoistPriority: hoistPriority || 0,
|
||||
dependencyKind: dependencyKind || HoisterDependencyKind.REGULAR,
|
||||
hoistedFrom: new Map(),
|
||||
hoistedTo: new Map(),
|
||||
};
|
||||
seenNodes.set(node, workNode);
|
||||
}
|
||||
parentNode.dependencies.set(node.name, workNode);
|
||||
parentNode.originalDependencies.set(node.name, workNode);
|
||||
if (!isSeen) {
|
||||
for (const dep of node.dependencies) {
|
||||
addNode(dep, workNode);
|
||||
}
|
||||
}
|
||||
else {
|
||||
const seenCoupledNodes = new Set();
|
||||
const markNodeCoupled = (node) => {
|
||||
if (seenCoupledNodes.has(node))
|
||||
return;
|
||||
seenCoupledNodes.add(node);
|
||||
node.decoupled = false;
|
||||
for (const dep of node.dependencies.values()) {
|
||||
if (!node.peerNames.has(dep.name)) {
|
||||
markNodeCoupled(dep);
|
||||
}
|
||||
}
|
||||
};
|
||||
markNodeCoupled(workNode);
|
||||
}
|
||||
};
|
||||
for (const dep of tree.dependencies)
|
||||
addNode(dep, treeCopy);
|
||||
return treeCopy;
|
||||
};
|
||||
const getIdentName = (locator) => locator.substring(0, locator.indexOf(`@`, 1));
|
||||
/**
|
||||
* Creates a clone of hoisted package tree with extra fields removed
|
||||
*
|
||||
* @param tree stripped down hoisted package tree clone
|
||||
*/
|
||||
const shrinkTree = (tree) => {
|
||||
const treeCopy = {
|
||||
name: tree.name,
|
||||
identName: getIdentName(tree.locator),
|
||||
references: new Set(tree.references),
|
||||
dependencies: new Set(),
|
||||
};
|
||||
const seenNodes = new Set([tree]);
|
||||
const addNode = (node, parentWorkNode, parentNode) => {
|
||||
const isSeen = seenNodes.has(node);
|
||||
let resultNode;
|
||||
if (parentWorkNode === node) {
|
||||
resultNode = parentNode;
|
||||
}
|
||||
else {
|
||||
const { name, references, locator } = node;
|
||||
resultNode = {
|
||||
name,
|
||||
identName: getIdentName(locator),
|
||||
references,
|
||||
dependencies: new Set(),
|
||||
};
|
||||
}
|
||||
parentNode.dependencies.add(resultNode);
|
||||
if (!isSeen) {
|
||||
seenNodes.add(node);
|
||||
for (const dep of node.dependencies.values()) {
|
||||
if (!node.peerNames.has(dep.name)) {
|
||||
addNode(dep, node, resultNode);
|
||||
}
|
||||
}
|
||||
seenNodes.delete(node);
|
||||
}
|
||||
};
|
||||
for (const dep of tree.dependencies.values())
|
||||
addNode(dep, tree, treeCopy);
|
||||
return treeCopy;
|
||||
};
|
||||
/**
|
||||
* Builds mapping, where key is an alias + dependent package ident and the value is the list of
|
||||
* parent package idents who depend on this package.
|
||||
*
|
||||
* @param rootNode package tree root node
|
||||
*
|
||||
* @returns preference map
|
||||
*/
|
||||
const buildPreferenceMap = (rootNode) => {
|
||||
const preferenceMap = new Map();
|
||||
const seenNodes = new Set([rootNode]);
|
||||
const getPreferenceKey = (node) => `${node.name}@${node.ident}`;
|
||||
const getOrCreatePreferenceEntry = (node) => {
|
||||
const key = getPreferenceKey(node);
|
||||
let entry = preferenceMap.get(key);
|
||||
if (!entry) {
|
||||
entry = { dependents: new Set(), peerDependents: new Set(), hoistPriority: 0 };
|
||||
preferenceMap.set(key, entry);
|
||||
}
|
||||
return entry;
|
||||
};
|
||||
const addDependent = (dependent, node) => {
|
||||
const isSeen = !!seenNodes.has(node);
|
||||
const entry = getOrCreatePreferenceEntry(node);
|
||||
entry.dependents.add(dependent.ident);
|
||||
if (!isSeen) {
|
||||
seenNodes.add(node);
|
||||
for (const dep of node.dependencies.values()) {
|
||||
const entry = getOrCreatePreferenceEntry(dep);
|
||||
entry.hoistPriority = Math.max(entry.hoistPriority, dep.hoistPriority);
|
||||
if (node.peerNames.has(dep.name)) {
|
||||
entry.peerDependents.add(node.ident);
|
||||
}
|
||||
else {
|
||||
addDependent(node, dep);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
for (const dep of rootNode.dependencies.values())
|
||||
if (!rootNode.peerNames.has(dep.name))
|
||||
addDependent(rootNode, dep);
|
||||
return preferenceMap;
|
||||
};
|
||||
const prettyPrintLocator = (locator) => {
|
||||
if (!locator)
|
||||
return `none`;
|
||||
const idx = locator.indexOf(`@`, 1);
|
||||
let name = locator.substring(0, idx);
|
||||
if (name.endsWith(`$wsroot$`))
|
||||
name = `wh:${name.replace(`$wsroot$`, ``)}`;
|
||||
const reference = locator.substring(idx + 1);
|
||||
if (reference === `workspace:.`) {
|
||||
return `.`;
|
||||
}
|
||||
else if (!reference) {
|
||||
return `${name}`;
|
||||
}
|
||||
else {
|
||||
let version = (reference.indexOf(`#`) > 0 ? reference.split(`#`)[1] : reference).replace(`npm:`, ``);
|
||||
if (reference.startsWith(`virtual`))
|
||||
name = `v:${name}`;
|
||||
if (version.startsWith(`workspace`)) {
|
||||
name = `w:${name}`;
|
||||
version = ``;
|
||||
}
|
||||
return `${name}${version ? `@${version}` : ``}`;
|
||||
}
|
||||
};
|
||||
const MAX_NODES_TO_DUMP = 50000;
|
||||
/**
|
||||
* Pretty-prints dependency tree in the `yarn why`-like format
|
||||
*
|
||||
* The function is used for troubleshooting purposes only.
|
||||
*
|
||||
* @param pkg node_modules tree
|
||||
*
|
||||
* @returns sorted node_modules tree
|
||||
*/
|
||||
const dumpDepTree = (tree) => {
|
||||
let nodeCount = 0;
|
||||
const dumpPackage = (pkg, parents, prefix = ``) => {
|
||||
if (nodeCount > MAX_NODES_TO_DUMP || parents.has(pkg))
|
||||
return ``;
|
||||
nodeCount++;
|
||||
const dependencies = Array.from(pkg.dependencies.values()).sort((n1, n2) => {
|
||||
if (n1.name === n2.name) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
return n1.name > n2.name ? 1 : -1;
|
||||
}
|
||||
});
|
||||
let str = ``;
|
||||
parents.add(pkg);
|
||||
for (let idx = 0; idx < dependencies.length; idx++) {
|
||||
const dep = dependencies[idx];
|
||||
if (!pkg.peerNames.has(dep.name) && dep !== pkg) {
|
||||
const reason = pkg.reasons.get(dep.name);
|
||||
const identName = getIdentName(dep.locator);
|
||||
str += `${prefix}${idx < dependencies.length - 1 ? `├─` : `└─`}${(parents.has(dep) ? `>` : ``) + (identName !== dep.name ? `a:${dep.name}:` : ``) + prettyPrintLocator(dep.locator) + (reason ? ` ${reason}` : ``)}\n`;
|
||||
str += dumpPackage(dep, parents, `${prefix}${idx < dependencies.length - 1 ? `│ ` : ` `}`);
|
||||
}
|
||||
}
|
||||
parents.delete(pkg);
|
||||
return str;
|
||||
};
|
||||
const treeDump = dumpPackage(tree, new Set());
|
||||
return treeDump + (nodeCount > MAX_NODES_TO_DUMP ? `\nTree is too large, part of the tree has been dunped\n` : ``);
|
||||
};
|
||||
//# sourceMappingURL=hoist.js.map
|
||||
1
electron/node_modules/app-builder-lib/out/node-module-collector/hoist.js.map
generated
vendored
Normal file
1
electron/node_modules/app-builder-lib/out/node-module-collector/hoist.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
18
electron/node_modules/app-builder-lib/out/node-module-collector/index.d.ts
generated
vendored
Normal file
18
electron/node_modules/app-builder-lib/out/node-module-collector/index.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
import { Nullish } from "builder-util-runtime";
|
||||
import { TmpDir } from "temp-file";
|
||||
import { NpmNodeModulesCollector } from "./npmNodeModulesCollector";
|
||||
import { getPackageManagerCommand, PM } from "./packageManager";
|
||||
import { PnpmNodeModulesCollector } from "./pnpmNodeModulesCollector";
|
||||
import { BunNodeModulesCollector } from "./bunNodeModulesCollector";
|
||||
import { Lazy } from "lazy-val";
|
||||
import { TraversalNodeModulesCollector } from "./traversalNodeModulesCollector";
|
||||
export { getPackageManagerCommand, PM };
|
||||
export declare function getCollectorByPackageManager(pm: PM, rootDir: string, tempDirManager: TmpDir): NpmNodeModulesCollector | PnpmNodeModulesCollector | TraversalNodeModulesCollector | BunNodeModulesCollector;
|
||||
export declare const determinePackageManagerEnv: ({ projectDir, appDir, workspaceRoot }: {
|
||||
projectDir: string;
|
||||
appDir: string;
|
||||
workspaceRoot: string | Nullish;
|
||||
}) => Lazy<{
|
||||
pm: PM;
|
||||
workspaceRoot: Promise<string | undefined>;
|
||||
}>;
|
||||
130
electron/node_modules/app-builder-lib/out/node-module-collector/index.js
generated
vendored
Normal file
130
electron/node_modules/app-builder-lib/out/node-module-collector/index.js
generated
vendored
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.determinePackageManagerEnv = exports.PM = exports.getPackageManagerCommand = void 0;
|
||||
exports.getCollectorByPackageManager = getCollectorByPackageManager;
|
||||
const npmNodeModulesCollector_1 = require("./npmNodeModulesCollector");
|
||||
const packageManager_1 = require("./packageManager");
|
||||
Object.defineProperty(exports, "getPackageManagerCommand", { enumerable: true, get: function () { return packageManager_1.getPackageManagerCommand; } });
|
||||
Object.defineProperty(exports, "PM", { enumerable: true, get: function () { return packageManager_1.PM; } });
|
||||
const pnpmNodeModulesCollector_1 = require("./pnpmNodeModulesCollector");
|
||||
const yarnBerryNodeModulesCollector_1 = require("./yarnBerryNodeModulesCollector");
|
||||
const yarnNodeModulesCollector_1 = require("./yarnNodeModulesCollector");
|
||||
const bunNodeModulesCollector_1 = require("./bunNodeModulesCollector");
|
||||
const lazy_val_1 = require("lazy-val");
|
||||
const builder_util_1 = require("builder-util");
|
||||
const fs = require("fs-extra");
|
||||
const path = require("path");
|
||||
const traversalNodeModulesCollector_1 = require("./traversalNodeModulesCollector");
|
||||
function getCollectorByPackageManager(pm, rootDir, tempDirManager) {
|
||||
switch (pm) {
|
||||
case packageManager_1.PM.PNPM:
|
||||
return new pnpmNodeModulesCollector_1.PnpmNodeModulesCollector(rootDir, tempDirManager);
|
||||
case packageManager_1.PM.YARN:
|
||||
return new yarnNodeModulesCollector_1.YarnNodeModulesCollector(rootDir, tempDirManager);
|
||||
case packageManager_1.PM.YARN_BERRY:
|
||||
return new yarnBerryNodeModulesCollector_1.YarnBerryNodeModulesCollector(rootDir, tempDirManager);
|
||||
case packageManager_1.PM.BUN:
|
||||
return new bunNodeModulesCollector_1.BunNodeModulesCollector(rootDir, tempDirManager);
|
||||
case packageManager_1.PM.NPM:
|
||||
return new npmNodeModulesCollector_1.NpmNodeModulesCollector(rootDir, tempDirManager);
|
||||
case packageManager_1.PM.TRAVERSAL:
|
||||
return new traversalNodeModulesCollector_1.TraversalNodeModulesCollector(rootDir, tempDirManager);
|
||||
}
|
||||
}
|
||||
const determinePackageManagerEnv = ({ projectDir, appDir, workspaceRoot }) => new lazy_val_1.Lazy(async () => {
|
||||
const availableDirs = [workspaceRoot, projectDir, appDir].filter((it) => !(0, builder_util_1.isEmptyOrSpaces)(it));
|
||||
const pm = await (0, packageManager_1.detectPackageManager)(availableDirs);
|
||||
const root = await findWorkspaceRoot(pm.pm, projectDir);
|
||||
if (root != null) {
|
||||
// re-detect package manager from workspace root, this seems particularly necessary for pnpm workspaces
|
||||
const actualPm = await (0, packageManager_1.detectPackageManager)([root]);
|
||||
builder_util_1.log.info({ pm: actualPm.pm, config: actualPm.corepackConfig, resolved: actualPm.resolvedDirectory, projectDir }, `detected workspace root for project using ${actualPm.detectionMethod}`);
|
||||
return {
|
||||
pm: actualPm.pm,
|
||||
workspaceRoot: Promise.resolve(actualPm.resolvedDirectory),
|
||||
};
|
||||
}
|
||||
return {
|
||||
pm: pm.pm,
|
||||
workspaceRoot: Promise.resolve(pm.resolvedDirectory),
|
||||
};
|
||||
});
|
||||
exports.determinePackageManagerEnv = determinePackageManagerEnv;
|
||||
async function findWorkspaceRoot(pm, cwd) {
|
||||
let command;
|
||||
switch (pm) {
|
||||
case packageManager_1.PM.PNPM:
|
||||
command = { command: "pnpm", args: ["--workspace-root", "exec", "pwd"] };
|
||||
break;
|
||||
case packageManager_1.PM.YARN_BERRY:
|
||||
command = { command: "yarn", args: ["workspaces", "list", "--json"] };
|
||||
break;
|
||||
case packageManager_1.PM.YARN: {
|
||||
command = { command: "yarn", args: ["workspaces", "info", "--silent"] };
|
||||
break;
|
||||
}
|
||||
case packageManager_1.PM.BUN:
|
||||
command = { command: "bun", args: ["pm", "ls", "--json"] };
|
||||
break;
|
||||
case packageManager_1.PM.NPM:
|
||||
default:
|
||||
command = { command: "npm", args: ["prefix", "-w"] };
|
||||
break;
|
||||
}
|
||||
const output = await (0, builder_util_1.spawn)(command.command, command.args, { cwd, stdio: ["ignore", "pipe", "ignore"] })
|
||||
.then(async (it) => {
|
||||
const out = it === null || it === void 0 ? void 0 : it.trim();
|
||||
if (!out) {
|
||||
return undefined;
|
||||
}
|
||||
if (pm === packageManager_1.PM.YARN) {
|
||||
JSON.parse(out); // if JSON valid, workspace detected
|
||||
return findNearestPackageJsonWithWorkspacesField(cwd);
|
||||
}
|
||||
else if (pm === packageManager_1.PM.BUN) {
|
||||
const json = JSON.parse(out);
|
||||
if (Array.isArray(json) && json.length > 0) {
|
||||
return findNearestPackageJsonWithWorkspacesField(cwd);
|
||||
}
|
||||
}
|
||||
else if (pm === packageManager_1.PM.YARN_BERRY) {
|
||||
const lines = out
|
||||
.split("\n")
|
||||
.map(l => l.trim())
|
||||
.filter(Boolean);
|
||||
for (const line of lines) {
|
||||
const parsed = JSON.parse(line);
|
||||
if (parsed.location != null) {
|
||||
const potential = path.resolve(cwd, parsed.location);
|
||||
return (await (0, builder_util_1.exists)(potential)) ? findNearestPackageJsonWithWorkspacesField(potential) : undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
return out.length === 0 || out === "undefined" ? undefined : out;
|
||||
})
|
||||
.catch(() => findNearestPackageJsonWithWorkspacesField(cwd));
|
||||
return output;
|
||||
}
|
||||
async function findNearestPackageJsonWithWorkspacesField(dir) {
|
||||
let current = dir;
|
||||
while (true) {
|
||||
const pkgPath = path.join(current, "package.json");
|
||||
try {
|
||||
const pkg = JSON.parse(await fs.readFile(pkgPath, "utf8"));
|
||||
if (pkg.workspaces) {
|
||||
builder_util_1.log.debug({ path: current }, "identified workspace root");
|
||||
return current;
|
||||
}
|
||||
}
|
||||
catch {
|
||||
// ignore
|
||||
}
|
||||
const parent = path.dirname(current);
|
||||
if (parent === current) {
|
||||
break;
|
||||
}
|
||||
current = parent;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
//# sourceMappingURL=index.js.map
|
||||
1
electron/node_modules/app-builder-lib/out/node-module-collector/index.js.map
generated
vendored
Normal file
1
electron/node_modules/app-builder-lib/out/node-module-collector/index.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue