electron-incremental-update 2.0.0-beta.8 → 2.0.0

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,87 @@
1
+ import { __require } from './chunk-RCRKUKFX.js';
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+ import electron 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(...paths) {
11
+ return isDev ? "DEV.asar" : path.join(path.dirname(electron.app.getAppPath()), `${electron.app.name}.asar`, ...paths);
12
+ }
13
+ function getAppVersion() {
14
+ return isDev ? getEntryVersion() : fs.readFileSync(getPathFromAppNameAsar("version"), "utf-8");
15
+ }
16
+ function getEntryVersion() {
17
+ return electron.app.getVersion();
18
+ }
19
+ function requireNative(moduleName) {
20
+ if (__EIU_IS_ESM__) {
21
+ throw new Error(`Cannot require "${path.join(__EIU_ENTRY_DIST_PATH__, moduleName)}", \`requireNative\` only support CommonJS`);
22
+ }
23
+ return __require(path.join(electron.app.getAppPath(), __EIU_ENTRY_DIST_PATH__, moduleName));
24
+ }
25
+ function restartApp() {
26
+ electron.app.relaunch();
27
+ electron.app.quit();
28
+ }
29
+ function setAppUserModelId(id) {
30
+ if (isWin) {
31
+ electron.app.setAppUserModelId(id ?? `org.${electron.app.name}`);
32
+ }
33
+ }
34
+ function disableHWAccForWin7() {
35
+ if (!__EIU_IS_ESM__ && __require("node:os").release().startsWith("6.1")) {
36
+ electron.app.disableHardwareAcceleration();
37
+ }
38
+ }
39
+ function singleInstance(window) {
40
+ const result = electron.app.requestSingleInstanceLock();
41
+ if (result) {
42
+ electron.app.on("second-instance", () => {
43
+ if (window) {
44
+ window.show();
45
+ if (window.isMinimized()) {
46
+ window.restore();
47
+ }
48
+ window.focus();
49
+ }
50
+ });
51
+ } else {
52
+ electron.app.quit();
53
+ }
54
+ return result;
55
+ }
56
+ function setPortableAppDataPath(dirName = "data") {
57
+ const portablePath = path.join(path.dirname(electron.app.getPath("exe")), dirName);
58
+ if (!fs.existsSync(portablePath)) {
59
+ fs.mkdirSync(portablePath);
60
+ }
61
+ electron.app.setPath("appData", portablePath);
62
+ }
63
+ function loadPage(win, htmlFilePath = "index.html") {
64
+ if (isDev) {
65
+ win.loadURL(process.env.VITE_DEV_SERVER_URL + htmlFilePath);
66
+ } else {
67
+ win.loadFile(getPathFromAppNameAsar("renderer", htmlFilePath));
68
+ }
69
+ }
70
+ function getPathFromMain(...paths) {
71
+ return isDev ? path.join(electron.app.getAppPath(), __EIU_ELECTRON_DIST_PATH__, "main", ...paths) : getPathFromAppNameAsar("main", ...paths);
72
+ }
73
+ function getPathFromPreload(...paths) {
74
+ return isDev ? path.join(electron.app.getAppPath(), __EIU_ELECTRON_DIST_PATH__, "preload", ...paths) : getPathFromAppNameAsar("preload", ...paths);
75
+ }
76
+ function getPathFromPublic(...paths) {
77
+ return isDev ? path.join(electron.app.getAppPath(), "public", ...paths) : getPathFromAppNameAsar("renderer", ...paths);
78
+ }
79
+ function getPathFromEntryAsar(...paths) {
80
+ return path.join(electron.app.getAppPath(), __EIU_ENTRY_DIST_PATH__, ...paths);
81
+ }
82
+ function handleUnexpectedErrors(callback) {
83
+ process.on("uncaughtException", callback);
84
+ process.on("unhandledRejection", callback);
85
+ }
86
+
87
+ export { disableHWAccForWin7, getAppVersion, getEntryVersion, getPathFromAppNameAsar, getPathFromEntryAsar, getPathFromMain, getPathFromPreload, getPathFromPublic, handleUnexpectedErrors, isDev, isLinux, isMac, isWin, loadPage, requireNative, restartApp, setAppUserModelId, setPortableAppDataPath, singleInstance };
@@ -25,7 +25,7 @@ function parseVersion(version) {
25
25
  ret.stageVersion = Number(_v) || -1;
26
26
  }
