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.d.ts CHANGED
@@ -1,134 +1,9 @@
1
- import { EventEmitter } from 'node:stream';
2
- import { U as UpdateJSON, a as UpdateInfo } from './version-CffZWDhZ.js';
3
- import { D as DownloadingInfo, U as URLHandler, I as IProvider } from './types-CPq1MrYZ.js';
1
+ import { U as Updater, a as UpdaterOption, L as Logger } from './core-D6QlpOgp.js';
2
+ export { C as CheckResult, D as DownloadResult, E as ErrorInfo, b as UpdaterError } from './core-D6QlpOgp.js';
3
+ import { I as IProvider } from './types-Bz1VD18z.js';
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 };
package/dist/index.js CHANGED
@@ -1,29 +1,16 @@
1
- import {
2
- __require,
3
- getAppVersion,
4
- getEntryVersion,
5
- getPathFromAppNameAsar,
6
- isDev,
7
- isUpdateJSON,
8
- restartApp,
9
- unzipFile
10
- } from "./chunk-BG22XZAB.js";
11
-
12
- // src/entry.ts
13
- import { join } from "node:path";
14
- import { existsSync as existsSync2, renameSync } from "node:fs";
15
- import { app as app2 } from "electron";
16
-
17
- // src/updater/core.ts
18
- import { existsSync, rmSync, writeFileSync } from "node:fs";
19
- import { EventEmitter } from "node:stream";
20
- import { app } from "electron";
1
+ import { isDev, getEntryVersion, getAppVersion, getPathFromAppNameAsar, restartApp } from './chunk-PNYRQYFC.js';
2
+ import { isUpdateJSON, __require } from './chunk-BVFQWBLK.js';
3
+ import { join } from 'node:path';
4
+ import { writeFileSync, existsSync, renameSync } from 'node:fs';
5
+ import { app } from 'electron';
6
+ import { EventEmitter } from 'node:events';
21
7
 
22
8
  // src/updater/types.ts
23
9
  var ErrorInfo = {
24
10
  download: "Download failed",
25
11
  validate: "Validate failed",
26
- param: "Missing params"
12
+ param: "Missing params",
13
+ network: "Network error"
27
14
  };
