UNPKG

10.3 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.prepareProductBuildArgs = exports.PkgTarget = void 0;
4const builder_util_1 = require("builder-util");
5const fs_1 = require("builder-util/out/fs");
6const appBuilder_1 = require("../util/appBuilder");
7const license_1 = require("../util/license");
8const promises_1 = require("fs/promises");
9const path = require("path");
10const appInfo_1 = require("../appInfo");
11const macCodeSign_1 = require("../codeSign/macCodeSign");
12const core_1 = require("../core");
13const fs_2 = require("fs");
14const certType = "Developer ID Installer";
15// http://www.shanekirk.com/2013/10/creating-flat-packages-in-osx/
16// to use --scripts, we must build .app bundle separately using pkgbuild
17// productbuild --scripts doesn't work (because scripts in this case not added to our package)
18// https://github.com/electron-userland/@electron/osx-sign/issues/96#issuecomment-274986942
19class PkgTarget extends core_1.Target {
20 constructor(packager, outDir) {
21 super("pkg");
22 this.packager = packager;
23 this.outDir = outDir;
24 this.options = {
25 allowAnywhere: true,
26 allowCurrentUserHome: true,
27 allowRootDirectory: true,
28 ...this.packager.config.pkg,
29 };
30 }
31 async build(appPath, arch) {
32 const packager = this.packager;
33 const options = this.options;
34 const appInfo = packager.appInfo;
35 // pkg doesn't like not ASCII symbols (Could not open package to list files: /Volumes/test/t-gIjdGK/test-project-0/dist/Test App ßW-1.1.0.pkg)
36 const artifactName = packager.expandArtifactNamePattern(options, "pkg", arch);
37 const artifactPath = path.join(this.outDir, artifactName);
38 await packager.info.callArtifactBuildStarted({
39 targetPresentableName: "pkg",
40 file: artifactPath,
41 arch,
42 });
43 const keychainFile = (await packager.codeSigningInfo.value).keychainFile;
44 const appOutDir = this.outDir;
45 // https://developer.apple.com/library/content/documentation/DeveloperTools/Reference/DistributionDefinitionRef/Chapters/Distribution_XML_Ref.html
46 const distInfoFile = path.join(appOutDir, "distribution.xml");
47 const innerPackageFile = path.join(appOutDir, `${(0, appInfo_1.filterCFBundleIdentifier)(appInfo.id)}.pkg`);
48 const componentPropertyListFile = path.join(appOutDir, `${(0, appInfo_1.filterCFBundleIdentifier)(appInfo.id)}.plist`);
49 const identity = (await Promise.all([
50 (0, macCodeSign_1.findIdentity)(certType, options.identity || packager.platformSpecificBuildOptions.identity, keychainFile),
51 this.customizeDistributionConfiguration(distInfoFile, appPath),
52 this.buildComponentPackage(appPath, componentPropertyListFile, innerPackageFile),
53 ]))[0];
54 if (identity == null && packager.forceCodeSigning) {
55 throw new Error(`Cannot find valid "${certType}" to sign standalone installer, please see https://electron.build/code-signing`);
56 }
57 const args = prepareProductBuildArgs(identity, keychainFile);
58 args.push("--distribution", distInfoFile);
59 args.push(artifactPath);
60 (0, builder_util_1.use)(options.productbuild, it => args.push(...it));
61 await (0, builder_util_1.exec)("productbuild", args, {
62 cwd: appOutDir,
63 });
64 await Promise.all([(0, promises_1.unlink)(innerPackageFile), (0, promises_1.unlink)(distInfoFile)]);
65 await packager.dispatchArtifactCreated(artifactPath, this, arch, packager.computeSafeArtifactName(artifactName, "pkg", arch));
66 }
67 async customizeDistributionConfiguration(distInfoFile, appPath) {
68 await (0, builder_util_1.exec)("productbuild", ["--synthesize", "--component", appPath, distInfoFile], {
69 cwd: this.outDir,
70 });
71 const options = this.options;
72 let distInfo = await (0, promises_1.readFile)(distInfoFile, "utf-8");
73 if (options.mustClose != null && options.mustClose.length !== 0) {
74 const startContent = ` <pkg-ref id="${this.packager.appInfo.id}">\n <must-close>\n`;
75 const endContent = " </must-close>\n </pkg-ref>\n</installer-gui-script>";
76 let mustCloseContent = "";
77 options.mustClose.forEach(appId => {
78 mustCloseContent += ` <app id="${appId}"/>\n`;
79 });
80 distInfo = distInfo.replace("</installer-gui-script>", `${startContent}${mustCloseContent}${endContent}`);
81 }
82 const insertIndex = distInfo.lastIndexOf("</installer-gui-script>");
83 distInfo =
84 distInfo.substring(0, insertIndex) +
85 ` <domains enable_anywhere="${options.allowAnywhere}" enable_currentUserHome="${options.allowCurrentUserHome}" enable_localSystem="${options.allowRootDirectory}" />\n` +
86 distInfo.substring(insertIndex);
87 if (options.background != null) {
88 const background = await this.packager.getResource(options.background.file);
89 if (background != null) {
90 const alignment = options.background.alignment || "center";
91 // noinspection SpellCheckingInspection
92 const scaling = options.background.scaling || "tofit";
93 distInfo = distInfo.substring(0, insertIndex) + ` <background file="${background}" alignment="${alignment}" scaling="${scaling}"/>\n` + distInfo.substring(insertIndex);
94 distInfo =
95 distInfo.substring(0, insertIndex) + ` <background-darkAqua file="${background}" alignment="${alignment}" scaling="${scaling}"/>\n` + distInfo.substring(insertIndex);
96 }
97 }
98 const welcome = await this.packager.getResource(options.welcome);
99 if (welcome != null) {
100 distInfo = distInfo.substring(0, insertIndex) + ` <welcome file="${welcome}"/>\n` + distInfo.substring(insertIndex);
101 }
102 const license = await (0, license_1.getNotLocalizedLicenseFile)(options.license, this.packager);
103 if (license != null) {
104 distInfo = distInfo.substring(0, insertIndex) + ` <license file="${license}"/>\n` + distInfo.substring(insertIndex);
105 }
106 const conclusion = await this.packager.getResource(options.conclusion);
107 if (conclusion != null) {
108 distInfo = distInfo.substring(0, insertIndex) + ` <conclusion file="${conclusion}"/>\n` + distInfo.substring(insertIndex);
109 }
110 (0, builder_util_1.debug)(distInfo);
111 await (0, promises_1.writeFile)(distInfoFile, distInfo);
112 }
113 async buildComponentPackage(appPath, propertyListOutputFile, packageOutputFile) {
114 var _a;
115 const options = this.options;
116 const rootPath = path.dirname(appPath);
117 // first produce a component plist template
118 await (0, builder_util_1.exec)("pkgbuild", ["--analyze", "--root", rootPath, propertyListOutputFile]);
119 // process the template plist
120 const plistInfo = (await (0, appBuilder_1.executeAppBuilderAsJson)(["decode-plist", "-f", propertyListOutputFile]))[0].filter((it) => it.RootRelativeBundlePath !== "Electron.dSYM");
121 let packageInfo = {};
122 if (plistInfo.length > 0) {
123 packageInfo = plistInfo[0];
124 // ChildBundles lists all of electron binaries within the .app.
125 // There is no particular reason for removing that key, except to be as close as possible to
126 // the PackageInfo generated by previous versions of electron-builder.
127 delete packageInfo.ChildBundles;
128 if (options.isRelocatable != null) {
129 packageInfo.BundleIsRelocatable = options.isRelocatable;
130 }
131 if (options.isVersionChecked != null) {
132 packageInfo.BundleIsVersionChecked = options.isVersionChecked;
133 }
134 if (options.hasStrictIdentifier != null) {
135 packageInfo.BundleHasStrictIdentifier = options.hasStrictIdentifier;
136 }
137 if (options.overwriteAction != null) {
138 packageInfo.BundleOverwriteAction = options.overwriteAction;
139 }
140 }
141 // now build the package
142 const args = ["--root", rootPath, "--identifier", this.packager.appInfo.id, "--component-plist", propertyListOutputFile];
143 (0, builder_util_1.use)(this.options.installLocation || "/Applications", it => args.push("--install-location", it));
144 // nasty nested ternary-statement, probably should optimize
145 const scriptsDir =
146 // user-provided scripts dir
147 options.scripts != null
148 ? path.resolve(this.packager.info.buildResourcesDir, options.scripts)
149 : // fallback to default unless user explicitly sets null
150 options.scripts !== null
151 ? path.join(this.packager.info.buildResourcesDir, "pkg-scripts")
152 : null;
153 if (scriptsDir && ((_a = (await (0, fs_1.statOrNull)(scriptsDir))) === null || _a === void 0 ? void 0 : _a.isDirectory())) {
154 const dirContents = (0, fs_2.readdirSync)(scriptsDir);
155 dirContents.forEach(name => {
156 if (name.includes("preinstall")) {
157 packageInfo.BundlePreInstallScriptPath = name;
158 }
159 else if (name.includes("postinstall")) {
160 packageInfo.BundlePostInstallScriptPath = name;
161 }
162 });
163 args.push("--scripts", scriptsDir);
164 }
165 if (plistInfo.length > 0) {
166 await (0, appBuilder_1.executeAppBuilderAndWriteJson)(["encode-plist"], { [propertyListOutputFile]: plistInfo });
167 }
168 args.push(packageOutputFile);
169 await (0, builder_util_1.exec)("pkgbuild", args);
170 }
171}
172exports.PkgTarget = PkgTarget;
173function prepareProductBuildArgs(identity, keychain) {
174 const args = [];
175 if (identity != null) {
176 args.push("--sign", identity.hash);
177 if (keychain != null) {
178 args.push("--keychain", keychain);
179 }
180 }
181 return args;
182}
183exports.prepareProductBuildArgs = prepareProductBuildArgs;
184//# sourceMappingURL=pkg.js.map
\No newline at end of file