app-builder-lib 27.0.0-alpha.4 → 27.0.0-alpha.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/appInfo.d.ts +1 -1
- package/dist/appInfo.d.ts.map +1 -1
- package/dist/appInfo.js +3 -3
- package/dist/appInfo.js.map +1 -1
- package/dist/codeSign/mac/macCodeSign.d.ts.map +1 -1
- package/dist/codeSign/mac/macCodeSign.js +3 -6
- package/dist/codeSign/mac/macCodeSign.js.map +1 -1
- package/dist/codeSign/win/signtoolBaseSignManager.d.ts.map +1 -1
- package/dist/codeSign/win/signtoolBaseSignManager.js +6 -4
- package/dist/codeSign/win/signtoolBaseSignManager.js.map +1 -1
- package/dist/codeSign/win/windowsSignAzureManager.d.ts.map +1 -1
- package/dist/codeSign/win/windowsSignAzureManager.js +31 -21
- package/dist/codeSign/win/windowsSignAzureManager.js.map +1 -1
- package/dist/configuration.d.ts +84 -44
- package/dist/configuration.d.ts.map +1 -1
- package/dist/configuration.js +11 -1
- package/dist/configuration.js.map +1 -1
- package/dist/electron/ElectronFramework.d.ts +2 -1
- package/dist/electron/ElectronFramework.d.ts.map +1 -1
- package/dist/electron/ElectronFramework.js +32 -28
- package/dist/electron/ElectronFramework.js.map +1 -1
- package/dist/electron/electronArchSupport.d.ts +12 -0
- package/dist/electron/electronArchSupport.d.ts.map +1 -0
- package/dist/electron/electronArchSupport.js +58 -0
- package/dist/electron/electronArchSupport.js.map +1 -0
- package/dist/electron/electronVersion.d.ts.map +1 -1
- package/dist/electron/electronVersion.js +1 -11
- package/dist/electron/electronVersion.js.map +1 -1
- package/dist/electron/mac/electronMac.js +12 -21
- package/dist/electron/mac/electronMac.js.map +1 -1
- package/dist/electron/mac/electronMacUtils.d.ts +24 -0
- package/dist/electron/mac/electronMacUtils.d.ts.map +1 -0
- package/dist/electron/mac/electronMacUtils.js +42 -0
- package/dist/electron/mac/electronMacUtils.js.map +1 -0
- package/dist/fileMatcher.d.ts +27 -2
- package/dist/fileMatcher.d.ts.map +1 -1
- package/dist/fileMatcher.js +204 -16
- package/dist/fileMatcher.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/indexInternal.d.ts +8 -5
- package/dist/indexInternal.d.ts.map +1 -1
- package/dist/indexInternal.js +8 -4
- package/dist/indexInternal.js.map +1 -1
- package/dist/macPackager.d.ts.map +1 -1
- package/dist/macPackager.js +15 -3
- package/dist/macPackager.js.map +1 -1
- package/dist/node-module-collector/moduleManager.d.ts +3 -1
- package/dist/node-module-collector/moduleManager.d.ts.map +1 -1
- package/dist/node-module-collector/moduleManager.js +9 -1
- package/dist/node-module-collector/moduleManager.js.map +1 -1
- package/dist/node-module-collector/nodeModulesCollector.d.ts +17 -1
- package/dist/node-module-collector/nodeModulesCollector.d.ts.map +1 -1
- package/dist/node-module-collector/nodeModulesCollector.js +67 -1
- package/dist/node-module-collector/nodeModulesCollector.js.map +1 -1
- package/dist/node-module-collector/pnpmNodeModulesCollector.js +5 -5
- package/dist/node-module-collector/pnpmNodeModulesCollector.js.map +1 -1
- package/dist/node-module-collector/types.d.ts +2 -0
- package/dist/node-module-collector/types.d.ts.map +1 -1
- package/dist/node-module-collector/types.js.map +1 -1
- package/dist/options/MsixOptions.d.ts +126 -0
- package/dist/options/MsixOptions.d.ts.map +1 -0
- package/dist/options/MsixOptions.js +2 -0
- package/dist/options/MsixOptions.js.map +1 -0
- package/dist/options/PlatformSpecificBuildOptions.d.ts +0 -6
- package/dist/options/PlatformSpecificBuildOptions.d.ts.map +1 -1
- package/dist/options/PlatformSpecificBuildOptions.js.map +1 -1
- package/dist/options/SnapOptions.d.ts +15 -13
- package/dist/options/SnapOptions.d.ts.map +1 -1
- package/dist/options/SnapOptions.js.map +1 -1
- package/dist/options/macOptions.d.ts +4 -4
- package/dist/options/macOptions.d.ts.map +1 -1
- package/dist/options/macOptions.js.map +1 -1
- package/dist/options/winOptions.d.ts +166 -36
- package/dist/options/winOptions.d.ts.map +1 -1
- package/dist/options/winOptions.js.map +1 -1
- package/dist/packager.d.ts +2 -0
- package/dist/packager.d.ts.map +1 -1
- package/dist/packager.js +26 -21
- package/dist/packager.js.map +1 -1
- package/dist/platformPackager.d.ts +2 -0
- package/dist/platformPackager.d.ts.map +1 -1
- package/dist/platformPackager.js +6 -0
- package/dist/platformPackager.js.map +1 -1
- package/dist/publish/PublishManager.d.ts +1 -0
- package/dist/publish/PublishManager.d.ts.map +1 -1
- package/dist/publish/PublishManager.js +20 -6
- package/dist/publish/PublishManager.js.map +1 -1
- package/dist/publish/updateInfoBuilder.d.ts.map +1 -1
- package/dist/publish/updateInfoBuilder.js +20 -22
- package/dist/publish/updateInfoBuilder.js.map +1 -1
- package/dist/targets/archive.d.ts +11 -0
- package/dist/targets/archive.d.ts.map +1 -1
- package/dist/targets/archive.js +40 -22
- package/dist/targets/archive.js.map +1 -1
- package/dist/targets/linux/FpmTarget.d.ts.map +1 -1
- package/dist/targets/linux/FpmTarget.js +3 -3
- package/dist/targets/linux/FpmTarget.js.map +1 -1
- package/dist/targets/linux/appimage/AppImageTarget.d.ts.map +1 -1
- package/dist/targets/linux/appimage/AppImageTarget.js +5 -6
- package/dist/targets/linux/appimage/AppImageTarget.js.map +1 -1
- package/dist/targets/linux/snap/SnapTarget.d.ts +1 -1
- package/dist/targets/linux/snap/SnapTarget.d.ts.map +1 -1
- package/dist/targets/linux/snap/SnapTarget.js +23 -1
- package/dist/targets/linux/snap/SnapTarget.js.map +1 -1
- package/dist/targets/linux/snap/core24.d.ts +1 -1
- package/dist/targets/linux/snap/core24.d.ts.map +1 -1
- package/dist/targets/linux/snap/core24.js +3 -2
- package/dist/targets/linux/snap/core24.js.map +1 -1
- package/dist/targets/linux/snap/coreCustom.d.ts +1 -1
- package/dist/targets/linux/snap/coreCustom.d.ts.map +1 -1
- package/dist/targets/linux/snap/coreCustom.js +2 -2
- package/dist/targets/linux/snap/coreCustom.js.map +1 -1
- package/dist/targets/linux/snap/coreLegacy.d.ts +1 -1
- package/dist/targets/linux/snap/coreLegacy.d.ts.map +1 -1
- package/dist/targets/linux/snap/coreLegacy.js +2 -1
- package/dist/targets/linux/snap/coreLegacy.js.map +1 -1
- package/dist/targets/linux/snap/snapcraft.d.ts +190 -0
- package/dist/targets/linux/snap/snapcraft.d.ts.map +1 -0
- package/dist/targets/linux/snap/snapcraft.js +11 -0
- package/dist/targets/linux/snap/snapcraft.js.map +1 -0
- package/dist/targets/linux/snap/snapcraftBuilder.d.ts +7 -1
- package/dist/targets/linux/snap/snapcraftBuilder.d.ts.map +1 -1
- package/dist/targets/linux/snap/snapcraftBuilder.js +57 -20
- package/dist/targets/linux/snap/snapcraftBuilder.js.map +1 -1
- package/dist/targets/mac/MacTargetHelper.d.ts +6 -0
- package/dist/targets/mac/MacTargetHelper.d.ts.map +1 -1
- package/dist/targets/mac/MacTargetHelper.js +22 -1
- package/dist/targets/mac/MacTargetHelper.js.map +1 -1
- package/dist/targets/targetFactory.d.ts +7 -0
- package/dist/targets/targetFactory.d.ts.map +1 -1
- package/dist/targets/targetFactory.js +28 -0
- package/dist/targets/targetFactory.js.map +1 -1
- package/dist/targets/win/AppxTarget.d.ts +0 -2
- package/dist/targets/win/AppxTarget.d.ts.map +1 -1
- package/dist/targets/win/AppxTarget.js +37 -317
- package/dist/targets/win/AppxTarget.js.map +1 -1
- package/dist/targets/win/MsixTarget.d.ts +22 -0
- package/dist/targets/win/MsixTarget.d.ts.map +1 -0
- package/dist/targets/win/MsixTarget.js +214 -0
- package/dist/targets/win/MsixTarget.js.map +1 -0
- package/dist/targets/win/nsis/NsisTarget.d.ts +3 -2
- package/dist/targets/win/nsis/NsisTarget.d.ts.map +1 -1
- package/dist/targets/win/nsis/NsisTarget.js +28 -46
- package/dist/targets/win/nsis/NsisTarget.js.map +1 -1
- package/dist/targets/win/nsis/nsisScriptGenerator.d.ts.map +1 -1
- package/dist/targets/win/nsis/nsisScriptGenerator.js +2 -1
- package/dist/targets/win/nsis/nsisScriptGenerator.js.map +1 -1
- package/dist/targets/win/nsis/nsisUtil.d.ts +5 -2
- package/dist/targets/win/nsis/nsisUtil.d.ts.map +1 -1
- package/dist/targets/win/nsis/nsisUtil.js +46 -22
- package/dist/targets/win/nsis/nsisUtil.js.map +1 -1
- package/dist/targets/win/nsis/progId.d.ts +21 -0
- package/dist/targets/win/nsis/progId.d.ts.map +1 -0
- package/dist/targets/win/nsis/progId.js +60 -0
- package/dist/targets/win/nsis/progId.js.map +1 -0
- package/dist/targets/win/winAppUtil.d.ts +115 -0
- package/dist/targets/win/winAppUtil.d.ts.map +1 -0
- package/dist/targets/win/winAppUtil.js +407 -0
- package/dist/targets/win/winAppUtil.js.map +1 -0
- package/dist/toolsets/7zip.d.ts.map +1 -1
- package/dist/toolsets/7zip.js +3 -1
- package/dist/toolsets/7zip.js.map +1 -1
- package/dist/toolsets/appimage.d.ts +3 -3
- package/dist/toolsets/appimage.d.ts.map +1 -1
- package/dist/toolsets/appimage.js +9 -6
- package/dist/toolsets/appimage.js.map +1 -1
- package/dist/toolsets/custom.d.ts +1 -3
- package/dist/toolsets/custom.d.ts.map +1 -1
- package/dist/toolsets/custom.js +4 -133
- package/dist/toolsets/custom.js.map +1 -1
- package/dist/toolsets/fpm.d.ts.map +1 -1
- package/dist/toolsets/fpm.js +11 -5
- package/dist/toolsets/fpm.js.map +1 -1
- package/dist/toolsets/icons.d.ts.map +1 -1
- package/dist/toolsets/icons.js +4 -1
- package/dist/toolsets/icons.js.map +1 -1
- package/dist/toolsets/linuxToolsMac.d.ts.map +1 -1
- package/dist/toolsets/linuxToolsMac.js +4 -1
- package/dist/toolsets/linuxToolsMac.js.map +1 -1
- package/dist/toolsets/nsis.d.ts.map +1 -1
- package/dist/toolsets/nsis.js +6 -3
- package/dist/toolsets/nsis.js.map +1 -1
- package/dist/toolsets/version.d.ts +12 -0
- package/dist/toolsets/version.d.ts.map +1 -0
- package/dist/toolsets/version.js +13 -0
- package/dist/toolsets/version.js.map +1 -0
- package/dist/toolsets/winCodeSign.d.ts +20 -3
- package/dist/toolsets/winCodeSign.d.ts.map +1 -1
- package/dist/toolsets/winCodeSign.js +56 -27
- package/dist/toolsets/winCodeSign.js.map +1 -1
- package/dist/toolsets/wine.d.ts +2 -1
- package/dist/toolsets/wine.d.ts.map +1 -1
- package/dist/toolsets/wine.js +15 -13
- package/dist/toolsets/wine.js.map +1 -1
- package/dist/util/NodeModuleCopyHelper.js +3 -3
- package/dist/util/NodeModuleCopyHelper.js.map +1 -1
- package/dist/util/appFileCopier.d.ts +39 -0
- package/dist/util/appFileCopier.d.ts.map +1 -1
- package/dist/util/appFileCopier.js +88 -22
- package/dist/util/appFileCopier.js.map +1 -1
- package/dist/util/config/config.d.ts +1 -0
- package/dist/util/config/config.d.ts.map +1 -1
- package/dist/util/config/config.js +4 -1
- package/dist/util/config/config.js.map +1 -1
- package/dist/util/config/load.d.ts +2 -2
- package/dist/util/config/load.d.ts.map +1 -1
- package/dist/util/config/load.js +3 -12
- package/dist/util/config/load.js.map +1 -1
- package/dist/util/config/schemaValidator.js +1 -1
- package/dist/util/config/schemaValidator.js.map +1 -1
- package/dist/util/electronGet.d.ts +6 -3
- package/dist/util/electronGet.d.ts.map +1 -1
- package/dist/util/electronGet.js +40 -20
- package/dist/util/electronGet.js.map +1 -1
- package/dist/util/flags.d.ts +0 -2
- package/dist/util/flags.d.ts.map +1 -1
- package/dist/util/flags.js +0 -6
- package/dist/util/flags.js.map +1 -1
- package/dist/util/hash.d.ts +1 -1
- package/dist/util/hash.d.ts.map +1 -1
- package/dist/util/hash.js +1 -15
- package/dist/util/hash.js.map +1 -1
- package/dist/util/packageMetadata.js +0 -10
- package/dist/util/packageMetadata.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/dist/vm/ParallelsVm.d.ts.map +1 -1
- package/dist/vm/ParallelsVm.js +18 -5
- package/dist/vm/ParallelsVm.js.map +1 -1
- package/dist/winPackager.d.ts.map +1 -1
- package/dist/winPackager.js +3 -0
- package/dist/winPackager.js.map +1 -1
- package/package.json +8 -8
- package/scheme.json +556 -133
- package/templates/appx/appxmanifest.xml +1 -1
- package/templates/msix/appxmanifest.xml +45 -0
- package/templates/nsis/installSection.nsh +14 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export declare const ELECTRON_BUILDER_NS_UUID: Buffer<ArrayBufferLike>;
|
|
2
|
+
/**
|
|
3
|
+
* Builds Windows file-association ProgIDs that follow Microsoft's recommendations
|
|
4
|
+
* (https://learn.microsoft.com/windows/win32/com/-progid--key):
|
|
5
|
+
* - at most 39 characters,
|
|
6
|
+
* - only alphanumeric characters plus a single separating period,
|
|
7
|
+
* - must not start with a digit.
|
|
8
|
+
*
|
|
9
|
+
* The result has the form `<program>.<component>`, where `<program>` is derived from the product
|
|
10
|
+
* filename (so it stays human-readable in the registry) and `<component>` mixes a readable prefix
|
|
11
|
+
* with a UUIDv5 derived from the app GUID. This keeps the ProgID unique across applications and
|
|
12
|
+
* stable for a given input, so the installer (register) and uninstaller (unregister) always agree.
|
|
13
|
+
*/
|
|
14
|
+
export declare class ProgIdMaker {
|
|
15
|
+
private readonly program;
|
|
16
|
+
private readonly namespace;
|
|
17
|
+
constructor(guid: string, productFilename: string);
|
|
18
|
+
progId(nameOrExt: string): string;
|
|
19
|
+
private static resolveProgram;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=progId.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"progId.d.ts","sourceRoot":"","sources":["../../../../src/targets/win/nsis/progId.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,wBAAwB,yBAAqD,CAAA;AAiB1F;;;;;;;;;;;GAWG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAQ;IAChC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAQ;gBAEtB,IAAI,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM;IASjD,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAQjC,OAAO,CAAC,MAAM,CAAC,cAAc;CAa9B"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { UUID } from "builder-util-runtime";
|
|
2
|
+
// noinspection SpellCheckingInspection
|
|
3
|
+
export const ELECTRON_BUILDER_NS_UUID = UUID.parse("50e065bc-3134-11e6-9bab-38c9862bdaf3");
|
|
4
|
+
// Microsoft caps a ProgID at 39 characters.
|
|
5
|
+
const MAX_PROG_ID_LENGTH = 39;
|
|
6
|
+
// Budget for the human-readable head (program + "." + component prefix); the rest is reserved for the
|
|
7
|
+
// UUID tail so that some entropy always survives the final truncation.
|
|
8
|
+
const MAX_READABLE_LENGTH = 31;
|
|
9
|
+
// Cap on the readable program segment, leaving room for the component to carry entropy.
|
|
10
|
+
const MAX_PROGRAM_LENGTH = 19;
|
|
11
|
+
// A product filename that sanitizes shorter than this is too short to be a useful program segment.
|
|
12
|
+
const MIN_PROGRAM_LENGTH = 6;
|
|
13
|
+
// ProgIDs may only contain alphanumerics plus a single separating period, so drop everything else.
|
|
14
|
+
function sanitize(value) {
|
|
15
|
+
return value.replace(/[^A-Za-z0-9]/g, "");
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Builds Windows file-association ProgIDs that follow Microsoft's recommendations
|
|
19
|
+
* (https://learn.microsoft.com/windows/win32/com/-progid--key):
|
|
20
|
+
* - at most 39 characters,
|
|
21
|
+
* - only alphanumeric characters plus a single separating period,
|
|
22
|
+
* - must not start with a digit.
|
|
23
|
+
*
|
|
24
|
+
* The result has the form `<program>.<component>`, where `<program>` is derived from the product
|
|
25
|
+
* filename (so it stays human-readable in the registry) and `<component>` mixes a readable prefix
|
|
26
|
+
* with a UUIDv5 derived from the app GUID. This keeps the ProgID unique across applications and
|
|
27
|
+
* stable for a given input, so the installer (register) and uninstaller (unregister) always agree.
|
|
28
|
+
*/
|
|
29
|
+
export class ProgIdMaker {
|
|
30
|
+
constructor(guid, productFilename) {
|
|
31
|
+
// `guid` may be any user-supplied string (including a non-UUID), so normalize it to a real UUID.
|
|
32
|
+
// It is lowercased because UUID.parse only understands lowercase hex; an uppercase GUID would
|
|
33
|
+
// otherwise be parsed into a corrupt namespace and collide across applications.
|
|
34
|
+
const uuidString = (UUID.check(guid) ? guid : UUID.v5(guid, ELECTRON_BUILDER_NS_UUID)).toLowerCase();
|
|
35
|
+
this.namespace = UUID.parse(uuidString);
|
|
36
|
+
this.program = ProgIdMaker.resolveProgram(guid, productFilename, uuidString);
|
|
37
|
+
}
|
|
38
|
+
progId(nameOrExt) {
|
|
39
|
+
const componentPrefix = sanitize(nameOrExt).slice(0, MAX_READABLE_LENGTH - this.program.length);
|
|
40
|
+
const componentUuid = sanitize(UUID.v5(nameOrExt, this.namespace));
|
|
41
|
+
return `${this.program}.${componentPrefix}${componentUuid}`.slice(0, MAX_PROG_ID_LENGTH);
|
|
42
|
+
}
|
|
43
|
+
// Resolves the readable program segment, preferring the product filename and falling back to the
|
|
44
|
+
// GUID so the result is always non-empty and never starts with a digit (both Microsoft requirements).
|
|
45
|
+
static resolveProgram(guid, productFilename, uuidString) {
|
|
46
|
+
let program = sanitize(productFilename);
|
|
47
|
+
if (program.length < MIN_PROGRAM_LENGTH) {
|
|
48
|
+
program = sanitize(guid);
|
|
49
|
+
}
|
|
50
|
+
if (program.length < MIN_PROGRAM_LENGTH) {
|
|
51
|
+
// `App<uuid>` is guaranteed long enough and starts with a letter.
|
|
52
|
+
program = sanitize(`App${uuidString}`);
|
|
53
|
+
}
|
|
54
|
+
else if (/^\d/.test(program)) {
|
|
55
|
+
program = `App${program}`;
|
|
56
|
+
}
|
|
57
|
+
return program.slice(0, MAX_PROGRAM_LENGTH);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=progId.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"progId.js","sourceRoot":"","sources":["../../../../src/targets/win/nsis/progId.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAA;AAE3C,uCAAuC;AACvC,MAAM,CAAC,MAAM,wBAAwB,GAAG,IAAI,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAA;AAE1F,4CAA4C;AAC5C,MAAM,kBAAkB,GAAG,EAAE,CAAA;AAC7B,sGAAsG;AACtG,uEAAuE;AACvE,MAAM,mBAAmB,GAAG,EAAE,CAAA;AAC9B,wFAAwF;AACxF,MAAM,kBAAkB,GAAG,EAAE,CAAA;AAC7B,mGAAmG;AACnG,MAAM,kBAAkB,GAAG,CAAC,CAAA;AAE5B,mGAAmG;AACnG,SAAS,QAAQ,CAAC,KAAa;IAC7B,OAAO,KAAK,CAAC,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC,CAAA;AAC3C,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,OAAO,WAAW;IAItB,YAAY,IAAY,EAAE,eAAuB;QAC/C,iGAAiG;QACjG,8FAA8F;QAC9F,gFAAgF;QAChF,MAAM,UAAU,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,wBAAwB,CAAC,CAAC,CAAC,WAAW,EAAE,CAAA;QACpG,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAA;QACvC,IAAI,CAAC,OAAO,GAAG,WAAW,CAAC,cAAc,CAAC,IAAI,EAAE,eAAe,EAAE,UAAU,CAAC,CAAA;IAC9E,CAAC;IAED,MAAM,CAAC,SAAiB;QACtB,MAAM,eAAe,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,mBAAmB,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;QAC/F,MAAM,aAAa,GAAG,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAA;QAClE,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,eAAe,GAAG,aAAa,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,kBAAkB,CAAC,CAAA;IAC1F,CAAC;IAED,iGAAiG;IACjG,sGAAsG;IAC9F,MAAM,CAAC,cAAc,CAAC,IAAY,EAAE,eAAuB,EAAE,UAAkB;QACrF,IAAI,OAAO,GAAG,QAAQ,CAAC,eAAe,CAAC,CAAA;QACvC,IAAI,OAAO,CAAC,MAAM,GAAG,kBAAkB,EAAE,CAAC;YACxC,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAA;QAC1B,CAAC;QACD,IAAI,OAAO,CAAC,MAAM,GAAG,kBAAkB,EAAE,CAAC;YACxC,kEAAkE;YAClE,OAAO,GAAG,QAAQ,CAAC,MAAM,UAAU,EAAE,CAAC,CAAA;QACxC,CAAC;aAAM,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAC/B,OAAO,GAAG,MAAM,OAAO,EAAE,CAAA;QAC3B,CAAC;QACD,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,kBAAkB,CAAC,CAAA;IAC7C,CAAC;CACF","sourcesContent":["import { UUID } from \"builder-util-runtime\"\n\n// noinspection SpellCheckingInspection\nexport const ELECTRON_BUILDER_NS_UUID = UUID.parse(\"50e065bc-3134-11e6-9bab-38c9862bdaf3\")\n\n// Microsoft caps a ProgID at 39 characters.\nconst MAX_PROG_ID_LENGTH = 39\n// Budget for the human-readable head (program + \".\" + component prefix); the rest is reserved for the\n// UUID tail so that some entropy always survives the final truncation.\nconst MAX_READABLE_LENGTH = 31\n// Cap on the readable program segment, leaving room for the component to carry entropy.\nconst MAX_PROGRAM_LENGTH = 19\n// A product filename that sanitizes shorter than this is too short to be a useful program segment.\nconst MIN_PROGRAM_LENGTH = 6\n\n// ProgIDs may only contain alphanumerics plus a single separating period, so drop everything else.\nfunction sanitize(value: string): string {\n return value.replace(/[^A-Za-z0-9]/g, \"\")\n}\n\n/**\n * Builds Windows file-association ProgIDs that follow Microsoft's recommendations\n * (https://learn.microsoft.com/windows/win32/com/-progid--key):\n * - at most 39 characters,\n * - only alphanumeric characters plus a single separating period,\n * - must not start with a digit.\n *\n * The result has the form `<program>.<component>`, where `<program>` is derived from the product\n * filename (so it stays human-readable in the registry) and `<component>` mixes a readable prefix\n * with a UUIDv5 derived from the app GUID. This keeps the ProgID unique across applications and\n * stable for a given input, so the installer (register) and uninstaller (unregister) always agree.\n */\nexport class ProgIdMaker {\n private readonly program: string\n private readonly namespace: Buffer\n\n constructor(guid: string, productFilename: string) {\n // `guid` may be any user-supplied string (including a non-UUID), so normalize it to a real UUID.\n // It is lowercased because UUID.parse only understands lowercase hex; an uppercase GUID would\n // otherwise be parsed into a corrupt namespace and collide across applications.\n const uuidString = (UUID.check(guid) ? guid : UUID.v5(guid, ELECTRON_BUILDER_NS_UUID)).toLowerCase()\n this.namespace = UUID.parse(uuidString)\n this.program = ProgIdMaker.resolveProgram(guid, productFilename, uuidString)\n }\n\n progId(nameOrExt: string): string {\n const componentPrefix = sanitize(nameOrExt).slice(0, MAX_READABLE_LENGTH - this.program.length)\n const componentUuid = sanitize(UUID.v5(nameOrExt, this.namespace))\n return `${this.program}.${componentPrefix}${componentUuid}`.slice(0, MAX_PROG_ID_LENGTH)\n }\n\n // Resolves the readable program segment, preferring the product filename and falling back to the\n // GUID so the result is always non-empty and never starts with a digit (both Microsoft requirements).\n private static resolveProgram(guid: string, productFilename: string, uuidString: string): string {\n let program = sanitize(productFilename)\n if (program.length < MIN_PROGRAM_LENGTH) {\n program = sanitize(guid)\n }\n if (program.length < MIN_PROGRAM_LENGTH) {\n // `App<uuid>` is guaranteed long enough and starts with a letter.\n program = sanitize(`App${uuidString}`)\n } else if (/^\\d/.test(program)) {\n program = `App${program}`\n }\n return program.slice(0, MAX_PROGRAM_LENGTH)\n }\n}\n"]}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { Arch, escapeForXml } from "builder-util";
|
|
2
|
+
import type { MsixWindowsService } from "../../options/MsixOptions.js";
|
|
3
|
+
import { Nullish } from "builder-util-runtime";
|
|
4
|
+
import type { Target, TargetSpecificOptions } from "../../core.js";
|
|
5
|
+
import { FileAssociation } from "../../options/FileAssociation.js";
|
|
6
|
+
import { Protocol } from "../../options/PlatformSpecificBuildOptions.js";
|
|
7
|
+
import { VmManager } from "../../vm/vm.js";
|
|
8
|
+
import type { WinPackager } from "../../winPackager.js";
|
|
9
|
+
export declare const APPX_ASSETS_DIR_NAME = "appx";
|
|
10
|
+
/**
|
|
11
|
+
* Escapes a string for safe use as an XML attribute value (double- or single-quoted) or element text.
|
|
12
|
+
* Aliased to builder-util's {@link escapeForXml} so the Appx/MSIX manifest path shares the single
|
|
13
|
+
* consolidated escaper (PR #9853) and cannot drift from it.
|
|
14
|
+
*/
|
|
15
|
+
export declare const escapeXmlAttr: typeof escapeForXml;
|
|
16
|
+
/**
|
|
17
|
+
* Manifest macros whose substituted values are raw user/config text and therefore must be
|
|
18
|
+
* XML-escaped before being placed into the (Appx/MSIX) manifest. Every other macro either
|
|
19
|
+
* returns a prebuilt XML fragment (capabilities, extensions, lockScreen, defaultTile,
|
|
20
|
+
* splashScreen, resourceLanguages, packageIntegrity) or a validated/constant value
|
|
21
|
+
* (version, applicationId, identityName, arch, logo, square*Logo) and must NOT be escaped.
|
|
22
|
+
*
|
|
23
|
+
* Note: `publisher` is emitted inside a single-quoted attribute (`Publisher='...'`). escapeForXml
|
|
24
|
+
* escapes `& < > " '` — apostrophes become `'`, which is valid inside the single-quoted
|
|
25
|
+
* attribute, so a `'` in a certificate Subject is handled correctly.
|
|
26
|
+
*/
|
|
27
|
+
export declare const RAW_TEXT_MANIFEST_MACROS: ReadonlySet<string>;
|
|
28
|
+
/**
|
|
29
|
+
* Substitutes `${macro}` placeholders in an Appx/MSIX manifest template. `resolve` returns the
|
|
30
|
+
* RAW value for a macro; values for macros in {@link RAW_TEXT_MANIFEST_MACROS} are XML-escaped
|
|
31
|
+
* here so individual call sites cannot forget to. `resolve` may throw for unknown macros.
|
|
32
|
+
*/
|
|
33
|
+
export declare function substituteManifestMacros(template: string, resolve: (macro: string) => string): string;
|
|
34
|
+
export declare const DEFAULT_RESOURCE_LANG = "en-US";
|
|
35
|
+
export declare const vendorAssetsForDefaultAssets: Record<string, string>;
|
|
36
|
+
export declare const restrictedApplicationIdValues: string[];
|
|
37
|
+
export declare function computeUserAssets(vm: VmManager, vendorPath: string, userAssetDir: string | null): Promise<{
|
|
38
|
+
userAssets: string[];
|
|
39
|
+
mappings: string[];
|
|
40
|
+
allAssets: string[];
|
|
41
|
+
}>;
|
|
42
|
+
/**
|
|
43
|
+
* The makeappx mapping file (`/f`) is a quote-delimited, newline-separated `[Files]` list with NO escape
|
|
44
|
+
* mechanism. A path component containing a double-quote or CR/LF would corrupt the format or inject an
|
|
45
|
+
* extra mapping entry (remapping/shadowing files in the produced package), so such paths are rejected.
|
|
46
|
+
*/
|
|
47
|
+
export declare function assertSafeMappingPath(value: string, kind: string): void;
|
|
48
|
+
/**
|
|
49
|
+
* Builds the `[Files]` mapping lines for the packaged app payload (`"<vm source>" "app\<rel>"`), shared
|
|
50
|
+
* by the AppX and MSIX targets. Each relative path is validated via {@link assertSafeMappingPath}.
|
|
51
|
+
*/
|
|
52
|
+
export declare function buildAppFileMappings(vm: VmManager, appOutDir: string): Promise<Array<string>>;
|
|
53
|
+
export declare function validateApplicationId(result: string, contextLabel: string): void;
|
|
54
|
+
export declare function validateIdentityName(result: string, contextLabel: string): void;
|
|
55
|
+
export declare function resourceLanguageTag(userLanguages: Array<string> | Nullish): string;
|
|
56
|
+
export declare function lockScreenTag(userAssets: Array<string>): string;
|
|
57
|
+
export declare function defaultTileTag(userAssets: Array<string>, showNameOnTiles: boolean): string;
|
|
58
|
+
export declare function splashScreenTag(userAssets: Array<string>): string;
|
|
59
|
+
export declare function isDefaultAssetIncluded(userAssets: Array<string>, defaultAsset: string): boolean;
|
|
60
|
+
export declare function isScaledAssetsProvided(userAssets: Array<string>): boolean;
|
|
61
|
+
/**
|
|
62
|
+
* Resolves the final applicationId value from config, stripping any leading numeric prefix
|
|
63
|
+
* from identityName (a common user mistake), then validates it.
|
|
64
|
+
*/
|
|
65
|
+
export declare function resolvePackageApplicationId(applicationId: string | undefined, identityName: string | null | undefined, appName: string, contextLabel: string): string;
|
|
66
|
+
export declare function resolvePackageIdentityName(identityName: string | null | undefined, appName: string, contextLabel: string): string;
|
|
67
|
+
export declare function buildCapabilitiesXml(capabilityNames: Array<string> | null | undefined): string;
|
|
68
|
+
export interface ExtensionsInput {
|
|
69
|
+
protocols: Array<Protocol>;
|
|
70
|
+
fileAssociations: Array<FileAssociation>;
|
|
71
|
+
addAutoLaunchExtension?: boolean;
|
|
72
|
+
customExtensionsPath?: string;
|
|
73
|
+
appDir: string;
|
|
74
|
+
executable: string;
|
|
75
|
+
displayName: string;
|
|
76
|
+
dependencyNames?: Record<string, string> | null;
|
|
77
|
+
}
|
|
78
|
+
export declare function buildExtensionsXml(input: ExtensionsInput): Promise<string>;
|
|
79
|
+
export declare function buildWindowsServicesXml(services: ReadonlyArray<MsixWindowsService> | undefined, defaultExecutable: string): string;
|
|
80
|
+
/** Options shared by the AppX and MSIX targets that the build pipeline reads directly. */
|
|
81
|
+
export interface AppxPackageBuildOptions extends TargetSpecificOptions {
|
|
82
|
+
readonly publisher?: string | null;
|
|
83
|
+
readonly makeappxArgs?: Array<string> | null;
|
|
84
|
+
readonly electronUpdaterAware?: boolean;
|
|
85
|
+
}
|
|
86
|
+
export interface AppxBuildContext {
|
|
87
|
+
readonly arch: Arch;
|
|
88
|
+
readonly artifactPath: string;
|
|
89
|
+
readonly vendorPathKit: string;
|
|
90
|
+
readonly vm: VmManager;
|
|
91
|
+
}
|
|
92
|
+
export interface AppxPackageBuildConfig {
|
|
93
|
+
/** `"appx"` | `"msix"` — drives artifact naming, the safe-artifact name, and the debug-log key. */
|
|
94
|
+
readonly kind: "appx" | "msix";
|
|
95
|
+
/** Human-facing target name for build-progress events (`"AppX"` | `"MSIX"`). */
|
|
96
|
+
readonly presentableName: string;
|
|
97
|
+
/** Writes the target-specific `AppxManifest.xml` (AppX and MSIX use different templates/macros). */
|
|
98
|
+
writeManifest(manifestFile: string, arch: Arch, publisher: string, userAssets: Array<string>): Promise<void>;
|
|
99
|
+
/** Optional pre-flight validation (e.g. the MSIX legacy-toolset guard); a throw aborts the build. */
|
|
100
|
+
preflight?(): void | Promise<void>;
|
|
101
|
+
/**
|
|
102
|
+
* Optional hook invoked synchronously (before the deferred pack task is queued) with the build
|
|
103
|
+
* context. MSIX uses it to record the per-arch artifact + VM/kit paths so `finishBuild` can assemble
|
|
104
|
+
* the `.msixbundle` / `.msixupload`.
|
|
105
|
+
*/
|
|
106
|
+
onBuilt?(ctx: AppxBuildContext): void;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Shared build pipeline for the AppX and MSIX targets — both pack via the Windows Kits `makeappx.exe`
|
|
110
|
+
* and differ only in the bits supplied through {@link AppxPackageBuildConfig}. It walks the app payload
|
|
111
|
+
* and assets into a `makeappx` mapping file, generates `resources.pri` when scaled assets are present,
|
|
112
|
+
* writes the manifest, then packs + signs the artifact on the target's build queue.
|
|
113
|
+
*/
|
|
114
|
+
export declare function buildAppxPackage(target: Target, packager: WinPackager, options: AppxPackageBuildOptions, appOutDir: string, arch: Arch, config: AppxPackageBuildConfig): Promise<void>;
|
|
115
|
+
//# sourceMappingURL=winAppUtil.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"winAppUtil.d.ts","sourceRoot":"","sources":["../../../src/targets/win/winAppUtil.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
import { asArray, copyOrLinkFile, ensureNotBusy, escapeForXml, InvalidConfigurationError, log, sanitizeDirPath, walk } from "builder-util";
|
|
2
|
+
import _fsExtra from "fs-extra";
|
|
3
|
+
const { emptyDir, readdir, readFile, writeFile } = _fsExtra;
|
|
4
|
+
import * as path from "path";
|
|
5
|
+
import { getWindowsKitsBundle } from "../../toolsets/winCodeSign.js";
|
|
6
|
+
import { getTemplatePath } from "../../util/pathManager.js";
|
|
7
|
+
import { createStageDir } from "../targetUtil.js";
|
|
8
|
+
import { CAPABILITIES, isValidCapabilityName } from "./AppxCapabilities.js";
|
|
9
|
+
export const APPX_ASSETS_DIR_NAME = "appx";
|
|
10
|
+
/**
|
|
11
|
+
* Escapes a string for safe use as an XML attribute value (double- or single-quoted) or element text.
|
|
12
|
+
* Aliased to builder-util's {@link escapeForXml} so the Appx/MSIX manifest path shares the single
|
|
13
|
+
* consolidated escaper (PR #9853) and cannot drift from it.
|
|
14
|
+
*/
|
|
15
|
+
export const escapeXmlAttr = escapeForXml;
|
|
16
|
+
/**
|
|
17
|
+
* Manifest macros whose substituted values are raw user/config text and therefore must be
|
|
18
|
+
* XML-escaped before being placed into the (Appx/MSIX) manifest. Every other macro either
|
|
19
|
+
* returns a prebuilt XML fragment (capabilities, extensions, lockScreen, defaultTile,
|
|
20
|
+
* splashScreen, resourceLanguages, packageIntegrity) or a validated/constant value
|
|
21
|
+
* (version, applicationId, identityName, arch, logo, square*Logo) and must NOT be escaped.
|
|
22
|
+
*
|
|
23
|
+
* Note: `publisher` is emitted inside a single-quoted attribute (`Publisher='...'`). escapeForXml
|
|
24
|
+
* escapes `& < > " '` — apostrophes become `'`, which is valid inside the single-quoted
|
|
25
|
+
* attribute, so a `'` in a certificate Subject is handled correctly.
|
|
26
|
+
*/
|
|
27
|
+
export const RAW_TEXT_MANIFEST_MACROS = new Set([
|
|
28
|
+
"publisher",
|
|
29
|
+
"publisherDisplayName",
|
|
30
|
+
"executable",
|
|
31
|
+
"displayName",
|
|
32
|
+
"description",
|
|
33
|
+
"backgroundColor",
|
|
34
|
+
"minVersion",
|
|
35
|
+
"maxVersionTested",
|
|
36
|
+
]);
|
|
37
|
+
/**
|
|
38
|
+
* Substitutes `${macro}` placeholders in an Appx/MSIX manifest template. `resolve` returns the
|
|
39
|
+
* RAW value for a macro; values for macros in {@link RAW_TEXT_MANIFEST_MACROS} are XML-escaped
|
|
40
|
+
* here so individual call sites cannot forget to. `resolve` may throw for unknown macros.
|
|
41
|
+
*/
|
|
42
|
+
export function substituteManifestMacros(template, resolve) {
|
|
43
|
+
return template.replace(/\${([a-zA-Z0-9]+)}/g, (_match, macro) => {
|
|
44
|
+
const value = resolve(macro);
|
|
45
|
+
return RAW_TEXT_MANIFEST_MACROS.has(macro) ? escapeXmlAttr(value) : value;
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
export const DEFAULT_RESOURCE_LANG = "en-US";
|
|
49
|
+
export const vendorAssetsForDefaultAssets = {
|
|
50
|
+
"StoreLogo.png": "SampleAppx.50x50.png",
|
|
51
|
+
"Square150x150Logo.png": "SampleAppx.150x150.png",
|
|
52
|
+
"Square44x44Logo.png": "SampleAppx.44x44.png",
|
|
53
|
+
"Wide310x150Logo.png": "SampleAppx.310x150.png",
|
|
54
|
+
};
|
|
55
|
+
export const restrictedApplicationIdValues = [
|
|
56
|
+
"CON",
|
|
57
|
+
"PRN",
|
|
58
|
+
"AUX",
|
|
59
|
+
"NUL",
|
|
60
|
+
"COM1",
|
|
61
|
+
"COM2",
|
|
62
|
+
"COM3",
|
|
63
|
+
"COM4",
|
|
64
|
+
"COM5",
|
|
65
|
+
"COM6",
|
|
66
|
+
"COM7",
|
|
67
|
+
"COM8",
|
|
68
|
+
"COM9",
|
|
69
|
+
"LPT1",
|
|
70
|
+
"LPT2",
|
|
71
|
+
"LPT3",
|
|
72
|
+
"LPT4",
|
|
73
|
+
"LPT5",
|
|
74
|
+
"LPT6",
|
|
75
|
+
"LPT7",
|
|
76
|
+
"LPT8",
|
|
77
|
+
"LPT9",
|
|
78
|
+
];
|
|
79
|
+
export async function computeUserAssets(vm, vendorPath, userAssetDir) {
|
|
80
|
+
const mappings = [];
|
|
81
|
+
let userAssets;
|
|
82
|
+
const allAssets = [];
|
|
83
|
+
if (userAssetDir == null) {
|
|
84
|
+
userAssets = [];
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
userAssets = (await readdir(userAssetDir)).filter(it => !it.startsWith(".") && !it.endsWith(".db") && it.includes("."));
|
|
88
|
+
for (const name of userAssets) {
|
|
89
|
+
// The makeappx mapping file is quote-delimited with no escape mechanism; reject names that would corrupt it / inject extra entries.
|
|
90
|
+
assertSafeMappingPath(name, "Asset file name");
|
|
91
|
+
mappings.push(`"${vm.toVmFile(userAssetDir)}${vm.pathSep}${name}" "assets\\${name}"`);
|
|
92
|
+
allAssets.push(path.join(userAssetDir, name));
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
for (const defaultAsset of Object.keys(vendorAssetsForDefaultAssets)) {
|
|
96
|
+
if (userAssets.length === 0 || !isDefaultAssetIncluded(userAssets, defaultAsset)) {
|
|
97
|
+
// codeql[js/shell-command-constructed-from-input] - vendorPath is a trusted toolset bundle dir and the asset name is a hardcoded constant; the joined path is resolved and contained under vendorPath via sanitizeDirPath, and only reaches makeappx as an execFile argv element (array args, no shell)
|
|
98
|
+
const file = sanitizeDirPath(path.join(vendorPath, "appxAssets", vendorAssetsForDefaultAssets[defaultAsset]), vendorPath);
|
|
99
|
+
mappings.push(`"${vm.toVmFile(file)}" "assets\\${defaultAsset}"`);
|
|
100
|
+
allAssets.push(file);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return { userAssets, mappings, allAssets };
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* The makeappx mapping file (`/f`) is a quote-delimited, newline-separated `[Files]` list with NO escape
|
|
107
|
+
* mechanism. A path component containing a double-quote or CR/LF would corrupt the format or inject an
|
|
108
|
+
* extra mapping entry (remapping/shadowing files in the produced package), so such paths are rejected.
|
|
109
|
+
*/
|
|
110
|
+
export function assertSafeMappingPath(value, kind) {
|
|
111
|
+
if (/["\r\n]/.test(value)) {
|
|
112
|
+
throw new InvalidConfigurationError(`${kind} cannot contain a double-quote or newline — the makeappx mapping file cannot represent it: ${JSON.stringify(value)}`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Builds the `[Files]` mapping lines for the packaged app payload (`"<vm source>" "app\<rel>"`), shared
|
|
117
|
+
* by the AppX and MSIX targets. Each relative path is validated via {@link assertSafeMappingPath}.
|
|
118
|
+
*/
|
|
119
|
+
export async function buildAppFileMappings(vm, appOutDir) {
|
|
120
|
+
return Promise.all((await walk(appOutDir)).map(file => {
|
|
121
|
+
let relPath = file.substring(appOutDir.length + 1);
|
|
122
|
+
if (path.sep !== "\\") {
|
|
123
|
+
relPath = relPath.replace(/\//g, "\\");
|
|
124
|
+
}
|
|
125
|
+
assertSafeMappingPath(relPath, "Packaged file path");
|
|
126
|
+
return `"${vm.toVmFile(file)}" "app\\${relPath}"`;
|
|
127
|
+
}));
|
|
128
|
+
}
|
|
129
|
+
export function validateApplicationId(result, contextLabel) {
|
|
130
|
+
const validCharactersRegex = /^([A-Za-z][A-Za-z0-9]*)(\.[A-Za-z][A-Za-z0-9]*)*$/;
|
|
131
|
+
if (result.length < 1 || result.length > 64) {
|
|
132
|
+
throw new InvalidConfigurationError(`${contextLabel} Application.Id must be between 1 and 64 characters in length: ${result}`);
|
|
133
|
+
}
|
|
134
|
+
if (!validCharactersRegex.test(result)) {
|
|
135
|
+
throw new InvalidConfigurationError(`${contextLabel} Application.Id must contain only alpha-numeric characters separated by periods, where each segment starts with an alphabetic character: ${result}`);
|
|
136
|
+
}
|
|
137
|
+
if (restrictedApplicationIdValues.includes(result.toUpperCase())) {
|
|
138
|
+
throw new InvalidConfigurationError(`${contextLabel} Application.Id cannot contain restricted values ${JSON.stringify(restrictedApplicationIdValues)}: ${result}`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
export function validateIdentityName(result, contextLabel) {
|
|
142
|
+
const validCharactersRegex = /^[a-zA-Z0-9.-]+$/;
|
|
143
|
+
if (result.length < 3 || result.length > 50) {
|
|
144
|
+
throw new InvalidConfigurationError(`${contextLabel} identityName must be between 3 and 50 characters in length: ${result}`);
|
|
145
|
+
}
|
|
146
|
+
if (!validCharactersRegex.test(result)) {
|
|
147
|
+
throw new InvalidConfigurationError(`${contextLabel} identityName must contain only alpha-numeric, period, and dash characters: ${result}`);
|
|
148
|
+
}
|
|
149
|
+
if (restrictedApplicationIdValues.includes(result.toUpperCase())) {
|
|
150
|
+
throw new InvalidConfigurationError(`${contextLabel} identityName cannot contain restricted values ${JSON.stringify(restrictedApplicationIdValues)}: ${result}`);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
export function resourceLanguageTag(userLanguages) {
|
|
154
|
+
if (userLanguages == null || userLanguages.length === 0) {
|
|
155
|
+
userLanguages = [DEFAULT_RESOURCE_LANG];
|
|
156
|
+
}
|
|
157
|
+
return userLanguages.map(it => `<Resource Language="${escapeXmlAttr(it.trim().replace(/_/g, "-"))}" />`).join("\n");
|
|
158
|
+
}
|
|
159
|
+
export function lockScreenTag(userAssets) {
|
|
160
|
+
if (isDefaultAssetIncluded(userAssets, "BadgeLogo.png")) {
|
|
161
|
+
return '<uap:LockScreen Notification="badgeAndTileText" BadgeLogo="assets\\BadgeLogo.png" />';
|
|
162
|
+
}
|
|
163
|
+
return "";
|
|
164
|
+
}
|
|
165
|
+
export function defaultTileTag(userAssets, showNameOnTiles) {
|
|
166
|
+
const defaultTiles = ["<uap:DefaultTile", 'Wide310x150Logo="assets\\Wide310x150Logo.png"'];
|
|
167
|
+
if (isDefaultAssetIncluded(userAssets, "LargeTile.png")) {
|
|
168
|
+
defaultTiles.push('Square310x310Logo="assets\\LargeTile.png"');
|
|
169
|
+
}
|
|
170
|
+
if (isDefaultAssetIncluded(userAssets, "SmallTile.png")) {
|
|
171
|
+
defaultTiles.push('Square71x71Logo="assets\\SmallTile.png"');
|
|
172
|
+
}
|
|
173
|
+
if (showNameOnTiles) {
|
|
174
|
+
defaultTiles.push(">");
|
|
175
|
+
defaultTiles.push("<uap:ShowNameOnTiles>");
|
|
176
|
+
defaultTiles.push("<uap:ShowOn", 'Tile="wide310x150Logo"', "/>");
|
|
177
|
+
defaultTiles.push("<uap:ShowOn", 'Tile="square150x150Logo"', "/>");
|
|
178
|
+
defaultTiles.push("</uap:ShowNameOnTiles>");
|
|
179
|
+
defaultTiles.push("</uap:DefaultTile>");
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
defaultTiles.push("/>");
|
|
183
|
+
}
|
|
184
|
+
return defaultTiles.join(" ");
|
|
185
|
+
}
|
|
186
|
+
export function splashScreenTag(userAssets) {
|
|
187
|
+
if (isDefaultAssetIncluded(userAssets, "SplashScreen.png")) {
|
|
188
|
+
return '<uap:SplashScreen Image="assets\\SplashScreen.png" />';
|
|
189
|
+
}
|
|
190
|
+
return "";
|
|
191
|
+
}
|
|
192
|
+
export function isDefaultAssetIncluded(userAssets, defaultAsset) {
|
|
193
|
+
const defaultAssetName = defaultAsset.substring(0, defaultAsset.indexOf("."));
|
|
194
|
+
return userAssets.some(it => it.includes(defaultAssetName));
|
|
195
|
+
}
|
|
196
|
+
export function isScaledAssetsProvided(userAssets) {
|
|
197
|
+
return userAssets.some(it => it.includes(".scale-") || it.includes(".targetsize-"));
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Resolves the final applicationId value from config, stripping any leading numeric prefix
|
|
201
|
+
* from identityName (a common user mistake), then validates it.
|
|
202
|
+
*/
|
|
203
|
+
export function resolvePackageApplicationId(applicationId, identityName, appName, contextLabel) {
|
|
204
|
+
let result;
|
|
205
|
+
const identitynumber = parseInt(identityName, 10) || NaN;
|
|
206
|
+
if (applicationId) {
|
|
207
|
+
result = applicationId;
|
|
208
|
+
validateApplicationId(result, contextLabel);
|
|
209
|
+
return result;
|
|
210
|
+
}
|
|
211
|
+
if (!isNaN(identitynumber) && identityName !== null && identityName !== undefined) {
|
|
212
|
+
if (identityName[0] === "0") {
|
|
213
|
+
log.warn(`Remove the 0${identitynumber}`);
|
|
214
|
+
result = identityName.replace("0" + identitynumber.toString(), "");
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
log.warn(`Remove the ${identitynumber}`);
|
|
218
|
+
result = identityName.replace(identitynumber.toString(), "");
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
222
|
+
result = identityName || appName;
|
|
223
|
+
}
|
|
224
|
+
// `result` is a derived value (from identityName or the app name). identityName allows characters
|
|
225
|
+
// (e.g. a dash) that are invalid in an Application.Id, so surface an actionable error rather than
|
|
226
|
+
// the raw low-level validation message when the derivation cannot produce a valid id.
|
|
227
|
+
try {
|
|
228
|
+
validateApplicationId(result, contextLabel);
|
|
229
|
+
}
|
|
230
|
+
catch (e) {
|
|
231
|
+
throw new InvalidConfigurationError(`${contextLabel} could not derive a valid Application.Id ("${result}") from identityName/name — Application.Id allows only alpha-numeric segments separated by periods (no dashes). Set the "applicationId" option explicitly. Cause: ${e.message}`);
|
|
232
|
+
}
|
|
233
|
+
return result;
|
|
234
|
+
}
|
|
235
|
+
export function resolvePackageIdentityName(identityName, appName, contextLabel) {
|
|
236
|
+
const result = identityName || appName;
|
|
237
|
+
validateIdentityName(result, contextLabel);
|
|
238
|
+
return result;
|
|
239
|
+
}
|
|
240
|
+
export function buildCapabilitiesXml(capabilityNames) {
|
|
241
|
+
const caps = asArray(capabilityNames);
|
|
242
|
+
const capSet = new Set(caps);
|
|
243
|
+
const invalid = Array.from(capSet).filter(cap => !isValidCapabilityName(cap));
|
|
244
|
+
if (invalid.length > 0) {
|
|
245
|
+
throw new Error(`invalid windows capabilit${invalid.length === 1 ? "y" : "ies"} specified: ${invalid.join(", ")}`);
|
|
246
|
+
}
|
|
247
|
+
capSet.add("runFullTrust");
|
|
248
|
+
const capabilityStrings = CAPABILITIES.filter(cap => capSet.has(cap.name)).map(cap => ` ${cap.toXMLString()}`);
|
|
249
|
+
return capabilityStrings.join("\n");
|
|
250
|
+
}
|
|
251
|
+
export async function buildExtensionsXml(input) {
|
|
252
|
+
const { protocols, fileAssociations, appDir, executable, displayName, customExtensionsPath } = input;
|
|
253
|
+
let isAddAutoLaunch = input.addAutoLaunchExtension;
|
|
254
|
+
if (isAddAutoLaunch === undefined) {
|
|
255
|
+
isAddAutoLaunch = input.dependencyNames != null && input.dependencyNames["electron-winstore-auto-launch"] != null;
|
|
256
|
+
}
|
|
257
|
+
if (!isAddAutoLaunch && protocols.length === 0 && fileAssociations.length === 0 && customExtensionsPath === undefined) {
|
|
258
|
+
return "";
|
|
259
|
+
}
|
|
260
|
+
let extensions = "<Extensions>";
|
|
261
|
+
if (isAddAutoLaunch) {
|
|
262
|
+
extensions += `
|
|
263
|
+
<desktop:Extension Category="windows.startupTask" Executable="${escapeXmlAttr(executable)}" EntryPoint="Windows.FullTrustApplication">
|
|
264
|
+
<desktop:StartupTask TaskId="SlackStartup" Enabled="true" DisplayName="${escapeXmlAttr(displayName)}" />
|
|
265
|
+
</desktop:Extension>`;
|
|
266
|
+
}
|
|
267
|
+
for (const protocol of protocols) {
|
|
268
|
+
for (const scheme of asArray(protocol.schemes)) {
|
|
269
|
+
extensions += `
|
|
270
|
+
<uap:Extension Category="windows.protocol">
|
|
271
|
+
<uap:Protocol Name="${escapeXmlAttr(scheme)}">
|
|
272
|
+
<uap:DisplayName>${escapeXmlAttr(protocol.name)}</uap:DisplayName>
|
|
273
|
+
</uap:Protocol>
|
|
274
|
+
</uap:Extension>`;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
for (const fileAssociation of fileAssociations) {
|
|
278
|
+
for (const ext of asArray(fileAssociation.ext)) {
|
|
279
|
+
const extEsc = escapeXmlAttr(ext);
|
|
280
|
+
extensions += `
|
|
281
|
+
<uap:Extension Category="windows.fileTypeAssociation">
|
|
282
|
+
<uap:FileTypeAssociation Name="${extEsc}">
|
|
283
|
+
<uap:SupportedFileTypes>
|
|
284
|
+
<uap:FileType>.${extEsc}</uap:FileType>
|
|
285
|
+
</uap:SupportedFileTypes>
|
|
286
|
+
</uap:FileTypeAssociation>
|
|
287
|
+
</uap:Extension>`;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
if (customExtensionsPath !== undefined) {
|
|
291
|
+
const extensionsPath = path.resolve(appDir, customExtensionsPath);
|
|
292
|
+
extensions += await readFile(extensionsPath, "utf8");
|
|
293
|
+
}
|
|
294
|
+
extensions += "</Extensions>";
|
|
295
|
+
return extensions;
|
|
296
|
+
}
|
|
297
|
+
export function buildWindowsServicesXml(services, defaultExecutable) {
|
|
298
|
+
if (!services || services.length === 0) {
|
|
299
|
+
return "";
|
|
300
|
+
}
|
|
301
|
+
return services
|
|
302
|
+
.map(svc => {
|
|
303
|
+
const exe = escapeXmlAttr(svc.executable || defaultExecutable);
|
|
304
|
+
// desktop6:Service requires both StartupType ("auto" | "manual" | "disabled") and StartAccount
|
|
305
|
+
// ("localSystem" | "localService" | "networkService"). Omitting StartAccount produces a manifest
|
|
306
|
+
// makeappx rejects. See https://learn.microsoft.com/uwp/schemas/appxpackage/uapmanifestschema/element-desktop6-service
|
|
307
|
+
const startupType = escapeXmlAttr(svc.startupType ?? "manual");
|
|
308
|
+
const startAccount = escapeXmlAttr(svc.startAccount ?? "localSystem");
|
|
309
|
+
const argsAttr = svc.arguments != null ? ` Arguments="${escapeXmlAttr(svc.arguments)}"` : "";
|
|
310
|
+
return `
|
|
311
|
+
<desktop6:Extension Category="windows.service" Executable="${exe}" EntryPoint="Windows.FullTrustApplication">
|
|
312
|
+
<desktop6:Service Name="${escapeXmlAttr(svc.name)}" StartupType="${startupType}" StartAccount="${startAccount}"${argsAttr} />
|
|
313
|
+
</desktop6:Extension>`;
|
|
314
|
+
})
|
|
315
|
+
.join("");
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Shared build pipeline for the AppX and MSIX targets — both pack via the Windows Kits `makeappx.exe`
|
|
319
|
+
* and differ only in the bits supplied through {@link AppxPackageBuildConfig}. It walks the app payload
|
|
320
|
+
* and assets into a `makeappx` mapping file, generates `resources.pri` when scaled assets are present,
|
|
321
|
+
* writes the manifest, then packs + signs the artifact on the target's build queue.
|
|
322
|
+
*/
|
|
323
|
+
export async function buildAppxPackage(target, packager, options, appOutDir, arch, config) {
|
|
324
|
+
await config.preflight?.();
|
|
325
|
+
const artifactName = packager.expandArtifactBeautyNamePattern(options, config.kind, arch);
|
|
326
|
+
const artifactPath = path.join(target.outDir, artifactName);
|
|
327
|
+
await packager.emitArtifactBuildStarted({ targetPresentableName: config.presentableName, file: artifactPath, arch });
|
|
328
|
+
const vendorPath = await getWindowsKitsBundle({ winCodeSign: packager.config.toolsets?.winCodeSign, resourcesDir: packager.buildResourcesDir });
|
|
329
|
+
const vm = await packager.vm.value;
|
|
330
|
+
config.onBuilt?.({ arch, artifactPath, vendorPathKit: vendorPath.kit, vm });
|
|
331
|
+
const stageDir = await createStageDir(target, packager, arch);
|
|
332
|
+
const mappingFile = stageDir.getTempFile("mapping.txt");
|
|
333
|
+
const makeAppXArgs = ["pack", "/o" /* overwrite the output file if it exists */, "/f", vm.toVmFile(mappingFile), "/p", vm.toVmFile(artifactPath)];
|
|
334
|
+
if (packager.compression === "store") {
|
|
335
|
+
makeAppXArgs.push("/nc");
|
|
336
|
+
}
|
|
337
|
+
const mappingList = [];
|
|
338
|
+
mappingList.push(await buildAppFileMappings(vm, appOutDir));
|
|
339
|
+
const userAssetDir = await packager.getResource(undefined, APPX_ASSETS_DIR_NAME);
|
|
340
|
+
const assetInfo = await computeUserAssets(vm, vendorPath.appxAssets, userAssetDir);
|
|
341
|
+
const userAssets = assetInfo.userAssets;
|
|
342
|
+
const manifestFile = stageDir.getTempFile("AppxManifest.xml");
|
|
343
|
+
// https://github.com/electron-userland/electron-builder/issues/2108#issuecomment-333200711
|
|
344
|
+
const publisher = await (await packager.signingManager.value).computePublisherName(target, options.publisher ?? null);
|
|
345
|
+
await config.writeManifest(manifestFile, arch, publisher, userAssets);
|
|
346
|
+
await packager.emitAppxManifestCreated(manifestFile);
|
|
347
|
+
mappingList.push(assetInfo.mappings);
|
|
348
|
+
mappingList.push([`"${vm.toVmFile(manifestFile)}" "AppxManifest.xml"`]);
|
|
349
|
+
if (isScaledAssetsProvided(userAssets)) {
|
|
350
|
+
const outFile = vm.toVmFile(stageDir.getTempFile("resources.pri"));
|
|
351
|
+
const makePriExe = path.join(vendorPath.kit, "makepri.exe");
|
|
352
|
+
const makePriPath = vm.toVmFile(makePriExe);
|
|
353
|
+
const assetRoot = stageDir.getTempFile("appx/assets");
|
|
354
|
+
await emptyDir(assetRoot);
|
|
355
|
+
await Promise.all(assetInfo.allAssets.map(it => copyOrLinkFile(it, path.join(assetRoot, path.basename(it)))));
|
|
356
|
+
// Wait out any transient AV/share lock on the freshly-extracted kit binary (see ensureNotBusy).
|
|
357
|
+
await ensureNotBusy(makePriExe);
|
|
358
|
+
await vm.exec(makePriPath, [
|
|
359
|
+
"new",
|
|
360
|
+
"/Overwrite",
|
|
361
|
+
"/Manifest",
|
|
362
|
+
vm.toVmFile(manifestFile),
|
|
363
|
+
"/ProjectRoot",
|
|
364
|
+
vm.toVmFile(path.dirname(assetRoot)),
|
|
365
|
+
"/ConfigXml",
|
|
366
|
+
vm.toVmFile(path.join(getTemplatePath("appx"), "priconfig.xml")),
|
|
367
|
+
"/OutputFile",
|
|
368
|
+
outFile,
|
|
369
|
+
]);
|
|
370
|
+
// in addition to resources.pri, resources.scale-140.pri and other such files will be generated
|
|
371
|
+
for (const resourceFile of (await readdir(stageDir.dir)).filter(it => it.startsWith("resources.")).sort()) {
|
|
372
|
+
mappingList.push([`"${vm.toVmFile(stageDir.getTempFile(resourceFile))}" "${resourceFile}"`]);
|
|
373
|
+
}
|
|
374
|
+
makeAppXArgs.push("/l");
|
|
375
|
+
}
|
|
376
|
+
let mapping = "[Files]";
|
|
377
|
+
for (const list of mappingList) {
|
|
378
|
+
mapping += "\r\n" + list.join("\r\n");
|
|
379
|
+
}
|
|
380
|
+
await writeFile(mappingFile, mapping);
|
|
381
|
+
packager.debugLogger.add(`${config.kind}.mapping`, mapping);
|
|
382
|
+
if (options.makeappxArgs != null) {
|
|
383
|
+
makeAppXArgs.push(...options.makeappxArgs);
|
|
384
|
+
}
|
|
385
|
+
target.buildQueueManager.add(async () => {
|
|
386
|
+
try {
|
|
387
|
+
const makeAppxExe = path.join(vendorPath.kit, "makeappx.exe");
|
|
388
|
+
// The kit binary is often freshly extracted to a cold cache; on Windows an AV scanner can briefly
|
|
389
|
+
// hold a deny-write lock long enough that spawning fails with `spawn UNKNOWN`. Wait for it to clear.
|
|
390
|
+
await ensureNotBusy(makeAppxExe);
|
|
391
|
+
await vm.exec(vm.toVmFile(makeAppxExe), makeAppXArgs);
|
|
392
|
+
await packager.signIf(artifactPath);
|
|
393
|
+
}
|
|
394
|
+
finally {
|
|
395
|
+
await stageDir.cleanup();
|
|
396
|
+
}
|
|
397
|
+
await packager.emitArtifactBuildCompleted({
|
|
398
|
+
file: artifactPath,
|
|
399
|
+
packager,
|
|
400
|
+
arch,
|
|
401
|
+
safeArtifactName: packager.computeSafeArtifactName(artifactName, config.kind),
|
|
402
|
+
target,
|
|
403
|
+
isWriteUpdateInfo: options.electronUpdaterAware,
|
|
404
|
+
});
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
//# sourceMappingURL=winAppUtil.js.map
|