electron-incremental-update 2.4.2 → 3.0.0-beta.2
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/README.md +72 -43
- package/dist/download-BN4uMS4_.d.mts +39 -0
- package/dist/download-DO7iuxEJ.d.cts +39 -0
- package/dist/electron-BFoZUBhU.cjs +320 -0
- package/dist/electron-CJIoO4ny.mjs +180 -0
- package/dist/index.cjs +259 -331
- package/dist/index.d.cts +179 -169
- package/dist/index.d.mts +204 -0
- package/dist/index.mjs +271 -0
- package/dist/provider.cjs +142 -356
- package/dist/provider.d.cts +116 -117
- package/dist/provider.d.mts +133 -0
- package/dist/provider.mjs +152 -0
- package/dist/types-BM9Jfu7q.d.cts +154 -0
- package/dist/types-DASqEPXE.d.mts +154 -0
- package/dist/utils.cjs +43 -381
- package/dist/utils.d.cts +117 -85
- package/dist/utils.d.mts +161 -0
- package/dist/utils.mjs +5 -0
- package/dist/version--eVB2A7n.mjs +72 -0
- package/dist/version-aPrLuz_-.cjs +129 -0
- package/dist/vite.d.mts +565 -0
- package/dist/vite.mjs +1222 -0
- package/dist/zip-BCC7FAQ_.cjs +264 -0
- package/dist/zip-Dwm7s1C9.mjs +185 -0
- package/package.json +65 -65
- package/dist/chunk-AAAM44NW.js +0 -70
- package/dist/chunk-IVHNGRZY.js +0 -122
- package/dist/chunk-PD4EV4MM.js +0 -147
- package/dist/index.d.ts +0 -194
- package/dist/index.js +0 -309
- package/dist/provider.d.ts +0 -134
- package/dist/provider.js +0 -178
- package/dist/types-CU7GyVez.d.cts +0 -151
- package/dist/types-CU7GyVez.d.ts +0 -151
- package/dist/utils.d.ts +0 -129
- package/dist/utils.js +0 -3
- package/dist/vite.d.ts +0 -533
- package/dist/vite.js +0 -945
- package/dist/zip-Blmn2vzE.d.cts +0 -71
- package/dist/zip-CnSv_Njj.d.ts +0 -71
- package/provider.d.ts +0 -1
- package/provider.js +0 -1
- package/utils.d.ts +0 -1
- package/utils.js +0 -1
- package/vite.d.ts +0 -1
- package/vite.js +0 -1
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
import { a as getPathFromAppNameAsar, f as isDev, i as getEntryVersion, r as getAppVersion, y as restartApp } from "./electron-CJIoO4ny.mjs";
|
|
2
|
+
import { r as isUpdateJSON } from "./version--eVB2A7n.mjs";
|
|
3
|
+
import { app } from "electron";
|
|
4
|
+
import fs from "node:fs";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { EventEmitter } from "node:events";
|
|
7
|
+
|
|
8
|
+
//#region src/entry/types.ts
|
|
9
|
+
var UpdaterError = class extends Error {
|
|
10
|
+
code;
|
|
11
|
+
constructor(code, info) {
|
|
12
|
+
super(`[${code}] ${info}`);
|
|
13
|
+
this.code = code;
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
//#endregion
|
|
18
|
+
//#region src/entry/updater.ts
|
|
19
|
+
var Updater = class extends EventEmitter {
|
|
20
|
+
CERT;
|
|
21
|
+
controller;
|
|
22
|
+
info;
|
|
23
|
+
tmpFilePath;
|
|
24
|
+
processing = false;
|
|
25
|
+
provider;
|
|
26
|
+
/**
|
|
27
|
+
* Updater logger
|
|
28
|
+
*/
|
|
29
|
+
logger;
|
|
30
|
+
/**
|
|
31
|
+
* Whether to receive beta update
|
|
32
|
+
*/
|
|
33
|
+
receiveBeta;
|
|
34
|
+
/**
|
|
35
|
+
* Whether force update in DEV
|
|
36
|
+
*/
|
|
37
|
+
forceUpdate;
|
|
38
|
+
/**
|
|
39
|
+
* Initialize incremental updater
|
|
40
|
+
* @param options UpdaterOption
|
|
41
|
+
*/
|
|
42
|
+
constructor(options = {}) {
|
|
43
|
+
super();
|
|
44
|
+
this.provider = options.provider;
|
|
45
|
+
this.receiveBeta = options.receiveBeta;
|
|
46
|
+
this.CERT = options.SIGNATURE_CERT || __EIU_SIGNATURE_CERT__;
|
|
47
|
+
this.logger = options.logger;
|
|
48
|
+
this.controller = new AbortController();
|
|
49
|
+
if (isDev && !this.logger) {
|
|
50
|
+
this.logger = {
|
|
51
|
+
info: (...args) => console.log("[EIU-INFO ]", ...args),
|
|
52
|
+
debug: (...args) => console.log("[EIU-DEBUG]", ...args),
|
|
53
|
+
warn: (...args) => console.log("[EIU-WARN ]", ...args),
|
|
54
|
+
error: (...args) => console.error("[EIU-ERROR]", ...args)
|
|
55
|
+
};
|
|
56
|
+
this.logger.info("No logger set, enable dev-only logger");
|
|
57
|
+
}
|
|
58
|
+
if (!this.provider) this.logger?.debug("WARN: No update provider");
|
|
59
|
+
}
|
|
60
|
+
async fetch(format, data) {
|
|
61
|
+
if (typeof data === "object") if (format === "json" && isUpdateJSON(data) || format === "buffer" && Buffer.isBuffer(data)) return data;
|
|
62
|
+
else {
|
|
63
|
+
this.err("Invalid type", "ERR_PARAM", `Invalid type at format '${format}': ${JSON.stringify(data)}`);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
this.logger?.debug(`Download from \`${this.provider.name}\``);
|
|
67
|
+
try {
|
|
68
|
+
const result = format === "json" ? await this.provider.downloadJSON(app.name, __EIU_VERSION_PATH__, this.controller.signal) : await this.provider.downloadAsar(this.info, this.controller.signal, (info) => this.emit("download-progress", info));
|
|
69
|
+
this.logger?.debug(`Download ${format} success${format === "buffer" ? `, file size: ${result.length}` : ""}`);
|
|
70
|
+
return result;
|
|
71
|
+
} catch (e) {
|
|
72
|
+
this.err(`Fetch ${format} failed`, "ERR_NETWORK", e instanceof Error ? e.message : e.toString());
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
cleanup() {
|
|
76
|
+
if (this.tmpFilePath && fs.existsSync(this.tmpFilePath)) try {
|
|
77
|
+
fs.unlinkSync(this.tmpFilePath);
|
|
78
|
+
this.tmpFilePath = void 0;
|
|
79
|
+
this.logger?.debug("Cleaned up temporary update file");
|
|
80
|
+
} catch (error) {
|
|
81
|
+
this.logger?.warn(`Failed to clean up temporary update file: ${error}`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Handle error message and emit error event
|
|
86
|
+
*/
|
|
87
|
+
err(msg, code, errorInfo) {
|
|
88
|
+
const err = new UpdaterError(code, errorInfo);
|
|
89
|
+
this.logger?.error(`[${code}] ${msg}`, err);
|
|
90
|
+
this.cleanup();
|
|
91
|
+
this.emit("error", err);
|
|
92
|
+
}
|
|
93
|
+
async checkForUpdates(data) {
|
|
94
|
+
const emitUnavailable = (msg, code, info) => {
|
|
95
|
+
this.logger?.info(`[${code}] ${msg}`);
|
|
96
|
+
this.logger?.debug("Check update end");
|
|
97
|
+
this.processing = false;
|
|
98
|
+
this.emit("update-not-available", code, msg, info);
|
|
99
|
+
return false;
|
|
100
|
+
};
|
|
101
|
+
if (this.processing) {
|
|
102
|
+
this.logger?.info("Updater is already processing, skip check update");
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
this.processing = true;
|
|
106
|
+
this.logger?.debug("Check update start");
|
|
107
|
+
if (!data && !this.provider) {
|
|
108
|
+
const msg = "No update json or provider";
|
|
109
|
+
this.err("Check update failed", "ERR_PARAM", msg);
|
|
110
|
+
return emitUnavailable(msg, "UNAVAILABLE_ERROR");
|
|
111
|
+
}
|
|
112
|
+
const _data = await this.fetch("json", data);
|
|
113
|
+
if (!_data) return emitUnavailable("Failed to get update info", "UNAVAILABLE_ERROR");
|
|
114
|
+
const { signature, version, minimumVersion, url, ...rest } = this.receiveBeta ? _data.beta : _data;
|
|
115
|
+
const info = {
|
|
116
|
+
signature,
|
|
117
|
+
minimumVersion,
|
|
118
|
+
version,
|
|
119
|
+
url
|
|
120
|
+
};
|
|
121
|
+
const extraVersionInfo = {
|
|
122
|
+
signature,
|
|
123
|
+
minimumVersion,
|
|
124
|
+
version,
|
|
125
|
+
appVersion: getAppVersion(),
|
|
126
|
+
entryVersion: getEntryVersion(),
|
|
127
|
+
...rest
|
|
128
|
+
};
|
|
129
|
+
this.logger?.debug(`Checked update, version: ${version}, signature: ${signature}`);
|
|
130
|
+
if (isDev && !this.forceUpdate && !data) return emitUnavailable("Skip check update in dev mode. To force update, set `updater.forceUpdate` to true or call checkUpdate with UpdateJSON", "UNAVAILABLE_DEV");
|
|
131
|
+
const isLowerVersion = this.provider.isLowerVersion;
|
|
132
|
+
try {
|
|
133
|
+
if (isLowerVersion(extraVersionInfo.entryVersion, minimumVersion)) return emitUnavailable(`Entry Version (${extraVersionInfo.entryVersion}) < MinimumVersion (${minimumVersion})`, "UNAVAILABLE_VERSION", extraVersionInfo);
|
|
134
|
+
this.logger?.info(`Current version is ${extraVersionInfo.appVersion}, new version is ${version}`);
|
|
135
|
+
if (!isLowerVersion(extraVersionInfo.appVersion, version)) return emitUnavailable(`Current version (${extraVersionInfo.appVersion}) > New version (${version})`, "UNAVAILABLE_VERSION", extraVersionInfo);
|
|
136
|
+
this.logger?.info(`Update available: ${version}`);
|
|
137
|
+
this.info = info;
|
|
138
|
+
this.processing = false;
|
|
139
|
+
this.logger?.debug("Check update end");
|
|
140
|
+
this.emit("update-available", extraVersionInfo);
|
|
141
|
+
return true;
|
|
142
|
+
} catch {
|
|
143
|
+
const msg = "Fail to parse version string";
|
|
144
|
+
this.err("Check update failed", "ERR_VALIDATE", msg);
|
|
145
|
+
return emitUnavailable(msg, "UNAVAILABLE_ERROR", extraVersionInfo);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
async downloadUpdate(data, info) {
|
|
149
|
+
const emitError = (code, errorInfo) => {
|
|
150
|
+
this.err(`Download update failed`, code, errorInfo);
|
|
151
|
+
this.logger?.debug("Download update end");
|
|
152
|
+
this.processing = false;
|
|
153
|
+
return false;
|
|
154
|
+
};
|
|
155
|
+
if (this.processing) {
|
|
156
|
+
this.logger?.info("Updater is already processing, skip download update");
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
this.processing = true;
|
|
160
|
+
this.logger?.debug("Download update start");
|
|
161
|
+
const _sig = info?.signature ?? this.info?.signature;
|
|
162
|
+
const _version = info?.version ?? this.info?.version;
|
|
163
|
+
if (!_sig || !_version) return emitError("ERR_PARAM", "No update signature, please call `checkUpdate` first or manually setup params");
|
|
164
|
+
if (!data && !this.provider) return emitError("ERR_PARAM", "No update asar buffer and provider");
|
|
165
|
+
const buffer = await this.fetch("buffer", data ? Buffer.from(data) : void 0);
|
|
166
|
+
if (!buffer) return emitError("ERR_PARAM", "No update asar file buffer");
|
|
167
|
+
this.logger?.debug("Validation start");
|
|
168
|
+
if (!await this.provider.verifySignaure(buffer, _version, _sig, this.CERT)) return emitError("ERR_VALIDATE", "Invalid update asar file");
|
|
169
|
+
this.logger?.debug("Validation end");
|
|
170
|
+
try {
|
|
171
|
+
this.tmpFilePath = `${getPathFromAppNameAsar()}.tmp`;
|
|
172
|
+
this.logger?.debug(`Install to ${this.tmpFilePath}`);
|
|
173
|
+
fs.writeFileSync(this.tmpFilePath, await this.provider.unzipFile(buffer));
|
|
174
|
+
this.logger?.info(`Download success, version: ${_version}`);
|
|
175
|
+
this.info = void 0;
|
|
176
|
+
this.emit("update-downloaded");
|
|
177
|
+
this.processing = false;
|
|
178
|
+
this.logger?.debug("Download update end");
|
|
179
|
+
return true;
|
|
180
|
+
} catch (error) {
|
|
181
|
+
this.cleanup();
|
|
182
|
+
return emitError("ERR_DOWNLOAD", `Failed to write update file: ${error instanceof Error ? error.message : error}`);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* quit App and install
|
|
187
|
+
*/
|
|
188
|
+
quitAndInstall() {
|
|
189
|
+
this.logger?.info("Quit and install");
|
|
190
|
+
restartApp();
|
|
191
|
+
}
|
|
192
|
+
cancel() {
|
|
193
|
+
if (this.controller.signal.aborted) return;
|
|
194
|
+
this.controller.abort();
|
|
195
|
+
this.cleanup();
|
|
196
|
+
this.logger?.info("Cancel update");
|
|
197
|
+
this.emit("update-cancelled");
|
|
198
|
+
this.controller = new AbortController();
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
/**
|
|
202
|
+
* Auto check update, download and install
|
|
203
|
+
*/
|
|
204
|
+
async function autoUpdate(updater) {
|
|
205
|
+
if (await updater.checkForUpdates() && await updater.downloadUpdate()) updater.quitAndInstall();
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
//#endregion
|
|
209
|
+
//#region src/entry/core.ts
|
|
210
|
+
/**
|
|
211
|
+
* Utils to startup with updater
|
|
212
|
+
* @param fn startup function
|
|
213
|
+
* @example
|
|
214
|
+
* // in electron/main/index.ts
|
|
215
|
+
* export default startupWithUpdater((updater) => {
|
|
216
|
+
* updater.checkUpdate()
|
|
217
|
+
* })
|
|
218
|
+
*/
|
|
219
|
+
function startupWithUpdater(fn) {
|
|
220
|
+
console.log(typeof fn);
|
|
221
|
+
return fn;
|
|
222
|
+
}
|
|
223
|
+
function runWithDefaultExport(mod, args) {
|
|
224
|
+
return (mod.default || mod)(args);
|
|
225
|
+
}
|
|
226
|
+
const defaultOnInstall = (install, _, __, logger) => {
|
|
227
|
+
install();
|
|
228
|
+
logger?.info(`update success!`);
|
|
229
|
+
};
|
|
230
|
+
/**
|
|
231
|
+
* Initialize Electron with updater
|
|
232
|
+
* @example
|
|
233
|
+
* createElectronApp({
|
|
234
|
+
* updater: {
|
|
235
|
+
* provider: new GitHubProvider({
|
|
236
|
+
* username: 'yourname',
|
|
237
|
+
* repo: 'electron',
|
|
238
|
+
* }),
|
|
239
|
+
* },
|
|
240
|
+
* beforeStart(mainFilePath, logger) {
|
|
241
|
+
* logger?.debug(mainFilePath)
|
|
242
|
+
* },
|
|
243
|
+
* })
|
|
244
|
+
*/
|
|
245
|
+
async function createElectronApp(appOptions = {}) {
|
|
246
|
+
const appNameAsarPath = getPathFromAppNameAsar();
|
|
247
|
+
const { mainPath = isDev ? path.join(app.getAppPath(), __EIU_ELECTRON_DIST_PATH__, "main", __EIU_MAIN_FILE__) : path.join(path.dirname(app.getAppPath()), __EIU_ASAR_BASE_NAME__, "main", __EIU_MAIN_FILE__), updater, onInstall = defaultOnInstall, beforeStart, onStartError } = appOptions;
|
|
248
|
+
const updaterInstance = typeof updater === "object" || !updater ? new Updater(updater) : await updater();
|
|
249
|
+
const logger = updaterInstance.logger;
|
|
250
|
+
try {
|
|
251
|
+
const tempAsarPath = `${appNameAsarPath}.tmp`;
|
|
252
|
+
if (fs.existsSync(tempAsarPath)) {
|
|
253
|
+
logger?.info(`Installing new asar from ${tempAsarPath}`);
|
|
254
|
+
await onInstall(() => fs.renameSync(tempAsarPath, appNameAsarPath), tempAsarPath, appNameAsarPath, logger);
|
|
255
|
+
}
|
|
256
|
+
await beforeStart?.(mainPath, logger);
|
|
257
|
+
if (__EIU_IS_ESM__) runWithDefaultExport(await import(`file://${mainPath}`), updaterInstance);
|
|
258
|
+
else runWithDefaultExport(require(mainPath), updaterInstance);
|
|
259
|
+
} catch (error) {
|
|
260
|
+
logger?.error("startup error, exit", error);
|
|
261
|
+
onStartError?.(error, logger);
|
|
262
|
+
app.quit();
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* @deprecated Use {@link createElectronApp} instead
|
|
267
|
+
*/
|
|
268
|
+
const initApp = createElectronApp;
|
|
269
|
+
|
|
270
|
+
//#endregion
|
|
271
|
+
export { Updater, UpdaterError, autoUpdate, createElectronApp, initApp, startupWithUpdater };
|