27
27
  if (Number.isNaN(major) || Number.isNaN(minor) || Number.isNaN(patch) || Number.isNaN(ret.stageVersion)) {
28
- throw new TypeError(`invalid version: ${version}`);
28
+ throw new TypeError(`Invalid version: ${version}`);
29
29
  }
30
30
  return ret;
31
31
  }
package/dist/index.cjs CHANGED
@@ -1,14 +1,15 @@
1
1
  'use strict';
2
2
 
3
- var path = require('path');
4
3
  var fs3 = require('fs');
5
- var electron = require('electron');
6
4
  var events = require('events');
5
+ var electron = require('electron');
6
+ var path = require('path');
7
7
 
8
8
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
9
9
 
10
- var path__default = /*#__PURE__*/_interopDefault(path);
11
10
  var fs3__default = /*#__PURE__*/_interopDefault(fs3);
11
+ var electron__default = /*#__PURE__*/_interopDefault(electron);
12
+ var path__default = /*#__PURE__*/_interopDefault(path);
12
13
 
13
14
  var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
14
15
  get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
@@ -27,66 +28,63 @@ process.platform === "win32";
27
28
  process.platform === "darwin";
28
29
  process.platform === "linux";
29
30
  function getPathFromAppNameAsar(...paths) {
30
- return isDev ? "DEV.asar" : path__default.default.join(path__default.default.dirname(electron.app.getAppPath()), `${electron.app.name}.asar`, ...paths);
31
+ return isDev ? "DEV.asar" : path__default.default.join(path__default.default.dirname(electron__default.default.app.getAppPath()), `${electron__default.default.app.name}.asar`, ...paths);
31
32
  }
32
33
  function getAppVersion() {
33
34
  return isDev ? getEntryVersion() : fs3__default.default.readFileSync(getPathFromAppNameAsar("version"), "utf-8");
34
35
  }
35
36
  function getEntryVersion() {
36
- return electron.app.getVersion();
37
+ return electron__default.default.app.getVersion();
37
38
  }
38
39
  function restartApp() {
39
- electron.app.relaunch();
40
- electron.app.quit();
40
+ electron__default.default.app.relaunch();
41
+ electron__default.default.app.quit();
41
42
  }
42
43
 
43
- // src/updater/types.ts
44
+ // src/entry/types.ts
44
45
  var ErrorInfo = {
45
- download: "Download failed",
46
- validate: "Validate failed",
47
- param: "Missing params",
48
- network: "Network error"
46
+ download: "Download Failed",
47
+ validate: "Validate Failed",
48
+ param: "Missing Params",
49
+ network: "Network Error"
49
50
  };
50
51
  var UpdaterError = class extends Error {
51
52
  code;
52
53
  constructor(msg, info) {
53
- super(ErrorInfo[msg] + ": " + info);
54
+ super(`[${ErrorInfo[msg]}] ${info}`);
54
55
  this.code = msg;
55
56
  }
56
57
  };
57
58
 
