"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.prepareProductBuildArgs = exports.PkgTarget = void 0;
const builder_util_1 = require("builder-util");
const fs_1 = require("builder-util/out/fs");
const appBuilder_1 = require("../util/appBuilder");
const license_1 = require("../util/license");
const promises_1 = require("fs/promises");
const path = require("path");
const appInfo_1 = require("../appInfo");
const macCodeSign_1 = require("../codeSign/macCodeSign");
const core_1 = require("../core");
const certType = "Developer ID Installer";
// http://www.shanekirk.com/2013/10/creating-flat-packages-in-osx/
// to use --scripts, we must build .app bundle separately using pkgbuild
// productbuild --scripts doesn't work (because scripts in this case not added to our package)
// https://github.com/electron-userland/@electron/osx-sign/issues/96#issuecomment-274986942
class PkgTarget extends core_1.Target {
constructor(packager, outDir) {
super("pkg");
this.packager = packager;
this.outDir = outDir;
this.options = {
allowAnywhere: true,
allowCurrentUserHome: true,
allowRootDirectory: true,
...this.packager.config.pkg,
};
}
async build(appPath, arch) {
const packager = this.packager;
const options = this.options;
const appInfo = packager.appInfo;
// 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)
const artifactName = packager.expandArtifactNamePattern(options, "pkg", arch);
const artifactPath = path.join(this.outDir, artifactName);
await packager.info.callArtifactBuildStarted({
targetPresentableName: "pkg",
file: artifactPath,
arch,
});
const keychainFile = (await packager.codeSigningInfo.value).keychainFile;
const appOutDir = this.outDir;
// https://developer.apple.com/library/content/documentation/DeveloperTools/Reference/DistributionDefinitionRef/Chapters/Distribution_XML_Ref.html
const distInfoFile = path.join(appOutDir, "distribution.xml");
const innerPackageFile = path.join(appOutDir, `${(0, appInfo_1.filterCFBundleIdentifier)(appInfo.id)}.pkg`);
const componentPropertyListFile = path.join(appOutDir, `${(0, appInfo_1.filterCFBundleIdentifier)(appInfo.id)}.plist`);
const identity = (await Promise.all([
(0, macCodeSign_1.findIdentity)(certType, options.identity || packager.platformSpecificBuildOptions.identity, keychainFile),
this.customizeDistributionConfiguration(distInfoFile, appPath),
this.buildComponentPackage(appPath, componentPropertyListFile, innerPackageFile),
]))[0];
if (identity == null && packager.forceCodeSigning) {
throw new Error(`Cannot find valid "${certType}" to sign standalone installer, please see https://electron.build/code-signing`);
}
const args = prepareProductBuildArgs(identity, keychainFile);
args.push("--distribution", distInfoFile);
args.push(artifactPath);
(0, builder_util_1.use)(options.productbuild, it => args.push(...it));
await (0, builder_util_1.exec)("productbuild", args, {
cwd: appOutDir,
});
await Promise.all([(0, promises_1.unlink)(innerPackageFile), (0, promises_1.unlink)(distInfoFile)]);
await packager.dispatchArtifactCreated(artifactPath, this, arch, packager.computeSafeArtifactName(artifactName, "pkg", arch));
}
async customizeDistributionConfiguration(distInfoFile, appPath) {
await (0, builder_util_1.exec)("productbuild", ["--synthesize", "--component", appPath, distInfoFile], {
cwd: this.outDir,
});
const options = this.options;
let distInfo = await (0, promises_1.readFile)(distInfoFile, "utf-8");
if (options.mustClose != null && options.mustClose.length !== 0) {
const startContent = ` \n \n`;
const endContent = " \n \n";
let mustCloseContent = "";
options.mustClose.forEach(appId => {
mustCloseContent += ` \n`;
});
distInfo = distInfo.replace("", `${startContent}${mustCloseContent}${endContent}`);
}
const insertIndex = distInfo.lastIndexOf("");
distInfo =
distInfo.substring(0, insertIndex) +
` \n` +
distInfo.substring(insertIndex);
if (options.background != null) {
const background = await this.packager.getResource(options.background.file);
if (background != null) {
const alignment = options.background.alignment || "center";
// noinspection SpellCheckingInspection
const scaling = options.background.scaling || "tofit";
distInfo = distInfo.substring(0, insertIndex) + ` \n` + distInfo.substring(insertIndex);
distInfo =
distInfo.substring(0, insertIndex) + ` \n` + distInfo.substring(insertIndex);
}
}
const welcome = await this.packager.getResource(options.welcome);
if (welcome != null) {
distInfo = distInfo.substring(0, insertIndex) + ` \n` + distInfo.substring(insertIndex);
}
const license = await (0, license_1.getNotLocalizedLicenseFile)(options.license, this.packager);
if (license != null) {
distInfo = distInfo.substring(0, insertIndex) + ` \n` + distInfo.substring(insertIndex);
}
const conclusion = await this.packager.getResource(options.conclusion);
if (conclusion != null) {
distInfo = distInfo.substring(0, insertIndex) + ` \n` + distInfo.substring(insertIndex);
}
(0, builder_util_1.debug)(distInfo);
await (0, promises_1.writeFile)(distInfoFile, distInfo);
}
async buildComponentPackage(appPath, propertyListOutputFile, packageOutputFile) {
const options = this.options;
const rootPath = path.dirname(appPath);
// first produce a component plist template
await (0, builder_util_1.exec)("pkgbuild", ["--analyze", "--root", rootPath, propertyListOutputFile]);
// process the template plist
const plistInfo = (await (0, appBuilder_1.executeAppBuilderAsJson)(["decode-plist", "-f", propertyListOutputFile]))[0].filter((it) => it.RootRelativeBundlePath !== "Electron.dSYM");
if (plistInfo.length > 0) {
const packageInfo = plistInfo[0];
// ChildBundles lists all of electron binaries within the .app.
// There is no particular reason for removing that key, except to be as close as possible to
// the PackageInfo generated by previous versions of electron-builder.
delete packageInfo.ChildBundles;
if (options.isRelocatable != null) {
packageInfo.BundleIsRelocatable = options.isRelocatable;
}
if (options.isVersionChecked != null) {
packageInfo.BundleIsVersionChecked = options.isVersionChecked;
}
if (options.hasStrictIdentifier != null) {
packageInfo.BundleHasStrictIdentifier = options.hasStrictIdentifier;
}
if (options.overwriteAction != null) {
packageInfo.BundleOverwriteAction = options.overwriteAction;
}
await (0, appBuilder_1.executeAppBuilderAndWriteJson)(["encode-plist"], { [propertyListOutputFile]: plistInfo });
}
// now build the package
const args = ["--root", rootPath, "--identifier", this.packager.appInfo.id, "--component-plist", propertyListOutputFile];
(0, builder_util_1.use)(this.options.installLocation || "/Applications", it => args.push("--install-location", it));
if (options.scripts != null) {
args.push("--scripts", path.resolve(this.packager.info.buildResourcesDir, options.scripts));
}
else if (options.scripts !== null) {
const dir = path.join(this.packager.info.buildResourcesDir, "pkg-scripts");
const stat = await (0, fs_1.statOrNull)(dir);
if (stat != null && stat.isDirectory()) {
args.push("--scripts", dir);
}
}
args.push(packageOutputFile);
await (0, builder_util_1.exec)("pkgbuild", args);
}
}
exports.PkgTarget = PkgTarget;
function prepareProductBuildArgs(identity, keychain) {
const args = [];
if (identity != null) {
args.push("--sign", identity.hash);
if (keychain != null) {
args.push("--keychain", keychain);
}
}
return args;
}
exports.prepareProductBuildArgs = prepareProductBuildArgs;
//# sourceMappingURL=pkg.js.map