electron-incremental-update 2.0.0-beta.2 → 2.0.0-beta.3

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.
@@ -0,0 +1,43 @@
1
+ import { writeFileSync } from 'node:fs';
2
+ import { brotliDecompress } from 'node:zlib';
3
+ import { createHash, createCipheriv, createSign, createPrivateKey, createDecipheriv, createVerify } from 'node:crypto';
4
+
5
+ // src/utils/unzip.ts
6
+ async function defaultUnzipFile(buffer, targetFilePath) {
7
+ return new Promise((resolve, reject) => {
8
+ brotliDecompress(buffer, (err, buffer2) => {
9
+ if (err) {
10
+ reject(err);
11
+ }
12
+ writeFileSync(targetFilePath, buffer2);
13
+ resolve();
14
+ });
15
+ });
16
+ }
17
+ function hashBuffer(data, length) {
18
+ const hash = createHash("SHA256").update(data).digest("binary");
19
+ return Buffer.from(hash).subarray(0, length);
20
+ }
21
+ function aesEncrypt(plainText, key, iv) {
22
+ const cipher = createCipheriv("aes-256-cbc", key, iv);
23
+ return cipher.update(plainText, "utf8", "base64url") + cipher.final("base64url");
24
+ }
25
+ function defaultSignature(buffer, privateKey, cert, version) {
26
+ const sig = createSign("RSA-SHA256").update(buffer).sign(createPrivateKey(privateKey), "base64");
27
+ return aesEncrypt(`${sig}%${version}`, hashBuffer(cert, 32), hashBuffer(buffer, 16));
28
+ }
29
+ function aesDecrypt(encryptedText, key, iv) {
30
+ const decipher = createDecipheriv("aes-256-cbc", key, iv);
31
+ return decipher.update(encryptedText, "base64url", "utf8") + decipher.final("utf8");
32
+ }
33
+ function defaultVerify(buffer, signature, cert) {
34
+ try {
35
+ const [sig, version] = aesDecrypt(signature, hashBuffer(cert, 32), hashBuffer(buffer, 16)).split("%");
36
+ const result = createVerify("RSA-SHA256").update(buffer).verify(cert, sig, "base64");
37
+ return result ? version : void 0;
38
+ } catch {
39
+ return void 0;
40
+ }
41
+ }
42
+
43
+ export { aesDecrypt, aesEncrypt, defaultSignature, defaultUnzipFile, defaultVerify, hashBuffer };
@@ -0,0 +1,76 @@
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
+
8
+ // src/utils/version.ts
9
+ function handleUnexpectedErrors(callback) {
10
+ process.on("uncaughtException", callback);
11
+ process.on("unhandledRejection", callback);
12
+ }
13
+ function parseVersion(version) {
14
+ const match = /^(\d+)\.(\d+)\.(\d+)(?:-([a-z0-9.-]+))?/i.exec(version);
15
+ if (!match) {
16
+ throw new TypeError(`invalid version: ${version}`);
17
+ }
18
+ const [major, minor, patch] = match.slice(1, 4).map(Number);
19
+ const ret = {
20
+ major,
21
+ minor,
22
+ patch,
23
+ stage: "",
24
+ stageVersion: -1
25
+ };
26
+ if (match[4]) {
27
+ let [stage, _v] = match[4].split(".");
28
+ ret.stage = stage;
29
+ ret.stageVersion = Number(_v) || -1;
30
+ }
31
+ if (Number.isNaN(major) || Number.isNaN(minor) || Number.isNaN(patch) || Number.isNaN(ret.stageVersion)) {
32
+ throw new TypeError(`invalid version: ${version}`);
33
+ }
34
+ return ret;
35
+ }
36
+ function defaultIsLowerVersion(oldVer, newVer) {
37
+ const oldV = parseVersion(oldVer);
38
+ const newV = parseVersion(newVer);
39
+ function compareStrings(str1, str2) {
40
+ if (str1 === "") {
41
+ return str2 !== "";
42
+ } else if (str2 === "") {
43
+ return true;
44
+ }
45
+ return str1 < str2;
46
+ }
47
+ for (let key of Object.keys(oldV)) {
48
+ if (key === "stage" && compareStrings(oldV[key], newV[key])) {
49
+ return true;
50
+ } else if (oldV[key] !== newV[key]) {
51
+ return oldV[key] < newV[key];
52
+ }
53
+ }
54
+ return false;
55
+ }
56
+ function isUpdateJSON(json) {
57
+ const is = (j) => !!(j && j.minimumVersion && j.signature && j.size && j.version);
58
+ return is(json) && is(json?.beta);
59
+ }
60
+ function defaultVersionJsonGenerator(existingJson, buffer, signature, version, minimumVersion) {
61
+ existingJson.beta = {
62
+ version,
63
+ minimumVersion,
64
+ signature,
65
+ size: buffer.length
66
+ };
67
+ if (!parseVersion(version).stage) {
68
+ existingJson.version = version;
69
+ existingJson.minimumVersion = minimumVersion;
70
+ existingJson.signature = signature;
71
+ existingJson.size = buffer.length;
72
+ }
73
+ return existingJson;
74
+ }
75
+
76
+ export { __require, defaultIsLowerVersion, defaultVersionJsonGenerator, handleUnexpectedErrors, isUpdateJSON, parseVersion };
@@ -0,0 +1,77 @@
1
+ import { __require } from './chunk-BVFQWBLK.js';
2
+ import { readFileSync, existsSync, mkdirSync } from 'node:fs';
3
+ import { join, dirname } from 'node:path';
4
+ import { app } from 'electron';
5
+
6
+ var isDev = __EIU_IS_DEV__;
7
+ var isWin = process.platform === "win32";
8
+ var isMac = process.platform === "darwin";
9
+ var isLinux = process.platform === "linux";
10
+ function getPathFromAppNameAsar(...path) {
11
+ return isDev ? "DEV.asar" : join(dirname(app.getAppPath()), `${app.name}.asar`, ...path);
12
+ }
13
+ function getAppVersion() {
14
+ return isDev ? getEntryVersion() : readFileSync(getPathFromAppNameAsar("version"), "utf-8");
15
+ }
16
+ function getEntryVersion() {
17
+ return app.getVersion();
18
+ }
19
+ function requireNative(moduleName) {
20
+ return __require(join(app.getAppPath(), __EIU_ENTRY_DIST_PATH__, moduleName));
21
+ }
22
+ function restartApp() {
23
+ app.relaunch();
24
+ app.quit();
25
+ }
26
+ function setAppUserModelId(id) {
27
+ if (isWin) {
28
+ app.setAppUserModelId(id ?? `org.${app.name}`);
29
+ }
30
+ }
31
+ function disableHWAccForWin7() {
32
+ if (__require("node:os").release().startsWith("6.1")) {
33
+ app.disableHardwareAcceleration();
34
+ }
35
+ }
36
+ function singleInstance(window) {
37
+ const result = app.requestSingleInstanceLock();
38
+ if (result) {
39
+ app.on("second-instance", () => {
40
+ if (window) {
41
+ window.show();
42
+ if (window.isMinimized()) {
43
+ window.restore();
44
+ }
45
+ window.focus();
46
+ }
47
+ });
48
+ } else {
49
+ app.quit();
50
+ }
51
+ return result;
52
+ }
53
+ function setPortableAppDataPath(dirName = "data") {
54
+ const portablePath = join(dirname(app.getPath("exe")), dirName);
55
+ if (!existsSync(portablePath)) {
56
+ mkdirSync(portablePath);
57
+ }
58
+ app.setPath("appData", portablePath);
59
+ }
60
+ function loadPage(win, htmlFilePath = "index.html") {
61
+ if (isDev) {
62
+ win.loadURL(process.env.VITE_DEV_SERVER_URL + htmlFilePath);
63
+ } else {
64
+ win.loadFile(getPathFromAppNameAsar("renderer", htmlFilePath));
65
+ }
66
+ }
67
+ function getPathFromPreload(...paths) {
68
+ return isDev ? join(app.getAppPath(), __EIU_ELECTRON_DIST_PATH__, "preload", ...paths) : getPathFromAppNameAsar("preload", ...paths);
69
+ }
70
+ function getPathFromPublic(...paths) {
71
+ return isDev ? join(app.getAppPath(), "public", ...paths) : getPathFromAppNameAsar("renderer", ...paths);
72
+ }
73
+ function getPathFromEntryAsar(...paths) {
74
+ return join(app.getAppPath(), __EIU_ENTRY_DIST_PATH__, ...paths);
75
+ }
76
+
77
+ export { disableHWAccForWin7, getAppVersion, getEntryVersion, getPathFromAppNameAsar, getPathFromEntryAsar, getPathFromPreload, getPathFromPublic, isDev, isLinux, isMac, isWin, loadPage, requireNative, restartApp, setAppUserModelId, setPortableAppDataPath, singleInstance };
package/dist/index.cjs CHANGED
@@ -1,94 +1,46 @@
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);
1
+ 'use strict';
19
2
 
