electron-incremental-update 3.0.0-beta.4 → 3.0.0-beta.6
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 +580 -887
- package/dist/{zip-Dwm7s1C9.mjs → download-BGaAyi1Z.mjs} +16 -69
- package/dist/download-BYnkme_X.cjs +167 -0
- package/dist/{download-BN4uMS4_.d.mts → download-BjWmHHAu.d.cts} +1 -1
- package/dist/{download-DO7iuxEJ.d.cts → download-DVWJfV3S.d.mts} +1 -1
- package/dist/{electron-BJCk7uxG.mjs → electron-BInvFJ-W.mjs} +38 -13
- package/dist/electron-D_8AbLQ5.cjs +346 -0
- package/dist/index.cjs +64 -32
- package/dist/index.d.cts +10 -13
- package/dist/index.d.mts +10 -13
- package/dist/index.mjs +60 -29
- package/dist/local-Daf8naRn.cjs +118 -0
- package/dist/local-s1cw_vwb.mjs +105 -0
- package/dist/provider.cjs +21 -40
- package/dist/provider.d.cts +53 -9
- package/dist/provider.d.mts +53 -9
- package/dist/provider.mjs +9 -30
- package/dist/{types-BM9Jfu7q.d.cts → types-BOqQ_r5Q.d.cts} +5 -5
- package/dist/{types-DASqEPXE.d.mts → types-BOqQ_r5Q.d.mts} +5 -5
- package/dist/utils.cjs +15 -15
- package/dist/utils.d.cts +2 -2
- package/dist/utils.d.mts +2 -2
- package/dist/utils.mjs +4 -5
- package/dist/vite.d.mts +122 -167
- package/dist/vite.mjs +684 -753
- package/dist/zip-D1dbBzw4.cjs +254 -0
- package/dist/zip-DUK3opmV.mjs +159 -0
- package/package.json +30 -35
- package/dist/electron-C-qmVhAt.cjs +0 -321
- package/dist/version--eVB2A7n.mjs +0 -72
- package/dist/version-aPrLuz_-.cjs +0 -129
- package/dist/zip-BCC7FAQ_.cjs +0 -264
package/dist/index.mjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { u as isUpdateJSON } from "./zip-DUK3opmV.mjs";
|
|
2
|
+
import { t as LocalDevProvider } from "./local-s1cw_vwb.mjs";
|
|
3
|
+
import { a as getPathFromAppNameAsar, f as isDev, i as getEntryVersion, r as getAppVersion, y as restartApp } from "./electron-BInvFJ-W.mjs";
|
|
4
4
|
import fs from "node:fs";
|
|
5
5
|
import path from "node:path";
|
|
6
|
+
import { BrowserWindow, app } from "electron";
|
|
6
7
|
import { EventEmitter } from "node:events";
|
|
7
|
-
|
|
8
8
|
//#region src/entry/types.ts
|
|
9
9
|
var UpdaterError = class extends Error {
|
|
10
10
|
code;
|
|
@@ -13,12 +13,12 @@ var UpdaterError = class extends Error {
|
|
|
13
13
|
this.code = code;
|
|
14
14
|
}
|
|
15
15
|
};
|
|
16
|
-
|
|
17
16
|
//#endregion
|
|
18
17
|
//#region src/entry/updater.ts
|
|
19
18
|
var Updater = class extends EventEmitter {
|
|
20
19
|
CERT;
|
|
21
20
|
controller;
|
|
21
|
+
getCurrentAppVersion;
|
|
22
22
|
info;
|
|
23
23
|
tmpFilePath;
|
|
24
24
|
processing = false;
|
|
@@ -45,6 +45,7 @@ var Updater = class extends EventEmitter {
|
|
|
45
45
|
this.receiveBeta = options.receiveBeta;
|
|
46
46
|
this.CERT = options.SIGNATURE_CERT || __EIU_SIGNATURE_CERT__;
|
|
47
47
|
this.logger = options.logger;
|
|
48
|
+
this.getCurrentAppVersion = options.getAppVersion ?? getAppVersion;
|
|
48
49
|
this.controller = new AbortController();
|
|
49
50
|
if (isDev && !this.logger) {
|
|
50
51
|
this.logger = {
|
|
@@ -55,7 +56,6 @@ var Updater = class extends EventEmitter {
|
|
|
55
56
|
};
|
|
56
57
|
this.logger.info("No logger set, enable dev-only logger");
|
|
57
58
|
}
|
|
58
|
-
if (!this.provider) this.logger?.debug("WARN: No update provider");
|
|
59
59
|
}
|
|
60
60
|
async fetch(format, data) {
|
|
61
61
|
if (typeof data === "object") if (format === "json" && isUpdateJSON(data) || format === "buffer" && Buffer.isBuffer(data)) return data;
|
|
@@ -88,9 +88,12 @@ var Updater = class extends EventEmitter {
|
|
|
88
88
|
const err = new UpdaterError(code, errorInfo);
|
|
89
89
|
this.logger?.error(`[${code}] ${msg}`, err);
|
|
90
90
|
this.cleanup();
|
|
91
|
-
this.emit("error", err);
|
|
91
|
+
if (this.listenerCount("error") > 0) this.emit("error", err);
|
|
92
92
|
}
|
|
93
|
-
|
|
93
|
+
/**
|
|
94
|
+
* Check update info using default options
|
|
95
|
+
*/
|
|
96
|
+
async checkForUpdates() {
|
|
94
97
|
const emitUnavailable = (msg, code, info) => {
|
|
95
98
|
this.logger?.info(`[${code}] ${msg}`);
|
|
96
99
|
this.logger?.debug("Check update end");
|
|
@@ -98,18 +101,18 @@ var Updater = class extends EventEmitter {
|
|
|
98
101
|
this.emit("update-not-available", code, msg, info);
|
|
99
102
|
return false;
|
|
100
103
|
};
|
|
104
|
+
if (!this.provider) {
|
|
105
|
+
const msg = "No update json or provider";
|
|
106
|
+
this.err("Check update failed", "ERR_PARAM", msg);
|
|
107
|
+
return emitUnavailable(msg, "UNAVAILABLE_ERROR");
|
|
108
|
+
}
|
|
101
109
|
if (this.processing) {
|
|
102
110
|
this.logger?.info("Updater is already processing, skip check update");
|
|
103
111
|
return false;
|
|
104
112
|
}
|
|
105
113
|
this.processing = true;
|
|
106
114
|
this.logger?.debug("Check update start");
|
|
107
|
-
|
|
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);
|
|
115
|
+
const _data = await this.fetch("json");
|
|
113
116
|
if (!_data) return emitUnavailable("Failed to get update info", "UNAVAILABLE_ERROR");
|
|
114
117
|
const { signature, version, minimumVersion, url, ...rest } = this.receiveBeta ? _data.beta : _data;
|
|
115
118
|
const info = {
|
|
@@ -122,12 +125,12 @@ var Updater = class extends EventEmitter {
|
|
|
122
125
|
signature,
|
|
123
126
|
minimumVersion,
|
|
124
127
|
version,
|
|
125
|
-
appVersion:
|
|
128
|
+
appVersion: this.getCurrentAppVersion(),
|
|
126
129
|
entryVersion: getEntryVersion(),
|
|
127
130
|
...rest
|
|
128
131
|
};
|
|
129
132
|
this.logger?.debug(`Checked update, version: ${version}, signature: ${signature}`);
|
|
130
|
-
if (isDev && !this.forceUpdate
|
|
133
|
+
if (isDev && !this.forceUpdate) return emitUnavailable("Skip check update in dev mode. To force update, set `updater.forceUpdate` to `true`", "UNAVAILABLE_DEV");
|
|
131
134
|
const isLowerVersion = this.provider.isLowerVersion;
|
|
132
135
|
try {
|
|
133
136
|
if (isLowerVersion(extraVersionInfo.entryVersion, minimumVersion)) return emitUnavailable(`Entry Version (${extraVersionInfo.entryVersion}) < MinimumVersion (${minimumVersion})`, "UNAVAILABLE_VERSION", extraVersionInfo);
|
|
@@ -145,25 +148,32 @@ var Updater = class extends EventEmitter {
|
|
|
145
148
|
return emitUnavailable(msg, "UNAVAILABLE_ERROR", extraVersionInfo);
|
|
146
149
|
}
|
|
147
150
|
}
|
|
148
|
-
|
|
151
|
+
/**
|
|
152
|
+
* Download update using default options
|
|
153
|
+
*/
|
|
154
|
+
async downloadUpdate() {
|
|
149
155
|
const emitError = (code, errorInfo) => {
|
|
150
156
|
this.err(`Download update failed`, code, errorInfo);
|
|
151
157
|
this.logger?.debug("Download update end");
|
|
152
158
|
this.processing = false;
|
|
153
159
|
return false;
|
|
154
160
|
};
|
|
161
|
+
if (!this.provider) return emitError("ERR_PARAM", "No update asar buffer and provider");
|
|
155
162
|
if (this.processing) {
|
|
156
163
|
this.logger?.info("Updater is already processing, skip download update");
|
|
157
164
|
return false;
|
|
158
165
|
}
|
|
159
166
|
this.processing = true;
|
|
160
167
|
this.logger?.debug("Download update start");
|
|
161
|
-
const _sig =
|
|
162
|
-
const _version =
|
|
163
|
-
if (!_sig || !_version) return emitError("ERR_PARAM", "No update signature, please call `checkUpdate` first
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
168
|
+
const _sig = this.info?.signature;
|
|
169
|
+
const _version = this.info?.version;
|
|
170
|
+
if (!_sig || !_version) return emitError("ERR_PARAM", "No update signature, please call `checkUpdate` first");
|
|
171
|
+
const buffer = await this.fetch("buffer");
|
|
172
|
+
if (!buffer) {
|
|
173
|
+
this.logger?.debug("Download update end");
|
|
174
|
+
this.processing = false;
|
|
175
|
+
return false;
|
|
176
|
+
}
|
|
167
177
|
this.logger?.debug("Validation start");
|
|
168
178
|
if (!await this.provider.verifySignaure(buffer, _version, _sig, this.CERT)) return emitError("ERR_VALIDATE", "Invalid update asar file");
|
|
169
179
|
this.logger?.debug("Validation end");
|
|
@@ -204,7 +214,6 @@ var Updater = class extends EventEmitter {
|
|
|
204
214
|
async function autoUpdate(updater) {
|
|
205
215
|
if (await updater.checkForUpdates() && await updater.downloadUpdate()) updater.quitAndInstall();
|
|
206
216
|
}
|
|
207
|
-
|
|
208
217
|
//#endregion
|
|
209
218
|
//#region src/entry/core.ts
|
|
210
219
|
/**
|
|
@@ -229,6 +238,25 @@ const defaultOnInstall = (install, _, __, logger) => {
|
|
|
229
238
|
install();
|
|
230
239
|
logger?.info(`update success!`);
|
|
231
240
|
};
|
|
241
|
+
function readDevAsarVersion() {
|
|
242
|
+
try {
|
|
243
|
+
return fs.readFileSync(getPathFromAppNameAsar("version"), "utf-8").trim();
|
|
244
|
+
} catch {
|
|
245
|
+
return app.getVersion();
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
function resolveUpdaterOption(updater) {
|
|
249
|
+
if (!isDev || !__EIU_LOCAL_DEV_UPDATE__ || updater?.provider) return updater;
|
|
250
|
+
return {
|
|
251
|
+
...updater,
|
|
252
|
+
provider: new LocalDevProvider({
|
|
253
|
+
baseDir: __EIU_LOCAL_DEV_UPDATE_DIR__,
|
|
254
|
+
chunkDelay: __EIU_LOCAL_DEV_UPDATE_CHUNK_DELAY__,
|
|
255
|
+
chunkSize: __EIU_LOCAL_DEV_UPDATE_CHUNK_SIZE__
|
|
256
|
+
}),
|
|
257
|
+
getAppVersion: updater?.getAppVersion ?? readDevAsarVersion
|
|
258
|
+
};
|
|
259
|
+
}
|
|
232
260
|
/**
|
|
233
261
|
* Initialize Electron with updater
|
|
234
262
|
* @example
|
|
@@ -247,7 +275,9 @@ const defaultOnInstall = (install, _, __, logger) => {
|
|
|
247
275
|
async function createElectronApp(appOptions = {}) {
|
|
248
276
|
const appNameAsarPath = getPathFromAppNameAsar();
|
|
249
277
|
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;
|
|
250
|
-
const
|
|
278
|
+
const useAutoLocalDevProvider = isDev && __EIU_LOCAL_DEV_UPDATE__ && typeof updater !== "function";
|
|
279
|
+
const updaterInstance = typeof updater === "object" || !updater ? new Updater(resolveUpdaterOption(updater)) : await updater();
|
|
280
|
+
if (useAutoLocalDevProvider && updaterInstance.provider?.name === "LocalDevProvider") updaterInstance.forceUpdate = true;
|
|
251
281
|
const logger = updaterInstance.logger;
|
|
252
282
|
try {
|
|
253
283
|
const tempAsarPath = `${appNameAsarPath}.tmp`;
|
|
@@ -256,8 +286,10 @@ async function createElectronApp(appOptions = {}) {
|
|
|
256
286
|
await onInstall(() => fs.renameSync(tempAsarPath, appNameAsarPath), tempAsarPath, appNameAsarPath, logger);
|
|
257
287
|
}
|
|
258
288
|
await beforeStart?.(mainPath, logger);
|
|
259
|
-
if (__EIU_IS_ESM__)
|
|
260
|
-
|
|
289
|
+
if (__EIU_IS_ESM__) {
|
|
290
|
+
const { pathToFileURL } = await import("node:url");
|
|
291
|
+
runWithDefaultExport(await import(pathToFileURL(mainPath).href), updaterInstance);
|
|
292
|
+
} else runWithDefaultExport(require(mainPath), updaterInstance);
|
|
261
293
|
} catch (error) {
|
|
262
294
|
logger?.error("Fail to startup", error);
|
|
263
295
|
onStartError?.(error, logger);
|
|
@@ -268,6 +300,5 @@ async function createElectronApp(appOptions = {}) {
|
|
|
268
300
|
* @deprecated Use {@link createElectronApp} instead
|
|
269
301
|
*/
|
|
270
302
|
const initApp = createElectronApp;
|
|
271
|
-
|
|
272
303
|
//#endregion
|
|
273
|
-
export { Updater, UpdaterError, autoUpdate, createElectronApp, initApp, startupWithUpdater };
|
|
304
|
+
export { Updater, UpdaterError, autoUpdate, createElectronApp, initApp, startupWithUpdater };
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
const require_zip = require("./zip-D1dbBzw4.cjs");
|
|
2
|
+
let node_path = require("node:path");
|
|
3
|
+
node_path = require_zip.__toESM(node_path, 1);
|
|
4
|
+
let node_fs_promises = require("node:fs/promises");
|
|
5
|
+
node_fs_promises = require_zip.__toESM(node_fs_promises, 1);
|
|
6
|
+
//#region src/provider/base.ts
|
|
7
|
+
var BaseProvider = class {
|
|
8
|
+
name = "BaseProvider";
|
|
9
|
+
/**
|
|
10
|
+
* @inheritdoc
|
|
11
|
+
*/
|
|
12
|
+
isLowerVersion = require_zip.defaultIsLowerVersion;
|
|
13
|
+
/**
|
|
14
|
+
* @inheritdoc
|
|
15
|
+
*/
|
|
16
|
+
verifySignaure = require_zip.defaultVerifySignature;
|
|
17
|
+
/**
|
|
18
|
+
* @inheritdoc
|
|
19
|
+
*/
|
|
20
|
+
unzipFile = require_zip.defaultUnzipFile;
|
|
21
|
+
};
|
|
22
|
+
//#endregion
|
|
23
|
+
//#region src/provider/local.ts
|
|
24
|
+
/**
|
|
25
|
+
* Update Provider for local development
|
|
26
|
+
* - download update json from `{baseDir}/{versionPath}`
|
|
27
|
+
* - download update asar from `{baseDir}/{name}-{version}.asar.gz`
|
|
28
|
+
*
|
|
29
|
+
* This provider is useful for testing updates during development without
|
|
30
|
+
* needing to deploy to a remote server.
|
|
31
|
+
* @param options provider options
|
|
32
|
+
*/
|
|
33
|
+
var LocalDevProvider = class extends BaseProvider {
|
|
34
|
+
name = "LocalDevProvider";
|
|
35
|
+
verifySignaure;
|
|
36
|
+
options;
|
|
37
|
+
constructor(options) {
|
|
38
|
+
super();
|
|
39
|
+
const resolvedOptions = {
|
|
40
|
+
chunkSize: 64 * 1024,
|
|
41
|
+
chunkDelay: 30,
|
|
42
|
+
...options
|
|
43
|
+
};
|
|
44
|
+
if (resolvedOptions.chunkSize <= 0) throw new Error("localDevUpdate.chunkSize must be greater than 0");
|
|
45
|
+
if (resolvedOptions.chunkDelay < 0) throw new Error("localDevUpdate.chunkDelay must be greater than or equal to 0");
|
|
46
|
+
this.options = resolvedOptions;
|
|
47
|
+
this.verifySignaure = async function verifySignaure() {
|
|
48
|
+
return true;
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* @inheritdoc
|
|
53
|
+
*/
|
|
54
|
+
async downloadJSON(name, versionPath, signal) {
|
|
55
|
+
signal.throwIfAborted();
|
|
56
|
+
const { beta, version, ...info } = await this.readJSON(versionPath);
|
|
57
|
+
const getURL = (ver) => node_path.default.join(this.options.baseDir, `${name}-${ver}.asar.gz`);
|
|
58
|
+
return {
|
|
59
|
+
...info,
|
|
60
|
+
version,
|
|
61
|
+
url: getURL(version),
|
|
62
|
+
beta: {
|
|
63
|
+
...beta,
|
|
64
|
+
url: getURL(beta.version)
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* @inheritdoc
|
|
70
|
+
*/
|
|
71
|
+
async downloadAsar(info, signal, onDownloading) {
|
|
72
|
+
signal.throwIfAborted();
|
|
73
|
+
const fileBuffer = await node_fs_promises.default.readFile(info.url);
|
|
74
|
+
await this.emitProgress(fileBuffer, signal, onDownloading);
|
|
75
|
+
return fileBuffer;
|
|
76
|
+
}
|
|
77
|
+
async readJSON(versionPath) {
|
|
78
|
+
const fullPath = node_path.default.join(this.options.baseDir, versionPath);
|
|
79
|
+
const content = await node_fs_promises.default.readFile(fullPath, "utf-8");
|
|
80
|
+
const json = JSON.parse(content);
|
|
81
|
+
if (!require_zip.isUpdateJSON(json)) throw new Error(`Invalid update json: ${content}`);
|
|
82
|
+
return json;
|
|
83
|
+
}
|
|
84
|
+
async emitProgress(fileBuffer, signal, onDownloading) {
|
|
85
|
+
if (!onDownloading) return;
|
|
86
|
+
const total = fileBuffer.length;
|
|
87
|
+
let transferred = 0;
|
|
88
|
+
let lastTime = Date.now();
|
|
89
|
+
while (transferred < total) {
|
|
90
|
+
signal.throwIfAborted();
|
|
91
|
+
const currentTime = Date.now();
|
|
92
|
+
const delta = Math.min(this.options.chunkSize, total - transferred);
|
|
93
|
+
transferred += delta;
|
|
94
|
+
onDownloading({
|
|
95
|
+
delta,
|
|
96
|
+
percent: Math.round(transferred / total * 100),
|
|
97
|
+
total,
|
|
98
|
+
transferred,
|
|
99
|
+
bps: Math.round(delta / Math.max(currentTime - lastTime, 1) * 1e3)
|
|
100
|
+
});
|
|
101
|
+
lastTime = currentTime;
|
|
102
|
+
if (transferred < total && this.options.chunkDelay > 0) await new Promise((resolve) => setTimeout(resolve, this.options.chunkDelay));
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
//#endregion
|
|
107
|
+
Object.defineProperty(exports, "BaseProvider", {
|
|
108
|
+
enumerable: true,
|
|
109
|
+
get: function() {
|
|
110
|
+
return BaseProvider;
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
Object.defineProperty(exports, "LocalDevProvider", {
|
|
114
|
+
enumerable: true,
|
|
115
|
+
get: function() {
|
|
116
|
+
return LocalDevProvider;
|
|
117
|
+
}
|
|
118
|
+
});
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { c as defaultIsLowerVersion, o as defaultVerifySignature, t as defaultUnzipFile, u as isUpdateJSON } from "./zip-DUK3opmV.mjs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import fs from "node:fs/promises";
|
|
4
|
+
//#region src/provider/base.ts
|
|
5
|
+
var BaseProvider = class {
|
|
6
|
+
name = "BaseProvider";
|
|
7
|
+
/**
|
|
8
|
+
* @inheritdoc
|
|
9
|
+
*/
|
|
10
|
+
isLowerVersion = defaultIsLowerVersion;
|
|
11
|
+
/**
|
|
12
|
+
* @inheritdoc
|
|
13
|
+
*/
|
|
14
|
+
verifySignaure = defaultVerifySignature;
|
|
15
|
+
/**
|
|
16
|
+
* @inheritdoc
|
|
17
|
+
*/
|
|
18
|
+
unzipFile = defaultUnzipFile;
|
|
19
|
+
};
|
|
20
|
+
//#endregion
|
|
21
|
+
//#region src/provider/local.ts
|
|
22
|
+
/**
|
|
23
|
+
* Update Provider for local development
|
|
24
|
+
* - download update json from `{baseDir}/{versionPath}`
|
|
25
|
+
* - download update asar from `{baseDir}/{name}-{version}.asar.gz`
|
|
26
|
+
*
|
|
27
|
+
* This provider is useful for testing updates during development without
|
|
28
|
+
* needing to deploy to a remote server.
|
|
29
|
+
* @param options provider options
|
|
30
|
+
*/
|
|
31
|
+
var LocalDevProvider = class extends BaseProvider {
|
|
32
|
+
name = "LocalDevProvider";
|
|
33
|
+
verifySignaure;
|
|
34
|
+
options;
|
|
35
|
+
constructor(options) {
|
|
36
|
+
super();
|
|
37
|
+
const resolvedOptions = {
|
|
38
|
+
chunkSize: 64 * 1024,
|
|
39
|
+
chunkDelay: 30,
|
|
40
|
+
...options
|
|
41
|
+
};
|
|
42
|
+
if (resolvedOptions.chunkSize <= 0) throw new Error("localDevUpdate.chunkSize must be greater than 0");
|
|
43
|
+
if (resolvedOptions.chunkDelay < 0) throw new Error("localDevUpdate.chunkDelay must be greater than or equal to 0");
|
|
44
|
+
this.options = resolvedOptions;
|
|
45
|
+
this.verifySignaure = async function verifySignaure() {
|
|
46
|
+
return true;
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* @inheritdoc
|
|
51
|
+
*/
|
|
52
|
+
async downloadJSON(name, versionPath, signal) {
|
|
53
|
+
signal.throwIfAborted();
|
|
54
|
+
const { beta, version, ...info } = await this.readJSON(versionPath);
|
|
55
|
+
const getURL = (ver) => path.join(this.options.baseDir, `${name}-${ver}.asar.gz`);
|
|
56
|
+
return {
|
|
57
|
+
...info,
|
|
58
|
+
version,
|
|
59
|
+
url: getURL(version),
|
|
60
|
+
beta: {
|
|
61
|
+
...beta,
|
|
62
|
+
url: getURL(beta.version)
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* @inheritdoc
|
|
68
|
+
*/
|
|
69
|
+
async downloadAsar(info, signal, onDownloading) {
|
|
70
|
+
signal.throwIfAborted();
|
|
71
|
+
const fileBuffer = await fs.readFile(info.url);
|
|
72
|
+
await this.emitProgress(fileBuffer, signal, onDownloading);
|
|
73
|
+
return fileBuffer;
|
|
74
|
+
}
|
|
75
|
+
async readJSON(versionPath) {
|
|
76
|
+
const fullPath = path.join(this.options.baseDir, versionPath);
|
|
77
|
+
const content = await fs.readFile(fullPath, "utf-8");
|
|
78
|
+
const json = JSON.parse(content);
|
|
79
|
+
if (!isUpdateJSON(json)) throw new Error(`Invalid update json: ${content}`);
|
|
80
|
+
return json;
|
|
81
|
+
}
|
|
82
|
+
async emitProgress(fileBuffer, signal, onDownloading) {
|
|
83
|
+
if (!onDownloading) return;
|
|
84
|
+
const total = fileBuffer.length;
|
|
85
|
+
let transferred = 0;
|
|
86
|
+
let lastTime = Date.now();
|
|
87
|
+
while (transferred < total) {
|
|
88
|
+
signal.throwIfAborted();
|
|
89
|
+
const currentTime = Date.now();
|
|
90
|
+
const delta = Math.min(this.options.chunkSize, total - transferred);
|
|
91
|
+
transferred += delta;
|
|
92
|
+
onDownloading({
|
|
93
|
+
delta,
|
|
94
|
+
percent: Math.round(transferred / total * 100),
|
|
95
|
+
total,
|
|
96
|
+
transferred,
|
|
97
|
+
bps: Math.round(delta / Math.max(currentTime - lastTime, 1) * 1e3)
|
|
98
|
+
});
|
|
99
|
+
lastTime = currentTime;
|
|
100
|
+
if (transferred < total && this.options.chunkDelay > 0) await new Promise((resolve) => setTimeout(resolve, this.options.chunkDelay));
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
//#endregion
|
|
105
|
+
export { BaseProvider as n, LocalDevProvider as t };
|
package/dist/provider.cjs
CHANGED
|
@@ -1,27 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
const
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_local = require("./local-Daf8naRn.cjs");
|
|
3
|
+
const require_download = require("./download-BYnkme_X.cjs");
|
|
3
4
|
let node_url = require("node:url");
|
|
4
|
-
|
|
5
|
-
//#region src/provider/base.ts
|
|
6
|
-
var BaseProvider = class {
|
|
7
|
-
name = "BaseProvider";
|
|
8
|
-
/**
|
|
9
|
-
* @inheritdoc
|
|
10
|
-
*/
|
|
11
|
-
isLowerVersion = require_version.defaultIsLowerVersion;
|
|
12
|
-
/**
|
|
13
|
-
* @inheritdoc
|
|
14
|
-
*/
|
|
15
|
-
verifySignaure = require_zip.defaultVerifySignature;
|
|
16
|
-
/**
|
|
17
|
-
* @inheritdoc
|
|
18
|
-
*/
|
|
19
|
-
unzipFile = require_zip.defaultUnzipFile;
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
//#endregion
|
|
23
5
|
//#region src/provider/github/base.ts
|
|
24
|
-
var BaseGitHubProvider = class extends BaseProvider {
|
|
6
|
+
var BaseGitHubProvider = class extends require_local.BaseProvider {
|
|
7
|
+
options;
|
|
25
8
|
constructor(options) {
|
|
26
9
|
super();
|
|
27
10
|
this.options = options;
|
|
@@ -32,12 +15,12 @@ var BaseGitHubProvider = class extends BaseProvider {
|
|
|
32
15
|
set urlHandler(handler) {
|
|
33
16
|
this.options.urlHandler = handler;
|
|
34
17
|
}
|
|
35
|
-
async parseURL(
|
|
36
|
-
const url = new node_url.URL(`/${this.options.user}/${this.options.repo}/${
|
|
18
|
+
async parseURL(pathOrURL) {
|
|
19
|
+
const url = node_url.URL.canParse(pathOrURL) ? new node_url.URL(pathOrURL) : new node_url.URL(`/${this.options.user}/${this.options.repo}/${pathOrURL}`, "https://github.com");
|
|
37
20
|
return (await this.urlHandler?.(url) || url).toString();
|
|
38
21
|
}
|
|
39
22
|
async downloadJSON(name, versionPath, signal) {
|
|
40
|
-
const { beta, version, ...info } = await
|
|
23
|
+
const { beta, version, ...info } = await require_download.defaultDownloadUpdateJSON(await this.parseURL(await this.getVersionURL(versionPath, signal)), this.getHeaders("json"), signal);
|
|
41
24
|
const getURL = (ver) => this.parseURL(`releases/download/v${ver}/${name}-${ver}.asar.gz`);
|
|
42
25
|
return {
|
|
43
26
|
...info,
|
|
@@ -53,10 +36,9 @@ var BaseGitHubProvider = class extends BaseProvider {
|
|
|
53
36
|
* @inheritdoc
|
|
54
37
|
*/
|
|
55
38
|
async downloadAsar(info, signal, onDownloading) {
|
|
56
|
-
return await
|
|
39
|
+
return await require_download.defaultDownloadAsar(info.url, this.getHeaders("octet-stream"), signal, onDownloading);
|
|
57
40
|
}
|
|
58
41
|
};
|
|
59
|
-
|
|
60
42
|
//#endregion
|
|
61
43
|
//#region src/provider/github/api.ts
|
|
62
44
|
const ERROR_MSG = "Cannot find UpdateJSON in latest release";
|
|
@@ -83,13 +65,12 @@ var GitHubApiProvider = class extends BaseGitHubProvider {
|
|
|
83
65
|
*/
|
|
84
66
|
async getVersionURL(versionPath, signal) {
|
|
85
67
|
const basename = versionPath.slice(versionPath.lastIndexOf("/") + 1);
|
|
86
|
-
const data = await
|
|
68
|
+
const data = await require_download.defaultDownloadText(await this.parseURL(`https://api.github.com/repos/${this.options.user}/${this.options.repo}/releases?per_page=1`), this.getHeaders("vnd.github.v3+json"), signal, require_download.resolveJson);
|
|
87
69
|
const versionAssets = data[0]?.assets.find((asset) => asset.name === basename);
|
|
88
70
|
if (!versionAssets) throw new Error(`${ERROR_MSG}, ${"message" in data ? data.message : "please check the release assets"}`);
|
|
89
71
|
return versionAssets.browser_download_url;
|
|
90
72
|
}
|
|
91
73
|
};
|
|
92
|
-
|
|
93
74
|
//#endregion
|
|
94
75
|
//#region src/provider/github/atom.ts
|
|
95
76
|
/**
|
|
@@ -113,14 +94,14 @@ var GitHubAtomProvider = class extends BaseGitHubProvider {
|
|
|
113
94
|
* @inheritdoc
|
|
114
95
|
*/
|
|
115
96
|
async getVersionURL(versionPath, signal) {
|
|
116
|
-
|
|
97
|
+
const tag = await require_download.defaultDownloadText(await this.parseURL(`releases.atom`), this.getHeaders("xml"), signal, (data, resolve, reject) => {
|
|
117
98
|
const result = data.match(/<entry>\s*<id>([^<]*\/)?([^/<]+)<\/id>/)?.[2];
|
|
118
99
|
if (result) resolve(result);
|
|
119
100
|
else reject("No tag matched");
|
|
120
|
-
})
|
|
101
|
+
});
|
|
102
|
+
return `releases/download/v${tag.startsWith("v") ? tag.slice(1) : tag}/${versionPath}`;
|
|
121
103
|
}
|
|
122
104
|
};
|
|
123
|
-
|
|
124
105
|
//#endregion
|
|
125
106
|
//#region src/provider/github/file.ts
|
|
126
107
|
/**
|
|
@@ -147,16 +128,16 @@ var GitHubProvider = class extends BaseGitHubProvider {
|
|
|
147
128
|
return `raw/${this.options.branch}/${versionPath}`;
|
|
148
129
|
}
|
|
149
130
|
};
|
|
150
|
-
|
|
151
131
|
//#endregion
|
|
152
132
|
exports.BaseGitHubProvider = BaseGitHubProvider;
|
|
153
|
-
exports.BaseProvider = BaseProvider;
|
|
133
|
+
exports.BaseProvider = require_local.BaseProvider;
|
|
154
134
|
exports.GitHubApiProvider = GitHubApiProvider;
|
|
155
135
|
exports.GitHubAtomProvider = GitHubAtomProvider;
|
|
156
136
|
exports.GitHubProvider = GitHubProvider;
|
|
157
|
-
exports.
|
|
158
|
-
exports.
|
|
159
|
-
exports.
|
|
160
|
-
exports.
|
|
161
|
-
exports.
|
|
162
|
-
exports.
|
|
137
|
+
exports.LocalDevProvider = require_local.LocalDevProvider;
|
|
138
|
+
exports.defaultDownloadAsar = require_download.defaultDownloadAsar;
|
|
139
|
+
exports.defaultDownloadText = require_download.defaultDownloadText;
|
|
140
|
+
exports.defaultDownloadUpdateJSON = require_download.defaultDownloadUpdateJSON;
|
|
141
|
+
exports.downloadUtil = require_download.downloadUtil;
|
|
142
|
+
exports.getHeader = require_download.getHeader;
|
|
143
|
+
exports.resolveJson = require_download.resolveJson;
|
package/dist/provider.d.cts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
import { a as getHeader, i as downloadUtil, n as defaultDownloadText, o as resolveJson, r as defaultDownloadUpdateJSON, t as defaultDownloadAsar } from "./download-
|
|
1
|
+
import { a as VersionJSON, i as UpdateInfoWithURL, m as Promisable, n as IProvider, r as URLHandler, t as DownloadingInfo } from "./types-BOqQ_r5Q.cjs";
|
|
2
|
+
import { a as getHeader, i as downloadUtil, n as defaultDownloadText, o as resolveJson, r as defaultDownloadUpdateJSON, t as defaultDownloadAsar } from "./download-BjWmHHAu.cjs";
|
|
3
|
+
import { Buffer as Buffer$1 } from "node:buffer";
|
|
3
4
|
|
|
4
5
|
//#region src/provider/base.d.ts
|
|
5
6
|
declare abstract class BaseProvider implements IProvider {
|
|
@@ -19,7 +20,7 @@ declare abstract class BaseProvider implements IProvider {
|
|
|
19
20
|
/**
|
|
20
21
|
* @inheritdoc
|
|
21
22
|
*/
|
|
22
|
-
abstract downloadJSON(name: string, versionPath: string, signal: AbortSignal): Promise<
|
|
23
|
+
abstract downloadJSON(name: string, versionPath: string, signal: AbortSignal): Promise<VersionJSON>;
|
|
23
24
|
/**
|
|
24
25
|
* @inheritdoc
|
|
25
26
|
*/
|
|
@@ -56,10 +57,10 @@ declare abstract class BaseGitHubProvider<T extends BaseGitHubProviderOptions =
|
|
|
56
57
|
constructor(options: T);
|
|
57
58
|
get urlHandler(): URLHandler | undefined;
|
|
58
59
|
set urlHandler(handler: URLHandler);
|
|
59
|
-
protected parseURL(
|
|
60
|
+
protected parseURL(pathOrURL: string): Promise<string>;
|
|
60
61
|
protected abstract getHeaders(accept: string): Record<string, string>;
|
|
61
62
|
protected abstract getVersionURL(versionPath: string, signal: AbortSignal): Promisable<string>;
|
|
62
|
-
downloadJSON(name: string, versionPath: string, signal: AbortSignal): Promise<
|
|
63
|
+
downloadJSON(name: string, versionPath: string, signal: AbortSignal): Promise<VersionJSON>;
|
|
63
64
|
/**
|
|
64
65
|
* @inheritdoc
|
|
65
66
|
*/
|
|
@@ -80,7 +81,7 @@ interface GitHubApiProviderOptions extends BaseGitHubProviderOptions {
|
|
|
80
81
|
* @param options provider options
|
|
81
82
|
*/
|
|
82
83
|
declare class GitHubApiProvider extends BaseGitHubProvider<GitHubApiProviderOptions> {
|
|
83
|
-
name: string;
|
|
84
|
+
override name: string;
|
|
84
85
|
protected getHeaders(accept: string): Record<string, string>;
|
|
85
86
|
/**
|
|
86
87
|
* @inheritdoc
|
|
@@ -99,7 +100,7 @@ declare class GitHubApiProvider extends BaseGitHubProvider<GitHubApiProviderOpti
|
|
|
99
100
|
* @param options provider options
|
|
100
101
|
*/
|
|
101
102
|
declare class GitHubAtomProvider extends BaseGitHubProvider {
|
|
102
|
-
name: string;
|
|
103
|
+
override name: string;
|
|
103
104
|
protected getHeaders(accept: string): Record<string, string>;
|
|
104
105
|
/**
|
|
105
106
|
* @inheritdoc
|
|
@@ -124,10 +125,53 @@ interface GitHubProviderOptions extends BaseGitHubProviderOptions {
|
|
|
124
125
|
* @param options provider options
|
|
125
126
|
*/
|
|
126
127
|
declare class GitHubProvider extends BaseGitHubProvider<GitHubProviderOptions> {
|
|
127
|
-
name: string;
|
|
128
|
+
override name: string;
|
|
128
129
|
constructor(options: GitHubProviderOptions);
|
|
129
130
|
protected getHeaders(accept: string): Record<string, string>;
|
|
130
131
|
protected getVersionURL(versionPath: string): string;
|
|
131
132
|
}
|
|
132
133
|
//#endregion
|
|
133
|
-
|
|
134
|
+
//#region src/provider/local.d.ts
|
|
135
|
+
interface LocalDevProviderOptions {
|
|
136
|
+
/**
|
|
137
|
+
* Base directory for update files
|
|
138
|
+
*/
|
|
139
|
+
baseDir: string;
|
|
140
|
+
/**
|
|
141
|
+
* Local read chunk size for simulated download progress
|
|
142
|
+
* @default 64 * 1024
|
|
143
|
+
*/
|
|
144
|
+
chunkSize?: number;
|
|
145
|
+
/**
|
|
146
|
+
* Delay between chunks in milliseconds
|
|
147
|
+
* @default 30
|
|
148
|
+
*/
|
|
149
|
+
chunkDelay?: number;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Update Provider for local development
|
|
153
|
+
* - download update json from `{baseDir}/{versionPath}`
|
|
154
|
+
* - download update asar from `{baseDir}/{name}-{version}.asar.gz`
|
|
155
|
+
*
|
|
156
|
+
* This provider is useful for testing updates during development without
|
|
157
|
+
* needing to deploy to a remote server.
|
|
158
|
+
* @param options provider options
|
|
159
|
+
*/
|
|
160
|
+
declare class LocalDevProvider extends BaseProvider {
|
|
161
|
+
override name: string;
|
|
162
|
+
override verifySignaure: IProvider["verifySignaure"];
|
|
163
|
+
private readonly options;
|
|
164
|
+
constructor(options: LocalDevProviderOptions);
|
|
165
|
+
/**
|
|
166
|
+
* @inheritdoc
|
|
167
|
+
*/
|
|
168
|
+
downloadJSON(name: string, versionPath: string, signal: AbortSignal): Promise<VersionJSON>;
|
|
169
|
+
/**
|
|
170
|
+
* @inheritdoc
|
|
171
|
+
*/
|
|
172
|
+
downloadAsar(info: UpdateInfoWithURL, signal: AbortSignal, onDownloading?: (info: DownloadingInfo) => void): Promise<Buffer$1>;
|
|
173
|
+
private readJSON;
|
|
174
|
+
private emitProgress;
|
|
175
|
+
}
|
|
176
|
+
//#endregion
|
|
177
|
+
export { BaseGitHubProvider, BaseGitHubProviderOptions, BaseProvider, DownloadingInfo, GitHubApiProvider, GitHubApiProviderOptions, GitHubAtomProvider, GitHubProvider, GitHubProviderOptions, IProvider, LocalDevProvider, LocalDevProviderOptions, URLHandler, UpdateInfoWithURL, VersionJSON, defaultDownloadAsar, defaultDownloadText, defaultDownloadUpdateJSON, downloadUtil, getHeader, resolveJson };
|