electron-incremental-update 1.3.0 → 2.0.0-beta.1
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 +6 -2
- package/dist/chunk-RSLOPAIZ.js +247 -0
- package/dist/decrypt-BNBcodiO.d.cts +4 -0
- package/dist/decrypt-BNBcodiO.d.ts +4 -0
- package/dist/index.cjs +108 -261
- package/dist/index.d.cts +68 -161
- package/dist/index.d.ts +68 -161
- package/dist/index.js +76 -195
- package/dist/provider.cjs +227 -0
- package/dist/provider.d.cts +37 -0
- package/dist/provider.d.ts +37 -0
- package/dist/provider.js +98 -0
- package/dist/types-DxPmQmaq.d.cts +61 -0
- package/dist/types-seJf3Wbc.d.ts +61 -0
- package/dist/utils.cjs +139 -115
- package/dist/utils.d.cts +31 -76
- package/dist/utils.d.ts +31 -76
- package/dist/utils.js +35 -11
- package/dist/{pure-GoN_3MEj.d.cts → version-CffZWDhZ.d.cts} +8 -7
- package/dist/{pure-GoN_3MEj.d.ts → version-CffZWDhZ.d.ts} +8 -7
- package/dist/vite.js +70 -117
- package/package.json +12 -6
- package/provider.d.ts +1 -0
- package/provider.js +1 -0
- package/dist/chunk-7ET4GMTZ.js +0 -236
- package/dist/chunk-CXHA5TF7.js +0 -236
- package/dist/chunk-HWUYTDEF.js +0 -236
- package/dist/chunk-RQCTJY4L.js +0 -236
- package/dist/chunk-SBPTSLG7.js +0 -235
- package/dist/vite.d.ts +0 -372
package/dist/index.js
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
__require,
|
|
3
|
+
getAppVersion,
|
|
4
|
+
getEntryVersion,
|
|
3
5
|
getPathFromAppNameAsar,
|
|
4
|
-
|
|
5
|
-
is,
|
|
6
|
+
isDev,
|
|
6
7
|
isUpdateJSON,
|
|
7
|
-
parseVersion,
|
|
8
8
|
restartApp,
|
|
9
|
-
unzipFile
|
|
10
|
-
|
|
11
|
-
} from "./chunk-SBPTSLG7.js";
|
|
9
|
+
unzipFile
|
|
10
|
+
} from "./chunk-RSLOPAIZ.js";
|
|
12
11
|
|
|
13
|
-
// src/
|
|
14
|
-
import {
|
|
12
|
+
// src/entry.ts
|
|
13
|
+
import { join } from "node:path";
|
|
15
14
|
import { existsSync as existsSync2, renameSync } from "node:fs";
|
|
16
15
|
import { app as app2 } from "electron";
|
|
17
16
|
|
|
@@ -19,36 +18,9 @@ import { app as app2 } from "electron";
|
|
|
19
18
|
import { existsSync, rmSync, writeFileSync } from "node:fs";
|
|
20
19
|
import { app } from "electron";
|
|
21
20
|
|
|
22
|
-
// src/crypto/dec.ts
|
|
23
|
-
import { createDecipheriv, createVerify } from "node:crypto";
|
|
24
|
-
|
|
25
|
-
// src/crypto/utils.ts
|
|
26
|
-
import { createHash } from "node:crypto";
|
|
27
|
-
function hashString(data, length) {
|
|
28
|
-
const hash = createHash("SHA256").update(data).digest("binary");
|
|
29
|
-
return Buffer.from(hash).subarray(0, length);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// src/crypto/dec.ts
|
|
33
|
-
function decrypt(encryptedText, key, iv) {
|
|
34
|
-
const decipher = createDecipheriv("aes-256-cbc", key, iv);
|
|
35
|
-
let decrypted = decipher.update(encryptedText, "base64url", "utf8");
|
|
36
|
-
decrypted += decipher.final("utf8");
|
|
37
|
-
return decrypted;
|
|
38
|
-
}
|
|
39
|
-
var verify = (buffer, signature, cert) => {
|
|
40
|
-
try {
|
|
41
|
-
const [sig, version] = decrypt(signature, hashString(cert, 32), hashString(buffer, 16)).split("%");
|
|
42
|
-
const result = createVerify("RSA-SHA256").update(buffer).verify(cert, sig, "base64");
|
|
43
|
-
return result ? version : false;
|
|
44
|
-
} catch (error) {
|
|
45
|
-
return false;
|
|
46
|
-
}
|
|
47
|
-
};
|
|
48
|
-
|
|
49
21
|
// src/updater/types.ts
|
|
50
22
|
var ErrorInfo = {
|
|
51
|
-
|
|
23
|
+
download: "Download failed",
|
|
52
24
|
validate: "Validate failed",
|
|
53
25
|
param: "Missing params",
|
|
54
26
|
version: "Unsatisfied version"
|
|
@@ -59,83 +31,15 @@ var UpdaterError = class extends Error {
|
|
|
59
31
|
}
|
|
60
32
|
};
|
|
61
33
|
|
|
62
|
-
// src/updater/defaultFunctions/download.ts
|
|
63
|
-
import { net } from "electron";
|
|
64
|
-
async function downlaodFn(url, headers, onResponse) {
|
|
65
|
-
await waitAppReady();
|
|
66
|
-
return new Promise((resolve2, reject) => {
|
|
67
|
-
const request = net.request({ url, method: "GET", redirect: "follow" });
|
|
68
|
-
Object.keys(headers).forEach((key) => request.setHeader(key, headers[key]));
|
|
69
|
-
request.on("response", (res) => onResponse(res, resolve2, reject));
|
|
70
|
-
request.on("error", reject);
|
|
71
|
-
request.end();
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
var downloadJSONDefault = async (url, headers) => {
|
|
75
|
-
return await downlaodFn(url, headers, (resp, resolve2, reject) => {
|
|
76
|
-
let data = "";
|
|
77
|
-
resp.on("data", (chunk) => data += chunk);
|
|
78
|
-
resp.on("end", () => {
|
|
79
|
-
try {
|
|
80
|
-
const json = JSON.parse(data);
|
|
81
|
-
if (isUpdateJSON(json)) {
|
|
82
|
-
resolve2(json);
|
|
83
|
-
} else {
|
|
84
|
-
throw Error;
|
|
85
|
-
}
|
|
86
|
-
} catch (ignore) {
|
|
87
|
-
reject(new Error("invalid update json"));
|
|
88
|
-
}
|
|
89
|
-
});
|
|
90
|
-
resp.on("aborted", () => reject(new Error("aborted")));
|
|
91
|
-
resp.on("error", () => reject(new Error("download error")));
|
|
92
|
-
});
|
|
93
|
-
};
|
|
94
|
-
var downloadBufferDefault = async (url, headers, total, onDownloading) => {
|
|
95
|
-
let current = 0;
|
|
96
|
-
return await downlaodFn(url, headers, (resp, resolve2, reject) => {
|
|
97
|
-
let data = [];
|
|
98
|
-
resp.on("data", (chunk) => {
|
|
99
|
-
current += chunk.length;
|
|
100
|
-
onDownloading?.({ percent: `${+(current / total).toFixed(2) * 100}%`, total, current });
|
|
101
|
-
data.push(chunk);
|
|
102
|
-
});
|
|
103
|
-
resp.on("end", () => resolve2(Buffer.concat(data)));
|
|
104
|
-
resp.on("aborted", () => reject(new Error("aborted")));
|
|
105
|
-
resp.on("error", () => reject(new Error("download error")));
|
|
106
|
-
});
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
// src/updater/defaultFunctions/compareVersion.ts
|
|
110
|
-
var isLowerVersionDefault = (version1, version2) => {
|
|
111
|
-
const oldV = parseVersion(version1);
|
|
112
|
-
const newV = parseVersion(version2);
|
|
113
|
-
function compareStrings(str1, str2) {
|
|
114
|
-
if (str1 === "") {
|
|
115
|
-
return str2 !== "";
|
|
116
|
-
} else if (str2 === "") {
|
|
117
|
-
return true;
|
|
118
|
-
}
|
|
119
|
-
return str1 < str2;
|
|
120
|
-
}
|
|
121
|
-
for (let key of Object.keys(oldV)) {
|
|
122
|
-
if (key === "stage" && compareStrings(oldV[key], newV[key])) {
|
|
123
|
-
return true;
|
|
124
|
-
} else if (oldV[key] !== newV[key]) {
|
|
125
|
-
return oldV[key] < newV[key];
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
return false;
|
|
129
|
-
};
|
|
130
|
-
|
|
131
34
|
// src/updater/core.ts
|
|
132
35
|
var Updater = class {
|
|
133
|
-
CERT =
|
|
36
|
+
CERT = __EIU_SIGNATURE_CERT__;
|
|
134
37
|
info;
|
|
135
|
-
|
|
38
|
+
options;
|
|
136
39
|
asarPath;
|
|
137
40
|
gzipPath;
|
|
138
41
|
tmpFilePath;
|
|
42
|
+
provider;
|
|
139
43
|
/**
|
|
140
44
|
* updater logger
|
|
141
45
|
*/
|
|
@@ -149,31 +53,49 @@ var Updater = class {
|
|
|
149
53
|
* }
|
|
150
54
|
*/
|
|
151
55
|
onDownloading;
|
|
56
|
+
/**
|
|
57
|
+
* URL handler hook
|
|
58
|
+
*
|
|
59
|
+
* for Github, there are some {@link https://github.com/XIU2/UserScript/blob/master/GithubEnhanced-High-Speed-Download.user.js#L34 public CDN links}
|
|
60
|
+
* @param url source url
|
|
61
|
+
* @param isDownloadAsar whether is download asar
|
|
62
|
+
*/
|
|
63
|
+
handleURL;
|
|
152
64
|
/**
|
|
153
65
|
* whether receive beta version
|
|
154
66
|
*/
|
|
155
67
|
get receiveBeta() {
|
|
156
|
-
return !!this.
|
|
68
|
+
return !!this.options.receiveBeta;
|
|
157
69
|
}
|
|
158
70
|
set receiveBeta(receiveBeta) {
|
|
159
|
-
this.
|
|
71
|
+
this.options.receiveBeta = receiveBeta;
|
|
160
72
|
}
|
|
161
73
|
/**
|
|
162
74
|
* initialize incremental updater
|
|
75
|
+
* @param provider update provider
|
|
163
76
|
* @param option UpdaterOption
|
|
164
77
|
*/
|
|
165
|
-
constructor(option = {}) {
|
|
166
|
-
this.
|
|
78
|
+
constructor(provider, option = {}) {
|
|
79
|
+
this.provider = provider;
|
|
80
|
+
this.options = option;
|
|
167
81
|
if (option.SIGNATURE_CERT) {
|
|
168
82
|
this.CERT = option.SIGNATURE_CERT;
|
|
169
83
|
}
|
|
84
|
+
if (option.logger) {
|
|
85
|
+
this.logger = option.logger;
|
|
86
|
+
}
|
|
170
87
|
this.asarPath = getPathFromAppNameAsar();
|
|
171
88
|
this.gzipPath = `${this.asarPath}.gz`;
|
|
172
89
|
this.tmpFilePath = `${this.asarPath}.tmp`;
|
|
173
90
|
}
|
|
174
91
|
async needUpdate(version, minVersion) {
|
|
175
|
-
|
|
176
|
-
|
|
92
|
+
if (isDev) {
|
|
93
|
+
this.logger?.warn(`in dev mode, skip check update`);
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
const isLowerVersion = this.provider.isLowerVersion;
|
|
97
|
+
const entryVersion = getEntryVersion();
|
|
98
|
+
const appVersion = getAppVersion();
|
|
177
99
|
if (await isLowerVersion(entryVersion, minVersion)) {
|
|
178
100
|
throw new UpdaterError(ErrorInfo.version, `entry version (${entryVersion}) < minimumVersion (${minVersion})`);
|
|
179
101
|
}
|
|
@@ -196,42 +118,14 @@ var Updater = class {
|
|
|
196
118
|
throw new UpdaterError(ErrorInfo.param, `invalid type at format '${format}': ${JSON.stringify(data)}`);
|
|
197
119
|
}
|
|
198
120
|
}
|
|
199
|
-
|
|
200
|
-
const headers = {
|
|
201
|
-
Accept: `application/${format === "json" ? "json" : "octet-stream"}`,
|
|
202
|
-
UserAgent: ua,
|
|
203
|
-
...this.option.downloadConfig?.extraHeader
|
|
204
|
-
};
|
|
205
|
-
this.logger?.debug(`download headers: ${JSON.stringify(headers)}`);
|
|
206
|
-
const config = format === "json" ? {
|
|
207
|
-
name: "updateJsonURL",
|
|
208
|
-
url: this.option.updateJsonURL,
|
|
209
|
-
repoFallback: `${this.option.repository?.replace("github.com", "raw.githubusercontent.com")}/master/version.json`,
|
|
210
|
-
fn: this.option.overrideFunctions?.downloadJSON ?? downloadJSONDefault
|
|
211
|
-
} : {
|
|
212
|
-
name: "releaseAsarURL",
|
|
213
|
-
url: this.option.releaseAsarURL,
|
|
214
|
-
repoFallback: `${this.option.repository}/releases/download/v${this.info?.version}/${app.name}-${this.info?.version}.asar.gz`,
|
|
215
|
-
fn: this.option.overrideFunctions?.downloadBuffer ?? downloadBufferDefault
|
|
216
|
-
};
|
|
217
|
-
data ??= config.url;
|
|
218
|
-
if (!data) {
|
|
219
|
-
this.logger?.debug(`no ${config.name}, fallback to use repository`);
|
|
220
|
-
if (!this.option.repository) {
|
|
221
|
-
throw new UpdaterError(ErrorInfo.param, `${config.name} or repository is not set`);
|
|
222
|
-
}
|
|
223
|
-
if (format === "buffer" && !this.info?.version) {
|
|
224
|
-
throw new UpdaterError(ErrorInfo.param, "version is not set");
|
|
225
|
-
}
|
|
226
|
-
data = config.repoFallback;
|
|
227
|
-
}
|
|
228
|
-
this.logger?.debug(`download ${format} from ${data}`);
|
|
121
|
+
this.logger?.debug(`download from ${this.provider.name}`);
|
|
229
122
|
try {
|
|
230
|
-
const
|
|
231
|
-
this.logger?.debug(`download ${format} success${format === "buffer" ? `, file size: ${
|
|
232
|
-
return
|
|
123
|
+
const result = format === "json" ? await this.provider.downloadJSON(data ?? __EIU_VERSION_PATH__) : await this.provider.downloadBuffer(app.name, this.info, this.onDownloading);
|
|
124
|
+
this.logger?.debug(`download ${format} success${format === "buffer" ? `, file size: ${result.length}` : ""}`);
|
|
125
|
+
return result;
|
|
233
126
|
} catch (e) {
|
|
234
|
-
|
|
127
|
+
this.logger?.warn(`download ${format} failed: ${e}`);
|
|
128
|
+
throw new UpdaterError(ErrorInfo.download, `download ${format} failed: ${e}`);
|
|
235
129
|
}
|
|
236
130
|
}
|
|
237
131
|
async checkUpdate(data) {
|
|
@@ -243,35 +137,32 @@ var Updater = class {
|
|
|
243
137
|
minimumVersion = beta.minimumVersion;
|
|
244
138
|
size = beta.size;
|
|
245
139
|
}
|
|
246
|
-
this.logger?.debug(`checked version: ${version}, size: ${size}, signature: ${signature}`);
|
|
140
|
+
this.logger?.debug(`checked update, version: ${version}, size: ${size}, signature: ${signature}`);
|
|
247
141
|
if (!await this.needUpdate(version, minimumVersion)) {
|
|
248
142
|
this.logger?.info(`update unavailable: ${version} is the latest version`);
|
|
249
|
-
return
|
|
143
|
+
return { success: false, data: version };
|
|
250
144
|
} else {
|
|
251
145
|
this.logger?.info(`update available: ${version}`);
|
|
252
|
-
this.info = {
|
|
253
|
-
|
|
254
|
-
minimumVersion,
|
|
255
|
-
version,
|
|
256
|
-
size
|
|
257
|
-
};
|
|
258
|
-
return this.info;
|
|
146
|
+
this.info = { signature, minimumVersion, version, size };
|
|
147
|
+
return { success: true, data: this.info };
|
|
259
148
|
}
|
|
260
149
|
} catch (error) {
|
|
261
150
|
this.logger?.error("check update failed", error);
|
|
262
|
-
return
|
|
151
|
+
return {
|
|
152
|
+
success: false,
|
|
153
|
+
data: error instanceof UpdaterError ? error : new UpdaterError(ErrorInfo.download, error.toString())
|
|
154
|
+
};
|
|
263
155
|
}
|
|
264
156
|
}
|
|
265
157
|
async download(data, sig) {
|
|
266
158
|
try {
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
throw new UpdaterError(ErrorInfo.param, "signature is empty");
|
|
159
|
+
if (!this.info) {
|
|
160
|
+
throw new UpdaterError(ErrorInfo.param, "no update info");
|
|
270
161
|
}
|
|
162
|
+
const _sig = sig ?? this.info.signature;
|
|
271
163
|
const buffer = await this.parseData("buffer", data);
|
|
272
164
|
this.logger?.debug("verify start");
|
|
273
|
-
const
|
|
274
|
-
const _ver = await _verify(buffer, _sig, this.CERT);
|
|
165
|
+
const _ver = await this.provider.verifySignaure(buffer, _sig, this.CERT);
|
|
275
166
|
if (!_ver) {
|
|
276
167
|
throw new UpdaterError(ErrorInfo.validate, "invalid signature or certificate");
|
|
277
168
|
}
|
|
@@ -282,10 +173,13 @@ var Updater = class {
|
|
|
282
173
|
await unzipFile(this.gzipPath, this.tmpFilePath);
|
|
283
174
|
this.logger?.info(`download success, version: ${_ver}`);
|
|
284
175
|
this.info = void 0;
|
|
285
|
-
return true;
|
|
176
|
+
return { success: true };
|
|
286
177
|
} catch (error) {
|
|
287
178
|
this.logger?.error("download asar failed", error);
|
|
288
|
-
return
|
|
179
|
+
return {
|
|
180
|
+
success: false,
|
|
181
|
+
data: error instanceof UpdaterError ? error : new UpdaterError(ErrorInfo.download, error.toString())
|
|
182
|
+
};
|
|
289
183
|
}
|
|
290
184
|
}
|
|
291
185
|
/**
|
|
@@ -297,66 +191,53 @@ var Updater = class {
|
|
|
297
191
|
}
|
|
298
192
|
};
|
|
299
193
|
|
|
300
|
-
// src/
|
|
301
|
-
function createUpdater(option) {
|
|
302
|
-
return new Updater(option);
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
// src/index.ts
|
|
194
|
+
// src/entry.ts
|
|
306
195
|
function startupWithUpdater(fn) {
|
|
307
196
|
return fn;
|
|
308
197
|
}
|
|
309
198
|
var defaultOnInstall = (install, _, __, logger) => {
|
|
310
199
|
install();
|
|
311
|
-
logger
|
|
200
|
+
logger.info(`update success!`);
|
|
312
201
|
};
|
|
313
|
-
async function initApp(appOptions
|
|
202
|
+
async function initApp(appOptions) {
|
|
314
203
|
const {
|
|
204
|
+
provider,
|
|
315
205
|
updater,
|
|
316
|
-
electronDevDistPath = "../dist-electron",
|
|
317
|
-
mainPath = "main/index.js",
|
|
318
|
-
hooks
|
|
319
|
-
} = appOptions || {};
|
|
320
|
-
const {
|
|
321
206
|
onInstall = defaultOnInstall,
|
|
322
207
|
beforeStart,
|
|
323
208
|
onStartError
|
|
324
|
-
} =
|
|
325
|
-
function handleError(err, logger2) {
|
|
326
|
-
console.error(err);
|
|
327
|
-
onStartError?.(err, logger2);
|
|
328
|
-
app2.quit();
|
|
329
|
-
}
|
|
209
|
+
} = appOptions;
|
|
330
210
|
let updaterInstance;
|
|
331
211
|
if (typeof updater === "object" || !updater) {
|
|
332
|
-
updaterInstance =
|
|
212
|
+
updaterInstance = new Updater(provider, updater);
|
|
333
213
|
} else {
|
|
334
214
|
updaterInstance = await updater();
|
|
335
215
|
}
|
|
336
|
-
const logger = updaterInstance.logger;
|
|
216
|
+
const logger = updaterInstance.logger || console;
|
|
337
217
|
try {
|
|
338
218
|
const appNameAsarPath = getPathFromAppNameAsar();
|
|
339
219
|
const tempAsarPath = `${appNameAsarPath}.tmp`;
|
|
340
220
|
if (existsSync2(tempAsarPath)) {
|
|
341
|
-
logger
|
|
221
|
+
logger.info(`installing new asar: ${tempAsarPath}`);
|
|
342
222
|
await onInstall(() => renameSync(tempAsarPath, appNameAsarPath), tempAsarPath, appNameAsarPath, logger);
|
|
343
223
|
}
|
|
344
|
-
const
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
224
|
+
const mainFilePath = join(
|
|
225
|
+
isDev ? join(app2.getAppPath(), __EIU_MAIN_DEV_DIR__) : appNameAsarPath,
|
|
226
|
+
"main",
|
|
227
|
+
__EIU_MAIN_FILE__
|
|
228
|
+
);
|
|
229
|
+
await beforeStart?.(mainFilePath, logger);
|
|
230
|
+
__require(mainFilePath)(updaterInstance);
|
|
348
231
|
} catch (error) {
|
|
349
|
-
|
|
232
|
+
logger.error("startup error", error);
|
|
233
|
+
onStartError?.(error, logger);
|
|
234
|
+
app2.quit();
|
|
350
235
|
}
|
|
351
236
|
}
|
|
352
237
|
export {
|
|
353
238
|
ErrorInfo,
|
|
354
239
|
Updater,
|
|
355
240
|
UpdaterError,
|
|
356
|
-
createUpdater,
|
|
357
|
-
downloadBufferDefault,
|
|
358
|
-
downloadJSONDefault,
|
|
359
241
|
initApp,
|
|
360
|
-
isLowerVersionDefault,
|
|
361
242
|
startupWithUpdater
|
|
362
243
|
};
|
|
@@ -0,0 +1,227 @@
|
|
|
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);
|
|
19
|
+
|
|
20
|
+
// src/provider/index.ts
|
|
21
|
+
var provider_exports = {};
|
|
22
|
+
__export(provider_exports, {
|
|
23
|
+
GitHubProvider: () => GitHubProvider,
|
|
24
|
+
downloadAsarBufferDefault: () => downloadAsarBufferDefault,
|
|
25
|
+
downloadUpdateJSONDefault: () => downloadUpdateJSONDefault
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(provider_exports);
|
|
28
|
+
|
|
29
|
+
// src/utils/electron.ts
|
|
30
|
+
var import_node_fs = require("fs");
|
|
31
|
+
var import_node_path = require("path");
|
|
32
|
+
var import_electron = require("electron");
|
|
33
|
+
var isDev = __EIU_IS_DEV__;
|
|
34
|
+
var isWin = process.platform === "win32";
|
|
35
|
+
var isMac = process.platform === "darwin";
|
|
36
|
+
var isLinux = process.platform === "linux";
|
|
37
|
+
function waitAppReady(timeout = 1e3) {
|
|
38
|
+
return import_electron.app.isReady() ? Promise.resolve() : new Promise((resolve, reject) => {
|
|
39
|
+
const _ = setTimeout(() => {
|
|
40
|
+
reject(new Error("app is not ready"));
|
|
41
|
+
}, timeout);
|
|
42
|
+
import_electron.app.whenReady().then(() => {
|
|
43
|
+
clearTimeout(_);
|
|
44
|
+
resolve();
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// src/utils/zip.ts
|
|
50
|
+
var import_node_fs2 = require("fs");
|
|
51
|
+
var import_node_zlib = require("zlib");
|
|
52
|
+
|
|
53
|
+
// src/utils/unzip.ts
|
|
54
|
+
var import_node_fs3 = require("fs");
|
|
55
|
+
var import_node_zlib2 = require("zlib");
|
|
56
|
+
|
|
57
|
+
// src/utils/version.ts
|
|
58
|
+
function parseVersion(version) {
|
|
59
|
+
const match = /^(\d+)\.(\d+)\.(\d+)(?:-([a-z0-9.-]+))?/i.exec(version);
|
|
60
|
+
if (!match) {
|
|
61
|
+
throw new TypeError(`invalid version: ${version}`);
|
|
62
|
+
}
|
|
63
|
+
const [major, minor, patch] = match.slice(1, 4).map(Number);
|
|
64
|
+
const ret = {
|
|
65
|
+
major,
|
|
66
|
+
minor,
|
|
67
|
+
patch,
|
|
68
|
+
stage: "",
|
|
69
|
+
stageVersion: -1
|
|
70
|
+
};
|
|
71
|
+
if (match[4]) {
|
|
72
|
+
let [stage, _v] = match[4].split(".");
|
|
73
|
+
ret.stage = stage;
|
|
74
|
+
ret.stageVersion = Number(_v) || -1;
|
|
75
|
+
}
|
|
76
|
+
if (Number.isNaN(major) || Number.isNaN(minor) || Number.isNaN(patch) || Number.isNaN(ret.stageVersion)) {
|
|
77
|
+
throw new TypeError(`invalid version: ${version}`);
|
|
78
|
+
}
|
|
79
|
+
return ret;
|
|
80
|
+
}
|
|
81
|
+
function isLowerVersionDefault(oldVer, newVer) {
|
|
82
|
+
const oldV = parseVersion(oldVer);
|
|
83
|
+
const newV = parseVersion(newVer);
|
|
84
|
+
function compareStrings(str1, str2) {
|
|
85
|
+
if (str1 === "") {
|
|
86
|
+
return str2 !== "";
|
|
87
|
+
} else if (str2 === "") {
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
return str1 < str2;
|
|
91
|
+
}
|
|
92
|
+
for (let key of Object.keys(oldV)) {
|
|
93
|
+
if (key === "stage" && compareStrings(oldV[key], newV[key])) {
|
|
94
|
+
return true;
|
|
95
|
+
} else if (oldV[key] !== newV[key]) {
|
|
96
|
+
return oldV[key] < newV[key];
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
function isUpdateJSON(json) {
|
|
102
|
+
const is = (j) => !!(j && j.minimumVersion && j.signature && j.size && j.version);
|
|
103
|
+
return is(json) && is(json?.beta);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// src/utils/crypto/decrypt.ts
|
|
107
|
+
var import_node_crypto2 = require("crypto");
|
|
108
|
+
|
|
109
|
+
// src/utils/crypto/utils.ts
|
|
110
|
+
var import_node_crypto = require("crypto");
|
|
111
|
+
function hashString(data, length) {
|
|
112
|
+
const hash = (0, import_node_crypto.createHash)("SHA256").update(data).digest("binary");
|
|
113
|
+
return Buffer.from(hash).subarray(0, length);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// src/utils/crypto/decrypt.ts
|
|
117
|
+
function decrypt(encryptedText, key, iv) {
|
|
118
|
+
const decipher = (0, import_node_crypto2.createDecipheriv)("aes-256-cbc", key, iv);
|
|
119
|
+
let decrypted = decipher.update(encryptedText, "base64url", "utf8");
|
|
120
|
+
decrypted += decipher.final("utf8");
|
|
121
|
+
return decrypted;
|
|
122
|
+
}
|
|
123
|
+
function verifySignatureDefault(buffer, signature, cert) {
|
|
124
|
+
try {
|
|
125
|
+
const [sig, version] = decrypt(signature, hashString(cert, 32), hashString(buffer, 16)).split("%");
|
|
126
|
+
const result = (0, import_node_crypto2.createVerify)("RSA-SHA256").update(buffer).verify(cert, sig, "base64");
|
|
127
|
+
return result ? version : void 0;
|
|
128
|
+
} catch (error) {
|
|
129
|
+
return void 0;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// src/utils/crypto/encrypt.ts
|
|
134
|
+
var import_node_crypto3 = require("crypto");
|
|
135
|
+
|
|
136
|
+
// src/provider/download.ts
|
|
137
|
+
var import_electron2 = require("electron");
|
|
138
|
+
async function downlaodFn(url, headers, onResponse) {
|
|
139
|
+
await waitAppReady();
|
|
140
|
+
return new Promise((resolve, reject) => {
|
|
141
|
+
const request = import_electron2.net.request({ url, method: "GET", redirect: "follow" });
|
|
142
|
+
Object.keys(headers).forEach((key) => request.setHeader(key, headers[key]));
|
|
143
|
+
request.on("response", (resp) => {
|
|
144
|
+
resp.on("aborted", () => reject(new Error("aborted")));
|
|
145
|
+
resp.on("error", () => reject(new Error("download error")));
|
|
146
|
+
onResponse(resp, resolve, reject);
|
|
147
|
+
});
|
|
148
|
+
request.on("error", reject);
|
|
149
|
+
request.end();
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
async function downloadUpdateJSONDefault(url, headers) {
|
|
153
|
+
return await downlaodFn(url, headers, (resp, resolve, reject) => {
|
|
154
|
+
let data = "";
|
|
155
|
+
resp.on("data", (chunk) => data += chunk);
|
|
156
|
+
resp.on("end", () => {
|
|
157
|
+
try {
|
|
158
|
+
const json = JSON.parse(data);
|
|
159
|
+
if (isUpdateJSON(json)) {
|
|
160
|
+
resolve(json);
|
|
161
|
+
} else {
|
|
162
|
+
throw Error;
|
|
163
|
+
}
|
|
164
|
+
} catch (ignore) {
|
|
165
|
+
reject(new Error("invalid update json"));
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
async function downloadAsarBufferDefault(url, headers, total, onDownloading) {
|
|
171
|
+
let current = 0;
|
|
172
|
+
return await downlaodFn(url, headers, (resp, resolve) => {
|
|
173
|
+
let data = [];
|
|
174
|
+
resp.on("data", (chunk) => {
|
|
175
|
+
current += chunk.length;
|
|
176
|
+
onDownloading?.({ percent: `${+(current / total).toFixed(2) * 100}%`, total, current });
|
|
177
|
+
data.push(chunk);
|
|
178
|
+
});
|
|
179
|
+
resp.on("end", () => resolve(Buffer.concat(data)));
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// src/provider/github.ts
|
|
184
|
+
var GitHubProvider = class {
|
|
185
|
+
ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36";
|
|
186
|
+
name = "GithubProvider";
|
|
187
|
+
urlHandler;
|
|
188
|
+
url;
|
|
189
|
+
extraHeaders;
|
|
190
|
+
constructor(options) {
|
|
191
|
+
this.url = new URL(options.url);
|
|
192
|
+
this.extraHeaders = options.extraHeaders;
|
|
193
|
+
this.urlHandler = options.urlHandler;
|
|
194
|
+
if (this.url.host !== "github.com") {
|
|
195
|
+
throw new Error(`${this.name}: invalid github url: ${options.url}`);
|
|
196
|
+
}
|
|
197
|
+
if (!this.url.pathname.endsWith("/")) {
|
|
198
|
+
this.url.pathname += "/";
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
parseURL(isDownloadAsar, path) {
|
|
202
|
+
const url = this.url.href + path;
|
|
203
|
+
return this.urlHandler ? this.urlHandler(url, isDownloadAsar) : url;
|
|
204
|
+
}
|
|
205
|
+
isLowerVersion = isLowerVersionDefault;
|
|
206
|
+
verifySignaure = verifySignatureDefault;
|
|
207
|
+
async downloadJSON(versionPath) {
|
|
208
|
+
return await downloadUpdateJSONDefault(
|
|
209
|
+
this.parseURL(false, `HEAD/${versionPath}`),
|
|
210
|
+
{ userAgent: this.ua, accept: "application/json", ...this.extraHeaders }
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
async downloadBuffer(name, { version, size }, onDownloading) {
|
|
214
|
+
return await downloadAsarBufferDefault(
|
|
215
|
+
this.parseURL(true, `releases/download/v${version}/${name}-${version}.asar.gz`),
|
|
216
|
+
{ userAgent: this.ua, accept: "application/octet-stream", ...this.extraHeaders },
|
|
217
|
+
size,
|
|
218
|
+
onDownloading
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
223
|
+
0 && (module.exports = {
|
|
224
|
+
GitHubProvider,
|
|
225
|
+
downloadAsarBufferDefault,
|
|
226
|
+
downloadUpdateJSONDefault
|
|
227
|
+
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { i as isLowerVersionDefault, U as UpdateJSON, a as UpdateInfo } from './version-CffZWDhZ.cjs';
|
|
2
|
+
import { v as verifySignatureDefault } from './decrypt-BNBcodiO.cjs';
|
|
3
|
+
import { U as URLHandler, I as IProvider, D as DownloadingInfo, O as OnDownloading } from './types-DxPmQmaq.cjs';
|
|
4
|
+
import '@subframe7536/type-utils';
|
|
5
|
+
|
|
6
|
+
interface GitHubProviderOptions {
|
|
7
|
+
/**
|
|
8
|
+
* github repo root url
|
|
9
|
+
* @example 'https://github.com/electron/electron'
|
|
10
|
+
*/
|
|
11
|
+
url: string;
|
|
12
|
+
extraHeaders?: Record<string, string>;
|
|
13
|
+
/**
|
|
14
|
+
* custom url handler
|
|
15
|
+
*
|
|
16
|
+
* for Github, there are some {@link https://github.com/XIU2/UserScript/blob/master/GithubEnhanced-High-Speed-Download.user.js#L34 public CDN links}
|
|
17
|
+
*/
|
|
18
|
+
urlHandler?: URLHandler;
|
|
19
|
+
}
|
|
20
|
+
declare class GitHubProvider implements IProvider {
|
|
21
|
+
private ua;
|
|
22
|
+
name: string;
|
|
23
|
+
urlHandler?: URLHandler;
|
|
24
|
+
private url;
|
|
25
|
+
private extraHeaders?;
|
|
26
|
+
constructor(options: GitHubProviderOptions);
|
|
27
|
+
private parseURL;
|
|
28
|
+
isLowerVersion: typeof isLowerVersionDefault;
|
|
29
|
+
verifySignaure: typeof verifySignatureDefault;
|
|
30
|
+
downloadJSON(versionPath: string): Promise<UpdateJSON>;
|
|
31
|
+
downloadBuffer(name: string, { version, size }: UpdateInfo, onDownloading?: (info: DownloadingInfo) => void): Promise<Buffer>;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
declare function downloadUpdateJSONDefault(url: string, headers: Record<string, any>): Promise<UpdateJSON>;
|
|
35
|
+
declare function downloadAsarBufferDefault(url: string, headers: Record<string, any>, total: number, onDownloading?: OnDownloading): Promise<Buffer>;
|
|
36
|
+
|
|
37
|
+
export { DownloadingInfo, GitHubProvider, type GitHubProviderOptions, IProvider, OnDownloading, URLHandler, downloadAsarBufferDefault, downloadUpdateJSONDefault };
|