20
- // src/entry.ts
21
- var entry_exports = {};
22
- __export(entry_exports, {
23
- ErrorInfo: () => ErrorInfo,
24
- Updater: () => Updater,
25
- UpdaterError: () => UpdaterError,
26
- initApp: () => initApp,
27
- startupWithUpdater: () => startupWithUpdater
28
- });
29
- module.exports = __toCommonJS(entry_exports);
30
- var import_node_path2 = require("path");
31
- var import_node_fs5 = require("fs");
32
- var import_electron4 = require("electron");
3
+ var path = require('path');
4
+ var fs = require('fs');
5
+ var electron = require('electron');
6
+ var events = require('events');
33
7
 
34
- // src/updater/core.ts
35
- var import_node_fs3 = require("fs");
36
- var import_node_stream = require("stream");
37
- var import_electron2 = require("electron");
8
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
9
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
10
+ }) : x)(function(x) {
11
+ if (typeof require !== "undefined") return require.apply(this, arguments);
12
+ throw Error('Dynamic require of "' + x + '" is not supported');
13
+ });
38
14
 
39
15
  // src/utils/version.ts
40
16
  function isUpdateJSON(json) {
41
17
  const is = (j) => !!(j && j.minimumVersion && j.signature && j.size && j.version);
42
18
  return is(json) && is(json?.beta);
43
19
  }
