electron-incremental-update 2.0.0-beta.1 → 2.0.0-beta.3
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 +3 -3
- package/dist/chunk-5WFXC5GU.js +43 -0
- package/dist/chunk-BVFQWBLK.js +76 -0
- package/dist/chunk-PNYRQYFC.js +77 -0
- package/dist/index.cjs +147 -196
- package/dist/index.d.cts +40 -43
- package/dist/index.d.ts +40 -43
- package/dist/index.js +124 -128
- package/dist/provider.cjs +92 -117
- package/dist/provider.d.cts +38 -12
- package/dist/provider.d.ts +38 -12
- package/dist/provider.js +56 -38
- package/dist/{types-seJf3Wbc.d.ts → types-DxhNaNgR.d.ts} +21 -7
- package/dist/{types-DxPmQmaq.d.cts → types-Tequ_V2o.d.cts} +21 -7
- package/dist/unzip-JjYLjJkH.d.cts +9 -0
- package/dist/unzip-JjYLjJkH.d.ts +9 -0
- package/dist/utils.cjs +119 -183
- package/dist/utils.d.cts +4 -16
- package/dist/utils.d.ts +4 -16
- package/dist/utils.js +19 -62
- package/dist/{version-CffZWDhZ.d.cts → version-CemSHimT.d.cts} +3 -2
- package/dist/{version-CffZWDhZ.d.ts → version-CemSHimT.d.ts} +3 -2
- package/dist/vite.js +135 -156
- package/package.json +10 -10
- package/dist/chunk-RSLOPAIZ.js +0 -247
- package/dist/decrypt-BNBcodiO.d.cts +0 -4
- package/dist/decrypt-BNBcodiO.d.ts +0 -4
package/dist/index.js
CHANGED
|
@@ -1,43 +1,30 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
isUpdateJSON,
|
|
8
|
-
restartApp,
|
|
9
|
-
unzipFile
|
|
10
|
-
} from "./chunk-RSLOPAIZ.js";
|
|
11
|
-
|
|
12
|
-
// src/entry.ts
|
|
13
|
-
import { join } from "node:path";
|
|
14
|
-
import { existsSync as existsSync2, renameSync } from "node:fs";
|
|
15
|
-
import { app as app2 } from "electron";
|
|
16
|
-
|
|
17
|
-
// src/updater/core.ts
|
|
18
|
-
import { existsSync, rmSync, writeFileSync } from "node:fs";
|
|
19
|
-
import { app } from "electron";
|
|
1
|
+
import { isDev, getPathFromAppNameAsar, getEntryVersion, getAppVersion, restartApp } from './chunk-PNYRQYFC.js';
|
|
2
|
+
import { isUpdateJSON, __require } from './chunk-BVFQWBLK.js';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { existsSync, rmSync, renameSync } from 'node:fs';
|
|
5
|
+
import { app } from 'electron';
|
|
6
|
+
import { EventEmitter } from 'node:events';
|
|
20
7
|
|
|
21
8
|
// src/updater/types.ts
|
|
22
9
|
var ErrorInfo = {
|
|
23
10
|
download: "Download failed",
|
|
24
11
|
validate: "Validate failed",
|
|
25
12
|
param: "Missing params",
|
|
26
|
-
|
|
13
|
+
network: "Network error"
|
|
27
14
|
};
|
|
28
15
|
var UpdaterError = class extends Error {
|
|
16
|
+
code;
|
|
29
17
|
constructor(msg, info) {
|
|
30
|
-
super(msg + ": " + info);
|
|
18
|
+
super(ErrorInfo[msg] + ": " + info);
|
|
19
|
+
this.code = msg;
|
|
31
20
|
}
|
|
32
21
|
};
|
|
33
22
|
|
|
34
23
|
// src/updater/core.ts
|
|
35
|
-
var Updater = class {
|
|
24
|
+
var Updater = class extends EventEmitter {
|
|
36
25
|
CERT = __EIU_SIGNATURE_CERT__;
|
|
37
26
|
info;
|
|
38
|
-
options;
|
|
39
27
|
asarPath;
|
|
40
|
-
gzipPath;
|
|
41
28
|
tmpFilePath;
|
|
42
29
|
provider;
|
|
43
30
|
/**
|
|
@@ -45,141 +32,134 @@ var Updater = class {
|
|
|
45
32
|
*/
|
|
46
33
|
logger;
|
|
47
34
|
/**
|
|
48
|
-
*
|
|
49
|
-
* @param progress download progress
|
|
50
|
-
* @example
|
|
51
|
-
* updater.onDownloading = ({ percent, total, current }) => {
|
|
52
|
-
* console.log(`download progress: ${percent}, total: ${total}, current: ${current}`)
|
|
53
|
-
* }
|
|
35
|
+
* whether to receive beta update
|
|
54
36
|
*/
|
|
55
|
-
|
|
37
|
+
receiveBeta;
|
|
56
38
|
/**
|
|
57
|
-
*
|
|
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
|
|
39
|
+
* whether force update in DEV
|
|
62
40
|
*/
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* whether receive beta version
|
|
66
|
-
*/
|
|
67
|
-
get receiveBeta() {
|
|
68
|
-
return !!this.options.receiveBeta;
|
|
69
|
-
}
|
|
70
|
-
set receiveBeta(receiveBeta) {
|
|
71
|
-
this.options.receiveBeta = receiveBeta;
|
|
72
|
-
}
|
|
41
|
+
forceUpdate;
|
|
73
42
|
/**
|
|
74
43
|
* initialize incremental updater
|
|
75
44
|
* @param provider update provider
|
|
76
45
|
* @param option UpdaterOption
|
|
77
46
|
*/
|
|
78
47
|
constructor(provider, option = {}) {
|
|
48
|
+
super();
|
|
79
49
|
this.provider = provider;
|
|
80
|
-
this.
|
|
50
|
+
this.receiveBeta = option.receiveBeta;
|
|
81
51
|
if (option.SIGNATURE_CERT) {
|
|
82
52
|
this.CERT = option.SIGNATURE_CERT;
|
|
83
53
|
}
|
|
84
54
|
if (option.logger) {
|
|
85
55
|
this.logger = option.logger;
|
|
86
56
|
}
|
|
57
|
+
if (isDev && !this.logger) {
|
|
58
|
+
this.logger = {
|
|
59
|
+
info: (...args) => console.log("[EIU-INFO ]", ...args),
|
|
60
|
+
debug: (...args) => console.log("[EIU-DEBUG]", ...args),
|
|
61
|
+
warn: (...args) => console.log("[EIU-WARN ]", ...args),
|
|
62
|
+
error: (...args) => console.error("[EIU-ERROR]", ...args)
|
|
63
|
+
};
|
|
64
|
+
this.logger.info("no logger set, enable dev-only logger");
|
|
65
|
+
}
|
|
87
66
|
this.asarPath = getPathFromAppNameAsar();
|
|
88
|
-
this.gzipPath = `${this.asarPath}.gz`;
|
|
89
67
|
this.tmpFilePath = `${this.asarPath}.tmp`;
|
|
90
68
|
}
|
|
91
|
-
async
|
|
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();
|
|
99
|
-
if (await isLowerVersion(entryVersion, minVersion)) {
|
|
100
|
-
throw new UpdaterError(ErrorInfo.version, `entry version (${entryVersion}) < minimumVersion (${minVersion})`);
|
|
101
|
-
}
|
|
102
|
-
this.logger?.info(`check update: current version is ${appVersion}, new version is ${version}`);
|
|
103
|
-
return await isLowerVersion(appVersion, version);
|
|
104
|
-
}
|
|
105
|
-
async parseData(format, data) {
|
|
69
|
+
async fetch(format, data) {
|
|
106
70
|
if (existsSync(this.tmpFilePath)) {
|
|
107
71
|
this.logger?.warn(`remove tmp file: ${this.tmpFilePath}`);
|
|
108
72
|
rmSync(this.tmpFilePath);
|
|
109
73
|
}
|
|
110
|
-
if (existsSync(this.gzipPath)) {
|
|
111
|
-
this.logger?.warn(`remove .gz file: ${this.gzipPath}`);
|
|
112
|
-
rmSync(this.gzipPath);
|
|
113
|
-
}
|
|
114
74
|
if (typeof data === "object") {
|
|
115
75
|
if (format === "json" && isUpdateJSON(data) || format === "buffer" && Buffer.isBuffer(data)) {
|
|
116
76
|
return data;
|
|
117
77
|
} else {
|
|
118
|
-
|
|
78
|
+
this.err("invalid type", "param", `invalid type at format '${format}': ${JSON.stringify(data)}`);
|
|
79
|
+
return;
|
|
119
80
|
}
|
|
120
81
|
}
|
|
121
82
|
this.logger?.debug(`download from ${this.provider.name}`);
|
|
122
83
|
try {
|
|
123
|
-
const result = format === "json" ? await this.provider.downloadJSON(data ?? __EIU_VERSION_PATH__) : await this.provider.
|
|
84
|
+
const result = format === "json" ? await this.provider.downloadJSON(data ?? __EIU_VERSION_PATH__) : await this.provider.downloadAsar(app.name, this.info, (data2) => this.emit("download-progress", data2));
|
|
124
85
|
this.logger?.debug(`download ${format} success${format === "buffer" ? `, file size: ${result.length}` : ""}`);
|
|
125
86
|
return result;
|
|
126
87
|
} catch (e) {
|
|
127
|
-
this.
|
|
128
|
-
throw new UpdaterError(ErrorInfo.download, `download ${format} failed: ${e}`);
|
|
88
|
+
this.err(`fetch ${format} failed`, "network", `download ${format} failed: ${e}`);
|
|
129
89
|
}
|
|
130
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* handle error message and emit error event
|
|
93
|
+
*/
|
|
94
|
+
err(msg, code, errorInfo) {
|
|
95
|
+
const err = new UpdaterError(code, errorInfo);
|
|
96
|
+
this.logger?.error(msg, err);
|
|
97
|
+
this.emit("error", err);
|
|
98
|
+
}
|
|
131
99
|
async checkUpdate(data) {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
100
|
+
const emitUnavailable = (msg) => {
|
|
101
|
+
this.logger?.info(msg);
|
|
102
|
+
this.emit("update-unavailable", msg);
|
|
103
|
+
return false;
|
|
104
|
+
};
|
|
105
|
+
const _data = await this.fetch("json", data);
|
|
106
|
+
if (!_data) {
|
|
107
|
+
return emitUnavailable("failed to get update info");
|
|
108
|
+
}
|
|
109
|
+
let { signature, size, version, minimumVersion, beta } = _data;
|
|
110
|
+
if (this.receiveBeta) {
|
|
111
|
+
version = beta.version;
|
|
112
|
+
signature = beta.signature;
|
|
113
|
+
minimumVersion = beta.minimumVersion;
|
|
114
|
+
size = beta.size;
|
|
115
|
+
}
|
|
116
|
+
this.logger?.debug(`checked update, version: ${version}, size: ${size}, signature: ${signature}`);
|
|
117
|
+
if (isDev && !this.forceUpdate && !data) {
|
|
118
|
+
return emitUnavailable("skip check update in dev mode, to force update, set `updater.forceUpdate` to true or call checkUpdate with UpdateJSON");
|
|
119
|
+
}
|
|
120
|
+
const isLowerVersion = this.provider.isLowerVersion;
|
|
121
|
+
const entryVersion = getEntryVersion();
|
|
122
|
+
const appVersion = getAppVersion();
|
|
123
|
+
if (isLowerVersion(entryVersion, minimumVersion)) {
|
|
124
|
+
return emitUnavailable(`entry version (${entryVersion}) < minimumVersion (${minimumVersion})`);
|
|
125
|
+
}
|
|
126
|
+
this.logger?.info(`check update: current version is ${appVersion}, new version is ${version}`);
|
|
127
|
+
if (!isLowerVersion(appVersion, version)) {
|
|
128
|
+
return emitUnavailable(`current version (${appVersion}) < new version (${version})`);
|
|
155
129
|
}
|
|
130
|
+
this.logger?.info(`update available: ${version}`);
|
|
131
|
+
this.info = { signature, minimumVersion, version, size };
|
|
132
|
+
this.emit("update-available", this.info);
|
|
133
|
+
return true;
|
|
156
134
|
}
|
|
157
135
|
async download(data, sig) {
|
|
136
|
+
const _sig = sig ?? this.info?.signature;
|
|
137
|
+
if (!_sig) {
|
|
138
|
+
this.err("download failed", "param", "no update signature, please call `checkUpdate` first");
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
const buffer = await this.fetch("buffer", data ? Buffer.from(data) : void 0);
|
|
142
|
+
if (!buffer) {
|
|
143
|
+
this.err("download failed", "param", "no update asar file buffer");
|
|
144
|
+
return false;
|
|
145
|
+
}
|
|
146
|
+
this.logger?.debug("verify start");
|
|
147
|
+
const _ver = await this.provider.verifySignaure(buffer, _sig, this.CERT);
|
|
148
|
+
if (!_ver) {
|
|
149
|
+
this.err("download failed", "validate", "invalid signature / certificate pair");
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
this.logger?.debug("verify success");
|
|
158
153
|
try {
|
|
159
|
-
if (!this.info) {
|
|
160
|
-
throw new UpdaterError(ErrorInfo.param, "no update info");
|
|
161
|
-
}
|
|
162
|
-
const _sig = sig ?? this.info.signature;
|
|
163
|
-
const buffer = await this.parseData("buffer", data);
|
|
164
|
-
this.logger?.debug("verify start");
|
|
165
|
-
const _ver = await this.provider.verifySignaure(buffer, _sig, this.CERT);
|
|
166
|
-
if (!_ver) {
|
|
167
|
-
throw new UpdaterError(ErrorInfo.validate, "invalid signature or certificate");
|
|
168
|
-
}
|
|
169
|
-
this.logger?.debug("verify success");
|
|
170
|
-
this.logger?.debug(`write to ${this.gzipPath}`);
|
|
171
|
-
writeFileSync(this.gzipPath, buffer);
|
|
172
154
|
this.logger?.debug(`extract to ${this.tmpFilePath}`);
|
|
173
|
-
await unzipFile(
|
|
155
|
+
await this.provider.unzipFile(buffer, this.tmpFilePath);
|
|
174
156
|
this.logger?.info(`download success, version: ${_ver}`);
|
|
175
157
|
this.info = void 0;
|
|
176
|
-
|
|
158
|
+
this.emit("update-downloaded");
|
|
159
|
+
return true;
|
|
177
160
|
} catch (error) {
|
|
178
|
-
this.
|
|
179
|
-
return
|
|
180
|
-
success: false,
|
|
181
|
-
data: error instanceof UpdaterError ? error : new UpdaterError(ErrorInfo.download, error.toString())
|
|
182
|
-
};
|
|
161
|
+
this.err("download failed", "download", `fail to unwrap asar file, ${error}`);
|
|
162
|
+
return false;
|
|
183
163
|
}
|
|
184
164
|
}
|
|
185
165
|
/**
|
|
@@ -189,6 +169,19 @@ var Updater = class {
|
|
|
189
169
|
this.logger?.info("quit and install");
|
|
190
170
|
restartApp();
|
|
191
171
|
}
|
|
172
|
+
/**
|
|
173
|
+
* setup provider URL handler
|
|
174
|
+
*
|
|
175
|
+
* @example
|
|
176
|
+
* updater.setURLHandler((url, isDownloadingAsar) => {
|
|
177
|
+
* if (isDownloadingAsar) {
|
|
178
|
+
* return url.replace('https://raw.githubusercontent.com', 'https://cdn.jsdelivr.net/gh')
|
|
179
|
+
* }
|
|
180
|
+
* })
|
|
181
|
+
*/
|
|
182
|
+
setURLHandler(handler) {
|
|
183
|
+
this.provider.urlHandler = handler;
|
|
184
|
+
}
|
|
192
185
|
};
|
|
193
186
|
|
|
194
187
|
// src/entry.ts
|
|
@@ -197,7 +190,7 @@ function startupWithUpdater(fn) {
|
|
|
197
190
|
}
|
|
198
191
|
var defaultOnInstall = (install, _, __, logger) => {
|
|
199
192
|
install();
|
|
200
|
-
logger
|
|
193
|
+
logger?.info(`update success!`);
|
|
201
194
|
};
|
|
202
195
|
async function initApp(appOptions) {
|
|
203
196
|
const {
|
|
@@ -213,31 +206,34 @@ async function initApp(appOptions) {
|
|
|
213
206
|
} else {
|
|
214
207
|
updaterInstance = await updater();
|
|
215
208
|
}
|
|
216
|
-
|
|
209
|
+
let logger = updaterInstance.logger;
|
|
210
|
+
if (isDev && !logger) {
|
|
211
|
+
logger = {
|
|
212
|
+
info: (...args) => console.log("[EIU-INFO ]", ...args),
|
|
213
|
+
debug: (...args) => console.log("[EIU-DEBUG]", ...args),
|
|
214
|
+
warn: (...args) => console.log("[EIU-WARN ]", ...args),
|
|
215
|
+
error: (...args) => console.error("[EIU-ERROR]", ...args)
|
|
216
|
+
};
|
|
217
|
+
}
|
|
217
218
|
try {
|
|
218
219
|
const appNameAsarPath = getPathFromAppNameAsar();
|
|
219
220
|
const tempAsarPath = `${appNameAsarPath}.tmp`;
|
|
220
|
-
if (
|
|
221
|
-
logger
|
|
221
|
+
if (existsSync(tempAsarPath)) {
|
|
222
|
+
logger?.info(`installing new asar: ${tempAsarPath}`);
|
|
222
223
|
await onInstall(() => renameSync(tempAsarPath, appNameAsarPath), tempAsarPath, appNameAsarPath, logger);
|
|
223
224
|
}
|
|
224
225
|
const mainFilePath = join(
|
|
225
|
-
isDev ? join(
|
|
226
|
+
isDev ? join(app.getAppPath(), __EIU_MAIN_DEV_DIR__) : appNameAsarPath,
|
|
226
227
|
"main",
|
|
227
228
|
__EIU_MAIN_FILE__
|
|
228
229
|
);
|
|
229
230
|
await beforeStart?.(mainFilePath, logger);
|
|
230
231
|
__require(mainFilePath)(updaterInstance);
|
|
231
232
|
} catch (error) {
|
|
232
|
-
logger
|
|
233
|
+
logger?.error("startup error", error);
|
|
233
234
|
onStartError?.(error, logger);
|
|
234
|
-
|
|
235
|
+
app.quit();
|
|
235
236
|
}
|
|
236
237
|
}
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
Updater,
|
|
240
|
-
UpdaterError,
|
|
241
|
-
initApp,
|
|
242
|
-
startupWithUpdater
|
|
243
|
-
};
|
|
238
|
+
|
|
239
|
+
export { ErrorInfo, Updater, UpdaterError, initApp, startupWithUpdater };
|
package/dist/provider.cjs
CHANGED
|
@@ -1,58 +1,11 @@
|
|
|
1
|
-
|
|
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
|
-
}
|
|
1
|
+
'use strict';
|
|
48
2
|
|
|
49
|
-
|
|
50
|
-
var
|
|
51
|
-
var
|
|
3
|
+
var electron = require('electron');
|
|
4
|
+
var crypto = require('crypto');
|
|
5
|
+
var fs = require('fs');
|
|
6
|
+
var zlib = require('zlib');
|
|
52
7
|
|
|
53
|
-
// src/
|
|
54
|
-
var import_node_fs3 = require("fs");
|
|
55
|
-
var import_node_zlib2 = require("zlib");
|
|
8
|
+
// src/provider/download.ts
|
|
56
9
|
|
|
57
10
|
// src/utils/version.ts
|
|
58
11
|
function parseVersion(version) {
|
|
@@ -78,7 +31,7 @@ function parseVersion(version) {
|
|
|
78
31
|
}
|
|
79
32
|
return ret;
|
|
80
33
|
}
|
|
81
|
-
function
|
|
34
|
+
function defaultIsLowerVersion(oldVer, newVer) {
|
|
82
35
|
const oldV = parseVersion(oldVer);
|
|
83
36
|
const newV = parseVersion(newVer);
|
|
84
37
|
function compareStrings(str1, str2) {
|
|
@@ -103,42 +56,11 @@ function isUpdateJSON(json) {
|
|
|
103
56
|
return is(json) && is(json?.beta);
|
|
104
57
|
}
|
|
105
58
|
|
|
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
59
|
// src/provider/download.ts
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
await waitAppReady();
|
|
60
|
+
async function downloadFn(url, headers, onResponse) {
|
|
61
|
+
await electron.app.whenReady();
|
|
140
62
|
return new Promise((resolve, reject) => {
|
|
141
|
-
const request =
|
|
63
|
+
const request = electron.net.request({ url, method: "GET", redirect: "follow" });
|
|
142
64
|
Object.keys(headers).forEach((key) => request.setHeader(key, headers[key]));
|
|
143
65
|
request.on("response", (resp) => {
|
|
144
66
|
resp.on("aborted", () => reject(new Error("aborted")));
|
|
@@ -149,8 +71,8 @@ async function downlaodFn(url, headers, onResponse) {
|
|
|
149
71
|
request.end();
|
|
150
72
|
});
|
|
151
73
|
}
|
|
152
|
-
async function
|
|
153
|
-
return await
|
|
74
|
+
async function defaultDownloadUpdateJSON(url, headers) {
|
|
75
|
+
return await downloadFn(url, headers, (resp, resolve, reject) => {
|
|
154
76
|
let data = "";
|
|
155
77
|
resp.on("data", (chunk) => data += chunk);
|
|
156
78
|
resp.on("end", () => {
|
|
@@ -161,67 +83,120 @@ async function downloadUpdateJSONDefault(url, headers) {
|
|
|
161
83
|
} else {
|
|
162
84
|
throw Error;
|
|
163
85
|
}
|
|
164
|
-
} catch
|
|
86
|
+
} catch {
|
|
165
87
|
reject(new Error("invalid update json"));
|
|
166
88
|
}
|
|
167
89
|
});
|
|
168
90
|
});
|
|
169
91
|
}
|
|
170
|
-
async function
|
|
171
|
-
let
|
|
172
|
-
|
|
92
|
+
async function defaultDownloadAsar(url, headers, total, onDownloading) {
|
|
93
|
+
let transferred = 0;
|
|
94
|
+
let time = Date.now();
|
|
95
|
+
return await downloadFn(url, headers, (resp, resolve) => {
|
|
173
96
|
let data = [];
|
|
174
97
|
resp.on("data", (chunk) => {
|
|
175
|
-
|
|
176
|
-
|
|
98
|
+
transferred += chunk.length;
|
|
99
|
+
const current = Date.now();
|
|
100
|
+
onDownloading?.({
|
|
101
|
+
percent: +(transferred / total).toFixed(2) * 100,
|
|
102
|
+
total,
|
|
103
|
+
transferred,
|
|
104
|
+
delta: chunk.length,
|
|
105
|
+
bps: chunk.length / ((current - time) * 1e3)
|
|
106
|
+
});
|
|
107
|
+
time = current;
|
|
177
108
|
data.push(chunk);
|
|
178
109
|
});
|
|
179
110
|
resp.on("end", () => resolve(Buffer.concat(data)));
|
|
180
111
|
});
|
|
181
112
|
}
|
|
113
|
+
function hashBuffer(data, length) {
|
|
114
|
+
const hash = crypto.createHash("SHA256").update(data).digest("binary");
|
|
115
|
+
return Buffer.from(hash).subarray(0, length);
|
|
116
|
+
}
|
|
117
|
+
function aesDecrypt(encryptedText, key, iv) {
|
|
118
|
+
const decipher = crypto.createDecipheriv("aes-256-cbc", key, iv);
|
|
119
|
+
return decipher.update(encryptedText, "base64url", "utf8") + decipher.final("utf8");
|
|
120
|
+
}
|
|
121
|
+
function defaultVerify(buffer, signature, cert) {
|
|
122
|
+
try {
|
|
123
|
+
const [sig, version] = aesDecrypt(signature, hashBuffer(cert, 32), hashBuffer(buffer, 16)).split("%");
|
|
124
|
+
const result = crypto.createVerify("RSA-SHA256").update(buffer).verify(cert, sig, "base64");
|
|
125
|
+
return result ? version : void 0;
|
|
126
|
+
} catch {
|
|
127
|
+
return void 0;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
async function defaultUnzipFile(buffer, targetFilePath) {
|
|
131
|
+
return new Promise((resolve, reject) => {
|
|
132
|
+
zlib.brotliDecompress(buffer, (err, buffer2) => {
|
|
133
|
+
if (err) {
|
|
134
|
+
reject(err);
|
|
135
|
+
}
|
|
136
|
+
fs.writeFileSync(targetFilePath, buffer2);
|
|
137
|
+
resolve();
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// src/provider/base.ts
|
|
143
|
+
var BaseProvider = class {
|
|
144
|
+
name = "BaseProvider";
|
|
145
|
+
isLowerVersion = defaultIsLowerVersion;
|
|
146
|
+
verifySignaure = defaultVerify;
|
|
147
|
+
unzipFile = defaultUnzipFile;
|
|
148
|
+
};
|
|
182
149
|
|
|
183
150
|
// src/provider/github.ts
|
|
184
|
-
var GitHubProvider = class {
|
|
151
|
+
var GitHubProvider = class extends BaseProvider {
|
|
185
152
|
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
153
|
name = "GithubProvider";
|
|
187
154
|
urlHandler;
|
|
188
155
|
url;
|
|
189
156
|
extraHeaders;
|
|
157
|
+
/**
|
|
158
|
+
* Update Provider for Github repo
|
|
159
|
+
* - download update json from `https://raw.githubusercontent.com/{user}/{repo}/HEAD/{versionPath}`
|
|
160
|
+
* - download update asar from `https://github.com/{user}/{repo}/releases/download/v{version}/{name}-{version}.asar.gz`
|
|
161
|
+
*
|
|
162
|
+
* you can setup `urlHandler` in {@link GitHubProviderOptions} or `Updater` to modify url before request
|
|
163
|
+
* @param options provider options
|
|
164
|
+
*/
|
|
190
165
|
constructor(options) {
|
|
191
|
-
|
|
166
|
+
super();
|
|
192
167
|
this.extraHeaders = options.extraHeaders;
|
|
193
168
|
this.urlHandler = options.urlHandler;
|
|
194
|
-
if (
|
|
169
|
+
if (!options.url.startsWith("https://github.com")) {
|
|
195
170
|
throw new Error(`${this.name}: invalid github url: ${options.url}`);
|
|
196
171
|
}
|
|
197
|
-
|
|
198
|
-
|
|
172
|
+
this.url = options.url;
|
|
173
|
+
if (!this.url.endsWith("/")) {
|
|
174
|
+
this.url += "/";
|
|
199
175
|
}
|
|
200
176
|
}
|
|
201
|
-
parseURL(isDownloadAsar,
|
|
202
|
-
const
|
|
203
|
-
|
|
177
|
+
async parseURL(isDownloadAsar, extraPath) {
|
|
178
|
+
const _url = new URL(this.url);
|
|
179
|
+
_url.hostname = isDownloadAsar ? "github.com" : "raw.githubusercontent.com";
|
|
180
|
+
_url.pathname += extraPath;
|
|
181
|
+
return (await this.urlHandler?.(_url, isDownloadAsar) || _url).toString();
|
|
204
182
|
}
|
|
205
|
-
isLowerVersion = isLowerVersionDefault;
|
|
206
|
-
verifySignaure = verifySignatureDefault;
|
|
207
183
|
async downloadJSON(versionPath) {
|
|
208
|
-
return await
|
|
209
|
-
this.parseURL(false, `HEAD/${versionPath}`),
|
|
184
|
+
return await defaultDownloadUpdateJSON(
|
|
185
|
+
await this.parseURL(false, `HEAD/${versionPath}`),
|
|
210
186
|
{ userAgent: this.ua, accept: "application/json", ...this.extraHeaders }
|
|
211
187
|
);
|
|
212
188
|
}
|
|
213
|
-
async
|
|
214
|
-
return await
|
|
215
|
-
this.parseURL(true, `releases/download/v${version}/${name}-${version}.asar.gz`),
|
|
189
|
+
async downloadAsar(name, { version, size }, onDownloading) {
|
|
190
|
+
return await defaultDownloadAsar(
|
|
191
|
+
await this.parseURL(true, `releases/download/v${version}/${name}-${version}.asar.gz`),
|
|
216
192
|
{ userAgent: this.ua, accept: "application/octet-stream", ...this.extraHeaders },
|
|
217
193
|
size,
|
|
218
194
|
onDownloading
|
|
219
195
|
);
|
|
220
196
|
}
|
|
221
197
|
};
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
});
|
|
198
|
+
|
|
199
|
+
exports.BaseProvider = BaseProvider;
|
|
200
|
+
exports.GitHubProvider = GitHubProvider;
|
|
201
|
+
exports.defaultDownloadAsar = defaultDownloadAsar;
|
|
202
|
+
exports.defaultDownloadUpdateJSON = defaultDownloadUpdateJSON;
|