58
- // src/updater/core.ts
59
+ // src/entry/updater.ts
59
60
  var Updater = class extends events.EventEmitter {
60
- CERT = __EIU_SIGNATURE_CERT__;
61
+ CERT;
62
+ controller;
61
63
  info;
62
64
  provider;
63
65
  /**
64
- * updater logger
66
+ * Updater logger
65
67
  */
66
68
  logger;
67
69
  /**
68
- * whether to receive beta update
70
+ * Whether to receive beta update
69
71
  */
70
72
  receiveBeta;
71
73
  /**
72
- * whether force update in DEV
74
+ * Whether force update in DEV
73
75
  */
74
76
  forceUpdate;
75
77
  /**
76
- * initialize incremental updater
77
- * @param provider update provider
78
- * @param option UpdaterOption
78
+ * Initialize incremental updater
79
+ * @param options UpdaterOption
79
80
  */
80
- constructor(provider, option = {}) {
81
+ constructor(options = {}) {
81
82
  super();
82
- this.provider = provider;
83
- this.receiveBeta = option.receiveBeta;
84
- if (option.SIGNATURE_CERT) {
85
- this.CERT = option.SIGNATURE_CERT;
86
- }
87
- if (option.logger) {
88
- this.logger = option.logger;
89
- }
83
+ this.provider = options.provider;
84
+ this.receiveBeta = options.receiveBeta;
85
+ this.CERT = options.SIGNATURE_CERT || __EIU_SIGNATURE_CERT__;
86
+ this.logger = options.logger;
87
+ this.controller = new AbortController();
90
88
  if (isDev && !this.logger) {
91
89
  this.logger = {
92
90
  info: (...args) => console.log("[EIU-INFO ]", ...args),
@@ -94,7 +92,10 @@ var Updater = class extends events.EventEmitter {
94
92
  warn: (...args) => console.log("[EIU-WARN ]", ...args),
95
93
  error: (...args) => console.error("[EIU-ERROR]", ...args)
96
94
  };
97
- this.logger.info("no logger set, enable dev-only logger");
95
+ this.logger.info("No logger set, enable dev-only logger");
96
+ }
97
+ if (!this.provider) {
98
+ this.logger?.debug("WARN: No update provider");
98
99
  }
99
100
  }
100
101
  async fetch(format, data) {
@@ -102,90 +103,99 @@ var Updater = class extends events.EventEmitter {
102
103
  if (format === "json" && isUpdateJSON(data) || format === "buffer" && Buffer.isBuffer(data)) {
103
104
  return data;
104
105
  } else {
105
- this.err("invalid type", "param", `invalid type at format '${format}': ${JSON.stringify(data)}`);
106
+ this.err("Invalid type", "param", `Invalid type at format '${format}': ${JSON.stringify(data)}`);
106
107
  return;
107
108
  }
108
109
  }
109
- this.logger?.debug(`download from ${this.provider.name}`);
110
+ this.logger?.debug(`Download from \`${this.provider.name}\``);
110
111
  try {
111
- 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));
112
- this.logger?.debug(`download ${format} success${format === "buffer" ? `, file size: ${result.length}` : ""}`);
112
+ const result = format === "json" ? await this.provider.downloadJSON(__EIU_VERSION_PATH__, this.controller.signal) : await this.provider.downloadAsar(electron.app.name, this.info, this.controller.signal, (info) => this.emit("download-progress", info));
113
+ this.logger?.debug(`Download ${format} success${format === "buffer" ? `, file size: ${result.length}` : ""}`);
113
114
  return result;
114
115
  } catch (e) {
115
- this.err(`fetch ${format} failed`, "network", `download ${format} failed: ${e}`);
116
+ this.err(`Fetch ${format} failed`, "network", e instanceof Error ? e.message : e.toString());
116
117
  }
117
118
  }
118
119
  /**
119
- * handle error message and emit error event
120
+ * Handle error message and emit error event
120
121
  */
121
122
  err(msg, code, errorInfo) {
122
123
  const err = new UpdaterError(code, errorInfo);
123
124
  this.logger?.error(msg, err);
124
125
  this.emit("error", err);
125
126
  }
126
- async checkUpdate(data) {
127
- const emitUnavailable = (msg) => {
127
+ async checkForUpdates(data) {
128
+ const emitUnavailable = (msg, info2) => {
128
129
  this.logger?.info(msg);
129
- this.emit("update-unavailable", msg);
130
+ this.emit("update-not-available", msg, info2);
130
131
  return false;
131
132
  };
133
+ if (!data && !this.provider) {
134
+ this.err("Check update failed", "param", "No update json or provider");
135
+ return false;
136
+ }
132
137
  const _data = await this.fetch("json", data);
133
138
  if (!_data) {
134
- return emitUnavailable("failed to get update info");
135
- }
136
- let { signature, version, minimumVersion, beta } = _data;
137
- if (this.receiveBeta) {
138
- version = beta.version;
139
- signature = beta.signature;
140
- minimumVersion = beta.minimumVersion;
139
+ return emitUnavailable("Failed to get update info");
141
140
  }
142
- this.logger?.debug(`checked update, version: ${version}, signature: ${signature}`);
141
+ const { signature, version, minimumVersion } = this.receiveBeta ? _data.beta : _data;
142
+ const info = { signature, minimumVersion, version };
143
+ this.logger?.debug(`Checked update, version: ${version}, signature: ${signature}`);
143
144
  if (isDev && !this.forceUpdate && !data) {
144
- return emitUnavailable("skip check update in dev mode, to force update, set `updater.forceUpdate` to true or call checkUpdate with UpdateJSON");
145
+ return emitUnavailable("Skip check update in dev mode. To force update, set `updater.forceUpdate` to true or call checkUpdate with UpdateJSON", info);
145
146
  }
146
147
  const isLowerVersion = this.provider.isLowerVersion;
147
148
  const entryVersion = getEntryVersion();
148
149
  const appVersion = getAppVersion();
149
- if (isLowerVersion(entryVersion, minimumVersion)) {
150
- return emitUnavailable(`entry version (${entryVersion}) < minimumVersion (${minimumVersion})`);
151
- }
152
- this.logger?.info(`check update: current version is ${appVersion}, new version is ${version}`);
153
- if (!isLowerVersion(appVersion, version)) {
154
- return emitUnavailable(`current version (${appVersion}) < new version (${version})`);
150
+ try {
151
+ if (isLowerVersion(entryVersion, minimumVersion)) {
152
+ return emitUnavailable(`Entry Version (${entryVersion}) < MinimumVersion (${minimumVersion})`, info);
153
+ }
154
+ this.logger?.info(`Check update: current version is ${appVersion}, new version is ${version}`);
155
+ if (!isLowerVersion(appVersion, version)) {
156
+ return emitUnavailable(`Current version (${appVersion}) < New version (${version})`, info);
157
+ }
158
+ this.logger?.info(`Update available: ${version}`);
159
+ this.emit("update-available", info);
160
+ this.info = info;
161
+ return true;
162
+ } catch {
163
+ this.err("Fail to parse version", "validate", "Fail to parse version string");
164
+ return false;
155
165
  }
156
- this.logger?.info(`update available: ${version}`);
157
- this.info = { signature, minimumVersion, version };
158
- this.emit("update-available", this.info);
159
- return true;
160
166
  }
161
167
  async downloadUpdate(data, info) {
162
168
  const _sig = info?.signature ?? this.info?.signature;
163
169
  const _version = info?.version ?? this.info?.version;
164
170
  if (!_sig || !_version) {
165
- this.err("download failed", "param", "no update signature, please call `checkUpdate` first or manually setup params");
171
+ this.err("Download failed", "param", "No update signature, please call `checkUpdate` first or manually setup params");
172
+ return false;
173
+ }
174
+ if (!data && !this.provider) {
175
+ this.err("Download failed", "param", "No update asar buffer and provider");
166
176
  return false;
167
177
  }
168
178
  const buffer = await this.fetch("buffer", data ? Buffer.from(data) : void 0);
169
179
  if (!buffer) {
170
- this.err("download failed", "param", "no update asar file buffer");
180
+ this.err("Download failed", "param", "No update asar file buffer");
171
181
  return false;
172
182
  }
173
183
  this.logger?.debug("verify start");
174
184
  if (!await this.provider.verifySignaure(buffer, _version, _sig, this.CERT)) {
175
- this.err("download failed", "validate", "invalid update asar file");
185
+ this.err("Download failed", "validate", "Invalid update asar file");
176
186
  return false;
177
187
  }
178
- this.logger?.debug("verify success");
188
+ this.logger?.debug("Verify success");
179
189
  try {
180
- const tmpFilePath = getPathFromAppNameAsar() + ".tmp";
181
- this.logger?.debug(`install to ${tmpFilePath}`);
190
+ const tmpFilePath = `${getPathFromAppNameAsar()}.tmp`;
191
+ this.logger?.debug(`Install to ${tmpFilePath}`);
182
192
  fs3__default.default.writeFileSync(tmpFilePath, await this.provider.unzipFile(buffer));
183
- this.logger?.info(`download success, version: ${_version}`);
193
+ this.logger?.info(`Download success, version: ${_version}`);
184
194
  this.info = void 0;
185
195
  this.emit("update-downloaded");
186
196
  return true;
187
197
  } catch (error) {
188
- this.err("download failed", "download", `fail to unwrap asar file, ${error}`);
198
+ this.err("Download failed", "download", `Fail to unwrap asar file, ${error}`);
189
199
  return false;
190
200
  }
191
201
  }
@@ -193,26 +203,24 @@ var Updater = class extends events.EventEmitter {
193
203
  * quit App and install
194
204
  */
195
205
  quitAndInstall() {
196
- this.logger?.info("quit and install");
206
+ this.logger?.info("Quit and install");
197
207
  restartApp();
198
208
  }
199
- /**
200
- * setup provider URL handler
201
- *
202
- * @example
203
- * updater.setURLHandler((url, isDownloadingAsar) => {
204
- * if (isDownloadingAsar) {
205
- * url.hostname = 'https://cdn.jsdelivr.net/gh'
206
- * return url
207
- * }
208
- * })
209
- */
210
- setURLHandler(handler) {
211
- this.provider.urlHandler = handler;
209
+ cancel() {
210
+ if (this.controller.signal.aborted) {
211
+ return;
212
+ }
213
+ this.controller.abort();
214
+ this.logger?.info("Cancel update");
215
+ this.emit("update-cancelled");
216
+ this.controller = new AbortController();
212
217
  }
213
218
  };
214
-
215
- // src/entry.ts
219
+ async function autoUpdate(updater) {
220
+ if (await updater.checkForUpdates() && await updater.downloadUpdate()) {
221
+ updater.quitAndInstall();
222
+ }
223
+ }
216
224
  function startupWithUpdater(fn) {
217
225
  return fn;
218
226
  }
@@ -220,9 +228,14 @@ var defaultOnInstall = (install, _, __, logger) => {
220
228
  install();
221
229
  logger?.info(`update success!`);
222
230
  };
223
- async function initApp(appOptions) {
231
+ async function createElectronApp(appOptions = {}) {
232
+ const appNameAsarPath = getPathFromAppNameAsar();
224
233
  const {
225
- provider,
234
+ mainPath = path__default.default.join(
235
+ isDev ? path__default.default.join(electron.app.getAppPath(), __EIU_MAIN_DEV_DIR__) : appNameAsarPath,
236
+ "main",
237
+ __EIU_MAIN_FILE__
238
+ ),
226
239
  updater,
227
240
  onInstall = defaultOnInstall,
228
241
  beforeStart,
@@ -230,42 +243,35 @@ async function initApp(appOptions) {
230
243
  } = appOptions;
231
244
  let updaterInstance;
232
245
  if (typeof updater === "object" || !updater) {
233
- updaterInstance = new Updater(provider, updater);
246
+ updaterInstance = new Updater(updater);
234
247
  } else {
235
248
  updaterInstance = await updater();
236
249
  }
237
- let logger = updaterInstance.logger;
238
- if (isDev && !logger) {
239
- logger = {
240
- info: (...args) => console.log("[EIU-INFO ]", ...args),
241
- debug: (...args) => console.log("[EIU-DEBUG]", ...args),
242
- warn: (...args) => console.log("[EIU-WARN ]", ...args),
243
- error: (...args) => console.error("[EIU-ERROR]", ...args)
244
- };
245
- }
250
+ const logger = updaterInstance.logger;
246
251
  try {
247
- const appNameAsarPath = getPathFromAppNameAsar();
248
252
  const tempAsarPath = `${appNameAsarPath}.tmp`;
249
253
  if (fs3__default.default.existsSync(tempAsarPath)) {
250
- logger?.info(`installing new asar: ${tempAsarPath}`);
254
+ logger?.info(`Installing new asar from ${tempAsarPath}`);
251
255
  await onInstall(() => fs3__default.default.renameSync(tempAsarPath, appNameAsarPath), tempAsarPath, appNameAsarPath, logger);
252
256
  }
253
- const mainFilePath = path__default.default.join(
254
- isDev ? path__default.default.join(electron.app.getAppPath(), __EIU_MAIN_DEV_DIR__) : appNameAsarPath,
255
- "main",
256
- __EIU_MAIN_FILE__
257
- );
258
- await beforeStart?.(mainFilePath, logger);
259
- __require(mainFilePath)(updaterInstance);
257
+ await beforeStart?.(mainPath, logger);
258
+ if (__EIU_IS_ESM__) {
259
+ (await import(`file://${mainPath}`)).default(updaterInstance);
260
+ } else {
261
+ __require(mainPath)(updaterInstance);
262
+ }
260
263
  } catch (error) {
261
264
  logger?.error("startup error", error);
262
265
  onStartError?.(error, logger);
263
266
  electron.app.quit();
264
267
  }
265
268
  }
269
+ var initApp = createElectronApp;
266
270
 
267
271
  exports.ErrorInfo = ErrorInfo;
268
272
  exports.Updater = Updater;
269
273
  exports.UpdaterError = UpdaterError;
274
+ exports.autoUpdate = autoUpdate;
275
+ exports.createElectronApp = createElectronApp;
270
276
  exports.initApp = initApp;
271
277
  exports.startupWithUpdater = startupWithUpdater;