electron-updater-for-render 1.1.3 → 2.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin/cli.cjs CHANGED
@@ -50,7 +50,8 @@ async function createUpdatePackage(options) {
50
50
  packageJsonPath,
51
51
  privateKeyPath,
52
52
  releaseNotesPath,
53
- forceUpdate
53
+ forceUpdate,
54
+ rolloutRule
54
55
  } = options;
55
56
  if (!import_fs.default.existsSync(outDir)) {
56
57
  throw new Error(`Output directory not found at ${outDir}`);
@@ -100,7 +101,8 @@ async function createUpdatePackage(options) {
100
101
  ...signature ? { signature } : {},
101
102
  date: (/* @__PURE__ */ new Date()).toISOString(),
102
103
  releaseNotes: releaseNotesContent,
103
- ...forceUpdate ? { forceUpdate } : {}
104
+ ...forceUpdate ? { forceUpdate } : {},
105
+ ...rolloutRule ? { rolloutRule } : {}
104
106
  };
105
107
  const jsonPath = import_path.default.join(updatesDir, "latest.json");
106
108
  import_fs.default.writeFileSync(jsonPath, JSON.stringify(updateInfo, null, 2));
package/dist/bin/cli.js CHANGED
@@ -23,7 +23,8 @@ async function createUpdatePackage(options) {
23
23
  packageJsonPath,
24
24
  privateKeyPath,
25
25
  releaseNotesPath,
26
- forceUpdate
26
+ forceUpdate,
27
+ rolloutRule
27
28
  } = options;
28
29
  if (!fs.existsSync(outDir)) {
29
30
  throw new Error(`Output directory not found at ${outDir}`);
@@ -73,7 +74,8 @@ async function createUpdatePackage(options) {
73
74
  ...signature ? { signature } : {},
74
75
  date: (/* @__PURE__ */ new Date()).toISOString(),
75
76
  releaseNotes: releaseNotesContent,
76
- ...forceUpdate ? { forceUpdate } : {}
77
+ ...forceUpdate ? { forceUpdate } : {},
78
+ ...rolloutRule ? { rolloutRule } : {}
77
79
  };
78
80
  const jsonPath = path.join(updatesDir, "latest.json");
79
81
  fs.writeFileSync(jsonPath, JSON.stringify(updateInfo, null, 2));
@@ -52,7 +52,8 @@ async function createUpdatePackage(options) {
52
52
  packageJsonPath,
53
53
  privateKeyPath,
54
54
  releaseNotesPath,
55
- forceUpdate
55
+ forceUpdate,
56
+ rolloutRule
56
57
  } = options;
57
58
  if (!import_fs.default.existsSync(outDir)) {
58
59
  throw new Error(`Output directory not found at ${outDir}`);
@@ -102,7 +103,8 @@ async function createUpdatePackage(options) {
102
103
  ...signature ? { signature } : {},
103
104
  date: (/* @__PURE__ */ new Date()).toISOString(),
104
105
  releaseNotes: releaseNotesContent,
105
- ...forceUpdate ? { forceUpdate } : {}
106
+ ...forceUpdate ? { forceUpdate } : {},
107
+ ...rolloutRule ? { rolloutRule } : {}
106
108
  };
107
109
  const jsonPath = import_path.default.join(updatesDir, "latest.json");
108
110
  import_fs.default.writeFileSync(jsonPath, JSON.stringify(updateInfo, null, 2));
@@ -17,7 +17,8 @@ async function createUpdatePackage(options) {
17
17
  packageJsonPath,
18
18
  privateKeyPath,
19
19
  releaseNotesPath,
20
- forceUpdate
20
+ forceUpdate,
21
+ rolloutRule
21
22
  } = options;
22
23
  if (!fs.existsSync(outDir)) {
23
24
  throw new Error(`Output directory not found at ${outDir}`);
@@ -67,7 +68,8 @@ async function createUpdatePackage(options) {
67
68
  ...signature ? { signature } : {},
68
69
  date: (/* @__PURE__ */ new Date()).toISOString(),
69
70
  releaseNotes: releaseNotesContent,
70
- ...forceUpdate ? { forceUpdate } : {}
71
+ ...forceUpdate ? { forceUpdate } : {},
72
+ ...rolloutRule ? { rolloutRule } : {}
71
73
  };
72
74
  const jsonPath = path.join(updatesDir, "latest.json");
73
75
  fs.writeFileSync(jsonPath, JSON.stringify(updateInfo, null, 2));
@@ -30,7 +30,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/main/index.ts
31
31
  var main_exports = {};
32
32
  __export(main_exports, {
33
- RenderUpdater: () => RenderUpdater
33
+ RenderUpdater: () => RenderUpdater,
34
+ setupUpdaterIPC: () => setupUpdaterIPC
34
35
  });
35
36
  module.exports = __toCommonJS(main_exports);
36
37
  var import_path2 = __toESM(require("path"), 1);
@@ -195,6 +196,7 @@ function verifyFileStream(filePath, info, publicKey) {
195
196
  }
196
197
 
197
198
  // src/main/index.ts
199
+ var import_electron3 = require("electron");
198
200
  var fsPromises = import_original_fs.default.promises;
199
201
  var RenderUpdater = class {
200
202
  versionsDir;
@@ -217,6 +219,9 @@ var RenderUpdater = class {
217
219
  onStatusChanged;
218
220
  onError;
219
221
  onBeforeRestart;
222
+ identity;
223
+ allowPrerelease;
224
+ requestOptions;
220
225
  constructor(options) {
221
226
  console.log("[RenderUpdater] Initializing with versionsDir:", options.versionsDir);
222
227
  this.versionsDir = options.versionsDir;
@@ -234,6 +239,9 @@ var RenderUpdater = class {
234
239
  this.onBeforeRestart = options.onBeforeRestart;
235
240
  this.routerMode = options.routerMode ?? "hash";
236
241
  this.protocolName = options.protocol ?? "app";
242
+ this.identity = options.identity;
243
+ this.allowPrerelease = options.allowPrerelease ?? false;
244
+ this.requestOptions = options.requestOptions;
237
245
  this.download = this.download.bind(this);
238
246
  this.check = this.check.bind(this);
239
247
  this.checkForUpdatesAndNotify = this.checkForUpdatesAndNotify.bind(this);
@@ -333,7 +341,18 @@ var RenderUpdater = class {
333
341
  async check() {
334
342
  let remoteInfo = null;
335
343
  try {
336
- const response = await fetch(`${this.baseUrl}/latest.json?t=${Date.now()}`);
344
+ const fetchUrl = new URL(`${this.baseUrl}/latest.json`);
345
+ fetchUrl.searchParams.append("t", Date.now().toString());
346
+ if (this.requestOptions?.query) {
347
+ for (const [k, v] of Object.entries(this.requestOptions.query)) {
348
+ fetchUrl.searchParams.append(k, v);
349
+ }
350
+ }
351
+ const fetchOpts = {};
352
+ if (this.requestOptions?.headers) {
353
+ fetchOpts.headers = this.requestOptions.headers;
354
+ }
355
+ const response = await fetch(fetchUrl.toString(), fetchOpts);
337
356
  if (response.ok) {
338
357
  remoteInfo = await response.json();
339
358
  }
@@ -343,7 +362,16 @@ var RenderUpdater = class {
343
362
  const runningVersion = this._activeVersion || "0.0.0";
344
363
  const pendingVersion = this._diskVersion || "0.0.0";
345
364
  if (remoteInfo && remoteInfo.version && import_semver.default.valid(remoteInfo.version)) {
346
- if (import_semver.default.gt(remoteInfo.version, pendingVersion)) {
365
+ let allowUpdate = true;
366
+ if (remoteInfo.rolloutRule?.deviceIds) {
367
+ if (!this.identity?.deviceId || !remoteInfo.rolloutRule.deviceIds.includes(this.identity.deviceId)) {
368
+ allowUpdate = false;
369
+ }
370
+ }
371
+ if (allowUpdate && !this.allowPrerelease && import_semver.default.prerelease(remoteInfo.version)) {
372
+ allowUpdate = false;
373
+ }
374
+ if (allowUpdate && import_semver.default.gt(remoteInfo.version, pendingVersion, { includePrerelease: this.allowPrerelease })) {
347
375
  return { updateAvailable: true, version: remoteInfo.version, info: remoteInfo, status: "available" };
348
376
  }
349
377
  }
@@ -368,7 +396,24 @@ var RenderUpdater = class {
368
396
  this.isDownloading = true;
369
397
  try {
370
398
  console.log("[RenderUpdater] download() entry. current this.versionsDir:", this.versionsDir);
371
- const infoToUse = providedInfo || await (await fetch(`${this.baseUrl}/latest.json?t=${Date.now()}`)).json();
399
+ let infoToUse;
400
+ if (providedInfo) {
401
+ infoToUse = providedInfo;
402
+ } else {
403
+ const fetchUrl = new URL(`${this.baseUrl}/latest.json`);
404
+ fetchUrl.searchParams.append("t", Date.now().toString());
405
+ if (this.requestOptions?.query) {
406
+ for (const [k, v] of Object.entries(this.requestOptions.query)) {
407
+ fetchUrl.searchParams.append(k, v);
408
+ }
409
+ }
410
+ const fetchOpts = {};
411
+ if (this.requestOptions?.headers) {
412
+ fetchOpts.headers = this.requestOptions.headers;
413
+ }
414
+ const res = await fetch(fetchUrl.toString(), fetchOpts);
415
+ infoToUse = await res.json();
416
+ }
372
417
  if (!this.versionsDir) throw new Error("[RenderUpdater] CRITICAL: this.versionsDir lost in download.");
373
418
  if (!infoToUse || !infoToUse.version) throw new Error(`[RenderUpdater] CRITICAL: infoToUse or version missing. info: ${JSON.stringify(infoToUse)}`);
374
419
  const versionDir = import_path2.default.join(this.versionsDir, infoToUse.version);
@@ -385,11 +430,12 @@ var RenderUpdater = class {
385
430
  const stats = await fsPromises.stat(tmpAsarPath);
386
431
  downloadedBytes = stats.size;
387
432
  }
388
- const fetchOptions = {};
433
+ const fetchOptions = { headers: {} };
434
+ if (this.requestOptions?.headers) {
435
+ Object.assign(fetchOptions.headers, this.requestOptions.headers);
436
+ }
389
437
  if (downloadedBytes > 0) {
390
- fetchOptions.headers = {
391
- Range: `bytes=${downloadedBytes}-`
392
- };
438
+ fetchOptions.headers["Range"] = `bytes=${downloadedBytes}-`;
393
439
  }
394
440
  const downloadUrl = infoToUse.path ? `${this.baseUrl.replace(/\/$/, "")}/${infoToUse.path}` : infoToUse.url;
395
441
  if (!downloadUrl) throw new Error("[RenderUpdater] Cannot determine download URL: info.path and info.url are both missing.");
@@ -580,7 +626,32 @@ ${info.releaseNotes || "\u65E0\u8BE6\u7EC6\u8BB0\u5F55\u3002"}`,
580
626
  return 0;
581
627
  }
582
628
  };
629
+ function setupUpdaterIPC(updater) {
630
+ import_electron3.ipcMain.handle("updater:check", () => updater.check());
631
+ import_electron3.ipcMain.handle("updater:download", () => updater.download());
632
+ import_electron3.ipcMain.handle("updater:installAndRestart", () => updater.installAndRestart());
633
+ import_electron3.ipcMain.on("updater:useVersion", (_, version) => updater.useVersion(version));
634
+ updater.onDownloadProgress = (percent) => {
635
+ const { webContents } = require("electron");
636
+ webContents.getAllWebContents().forEach((wc) => {
637
+ wc.send("updater:onDownloadProgress", percent);
638
+ });
639
+ };
640
+ updater.onStatusChanged = (status) => {
641
+ const { webContents } = require("electron");
642
+ webContents.getAllWebContents().forEach((wc) => {
643
+ wc.send("updater:onStatusChanged", status);
644
+ });
645
+ };
646
+ updater.onBeforeRestart = () => {
647
+ const { webContents } = require("electron");
648
+ webContents.getAllWebContents().forEach((wc) => {
649
+ wc.send("updater:onBeforeRestart");
650
+ });
651
+ };
652
+ }
583
653
  // Annotate the CommonJS export names for ESM import in node:
584
654
  0 && (module.exports = {
585
- RenderUpdater
655
+ RenderUpdater,
656
+ setupUpdaterIPC
586
657
  });
@@ -21,6 +21,9 @@ export declare class RenderUpdater {
21
21
  }) => void;
22
22
  onError?: (error: Error) => void;
23
23
  onBeforeRestart?: () => void | Promise<void>;
24
+ private identity?;
25
+ private allowPrerelease;
26
+ private requestOptions?;
24
27
  constructor(options: UpdaterOptions);
25
28
  private readCurrentVersionFromFileSync;
26
29
  private cleanOldVersions;
@@ -49,3 +52,4 @@ export declare class RenderUpdater {
49
52
  private showNewUpdateDialog;
50
53
  private showDownloadCompleteDialog;
51
54
  }
55
+ export declare function setupUpdaterIPC(updater: RenderUpdater): void;
@@ -1,3 +1,10 @@
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined") return require.apply(this, arguments);
5
+ throw Error('Dynamic require of "' + x + '" is not supported');
6
+ });
7
+
1
8
  // src/main/index.ts
2
9
  import path2 from "path";
3
10
  import fs2 from "original-fs";
@@ -161,6 +168,7 @@ function verifyFileStream(filePath, info, publicKey) {
161
168
  }
162
169
 
163
170
  // src/main/index.ts
171
+ import { ipcMain } from "electron";
164
172
  var fsPromises = fs2.promises;
165
173
  var RenderUpdater = class {
166
174
  versionsDir;
@@ -183,6 +191,9 @@ var RenderUpdater = class {
183
191
  onStatusChanged;
184
192
  onError;
185
193
  onBeforeRestart;
194
+ identity;
195
+ allowPrerelease;
196
+ requestOptions;
186
197
  constructor(options) {
187
198
  console.log("[RenderUpdater] Initializing with versionsDir:", options.versionsDir);
188
199
  this.versionsDir = options.versionsDir;
@@ -200,6 +211,9 @@ var RenderUpdater = class {
200
211
  this.onBeforeRestart = options.onBeforeRestart;
201
212
  this.routerMode = options.routerMode ?? "hash";
202
213
  this.protocolName = options.protocol ?? "app";
214
+ this.identity = options.identity;
215
+ this.allowPrerelease = options.allowPrerelease ?? false;
216
+ this.requestOptions = options.requestOptions;
203
217
  this.download = this.download.bind(this);
204
218
  this.check = this.check.bind(this);
205
219
  this.checkForUpdatesAndNotify = this.checkForUpdatesAndNotify.bind(this);
@@ -299,7 +313,18 @@ var RenderUpdater = class {
299
313
  async check() {
300
314
  let remoteInfo = null;
301
315
  try {
302
- const response = await fetch(`${this.baseUrl}/latest.json?t=${Date.now()}`);
316
+ const fetchUrl = new URL(`${this.baseUrl}/latest.json`);
317
+ fetchUrl.searchParams.append("t", Date.now().toString());
318
+ if (this.requestOptions?.query) {
319
+ for (const [k, v] of Object.entries(this.requestOptions.query)) {
320
+ fetchUrl.searchParams.append(k, v);
321
+ }
322
+ }
323
+ const fetchOpts = {};
324
+ if (this.requestOptions?.headers) {
325
+ fetchOpts.headers = this.requestOptions.headers;
326
+ }
327
+ const response = await fetch(fetchUrl.toString(), fetchOpts);
303
328
  if (response.ok) {
304
329
  remoteInfo = await response.json();
305
330
  }
@@ -309,7 +334,16 @@ var RenderUpdater = class {
309
334
  const runningVersion = this._activeVersion || "0.0.0";
310
335
  const pendingVersion = this._diskVersion || "0.0.0";
311
336
  if (remoteInfo && remoteInfo.version && semver.valid(remoteInfo.version)) {
312
- if (semver.gt(remoteInfo.version, pendingVersion)) {
337
+ let allowUpdate = true;
338
+ if (remoteInfo.rolloutRule?.deviceIds) {
339
+ if (!this.identity?.deviceId || !remoteInfo.rolloutRule.deviceIds.includes(this.identity.deviceId)) {
340
+ allowUpdate = false;
341
+ }
342
+ }
343
+ if (allowUpdate && !this.allowPrerelease && semver.prerelease(remoteInfo.version)) {
344
+ allowUpdate = false;
345
+ }
346
+ if (allowUpdate && semver.gt(remoteInfo.version, pendingVersion, { includePrerelease: this.allowPrerelease })) {
313
347
  return { updateAvailable: true, version: remoteInfo.version, info: remoteInfo, status: "available" };
314
348
  }
315
349
  }
@@ -334,7 +368,24 @@ var RenderUpdater = class {
334
368
  this.isDownloading = true;
335
369
  try {
336
370
  console.log("[RenderUpdater] download() entry. current this.versionsDir:", this.versionsDir);
337
- const infoToUse = providedInfo || await (await fetch(`${this.baseUrl}/latest.json?t=${Date.now()}`)).json();
371
+ let infoToUse;
372
+ if (providedInfo) {
373
+ infoToUse = providedInfo;
374
+ } else {
375
+ const fetchUrl = new URL(`${this.baseUrl}/latest.json`);
376
+ fetchUrl.searchParams.append("t", Date.now().toString());
377
+ if (this.requestOptions?.query) {
378
+ for (const [k, v] of Object.entries(this.requestOptions.query)) {
379
+ fetchUrl.searchParams.append(k, v);
380
+ }
381
+ }
382
+ const fetchOpts = {};
383
+ if (this.requestOptions?.headers) {
384
+ fetchOpts.headers = this.requestOptions.headers;
385
+ }
386
+ const res = await fetch(fetchUrl.toString(), fetchOpts);
387
+ infoToUse = await res.json();
388
+ }
338
389
  if (!this.versionsDir) throw new Error("[RenderUpdater] CRITICAL: this.versionsDir lost in download.");
339
390
  if (!infoToUse || !infoToUse.version) throw new Error(`[RenderUpdater] CRITICAL: infoToUse or version missing. info: ${JSON.stringify(infoToUse)}`);
340
391
  const versionDir = path2.join(this.versionsDir, infoToUse.version);
@@ -351,11 +402,12 @@ var RenderUpdater = class {
351
402
  const stats = await fsPromises.stat(tmpAsarPath);
352
403
  downloadedBytes = stats.size;
353
404
  }
354
- const fetchOptions = {};
405
+ const fetchOptions = { headers: {} };
406
+ if (this.requestOptions?.headers) {
407
+ Object.assign(fetchOptions.headers, this.requestOptions.headers);
408
+ }
355
409
  if (downloadedBytes > 0) {
356
- fetchOptions.headers = {
357
- Range: `bytes=${downloadedBytes}-`
358
- };
410
+ fetchOptions.headers["Range"] = `bytes=${downloadedBytes}-`;
359
411
  }
360
412
  const downloadUrl = infoToUse.path ? `${this.baseUrl.replace(/\/$/, "")}/${infoToUse.path}` : infoToUse.url;
361
413
  if (!downloadUrl) throw new Error("[RenderUpdater] Cannot determine download URL: info.path and info.url are both missing.");
@@ -546,6 +598,31 @@ ${info.releaseNotes || "\u65E0\u8BE6\u7EC6\u8BB0\u5F55\u3002"}`,
546
598
  return 0;
547
599
  }
548
600
  };
601
+ function setupUpdaterIPC(updater) {
602
+ ipcMain.handle("updater:check", () => updater.check());
603
+ ipcMain.handle("updater:download", () => updater.download());
604
+ ipcMain.handle("updater:installAndRestart", () => updater.installAndRestart());
605
+ ipcMain.on("updater:useVersion", (_, version) => updater.useVersion(version));
606
+ updater.onDownloadProgress = (percent) => {
607
+ const { webContents } = __require("electron");
608
+ webContents.getAllWebContents().forEach((wc) => {
609
+ wc.send("updater:onDownloadProgress", percent);
610
+ });
611
+ };
612
+ updater.onStatusChanged = (status) => {
613
+ const { webContents } = __require("electron");
614
+ webContents.getAllWebContents().forEach((wc) => {
615
+ wc.send("updater:onStatusChanged", status);
616
+ });
617
+ };
618
+ updater.onBeforeRestart = () => {
619
+ const { webContents } = __require("electron");
620
+ webContents.getAllWebContents().forEach((wc) => {
621
+ wc.send("updater:onBeforeRestart");
622
+ });
623
+ };
624
+ }
549
625
  export {
550
- RenderUpdater
626
+ RenderUpdater,
627
+ setupUpdaterIPC
551
628
  };
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/preload/index.ts
21
+ var preload_exports = {};
22
+ __export(preload_exports, {
23
+ exposeUpdaterPreload: () => exposeUpdaterPreload
24
+ });
25
+ module.exports = __toCommonJS(preload_exports);
26
+ function exposeUpdaterPreload(ipcRenderer) {
27
+ return {
28
+ check: () => ipcRenderer.invoke("updater:check"),
29
+ download: () => ipcRenderer.invoke("updater:download"),
30
+ installAndRestart: () => ipcRenderer.invoke("updater:installAndRestart"),
31
+ useVersion: (version) => ipcRenderer.send("updater:useVersion", version),
32
+ // 监听事件
33
+ onDownloadProgress: (callback) => {
34
+ ipcRenderer.on("updater:onDownloadProgress", (_, percent) => callback(percent));
35
+ },
36
+ onStatusChanged: (callback) => {
37
+ ipcRenderer.on("updater:onStatusChanged", (_, data) => callback(data));
38
+ },
39
+ onBeforeRestart: (callback) => {
40
+ ipcRenderer.on("updater:onBeforeRestart", () => callback());
41
+ }
42
+ };
43
+ }
44
+ // Annotate the CommonJS export names for ESM import in node:
45
+ 0 && (module.exports = {
46
+ exposeUpdaterPreload
47
+ });
@@ -0,0 +1,13 @@
1
+ import type { IpcRenderer } from 'electron';
2
+ export declare function exposeUpdaterPreload(ipcRenderer: IpcRenderer): {
3
+ check: () => Promise<any>;
4
+ download: () => Promise<any>;
5
+ installAndRestart: () => Promise<any>;
6
+ useVersion: (version: string) => void;
7
+ onDownloadProgress: (callback: (percent: number) => void) => void;
8
+ onStatusChanged: (callback: (data: {
9
+ status: "ready" | "available" | "idle";
10
+ version: string;
11
+ }) => void) => void;
12
+ onBeforeRestart: (callback: () => void) => void;
13
+ };
@@ -0,0 +1,22 @@
1
+ // src/preload/index.ts
2
+ function exposeUpdaterPreload(ipcRenderer) {
3
+ return {
4
+ check: () => ipcRenderer.invoke("updater:check"),
5
+ download: () => ipcRenderer.invoke("updater:download"),
6
+ installAndRestart: () => ipcRenderer.invoke("updater:installAndRestart"),
7
+ useVersion: (version) => ipcRenderer.send("updater:useVersion", version),
8
+ // 监听事件
9
+ onDownloadProgress: (callback) => {
10
+ ipcRenderer.on("updater:onDownloadProgress", (_, percent) => callback(percent));
11
+ },
12
+ onStatusChanged: (callback) => {
13
+ ipcRenderer.on("updater:onStatusChanged", (_, data) => callback(data));
14
+ },
15
+ onBeforeRestart: (callback) => {
16
+ ipcRenderer.on("updater:onBeforeRestart", () => callback());
17
+ }
18
+ };
19
+ }
20
+ export {
21
+ exposeUpdaterPreload
22
+ };
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/renderer/index.ts
21
+ var renderer_exports = {};
22
+ __export(renderer_exports, {
23
+ getUpdater: () => getUpdater
24
+ });
25
+ module.exports = __toCommonJS(renderer_exports);
26
+ function getUpdater(namespace = "updaterAPI") {
27
+ if (typeof window === "undefined") {
28
+ throw new Error("[RenderUpdater] getUpdater() can only be called in a Browser/Renderer context.");
29
+ }
30
+ const api = window[namespace];
31
+ if (!api) {
32
+ throw new Error(`[RenderUpdater] Cannot find window.${namespace}. Did you forget to call exposeUpdaterPreload in your preload script?`);
33
+ }
34
+ return api;
35
+ }
36
+ // Annotate the CommonJS export names for ESM import in node:
37
+ 0 && (module.exports = {
38
+ getUpdater
39
+ });
@@ -0,0 +1,23 @@
1
+ import type { UpdateInfo } from '../types';
2
+ export interface UpdaterClientAPI {
3
+ check(): Promise<{
4
+ updateAvailable: boolean;
5
+ version?: string;
6
+ info?: UpdateInfo;
7
+ status: 'idle' | 'available' | 'ready';
8
+ }>;
9
+ download(): Promise<void>;
10
+ installAndRestart(): Promise<void>;
11
+ useVersion(version: string): void;
12
+ onDownloadProgress(callback: (percent: number) => void): void;
13
+ onStatusChanged(callback: (data: {
14
+ status: 'ready' | 'available' | 'idle';
15
+ version: string;
16
+ }) => void): void;
17
+ onBeforeRestart(callback: () => void): void;
18
+ }
19
+ /**
20
+ * Ensures the updater preload API is accessible and typed.
21
+ * This should only be used in the renderer process (e.g. standard Vue/React contexts).
22
+ */
23
+ export declare function getUpdater(namespace?: string): UpdaterClientAPI;
@@ -0,0 +1,14 @@
1
+ // src/renderer/index.ts
2
+ function getUpdater(namespace = "updaterAPI") {
3
+ if (typeof window === "undefined") {
4
+ throw new Error("[RenderUpdater] getUpdater() can only be called in a Browser/Renderer context.");
5
+ }
6
+ const api = window[namespace];
7
+ if (!api) {
8
+ throw new Error(`[RenderUpdater] Cannot find window.${namespace}. Did you forget to call exposeUpdaterPreload in your preload script?`);
9
+ }
10
+ return api;
11
+ }
12
+ export {
13
+ getUpdater
14
+ };
package/dist/types.cjs ADDED
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __copyProps = (to, from, except, desc) => {
7
+ if (from && typeof from === "object" || typeof from === "function") {
8
+ for (let key of __getOwnPropNames(from))
9
+ if (!__hasOwnProp.call(to, key) && key !== except)
10
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
11
+ }
12
+ return to;
13
+ };
14
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
15
+
16
+ // src/types.ts
17
+ var types_exports = {};
18
+ module.exports = __toCommonJS(types_exports);
package/dist/types.d.ts CHANGED
@@ -12,6 +12,13 @@ export interface UpdateInfo {
12
12
  * 'silent' - downloads and restarts invisibly on the background.
13
13
  */
14
14
  forceUpdate?: 'prompt' | 'silent';
15
+ /**
16
+ * Defines targeted rollout rules.
17
+ * If not empty, only clients matching the rules will be allowed to update.
18
+ */
19
+ rolloutRule?: {
20
+ deviceIds?: string[];
21
+ };
15
22
  }
16
23
  export interface UpdaterOptions {
17
24
  /**
@@ -23,6 +30,24 @@ export interface UpdaterOptions {
23
30
  * (e.g. app.getPath('userData') + '/versions')
24
31
  */
25
32
  versionsDir: string;
33
+ /**
34
+ * Client identity details for targeted rollouts (e.g. gray release).
35
+ */
36
+ identity?: {
37
+ deviceId?: string;
38
+ };
39
+ /**
40
+ * If true, will allow semver engine to pull prerelease versions (like beta or rc).
41
+ * Default: false
42
+ */
43
+ allowPrerelease?: boolean;
44
+ /**
45
+ * Custom HTTP headers and query params for the check & download requests (useful for auth).
46
+ */
47
+ requestOptions?: {
48
+ headers?: Record<string, string>;
49
+ query?: Record<string, string>;
50
+ };
26
51
  /**
27
52
  * Public key string (PEM format) to verify the RSA signature
28
53
  */
@@ -122,4 +147,10 @@ export interface BuilderOptions {
122
147
  * 'silent': Stealthily apply it in the background.
123
148
  */
124
149
  forceUpdate?: 'prompt' | 'silent';
150
+ /**
151
+ * Rollout whitelist rule for precise targeting during build packing.
152
+ */
153
+ rolloutRule?: {
154
+ deviceIds?: string[];
155
+ };
125
156
  }
package/dist/types.js ADDED
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "electron-updater-for-render",
3
- "version": "1.1.3",
3
+ "version": "2.0.0-beta.1",
4
4
  "description": "A lightweight incremental updater for Electron renderer processes",
5
5
  "type": "module",
6
6
  "bin": {
@@ -15,6 +15,26 @@
15
15
  "import": "./dist/main/index.js",
16
16
  "require": "./dist/main/index.cjs"
17
17
  },
18
+ "./main": {
19
+ "types": "./dist/main/index.d.ts",
20
+ "import": "./dist/main/index.js",
21
+ "require": "./dist/main/index.cjs"
22
+ },
23
+ "./preload": {
24
+ "types": "./dist/preload/index.d.ts",
25
+ "import": "./dist/preload/index.js",
26
+ "require": "./dist/preload/index.cjs"
27
+ },
28
+ "./renderer": {
29
+ "types": "./dist/renderer/index.d.ts",
30
+ "import": "./dist/renderer/index.js",
31
+ "require": "./dist/renderer/index.cjs"
32
+ },
33
+ "./types": {
34
+ "types": "./dist/types.d.ts",
35
+ "import": "./dist/types.js",
36
+ "require": "./dist/types.cjs"
37
+ },
18
38
  "./builder": {
19
39
  "types": "./dist/builder/index.d.ts",
20
40
  "import": "./dist/builder/index.js",