app-builder-lib 27.0.0-alpha.5 → 27.0.0-alpha.7

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.
Files changed (154) hide show
  1. package/dist/appInfo.d.ts +1 -1
  2. package/dist/appInfo.d.ts.map +1 -1
  3. package/dist/appInfo.js +3 -3
  4. package/dist/appInfo.js.map +1 -1
  5. package/dist/codeSign/win/signtoolBaseSignManager.d.ts +23 -0
  6. package/dist/codeSign/win/signtoolBaseSignManager.d.ts.map +1 -1
  7. package/dist/codeSign/win/signtoolBaseSignManager.js +75 -3
  8. package/dist/codeSign/win/signtoolBaseSignManager.js.map +1 -1
  9. package/dist/configuration.d.ts +89 -5
  10. package/dist/configuration.d.ts.map +1 -1
  11. package/dist/configuration.js +11 -1
  12. package/dist/configuration.js.map +1 -1
  13. package/dist/electron/ElectronFramework.d.ts +2 -1
  14. package/dist/electron/ElectronFramework.d.ts.map +1 -1
  15. package/dist/electron/ElectronFramework.js +30 -26
  16. package/dist/electron/ElectronFramework.js.map +1 -1
  17. package/dist/electron/electronArchSupport.d.ts +12 -0
  18. package/dist/electron/electronArchSupport.d.ts.map +1 -0
  19. package/dist/electron/electronArchSupport.js +58 -0
  20. package/dist/electron/electronArchSupport.js.map +1 -0
  21. package/dist/electron/mac/electronMac.js +12 -21
  22. package/dist/electron/mac/electronMac.js.map +1 -1
  23. package/dist/electron/mac/electronMacUtils.d.ts +24 -0
  24. package/dist/electron/mac/electronMacUtils.d.ts.map +1 -0
  25. package/dist/electron/mac/electronMacUtils.js +42 -0
  26. package/dist/electron/mac/electronMacUtils.js.map +1 -0
  27. package/dist/fileMatcher.d.ts +15 -0
  28. package/dist/fileMatcher.d.ts.map +1 -1
  29. package/dist/fileMatcher.js +41 -2
  30. package/dist/fileMatcher.js.map +1 -1
  31. package/dist/index.d.ts +1 -0
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js.map +1 -1
  34. package/dist/indexInternal.d.ts +5 -2
  35. package/dist/indexInternal.d.ts.map +1 -1
  36. package/dist/indexInternal.js +5 -1
  37. package/dist/indexInternal.js.map +1 -1
  38. package/dist/macPackager.d.ts.map +1 -1
  39. package/dist/macPackager.js +17 -6
  40. package/dist/macPackager.js.map +1 -1
  41. package/dist/node-module-collector/moduleManager.d.ts +2 -1
  42. package/dist/node-module-collector/moduleManager.d.ts.map +1 -1
  43. package/dist/node-module-collector/moduleManager.js +2 -0
  44. package/dist/node-module-collector/moduleManager.js.map +1 -1
  45. package/dist/node-module-collector/nodeModulesCollector.d.ts +28 -2
  46. package/dist/node-module-collector/nodeModulesCollector.d.ts.map +1 -1
  47. package/dist/node-module-collector/nodeModulesCollector.js +95 -6
  48. package/dist/node-module-collector/nodeModulesCollector.js.map +1 -1
  49. package/dist/node-module-collector/pnpmNodeModulesCollector.d.ts.map +1 -1
  50. package/dist/node-module-collector/pnpmNodeModulesCollector.js +3 -1
  51. package/dist/node-module-collector/pnpmNodeModulesCollector.js.map +1 -1
  52. package/dist/node-module-collector/types.d.ts +2 -0
  53. package/dist/node-module-collector/types.d.ts.map +1 -1
  54. package/dist/node-module-collector/types.js.map +1 -1
  55. package/dist/options/MsixOptions.d.ts +126 -0
  56. package/dist/options/MsixOptions.d.ts.map +1 -0
  57. package/dist/options/MsixOptions.js +2 -0
  58. package/dist/options/MsixOptions.js.map +1 -0
  59. package/dist/options/SnapOptions.d.ts +8 -4
  60. package/dist/options/SnapOptions.d.ts.map +1 -1
  61. package/dist/options/SnapOptions.js.map +1 -1
  62. package/dist/options/macOptions.d.ts +21 -11
  63. package/dist/options/macOptions.d.ts.map +1 -1
  64. package/dist/options/macOptions.js.map +1 -1
  65. package/dist/options/winOptions.d.ts +7 -6
  66. package/dist/options/winOptions.d.ts.map +1 -1
  67. package/dist/options/winOptions.js.map +1 -1
  68. package/dist/packager.d.ts.map +1 -1
  69. package/dist/packager.js +8 -1
  70. package/dist/packager.js.map +1 -1
  71. package/dist/publish/PublishManager.d.ts.map +1 -1
  72. package/dist/publish/PublishManager.js +13 -4
  73. package/dist/publish/PublishManager.js.map +1 -1
  74. package/dist/publish/updateInfoBuilder.d.ts.map +1 -1
  75. package/dist/publish/updateInfoBuilder.js +23 -23
  76. package/dist/publish/updateInfoBuilder.js.map +1 -1
  77. package/dist/targets/archive.d.ts +11 -0
  78. package/dist/targets/archive.d.ts.map +1 -1
  79. package/dist/targets/archive.js +40 -22
  80. package/dist/targets/archive.js.map +1 -1
  81. package/dist/targets/linux/FlatpakTarget.d.ts.map +1 -1
  82. package/dist/targets/linux/FlatpakTarget.js +4 -1
  83. package/dist/targets/linux/FlatpakTarget.js.map +1 -1
  84. package/dist/targets/linux/FpmTarget.d.ts.map +1 -1
  85. package/dist/targets/linux/FpmTarget.js +9 -0
  86. package/dist/targets/linux/FpmTarget.js.map +1 -1
  87. package/dist/targets/linux/appimage/appImageUtil.d.ts +1 -1
  88. package/dist/targets/linux/appimage/appImageUtil.js +3 -3
  89. package/dist/targets/linux/appimage/appImageUtil.js.map +1 -1
  90. package/dist/targets/linux/snap/core24.d.ts +27 -0
  91. package/dist/targets/linux/snap/core24.d.ts.map +1 -1
  92. package/dist/targets/linux/snap/core24.js +92 -57
  93. package/dist/targets/linux/snap/core24.js.map +1 -1
  94. package/dist/targets/linux/snap/snapcraft.d.ts +190 -0
  95. package/dist/targets/linux/snap/snapcraft.d.ts.map +1 -0
  96. package/dist/targets/linux/snap/snapcraft.js +11 -0
  97. package/dist/targets/linux/snap/snapcraft.js.map +1 -0
  98. package/dist/targets/mac/MacTargetHelper.d.ts +18 -2
  99. package/dist/targets/mac/MacTargetHelper.d.ts.map +1 -1
  100. package/dist/targets/mac/MacTargetHelper.js +42 -12
  101. package/dist/targets/mac/MacTargetHelper.js.map +1 -1
  102. package/dist/targets/win/AppxTarget.d.ts +0 -2
  103. package/dist/targets/win/AppxTarget.d.ts.map +1 -1
  104. package/dist/targets/win/AppxTarget.js +37 -325
  105. package/dist/targets/win/AppxTarget.js.map +1 -1
  106. package/dist/targets/win/MsiTarget.js +2 -2
  107. package/dist/targets/win/MsiTarget.js.map +1 -1
  108. package/dist/targets/win/MsixTarget.d.ts +22 -0
  109. package/dist/targets/win/MsixTarget.d.ts.map +1 -0
  110. package/dist/targets/win/MsixTarget.js +214 -0
  111. package/dist/targets/win/MsixTarget.js.map +1 -0
  112. package/dist/targets/win/nsis/NsisTarget.d.ts.map +1 -1
  113. package/dist/targets/win/nsis/NsisTarget.js +5 -0
  114. package/dist/targets/win/nsis/NsisTarget.js.map +1 -1
  115. package/dist/targets/win/winAppUtil.d.ts +115 -0
  116. package/dist/targets/win/winAppUtil.d.ts.map +1 -0
  117. package/dist/targets/win/winAppUtil.js +407 -0
  118. package/dist/targets/win/winAppUtil.js.map +1 -0
  119. package/dist/toolsets/custom.js +4 -2
  120. package/dist/toolsets/custom.js.map +1 -1
  121. package/dist/toolsets/icons.d.ts.map +1 -1
  122. package/dist/toolsets/icons.js +4 -1
  123. package/dist/toolsets/icons.js.map +1 -1
  124. package/dist/toolsets/winCodeSign.d.ts +9 -0
  125. package/dist/toolsets/winCodeSign.d.ts.map +1 -1
  126. package/dist/toolsets/winCodeSign.js +11 -0
  127. package/dist/toolsets/winCodeSign.js.map +1 -1
  128. package/dist/util/appFileCopier.d.ts.map +1 -1
  129. package/dist/util/appFileCopier.js +85 -4
  130. package/dist/util/appFileCopier.js.map +1 -1
  131. package/dist/util/electronGet.d.ts +5 -0
  132. package/dist/util/electronGet.d.ts.map +1 -1
  133. package/dist/util/electronGet.js +124 -18
  134. package/dist/util/electronGet.js.map +1 -1
  135. package/dist/util/flags.d.ts +0 -1
  136. package/dist/util/flags.d.ts.map +1 -1
  137. package/dist/util/flags.js +0 -3
  138. package/dist/util/flags.js.map +1 -1
  139. package/dist/util/packageMetadata.js +46 -31
  140. package/dist/util/packageMetadata.js.map +1 -1
  141. package/dist/version.d.ts +1 -1
  142. package/dist/version.js +1 -1
  143. package/dist/version.js.map +1 -1
  144. package/dist/vm/ParallelsVm.d.ts.map +1 -1
  145. package/dist/vm/ParallelsVm.js +18 -5
  146. package/dist/vm/ParallelsVm.js.map +1 -1
  147. package/dist/winPackager.d.ts.map +1 -1
  148. package/dist/winPackager.js +3 -0
  149. package/dist/winPackager.js.map +1 -1
  150. package/package.json +8 -8
  151. package/scheme.json +498 -18
  152. package/templates/appx/appxmanifest.xml +1 -1
  153. package/templates/msix/appxmanifest.xml +45 -0
  154. package/templates/nsis/installSection.nsh +14 -0
