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

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/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,35 +51,22 @@ 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
- asarPath;
107
- gzipPath;
108
- tmpFilePath;
109
57
  provider;
110
58
  /**
111
59
  * updater logger
112
60
  */
113
61
  logger;
114
62
  /**
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
63
+ * whether to receive beta update
120
64
  */
121
- handleURL;
65
+ receiveBeta;
122
66
  /**
123
- * whether receive beta version
67
+ * whether force update in DEV
124
68
  */
125
- get receiveBeta() {
126
- return !!this.options.receiveBeta;
127
- }
128
- set receiveBeta(receiveBeta) {
129
- this.options.receiveBeta = receiveBeta;
130
- }
69
+ forceUpdate;
131
70
  /**
132
71
  * initialize incremental updater
133
72
  * @param provider update provider
@@ -136,7 +75,7 @@ var Updater = class extends import_node_stream.EventEmitter {
136
75
  constructor(provider, option = {}) {
137
76
  super();
138
77
  this.provider = provider;
139
- this.options = option;
78
+ this.receiveBeta = option.receiveBeta;
140
79
  if (option.SIGNATURE_CERT) {
141
80
  this.CERT = option.SIGNATURE_CERT;
142
81
  }
@@ -152,19 +91,8 @@ var Updater = class extends import_node_stream.EventEmitter {
152
91
  };
153
92
  this.logger.info("no logger set, enable dev-only logger");
154
93
  }
155
- this.asarPath = getPathFromAppNameAsar();
156
- this.gzipPath = `${this.asarPath}.gz`;
157
- this.tmpFilePath = `${this.asarPath}.tmp`;
158
94
  }
159
95
  async fetch(format, data) {
160
- if ((0, import_node_fs3.existsSync)(this.tmpFilePath)) {
161
- 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);
167
- }
168
96
  if (typeof data === "object") {
169
97
  if (format === "json" && isUpdateJSON(data) || format === "buffer" && Buffer.isBuffer(data)) {
170
98
  return data;
@@ -175,11 +103,11 @@ var Updater = class extends import_node_stream.EventEmitter {
175
103
  }
176
104
  this.logger?.debug(`download from ${this.provider.name}`);
177
105
  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));
106
+ 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
107
  this.logger?.debug(`download ${format} success${format === "buffer" ? `, file size: ${result.length}` : ""}`);
180
108
  return result;
181
109
  } catch (e) {
182
- this.err(`download ${format} failed`, "download", `download ${format} failed: ${e}`);
110
+ this.err(`fetch ${format} failed`, "network", `download ${format} failed: ${e}`);
183
111
  }
184
112
  }
185
113
  /**
@@ -194,11 +122,11 @@ var Updater = class extends import_node_stream.EventEmitter {
194
122
  const emitUnavailable = (msg) => {
195
123
  this.logger?.info(msg);
196
124
  this.emit("update-unavailable", msg);
125
+ return false;
197
126
  };
198
127
  const _data = await this.fetch("json", data);
199
128
  if (!_data) {
200
- emitUnavailable("failed to get update info");
201
- return false;
129
+ return emitUnavailable("failed to get update info");
202
130
  }
203
131
  let { signature, size, version, minimumVersion, beta } = _data;
204
132
  if (this.receiveBeta) {
@@ -208,33 +136,30 @@ var Updater = class extends import_node_stream.EventEmitter {
208
136
  size = beta.size;
209
137
  }
210
138
  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;
139
+ if (isDev && !this.forceUpdate && !data) {
140
+ return emitUnavailable("skip check update in dev mode, to force update, set `updater.forceUpdate` to true or call checkUpdate with UpdateJSON");
214
141
  }
215
142
  const isLowerVersion = this.provider.isLowerVersion;
216
143
  const entryVersion = getEntryVersion();
217
144
  const appVersion = getAppVersion();
218
145
  if (isLowerVersion(entryVersion, minimumVersion)) {
219
- emitUnavailable(`entry version (${entryVersion}) < minimumVersion (${minimumVersion})`);
220
- return false;
146
+ return emitUnavailable(`entry version (${entryVersion}) < minimumVersion (${minimumVersion})`);
221
147
  }
222
148
  this.logger?.info(`check update: current version is ${appVersion}, new version is ${version}`);
223
149
  if (!isLowerVersion(appVersion, version)) {
224
- emitUnavailable(`current version (${appVersion}) < new version (${version})`);
225
- return false;
150
+ return emitUnavailable(`current version (${appVersion}) < new version (${version})`);
226
151
  }
227
152
  this.logger?.info(`update available: ${version}`);
228
153
  this.info = { signature, minimumVersion, version, size };
229
154
  this.emit("update-available", this.info);
230
155
  return true;
231
156
  }
232
- async download(data, sig) {
233
- if (!this.info) {
234
- this.err("download failed", "param", "no update info, call `checkUpdate` first");
157
+ async downloadUpdate(data, sig) {
158
+ const _sig = sig ?? this.info?.signature;
159
+ if (!_sig) {
160
+ this.err("download failed", "param", "no update signature, please call `checkUpdate` first");
235
161
  return false;
236
162
  }
237
- const _sig = sig ?? this.info.signature;
238
163
  const buffer = await this.fetch("buffer", data ? Buffer.from(data) : void 0);
239
164
  if (!buffer) {
240
165
  this.err("download failed", "param", "no update asar file buffer");
@@ -243,21 +168,20 @@ var Updater = class extends import_node_stream.EventEmitter {
243
168
  this.logger?.debug("verify start");
244
169
  const _ver = await this.provider.verifySignaure(buffer, _sig, this.CERT);
245
170
  if (!_ver) {
246
- this.err("verify failed", "validate", "invalid signature / certificate pair");
171
+ this.err("download failed", "validate", "invalid signature / certificate pair");
247
172
  return false;
248
173
  }
249
174
  this.logger?.debug("verify success");
250
175
  try {
251
- this.logger?.debug(`write to ${this.gzipPath}`);
252
- (0, import_node_fs3.writeFileSync)(this.gzipPath, buffer);
253
- this.logger?.debug(`extract to ${this.tmpFilePath}`);
254
- await unzipFile(this.gzipPath, this.tmpFilePath);
176
+ const tmpFilePath = getPathFromAppNameAsar() + ".tmp";
177
+ this.logger?.debug(`install to ${tmpFilePath}`);
178
+ fs.writeFileSync(tmpFilePath, await this.provider.unzipFile(buffer));
255
179
  this.logger?.info(`download success, version: ${_ver}`);
256
180
  this.info = void 0;
257
181
  this.emit("update-downloaded");
258
182
  return true;
259
183
  } catch (error) {
260
- this.err("unwrap asar failed", "download", `fail to unwrap asar file, ${error}`);
184
+ this.err("download failed", "download", `fail to unwrap asar file, ${error}`);
261
185
  return false;
262
186
  }
263
187
  }
@@ -268,28 +192,29 @@ var Updater = class extends import_node_stream.EventEmitter {
268
192
  this.logger?.info("quit and install");
269
193
  restartApp();
270
194
  }
195
+ /**
196
+ * setup provider URL handler
197
+ *
198
+ * @example
199
+ * updater.setURLHandler((url, isDownloadingAsar) => {
200
+ * if (isDownloadingAsar) {
201
+ * url.hostname = 'https://cdn.jsdelivr.net/gh'
202
+ * return url
203
+ * }
204
+ * })
205
+ */
206
+ setURLHandler(handler) {
207
+ this.provider.urlHandler = handler;
208
+ }
271
209
  };
