electron-builder-squirrel-windows 27.0.0-alpha.1 → 27.0.0-alpha.11

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.
@@ -1,5 +1,5 @@
1
1
  import { Arch, SquirrelWindowsOptions, Target, WinPackager } from "app-builder-lib";
2
- import { Options as SquirrelOptions } from "electron-winstaller";
2
+ import { InstallerOptions } from "./windowsInstaller.js";
3
3
  export default class SquirrelWindowsTarget extends Target {
4
4
  private readonly packager;
5
5
  readonly outDir: string;
@@ -15,6 +15,6 @@ export default class SquirrelWindowsTarget extends Target {
15
15
  private get exeName();
16
16
  private select7zipArch;
17
17
  private createNuspecTemplateWithProjectUrl;
18
- computeEffectiveDistOptions(appDirectory: string, outputDirectory: string, setupFile: string): Promise<SquirrelOptions>;
18
+ computeEffectiveDistOptions(appDirectory: string, outputDirectory: string, setupFile: string): Promise<InstallerOptions>;
19
19
  }
20
20
  //# sourceMappingURL=SquirrelWindowsTarget.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SquirrelWindowsTarget.d.ts","sourceRoot":"","sources":["../src/SquirrelWindowsTarget.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,IAAI,EAAiB,sBAAsB,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAIlG,OAAO,EAAE,OAAO,IAAI,eAAe,EAA0C,MAAM,qBAAqB,CAAA;AAGxG,MAAM,CAAC,OAAO,OAAO,qBAAsB,SAAQ,MAAM;IAMrD,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM;IANzB,QAAQ,CAAC,OAAO,EAAE,sBAAsB,CAAA;IAExC,gBAAgB,UAAQ;gBAGL,QAAQ,EAAE,WAAW,EAC7B,MAAM,EAAE,MAAM;YAMX,4BAA4B;IAoC1C,OAAO,CAAC,mBAAmB;YAMb,gBAAgB;YA2ChB,yBAAyB;IAwBjC,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI;IAwEzC,OAAO,KAAK,OAAO,GAElB;IAED,OAAO,KAAK,OAAO,GAGlB;IAED,OAAO,CAAC,cAAc;YASR,kCAAkC;IAc1C,2BAA2B,CAAC,YAAY,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;CAuE9H"}
1
+ {"version":3,"file":"SquirrelWindowsTarget.d.ts","sourceRoot":"","sources":["../src/SquirrelWindowsTarget.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAiB,sBAAsB,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAQlG,OAAO,EAAE,gBAAgB,EAA0C,MAAM,uBAAuB,CAAA;AAEhG,MAAM,CAAC,OAAO,OAAO,qBAAsB,SAAQ,MAAM;IAMrD,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM;IANzB,QAAQ,CAAC,OAAO,EAAE,sBAAsB,CAAA;IAExC,gBAAgB,UAAQ;gBAGL,QAAQ,EAAE,WAAW,EAC7B,MAAM,EAAE,MAAM;YAMX,4BAA4B;IAgD1C,OAAO,CAAC,mBAAmB;YAMb,gBAAgB;YAgDhB,yBAAyB;IA0BjC,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI;IAwEzC,OAAO,KAAK,OAAO,GAElB;IAED,OAAO,KAAK,OAAO,GAGlB;IAED,OAAO,CAAC,cAAc;YAiBR,kCAAkC;IAa1C,2BAA2B,CAAC,YAAY,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;CAqE/H"}
@@ -1,14 +1,12 @@
1
- import { createRequire } from "node:module";
2
- import { InvalidConfigurationError, log, isEmptyOrSpaces, exists } from "builder-util";
3
- const _requireResolve = createRequire(import.meta.url).resolve;
4
- import { downloadBuilderToolset, withToolsetLock } from "app-builder-lib/internal";
5
- import { sanitizeFileName } from "builder-util/internal";
6
1
  import { getArchSuffix, Target } from "app-builder-lib";
7
- import * as path from "path";
2
+ import { getRceditBundle, withToolsetLock, WineVmManager } from "app-builder-lib/internal";
3
+ import { InvalidConfigurationError, isEmptyOrSpaces, log, escapeForXml, prepareFixedNameWrite } from "builder-util";
4
+ import { sanitizeFileName } from "builder-util/internal";
8
5
  import * as fs from "fs";
9
6
  import * as os from "os";
10
- import { createWindowsInstaller, convertVersion } from "electron-winstaller";
11
- import { WineVmManager } from "app-builder-lib/internal";
7
+ import * as path from "path";
8
+ import { getSquirrelToolsetPath, getWixToolsetPath } from "./toolset.js";
9
+ import { convertVersion, createWindowsInstaller } from "./windowsInstaller.js";
12
10
  export default class SquirrelWindowsTarget extends Target {
13
11
  constructor(packager, outDir) {
14
12
  super("squirrel");
@@ -18,40 +16,50 @@ export default class SquirrelWindowsTarget extends Target {
18
16
  this.options = packager.getOptionsForTarget("squirrelWindows");
19
17
  }
20
18
  async prepareSignedVendorDirectory() {
21
- const customSquirrelVendorDirectory = this.options.customSquirrelVendorDir;
22
19
  const tmpVendorDirectory = await this.packager.tempDirManager.createTempDir({ prefix: "squirrel-windows-vendor" });
23
- if (customSquirrelVendorDirectory && (await exists(customSquirrelVendorDirectory))) {
24
- await fs.promises.cp(customSquirrelVendorDirectory, tmpVendorDirectory, { recursive: true });
25
- }
26
- else {
27
- if (!isEmptyOrSpaces(customSquirrelVendorDirectory)) {
28
- log.warn({ customSquirrelVendorDirectory }, "unable to access custom Squirrel.Windows vendor directory, falling back to default vendor");
29
- }
30
- const windowInstallerPackage = _requireResolve("electron-winstaller/package.json");
31
- const [squirrelBin] = await Promise.all([
32
- downloadBuilderToolset({
33
- releaseName: "squirrel.windows@1.0.0",
34
- filenameWithExt: "squirrel.windows-2.0.1-patched.7z",
35
- checksums: { "squirrel.windows-2.0.1-patched.7z": "76851f0c192eaf9bc6f8f3eecdfe325857ebe70d7833ec62ed846a1acd50c846" },
36
- }),
37
- fs.promises.cp(path.join(path.dirname(windowInstallerPackage), "vendor"), tmpVendorDirectory, { recursive: true }),
38
- ]);
39
- await fs.promises.cp(path.join(squirrelBin, "electron-winstaller", "vendor"), tmpVendorDirectory, { recursive: true });
20
+ // The vendor toolset comes from the maintained squirrel.windows bundle. Pin a version or supply a
21
+ // custom/local bundle (e.g. for air-gapped builds) via `toolsets.squirrel` (a ToolsetCustom object).
22
+ const squirrelToolset = await getSquirrelToolsetPath(this.packager.config.toolsets?.squirrel, this.packager.buildResourcesDir);
23
+ await fs.promises.cp(path.join(squirrelToolset, "electron-winstaller", "vendor"), tmpVendorDirectory, { recursive: true });
24
+ // Both Squirrel.exe and Squirrel-Mono.exe shell out to rcedit.exe (via setPEVersionInfoAndIcon)
25
+ // during --releasify to stamp version info and the app icon into Setup.exe, so rcedit must live in
26
+ // the vendor dir on every host — on non-Windows it runs under wine alongside the other Win32 vendor
27
+ // exes (Setup.exe, StubExecutable.exe, …). The bundle omits rcedit, so resolve it from the
28
+ // win-codesign toolset, which already versions and caches it across platforms.
29
+ //
30
+ // getRceditBundle honors the user's `toolsets.winCodeSign` selection, so users retain a bypass if a
31
+ // newer toolset regresses: `"0.0.0"` falls back to the legacy winCodeSign-2.6.0 rcedit, a custom
32
+ // toolset object uses their own rcedit, and the default (unset/"latest") pulls rcedit-windows-2_0_0.
33
+ const rcedit = await getRceditBundle(this.packager.config.toolsets?.winCodeSign, this.packager.buildResourcesDir);
34
+ // Pick rcedit by host arch (x64 for x64/arm64, x86 only for ia32). On non-Windows it runs under wine:
35
+ // the 32-bit build fails on arm64 macOS even under Rosetta (which translates x64, not x86), so the x64
36
+ // build is required there.
37
+ const rceditExe = os.arch() === "ia32" ? rcedit.x86 : rcedit.x64;
38
+ await fs.promises.copyFile(rceditExe, path.join(tmpVendorDirectory, "rcedit.exe"));
39
+ // When building an MSI, Squirrel's createMsiPackage runs candle.exe/light.exe from the vendor dir and
40
+ // reads template.wxs there. The bundle ships neither, so merge the shared WiX toolset (the same
41
+ // candle/light electron-builder's MSI target uses) into the vendor dir, plus the Squirrel MSI template
42
+ // (authored against the v4 namespace this transitional WiX 4 requires).
43
+ if (this.options.msi) {
44
+ const wixToolset = await getWixToolsetPath();
45
+ await fs.promises.cp(wixToolset, tmpVendorDirectory, { recursive: true });
46
+ await fs.promises.copyFile(path.resolve(import.meta.dirname, "..", "template.wxs"), path.join(tmpVendorDirectory, "template.wxs"));
40
47
  }
48
+ // Squirrel.exe is the core updater binary the bundle always ships; a missing one means a broken
49
+ // vendor toolset. Fail loudly rather than skipping signing — skipping would produce a broken
50
+ // installer and bypass the forceCodeSigning enforcement inside signIf (its awaited promise rejects
51
+ // when the file can't be signed and forceCodeSigning is set).
41
52
  const files = await fs.promises.readdir(tmpVendorDirectory);
42
- const squirrelExe = files.find(f => f === "Squirrel.exe");
43
- if (squirrelExe) {
44
- const filePath = path.join(tmpVendorDirectory, squirrelExe);
45
- log.debug({ file: filePath }, "signing vendor executable");
46
- await this.packager.signIf(filePath);
47
- }
48
- else {
49
- log.warn("Squirrel.exe not found in vendor directory, skipping signing");
53
+ if (!files.includes("Squirrel.exe")) {
54
+ throw new Error(`Squirrel.exe not found in vendor directory: ${tmpVendorDirectory}`);
50
55
  }
56
+ const squirrelExePath = path.join(tmpVendorDirectory, "Squirrel.exe");
57
+ log.debug({ file: squirrelExePath }, "signing vendor executable");
58
+ await this.packager.signIf(squirrelExePath);
51
59
  return tmpVendorDirectory;
52
60
  }
53
61
  assertShellSafePath(filePath, description) {
54
- if (/[\r\n`$;&|<>]/.test(filePath)) {
62
+ if (/[\r\n\0`$;&|<>]/.test(filePath)) {
55
63
  throw new InvalidConfigurationError(`${description} contains unsafe shell characters: ${filePath}`);
56
64
  }
57
65
  }
@@ -83,7 +91,12 @@ export default class SquirrelWindowsTarget extends Target {
83
91
  }
84
92
  canonicalTargetPath = path.resolve(canonicalTargetParent, relativeFromResolvedParent);
85
93
  }
86
- catch {
94
+ catch (e) {
95
+ // Only fall back for filesystem errors (target parent not found, permission, etc.).
96
+ // Validation errors must propagate so callers get an actionable message.
97
+ if (e instanceof InvalidConfigurationError) {
98
+ throw e;
99
+ }
87
100
  canonicalTargetPath = resolvedTargetPath;
88
101
  }
89
102
  }
@@ -104,6 +117,8 @@ export default class SquirrelWindowsTarget extends Target {
104
117
  throw new Error(`App executable not found in app directory: ${appOutDir}`);
105
118
  }
106
119
  const filePath = await this.ensurePathInside(appOutDir, path.join(appOutDir, appExe.name), "App executable path");
120
+ // a symlink at the name, from the copied app files, is replaced rather than resolved onto another file of the app
121
+ await prepareFixedNameWrite(appOutDir, path.join(appOutDir, `${this.exeName}_ExecutionStub.exe`), "Squirrel execution stub");
107
122
  const stubExePath = await this.ensurePathInside(appOutDir, path.join(appOutDir, `${this.exeName}_ExecutionStub.exe`), "Stub executable path");
108
123
  const stubExecutableSource = await this.ensurePathInside(vendorDir, path.join(vendorDir, "StubExecutable.exe"), "Stub executable source");
109
124
  const writeZipToSetupExe = await this.ensurePathInside(vendorDir, path.join(vendorDir, "WriteZipToSetup.exe"), "WriteZipToSetup executable");
@@ -186,10 +201,18 @@ export default class SquirrelWindowsTarget extends Target {
186
201
  select7zipArch(vendorDirectory) {
187
202
  // https://github.com/electron/windows-installer/blob/main/script/select-7z-arch.js
188
203
  // Even if we're cross-compiling for a different arch like arm64,
189
- // we still need to use the 7-Zip executable for the host arch
190
- const resolvedArch = os.arch;
191
- fs.copyFileSync(path.join(vendorDirectory, `7z-${resolvedArch}.exe`), path.join(vendorDirectory, "7z.exe"));
192
- fs.copyFileSync(path.join(vendorDirectory, `7z-${resolvedArch}.dll`), path.join(vendorDirectory, "7z.dll"));
204
+ // we still need to use the 7-Zip executable for the host arch.
205
+ // When arch-specific variants aren't present (vendor bundle ships a pre-selected 7z.exe),
206
+ // skip the copy — the bundle's 7z.exe is already correct.
207
+ const resolvedArch = os.arch();
208
+ const archExe = path.join(vendorDirectory, `7z-${resolvedArch}.exe`);
209
+ const archDll = path.join(vendorDirectory, `7z-${resolvedArch}.dll`);
210
+ if (fs.existsSync(archExe)) {
211
+ fs.copyFileSync(archExe, path.join(vendorDirectory, "7z.exe"));
212
+ }
213
+ if (fs.existsSync(archDll)) {
214
+ fs.copyFileSync(archDll, path.join(vendorDirectory, "7z.dll"));
215
+ }
193
216
  }
194
217
  async createNuspecTemplateWithProjectUrl() {
195
218
  const templatePath = path.resolve(import.meta.dirname, "..", "template.nuspectemplate");
@@ -197,8 +220,7 @@ export default class SquirrelWindowsTarget extends Target {
197
220
  if (projectUrl != null) {
198
221
  const nuspecTemplate = await this.packager.tempDirManager.getTempFile({ prefix: "template", suffix: ".nuspectemplate" });
199
222
  let templateContent = await fs.promises.readFile(templatePath, "utf8");
200
- const searchString = "<copyright><%- copyright %></copyright>";
201
- templateContent = templateContent.replace(searchString, `${searchString}\n <projectUrl>${projectUrl}</projectUrl>`);
223
+ templateContent = addProjectUrl(templateContent, projectUrl);
202
224
  await fs.promises.writeFile(nuspecTemplate, templateContent);
203
225
  return nuspecTemplate;
204
226
  }
@@ -216,62 +238,72 @@ export default class SquirrelWindowsTarget extends Target {
216
238
  throw new InvalidConfigurationError("squirrelWindows.iconUrl is not specified, please see https://www.electron.build/squirrel-windows#SquirrelWindowsOptions-iconUrl");
217
239
  }
218
240
  }
219
- checkConflictingOptions(this.options);
241
+ normalizeSquirrelOptions(this.options);
220
242
  const appInfo = packager.appInfo;
221
- const options = {
222
- appDirectory: appDirectory,
223
- outputDirectory: outputDirectory,
224
- name: this.options.useAppIdAsId ? appInfo.id : this.appName,
225
- title: appInfo.productName || appInfo.name,
226
- version: appInfo.version,
227
- description: appInfo.description,
228
- exe: `${this.exeName}.exe`,
229
- authors: appInfo.companyName || "",
230
- nuspecTemplate: await this.createNuspecTemplateWithProjectUrl(),
231
- iconUrl,
232
- copyright: appInfo.copyright,
233
- noMsi: !this.options.msi,
234
- usePackageJson: false,
235
- };
236
- options.vendorDirectory = await this.prepareSignedVendorDirectory();
237
- this.select7zipArch(options.vendorDirectory);
238
- options.fixUpPaths = true;
239
- options.setupExe = setupFile;
240
- if (this.options.msi) {
241
- options.setupMsi = setupFile.replace(".exe", ".msi");
242
- }
243
- if (isEmptyOrSpaces(options.description)) {
244
- options.description = this.options.name || appInfo.productName;
245
- }
246
- if (options.remoteToken == null) {
247
- options.remoteToken = process.env.GH_TOKEN || process.env.GITHUB_TOKEN;
248
- }
243
+ const description = isEmptyOrSpaces(appInfo.description) ? this.options.name || appInfo.productName : appInfo.description;
244
+ let remoteReleases;
249
245
  if (this.options.remoteReleases === true) {
250
246
  const info = await packager.repositoryInfo;
251
247
  if (info == null) {
252
248
  log.warn("remoteReleases set to true, but cannot get repository info");
253
249
  }
254
250
  else {
255
- options.remoteReleases = `https://github.com/${info.user}/${info.project}`;
256
- log.info({ remoteReleases: options.remoteReleases }, `remoteReleases is set`);
251
+ remoteReleases = `https://github.com/${info.user}/${info.project}`;
252
+ log.info({ remoteReleases }, `remoteReleases is set`);
257
253
  }
258
254
  }
259
255
  else if (typeof this.options.remoteReleases === "string" && !isEmptyOrSpaces(this.options.remoteReleases)) {
260
- options.remoteReleases = this.options.remoteReleases;
256
+ remoteReleases = this.options.remoteReleases;
261
257
  }
258
+ let loadingGif;
262
259
  if (this.options.loadingGif) {
263
- options.loadingGif = path.resolve(packager.projectDir, this.options.loadingGif);
260
+ loadingGif = path.resolve(packager.projectDir, this.options.loadingGif);
264
261
  }
265
262
  else {
266
- const resourceList = await packager.resourceList;
267
- if (resourceList.includes("install-spinner.gif")) {
268
- options.loadingGif = path.join(packager.buildResourcesDir, "install-spinner.gif");
269
- }
263
+ // User-supplied buildResources gif wins; otherwise fall back to the bundled default spinner —
264
+ // parity with electron-winstaller, which always supplied resources/install-spinner.gif when none
265
+ // was configured (a fresh-install progress animation; never omitted).
266
+ loadingGif = (await packager.getResource(undefined, "install-spinner.gif")) ?? path.resolve(import.meta.dirname, "..", "install-spinner.gif");
270
267
  }
271
- return options;
268
+ const vendorDirectory = await this.prepareSignedVendorDirectory();
269
+ this.select7zipArch(vendorDirectory);
270
+ return {
271
+ appDirectory,
272
+ outputDirectory,
273
+ vendorDirectory,
274
+ name: this.options.useAppIdAsId ? appInfo.id : this.appName,
275
+ title: appInfo.productName || appInfo.name,
276
+ version: appInfo.version,
277
+ description,
278
+ exe: `${this.exeName}.exe`,
279
+ authors: appInfo.companyName || "",
280
+ nuspecTemplate: await this.createNuspecTemplateWithProjectUrl(),
281
+ iconUrl,
282
+ copyright: appInfo.copyright,
283
+ msi: this.options.msi,
284
+ fixUpPaths: true,
285
+ setupExe: setupFile,
286
+ setupMsi: this.options.msi ? setupFile.replace(/\.exe$/i, ".msi") : undefined,
287
+ loadingGif,
288
+ remoteReleases,
289
+ remoteToken: firstNonBlank(this.options.remoteToken, process.env.GH_TOKEN, process.env.GITHUB_TOKEN),
290
+ createTempDir: opts => this.packager.tempDirManager.createTempDir(opts),
291
+ externalLinks: await packager.getExternalLinkPolicy(),
292
+ };
272
293
  }
273
294
  }
274
- function checkConflictingOptions(options) {
295
+ /** @internal */
296
+ export function addProjectUrl(template, projectUrl) {
297
+ const searchString = "<copyright><%- copyright %></copyright>";
298
+ return template.replace(searchString, `${searchString}\n <projectUrl>${escapeForXml(projectUrl)}</projectUrl>`);
299
+ }
300
+ // `remoteToken: ""` (or whitespace) in the config counts as unset: fall through to the environment
301
+ // instead of shadowing GH_TOKEN/GITHUB_TOKEN with a value SyncReleases would drop anyway.
302
+ function firstNonBlank(...values) {
303
+ const value = values.find(it => !isEmptyOrSpaces(it));
304
+ return value == null ? undefined : value.trim();
305
+ }
306
+ function normalizeSquirrelOptions(options) {
275
307
  for (const name of ["outputDirectory", "appDirectory", "exe", "fixUpPaths", "usePackageJson", "extraFileSpecs", "extraMetadataSpecs", "skipUpdateIcon", "setupExe"]) {
276
308
  if (name in options) {
277
309
  throw new InvalidConfigurationError(`Option ${name} is ignored, do not specify it.`);
@@ -1 +1 @@
1
- {"version":3,"file":"SquirrelWindowsTarget.js","sourceRoot":"","sources":["../src/SquirrelWindowsTarget.ts"],"names":[],"mappings":"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","sourcesContent":["import { createRequire } from \"node:module\"\nimport { InvalidConfigurationError, log, isEmptyOrSpaces, exists } from \"builder-util\"\n\nconst _requireResolve = createRequire(import.meta.url).resolve\nimport { downloadBuilderToolset, withToolsetLock } from \"app-builder-lib/internal\"\nimport { sanitizeFileName } from \"builder-util/internal\"\nimport { Arch, getArchSuffix, SquirrelWindowsOptions, Target, WinPackager } from \"app-builder-lib\"\nimport * as path from \"path\"\nimport * as fs from \"fs\"\nimport * as os from \"os\"\nimport { Options as SquirrelOptions, createWindowsInstaller, convertVersion } from \"electron-winstaller\"\nimport { WineVmManager } from \"app-builder-lib/internal\"\n\nexport default class SquirrelWindowsTarget extends Target {\n readonly options: SquirrelWindowsOptions\n\n isAsyncSupported = false\n\n constructor(\n private readonly packager: WinPackager,\n readonly outDir: string\n ) {\n super(\"squirrel\")\n this.options = packager.getOptionsForTarget<SquirrelWindowsOptions>(\"squirrelWindows\")\n }\n\n private async prepareSignedVendorDirectory(): Promise<string> {\n const customSquirrelVendorDirectory = this.options.customSquirrelVendorDir\n const tmpVendorDirectory = await this.packager.tempDirManager.createTempDir({ prefix: \"squirrel-windows-vendor\" })\n\n if (customSquirrelVendorDirectory && (await exists(customSquirrelVendorDirectory))) {\n await fs.promises.cp(customSquirrelVendorDirectory, tmpVendorDirectory, { recursive: true })\n } else {\n if (!isEmptyOrSpaces(customSquirrelVendorDirectory)) {\n log.warn({ customSquirrelVendorDirectory }, \"unable to access custom Squirrel.Windows vendor directory, falling back to default vendor\")\n }\n\n const windowInstallerPackage = _requireResolve(\"electron-winstaller/package.json\")\n const [squirrelBin] = await Promise.all([\n downloadBuilderToolset({\n releaseName: \"squirrel.windows@1.0.0\",\n filenameWithExt: \"squirrel.windows-2.0.1-patched.7z\",\n checksums: { \"squirrel.windows-2.0.1-patched.7z\": \"76851f0c192eaf9bc6f8f3eecdfe325857ebe70d7833ec62ed846a1acd50c846\" },\n }),\n fs.promises.cp(path.join(path.dirname(windowInstallerPackage), \"vendor\"), tmpVendorDirectory, { recursive: true }),\n ])\n\n await fs.promises.cp(path.join(squirrelBin, \"electron-winstaller\", \"vendor\"), tmpVendorDirectory, { recursive: true })\n }\n\n const files = await fs.promises.readdir(tmpVendorDirectory)\n const squirrelExe = files.find(f => f === \"Squirrel.exe\")\n if (squirrelExe) {\n const filePath = path.join(tmpVendorDirectory, squirrelExe)\n log.debug({ file: filePath }, \"signing vendor executable\")\n await this.packager.signIf(filePath)\n } else {\n log.warn(\"Squirrel.exe not found in vendor directory, skipping signing\")\n }\n return tmpVendorDirectory\n }\n\n private assertShellSafePath(filePath: string, description: string): void {\n if (/[\\r\\n`$;&|<>]/.test(filePath)) {\n throw new InvalidConfigurationError(`${description} contains unsafe shell characters: ${filePath}`)\n }\n }\n\n private async ensurePathInside(baseDir: string, targetPath: string, description: string): Promise<string> {\n const resolvedBaseDir = path.resolve(baseDir)\n const resolvedTargetPath = path.resolve(targetPath)\n\n let canonicalBaseDir = resolvedBaseDir\n let canonicalTargetPath = resolvedTargetPath\n\n try {\n canonicalBaseDir = await fs.promises.realpath(resolvedBaseDir)\n } catch {\n canonicalBaseDir = resolvedBaseDir\n }\n\n try {\n canonicalTargetPath = await fs.promises.realpath(resolvedTargetPath)\n } catch {\n // Target may not exist yet; resolve the parent to handle symlinks/junctions consistently\n try {\n const resolvedTargetParent = path.dirname(resolvedTargetPath)\n const canonicalTargetParent = await fs.promises.realpath(resolvedTargetParent)\n const relativeFromResolvedParent = path.relative(resolvedTargetParent, resolvedTargetPath)\n if (\n isEmptyOrSpaces(relativeFromResolvedParent) ||\n path.isAbsolute(relativeFromResolvedParent) ||\n relativeFromResolvedParent.split(path.sep).includes(\"..\") ||\n /[\\0\\r\\n]/.test(relativeFromResolvedParent)\n ) {\n throw new InvalidConfigurationError(`${description} contains invalid path segments`)\n }\n canonicalTargetPath = path.resolve(canonicalTargetParent, relativeFromResolvedParent)\n } catch {\n canonicalTargetPath = resolvedTargetPath\n }\n }\n\n const relativePath = path.relative(canonicalBaseDir, canonicalTargetPath)\n if (relativePath.startsWith(\"..\") || path.isAbsolute(relativePath)) {\n throw new InvalidConfigurationError(`${description} must be inside ${canonicalBaseDir}`)\n }\n this.assertShellSafePath(canonicalTargetPath, description)\n return canonicalTargetPath\n }\n\n private async generateStubExecutableExe(appOutDir: string, vendorDir: string) {\n if (!path.isAbsolute(appOutDir) || !path.isAbsolute(vendorDir)) {\n throw new InvalidConfigurationError(\"appOutDir and vendorDir must be absolute paths\")\n }\n\n const files = await fs.promises.readdir(appOutDir, { withFileTypes: true })\n const appExe = files.find(f => f.name === `${this.exeName}.exe`)\n if (!appExe) {\n throw new Error(`App executable not found in app directory: ${appOutDir}`)\n }\n\n const filePath = await this.ensurePathInside(appOutDir, path.join(appOutDir, appExe.name), \"App executable path\")\n const stubExePath = await this.ensurePathInside(appOutDir, path.join(appOutDir, `${this.exeName}_ExecutionStub.exe`), \"Stub executable path\")\n const stubExecutableSource = await this.ensurePathInside(vendorDir, path.join(vendorDir, \"StubExecutable.exe\"), \"Stub executable source\")\n const writeZipToSetupExe = await this.ensurePathInside(vendorDir, path.join(vendorDir, \"WriteZipToSetup.exe\"), \"WriteZipToSetup executable\")\n\n await fs.promises.copyFile(stubExecutableSource, stubExePath)\n const wineVm = new WineVmManager(this.packager.config.toolsets?.wine, this.packager.buildResourcesDir)\n await wineVm.exec(writeZipToSetupExe, [\"--copy-stub-resources\", filePath, stubExePath])\n await this.packager.signIf(stubExePath)\n log.debug({ file: filePath }, \"signing app executable\")\n await this.packager.signIf(filePath)\n }\n\n async build(appOutDir: string, arch: Arch) {\n const packager = this.packager\n const version = packager.appInfo.version\n const sanitizedName = sanitizeFileName(this.appName)\n\n const setupFile = packager.expandArtifactNamePattern(this.options, \"exe\", arch, \"${productName} Setup ${version}.${ext}\")\n const installerOutDir = path.join(this.outDir, `squirrel-windows${getArchSuffix(arch)}`)\n const artifactPath = path.join(installerOutDir, setupFile)\n const msiArtifactPath = path.join(installerOutDir, packager.expandArtifactNamePattern(this.options, \"msi\", arch, \"${productName} Setup ${version}.${ext}\"))\n\n this.buildQueueManager.add(async () => {\n await packager.emitArtifactBuildStarted({\n targetPresentableName: \"Squirrel.Windows\",\n file: artifactPath,\n arch,\n })\n const distOptions = await this.computeEffectiveDistOptions(appOutDir, installerOutDir, setupFile)\n await this.generateStubExecutableExe(appOutDir, distOptions.vendorDirectory!)\n await withToolsetLock(() => createWindowsInstaller(distOptions))\n\n await packager.signAndEditResources(artifactPath, arch, installerOutDir)\n\n if (this.options.msi) {\n await packager.signIf(msiArtifactPath)\n }\n\n const safeArtifactName = (ext: string) => `${sanitizedName}-Setup-${version}${getArchSuffix(arch)}.${ext}`\n\n await packager.emitArtifactBuildCompleted({\n file: artifactPath,\n target: this,\n arch,\n safeArtifactName: safeArtifactName(\"exe\"),\n packager: this.packager,\n })\n\n if (this.options.msi) {\n await packager.emitArtifactCreated({\n file: msiArtifactPath,\n target: this,\n arch,\n safeArtifactName: safeArtifactName(\"msi\"),\n packager: this.packager,\n })\n }\n\n const packagePrefix = `${this.appName}-${convertVersion(version)}-`\n await packager.emitArtifactCreated({\n file: path.join(installerOutDir, `${packagePrefix}full.nupkg`),\n target: this,\n arch,\n packager,\n })\n if (distOptions.remoteReleases != null) {\n await packager.emitArtifactCreated({\n file: path.join(installerOutDir, `${packagePrefix}delta.nupkg`),\n target: this,\n arch,\n packager,\n })\n }\n\n await packager.emitArtifactCreated({\n file: path.join(installerOutDir, \"RELEASES\"),\n target: this,\n arch,\n packager,\n })\n })\n return Promise.resolve()\n }\n\n private get appName() {\n return this.options.name || this.packager.appInfo.name\n }\n\n private get exeName() {\n const name = this.packager.appInfo.productFilename || this.options.name || this.packager.appInfo.productName\n return sanitizeFileName(name)\n }\n\n private select7zipArch(vendorDirectory: string) {\n // https://github.com/electron/windows-installer/blob/main/script/select-7z-arch.js\n // Even if we're cross-compiling for a different arch like arm64,\n // we still need to use the 7-Zip executable for the host arch\n const resolvedArch = os.arch\n fs.copyFileSync(path.join(vendorDirectory, `7z-${resolvedArch}.exe`), path.join(vendorDirectory, \"7z.exe\"))\n fs.copyFileSync(path.join(vendorDirectory, `7z-${resolvedArch}.dll`), path.join(vendorDirectory, \"7z.dll\"))\n }\n\n private async createNuspecTemplateWithProjectUrl() {\n const templatePath = path.resolve(import.meta.dirname, \"..\", \"template.nuspectemplate\")\n const projectUrl = await this.packager.appInfo.computePackageUrl()\n if (projectUrl != null) {\n const nuspecTemplate = await this.packager.tempDirManager.getTempFile({ prefix: \"template\", suffix: \".nuspectemplate\" })\n let templateContent = await fs.promises.readFile(templatePath, \"utf8\")\n const searchString = \"<copyright><%- copyright %></copyright>\"\n templateContent = templateContent.replace(searchString, `${searchString}\\n <projectUrl>${projectUrl}</projectUrl>`)\n await fs.promises.writeFile(nuspecTemplate, templateContent)\n return nuspecTemplate\n }\n return templatePath\n }\n\n async computeEffectiveDistOptions(appDirectory: string, outputDirectory: string, setupFile: string): Promise<SquirrelOptions> {\n const packager = this.packager\n let iconUrl = this.options.iconUrl\n if (iconUrl == null) {\n const info = await packager.repositoryInfo\n if (info != null) {\n iconUrl = `https://github.com/${info.user}/${info.project}/blob/master/${packager.relativeBuildResourcesDirname}/icon.ico?raw=true`\n }\n\n if (iconUrl == null) {\n throw new InvalidConfigurationError(\"squirrelWindows.iconUrl is not specified, please see https://www.electron.build/squirrel-windows#SquirrelWindowsOptions-iconUrl\")\n }\n }\n\n checkConflictingOptions(this.options)\n const appInfo = packager.appInfo\n const options: SquirrelOptions = {\n appDirectory: appDirectory,\n outputDirectory: outputDirectory,\n name: this.options.useAppIdAsId ? appInfo.id : this.appName,\n title: appInfo.productName || appInfo.name,\n version: appInfo.version,\n description: appInfo.description,\n exe: `${this.exeName}.exe`,\n authors: appInfo.companyName || \"\",\n nuspecTemplate: await this.createNuspecTemplateWithProjectUrl(),\n iconUrl,\n copyright: appInfo.copyright,\n noMsi: !this.options.msi,\n usePackageJson: false,\n }\n\n options.vendorDirectory = await this.prepareSignedVendorDirectory()\n this.select7zipArch(options.vendorDirectory)\n options.fixUpPaths = true\n options.setupExe = setupFile\n if (this.options.msi) {\n options.setupMsi = setupFile.replace(\".exe\", \".msi\")\n }\n\n if (isEmptyOrSpaces(options.description)) {\n options.description = this.options.name || appInfo.productName\n }\n\n if (options.remoteToken == null) {\n options.remoteToken = process.env.GH_TOKEN || process.env.GITHUB_TOKEN\n }\n\n if (this.options.remoteReleases === true) {\n const info = await packager.repositoryInfo\n if (info == null) {\n log.warn(\"remoteReleases set to true, but cannot get repository info\")\n } else {\n options.remoteReleases = `https://github.com/${info.user}/${info.project}`\n log.info({ remoteReleases: options.remoteReleases }, `remoteReleases is set`)\n }\n } else if (typeof this.options.remoteReleases === \"string\" && !isEmptyOrSpaces(this.options.remoteReleases)) {\n options.remoteReleases = this.options.remoteReleases\n }\n\n if (this.options.loadingGif) {\n options.loadingGif = path.resolve(packager.projectDir, this.options.loadingGif)\n } else {\n const resourceList = await packager.resourceList\n if (resourceList.includes(\"install-spinner.gif\")) {\n options.loadingGif = path.join(packager.buildResourcesDir, \"install-spinner.gif\")\n }\n }\n\n return options\n }\n}\n\nfunction checkConflictingOptions(options: any) {\n for (const name of [\"outputDirectory\", \"appDirectory\", \"exe\", \"fixUpPaths\", \"usePackageJson\", \"extraFileSpecs\", \"extraMetadataSpecs\", \"skipUpdateIcon\", \"setupExe\"]) {\n if (name in options) {\n throw new InvalidConfigurationError(`Option ${name} is ignored, do not specify it.`)\n }\n }\n\n const msi = options.msi\n if (msi != null && typeof msi !== \"boolean\") {\n throw new InvalidConfigurationError(`msi expected to be boolean value, but string '\"${msi}\"' was specified`)\n }\n}\n"]}
1
+ {"version":3,"file":"SquirrelWindowsTarget.js","sourceRoot":"","sources":["../src/SquirrelWindowsTarget.ts"],"names":[],"mappings":"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","sourcesContent":["import { Arch, getArchSuffix, SquirrelWindowsOptions, Target, WinPackager } from \"app-builder-lib\"\nimport { getRceditBundle, withToolsetLock, WineVmManager } from \"app-builder-lib/internal\"\nimport { InvalidConfigurationError, isEmptyOrSpaces, log, escapeForXml, prepareFixedNameWrite } from \"builder-util\"\nimport { sanitizeFileName } from \"builder-util/internal\"\nimport * as fs from \"fs\"\nimport * as os from \"os\"\nimport * as path from \"path\"\nimport { getSquirrelToolsetPath, getWixToolsetPath } from \"./toolset.js\"\nimport { InstallerOptions, convertVersion, createWindowsInstaller } from \"./windowsInstaller.js\"\n\nexport default class SquirrelWindowsTarget extends Target {\n readonly options: SquirrelWindowsOptions\n\n isAsyncSupported = false\n\n constructor(\n private readonly packager: WinPackager,\n readonly outDir: string\n ) {\n super(\"squirrel\")\n this.options = packager.getOptionsForTarget<SquirrelWindowsOptions>(\"squirrelWindows\")\n }\n\n private async prepareSignedVendorDirectory(): Promise<string> {\n const tmpVendorDirectory = await this.packager.tempDirManager.createTempDir({ prefix: \"squirrel-windows-vendor\" })\n\n // The vendor toolset comes from the maintained squirrel.windows bundle. Pin a version or supply a\n // custom/local bundle (e.g. for air-gapped builds) via `toolsets.squirrel` (a ToolsetCustom object).\n const squirrelToolset = await getSquirrelToolsetPath(this.packager.config.toolsets?.squirrel, this.packager.buildResourcesDir)\n await fs.promises.cp(path.join(squirrelToolset, \"electron-winstaller\", \"vendor\"), tmpVendorDirectory, { recursive: true })\n\n // Both Squirrel.exe and Squirrel-Mono.exe shell out to rcedit.exe (via setPEVersionInfoAndIcon)\n // during --releasify to stamp version info and the app icon into Setup.exe, so rcedit must live in\n // the vendor dir on every host — on non-Windows it runs under wine alongside the other Win32 vendor\n // exes (Setup.exe, StubExecutable.exe, …). The bundle omits rcedit, so resolve it from the\n // win-codesign toolset, which already versions and caches it across platforms.\n //\n // getRceditBundle honors the user's `toolsets.winCodeSign` selection, so users retain a bypass if a\n // newer toolset regresses: `\"0.0.0\"` falls back to the legacy winCodeSign-2.6.0 rcedit, a custom\n // toolset object uses their own rcedit, and the default (unset/\"latest\") pulls rcedit-windows-2_0_0.\n const rcedit = await getRceditBundle(this.packager.config.toolsets?.winCodeSign, this.packager.buildResourcesDir)\n // Pick rcedit by host arch (x64 for x64/arm64, x86 only for ia32). On non-Windows it runs under wine:\n // the 32-bit build fails on arm64 macOS even under Rosetta (which translates x64, not x86), so the x64\n // build is required there.\n const rceditExe = os.arch() === \"ia32\" ? rcedit.x86 : rcedit.x64\n await fs.promises.copyFile(rceditExe, path.join(tmpVendorDirectory, \"rcedit.exe\"))\n\n // When building an MSI, Squirrel's createMsiPackage runs candle.exe/light.exe from the vendor dir and\n // reads template.wxs there. The bundle ships neither, so merge the shared WiX toolset (the same\n // candle/light electron-builder's MSI target uses) into the vendor dir, plus the Squirrel MSI template\n // (authored against the v4 namespace this transitional WiX 4 requires).\n if (this.options.msi) {\n const wixToolset = await getWixToolsetPath()\n await fs.promises.cp(wixToolset, tmpVendorDirectory, { recursive: true })\n await fs.promises.copyFile(path.resolve(import.meta.dirname, \"..\", \"template.wxs\"), path.join(tmpVendorDirectory, \"template.wxs\"))\n }\n\n // Squirrel.exe is the core updater binary the bundle always ships; a missing one means a broken\n // vendor toolset. Fail loudly rather than skipping signing — skipping would produce a broken\n // installer and bypass the forceCodeSigning enforcement inside signIf (its awaited promise rejects\n // when the file can't be signed and forceCodeSigning is set).\n const files = await fs.promises.readdir(tmpVendorDirectory)\n if (!files.includes(\"Squirrel.exe\")) {\n throw new Error(`Squirrel.exe not found in vendor directory: ${tmpVendorDirectory}`)\n }\n const squirrelExePath = path.join(tmpVendorDirectory, \"Squirrel.exe\")\n log.debug({ file: squirrelExePath }, \"signing vendor executable\")\n await this.packager.signIf(squirrelExePath)\n return tmpVendorDirectory\n }\n\n private assertShellSafePath(filePath: string, description: string): void {\n if (/[\\r\\n\\0`$;&|<>]/.test(filePath)) {\n throw new InvalidConfigurationError(`${description} contains unsafe shell characters: ${filePath}`)\n }\n }\n\n private async ensurePathInside(baseDir: string, targetPath: string, description: string): Promise<string> {\n const resolvedBaseDir = path.resolve(baseDir)\n const resolvedTargetPath = path.resolve(targetPath)\n\n let canonicalBaseDir = resolvedBaseDir\n let canonicalTargetPath = resolvedTargetPath\n\n try {\n canonicalBaseDir = await fs.promises.realpath(resolvedBaseDir)\n } catch {\n canonicalBaseDir = resolvedBaseDir\n }\n\n try {\n canonicalTargetPath = await fs.promises.realpath(resolvedTargetPath)\n } catch {\n // Target may not exist yet; resolve the parent to handle symlinks/junctions consistently\n try {\n const resolvedTargetParent = path.dirname(resolvedTargetPath)\n const canonicalTargetParent = await fs.promises.realpath(resolvedTargetParent)\n const relativeFromResolvedParent = path.relative(resolvedTargetParent, resolvedTargetPath)\n if (\n isEmptyOrSpaces(relativeFromResolvedParent) ||\n path.isAbsolute(relativeFromResolvedParent) ||\n relativeFromResolvedParent.split(path.sep).includes(\"..\") ||\n /[\\0\\r\\n]/.test(relativeFromResolvedParent)\n ) {\n throw new InvalidConfigurationError(`${description} contains invalid path segments`)\n }\n canonicalTargetPath = path.resolve(canonicalTargetParent, relativeFromResolvedParent)\n } catch (e: unknown) {\n // Only fall back for filesystem errors (target parent not found, permission, etc.).\n // Validation errors must propagate so callers get an actionable message.\n if (e instanceof InvalidConfigurationError) {\n throw e\n }\n canonicalTargetPath = resolvedTargetPath\n }\n }\n\n const relativePath = path.relative(canonicalBaseDir, canonicalTargetPath)\n if (relativePath.startsWith(\"..\") || path.isAbsolute(relativePath)) {\n throw new InvalidConfigurationError(`${description} must be inside ${canonicalBaseDir}`)\n }\n this.assertShellSafePath(canonicalTargetPath, description)\n return canonicalTargetPath\n }\n\n private async generateStubExecutableExe(appOutDir: string, vendorDir: string) {\n if (!path.isAbsolute(appOutDir) || !path.isAbsolute(vendorDir)) {\n throw new InvalidConfigurationError(\"appOutDir and vendorDir must be absolute paths\")\n }\n\n const files = await fs.promises.readdir(appOutDir, { withFileTypes: true })\n const appExe = files.find(f => f.name === `${this.exeName}.exe`)\n if (!appExe) {\n throw new Error(`App executable not found in app directory: ${appOutDir}`)\n }\n\n const filePath = await this.ensurePathInside(appOutDir, path.join(appOutDir, appExe.name), \"App executable path\")\n // a symlink at the name, from the copied app files, is replaced rather than resolved onto another file of the app\n await prepareFixedNameWrite(appOutDir, path.join(appOutDir, `${this.exeName}_ExecutionStub.exe`), \"Squirrel execution stub\")\n const stubExePath = await this.ensurePathInside(appOutDir, path.join(appOutDir, `${this.exeName}_ExecutionStub.exe`), \"Stub executable path\")\n const stubExecutableSource = await this.ensurePathInside(vendorDir, path.join(vendorDir, \"StubExecutable.exe\"), \"Stub executable source\")\n const writeZipToSetupExe = await this.ensurePathInside(vendorDir, path.join(vendorDir, \"WriteZipToSetup.exe\"), \"WriteZipToSetup executable\")\n\n await fs.promises.copyFile(stubExecutableSource, stubExePath)\n const wineVm = new WineVmManager(this.packager.config.toolsets?.wine, this.packager.buildResourcesDir)\n await wineVm.exec(writeZipToSetupExe, [\"--copy-stub-resources\", filePath, stubExePath])\n await this.packager.signIf(stubExePath)\n log.debug({ file: filePath }, \"signing app executable\")\n await this.packager.signIf(filePath)\n }\n\n async build(appOutDir: string, arch: Arch) {\n const packager = this.packager\n const version = packager.appInfo.version\n const sanitizedName = sanitizeFileName(this.appName)\n\n const setupFile = packager.expandArtifactNamePattern(this.options, \"exe\", arch, \"${productName} Setup ${version}.${ext}\")\n const installerOutDir = path.join(this.outDir, `squirrel-windows${getArchSuffix(arch)}`)\n const artifactPath = path.join(installerOutDir, setupFile)\n const msiArtifactPath = path.join(installerOutDir, packager.expandArtifactNamePattern(this.options, \"msi\", arch, \"${productName} Setup ${version}.${ext}\"))\n\n this.buildQueueManager.add(async () => {\n await packager.emitArtifactBuildStarted({\n targetPresentableName: \"Squirrel.Windows\",\n file: artifactPath,\n arch,\n })\n const distOptions = await this.computeEffectiveDistOptions(appOutDir, installerOutDir, setupFile)\n await this.generateStubExecutableExe(appOutDir, distOptions.vendorDirectory)\n await withToolsetLock(() => createWindowsInstaller(distOptions))\n\n await packager.signAndEditResources(artifactPath, arch, installerOutDir)\n\n if (this.options.msi) {\n await packager.signIf(msiArtifactPath)\n }\n\n const safeArtifactName = (ext: string) => `${sanitizedName}-Setup-${version}${getArchSuffix(arch)}.${ext}`\n\n await packager.emitArtifactBuildCompleted({\n file: artifactPath,\n target: this,\n arch,\n safeArtifactName: safeArtifactName(\"exe\"),\n packager: this.packager,\n })\n\n if (this.options.msi) {\n await packager.emitArtifactCreated({\n file: msiArtifactPath,\n target: this,\n arch,\n safeArtifactName: safeArtifactName(\"msi\"),\n packager: this.packager,\n })\n }\n\n const packagePrefix = `${this.appName}-${convertVersion(version)}-`\n await packager.emitArtifactCreated({\n file: path.join(installerOutDir, `${packagePrefix}full.nupkg`),\n target: this,\n arch,\n packager,\n })\n if (distOptions.remoteReleases != null) {\n await packager.emitArtifactCreated({\n file: path.join(installerOutDir, `${packagePrefix}delta.nupkg`),\n target: this,\n arch,\n packager,\n })\n }\n\n await packager.emitArtifactCreated({\n file: path.join(installerOutDir, \"RELEASES\"),\n target: this,\n arch,\n packager,\n })\n })\n return Promise.resolve()\n }\n\n private get appName() {\n return this.options.name || this.packager.appInfo.name\n }\n\n private get exeName() {\n const name = this.packager.appInfo.productFilename || this.options.name || this.packager.appInfo.productName\n return sanitizeFileName(name)\n }\n\n private select7zipArch(vendorDirectory: string) {\n // https://github.com/electron/windows-installer/blob/main/script/select-7z-arch.js\n // Even if we're cross-compiling for a different arch like arm64,\n // we still need to use the 7-Zip executable for the host arch.\n // When arch-specific variants aren't present (vendor bundle ships a pre-selected 7z.exe),\n // skip the copy — the bundle's 7z.exe is already correct.\n const resolvedArch = os.arch()\n const archExe = path.join(vendorDirectory, `7z-${resolvedArch}.exe`)\n const archDll = path.join(vendorDirectory, `7z-${resolvedArch}.dll`)\n if (fs.existsSync(archExe)) {\n fs.copyFileSync(archExe, path.join(vendorDirectory, \"7z.exe\"))\n }\n if (fs.existsSync(archDll)) {\n fs.copyFileSync(archDll, path.join(vendorDirectory, \"7z.dll\"))\n }\n }\n\n private async createNuspecTemplateWithProjectUrl() {\n const templatePath = path.resolve(import.meta.dirname, \"..\", \"template.nuspectemplate\")\n const projectUrl = await this.packager.appInfo.computePackageUrl()\n if (projectUrl != null) {\n const nuspecTemplate = await this.packager.tempDirManager.getTempFile({ prefix: \"template\", suffix: \".nuspectemplate\" })\n let templateContent = await fs.promises.readFile(templatePath, \"utf8\")\n templateContent = addProjectUrl(templateContent, projectUrl)\n await fs.promises.writeFile(nuspecTemplate, templateContent)\n return nuspecTemplate\n }\n return templatePath\n }\n\n async computeEffectiveDistOptions(appDirectory: string, outputDirectory: string, setupFile: string): Promise<InstallerOptions> {\n const packager = this.packager\n let iconUrl = this.options.iconUrl\n if (iconUrl == null) {\n const info = await packager.repositoryInfo\n if (info != null) {\n iconUrl = `https://github.com/${info.user}/${info.project}/blob/master/${packager.relativeBuildResourcesDirname}/icon.ico?raw=true`\n }\n\n if (iconUrl == null) {\n throw new InvalidConfigurationError(\"squirrelWindows.iconUrl is not specified, please see https://www.electron.build/squirrel-windows#SquirrelWindowsOptions-iconUrl\")\n }\n }\n\n normalizeSquirrelOptions(this.options)\n const appInfo = packager.appInfo\n\n const description = isEmptyOrSpaces(appInfo.description) ? this.options.name || appInfo.productName : appInfo.description\n\n let remoteReleases: string | undefined\n if (this.options.remoteReleases === true) {\n const info = await packager.repositoryInfo\n if (info == null) {\n log.warn(\"remoteReleases set to true, but cannot get repository info\")\n } else {\n remoteReleases = `https://github.com/${info.user}/${info.project}`\n log.info({ remoteReleases }, `remoteReleases is set`)\n }\n } else if (typeof this.options.remoteReleases === \"string\" && !isEmptyOrSpaces(this.options.remoteReleases)) {\n remoteReleases = this.options.remoteReleases\n }\n\n let loadingGif: string\n if (this.options.loadingGif) {\n loadingGif = path.resolve(packager.projectDir, this.options.loadingGif)\n } else {\n // User-supplied buildResources gif wins; otherwise fall back to the bundled default spinner —\n // parity with electron-winstaller, which always supplied resources/install-spinner.gif when none\n // was configured (a fresh-install progress animation; never omitted).\n loadingGif = (await packager.getResource(undefined, \"install-spinner.gif\")) ?? path.resolve(import.meta.dirname, \"..\", \"install-spinner.gif\")\n }\n\n const vendorDirectory = await this.prepareSignedVendorDirectory()\n this.select7zipArch(vendorDirectory)\n\n return {\n appDirectory,\n outputDirectory,\n vendorDirectory,\n name: this.options.useAppIdAsId ? appInfo.id : this.appName,\n title: appInfo.productName || appInfo.name,\n version: appInfo.version,\n description,\n exe: `${this.exeName}.exe`,\n authors: appInfo.companyName || \"\",\n nuspecTemplate: await this.createNuspecTemplateWithProjectUrl(),\n iconUrl,\n copyright: appInfo.copyright,\n msi: this.options.msi,\n fixUpPaths: true,\n setupExe: setupFile,\n setupMsi: this.options.msi ? setupFile.replace(/\\.exe$/i, \".msi\") : undefined,\n loadingGif,\n remoteReleases,\n remoteToken: firstNonBlank(this.options.remoteToken, process.env.GH_TOKEN, process.env.GITHUB_TOKEN),\n createTempDir: opts => this.packager.tempDirManager.createTempDir(opts),\n externalLinks: await packager.getExternalLinkPolicy(),\n }\n }\n}\n\n/** @internal */\nexport function addProjectUrl(template: string, projectUrl: string): string {\n const searchString = \"<copyright><%- copyright %></copyright>\"\n return template.replace(searchString, `${searchString}\\n <projectUrl>${escapeForXml(projectUrl)}</projectUrl>`)\n}\n\n// `remoteToken: \"\"` (or whitespace) in the config counts as unset: fall through to the environment\n// instead of shadowing GH_TOKEN/GITHUB_TOKEN with a value SyncReleases would drop anyway.\nfunction firstNonBlank(...values: Array<string | null | undefined>): string | undefined {\n const value = values.find(it => !isEmptyOrSpaces(it))\n return value == null ? undefined : value.trim()\n}\n\nfunction normalizeSquirrelOptions(options: any) {\n for (const name of [\"outputDirectory\", \"appDirectory\", \"exe\", \"fixUpPaths\", \"usePackageJson\", \"extraFileSpecs\", \"extraMetadataSpecs\", \"skipUpdateIcon\", \"setupExe\"]) {\n if (name in options) {\n throw new InvalidConfigurationError(`Option ${name} is ignored, do not specify it.`)\n }\n }\n\n const msi = options.msi\n if (msi != null && typeof msi !== \"boolean\") {\n throw new InvalidConfigurationError(`msi expected to be boolean value, but string '\"${msi}\"' was specified`)\n }\n}\n"]}
@@ -1 +1,2 @@
1
+ export {};
1
2
  //# sourceMappingURL=indexInternal.d.ts.map
@@ -1,3 +1,3 @@
1
- "use strict";
1
+ export {};
2
2
  // No production cross-package internals yet.
3
3
  //# sourceMappingURL=indexInternal.js.map
@@ -0,0 +1,22 @@
1
+ import { ToolsetConfig } from "app-builder-lib";
2
+ export declare const squirrelWindowsChecksums: {
3
+ readonly "1.1.1": {
4
+ readonly "squirrel.windows-2.0.1-patched.zip": "77cc2c451639c3b0bd68fde67111f726a236e6750d15f521c79e606fd7119e72";
5
+ };
6
+ };
7
+ /**
8
+ * Returns the path to the squirrel.windows toolset directory. It contains an
9
+ * `electron-winstaller/vendor/` subtree with the Squirrel vendor executables (Squirrel.exe,
10
+ * nuget.exe, SyncReleases.exe, 7z, …).
11
+ *
12
+ * Honors `toolsets.squirrel`: a pinned version (or unset / `"latest"`) downloads the maintained
13
+ * electron-builder-binaries bundle; a {@link ToolsetCustom} object supplies a custom or local bundle
14
+ * (which must mirror the same `electron-winstaller/vendor/` layout).
15
+ */
16
+ export declare function getSquirrelToolsetPath(toolset: ToolsetConfig["squirrel"], resourcesDir: string): Promise<string>;
17
+ /**
18
+ * Returns the path to the WiX toolset directory (candle.exe, light.exe, WixNetFxExtension.dll, …).
19
+ * Only needed when building an MSI.
20
+ */
21
+ export declare function getWixToolsetPath(): Promise<string>;
22
+ //# sourceMappingURL=toolset.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolset.d.ts","sourceRoot":"","sources":["../src/toolset.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAO/C,eAAO,MAAM,wBAAwB;;;;CAI3B,CAAA;AAEV;;;;;;;;GAQG;AACH,wBAAsB,sBAAsB,CAAC,OAAO,EAAE,aAAa,CAAC,UAAU,CAAC,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAoBtH;AAUD;;;GAGG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC,CAMzD"}
@@ -0,0 +1,56 @@
1
+ import { downloadBuilderToolset, getCustomToolsetPath, resolveToolsetVersion } from "app-builder-lib/internal";
2
+ import { InvalidConfigurationError } from "builder-util";
3
+ // Newest squirrel.windows bundle — selected when `toolsets.squirrel` is unset / null / "latest".
4
+ const SQUIRREL_LATEST = "1.1.1";
5
+ export const squirrelWindowsChecksums = {
6
+ "1.1.1": {
7
+ "squirrel.windows-2.0.1-patched.zip": "77cc2c451639c3b0bd68fde67111f726a236e6750d15f521c79e606fd7119e72",
8
+ },
9
+ };
10
+ /**
11
+ * Returns the path to the squirrel.windows toolset directory. It contains an
12
+ * `electron-winstaller/vendor/` subtree with the Squirrel vendor executables (Squirrel.exe,
13
+ * nuget.exe, SyncReleases.exe, 7z, …).
14
+ *
15
+ * Honors `toolsets.squirrel`: a pinned version (or unset / `"latest"`) downloads the maintained
16
+ * electron-builder-binaries bundle; a {@link ToolsetCustom} object supplies a custom or local bundle
17
+ * (which must mirror the same `electron-winstaller/vendor/` layout).
18
+ */
19
+ export async function getSquirrelToolsetPath(toolset, resourcesDir) {
20
+ if (typeof toolset === "object" && toolset != null) {
21
+ return getCustomToolsetPath(toolset, resourcesDir);
22
+ }
23
+ const version = resolveToolsetVersion(toolset, SQUIRREL_LATEST);
24
+ // The `toolsets.squirrel` type and scheme.json only admit known versions, but a programmatic config
25
+ // bypasses both. Never forward an unknown version: without a checksum entry the downloader would run
26
+ // with integrity verification disabled.
27
+ const checksums = squirrelWindowsChecksums[version];
28
+ if (checksums == null) {
29
+ throw new InvalidConfigurationError(`Unknown toolsets.squirrel version "${version}". Known versions: ${Object.keys(squirrelWindowsChecksums).join(", ")} (or "latest"). ` +
30
+ `To use a custom bundle, set toolsets.squirrel to a ToolsetCustom object (url + checksum) instead.`);
31
+ }
32
+ return downloadBuilderToolset({
33
+ releaseName: `squirrel.windows@${version}`,
34
+ filenameWithExt: "squirrel.windows-2.0.1-patched.zip",
35
+ checksums,
36
+ });
37
+ }
38
+ // Squirrel's createMsiPackage (msi: true) runs candle.exe/light.exe with `-ext WixNetFxExtension` from
39
+ // its own vendor dir. The squirrel.windows bundle omits the WiX toolchain, so reuse the shared WiX
40
+ // toolset (the same candle/light electron-builder's MSI target uses) and merge it into the vendor dir.
41
+ // This is a transitional WiX 4 (4.0.0.5512): it accepts the v3-style element structure but requires the
42
+ // v4 namespace, so template.wxs is authored against http://wixtoolset.org/schemas/v4/wxs.
43
+ const WIX_TOOLSET_FILE = "wix-4.0.0.5512.2.7z";
44
+ const WIX_TOOLSET_SHA256 = "fe677fcd837b18c9b912985d91636bbd8a1e800c3b3a6a841b6f96e89624e839";
45
+ /**
46
+ * Returns the path to the WiX toolset directory (candle.exe, light.exe, WixNetFxExtension.dll, …).
47
+ * Only needed when building an MSI.
48
+ */
49
+ export async function getWixToolsetPath() {
50
+ return downloadBuilderToolset({
51
+ releaseName: "wix-4.0.0.5512.2",
52
+ filenameWithExt: WIX_TOOLSET_FILE,
53
+ checksums: { [WIX_TOOLSET_FILE]: WIX_TOOLSET_SHA256 },
54
+ });
55
+ }
56
+ //# sourceMappingURL=toolset.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolset.js","sourceRoot":"","sources":["../src/toolset.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAA;AAC9G,OAAO,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAA;AAExD,iGAAiG;AACjG,MAAM,eAAe,GAAG,OAAO,CAAA;AAE/B,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC,OAAO,EAAE;QACP,oCAAoC,EAAE,kEAAkE;KACzG;CACO,CAAA;AAEV;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,OAAkC,EAAE,YAAoB;IACnG,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,IAAI,IAAI,EAAE,CAAC;QACnD,OAAO,oBAAoB,CAAC,OAAO,EAAE,YAAY,CAAC,CAAA;IACpD,CAAC;IACD,MAAM,OAAO,GAAG,qBAAqB,CAAC,OAAO,EAAE,eAAe,CAAC,CAAA;IAC/D,oGAAoG;IACpG,qGAAqG;IACrG,wCAAwC;IACxC,MAAM,SAAS,GAAI,wBAA4E,CAAC,OAAO,CAAC,CAAA;IACxG,IAAI,SAAS,IAAI,IAAI,EAAE,CAAC;QACtB,MAAM,IAAI,yBAAyB,CACjC,sCAAsC,OAAO,sBAAsB,MAAM,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,kBAAkB;YACnI,mGAAmG,CACtG,CAAA;IACH,CAAC;IACD,OAAO,sBAAsB,CAAC;QAC5B,WAAW,EAAE,oBAAoB,OAAO,EAAE;QAC1C,eAAe,EAAE,oCAAoC;QACrD,SAAS;KACV,CAAC,CAAA;AACJ,CAAC;AAED,uGAAuG;AACvG,mGAAmG;AACnG,uGAAuG;AACvG,wGAAwG;AACxG,0FAA0F;AAC1F,MAAM,gBAAgB,GAAG,qBAAqB,CAAA;AAC9C,MAAM,kBAAkB,GAAG,kEAAkE,CAAA;AAE7F;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACrC,OAAO,sBAAsB,CAAC;QAC5B,WAAW,EAAE,kBAAkB;QAC/B,eAAe,EAAE,gBAAgB;QACjC,SAAS,EAAE,EAAE,CAAC,gBAAgB,CAAC,EAAE,kBAAkB,EAAE;KACtD,CAAC,CAAA;AACJ,CAAC","sourcesContent":["import { ToolsetConfig } from \"app-builder-lib\"\nimport { downloadBuilderToolset, getCustomToolsetPath, resolveToolsetVersion } from \"app-builder-lib/internal\"\nimport { InvalidConfigurationError } from \"builder-util\"\n\n// Newest squirrel.windows bundle — selected when `toolsets.squirrel` is unset / null / \"latest\".\nconst SQUIRREL_LATEST = \"1.1.1\"\n\nexport const squirrelWindowsChecksums = {\n \"1.1.1\": {\n \"squirrel.windows-2.0.1-patched.zip\": \"77cc2c451639c3b0bd68fde67111f726a236e6750d15f521c79e606fd7119e72\",\n },\n} as const\n\n/**\n * Returns the path to the squirrel.windows toolset directory. It contains an\n * `electron-winstaller/vendor/` subtree with the Squirrel vendor executables (Squirrel.exe,\n * nuget.exe, SyncReleases.exe, 7z, …).\n *\n * Honors `toolsets.squirrel`: a pinned version (or unset / `\"latest\"`) downloads the maintained\n * electron-builder-binaries bundle; a {@link ToolsetCustom} object supplies a custom or local bundle\n * (which must mirror the same `electron-winstaller/vendor/` layout).\n */\nexport async function getSquirrelToolsetPath(toolset: ToolsetConfig[\"squirrel\"], resourcesDir: string): Promise<string> {\n if (typeof toolset === \"object\" && toolset != null) {\n return getCustomToolsetPath(toolset, resourcesDir)\n }\n const version = resolveToolsetVersion(toolset, SQUIRREL_LATEST)\n // The `toolsets.squirrel` type and scheme.json only admit known versions, but a programmatic config\n // bypasses both. Never forward an unknown version: without a checksum entry the downloader would run\n // with integrity verification disabled.\n const checksums = (squirrelWindowsChecksums as Partial<Record<string, Record<string, string>>>)[version]\n if (checksums == null) {\n throw new InvalidConfigurationError(\n `Unknown toolsets.squirrel version \"${version}\". Known versions: ${Object.keys(squirrelWindowsChecksums).join(\", \")} (or \"latest\"). ` +\n `To use a custom bundle, set toolsets.squirrel to a ToolsetCustom object (url + checksum) instead.`\n )\n }\n return downloadBuilderToolset({\n releaseName: `squirrel.windows@${version}`,\n filenameWithExt: \"squirrel.windows-2.0.1-patched.zip\",\n checksums,\n })\n}\n\n// Squirrel's createMsiPackage (msi: true) runs candle.exe/light.exe with `-ext WixNetFxExtension` from\n// its own vendor dir. The squirrel.windows bundle omits the WiX toolchain, so reuse the shared WiX\n// toolset (the same candle/light electron-builder's MSI target uses) and merge it into the vendor dir.\n// This is a transitional WiX 4 (4.0.0.5512): it accepts the v3-style element structure but requires the\n// v4 namespace, so template.wxs is authored against http://wixtoolset.org/schemas/v4/wxs.\nconst WIX_TOOLSET_FILE = \"wix-4.0.0.5512.2.7z\"\nconst WIX_TOOLSET_SHA256 = \"fe677fcd837b18c9b912985d91636bbd8a1e800c3b3a6a841b6f96e89624e839\"\n\n/**\n * Returns the path to the WiX toolset directory (candle.exe, light.exe, WixNetFxExtension.dll, …).\n * Only needed when building an MSI.\n */\nexport async function getWixToolsetPath(): Promise<string> {\n return downloadBuilderToolset({\n releaseName: \"wix-4.0.0.5512.2\",\n filenameWithExt: WIX_TOOLSET_FILE,\n checksums: { [WIX_TOOLSET_FILE]: WIX_TOOLSET_SHA256 },\n })\n}\n"]}
@@ -0,0 +1,34 @@
1
+ import { ExternalLinkPolicy } from "builder-util";
2
+ export declare function convertVersion(version: string): string;
3
+ export declare function escapeXml(value: string): string;
4
+ export declare function renderNuspecTemplate(templateContent: string, vars: Record<string, string>): string;
5
+ export declare function buildAdditionalFilesXml(appDirectory: string): Promise<string>;
6
+ export interface InstallerOptions {
7
+ appDirectory: string;
8
+ outputDirectory: string;
9
+ vendorDirectory: string;
10
+ name: string;
11
+ title?: string | null;
12
+ version: string;
13
+ description?: string | null;
14
+ exe: string;
15
+ authors: string;
16
+ owners?: string | null;
17
+ iconUrl?: string | null;
18
+ copyright?: string | null;
19
+ nuspecTemplate: string;
20
+ loadingGif?: string | null;
21
+ msi?: boolean;
22
+ remoteReleases?: string | null;
23
+ remoteToken?: string | null;
24
+ setupExe?: string | null;
25
+ setupMsi?: string | null;
26
+ fixUpPaths?: boolean;
27
+ createTempDir: (options: {
28
+ prefix: string;
29
+ }) => Promise<string>;
30
+ /** The `fileOptions.allowExternalLinks` build option: NuGet stores what a symlink points to, so a symlink that leaves the app fails unless it allows it. */
31
+ externalLinks?: ExternalLinkPolicy | null;
32
+ }
33
+ export declare function createWindowsInstaller(options: InstallerOptions): Promise<void>;
34
+ //# sourceMappingURL=windowsInstaller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"windowsInstaller.d.ts","sourceRoot":"","sources":["../src/windowsInstaller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuC,kBAAkB,EAA8B,MAAM,cAAc,CAAA;AAIlH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAItD;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED,wBAAgB,oBAAoB,CAAC,eAAe,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAElG;AAED,wBAAsB,uBAAuB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAiBnF;AAED,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,MAAM,CAAA;IACpB,eAAe,EAAE,MAAM,CAAA;IACvB,eAAe,EAAE,MAAM,CAAA;IACvB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,GAAG,EAAE,MAAM,CAAA;IACX,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,cAAc,EAAE,MAAM,CAAA;IACtB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,GAAG,CAAC,EAAE,OAAO,CAAA;IACb,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,aAAa,EAAE,CAAC,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;IAC/D,4JAA4J;IAC5J,aAAa,CAAC,EAAE,kBAAkB,GAAG,IAAI,CAAA;CAC1C;AAED,wBAAsB,sBAAsB,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CA0GrF"}
@@ -0,0 +1,113 @@
1
+ import { assertNoSymlinkLeaves, exec, exists, log, prepareFixedNameWrite } from "builder-util";
2
+ import * as fs from "fs/promises";
3
+ import * as path from "path";
4
+ export function convertVersion(version) {
5
+ const parts = version.split("+")[0].split("-");
6
+ const mainVersion = parts.shift();
7
+ return parts.length > 0 ? [mainVersion, parts.join("-").replace(/\./g, "")].join("-") : mainVersion;
8
+ }
9
+ export function escapeXml(value) {
10
+ return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
11
+ }
12
+ export function renderNuspecTemplate(templateContent, vars) {
13
+ return Object.entries(vars).reduce((t, [k, v]) => t.split(`<%- ${k} %>`).join(v), templateContent);
14
+ }
15
+ export async function buildAdditionalFilesXml(appDirectory) {
16
+ const checks = [
17
+ { rel: "swiftshader", src: "swiftshader\\**", target: "lib\\net45\\swiftshader" },
18
+ { rel: "vk_swiftshader_icd.json", src: "vk_swiftshader_icd.json", target: "lib\\net45" },
19
+ ];
20
+ const lines = [];
21
+ for (const { rel, src, target } of checks) {
22
+ try {
23
+ await fs.access(path.join(appDirectory, rel));
24
+ lines.push(` <file src="${src}" target="${target}" />`);
25
+ }
26
+ catch (e) {
27
+ if (e?.code !== "ENOENT") {
28
+ throw e;
29
+ }
30
+ }
31
+ }
32
+ return lines.join("\n");
33
+ }
34
+ export async function createWindowsInstaller(options) {
35
+ const { appDirectory, outputDirectory, vendorDirectory, name, version, exe, nuspecTemplate, loadingGif, msi, remoteReleases, remoteToken, setupExe, setupMsi, fixUpPaths = false, createTempDir, externalLinks, } = options;
36
+ const useMono = process.platform !== "win32";
37
+ if (useMono) {
38
+ log.warn("building Squirrel.Windows on non-Windows requires mono in PATH; spawn will fail if it is missing");
39
+ }
40
+ // Squirrel.exe must live in the app directory so the nuspec can reference it
41
+ // into the app output directory, which untrusted files were copied into: replace, never follow, a symlink at the name
42
+ const squirrelExe = path.join(appDirectory, "Squirrel.exe");
43
+ await prepareFixedNameWrite(appDirectory, squirrelExe, "Squirrel.exe");
44
+ await fs.copyFile(path.join(vendorDirectory, "Squirrel.exe"), squirrelExe);
45
+ const nugetVersion = convertVersion(version);
46
+ const authors = options.authors || "";
47
+ const copyright = options.copyright || `Copyright © ${new Date().getFullYear()} ${authors}`;
48
+ const owners = options.owners || authors;
49
+ let additionalFilesXml = await buildAdditionalFilesXml(appDirectory);
50
+ let templateContent = await fs.readFile(nuspecTemplate, "utf8");
51
+ if (path.sep === "/") {
52
+ templateContent = templateContent.replace(/\\/g, "/");
53
+ additionalFilesXml = additionalFilesXml.replace(/\\/g, "/");
54
+ }
55
+ const nuspecContent = renderNuspecTemplate(templateContent, {
56
+ name: escapeXml(name),
57
+ title: escapeXml(options.title || name),
58
+ version: escapeXml(nugetVersion),
59
+ authors: escapeXml(authors),
60
+ owners: escapeXml(owners),
61
+ iconUrl: escapeXml(options.iconUrl || ""),
62
+ description: escapeXml(options.description || options.title || name),
63
+ copyright: escapeXml(copyright),
64
+ exe: escapeXml(exe),
65
+ additionalFilesXml,
66
+ });
67
+ const nugetOutput = await createTempDir({ prefix: "squirrel-nuget-" });
68
+ const nuspecPath = path.join(nugetOutput, `${name}.nuspec`);
69
+ await fs.writeFile(nuspecPath, nuspecContent);
70
+ const nugetExe = path.join(vendorDirectory, "nuget.exe");
71
+ // NuGet stores what a symlink points to: one that leaves the app would package files from elsewhere on the build machine
72
+ await assertNoSymlinkLeaves(appDirectory, "the Squirrel.Windows NuGet package", externalLinks);
73
+ const nugetArgs = ["pack", nuspecPath, "-BasePath", appDirectory, "-OutputDirectory", nugetOutput, "-NoDefaultExcludes"];
74
+ await (useMono ? exec("mono", [nugetExe, ...nugetArgs]) : exec(nugetExe, nugetArgs));
75
+ const nupkgPath = path.join(nugetOutput, `${name}.${nugetVersion}.nupkg`);
76
+ if (remoteReleases) {
77
+ const syncReleasesExe = path.join(vendorDirectory, "SyncReleases.exe");
78
+ const syncArgs = ["-u", remoteReleases, "-r", outputDirectory];
79
+ if (remoteToken) {
80
+ syncArgs.push("-t", remoteToken);
81
+ }
82
+ await (useMono ? exec("mono", [syncReleasesExe, ...syncArgs]) : exec(syncReleasesExe, syncArgs));
83
+ }
84
+ const releasifyArgs = ["--releasify", nupkgPath, "--releaseDir", outputDirectory];
85
+ if (loadingGif) {
86
+ releasifyArgs.push("--loadingGif", loadingGif);
87
+ }
88
+ if (!msi) {
89
+ releasifyArgs.push("--no-msi");
90
+ }
91
+ if (useMono) {
92
+ await exec("mono", [path.join(vendorDirectory, "Squirrel-Mono.exe"), ...releasifyArgs]);
93
+ }
94
+ else {
95
+ await exec(path.join(vendorDirectory, "Squirrel.exe"), releasifyArgs);
96
+ }
97
+ if (fixUpPaths) {
98
+ if (setupExe) {
99
+ await fs.rename(path.join(outputDirectory, "Setup.exe"), path.join(outputDirectory, setupExe));
100
+ }
101
+ if (setupMsi) {
102
+ // setupMsi is only set when MSI output was requested (msi: true), so releasify ran without
103
+ // --no-msi and Setup.msi must exist. A missing file here is a real failure, not an expected
104
+ // absence — surface it instead of silently dropping the artifact.
105
+ const setupMsiPath = path.join(outputDirectory, "Setup.msi");
106
+ if (!(await exists(setupMsiPath))) {
107
+ throw new Error(`MSI output was requested but Squirrel.Windows did not produce ${setupMsiPath}`);
108
+ }
109
+ await fs.rename(setupMsiPath, path.join(outputDirectory, setupMsi));
110
+ }
111
+ }
112
+ }
113
+ //# sourceMappingURL=windowsInstaller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"windowsInstaller.js","sourceRoot":"","sources":["../src/windowsInstaller.ts"],"names":[],"mappings":"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","sourcesContent":["import { assertNoSymlinkLeaves, exec, exists, ExternalLinkPolicy, log, prepareFixedNameWrite } from \"builder-util\"\nimport * as fs from \"fs/promises\"\nimport * as path from \"path\"\n\nexport function convertVersion(version: string): string {\n const parts = version.split(\"+\")[0].split(\"-\")\n const mainVersion = parts.shift()\n return parts.length > 0 ? [mainVersion, parts.join(\"-\").replace(/\\./g, \"\")].join(\"-\") : mainVersion!\n}\n\nexport function escapeXml(value: string): string {\n return value.replace(/&/g, \"&amp;\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\").replace(/\"/g, \"&quot;\").replace(/'/g, \"&apos;\")\n}\n\nexport function renderNuspecTemplate(templateContent: string, vars: Record<string, string>): string {\n return Object.entries(vars).reduce((t, [k, v]) => t.split(`<%- ${k} %>`).join(v), templateContent)\n}\n\nexport async function buildAdditionalFilesXml(appDirectory: string): Promise<string> {\n const checks: Array<{ rel: string; src: string; target: string }> = [\n { rel: \"swiftshader\", src: \"swiftshader\\\\**\", target: \"lib\\\\net45\\\\swiftshader\" },\n { rel: \"vk_swiftshader_icd.json\", src: \"vk_swiftshader_icd.json\", target: \"lib\\\\net45\" },\n ]\n const lines: string[] = []\n for (const { rel, src, target } of checks) {\n try {\n await fs.access(path.join(appDirectory, rel))\n lines.push(` <file src=\"${src}\" target=\"${target}\" />`)\n } catch (e: any) {\n if (e?.code !== \"ENOENT\") {\n throw e\n }\n }\n }\n return lines.join(\"\\n\")\n}\n\nexport interface InstallerOptions {\n appDirectory: string\n outputDirectory: string\n vendorDirectory: string\n name: string\n title?: string | null\n version: string\n description?: string | null\n exe: string\n authors: string\n owners?: string | null\n iconUrl?: string | null\n copyright?: string | null\n nuspecTemplate: string\n loadingGif?: string | null\n msi?: boolean\n remoteReleases?: string | null\n remoteToken?: string | null\n setupExe?: string | null\n setupMsi?: string | null\n fixUpPaths?: boolean\n createTempDir: (options: { prefix: string }) => Promise<string>\n /** The `fileOptions.allowExternalLinks` build option: NuGet stores what a symlink points to, so a symlink that leaves the app fails unless it allows it. */\n externalLinks?: ExternalLinkPolicy | null\n}\n\nexport async function createWindowsInstaller(options: InstallerOptions): Promise<void> {\n const {\n appDirectory,\n outputDirectory,\n vendorDirectory,\n name,\n version,\n exe,\n nuspecTemplate,\n loadingGif,\n msi,\n remoteReleases,\n remoteToken,\n setupExe,\n setupMsi,\n fixUpPaths = false,\n createTempDir,\n externalLinks,\n } = options\n\n const useMono = process.platform !== \"win32\"\n if (useMono) {\n log.warn(\"building Squirrel.Windows on non-Windows requires mono in PATH; spawn will fail if it is missing\")\n }\n\n // Squirrel.exe must live in the app directory so the nuspec can reference it\n // into the app output directory, which untrusted files were copied into: replace, never follow, a symlink at the name\n const squirrelExe = path.join(appDirectory, \"Squirrel.exe\")\n await prepareFixedNameWrite(appDirectory, squirrelExe, \"Squirrel.exe\")\n await fs.copyFile(path.join(vendorDirectory, \"Squirrel.exe\"), squirrelExe)\n\n const nugetVersion = convertVersion(version)\n const authors = options.authors || \"\"\n const copyright = options.copyright || `Copyright © ${new Date().getFullYear()} ${authors}`\n const owners = options.owners || authors\n let additionalFilesXml = await buildAdditionalFilesXml(appDirectory)\n\n let templateContent = await fs.readFile(nuspecTemplate, \"utf8\")\n if (path.sep === \"/\") {\n templateContent = templateContent.replace(/\\\\/g, \"/\")\n additionalFilesXml = additionalFilesXml.replace(/\\\\/g, \"/\")\n }\n\n const nuspecContent = renderNuspecTemplate(templateContent, {\n name: escapeXml(name),\n title: escapeXml(options.title || name),\n version: escapeXml(nugetVersion),\n authors: escapeXml(authors),\n owners: escapeXml(owners),\n iconUrl: escapeXml(options.iconUrl || \"\"),\n description: escapeXml(options.description || options.title || name),\n copyright: escapeXml(copyright),\n exe: escapeXml(exe),\n additionalFilesXml,\n })\n\n const nugetOutput = await createTempDir({ prefix: \"squirrel-nuget-\" })\n const nuspecPath = path.join(nugetOutput, `${name}.nuspec`)\n await fs.writeFile(nuspecPath, nuspecContent)\n\n const nugetExe = path.join(vendorDirectory, \"nuget.exe\")\n // NuGet stores what a symlink points to: one that leaves the app would package files from elsewhere on the build machine\n await assertNoSymlinkLeaves(appDirectory, \"the Squirrel.Windows NuGet package\", externalLinks)\n const nugetArgs = [\"pack\", nuspecPath, \"-BasePath\", appDirectory, \"-OutputDirectory\", nugetOutput, \"-NoDefaultExcludes\"]\n await (useMono ? exec(\"mono\", [nugetExe, ...nugetArgs]) : exec(nugetExe, nugetArgs))\n\n const nupkgPath = path.join(nugetOutput, `${name}.${nugetVersion}.nupkg`)\n\n if (remoteReleases) {\n const syncReleasesExe = path.join(vendorDirectory, \"SyncReleases.exe\")\n const syncArgs = [\"-u\", remoteReleases, \"-r\", outputDirectory]\n if (remoteToken) {\n syncArgs.push(\"-t\", remoteToken)\n }\n await (useMono ? exec(\"mono\", [syncReleasesExe, ...syncArgs]) : exec(syncReleasesExe, syncArgs))\n }\n\n const releasifyArgs = [\"--releasify\", nupkgPath, \"--releaseDir\", outputDirectory]\n if (loadingGif) {\n releasifyArgs.push(\"--loadingGif\", loadingGif)\n }\n if (!msi) {\n releasifyArgs.push(\"--no-msi\")\n }\n\n if (useMono) {\n await exec(\"mono\", [path.join(vendorDirectory, \"Squirrel-Mono.exe\"), ...releasifyArgs])\n } else {\n await exec(path.join(vendorDirectory, \"Squirrel.exe\"), releasifyArgs)\n }\n\n if (fixUpPaths) {\n if (setupExe) {\n await fs.rename(path.join(outputDirectory, \"Setup.exe\"), path.join(outputDirectory, setupExe))\n }\n if (setupMsi) {\n // setupMsi is only set when MSI output was requested (msi: true), so releasify ran without\n // --no-msi and Setup.msi must exist. A missing file here is a real failure, not an expected\n // absence — surface it instead of silently dropping the artifact.\n const setupMsiPath = path.join(outputDirectory, \"Setup.msi\")\n if (!(await exists(setupMsiPath))) {\n throw new Error(`MSI output was requested but Squirrel.Windows did not produce ${setupMsiPath}`)\n }\n await fs.rename(setupMsiPath, path.join(outputDirectory, setupMsi))\n }\n }\n}\n"]}
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "electron-builder-squirrel-windows",
3
- "version": "27.0.0-alpha.1",
3
+ "version": "27.0.0-alpha.11",
4
4
  "type": "module",
5
5
  "main": "./dist/SquirrelWindowsTarget.js",
6
6
  "exports": {
@@ -26,19 +26,16 @@
26
26
  "homepage": "https://github.com/electron-userland/electron-builder",
27
27
  "files": [
28
28
  "dist",
29
- "template.nuspectemplate"
29
+ "template.nuspectemplate",
30
+ "template.wxs",
31
+ "install-spinner.gif"
30
32
  ],
31
33
  "engines": {
32
34
  "node": ">=22.12.0"
33
35
  },
34
36
  "dependencies": {
35
- "electron-winstaller": "5.4.0",
36
- "app-builder-lib": "27.0.0-alpha.1",
37
- "builder-util": "27.0.0-alpha.0"
38
- },
39
- "devDependencies": {
40
- "@types/archiver": "5.3.1",
41
- "@types/fs-extra": "9.0.13"
37
+ "app-builder-lib": "27.0.0-alpha.11",
38
+ "builder-util": "27.0.0-alpha.11"
42
39
  },
43
40
  "types": "./dist/SquirrelWindowsTarget.d.ts",
44
41
  "scripts": {
@@ -25,8 +25,6 @@
25
25
  <file src="LICENSE.electron.txt" target="lib\net45\LICENSE.electron.txt" />
26
26
  <file src="LICENSES.chromium.html" target="lib\net45\LICENSES.chromium.html" />
27
27
  <file src="<%- exe %>" target="lib\net45\<%- exe %>" />
28
- <% additionalFiles.forEach(function(f) { %>
29
- <file src="<%- f.src %>" target="<%- f.target %>" />
30
- <% }); %>
28
+ <%- additionalFilesXml %>
31
29
  </files>
32
30
  </package>
package/template.wxs ADDED
@@ -0,0 +1,39 @@
1
+ <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2
+ <Product Id="*" Name="{{Title}} Deployment Tool" Language="1033" Codepage="{{Codepage}}" Version="!(bind.FileVersion.{{Id}}.exe)" UpgradeCode="{{IdAsGuid1}}" Manufacturer="{{Author}}">
3
+
4
+ <Package Description="This package installs a deployment tool for {{Title}}. Not {{Title}} itself. {{Title}} is only installed if a user logs into the machine." InstallScope="perMachine" Comments="Comments" InstallerVersion="200" Compressed="yes" Platform="{{Platform}}"/>
5
+ <MajorUpgrade AllowSameVersionUpgrades="yes" DowngradeErrorMessage="A later version of this product is already installed. Setup will now exit."/>
6
+ <Media Id="1" Cabinet="contents.cab" EmbedCab="yes" CompressionLevel="high"/>
7
+
8
+ <PropertyRef Id="NETFRAMEWORK45" />
9
+
10
+ <Condition Message="This application requires .NET Framework 4.5 or higher. Please install the latest .NET Framework then run this installer again.">
11
+ <![CDATA[Installed OR NETFRAMEWORK45]]>
12
+ </Condition>
13
+
14
+ <Directory Id="TARGETDIR" Name="SourceDir">
15
+ <Directory Id="{{ProgramFilesFolder}}">
16
+ <Directory Id="APPLICATIONROOTDIRECTORY" Name="{{Title}} Deployment" />
17
+ </Directory>
18
+ </Directory>
19
+
20
+ <DirectoryRef Id="APPLICATIONROOTDIRECTORY">
21
+ <Component Id="{{Id}}.exe" Guid="{{IdAsGuid2}}" Win64="{{Win64YesNo}}">
22
+ <File Id="{{Id}}.exe" Name="{{Id}}DeploymentTool.exe" Source="./Setup.exe" KeyPath="yes"/>
23
+ </Component>
24
+ </DirectoryRef>
25
+
26
+ <DirectoryRef Id="TARGETDIR">
27
+ <Component Id="RegistryEntries" Guid="{{IdAsGuid3}}" Win64="{{Win64YesNo}}">
28
+ <RegistryKey Root="HKLM" Key="SOFTWARE\Microsoft\Windows\CurrentVersion\Run">
29
+ <RegistryValue Type="expandable" Name="{{Id}}Deployment" Value="&quot;[#{{Id}}.exe]&quot; --checkInstall" />
30
+ </RegistryKey>
31
+ </Component>
32
+ </DirectoryRef>
33
+
34
+ <Feature Id="MainApplication" Title="Main Application" Level="1">
35
+ <ComponentRef Id="{{Id}}.exe" />
36
+ <ComponentRef Id="RegistryEntries" />
37
+ </Feature>
38
+ </Product>
39
+ </Wix>