28
15
  var UpdaterError = class extends Error {
29
16
  code;
@@ -37,32 +24,19 @@ var UpdaterError = class extends Error {
37
24
  var Updater = class extends EventEmitter {
38
25
  CERT = __EIU_SIGNATURE_CERT__;
39
26
  info;
40
- options;
41
- asarPath;
42
- gzipPath;
43
- tmpFilePath;
44
27
  provider;
45
28
  /**
46
29
  * updater logger
47
30
  */
48
31
  logger;
49
32
  /**
50
- * URL handler hook
51
- *
52
- * for Github, there are some {@link https://github.com/XIU2/UserScript/blob/master/GithubEnhanced-High-Speed-Download.user.js#L34 public CDNs}
53
- * @param url source url
54
- * @param isDownloadAsar whether is download asar
33
+ * whether to receive beta update
55
34
  */
56
- handleURL;
35
+ receiveBeta;
57
36
  /**
58
- * whether receive beta version
37
+ * whether force update in DEV
59
38
  */
60
- get receiveBeta() {
61
- return !!this.options.receiveBeta;
62
- }
63
- set receiveBeta(receiveBeta) {
64
- this.options.receiveBeta = receiveBeta;
65
- }
39
+ forceUpdate;
66
40
  /**
67
41
  * initialize incremental updater
68
42
  * @param provider update provider
@@ -71,7 +45,7 @@ var Updater = class extends EventEmitter {
71
45
  constructor(provider, option = {}) {
72
46
  super();
73
47
  this.provider = provider;
74
- this.options = option;
48
+ this.receiveBeta = option.receiveBeta;
75
49
  if (option.SIGNATURE_CERT) {
76
50
  this.CERT = option.SIGNATURE_CERT;
77
51
  }
@@ -87,19 +61,8 @@ var Updater = class extends EventEmitter {
87
61
  };
88
62
  this.logger.info("no logger set, enable dev-only logger");
89
63
  }
90
- this.asarPath = getPathFromAppNameAsar();
91
- this.gzipPath = `${this.asarPath}.gz`;
92
- this.tmpFilePath = `${this.asarPath}.tmp`;
93
64
  }
94
65
  async fetch(format, data) {
95
- if (existsSync(this.tmpFilePath)) {
96
- this.logger?.warn(`remove tmp file: ${this.tmpFilePath}`);
97
- rmSync(this.tmpFilePath);
98
- }
99
- if (existsSync(this.gzipPath)) {
100
- this.logger?.warn(`remove .gz file: ${this.gzipPath}`);
101
- rmSync(this.gzipPath);
102
- }
103
66
  if (typeof data === "object") {
104
67
  if (format === "json" && isUpdateJSON(data) || format === "buffer" && Buffer.isBuffer(data)) {
105
68
  return data;
@@ -114,7 +77,7 @@ var Updater = class extends EventEmitter {
114
77
  this.logger?.debug(`download ${format} success${format === "buffer" ? `, file size: ${result.length}` : ""}`);
115
78
  return result;
116
79
  } catch (e) {
117
- this.err(`download ${format} failed`, "download", `download ${format} failed: ${e}`);
80
+ this.err(`fetch ${format} failed`, "network", `download ${format} failed: ${e}`);
118
81
  }
119
82
  }
120
83
  /**
@@ -129,11 +92,11 @@ var Updater = class extends EventEmitter {
129
92
  const emitUnavailable = (msg) => {
130
93
  this.logger?.info(msg);
131
94
  this.emit("update-unavailable", msg);
95
+ return false;
132
96
  };
133
97
  const _data = await this.fetch("json", data);
134
98
  if (!_data) {
135
- emitUnavailable("failed to get update info");
136
- return false;
99
+ return emitUnavailable("failed to get update info");
137
100
  }
138
101
  let { signature, size, version, minimumVersion, beta } = _data;
139
102
  if (this.receiveBeta) {
@@ -143,33 +106,30 @@ var Updater = class extends EventEmitter {
143
106
  size = beta.size;
144
107
  }
145
108
  this.logger?.debug(`checked update, version: ${version}, size: ${size}, signature: ${signature}`);
146
- if (isDev) {
147
- emitUnavailable("in dev mode, skip check update");
148
- return false;
109
+ if (isDev && !this.forceUpdate && !data) {
110
+ return emitUnavailable("skip check update in dev mode, to force update, set `updater.forceUpdate` to true or call checkUpdate with UpdateJSON");
149
111
  }
150
112
  const isLowerVersion = this.provider.isLowerVersion;
151
113
  const entryVersion = getEntryVersion();
152
114
  const appVersion = getAppVersion();
153
115
  if (isLowerVersion(entryVersion, minimumVersion)) {
154
- emitUnavailable(`entry version (${entryVersion}) < minimumVersion (${minimumVersion})`);
155
- return false;
116
+ return emitUnavailable(`entry version (${entryVersion}) < minimumVersion (${minimumVersion})`);
156
117
  }
157
118
  this.logger?.info(`check update: current version is ${appVersion}, new version is ${version}`);
158
119
  if (!isLowerVersion(appVersion, version)) {
159
- emitUnavailable(`current version (${appVersion}) < new version (${version})`);
160
- return false;
120
+ return emitUnavailable(`current version (${appVersion}) < new version (${version})`);
161
121
  }
162
122
  this.logger?.info(`update available: ${version}`);
163
123
  this.info = { signature, minimumVersion, version, size };
164
124
  this.emit("update-available", this.info);
165
125
  return true;
166
126
  }
167
- async download(data, sig) {
168
- if (!this.info) {
169
- this.err("download failed", "param", "no update info, call `checkUpdate` first");
127
+ async downloadUpdate(data, sig) {
128
+ const _sig = sig ?? this.info?.signature;
129
+ if (!_sig) {
130
+ this.err("download failed", "param", "no update signature, please call `checkUpdate` first");
170
131
  return false;
171
132
  }
172
- const _sig = sig ?? this.info.signature;
173
133
  const buffer = await this.fetch("buffer", data ? Buffer.from(data) : void 0);
174
134
  if (!buffer) {
175
135
  this.err("download failed", "param", "no update asar file buffer");
@@ -178,21 +138,20 @@ var Updater = class extends EventEmitter {
178
138
  this.logger?.debug("verify start");
179
139
  const _ver = await this.provider.verifySignaure(buffer, _sig, this.CERT);
180
140
  if (!_ver) {
181
- this.err("verify failed", "validate", "invalid signature / certificate pair");
141
+ this.err("download failed", "validate", "invalid signature / certificate pair");
182
142
  return false;
183
143
  }
184
144
  this.logger?.debug("verify success");
185
145
  try {
186
- this.logger?.debug(`write to ${this.gzipPath}`);
187
- writeFileSync(this.gzipPath, buffer);
188
- this.logger?.debug(`extract to ${this.tmpFilePath}`);
189
- await unzipFile(this.gzipPath, this.tmpFilePath);
146
+ const tmpFilePath = getPathFromAppNameAsar() + ".tmp";
147
+ this.logger?.debug(`install to ${tmpFilePath}`);
148
+ writeFileSync(tmpFilePath, await this.provider.unzipFile(buffer));
190
149
  this.logger?.info(`download success, version: ${_ver}`);
191
150
  this.info = void 0;
192
151
  this.emit("update-downloaded");
193
152
  return true;
194
153
  } catch (error) {
195
- this.err("unwrap asar failed", "download", `fail to unwrap asar file, ${error}`);
154
+ this.err("download failed", "download", `fail to unwrap asar file, ${error}`);
196
155
  return false;
197
156
  }
198
157
  }
@@ -203,6 +162,20 @@ var Updater = class extends EventEmitter {
203
162
  this.logger?.info("quit and install");
204
163
  restartApp();
205
164
  }
165
+ /**
166
+ * setup provider URL handler
167
+ *
168
+ * @example
169
+ * updater.setURLHandler((url, isDownloadingAsar) => {
170
+ * if (isDownloadingAsar) {
171
+ * url.hostname = 'https://cdn.jsdelivr.net/gh'
172
+ * return url
173
+ * }
174
+ * })
175
+ */
176
+ setURLHandler(handler) {
177
+ this.provider.urlHandler = handler;
178
+ }
206
179
  };
207
180
 
208
181
  // src/entry.ts
@@ -211,7 +184,7 @@ function startupWithUpdater(fn) {
211
184
  }
212
185
  var defaultOnInstall = (install, _, __, logger) => {
213
186
  install();
214
- logger.info(`update success!`);
187
+ logger?.info(`update success!`);
215
188
  };
216
189
  async function initApp(appOptions) {
217
190
  const {
@@ -227,31 +200,34 @@ async function initApp(appOptions) {
227
200
  } else {
228
201
  updaterInstance = await updater();
229
202
  }
230
- const logger = updaterInstance.logger || console;
203
+ let logger = updaterInstance.logger;
204
+ if (isDev && !logger) {
205
+ logger = {
206
+ info: (...args) => console.log("[EIU-INFO ]", ...args),
207
+ debug: (...args) => console.log("[EIU-DEBUG]", ...args),
208
+ warn: (...args) => console.log("[EIU-WARN ]", ...args),
209
+ error: (...args) => console.error("[EIU-ERROR]", ...args)
210
+ };
211
+ }
231
212
  try {
232
213
  const appNameAsarPath = getPathFromAppNameAsar();
233
214
  const tempAsarPath = `${appNameAsarPath}.tmp`;
234
- if (existsSync2(tempAsarPath)) {
235
- logger.info(`installing new asar: ${tempAsarPath}`);
215
+ if (existsSync(tempAsarPath)) {
216
+ logger?.info(`installing new asar: ${tempAsarPath}`);
236
217
  await onInstall(() => renameSync(tempAsarPath, appNameAsarPath), tempAsarPath, appNameAsarPath, logger);
237
218
  }
238
219
  const mainFilePath = join(
239
- isDev ? join(app2.getAppPath(), __EIU_MAIN_DEV_DIR__) : appNameAsarPath,
220
+ isDev ? join(app.getAppPath(), __EIU_MAIN_DEV_DIR__) : appNameAsarPath,
240
221
  "main",
241
222
  __EIU_MAIN_FILE__
242
223
  );
243
224
  await beforeStart?.(mainFilePath, logger);
244
225
  __require(mainFilePath)(updaterInstance);
245
226
  } catch (error) {
246
- logger.error("startup error", error);
227
+ logger?.error("startup error", error);
247
228
  onStartError?.(error, logger);
248
- app2.quit();
229
+ app.quit();
249
230
  }
250
231
  }
251
- export {
252
- ErrorInfo,
253
- Updater,
254
- UpdaterError,
255
- initApp,
256
- startupWithUpdater
257
- };
232
+
233
+ export { ErrorInfo, Updater, UpdaterError, initApp, startupWithUpdater };