272
210
 
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
211
  // src/entry.ts
287
212
  function startupWithUpdater(fn) {
288
213
  return fn;
289
214
  }
290
215
  var defaultOnInstall = (install, _, __, logger) => {
291
216
  install();
292
- logger.info(`update success!`);
217
+ logger?.info(`update success!`);
293
218
  };
294
219
  async function initApp(appOptions) {
295
220
  const {
@@ -305,32 +230,38 @@ async function initApp(appOptions) {
305
230
  } else {
306
231
  updaterInstance = await updater();
307
232
  }
308
- const logger = updaterInstance.logger || console;
233
+ let logger = updaterInstance.logger;
234
+ if (isDev && !logger) {
235
+ logger = {
236
+ info: (...args) => console.log("[EIU-INFO ]", ...args),
237
+ debug: (...args) => console.log("[EIU-DEBUG]", ...args),
238
+ warn: (...args) => console.log("[EIU-WARN ]", ...args),
239
+ error: (...args) => console.error("[EIU-ERROR]", ...args)
240
+ };
241
+ }
309
242
  try {
310
243
  const appNameAsarPath = getPathFromAppNameAsar();
311
244
  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);
245
+ if (fs.existsSync(tempAsarPath)) {
246
+ logger?.info(`installing new asar: ${tempAsarPath}`);
247
+ await onInstall(() => fs.renameSync(tempAsarPath, appNameAsarPath), tempAsarPath, appNameAsarPath, logger);
315
248
  }
316
- const mainFilePath = (0, import_node_path2.join)(
317
- isDev ? (0, import_node_path2.join)(import_electron4.app.getAppPath(), __EIU_MAIN_DEV_DIR__) : appNameAsarPath,
249
+ const mainFilePath = path.join(
250
+ isDev ? path.join(electron.app.getAppPath(), __EIU_MAIN_DEV_DIR__) : appNameAsarPath,
318
251
  "main",
319
252
  __EIU_MAIN_FILE__
320
253
  );
321
254
  await beforeStart?.(mainFilePath, logger);
322
- require(mainFilePath)(updaterInstance);
255
+ __require(mainFilePath)(updaterInstance);
323
256
  } catch (error) {
324
- logger.error("startup error", error);
257
+ logger?.error("startup error", error);
325
258
  onStartError?.(error, logger);
326
- import_electron4.app.quit();
259
+ electron.app.quit();
327
260
  }
328
261
  }
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
- });
262
+
263
+ exports.ErrorInfo = ErrorInfo;
264
+ exports.Updater = Updater;
265
+ exports.UpdaterError = UpdaterError;
266
+ exports.initApp = initApp;
267
+ exports.startupWithUpdater = startupWithUpdater;
package/dist/index.d.cts CHANGED
@@ -1,134 +1,9 @@
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 { U as Updater, a as UpdaterOption, L as Logger } from './core-CW7TMqi7.cjs';
2
+ export { C as CheckResult, D as DownloadResult, E as ErrorInfo, b as UpdaterError } from './core-CW7TMqi7.cjs';
3
+ import { I as IProvider } from './types-Bz1VD18z.cjs';
4
+ import 'node:events';
4
5
  import '@subframe7536/type-utils';