44
-
45
- // src/utils/electron.ts
46
- var import_node_fs = require("fs");
47
- var import_node_path = require("path");
48
- var import_electron = require("electron");
49
20
  var isDev = __EIU_IS_DEV__;
50
- var isWin = process.platform === "win32";
51
- var isMac = process.platform === "darwin";
52
- var isLinux = process.platform === "linux";
53
- function getPathFromAppNameAsar(...path) {
54
- return isDev ? "DEV.asar" : (0, import_node_path.join)((0, import_node_path.dirname)(import_electron.app.getAppPath()), `${import_electron.app.name}.asar`, ...path);
21
+ process.platform === "win32";
22
+ process.platform === "darwin";
23
+ process.platform === "linux";
24
+ function getPathFromAppNameAsar(...path$1) {
25
+ return isDev ? "DEV.asar" : path.join(path.dirname(electron.app.getAppPath()), `${electron.app.name}.asar`, ...path$1);
55
26
  }
56
27
  function getAppVersion() {
57
- return isDev ? getEntryVersion() : (0, import_node_fs.readFileSync)(getPathFromAppNameAsar("version"), "utf-8");
28
+ return isDev ? getEntryVersion() : fs.readFileSync(getPathFromAppNameAsar("version"), "utf-8");
58
29
  }
59
30
  function getEntryVersion() {
60
- return import_electron.app.getVersion();
31
+ return electron.app.getVersion();
61
32
  }
62
33
  function restartApp() {
63
- import_electron.app.relaunch();
64
- import_electron.app.quit();
65
- }
66
-
67
- // src/utils/unzip.ts
68
- var import_node_fs2 = require("fs");
69
- var import_node_zlib = require("zlib");
70
- async function unzipFile(gzipPath, targetFilePath = gzipPath.slice(0, -3)) {
71
- if (!(0, import_node_fs2.existsSync)(gzipPath)) {
72
- throw new Error(`path to zipped file not exist: ${gzipPath}`);
73
- }
74
- const compressedBuffer = (0, import_node_fs2.readFileSync)(gzipPath);
75
- return new Promise((resolve, reject) => {
76
- (0, import_node_zlib.brotliDecompress)(compressedBuffer, (err, buffer) => {
77
- (0, import_node_fs2.rmSync)(gzipPath);
78
- if (err) {
79
- reject(err);
80
- }
81
- (0, import_node_fs2.writeFileSync)(targetFilePath, buffer);
82
- resolve();
83
- });
84
- });
34
+ electron.app.relaunch();
35
+ electron.app.quit();
85
36
  }
86
37
 
87
38
  // src/updater/types.ts
88
39
  var ErrorInfo = {
89
40
  download: "Download failed",
90
41
  validate: "Validate failed",
91
- param: "Missing params"
42
+ param: "Missing params",
43
+ network: "Network error"
92
44
  };
93
45
  var UpdaterError = class extends Error {
94
46
  code;
@@ -99,12 +51,10 @@ var UpdaterError = class extends Error {
99
51
  };
100
52
 
101
53
  // src/updater/core.ts
102
- var Updater = class extends import_node_stream.EventEmitter {
54
+ var Updater = class extends events.EventEmitter {
103
55
  CERT = __EIU_SIGNATURE_CERT__;
104
56
  info;
105
- options;
106
57
  asarPath;
107
- gzipPath;
108
58
  tmpFilePath;
109
59
  provider;
110
60
  /**
@@ -112,22 +62,13 @@ var Updater = class extends import_node_stream.EventEmitter {
112
62
  */
113
63
  logger;
114
64
  /**
115
- * URL handler hook
116
- *
117
- * for Github, there are some {@link https://github.com/XIU2/UserScript/blob/master/GithubEnhanced-High-Speed-Download.user.js#L34 public CDNs}
118
- * @param url source url
119
- * @param isDownloadAsar whether is download asar
65
+ * whether to receive beta update
120
66
  */
121
- handleURL;
67
+ receiveBeta;
122
68
  /**
123
- * whether receive beta version
69
+ * whether force update in DEV
124
70
  */
125
- get receiveBeta() {
126
- return !!this.options.receiveBeta;
127
- }
128
- set receiveBeta(receiveBeta) {
129
- this.options.receiveBeta = receiveBeta;
130
- }
71
+ forceUpdate;
131
72
  /**
132
73
  * initialize incremental updater
133
74
  * @param provider update provider
@@ -136,7 +77,7 @@ var Updater = class extends import_node_stream.EventEmitter {
136
77
  constructor(provider, option = {}) {
137
78
  super();
138
79
  this.provider = provider;
139
- this.options = option;
80
+ this.receiveBeta = option.receiveBeta;
140
81
  if (option.SIGNATURE_CERT) {
141
82
  this.CERT = option.SIGNATURE_CERT;
142
83
  }
@@ -153,17 +94,12 @@ var Updater = class extends import_node_stream.EventEmitter {
153
94
  this.logger.info("no logger set, enable dev-only logger");
154
95
  }
155
96
  this.asarPath = getPathFromAppNameAsar();
156
- this.gzipPath = `${this.asarPath}.gz`;
157
97
  this.tmpFilePath = `${this.asarPath}.tmp`;
158
98
  }
159
99
  async fetch(format, data) {
160
- if ((0, import_node_fs3.existsSync)(this.tmpFilePath)) {
100
+ if (fs.existsSync(this.tmpFilePath)) {
161
101
  this.logger?.warn(`remove tmp file: ${this.tmpFilePath}`);
162
- (0, import_node_fs3.rmSync)(this.tmpFilePath);
163
- }
164
- if ((0, import_node_fs3.existsSync)(this.gzipPath)) {
165
- this.logger?.warn(`remove .gz file: ${this.gzipPath}`);
166
- (0, import_node_fs3.rmSync)(this.gzipPath);
102
+ fs.rmSync(this.tmpFilePath);
167
103
  }
168
104
  if (typeof data === "object") {
169
105
  if (format === "json" && isUpdateJSON(data) || format === "buffer" && Buffer.isBuffer(data)) {
@@ -175,11 +111,11 @@ var Updater = class extends import_node_stream.EventEmitter {
175
111
  }
176
112
  this.logger?.debug(`download from ${this.provider.name}`);
177
113
  try {
178
- const result = format === "json" ? await this.provider.downloadJSON(data ?? __EIU_VERSION_PATH__) : await this.provider.downloadAsar(import_electron2.app.name, this.info, (data2) => this.emit("download-progress", data2));
114
+ const result = format === "json" ? await this.provider.downloadJSON(data ?? __EIU_VERSION_PATH__) : await this.provider.downloadAsar(electron.app.name, this.info, (data2) => this.emit("download-progress", data2));
179
115
  this.logger?.debug(`download ${format} success${format === "buffer" ? `, file size: ${result.length}` : ""}`);
180
116
  return result;
181
117
  } catch (e) {
182
- this.err(`download ${format} failed`, "download", `download ${format} failed: ${e}`);
118
+ this.err(`fetch ${format} failed`, "network", `download ${format} failed: ${e}`);
183
119
  }
184
120
  }
185
121
  /**
@@ -194,11 +130,11 @@ var Updater = class extends import_node_stream.EventEmitter {
194
130
  const emitUnavailable = (msg) => {
195
131
  this.logger?.info(msg);
196
132
  this.emit("update-unavailable", msg);
133
+ return false;
197
134
  };
198
135
  const _data = await this.fetch("json", data);
199
136
  if (!_data) {
200
- emitUnavailable("failed to get update info");
201
- return false;
137
+ return emitUnavailable("failed to get update info");
202
138
  }
203
139
  let { signature, size, version, minimumVersion, beta } = _data;
204
140
  if (this.receiveBeta) {
@@ -208,21 +144,18 @@ var Updater = class extends import_node_stream.EventEmitter {
208
144
  size = beta.size;
209
145
  }
210
146
  this.logger?.debug(`checked update, version: ${version}, size: ${size}, signature: ${signature}`);
211
- if (isDev) {
212
- emitUnavailable("in dev mode, skip check update");
213
- return false;
147
+ if (isDev && !this.forceUpdate && !data) {
148
+ return emitUnavailable("skip check update in dev mode, to force update, set `updater.forceUpdate` to true or call checkUpdate with UpdateJSON");
214
149
  }
215
150
  const isLowerVersion = this.provider.isLowerVersion;
216
151
  const entryVersion = getEntryVersion();
217
152
  const appVersion = getAppVersion();
218
153
  if (isLowerVersion(entryVersion, minimumVersion)) {
219
- emitUnavailable(`entry version (${entryVersion}) < minimumVersion (${minimumVersion})`);
220
- return false;
154
+ return emitUnavailable(`entry version (${entryVersion}) < minimumVersion (${minimumVersion})`);
221
155
  }
222
156
  this.logger?.info(`check update: current version is ${appVersion}, new version is ${version}`);
223
157
  if (!isLowerVersion(appVersion, version)) {
224
- emitUnavailable(`current version (${appVersion}) < new version (${version})`);
225
- return false;
158
+ return emitUnavailable(`current version (${appVersion}) < new version (${version})`);
226
159
  }
227
160
  this.logger?.info(`update available: ${version}`);
228
161
  this.info = { signature, minimumVersion, version, size };
@@ -230,11 +163,11 @@ var Updater = class extends import_node_stream.EventEmitter {
230
163
  return true;
231
164
  }
232
165
  async download(data, sig) {
233
- if (!this.info) {
234
- this.err("download failed", "param", "no update info, call `checkUpdate` first");
166
+ const _sig = sig ?? this.info?.signature;
167
+ if (!_sig) {
168
+ this.err("download failed", "param", "no update signature, please call `checkUpdate` first");
235
169
  return false;
236
170
  }
237
- const _sig = sig ?? this.info.signature;
238
171
  const buffer = await this.fetch("buffer", data ? Buffer.from(data) : void 0);
239
172
  if (!buffer) {
240
173
  this.err("download failed", "param", "no update asar file buffer");
@@ -243,21 +176,19 @@ var Updater = class extends import_node_stream.EventEmitter {
243
176
  this.logger?.debug("verify start");
244
177
  const _ver = await this.provider.verifySignaure(buffer, _sig, this.CERT);
245
178
  if (!_ver) {
246
- this.err("verify failed", "validate", "invalid signature / certificate pair");
179
+ this.err("download failed", "validate", "invalid signature / certificate pair");
247
180
  return false;
248
181
  }
249
182
  this.logger?.debug("verify success");
250
183
  try {
251
- this.logger?.debug(`write to ${this.gzipPath}`);
252
- (0, import_node_fs3.writeFileSync)(this.gzipPath, buffer);
253
184
  this.logger?.debug(`extract to ${this.tmpFilePath}`);
254
- await unzipFile(this.gzipPath, this.tmpFilePath);
185
+ await this.provider.unzipFile(buffer, this.tmpFilePath);
255
186
  this.logger?.info(`download success, version: ${_ver}`);
256
187
  this.info = void 0;
257
188
  this.emit("update-downloaded");
258
189
  return true;
259
190
  } catch (error) {
260
- this.err("unwrap asar failed", "download", `fail to unwrap asar file, ${error}`);
191
+ this.err("download failed", "download", `fail to unwrap asar file, ${error}`);
261
192
  return false;
262
193
  }
263
194
  }
@@ -268,28 +199,28 @@ var Updater = class extends import_node_stream.EventEmitter {
268
199
  this.logger?.info("quit and install");
269
200
  restartApp();
270
201
  }
202
+ /**
203
+ * setup provider URL handler
204
+ *
205
+ * @example
206
+ * updater.setURLHandler((url, isDownloadingAsar) => {
207
+ * if (isDownloadingAsar) {
208
+ * return url.replace('https://raw.githubusercontent.com', 'https://cdn.jsdelivr.net/gh')
209
+ * }
210
+ * })
211
+ */
212
+ setURLHandler(handler) {
213
+ this.provider.urlHandler = handler;
214
+ }
271
215
  };
272
216
 
273
- // src/utils/zip.ts
274
- var import_node_fs4 = require("fs");
275
- var import_node_zlib2 = require("zlib");
276
-
277
- // src/utils/crypto/decrypt.ts
278
- var import_node_crypto2 = require("crypto");
279
-
280
- // src/utils/crypto/utils.ts
281
- var import_node_crypto = require("crypto");
282
-
283
- // src/utils/crypto/encrypt.ts
284
- var import_node_crypto3 = require("crypto");
285
-
286
217
  // src/entry.ts
287
218
  function startupWithUpdater(fn) {
288
219
  return fn;
289
220
  }
290
221
  var defaultOnInstall = (install, _, __, logger) => {
291
222
  install();
292
- logger.info(`update success!`);
223
+ logger?.info(`update success!`);
293
224
  };
294
225
  async function initApp(appOptions) {
295
226
  const {
@@ -305,32 +236,38 @@ async function initApp(appOptions) {
305
236
  } else {
306
237
  updaterInstance = await updater();
307
238
  }
308
- const logger = updaterInstance.logger || console;
239
+ let logger = updaterInstance.logger;
240
+ if (isDev && !logger) {
241
+ logger = {
242
+ info: (...args) => console.log("[EIU-INFO ]", ...args),
243
+ debug: (...args) => console.log("[EIU-DEBUG]", ...args),
244
+ warn: (...args) => console.log("[EIU-WARN ]", ...args),
245
+ error: (...args) => console.error("[EIU-ERROR]", ...args)
246
+ };
247
+ }
309
248
  try {
310
249
  const appNameAsarPath = getPathFromAppNameAsar();
311
250
  const tempAsarPath = `${appNameAsarPath}.tmp`;
312
- if ((0, import_node_fs5.existsSync)(tempAsarPath)) {
313
- logger.info(`installing new asar: ${tempAsarPath}`);
314
- await onInstall(() => (0, import_node_fs5.renameSync)(tempAsarPath, appNameAsarPath), tempAsarPath, appNameAsarPath, logger);
251
+ if (fs.existsSync(tempAsarPath)) {
252
+ logger?.info(`installing new asar: ${tempAsarPath}`);
253
+ await onInstall(() => fs.renameSync(tempAsarPath, appNameAsarPath), tempAsarPath, appNameAsarPath, logger);
315
254
  }
316
- const mainFilePath = (0, import_node_path2.join)(
317
- isDev ? (0, import_node_path2.join)(import_electron4.app.getAppPath(), __EIU_MAIN_DEV_DIR__) : appNameAsarPath,
255
+ const mainFilePath = path.join(
256
+ isDev ? path.join(electron.app.getAppPath(), __EIU_MAIN_DEV_DIR__) : appNameAsarPath,
318
257
  "main",
319
258
  __EIU_MAIN_FILE__
320
259
  );
321
260
  await beforeStart?.(mainFilePath, logger);
322
- require(mainFilePath)(updaterInstance);
261
+ __require(mainFilePath)(updaterInstance);
323
262
  } catch (error) {
324
- logger.error("startup error", error);
263
+ logger?.error("startup error", error);
325
264
  onStartError?.(error, logger);
326
- import_electron4.app.quit();
265
+ electron.app.quit();
327
266
  }
328
267
  }
329
- // Annotate the CommonJS export names for ESM import in node:
330
- 0 && (module.exports = {
331
- ErrorInfo,
332
- Updater,
333
- UpdaterError,
334
- initApp,
335
- startupWithUpdater
336
- });
268
+
269
+ exports.ErrorInfo = ErrorInfo;
270
+ exports.Updater = Updater;
271
+ exports.UpdaterError = UpdaterError;
272
+ exports.initApp = initApp;
273
+ exports.startupWithUpdater = startupWithUpdater;
package/dist/index.d.cts CHANGED
@@ -1,12 +1,13 @@
1
- import { EventEmitter } from 'node:stream';
2
- import { U as UpdateJSON, a as UpdateInfo } from './version-CffZWDhZ.cjs';
3
- import { D as DownloadingInfo, U as URLHandler, I as IProvider } from './types-COqp44eg.cjs';
1
+ import { EventEmitter } from 'node:events';
2
+ import { U as UpdateJSON, a as UpdateInfo } from './version-CemSHimT.cjs';
3
+ import { D as DownloadingInfo, I as IProvider, U as URLHandler } from './types-Tequ_V2o.cjs';
4
4
  import '@subframe7536/type-utils';
5
5
 
6
6
  declare const ErrorInfo: {
7
7
  readonly download: "Download failed";
8
8
  readonly validate: "Validate failed";
9
9
  readonly param: "Missing params";
10
+ readonly network: "Network error";
10
11
  };
11
12
  declare class UpdaterError extends Error {
12
13
  code: keyof typeof ErrorInfo;
@@ -60,9 +61,7 @@ declare class Updater extends EventEmitter<{
60
61
  }> {
61
62
  private CERT;
62
63
  private info?;
63
- private options;
64
64
  private asarPath;
65
- private gzipPath;
66
65
  private tmpFilePath;
67
66
  private provider;
68
67
  /**
@@ -70,18 +69,13 @@ declare class Updater extends EventEmitter<{
70
69
  */
71
70
  logger?: Logger;
72
71
  /**
73
- * URL handler hook
74
- *
75
- * for Github, there are some {@link https://github.com/XIU2/UserScript/blob/master/GithubEnhanced-High-Speed-Download.user.js#L34 public CDNs}
76
- * @param url source url
77
- * @param isDownloadAsar whether is download asar
72
+ * whether to receive beta update
78
73
  */
79
- handleURL?: URLHandler;
74
+ receiveBeta?: boolean;
80
75
  /**
81
- * whether receive beta version
76
+ * whether force update in DEV
82
77
  */
83
- get receiveBeta(): boolean;
84
- set receiveBeta(receiveBeta: boolean);
78
+ forceUpdate?: boolean;
85
79
  /**
86
80
  * initialize incremental updater
87
81
  * @param provider update provider
@@ -122,11 +116,22 @@ declare class Updater extends EventEmitter<{
122
116
  * @param data existing `asar.gz` buffer
123
117
  * @param sig signature
124
118
  */
125
- download(data: Uint8Array, sig: string): Promise<boolean>;
119
+ download(data: Uint8Array | Buffer, sig: string): Promise<boolean>;
126
120
  /**
127
121
  * quit App and install
128
122
  */
129
123
  quitAndInstall(): void;
124
+ /**
125
+ * setup provider URL handler
126
+ *
127
+ * @example
128
+ * updater.setURLHandler((url, isDownloadingAsar) => {
129
+ * if (isDownloadingAsar) {
130
+ * return url.replace('https://raw.githubusercontent.com', 'https://cdn.jsdelivr.net/gh')
131
+ * }
132
+ * })
133
+ */
134
+ setURLHandler(handler: URLHandler): void;
130
135
  }
131
136
 
132
137
  type Promisable<T> = T | Promise<T>;
@@ -138,7 +143,7 @@ type Promisable<T> = T | Promise<T>;
138
143
  * @param logger logger
139
144
  * @default install(); logger.info(`update success!`)
140
145
  */
141
- type OnInstallFunction = (install: VoidFunction, tempAsarPath: string, appNameAsarPath: string, logger: Logger) => Promisable<void>;
146
+ type OnInstallFunction = (install: VoidFunction, tempAsarPath: string, appNameAsarPath: string, logger?: Logger) => Promisable<void>;
142
147
  interface AppOption {
143
148
  /**
144
149
  * update provider
@@ -157,13 +162,13 @@ interface AppOption {
157
162
  * @param mainFilePath main file path of `${app.name}.asar`
158
163
  * @param logger logger
159
164
  */
160
- beforeStart?: (mainFilePath: string, logger: Logger) => Promisable<void>;
165
+ beforeStart?: (mainFilePath: string, logger?: Logger) => Promisable<void>;
161
166
  /**
162
167
  * hooks on app start up error
163
168
  * @param err installing or startup error
164
169
  * @param logger logger
165
170
  */
166
- onStartError?: (err: unknown, logger: Logger) => void;
171
+ onStartError?: (err: unknown, logger?: Logger) => void;
167
172
  }
168
173
  /**
169
174
  * utils for startuping with updater