@@ -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 `&apos;`, 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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"winAppUtil.js","sourceRoot":"","sources":["../../../src/targets/win/winAppUtil.ts"],"names":[],"mappings":"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","sourcesContent":["import { Arch, asArray, copyOrLinkFile, ensureNotBusy, escapeForXml, InvalidConfigurationError, log, sanitizeDirPath, walk } from \"builder-util\"\nimport type { MsixWindowsService } from \"../../options/MsixOptions.js\"\nimport { Nullish } from \"builder-util-runtime\"\nimport _fsExtra from \"fs-extra\"\nconst { emptyDir, readdir, readFile, writeFile } = _fsExtra\nimport * as path from \"path\"\nimport type { Target, TargetSpecificOptions } from \"../../core.js\"\nimport { FileAssociation } from \"../../options/FileAssociation.js\"\nimport { Protocol } from \"../../options/PlatformSpecificBuildOptions.js\"\nimport { getWindowsKitsBundle } from \"../../toolsets/winCodeSign.js\"\nimport { getTemplatePath } from \"../../util/pathManager.js\"\nimport { VmManager } from \"../../vm/vm.js\"\nimport type { WinPackager } from \"../../winPackager.js\"\nimport { createStageDir } from \"../targetUtil.js\"\nimport { CAPABILITIES, isValidCapabilityName } from \"./AppxCapabilities.js\"\n\nexport const APPX_ASSETS_DIR_NAME = \"appx\"\n\n/**\n * Escapes a string for safe use as an XML attribute value (double- or single-quoted) or element text.\n * Aliased to builder-util's {@link escapeForXml} so the Appx/MSIX manifest path shares the single\n * consolidated escaper (PR #9853) and cannot drift from it.\n */\nexport const escapeXmlAttr = escapeForXml\n\n/**\n * Manifest macros whose substituted values are raw user/config text and therefore must be\n * XML-escaped before being placed into the (Appx/MSIX) manifest. Every other macro either\n * returns a prebuilt XML fragment (capabilities, extensions, lockScreen, defaultTile,\n * splashScreen, resourceLanguages, packageIntegrity) or a validated/constant value\n * (version, applicationId, identityName, arch, logo, square*Logo) and must NOT be escaped.\n *\n * Note: `publisher` is emitted inside a single-quoted attribute (`Publisher='...'`). escapeForXml\n * escapes `& < > \" '` — apostrophes become `&apos;`, which is valid inside the single-quoted\n * attribute, so a `'` in a certificate Subject is handled correctly.\n */\nexport const RAW_TEXT_MANIFEST_MACROS: ReadonlySet<string> = new Set([\n \"publisher\",\n \"publisherDisplayName\",\n \"executable\",\n \"displayName\",\n \"description\",\n \"backgroundColor\",\n \"minVersion\",\n \"maxVersionTested\",\n])\n\n/**\n * Substitutes `${macro}` placeholders in an Appx/MSIX manifest template. `resolve` returns the\n * RAW value for a macro; values for macros in {@link RAW_TEXT_MANIFEST_MACROS} are XML-escaped\n * here so individual call sites cannot forget to. `resolve` may throw for unknown macros.\n */\nexport function substituteManifestMacros(template: string, resolve: (macro: string) => string): string {\n return template.replace(/\\${([a-zA-Z0-9]+)}/g, (_match, macro: string): string => {\n const value = resolve(macro)\n return RAW_TEXT_MANIFEST_MACROS.has(macro) ? escapeXmlAttr(value) : value\n })\n}\n\nexport const DEFAULT_RESOURCE_LANG = \"en-US\"\n\nexport const vendorAssetsForDefaultAssets: Record<string, string> = {\n \"StoreLogo.png\": \"SampleAppx.50x50.png\",\n \"Square150x150Logo.png\": \"SampleAppx.150x150.png\",\n \"Square44x44Logo.png\": \"SampleAppx.44x44.png\",\n \"Wide310x150Logo.png\": \"SampleAppx.310x150.png\",\n}\n\nexport const restrictedApplicationIdValues = [\n \"CON\",\n \"PRN\",\n \"AUX\",\n \"NUL\",\n \"COM1\",\n \"COM2\",\n \"COM3\",\n \"COM4\",\n \"COM5\",\n \"COM6\",\n \"COM7\",\n \"COM8\",\n \"COM9\",\n \"LPT1\",\n \"LPT2\",\n \"LPT3\",\n \"LPT4\",\n \"LPT5\",\n \"LPT6\",\n \"LPT7\",\n \"LPT8\",\n \"LPT9\",\n]\n\nexport async function computeUserAssets(vm: VmManager, vendorPath: string, userAssetDir: string | null) {\n const mappings: Array<string> = []\n let userAssets: Array<string>\n const allAssets: Array<string> = []\n if (userAssetDir == null) {\n userAssets = []\n } else {\n userAssets = (await readdir(userAssetDir)).filter(it => !it.startsWith(\".\") && !it.endsWith(\".db\") && it.includes(\".\"))\n for (const name of userAssets) {\n // The makeappx mapping file is quote-delimited with no escape mechanism; reject names that would corrupt it / inject extra entries.\n assertSafeMappingPath(name, \"Asset file name\")\n mappings.push(`\"${vm.toVmFile(userAssetDir)}${vm.pathSep}${name}\" \"assets\\\\${name}\"`)\n allAssets.push(path.join(userAssetDir, name))\n }\n }\n\n for (const defaultAsset of Object.keys(vendorAssetsForDefaultAssets)) {\n if (userAssets.length === 0 || !isDefaultAssetIncluded(userAssets, defaultAsset)) {\n // 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)\n const file = sanitizeDirPath(path.join(vendorPath, \"appxAssets\", vendorAssetsForDefaultAssets[defaultAsset]), vendorPath)\n mappings.push(`\"${vm.toVmFile(file)}\" \"assets\\\\${defaultAsset}\"`)\n allAssets.push(file)\n }\n }\n\n return { userAssets, mappings, allAssets }\n}\n\n/**\n * The makeappx mapping file (`/f`) is a quote-delimited, newline-separated `[Files]` list with NO escape\n * mechanism. A path component containing a double-quote or CR/LF would corrupt the format or inject an\n * extra mapping entry (remapping/shadowing files in the produced package), so such paths are rejected.\n */\nexport function assertSafeMappingPath(value: string, kind: string): void {\n if (/[\"\\r\\n]/.test(value)) {\n throw new InvalidConfigurationError(`${kind} cannot contain a double-quote or newline — the makeappx mapping file cannot represent it: ${JSON.stringify(value)}`)\n }\n}\n\n/**\n * Builds the `[Files]` mapping lines for the packaged app payload (`\"<vm source>\" \"app\\<rel>\"`), shared\n * by the AppX and MSIX targets. Each relative path is validated via {@link assertSafeMappingPath}.\n */\nexport async function buildAppFileMappings(vm: VmManager, appOutDir: string): Promise<Array<string>> {\n return Promise.all(\n (await walk(appOutDir)).map(file => {\n let relPath = file.substring(appOutDir.length + 1)\n if (path.sep !== \"\\\\\") {\n relPath = relPath.replace(/\\//g, \"\\\\\")\n }\n assertSafeMappingPath(relPath, \"Packaged file path\")\n return `\"${vm.toVmFile(file)}\" \"app\\\\${relPath}\"`\n })\n )\n}\n\nexport function validateApplicationId(result: string, contextLabel: string): void {\n const validCharactersRegex = /^([A-Za-z][A-Za-z0-9]*)(\\.[A-Za-z][A-Za-z0-9]*)*$/\n if (result.length < 1 || result.length > 64) {\n throw new InvalidConfigurationError(`${contextLabel} Application.Id must be between 1 and 64 characters in length: ${result}`)\n }\n if (!validCharactersRegex.test(result)) {\n throw new InvalidConfigurationError(\n `${contextLabel} Application.Id must contain only alpha-numeric characters separated by periods, where each segment starts with an alphabetic character: ${result}`\n )\n }\n if (restrictedApplicationIdValues.includes(result.toUpperCase())) {\n throw new InvalidConfigurationError(`${contextLabel} Application.Id cannot contain restricted values ${JSON.stringify(restrictedApplicationIdValues)}: ${result}`)\n }\n}\n\nexport function validateIdentityName(result: string, contextLabel: string): void {\n const validCharactersRegex = /^[a-zA-Z0-9.-]+$/\n if (result.length < 3 || result.length > 50) {\n throw new InvalidConfigurationError(`${contextLabel} identityName must be between 3 and 50 characters in length: ${result}`)\n }\n if (!validCharactersRegex.test(result)) {\n throw new InvalidConfigurationError(`${contextLabel} identityName must contain only alpha-numeric, period, and dash characters: ${result}`)\n }\n if (restrictedApplicationIdValues.includes(result.toUpperCase())) {\n throw new InvalidConfigurationError(`${contextLabel} identityName cannot contain restricted values ${JSON.stringify(restrictedApplicationIdValues)}: ${result}`)\n }\n}\n\nexport function resourceLanguageTag(userLanguages: Array<string> | Nullish): string {\n if (userLanguages == null || userLanguages.length === 0) {\n userLanguages = [DEFAULT_RESOURCE_LANG]\n }\n return userLanguages.map(it => `<Resource Language=\"${escapeXmlAttr(it.trim().replace(/_/g, \"-\"))}\" />`).join(\"\\n\")\n}\n\nexport function lockScreenTag(userAssets: Array<string>): string {\n if (isDefaultAssetIncluded(userAssets, \"BadgeLogo.png\")) {\n return '<uap:LockScreen Notification=\"badgeAndTileText\" BadgeLogo=\"assets\\\\BadgeLogo.png\" />'\n }\n return \"\"\n}\n\nexport function defaultTileTag(userAssets: Array<string>, showNameOnTiles: boolean): string {\n const defaultTiles: Array<string> = [\"<uap:DefaultTile\", 'Wide310x150Logo=\"assets\\\\Wide310x150Logo.png\"']\n\n if (isDefaultAssetIncluded(userAssets, \"LargeTile.png\")) {\n defaultTiles.push('Square310x310Logo=\"assets\\\\LargeTile.png\"')\n }\n if (isDefaultAssetIncluded(userAssets, \"SmallTile.png\")) {\n defaultTiles.push('Square71x71Logo=\"assets\\\\SmallTile.png\"')\n }\n\n if (showNameOnTiles) {\n defaultTiles.push(\">\")\n defaultTiles.push(\"<uap:ShowNameOnTiles>\")\n defaultTiles.push(\"<uap:ShowOn\", 'Tile=\"wide310x150Logo\"', \"/>\")\n defaultTiles.push(\"<uap:ShowOn\", 'Tile=\"square150x150Logo\"', \"/>\")\n defaultTiles.push(\"</uap:ShowNameOnTiles>\")\n defaultTiles.push(\"</uap:DefaultTile>\")\n } else {\n defaultTiles.push(\"/>\")\n }\n return defaultTiles.join(\" \")\n}\n\nexport function splashScreenTag(userAssets: Array<string>): string {\n if (isDefaultAssetIncluded(userAssets, \"SplashScreen.png\")) {\n return '<uap:SplashScreen Image=\"assets\\\\SplashScreen.png\" />'\n }\n return \"\"\n}\n\nexport function isDefaultAssetIncluded(userAssets: Array<string>, defaultAsset: string): boolean {\n const defaultAssetName = defaultAsset.substring(0, defaultAsset.indexOf(\".\"))\n return userAssets.some(it => it.includes(defaultAssetName))\n}\n\nexport function isScaledAssetsProvided(userAssets: Array<string>): boolean {\n return userAssets.some(it => it.includes(\".scale-\") || it.includes(\".targetsize-\"))\n}\n\n/**\n * Resolves the final applicationId value from config, stripping any leading numeric prefix\n * from identityName (a common user mistake), then validates it.\n */\nexport function resolvePackageApplicationId(applicationId: string | undefined, identityName: string | null | undefined, appName: string, contextLabel: string): string {\n let result: string\n const identitynumber = parseInt(identityName as string, 10) || NaN\n\n if (applicationId) {\n result = applicationId\n validateApplicationId(result, contextLabel)\n return result\n }\n\n if (!isNaN(identitynumber) && identityName !== null && identityName !== undefined) {\n if (identityName[0] === \"0\") {\n log.warn(`Remove the 0${identitynumber}`)\n result = identityName.replace(\"0\" + identitynumber.toString(), \"\")\n } else {\n log.warn(`Remove the ${identitynumber}`)\n result = identityName.replace(identitynumber.toString(), \"\")\n }\n } else {\n result = identityName || appName\n }\n\n // `result` is a derived value (from identityName or the app name). identityName allows characters\n // (e.g. a dash) that are invalid in an Application.Id, so surface an actionable error rather than\n // the raw low-level validation message when the derivation cannot produce a valid id.\n try {\n validateApplicationId(result, contextLabel)\n } catch (e) {\n throw new InvalidConfigurationError(\n `${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 as Error).message}`\n )\n }\n return result\n}\n\nexport function resolvePackageIdentityName(identityName: string | null | undefined, appName: string, contextLabel: string): string {\n const result = identityName || appName\n validateIdentityName(result, contextLabel)\n return result\n}\n\nexport function buildCapabilitiesXml(capabilityNames: Array<string> | null | undefined): string {\n const caps = asArray(capabilityNames)\n const capSet = new Set(caps)\n\n const invalid = Array.from(capSet).filter(cap => !isValidCapabilityName(cap))\n if (invalid.length > 0) {\n throw new Error(`invalid windows capabilit${invalid.length === 1 ? \"y\" : \"ies\"} specified: ${invalid.join(\", \")}`)\n }\n\n capSet.add(\"runFullTrust\")\n\n const capabilityStrings = CAPABILITIES.filter(cap => capSet.has(cap.name)).map(cap => ` ${cap.toXMLString()}`)\n return capabilityStrings.join(\"\\n\")\n}\n\nexport interface ExtensionsInput {\n protocols: Array<Protocol>\n fileAssociations: Array<FileAssociation>\n addAutoLaunchExtension?: boolean\n customExtensionsPath?: string\n appDir: string\n executable: string\n displayName: string\n dependencyNames?: Record<string, string> | null\n}\n\nexport async function buildExtensionsXml(input: ExtensionsInput): Promise<string> {\n const { protocols, fileAssociations, appDir, executable, displayName, customExtensionsPath } = input\n\n let isAddAutoLaunch = input.addAutoLaunchExtension\n if (isAddAutoLaunch === undefined) {\n isAddAutoLaunch = input.dependencyNames != null && input.dependencyNames[\"electron-winstore-auto-launch\"] != null\n }\n\n if (!isAddAutoLaunch && protocols.length === 0 && fileAssociations.length === 0 && customExtensionsPath === undefined) {\n return \"\"\n }\n\n let extensions = \"<Extensions>\"\n\n if (isAddAutoLaunch) {\n extensions += `\n <desktop:Extension Category=\"windows.startupTask\" Executable=\"${escapeXmlAttr(executable)}\" EntryPoint=\"Windows.FullTrustApplication\">\n <desktop:StartupTask TaskId=\"SlackStartup\" Enabled=\"true\" DisplayName=\"${escapeXmlAttr(displayName)}\" />\n </desktop:Extension>`\n }\n\n for (const protocol of protocols) {\n for (const scheme of asArray(protocol.schemes)) {\n extensions += `\n <uap:Extension Category=\"windows.protocol\">\n <uap:Protocol Name=\"${escapeXmlAttr(scheme)}\">\n <uap:DisplayName>${escapeXmlAttr(protocol.name)}</uap:DisplayName>\n </uap:Protocol>\n </uap:Extension>`\n }\n }\n\n for (const fileAssociation of fileAssociations) {\n for (const ext of asArray(fileAssociation.ext)) {\n const extEsc = escapeXmlAttr(ext)\n extensions += `\n <uap:Extension Category=\"windows.fileTypeAssociation\">\n <uap:FileTypeAssociation Name=\"${extEsc}\">\n <uap:SupportedFileTypes>\n <uap:FileType>.${extEsc}</uap:FileType>\n </uap:SupportedFileTypes>\n </uap:FileTypeAssociation>\n </uap:Extension>`\n }\n }\n\n if (customExtensionsPath !== undefined) {\n const extensionsPath = path.resolve(appDir, customExtensionsPath)\n extensions += await readFile(extensionsPath, \"utf8\")\n }\n\n extensions += \"</Extensions>\"\n return extensions\n}\n\nexport function buildWindowsServicesXml(services: ReadonlyArray<MsixWindowsService> | undefined, defaultExecutable: string): string {\n if (!services || services.length === 0) {\n return \"\"\n }\n return services\n .map(svc => {\n const exe = escapeXmlAttr(svc.executable || defaultExecutable)\n // desktop6:Service requires both StartupType (\"auto\" | \"manual\" | \"disabled\") and StartAccount\n // (\"localSystem\" | \"localService\" | \"networkService\"). Omitting StartAccount produces a manifest\n // makeappx rejects. See https://learn.microsoft.com/uwp/schemas/appxpackage/uapmanifestschema/element-desktop6-service\n const startupType = escapeXmlAttr(svc.startupType ?? \"manual\")\n const startAccount = escapeXmlAttr(svc.startAccount ?? \"localSystem\")\n const argsAttr = svc.arguments != null ? ` Arguments=\"${escapeXmlAttr(svc.arguments)}\"` : \"\"\n return `\n <desktop6:Extension Category=\"windows.service\" Executable=\"${exe}\" EntryPoint=\"Windows.FullTrustApplication\">\n <desktop6:Service Name=\"${escapeXmlAttr(svc.name)}\" StartupType=\"${startupType}\" StartAccount=\"${startAccount}\"${argsAttr} />\n </desktop6:Extension>`\n })\n .join(\"\")\n}\n\n/** Options shared by the AppX and MSIX targets that the build pipeline reads directly. */\nexport interface AppxPackageBuildOptions extends TargetSpecificOptions {\n readonly publisher?: string | null\n readonly makeappxArgs?: Array<string> | null\n readonly electronUpdaterAware?: boolean\n}\n\nexport interface AppxBuildContext {\n readonly arch: Arch\n readonly artifactPath: string\n readonly vendorPathKit: string\n readonly vm: VmManager\n}\n\nexport interface AppxPackageBuildConfig {\n /** `\"appx\"` | `\"msix\"` — drives artifact naming, the safe-artifact name, and the debug-log key. */\n readonly kind: \"appx\" | \"msix\"\n /** Human-facing target name for build-progress events (`\"AppX\"` | `\"MSIX\"`). */\n readonly presentableName: string\n /** Writes the target-specific `AppxManifest.xml` (AppX and MSIX use different templates/macros). */\n writeManifest(manifestFile: string, arch: Arch, publisher: string, userAssets: Array<string>): Promise<void>\n /** Optional pre-flight validation (e.g. the MSIX legacy-toolset guard); a throw aborts the build. */\n preflight?(): void | Promise<void>\n /**\n * Optional hook invoked synchronously (before the deferred pack task is queued) with the build\n * context. MSIX uses it to record the per-arch artifact + VM/kit paths so `finishBuild` can assemble\n * the `.msixbundle` / `.msixupload`.\n */\n onBuilt?(ctx: AppxBuildContext): void\n}\n\n/**\n * Shared build pipeline for the AppX and MSIX targets — both pack via the Windows Kits `makeappx.exe`\n * and differ only in the bits supplied through {@link AppxPackageBuildConfig}. It walks the app payload\n * and assets into a `makeappx` mapping file, generates `resources.pri` when scaled assets are present,\n * writes the manifest, then packs + signs the artifact on the target's build queue.\n */\nexport async function buildAppxPackage(\n target: Target,\n packager: WinPackager,\n options: AppxPackageBuildOptions,\n appOutDir: string,\n arch: Arch,\n config: AppxPackageBuildConfig\n): Promise<void> {\n await config.preflight?.()\n\n const artifactName = packager.expandArtifactBeautyNamePattern(options, config.kind, arch)\n const artifactPath = path.join(target.outDir, artifactName)\n await packager.emitArtifactBuildStarted({ targetPresentableName: config.presentableName, file: artifactPath, arch })\n\n const vendorPath = await getWindowsKitsBundle({ winCodeSign: packager.config.toolsets?.winCodeSign, resourcesDir: packager.buildResourcesDir })\n const vm = await packager.vm.value\n\n config.onBuilt?.({ arch, artifactPath, vendorPathKit: vendorPath.kit, vm })\n\n const stageDir = await createStageDir(target, packager, arch)\n\n const mappingFile = stageDir.getTempFile(\"mapping.txt\")\n const makeAppXArgs = [\"pack\", \"/o\" /* overwrite the output file if it exists */, \"/f\", vm.toVmFile(mappingFile), \"/p\", vm.toVmFile(artifactPath)]\n if (packager.compression === \"store\") {\n makeAppXArgs.push(\"/nc\")\n }\n\n const mappingList: Array<Array<string>> = []\n mappingList.push(await buildAppFileMappings(vm, appOutDir))\n\n const userAssetDir = await packager.getResource(undefined, APPX_ASSETS_DIR_NAME)\n const assetInfo = await computeUserAssets(vm, vendorPath.appxAssets, userAssetDir)\n const userAssets = assetInfo.userAssets\n\n const manifestFile = stageDir.getTempFile(\"AppxManifest.xml\")\n // https://github.com/electron-userland/electron-builder/issues/2108#issuecomment-333200711\n const publisher = await (await packager.signingManager.value).computePublisherName(target, options.publisher ?? null)\n await config.writeManifest(manifestFile, arch, publisher, userAssets)\n\n await packager.emitAppxManifestCreated(manifestFile)\n mappingList.push(assetInfo.mappings)\n mappingList.push([`\"${vm.toVmFile(manifestFile)}\" \"AppxManifest.xml\"`])\n\n if (isScaledAssetsProvided(userAssets)) {\n const outFile = vm.toVmFile(stageDir.getTempFile(\"resources.pri\"))\n const makePriExe = path.join(vendorPath.kit, \"makepri.exe\")\n const makePriPath = vm.toVmFile(makePriExe)\n\n const assetRoot = stageDir.getTempFile(\"appx/assets\")\n await emptyDir(assetRoot)\n await Promise.all(assetInfo.allAssets.map(it => copyOrLinkFile(it, path.join(assetRoot, path.basename(it)))))\n\n // Wait out any transient AV/share lock on the freshly-extracted kit binary (see ensureNotBusy).\n await ensureNotBusy(makePriExe)\n await vm.exec(makePriPath, [\n \"new\",\n \"/Overwrite\",\n \"/Manifest\",\n vm.toVmFile(manifestFile),\n \"/ProjectRoot\",\n vm.toVmFile(path.dirname(assetRoot)),\n \"/ConfigXml\",\n vm.toVmFile(path.join(getTemplatePath(\"appx\"), \"priconfig.xml\")),\n \"/OutputFile\",\n outFile,\n ])\n\n // in addition to resources.pri, resources.scale-140.pri and other such files will be generated\n for (const resourceFile of (await readdir(stageDir.dir)).filter(it => it.startsWith(\"resources.\")).sort()) {\n mappingList.push([`\"${vm.toVmFile(stageDir.getTempFile(resourceFile))}\" \"${resourceFile}\"`])\n }\n makeAppXArgs.push(\"/l\")\n }\n\n let mapping = \"[Files]\"\n for (const list of mappingList) {\n mapping += \"\\r\\n\" + list.join(\"\\r\\n\")\n }\n await writeFile(mappingFile, mapping)\n packager.debugLogger.add(`${config.kind}.mapping`, mapping)\n\n if (options.makeappxArgs != null) {\n makeAppXArgs.push(...options.makeappxArgs)\n }\n\n target.buildQueueManager.add(async () => {\n try {\n const makeAppxExe = path.join(vendorPath.kit, \"makeappx.exe\")\n // The kit binary is often freshly extracted to a cold cache; on Windows an AV scanner can briefly\n // hold a deny-write lock long enough that spawning fails with `spawn UNKNOWN`. Wait for it to clear.\n await ensureNotBusy(makeAppxExe)\n await vm.exec(vm.toVmFile(makeAppxExe), makeAppXArgs)\n await packager.signIf(artifactPath)\n } finally {\n await stageDir.cleanup()\n }\n\n await packager.emitArtifactBuildCompleted({\n file: artifactPath,\n packager,\n arch,\n safeArtifactName: packager.computeSafeArtifactName(artifactName, config.kind),\n target,\n isWriteUpdateInfo: options.electronUpdaterAware,\n })\n })\n}\n"]}
@@ -69,8 +69,10 @@ async function _resolveCustomToolsetPath(custom, resourcesDir) {
69
69
  const cacheDir = await cacheDirectoryOverrideAllowed.value;
70
70
  const customToolsetDir = path.join(cacheDir, "custom-toolsets");
71
71
  await mkdir(customToolsetDir, { recursive: true });
72
- // wipe first to ensure idempotent extraction if the source file changed since last extraction
73
- const toolsetTarget = path.join(customToolsetDir, releaseName);
72
+ // wipe first to ensure idempotent extraction if the source file changed since last extraction.
73
+ // Contain the destination within customToolsetDir (mirrors the `url` branch): `version` is a free-form
74
+ // config field, so a `../…` value must not let rmdir/extract escape the cache directory.
75
+ const toolsetTarget = sanitizeDirPath(path.join(customToolsetDir, releaseName), customToolsetDir);
74
76
  if (await exists(toolsetTarget)) {
75
77
  await rmdir(toolsetTarget, { recursive: true });
76
78
  }
@@ -1 +1 @@
1
- {"version":3,"file":"custom.js","sourceRoot":"","sources":["../../src/toolsets/custom.ts"],"names":[],"mappings":"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","sourcesContent":["import { exists, sanitizeDirPath, validateSecuredUrl } from \"builder-util\"\nimport { mkdir, rmdir, stat } from \"fs/promises\"\nimport * as path from \"path\"\nimport { ToolsetCustom } from \"../configuration.js\"\nimport { cacheDirectoryOverrideAllowed, downloadBuilderToolset, extractArchive, hashUrlSafe } from \"../util/electronGet.js\"\n\nasync function validateCustomToolset(custom: ToolsetCustom, resourcesDir?: string) {\n const url = custom.url.trim()\n try {\n const parsed = validateSecuredUrl(url)\n if (parsed.pathname.endsWith(\"/\")) {\n throw new Error(`URL must point to a file, but got ${parsed.href}`)\n }\n return { toolset: custom, type: \"url\" }\n } catch {\n // Ignore. If the URL is invalid, validate it as a file path\n }\n if (url.startsWith(\"file://\")) {\n const p = url.slice(\"file://\".length)\n const isWithinResources = resourcesDir ? path.normalize(p).startsWith(path.normalize(resourcesDir + path.sep)) : false\n const isValid = path.isAbsolute(p) || isWithinResources\n const type =\n isValid &&\n (await exists(p)) &&\n (await stat(p)\n .then(s => (s.isDirectory() ? \"directory\" : s.isFile() ? \"file\" : false))\n .catch(() => false))\n if (type) {\n return { toolset: custom, type }\n }\n }\n throw new Error(`Invalid custom toolset: ${url}. Must be a valid https:// URL or a file:// path.`)\n}\n\n// Strip the file:// prefix and sanitize the path against resourcesDir (relative paths must be within it)\nfunction resolveFilePath(url: string, resourcesDir?: string): string {\n const p = url.startsWith(\"file://\") ? url.slice(\"file://\".length) : url\n return path.isAbsolute(p) ? sanitizeDirPath(p) : sanitizeDirPath(p, resourcesDir)\n}\n\nconst _customToolsetCache = new Map<string, Promise<string>>()\n\nexport function clearCustomToolsetCache(): void {\n _customToolsetCache.clear()\n}\n\nexport function getCustomToolsetPath(custom: ToolsetCustom, resourcesDir?: string): Promise<string> {\n const key = JSON.stringify({ url: custom.url, checksum: custom.checksum ?? \"\", resourcesDir })\n let cached = _customToolsetCache.get(key)\n if (cached == null) {\n cached = _resolveCustomToolsetPath(custom, resourcesDir)\n _customToolsetCache.set(key, cached)\n }\n return cached\n}\n\nasync function _resolveCustomToolsetPath(custom: ToolsetCustom, resourcesDir?: string): Promise<string> {\n const { type, toolset } = await validateCustomToolset(custom, resourcesDir)\n\n if (type === \"directory\") {\n return resolveFilePath(toolset.url, resourcesDir)\n }\n\n if (!toolset.checksum) {\n throw new Error(`ToolsetCustom.checksum is required for ${type} toolsets (url: ${toolset.url})`)\n }\n\n const binaryVersion = toolset.version ?? toolset.checksum.substring(0, 8)\n const releaseName = `${binaryVersion}-${hashUrlSafe(toolset.url)}`\n\n if (type === \"url\") {\n return downloadBuilderToolset({\n releaseName: releaseName,\n filenameWithExt: path.basename(toolset.url),\n checksums: { [path.basename(toolset.url)]: toolset.checksum },\n overrideUrl: toolset.url,\n })\n } else if (type === \"file\") {\n const cacheDir = await cacheDirectoryOverrideAllowed.value\n const customToolsetDir = path.join(cacheDir, \"custom-toolsets\")\n await mkdir(customToolsetDir, { recursive: true })\n\n // wipe first to ensure idempotent extraction if the source file changed since last extraction\n const toolsetTarget = path.join(customToolsetDir, releaseName)\n if (await exists(toolsetTarget)) {\n await rmdir(toolsetTarget, { recursive: true })\n }\n await extractArchive(resolveFilePath(toolset.url, resourcesDir), toolsetTarget)\n return toolsetTarget\n }\n\n throw new Error(`Unsupported custom toolset type: ${type}`)\n}\n"]}
1
+ {"version":3,"file":"custom.js","sourceRoot":"","sources":["../../src/toolsets/custom.ts"],"names":[],"mappings":"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","sourcesContent":["import { exists, sanitizeDirPath, validateSecuredUrl } from \"builder-util\"\nimport { mkdir, rmdir, stat } from \"fs/promises\"\nimport * as path from \"path\"\nimport { ToolsetCustom } from \"../configuration.js\"\nimport { cacheDirectoryOverrideAllowed, downloadBuilderToolset, extractArchive, hashUrlSafe } from \"../util/electronGet.js\"\n\nasync function validateCustomToolset(custom: ToolsetCustom, resourcesDir?: string) {\n const url = custom.url.trim()\n try {\n const parsed = validateSecuredUrl(url)\n if (parsed.pathname.endsWith(\"/\")) {\n throw new Error(`URL must point to a file, but got ${parsed.href}`)\n }\n return { toolset: custom, type: \"url\" }\n } catch {\n // Ignore. If the URL is invalid, validate it as a file path\n }\n if (url.startsWith(\"file://\")) {\n const p = url.slice(\"file://\".length)\n const isWithinResources = resourcesDir ? path.normalize(p).startsWith(path.normalize(resourcesDir + path.sep)) : false\n const isValid = path.isAbsolute(p) || isWithinResources\n const type =\n isValid &&\n (await exists(p)) &&\n (await stat(p)\n .then(s => (s.isDirectory() ? \"directory\" : s.isFile() ? \"file\" : false))\n .catch(() => false))\n if (type) {\n return { toolset: custom, type }\n }\n }\n throw new Error(`Invalid custom toolset: ${url}. Must be a valid https:// URL or a file:// path.`)\n}\n\n// Strip the file:// prefix and sanitize the path against resourcesDir (relative paths must be within it)\nfunction resolveFilePath(url: string, resourcesDir?: string): string {\n const p = url.startsWith(\"file://\") ? url.slice(\"file://\".length) : url\n return path.isAbsolute(p) ? sanitizeDirPath(p) : sanitizeDirPath(p, resourcesDir)\n}\n\nconst _customToolsetCache = new Map<string, Promise<string>>()\n\nexport function clearCustomToolsetCache(): void {\n _customToolsetCache.clear()\n}\n\nexport function getCustomToolsetPath(custom: ToolsetCustom, resourcesDir?: string): Promise<string> {\n const key = JSON.stringify({ url: custom.url, checksum: custom.checksum ?? \"\", resourcesDir })\n let cached = _customToolsetCache.get(key)\n if (cached == null) {\n cached = _resolveCustomToolsetPath(custom, resourcesDir)\n _customToolsetCache.set(key, cached)\n }\n return cached\n}\n\nasync function _resolveCustomToolsetPath(custom: ToolsetCustom, resourcesDir?: string): Promise<string> {\n const { type, toolset } = await validateCustomToolset(custom, resourcesDir)\n\n if (type === \"directory\") {\n return resolveFilePath(toolset.url, resourcesDir)\n }\n\n if (!toolset.checksum) {\n throw new Error(`ToolsetCustom.checksum is required for ${type} toolsets (url: ${toolset.url})`)\n }\n\n const binaryVersion = toolset.version ?? toolset.checksum.substring(0, 8)\n const releaseName = `${binaryVersion}-${hashUrlSafe(toolset.url)}`\n\n if (type === \"url\") {\n return downloadBuilderToolset({\n releaseName: releaseName,\n filenameWithExt: path.basename(toolset.url),\n checksums: { [path.basename(toolset.url)]: toolset.checksum },\n overrideUrl: toolset.url,\n })\n } else if (type === \"file\") {\n const cacheDir = await cacheDirectoryOverrideAllowed.value\n const customToolsetDir = path.join(cacheDir, \"custom-toolsets\")\n await mkdir(customToolsetDir, { recursive: true })\n\n // wipe first to ensure idempotent extraction if the source file changed since last extraction.\n // Contain the destination within customToolsetDir (mirrors the `url` branch): `version` is a free-form\n // config field, so a `../…` value must not let rmdir/extract escape the cache directory.\n const toolsetTarget = sanitizeDirPath(path.join(customToolsetDir, releaseName), customToolsetDir)\n if (await exists(toolsetTarget)) {\n await rmdir(toolsetTarget, { recursive: true })\n }\n await extractArchive(resolveFilePath(toolset.url, resourcesDir), toolsetTarget)\n return toolsetTarget\n }\n\n throw new Error(`Unsupported custom toolset type: ${type}`)\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"icons.d.ts","sourceRoot":"","sources":["../../src/toolsets/icons.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAqBnD,wBAAsB,mBAAmB,CAAC,KAAK,EAAE,aAAa,CAAC,OAAO,CAAC,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAW9G;AAED,KAAK,qBAAqB,GAAG;IAC3B,SAAS,EAAE,MAAM,CAAA;IACjB,YAAY,EAAE,MAAM,GAAG,KAAK,GAAG,KAAK,CAAA;IACpC,MAAM,EAAE,MAAM,CAAA;IACd,YAAY,EAAE,aAAa,CAAC,OAAO,CAAC,CAAA;IACpC,YAAY,EAAE,MAAM,CAAA;CACrB,CAAA;AAID,wBAAsB,YAAY,CAAC,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,YAAY,EAAE,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAcxI"}
1
+ {"version":3,"file":"icons.d.ts","sourceRoot":"","sources":["../../src/toolsets/icons.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAwBnD,wBAAsB,mBAAmB,CAAC,KAAK,EAAE,aAAa,CAAC,OAAO,CAAC,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAW9G;AAED,KAAK,qBAAqB,GAAG;IAC3B,SAAS,EAAE,MAAM,CAAA;IACjB,YAAY,EAAE,MAAM,GAAG,KAAK,GAAG,KAAK,CAAA;IACpC,MAAM,EAAE,MAAM,CAAA;IACd,YAAY,EAAE,aAAa,CAAC,OAAO,CAAC,CAAA;IACpC,YAAY,EAAE,MAAM,CAAA;CACrB,CAAA;AAID,wBAAsB,YAAY,CAAC,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,YAAY,EAAE,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAcxI"}
@@ -5,7 +5,7 @@ import { withIconsLock } from "../util/toolsetLock.js";
5
5
  import { getCustomToolsetPath } from "./custom.js";
6
6
  import { resolveToolsetVersion } from "./version.js";
7
7
  // Newest icons-conversion bundle — selected when the config is unset / null / "latest".
8
- const ICONS_LATEST = "1.2.1";
8
+ const ICONS_LATEST = "1.2.3";
9
9
  const iconsToolsChecksums = {
10
10
  "1.1.0": {
11
11
  "icons-bundle.tar.gz": "2241c9501aa5ddd19317956449f50a1bc311df2c34058aae9bf8bfe62081eaec",
@@ -16,6 +16,9 @@ const iconsToolsChecksums = {
16
16
  "1.2.1": {
17
17
  "icons-bundle.tar.gz": "193241afc7c81ab165fa0af15ef0af88f796eb69e8e5bb4249a49310d8be242a",
18
18
  },
19
+ "1.2.3": {
20
+ "icons-bundle.tar.gz": "4e5bb546c9d3ab0c2bbacc22857467bf415f742a34c2be9dd138779d2fc066f9",
21
+ },
19
22
  };
20
23
  export async function getIconsToolsetPath(icons, resourcesDir) {
21
24
  if (typeof icons === "object" && icons != null) {
@@ -1 +1 @@
1
- {"version":3,"file":"icons.js","sourceRoot":"","sources":["../../src/toolsets/icons.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,yBAAyB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AACvF,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAE5B,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAA;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AACtD,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAClD,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAA;AAEpD,wFAAwF;AACxF,MAAM,YAAY,GAAG,OAAO,CAAA;AAE5B,MAAM,mBAAmB,GAAG;IAC1B,OAAO,EAAE;QACP,qBAAqB,EAAE,kEAAkE;KAC1F;IACD,OAAO,EAAE;QACP,qBAAqB,EAAE,kEAAkE;KAC1F;IACD,OAAO,EAAE;QACP,qBAAqB,EAAE,kEAAkE;KAC1F;CACO,CAAA;AAEV,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,KAA6B,EAAE,YAAoB;IAC3F,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;QAC/C,OAAO,oBAAoB,CAAC,KAAK,EAAE,YAAY,CAAC,CAAA;IAClD,CAAC;IACD,MAAM,OAAO,GAAG,qBAAqB,CAAC,KAAK,EAAE,YAAY,CAAC,CAAA;IAC1D,OAAO,sBAAsB,CAAC;QAC5B,WAAW,EAAE,SAAS,OAAO,EAAE;QAC/B,eAAe,EAAE,qBAAqB;QACtC,SAAS,EAAE,mBAAmB,CAAC,OAAO,CAAC;QACvC,aAAa,EAAE,6CAA6C;KAC7D,CAAC,CAAA;AACJ,CAAC;AAUD,MAAM,oBAAoB,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,CAAU,CAAA;AAE5D,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,YAAY,EAAyB;IACvH,IAAI,CAAE,oBAA0C,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;QACxE,MAAM,IAAI,yBAAyB,CAAC,+BAA+B,YAAY,EAAE,CAAC,CAAA;IACpF,CAAC;IACD,MAAM,SAAS,GAAG,eAAe,CAAC,SAAS,CAAC,CAAA;IAC5C,MAAM,UAAU,GAAG,eAAe,CAAC,MAAM,CAAC,CAAA;IAE1C,MAAM,WAAW,GAAG,MAAM,mBAAmB,CAAC,YAAY,EAAE,YAAY,CAAC,CAAA;IACzE,MAAM,UAAU,GAAG,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,cAAc,CAAC,EAAE,WAAW,CAAC,CAAA;IAC1F,IAAI,CAAC,CAAC,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,yBAAyB,CAAC,0CAA0C,UAAU,EAAE,CAAC,CAAA;IAC7F,CAAC;IACD,sLAAsL;IACtL,MAAM,aAAa,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,YAAY,EAAE,OAAO,EAAE,UAAU,CAAC,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,CAAA;AACxJ,CAAC","sourcesContent":["import { exec, exists, InvalidConfigurationError, sanitizeDirPath } from \"builder-util\"\nimport * as path from \"path\"\nimport { ToolsetConfig } from \"../configuration.js\"\nimport { downloadBuilderToolset } from \"../util/electronGet.js\"\nimport { withIconsLock } from \"../util/toolsetLock.js\"\nimport { getCustomToolsetPath } from \"./custom.js\"\nimport { resolveToolsetVersion } from \"./version.js\"\n\n// Newest icons-conversion bundle — selected when the config is unset / null / \"latest\".\nconst ICONS_LATEST = \"1.2.1\"\n\nconst iconsToolsChecksums = {\n \"1.1.0\": {\n \"icons-bundle.tar.gz\": \"2241c9501aa5ddd19317956449f50a1bc311df2c34058aae9bf8bfe62081eaec\",\n },\n \"1.2.0\": {\n \"icons-bundle.tar.gz\": \"788add2400487fe00d5ceac4a8347bd71fc43c8c988fde879f929992ea0c03ea\",\n },\n \"1.2.1\": {\n \"icons-bundle.tar.gz\": \"193241afc7c81ab165fa0af15ef0af88f796eb69e8e5bb4249a49310d8be242a\",\n },\n} as const\n\nexport async function getIconsToolsetPath(icons: ToolsetConfig[\"icons\"], resourcesDir: string): Promise<string> {\n if (typeof icons === \"object\" && icons != null) {\n return getCustomToolsetPath(icons, resourcesDir)\n }\n const version = resolveToolsetVersion(icons, ICONS_LATEST)\n return downloadBuilderToolset({\n releaseName: `icons@${version}`,\n filenameWithExt: \"icons-bundle.tar.gz\",\n checksums: iconsToolsChecksums[version],\n githubOrgRepo: \"electron-userland/electron-builder-binaries\",\n })\n}\n\ntype IconConversionOptions = {\n inputFile: string\n outputFormat: \"icns\" | \"ico\" | \"set\"\n outDir: string\n iconsToolset: ToolsetConfig[\"icons\"]\n resourcesDir: string\n}\n\nconst VALID_OUTPUT_FORMATS = [\"icns\", \"ico\", \"set\"] as const\n\nexport async function runIconsTool({ inputFile, outputFormat, outDir, iconsToolset, resourcesDir }: IconConversionOptions): Promise<void> {\n if (!(VALID_OUTPUT_FORMATS as readonly string[]).includes(outputFormat)) {\n throw new InvalidConfigurationError(`Invalid icon output format: ${outputFormat}`)\n }\n const safeInput = sanitizeDirPath(inputFile)\n const safeOutDir = sanitizeDirPath(outDir)\n\n const toolsetPath = await getIconsToolsetPath(iconsToolset, resourcesDir)\n const scriptPath = sanitizeDirPath(path.resolve(toolsetPath, \"icon-tool.js\"), toolsetPath)\n if (!(await exists(scriptPath))) {\n throw new InvalidConfigurationError(`Icons tool not found at expected path: ${scriptPath}`)\n }\n // Serialize icon-tool spawns across processes: each reserves a large WebAssembly.Memory, andrunning many in parallel (e.g. across vitest workers) exhausts memory. See withIconsLock.\n await withIconsLock(() => exec(process.execPath, [scriptPath, `--input`, safeInput, `--format`, outputFormat, `--out`, safeOutDir], { shell: false }))\n}\n"]}
1
+ {"version":3,"file":"icons.js","sourceRoot":"","sources":["../../src/toolsets/icons.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,yBAAyB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AACvF,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAE5B,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAA;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AACtD,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAClD,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAA;AAEpD,wFAAwF;AACxF,MAAM,YAAY,GAAG,OAAO,CAAA;AAE5B,MAAM,mBAAmB,GAAG;IAC1B,OAAO,EAAE;QACP,qBAAqB,EAAE,kEAAkE;KAC1F;IACD,OAAO,EAAE;QACP,qBAAqB,EAAE,kEAAkE;KAC1F;IACD,OAAO,EAAE;QACP,qBAAqB,EAAE,kEAAkE;KAC1F;IACD,OAAO,EAAE;QACP,qBAAqB,EAAE,kEAAkE;KAC1F;CACO,CAAA;AAEV,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,KAA6B,EAAE,YAAoB;IAC3F,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;QAC/C,OAAO,oBAAoB,CAAC,KAAK,EAAE,YAAY,CAAC,CAAA;IAClD,CAAC;IACD,MAAM,OAAO,GAAG,qBAAqB,CAAC,KAAK,EAAE,YAAY,CAAC,CAAA;IAC1D,OAAO,sBAAsB,CAAC;QAC5B,WAAW,EAAE,SAAS,OAAO,EAAE;QAC/B,eAAe,EAAE,qBAAqB;QACtC,SAAS,EAAE,mBAAmB,CAAC,OAAO,CAAC;QACvC,aAAa,EAAE,6CAA6C;KAC7D,CAAC,CAAA;AACJ,CAAC;AAUD,MAAM,oBAAoB,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,CAAU,CAAA;AAE5D,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,YAAY,EAAyB;IACvH,IAAI,CAAE,oBAA0C,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;QACxE,MAAM,IAAI,yBAAyB,CAAC,+BAA+B,YAAY,EAAE,CAAC,CAAA;IACpF,CAAC;IACD,MAAM,SAAS,GAAG,eAAe,CAAC,SAAS,CAAC,CAAA;IAC5C,MAAM,UAAU,GAAG,eAAe,CAAC,MAAM,CAAC,CAAA;IAE1C,MAAM,WAAW,GAAG,MAAM,mBAAmB,CAAC,YAAY,EAAE,YAAY,CAAC,CAAA;IACzE,MAAM,UAAU,GAAG,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,cAAc,CAAC,EAAE,WAAW,CAAC,CAAA;IAC1F,IAAI,CAAC,CAAC,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,yBAAyB,CAAC,0CAA0C,UAAU,EAAE,CAAC,CAAA;IAC7F,CAAC;IACD,sLAAsL;IACtL,MAAM,aAAa,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,YAAY,EAAE,OAAO,EAAE,UAAU,CAAC,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,CAAA;AACxJ,CAAC","sourcesContent":["import { exec, exists, InvalidConfigurationError, sanitizeDirPath } from \"builder-util\"\nimport * as path from \"path\"\nimport { ToolsetConfig } from \"../configuration.js\"\nimport { downloadBuilderToolset } from \"../util/electronGet.js\"\nimport { withIconsLock } from \"../util/toolsetLock.js\"\nimport { getCustomToolsetPath } from \"./custom.js\"\nimport { resolveToolsetVersion } from \"./version.js\"\n\n// Newest icons-conversion bundle — selected when the config is unset / null / \"latest\".\nconst ICONS_LATEST = \"1.2.3\"\n\nconst iconsToolsChecksums = {\n \"1.1.0\": {\n \"icons-bundle.tar.gz\": \"2241c9501aa5ddd19317956449f50a1bc311df2c34058aae9bf8bfe62081eaec\",\n },\n \"1.2.0\": {\n \"icons-bundle.tar.gz\": \"788add2400487fe00d5ceac4a8347bd71fc43c8c988fde879f929992ea0c03ea\",\n },\n \"1.2.1\": {\n \"icons-bundle.tar.gz\": \"193241afc7c81ab165fa0af15ef0af88f796eb69e8e5bb4249a49310d8be242a\",\n },\n \"1.2.3\": {\n \"icons-bundle.tar.gz\": \"4e5bb546c9d3ab0c2bbacc22857467bf415f742a34c2be9dd138779d2fc066f9\",\n },\n} as const\n\nexport async function getIconsToolsetPath(icons: ToolsetConfig[\"icons\"], resourcesDir: string): Promise<string> {\n if (typeof icons === \"object\" && icons != null) {\n return getCustomToolsetPath(icons, resourcesDir)\n }\n const version = resolveToolsetVersion(icons, ICONS_LATEST)\n return downloadBuilderToolset({\n releaseName: `icons@${version}`,\n filenameWithExt: \"icons-bundle.tar.gz\",\n checksums: iconsToolsChecksums[version],\n githubOrgRepo: \"electron-userland/electron-builder-binaries\",\n })\n}\n\ntype IconConversionOptions = {\n inputFile: string\n outputFormat: \"icns\" | \"ico\" | \"set\"\n outDir: string\n iconsToolset: ToolsetConfig[\"icons\"]\n resourcesDir: string\n}\n\nconst VALID_OUTPUT_FORMATS = [\"icns\", \"ico\", \"set\"] as const\n\nexport async function runIconsTool({ inputFile, outputFormat, outDir, iconsToolset, resourcesDir }: IconConversionOptions): Promise<void> {\n if (!(VALID_OUTPUT_FORMATS as readonly string[]).includes(outputFormat)) {\n throw new InvalidConfigurationError(`Invalid icon output format: ${outputFormat}`)\n }\n const safeInput = sanitizeDirPath(inputFile)\n const safeOutDir = sanitizeDirPath(outDir)\n\n const toolsetPath = await getIconsToolsetPath(iconsToolset, resourcesDir)\n const scriptPath = sanitizeDirPath(path.resolve(toolsetPath, \"icon-tool.js\"), toolsetPath)\n if (!(await exists(scriptPath))) {\n throw new InvalidConfigurationError(`Icons tool not found at expected path: ${scriptPath}`)\n }\n // Serialize icon-tool spawns across processes: each reserves a large WebAssembly.Memory, andrunning many in parallel (e.g. across vitest workers) exhausts memory. See withIconsLock.\n await withIconsLock(() => exec(process.execPath, [scriptPath, `--input`, safeInput, `--format`, outputFormat, `--out`, safeOutDir], { shell: false }))\n}\n"]}
@@ -77,6 +77,15 @@ export declare function getWindowsKitsBundle({ winCodeSign, resourcesDir }: {
77
77
  appxAssets: string;
78
78
  }>;
79
79
  export declare function isOldWin6(): boolean;
80
+ /**
81
+ * True only for the explicit legacy winCodeSign pin (`"0.0.0"` → winCodeSign-2.6.0). That bundle lacks
82
+ * the modern Windows Kits SDK (no MSIX-capable `makeappx`/`makepri`), so it cannot build MSIX — only the
83
+ * MSIX target gates on this. AppX still builds fine with the legacy bundle (it has its own legacy-bundle
84
+ * `signtool` handling in `getWindowsSignToolExe`). Unset / `null` / `"latest"` and any modern version pin
85
+ * resolve to a modern bundle; a custom `{ url, … }` toolset is the caller's responsibility and is not
86
+ * treated as legacy.
87
+ */
88
+ export declare function isLegacyWinCodeSign(winCodeSign: ToolsetConfig["winCodeSign"] | Nullish): boolean;
80
89
  export declare function getAtsBundleDir(winCodeSign: string): Promise<string>;
81
90
  export declare function getDotnetRuntimeDir(winCodeSign: string): Promise<string>;
82
91
  export declare function getRceditBundle(winCodeSign: ToolsetConfig["winCodeSign"] | Nullish, resourcesDir?: string): Promise<{
@@ -1 +1 @@
1
- {"version":3,"file":"winCodeSign.d.ts","sourceRoot":"","sources":["../../src/toolsets/winCodeSign.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAA;AAG9C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,EAAE,QAAQ,EAAkB,MAAM,wBAAwB,CAAA;AAMjE,eAAO,MAAM,mBAAmB,UAAU,CAAA;AAU1C,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0DvB,CAAA;AAaV,wBAAsB,eAAe,CAAC,WAAW,EAAE,aAAa,CAAC,aAAa,CAAC,GAAG,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAOlJ;AAED;;;;;;;;GAQG;AACH,wBAAsB,oBAAoB,CAAC,EAAE,WAAW,EAAE,YAAY,EAAE,EAAE;IAAE,WAAW,EAAE,aAAa,CAAC,aAAa,CAAC,GAAG,OAAO,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE;;;GAevJ;AAED,wBAAgB,SAAS,YAGxB;AA2DD,wBAAsB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAW1E;AAED,wBAAsB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAW9E;AAED,wBAAsB,eAAe,CAAC,WAAW,EAAE,aAAa,CAAC,aAAa,CAAC,GAAG,OAAO,EAAE,YAAY,SAAK;;;GAgB3G"}
1
+ {"version":3,"file":"winCodeSign.d.ts","sourceRoot":"","sources":["../../src/toolsets/winCodeSign.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAA;AAG9C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,EAAE,QAAQ,EAAkB,MAAM,wBAAwB,CAAA;AAMjE,eAAO,MAAM,mBAAmB,UAAU,CAAA;AAU1C,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0DvB,CAAA;AAaV,wBAAsB,eAAe,CAAC,WAAW,EAAE,aAAa,CAAC,aAAa,CAAC,GAAG,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAOlJ;AAED;;;;;;;;GAQG;AACH,wBAAsB,oBAAoB,CAAC,EAAE,WAAW,EAAE,YAAY,EAAE,EAAE;IAAE,WAAW,EAAE,aAAa,CAAC,aAAa,CAAC,GAAG,OAAO,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE;;;GAevJ;AAED,wBAAgB,SAAS,YAGxB;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,aAAa,CAAC,aAAa,CAAC,GAAG,OAAO,GAAG,OAAO,CAEhG;AA2DD,wBAAsB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAW1E;AAED,wBAAsB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAW9E;AAED,wBAAsB,eAAe,CAAC,WAAW,EAAE,aAAa,CAAC,aAAa,CAAC,GAAG,OAAO,EAAE,YAAY,SAAK;;;GAgB3G"}