5
6
 
6
- declare const ErrorInfo: {
7
- readonly download: "Download failed";
8
- readonly validate: "Validate failed";
9
- readonly param: "Missing params";
10
- };
11
- declare class UpdaterError extends Error {
12
- code: keyof typeof ErrorInfo;
13
- constructor(msg: keyof typeof ErrorInfo, info: string);
14
- }
15
- type CheckResult<T extends UpdateJSON> = {
16
- success: true;
17
- data: Omit<T, 'beta'>;
18
- } | {
19
- success: false;
20
- /**
21
- * minimal version that can update
22
- */
23
- data: string;
24
- } | {
25
- success: false;
26
- data: UpdaterError;
27
- };
28
- type DownloadResult = {
29
- success: true;
30
- } | {
31
- success: false;
32
- data: UpdaterError;
33
- };
34
- interface Logger {
35
- info: (msg: string) => void;
36
- debug: (msg: string) => void;
37
- warn: (msg: string) => void;
38
- error: (msg: string, e?: unknown) => void;
39
- }
40
- interface UpdaterOption {
41
- /**
42
- * public key of signature, which will be auto generated by plugin,
43
- * generate by `selfsigned` if not set
44
- */
45
- SIGNATURE_CERT?: string;
46
- /**
47
- * whether to receive beta update
48
- */
49
- receiveBeta?: boolean;
50
- logger?: Logger;
51
- }
52
-
53
- declare class Updater extends EventEmitter<{
54
- 'checking': any;
55
- 'update-available': [data: UpdateInfo];
56
- 'update-unavailable': [reason: string];
57
- 'error': [error: UpdaterError];
58
- 'download-progress': [info: DownloadingInfo];
59
- 'update-downloaded': any;
60
- }> {
61
- private CERT;
62
- private info?;
63
- private options;
64
- private asarPath;
65
- private gzipPath;
66
- private tmpFilePath;
67
- private provider;
68
- /**
69
- * updater logger
70
- */
71
- logger?: Logger;
72
- /**
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
78
- */
79
- handleURL?: URLHandler;
80
- /**
81
- * whether receive beta version
82
- */
83
- get receiveBeta(): boolean;
84
- set receiveBeta(receiveBeta: boolean);
85
- /**
86
- * initialize incremental updater
87
- * @param provider update provider
88
- * @param option UpdaterOption
89
- */
90
- constructor(provider: IProvider, option?: UpdaterOption);
91
- /**
92
- * this function is used to parse download data.
93
- * - if format is `'json'`
94
- * - if data is `UpdateJSON`, return it
95
- * - if data is string or absent, download URL data and return it
96
- * - if format is `'buffer'`
97
- * - if data is `Buffer`, return it
98
- * - if data is string or absent, download URL data and return it
99
- * @param format 'json' or 'buffer'
100
- * @param data download URL or update json or buffer
101
- */
102
- private fetch;
103
- /**
104
- * handle error message and emit error event
105
- */
106
- private err;
107
- /**
108
- * check update info using default options
109
- */
110
- checkUpdate(): Promise<boolean>;
111
- /**
112
- * check update info using existing update json
113
- * @param data existing update json
114
- */
115
- checkUpdate(data: UpdateJSON): Promise<boolean>;
116
- /**
117
- * download update using default options
118
- */
119
- download(): Promise<boolean>;
120
- /**
121
- * download update using existing `asar.gz` buffer and signature
122
- * @param data existing `asar.gz` buffer
123
- * @param sig signature
124
- */
125
- download(data: Uint8Array, sig: string): Promise<boolean>;
126
- /**
127
- * quit App and install
128
- */
129
- quitAndInstall(): void;
130
- }
131
-
132
7
  type Promisable<T> = T | Promise<T>;
133
8
  /**
134
9
  * hooks on rename temp asar path to `${app.name}.asar`
@@ -138,7 +13,7 @@ type Promisable<T> = T | Promise<T>;
138
13
  * @param logger logger
139
14
  * @default install(); logger.info(`update success!`)
140
15
  */
141
- type OnInstallFunction = (install: VoidFunction, tempAsarPath: string, appNameAsarPath: string, logger: Logger) => Promisable<void>;
16
+ type OnInstallFunction = (install: VoidFunction, tempAsarPath: string, appNameAsarPath: string, logger?: Logger) => Promisable<void>;
142
17
  interface AppOption {
143
18
  /**
144
19
  * update provider
@@ -157,13 +32,13 @@ interface AppOption {
157
32
  * @param mainFilePath main file path of `${app.name}.asar`
158
33
  * @param logger logger
159
34
  */
160
- beforeStart?: (mainFilePath: string, logger: Logger) => Promisable<void>;
35
+ beforeStart?: (mainFilePath: string, logger?: Logger) => Promisable<void>;
161
36
  /**
162
37
  * hooks on app start up error
163
38
  * @param err installing or startup error
164
39
  * @param logger logger
165
40
  */
166
- onStartError?: (err: unknown, logger: Logger) => void;
41
+ onStartError?: (err: unknown, logger?: Logger) => void;
167
42
  }
168
43
  /**
169
44
  * utils for startuping with updater
@@ -200,4 +75,4 @@ declare function startupWithUpdater(fn: (updater: Updater) => Promisable<void>):
200
75
  */
201
76
  declare function initApp(appOptions: AppOption): Promise<void>;
202
77
 
203
- export { type AppOption, type CheckResult, type DownloadResult, ErrorInfo, type Logger, Updater, UpdaterError, type UpdaterOption, initApp, startupWithUpdater };
78
+ export { type AppOption, Logger, Updater, UpdaterOption, initApp, startupWithUpdater };