electron-incremental-update 0.6.0 → 0.6.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 +6 -5
- package/dist/{chunk-VADH6AZA.mjs → chunk-KMBSE4OO.mjs} +4 -4
- package/dist/index.cjs +112 -85
- package/dist/index.d.ts +32 -19
- package/dist/index.mjs +105 -69
- package/dist/vite.cjs +44 -36
- package/dist/vite.d.ts +23 -1
- package/dist/vite.mjs +43 -35
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -76,7 +76,11 @@ const updater = createUpdater({
|
|
|
76
76
|
initApp({ name }).setUpdater(updater)
|
|
77
77
|
```
|
|
78
78
|
|
|
79
|
-
###
|
|
79
|
+
### usage in main process
|
|
80
|
+
|
|
81
|
+
To utilize the electron `net` module for requesting update information, the `checkUpdate` and `downloadAndInstall` functions must be called after the app is ready by default.
|
|
82
|
+
|
|
83
|
+
However, you have the option to customize the download function when creating the updater.
|
|
80
84
|
|
|
81
85
|
```ts
|
|
82
86
|
// electron/main/index.ts
|
|
@@ -86,6 +90,7 @@ import { app } from 'electron'
|
|
|
86
90
|
import { name } from '../../package.json'
|
|
87
91
|
|
|
88
92
|
export default function (updater: Updater) {
|
|
93
|
+
await app.whenReady()
|
|
89
94
|
console.log('\ncurrent:')
|
|
90
95
|
console.log(`\tasar path: ${getProductAsarPath(name)}`)
|
|
91
96
|
console.log(`\tentry: ${getEntryVersion()}`)
|
|
@@ -111,10 +116,6 @@ export default function (updater: Updater) {
|
|
|
111
116
|
response === 0 && console.log(await updater.downloadAndInstall())
|
|
112
117
|
}
|
|
113
118
|
})
|
|
114
|
-
// app logics
|
|
115
|
-
app.whenReady().then(() => {
|
|
116
|
-
// ...
|
|
117
|
-
})
|
|
118
119
|
}
|
|
119
120
|
```
|
|
120
121
|
|
|
@@ -26,15 +26,15 @@ function key(data, length) {
|
|
|
26
26
|
const hash = createHash("SHA256").update(data).digest("binary");
|
|
27
27
|
return Buffer2.from(hash).subarray(0, length);
|
|
28
28
|
}
|
|
29
|
-
|
|
29
|
+
var signature = (buffer, privateKey, cert, version) => {
|
|
30
30
|
const sig = createSign("RSA-SHA256").update(buffer).sign({
|
|
31
31
|
key: privateKey,
|
|
32
32
|
padding: constants.RSA_PKCS1_PADDING,
|
|
33
33
|
saltLength: constants.RSA_PSS_SALTLEN_DIGEST
|
|
34
34
|
}, "base64");
|
|
35
35
|
return encrypt(`${sig}%${version}`, key(cert, 32), key(buffer, 16));
|
|
36
|
-
}
|
|
37
|
-
|
|
36
|
+
};
|
|
37
|
+
var verify = (buffer, signature2, cert) => {
|
|
38
38
|
try {
|
|
39
39
|
const [sig, version] = decrypt(signature2, key(cert, 32), key(buffer, 16)).split("%");
|
|
40
40
|
const result = createVerify("RSA-SHA256").update(buffer).verify(cert, sig, "base64");
|
|
@@ -42,7 +42,7 @@ function verify(buffer, signature2, cert) {
|
|
|
42
42
|
} catch (error) {
|
|
43
43
|
return false;
|
|
44
44
|
}
|
|
45
|
-
}
|
|
45
|
+
};
|
|
46
46
|
|
|
47
47
|
export {
|
|
48
48
|
__require,
|
package/dist/index.cjs
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __create = Object.create;
|
|
3
2
|
var __defProp = Object.defineProperty;
|
|
4
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
6
|
var __export = (target, all) => {
|
|
9
7
|
for (var name in all)
|
|
@@ -17,14 +15,6 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
17
15
|
}
|
|
18
16
|
return to;
|
|
19
17
|
};
|
|
20
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
-
mod
|
|
27
|
-
));
|
|
28
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
19
|
|
|
30
20
|
// src/index.ts
|
|
@@ -39,11 +29,12 @@ __export(src_exports, {
|
|
|
39
29
|
isUpdateJSON: () => isUpdateJSON,
|
|
40
30
|
parseGithubCdnURL: () => parseGithubCdnURL,
|
|
41
31
|
requireNative: () => requireNative,
|
|
42
|
-
restartApp: () => restartApp
|
|
32
|
+
restartApp: () => restartApp,
|
|
33
|
+
waitAppReady: () => waitAppReady
|
|
43
34
|
});
|
|
44
35
|
module.exports = __toCommonJS(src_exports);
|
|
45
36
|
var import_node_path3 = require("path");
|
|
46
|
-
var
|
|
37
|
+
var import_electron4 = require("electron");
|
|
47
38
|
|
|
48
39
|
// src/updater/index.ts
|
|
49
40
|
var import_node_events = require("events");
|
|
@@ -52,7 +43,7 @@ var import_node_zlib = require("zlib");
|
|
|
52
43
|
var import_node_fs2 = require("fs");
|
|
53
44
|
var import_promises = require("fs/promises");
|
|
54
45
|
var import_node_path2 = require("path");
|
|
55
|
-
var
|
|
46
|
+
var import_electron3 = require("electron");
|
|
56
47
|
|
|
57
48
|
// src/crypto.ts
|
|
58
49
|
var import_node_crypto = require("crypto");
|
|
@@ -68,7 +59,7 @@ function key(data, length) {
|
|
|
68
59
|
const hash = (0, import_node_crypto.createHash)("SHA256").update(data).digest("binary");
|
|
69
60
|
return import_node_buffer.Buffer.from(hash).subarray(0, length);
|
|
70
61
|
}
|
|
71
|
-
|
|
62
|
+
var verify = (buffer, signature, cert) => {
|
|
72
63
|
try {
|
|
73
64
|
const [sig, version] = decrypt(signature, key(cert, 32), key(buffer, 16)).split("%");
|
|
74
65
|
const result = (0, import_node_crypto.createVerify)("RSA-SHA256").update(buffer).verify(cert, sig, "base64");
|
|
@@ -76,24 +67,91 @@ function verify(buffer, signature, cert) {
|
|
|
76
67
|
} catch (error) {
|
|
77
68
|
return false;
|
|
78
69
|
}
|
|
79
|
-
}
|
|
70
|
+
};
|
|
80
71
|
|
|
81
72
|
// src/updater/defaultFunctions.ts
|
|
82
73
|
var import_node_buffer2 = require("buffer");
|
|
83
|
-
var
|
|
74
|
+
var import_electron2 = require("electron");
|
|
84
75
|
|
|
85
76
|
// src/updater/types.ts
|
|
86
77
|
function isUpdateJSON(json) {
|
|
87
78
|
return "signature" in json && "version" in json && "size" in json;
|
|
88
79
|
}
|
|
89
80
|
|
|
81
|
+
// src/updater/utils.ts
|
|
82
|
+
var import_node_fs = require("fs");
|
|
83
|
+
var import_node_path = require("path");
|
|
84
|
+
var import_electron = require("electron");
|
|
85
|
+
function getProductAsarPath(name) {
|
|
86
|
+
return import_electron.app.isPackaged ? (0, import_node_path.join)((0, import_node_path.dirname)(import_electron.app.getAppPath()), `${name}.asar`) : "dev";
|
|
87
|
+
}
|
|
88
|
+
function getEntryVersion() {
|
|
89
|
+
return import_electron.app.getVersion();
|
|
90
|
+
}
|
|
91
|
+
function getProductVersion(name) {
|
|
92
|
+
return import_electron.app.isPackaged ? (0, import_node_fs.readFileSync)((0, import_node_path.join)(getProductAsarPath(name), "version"), "utf-8") : getEntryVersion();
|
|
93
|
+
}
|
|
94
|
+
function requireNative(packageName) {
|
|
95
|
+
const path = import_electron.app.isPackaged ? (0, import_node_path.join)(import_electron.app.getAppPath(), "node_modules", packageName) : packageName;
|
|
96
|
+
return require(path);
|
|
97
|
+
}
|
|
98
|
+
function parseGithubCdnURL(repository, cdnPrefix, relativeFilePath) {
|
|
99
|
+
if (!repository.startsWith("https://github.com/")) {
|
|
100
|
+
throw new Error("url must start with https://github.com/");
|
|
101
|
+
}
|
|
102
|
+
repository = repository.trim().replace(/\/?$/, "/").trim();
|
|
103
|
+
relativeFilePath = relativeFilePath.trim().replace(/^\/|\/?$/g, "").trim();
|
|
104
|
+
cdnPrefix = cdnPrefix.trim().replace(/^\/?|\/?$/g, "").trim();
|
|
105
|
+
return repository.replace("github.com", cdnPrefix) + relativeFilePath;
|
|
106
|
+
}
|
|
107
|
+
function getGithubReleaseCdnGroup() {
|
|
108
|
+
return [
|
|
109
|
+
{ cdnPrefix: "gh.gh2233.ml", maintainer: "@X.I.U/XIU2" },
|
|
110
|
+
{ cdnPrefix: "ghproxy.com", maintainer: "gh-proxy" },
|
|
111
|
+
{ cdnPrefix: "gh.ddlc.top", maintainer: "@mtr-static-official" },
|
|
112
|
+
{ cdnPrefix: "ghdl.feizhuqwq.cf", maintainer: "feizhuqwq.com" },
|
|
113
|
+
{ cdnPrefix: "slink.ltd", maintainer: "\u77E5\u4E86\u5C0F\u7AD9" },
|
|
114
|
+
{ cdnPrefix: "git.xfj0.cn", maintainer: "anonymous1" },
|
|
115
|
+
{ cdnPrefix: "gh.con.sh", maintainer: "anonymous2" },
|
|
116
|
+
{ cdnPrefix: "ghps.cc", maintainer: "anonymous3" },
|
|
117
|
+
{ cdnPrefix: "cors.isteed.cc/github.com", maintainer: "Lufs's" },
|
|
118
|
+
{ cdnPrefix: "hub.gitmirror.com", maintainer: "GitMirror" },
|
|
119
|
+
{ cdnPrefix: "js.xxooo.ml", maintainer: "\u996D\u592A\u786C" },
|
|
120
|
+
{ cdnPrefix: "download.njuu.cf", maintainer: "LibraryCloud-njuu" },
|
|
121
|
+
{ cdnPrefix: "download.yzuu.cf", maintainer: "LibraryCloud-yzuu" },
|
|
122
|
+
{ cdnPrefix: "download.nuaa.cf", maintainer: "LibraryCloud-nuaa" }
|
|
123
|
+
];
|
|
124
|
+
}
|
|
125
|
+
function restartApp() {
|
|
126
|
+
import_electron.app.relaunch();
|
|
127
|
+
import_electron.app.quit();
|
|
128
|
+
}
|
|
129
|
+
function waitAppReady(duration = 1e3) {
|
|
130
|
+
return new Promise((resolve3, reject) => {
|
|
131
|
+
const timeout = setTimeout(() => {
|
|
132
|
+
reject(new Error("app is not ready"));
|
|
133
|
+
}, duration);
|
|
134
|
+
import_electron.app.whenReady().then(() => {
|
|
135
|
+
clearTimeout(timeout);
|
|
136
|
+
resolve3(null);
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
|
|
90
141
|
// src/updater/defaultFunctions.ts
|
|
91
|
-
function downloadJSONDefault(url, updater, headers) {
|
|
142
|
+
async function downloadJSONDefault(url, updater, headers) {
|
|
143
|
+
await waitAppReady();
|
|
92
144
|
return new Promise((resolve3, reject) => {
|
|
93
|
-
|
|
145
|
+
const request = import_electron2.net.request({
|
|
146
|
+
url,
|
|
147
|
+
method: "GET",
|
|
148
|
+
redirect: "follow"
|
|
149
|
+
});
|
|
150
|
+
Object.keys(headers).forEach((key2) => {
|
|
151
|
+
request.setHeader(key2, headers[key2]);
|
|
152
|
+
});
|
|
153
|
+
request.on("response", (res) => {
|
|
94
154
|
let data = "";
|
|
95
|
-
res.setEncoding("utf8");
|
|
96
|
-
res.headers = headers;
|
|
97
155
|
res.on("data", (chunk) => data += chunk);
|
|
98
156
|
res.on("end", () => {
|
|
99
157
|
try {
|
|
@@ -107,17 +165,27 @@ function downloadJSONDefault(url, updater, headers) {
|
|
|
107
165
|
reject(new Error("invalid json"));
|
|
108
166
|
}
|
|
109
167
|
});
|
|
110
|
-
})
|
|
168
|
+
});
|
|
169
|
+
request.on("error", (e) => {
|
|
111
170
|
reject(e);
|
|
112
171
|
});
|
|
172
|
+
request.end();
|
|
113
173
|
});
|
|
114
174
|
}
|
|
115
|
-
function downloadBufferDefault(url, updater, headers) {
|
|
175
|
+
async function downloadBufferDefault(url, updater, headers) {
|
|
176
|
+
await waitAppReady();
|
|
116
177
|
let progress = 0;
|
|
117
178
|
return new Promise((resolve3, reject) => {
|
|
118
|
-
|
|
179
|
+
const request = import_electron2.net.request({
|
|
180
|
+
url,
|
|
181
|
+
method: "GET",
|
|
182
|
+
redirect: "follow"
|
|
183
|
+
});
|
|
184
|
+
Object.keys(headers).forEach((key2) => {
|
|
185
|
+
request.setHeader(key2, headers[key2]);
|
|
186
|
+
});
|
|
187
|
+
request.on("response", (res) => {
|
|
119
188
|
let data = [];
|
|
120
|
-
res.headers = headers;
|
|
121
189
|
res.on("data", (chunk) => {
|
|
122
190
|
progress += chunk.length;
|
|
123
191
|
updater.emit("downloading", progress);
|
|
@@ -129,9 +197,10 @@ function downloadBufferDefault(url, updater, headers) {
|
|
|
129
197
|
}).on("error", (e) => {
|
|
130
198
|
reject(e);
|
|
131
199
|
});
|
|
200
|
+
request.end();
|
|
132
201
|
});
|
|
133
202
|
}
|
|
134
|
-
|
|
203
|
+
var compareVersionDefault = (oldVersion, newVersion) => {
|
|
135
204
|
if (!oldVersion || !newVersion) {
|
|
136
205
|
throw new TypeError("invalid version");
|
|
137
206
|
}
|
|
@@ -152,56 +221,7 @@ function compareVersionDefault(oldVersion, newVersion) {
|
|
|
152
221
|
return true;
|
|
153
222
|
}
|
|
154
223
|
return false;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
// src/updater/utils.ts
|
|
158
|
-
var import_node_fs = require("fs");
|
|
159
|
-
var import_node_path = require("path");
|
|
160
|
-
var import_electron = require("electron");
|
|
161
|
-
function getProductAsarPath(name) {
|
|
162
|
-
return import_electron.app.isPackaged ? (0, import_node_path.join)((0, import_node_path.dirname)(import_electron.app.getAppPath()), `${name}.asar`) : "dev";
|
|
163
|
-
}
|
|
164
|
-
function getEntryVersion() {
|
|
165
|
-
return import_electron.app.getVersion();
|
|
166
|
-
}
|
|
167
|
-
function getProductVersion(name) {
|
|
168
|
-
return import_electron.app.isPackaged ? (0, import_node_fs.readFileSync)((0, import_node_path.join)(getProductAsarPath(name), "version"), "utf-8") : getEntryVersion();
|
|
169
|
-
}
|
|
170
|
-
function requireNative(packageName) {
|
|
171
|
-
const path = import_electron.app.isPackaged ? (0, import_node_path.join)(import_electron.app.getAppPath(), "node_modules", packageName) : packageName;
|
|
172
|
-
return require(path);
|
|
173
|
-
}
|
|
174
|
-
function parseGithubCdnURL(repository, cdnPrefix, relativeFilePath) {
|
|
175
|
-
if (!repository.startsWith("https://github.com/")) {
|
|
176
|
-
throw new Error("url must start with https://github.com/");
|
|
177
|
-
}
|
|
178
|
-
repository = repository.trim().replace(/\/?$/, "/").trim();
|
|
179
|
-
relativeFilePath = relativeFilePath.trim().replace(/^\/|\/?$/g, "").trim();
|
|
180
|
-
cdnPrefix = cdnPrefix.trim().replace(/^\/?|\/?$/g, "").trim();
|
|
181
|
-
return repository.replace("github.com", cdnPrefix) + relativeFilePath;
|
|
182
|
-
}
|
|
183
|
-
function getGithubReleaseCdnGroup() {
|
|
184
|
-
return [
|
|
185
|
-
{ cdnPrefix: "gh.gh2233.ml", maintainer: "@X.I.U/XIU2" },
|
|
186
|
-
{ cdnPrefix: "ghproxy.com", maintainer: "gh-proxy" },
|
|
187
|
-
{ cdnPrefix: "gh.ddlc.top", maintainer: "@mtr-static-official" },
|
|
188
|
-
{ cdnPrefix: "ghdl.feizhuqwq.cf", maintainer: "feizhuqwq.com" },
|
|
189
|
-
{ cdnPrefix: "slink.ltd", maintainer: "\u77E5\u4E86\u5C0F\u7AD9" },
|
|
190
|
-
{ cdnPrefix: "git.xfj0.cn", maintainer: "anonymous1" },
|
|
191
|
-
{ cdnPrefix: "gh.con.sh", maintainer: "anonymous2" },
|
|
192
|
-
{ cdnPrefix: "ghps.cc", maintainer: "anonymous3" },
|
|
193
|
-
{ cdnPrefix: "cors.isteed.cc/github.com", maintainer: "Lufs's" },
|
|
194
|
-
{ cdnPrefix: "hub.gitmirror.com", maintainer: "GitMirror" },
|
|
195
|
-
{ cdnPrefix: "js.xxooo.ml", maintainer: "\u996D\u592A\u786C" },
|
|
196
|
-
{ cdnPrefix: "download.njuu.cf", maintainer: "LibraryCloud-njuu" },
|
|
197
|
-
{ cdnPrefix: "download.yzuu.cf", maintainer: "LibraryCloud-yzuu" },
|
|
198
|
-
{ cdnPrefix: "download.nuaa.cf", maintainer: "LibraryCloud-nuaa" }
|
|
199
|
-
];
|
|
200
|
-
}
|
|
201
|
-
function restartApp() {
|
|
202
|
-
import_electron.app.relaunch();
|
|
203
|
-
import_electron.app.quit();
|
|
204
|
-
}
|
|
224
|
+
};
|
|
205
225
|
|
|
206
226
|
// src/updater/index.ts
|
|
207
227
|
function createUpdater({
|
|
@@ -211,15 +231,19 @@ function createUpdater({
|
|
|
211
231
|
releaseAsarURL: _release,
|
|
212
232
|
updateJsonURL: _update,
|
|
213
233
|
debug = false,
|
|
214
|
-
downloadConfig,
|
|
215
|
-
|
|
234
|
+
downloadConfig: { extraHeader, userAgent } = {},
|
|
235
|
+
overrideFunctions: {
|
|
236
|
+
compareVersion,
|
|
237
|
+
verifySignaure,
|
|
238
|
+
downloadBuffer,
|
|
239
|
+
downloadJSON
|
|
240
|
+
} = {}
|
|
216
241
|
}) {
|
|
217
242
|
const updater = new import_node_events.EventEmitter();
|
|
218
243
|
let signature = "";
|
|
219
244
|
const asarPath = getProductAsarPath(productName);
|
|
220
245
|
const gzipPath = `${asarPath}.gz`;
|
|
221
246
|
const tmpFilePath = gzipPath.replace(".asar.gz", ".tmp.asar");
|
|
222
|
-
const { downloadBuffer, downloadJSON, extraHeader, userAgent } = downloadConfig || {};
|
|
223
247
|
function log(msg) {
|
|
224
248
|
debug && updater.emit("debug", msg);
|
|
225
249
|
}
|
|
@@ -244,7 +268,7 @@ function createUpdater({
|
|
|
244
268
|
});
|
|
245
269
|
}
|
|
246
270
|
function needUpdate(version) {
|
|
247
|
-
if (!
|
|
271
|
+
if (!import_electron3.app.isPackaged) {
|
|
248
272
|
log("in dev mode, no need to update");
|
|
249
273
|
return false;
|
|
250
274
|
}
|
|
@@ -303,11 +327,12 @@ function createUpdater({
|
|
|
303
327
|
throw new Error(`invalid type at format '${format}': ${data}`);
|
|
304
328
|
}
|
|
305
329
|
}
|
|
330
|
+
updater.setDebug = (isDebug) => debug = isDebug;
|
|
306
331
|
updater.checkUpdate = async (data) => {
|
|
307
332
|
try {
|
|
308
333
|
const { signature: _sig, size, version } = await parseData("json", data);
|
|
309
|
-
log(`checked version: ${version}, size: ${size}`);
|
|
310
|
-
if (!
|
|
334
|
+
log(`checked version: ${version}, size: ${size}, signature: ${_sig}`);
|
|
335
|
+
if (!needUpdate(version)) {
|
|
311
336
|
log(`update unavailable: ${version}`);
|
|
312
337
|
return void 0;
|
|
313
338
|
} else {
|
|
@@ -328,12 +353,13 @@ function createUpdater({
|
|
|
328
353
|
}
|
|
329
354
|
const buffer = await parseData("buffer", data);
|
|
330
355
|
log("verify start");
|
|
331
|
-
const
|
|
356
|
+
const _verify = verifySignaure ?? verify;
|
|
357
|
+
const version = _verify(buffer, _sig, SIGNATURE_CERT);
|
|
332
358
|
if (!version) {
|
|
333
359
|
throw new Error("verify failed, invalid signature");
|
|
334
360
|
}
|
|
335
361
|
log("verify success");
|
|
336
|
-
if (!
|
|
362
|
+
if (!needUpdate(version)) {
|
|
337
363
|
throw new Error(`update unavailable: ${version}`);
|
|
338
364
|
}
|
|
339
365
|
log(`write file: ${gzipPath}`);
|
|
@@ -365,7 +391,7 @@ function initApp(appOptions, updaterOptions) {
|
|
|
365
391
|
electronDistPath = "dist-electron",
|
|
366
392
|
mainPath = "main/index.js"
|
|
367
393
|
} = appOptions ?? {};
|
|
368
|
-
const mainDir =
|
|
394
|
+
const mainDir = import_electron4.app.isPackaged ? `../${productName}.asar` : electronDistPath;
|
|
369
395
|
const entry = (0, import_node_path3.resolve)(__dirname, mainDir, mainPath);
|
|
370
396
|
if (updaterOptions) {
|
|
371
397
|
require(entry)(
|
|
@@ -390,5 +416,6 @@ function initApp(appOptions, updaterOptions) {
|
|
|
390
416
|
isUpdateJSON,
|
|
391
417
|
parseGithubCdnURL,
|
|
392
418
|
requireNative,
|
|
393
|
-
restartApp
|
|
419
|
+
restartApp,
|
|
420
|
+
waitAppReady
|
|
394
421
|
});
|
package/dist/index.d.ts
CHANGED
|
@@ -41,7 +41,10 @@ interface TypedUpdater<T extends Record<string | symbol, MaybeArray<any>>, Event
|
|
|
41
41
|
* - `Error`: fail
|
|
42
42
|
*/
|
|
43
43
|
downloadAndInstall(data?: string | Buffer, sig?: string): Promise<InstallResult>;
|
|
44
|
+
setDebug(debug: boolean): void;
|
|
44
45
|
}
|
|
46
|
+
type FunctionVerifySignature = (buffer: Buffer, signature: string, cert: string) => string | false;
|
|
47
|
+
type FunctionCompareVersion = (oldVersion: string, newVersion: string) => boolean;
|
|
45
48
|
type Updater = TypedUpdater<UpdateEvents>;
|
|
46
49
|
interface UpdaterOption {
|
|
47
50
|
/**
|
|
@@ -91,25 +94,23 @@ interface UpdaterOption {
|
|
|
91
94
|
* whether to enable debug listener
|
|
92
95
|
*/
|
|
93
96
|
debug?: boolean;
|
|
94
|
-
|
|
95
|
-
* custom version compare function
|
|
96
|
-
* @param oldVersion old version string
|
|
97
|
-
* @param newVersion new version string
|
|
98
|
-
* @returns whether to update
|
|
99
|
-
*/
|
|
100
|
-
compareVersion?: (oldVersion: string, newVersion: string) => boolean;
|
|
101
|
-
downloadConfig?: {
|
|
97
|
+
overrideFunctions?: {
|
|
102
98
|
/**
|
|
103
|
-
*
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
99
|
+
* custom version compare function {@link FunctionCompareVersion}
|
|
100
|
+
* @param oldVersion old version string
|
|
101
|
+
* @param newVersion new version string
|
|
102
|
+
* @returns whether to update
|
|
103
|
+
*/
|
|
104
|
+
compareVersion?: FunctionCompareVersion;
|
|
107
105
|
/**
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
106
|
+
* custom verify signature function {@link FunctionVerifySignature}
|
|
107
|
+
* @param buffer file buffer
|
|
108
|
+
* @param signature signature
|
|
109
|
+
* @param cert certificate
|
|
110
|
+
*/
|
|
111
|
+
verifySignaure?: FunctionVerifySignature;
|
|
111
112
|
/**
|
|
112
|
-
* download JSON function
|
|
113
|
+
* custom download JSON function
|
|
113
114
|
* @param url download url
|
|
114
115
|
* @param updater updater, to trigger events
|
|
115
116
|
* @param header download header
|
|
@@ -117,7 +118,7 @@ interface UpdaterOption {
|
|
|
117
118
|
*/
|
|
118
119
|
downloadJSON?: (url: string, updater: Updater, headers: Record<string, any>) => Promise<UpdateJSON>;
|
|
119
120
|
/**
|
|
120
|
-
* download buffer function
|
|
121
|
+
* custom download buffer function
|
|
121
122
|
* @param url download url
|
|
122
123
|
* @param updater updater, to trigger events
|
|
123
124
|
* @param header download header
|
|
@@ -125,6 +126,17 @@ interface UpdaterOption {
|
|
|
125
126
|
*/
|
|
126
127
|
downloadBuffer?: (url: string, updater: Updater, headers: Record<string, any>) => Promise<Buffer>;
|
|
127
128
|
};
|
|
129
|
+
downloadConfig?: {
|
|
130
|
+
/**
|
|
131
|
+
* download user agent
|
|
132
|
+
* @default 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36'
|
|
133
|
+
*/
|
|
134
|
+
userAgent?: string;
|
|
135
|
+
/**
|
|
136
|
+
* extra download header, `accept` and `user-agent` is set by default
|
|
137
|
+
*/
|
|
138
|
+
extraHeader?: Record<string, string>;
|
|
139
|
+
};
|
|
128
140
|
}
|
|
129
141
|
|
|
130
142
|
/**
|
|
@@ -158,8 +170,9 @@ declare function getGithubReleaseCdnGroup(): {
|
|
|
158
170
|
maintainer: string;
|
|
159
171
|
}[];
|
|
160
172
|
declare function restartApp(): void;
|
|
173
|
+
declare function waitAppReady(duration?: number): Promise<unknown>;
|
|
161
174
|
|
|
162
|
-
declare function createUpdater({ SIGNATURE_CERT, repository, productName, releaseAsarURL: _release, updateJsonURL: _update, debug, downloadConfig, compareVersion, }: UpdaterOption): Updater;
|
|
175
|
+
declare function createUpdater({ SIGNATURE_CERT, repository, productName, releaseAsarURL: _release, updateJsonURL: _update, debug, downloadConfig: { extraHeader, userAgent }, overrideFunctions: { compareVersion, verifySignaure, downloadBuffer, downloadJSON, }, }: UpdaterOption): Updater;
|
|
163
176
|
|
|
164
177
|
type AppOption = {
|
|
165
178
|
/**
|
|
@@ -220,4 +233,4 @@ declare function initApp(appOptions: AppOption): {
|
|
|
220
233
|
*/
|
|
221
234
|
declare function initApp(appOptions: AppOption, updaterOptions: InitUpdaterOptions): undefined;
|
|
222
235
|
|
|
223
|
-
export { AppOption, CheckResultType, InitUpdaterOptions, InstallResult, UpdateJSON, Updater, UpdaterOption, createUpdater, getEntryVersion, getGithubReleaseCdnGroup, getProductAsarPath, getProductVersion, initApp, isUpdateJSON, parseGithubCdnURL, requireNative, restartApp };
|
|
236
|
+
export { AppOption, CheckResultType, FunctionCompareVersion, FunctionVerifySignature, InitUpdaterOptions, InstallResult, UpdateJSON, Updater, UpdaterOption, createUpdater, getEntryVersion, getGithubReleaseCdnGroup, getProductAsarPath, getProductVersion, initApp, isUpdateJSON, parseGithubCdnURL, requireNative, restartApp, waitAppReady };
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
__require,
|
|
3
3
|
verify
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-KMBSE4OO.mjs";
|
|
5
5
|
|
|
6
6
|
// src/index.ts
|
|
7
7
|
import { resolve as resolve2 } from "node:path";
|
|
@@ -18,20 +18,87 @@ import { app as app2 } from "electron";
|
|
|
18
18
|
|
|
19
19
|
// src/updater/defaultFunctions.ts
|
|
20
20
|
import { Buffer } from "node:buffer";
|
|
21
|
-
import
|
|
21
|
+
import { net } from "electron";
|
|
22
22
|
|
|
23
23
|
// src/updater/types.ts
|
|
24
24
|
function isUpdateJSON(json) {
|
|
25
25
|
return "signature" in json && "version" in json && "size" in json;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
// src/updater/utils.ts
|
|
29
|
+
import { readFileSync } from "node:fs";
|
|
30
|
+
import { dirname, join } from "node:path";
|
|
31
|
+
import { app } from "electron";
|
|
32
|
+
function getProductAsarPath(name) {
|
|
33
|
+
return app.isPackaged ? join(dirname(app.getAppPath()), `${name}.asar`) : "dev";
|
|
34
|
+
}
|
|
35
|
+
function getEntryVersion() {
|
|
36
|
+
return app.getVersion();
|
|
37
|
+
}
|
|
38
|
+
function getProductVersion(name) {
|
|
39
|
+
return app.isPackaged ? readFileSync(join(getProductAsarPath(name), "version"), "utf-8") : getEntryVersion();
|
|
40
|
+
}
|
|
41
|
+
function requireNative(packageName) {
|
|
42
|
+
const path = app.isPackaged ? join(app.getAppPath(), "node_modules", packageName) : packageName;
|
|
43
|
+
return __require(path);
|
|
44
|
+
}
|
|
45
|
+
function parseGithubCdnURL(repository, cdnPrefix, relativeFilePath) {
|
|
46
|
+
if (!repository.startsWith("https://github.com/")) {
|
|
47
|
+
throw new Error("url must start with https://github.com/");
|
|
48
|
+
}
|
|
49
|
+
repository = repository.trim().replace(/\/?$/, "/").trim();
|
|
50
|
+
relativeFilePath = relativeFilePath.trim().replace(/^\/|\/?$/g, "").trim();
|
|
51
|
+
cdnPrefix = cdnPrefix.trim().replace(/^\/?|\/?$/g, "").trim();
|
|
52
|
+
return repository.replace("github.com", cdnPrefix) + relativeFilePath;
|
|
53
|
+
}
|
|
54
|
+
function getGithubReleaseCdnGroup() {
|
|
55
|
+
return [
|
|
56
|
+
{ cdnPrefix: "gh.gh2233.ml", maintainer: "@X.I.U/XIU2" },
|
|
57
|
+
{ cdnPrefix: "ghproxy.com", maintainer: "gh-proxy" },
|
|
58
|
+
{ cdnPrefix: "gh.ddlc.top", maintainer: "@mtr-static-official" },
|
|
59
|
+
{ cdnPrefix: "ghdl.feizhuqwq.cf", maintainer: "feizhuqwq.com" },
|
|
60
|
+
{ cdnPrefix: "slink.ltd", maintainer: "\u77E5\u4E86\u5C0F\u7AD9" },
|
|
61
|
+
{ cdnPrefix: "git.xfj0.cn", maintainer: "anonymous1" },
|
|
62
|
+
{ cdnPrefix: "gh.con.sh", maintainer: "anonymous2" },
|
|
63
|
+
{ cdnPrefix: "ghps.cc", maintainer: "anonymous3" },
|
|
64
|
+
{ cdnPrefix: "cors.isteed.cc/github.com", maintainer: "Lufs's" },
|
|
65
|
+
{ cdnPrefix: "hub.gitmirror.com", maintainer: "GitMirror" },
|
|
66
|
+
{ cdnPrefix: "js.xxooo.ml", maintainer: "\u996D\u592A\u786C" },
|
|
67
|
+
{ cdnPrefix: "download.njuu.cf", maintainer: "LibraryCloud-njuu" },
|
|
68
|
+
{ cdnPrefix: "download.yzuu.cf", maintainer: "LibraryCloud-yzuu" },
|
|
69
|
+
{ cdnPrefix: "download.nuaa.cf", maintainer: "LibraryCloud-nuaa" }
|
|
70
|
+
];
|
|
71
|
+
}
|
|
72
|
+
function restartApp() {
|
|
73
|
+
app.relaunch();
|
|
74
|
+
app.quit();
|
|
75
|
+
}
|
|
76
|
+
function waitAppReady(duration = 1e3) {
|
|
77
|
+
return new Promise((resolve3, reject) => {
|
|
78
|
+
const timeout = setTimeout(() => {
|
|
79
|
+
reject(new Error("app is not ready"));
|
|
80
|
+
}, duration);
|
|
81
|
+
app.whenReady().then(() => {
|
|
82
|
+
clearTimeout(timeout);
|
|
83
|
+
resolve3(null);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
28
88
|
// src/updater/defaultFunctions.ts
|
|
29
|
-
function downloadJSONDefault(url, updater, headers) {
|
|
89
|
+
async function downloadJSONDefault(url, updater, headers) {
|
|
90
|
+
await waitAppReady();
|
|
30
91
|
return new Promise((resolve3, reject) => {
|
|
31
|
-
|
|
92
|
+
const request = net.request({
|
|
93
|
+
url,
|
|
94
|
+
method: "GET",
|
|
95
|
+
redirect: "follow"
|
|
96
|
+
});
|
|
97
|
+
Object.keys(headers).forEach((key) => {
|
|
98
|
+
request.setHeader(key, headers[key]);
|
|
99
|
+
});
|
|
100
|
+
request.on("response", (res) => {
|
|
32
101
|
let data = "";
|
|
33
|
-
res.setEncoding("utf8");
|
|
34
|
-
res.headers = headers;
|
|
35
102
|
res.on("data", (chunk) => data += chunk);
|
|
36
103
|
res.on("end", () => {
|
|
37
104
|
try {
|
|
@@ -45,17 +112,27 @@ function downloadJSONDefault(url, updater, headers) {
|
|
|
45
112
|
reject(new Error("invalid json"));
|
|
46
113
|
}
|
|
47
114
|
});
|
|
48
|
-
})
|
|
115
|
+
});
|
|
116
|
+
request.on("error", (e) => {
|
|
49
117
|
reject(e);
|
|
50
118
|
});
|
|
119
|
+
request.end();
|
|
51
120
|
});
|
|
52
121
|
}
|
|
53
|
-
function downloadBufferDefault(url, updater, headers) {
|
|
122
|
+
async function downloadBufferDefault(url, updater, headers) {
|
|
123
|
+
await waitAppReady();
|
|
54
124
|
let progress = 0;
|
|
55
125
|
return new Promise((resolve3, reject) => {
|
|
56
|
-
|
|
126
|
+
const request = net.request({
|
|
127
|
+
url,
|
|
128
|
+
method: "GET",
|
|
129
|
+
redirect: "follow"
|
|
130
|
+
});
|
|
131
|
+
Object.keys(headers).forEach((key) => {
|
|
132
|
+
request.setHeader(key, headers[key]);
|
|
133
|
+
});
|
|
134
|
+
request.on("response", (res) => {
|
|
57
135
|
let data = [];
|
|
58
|
-
res.headers = headers;
|
|
59
136
|
res.on("data", (chunk) => {
|
|
60
137
|
progress += chunk.length;
|
|
61
138
|
updater.emit("downloading", progress);
|
|
@@ -67,9 +144,10 @@ function downloadBufferDefault(url, updater, headers) {
|
|
|
67
144
|
}).on("error", (e) => {
|
|
68
145
|
reject(e);
|
|
69
146
|
});
|
|
147
|
+
request.end();
|
|
70
148
|
});
|
|
71
149
|
}
|
|
72
|
-
|
|
150
|
+
var compareVersionDefault = (oldVersion, newVersion) => {
|
|
73
151
|
if (!oldVersion || !newVersion) {
|
|
74
152
|
throw new TypeError("invalid version");
|
|
75
153
|
}
|
|
@@ -90,56 +168,7 @@ function compareVersionDefault(oldVersion, newVersion) {
|
|
|
90
168
|
return true;
|
|
91
169
|
}
|
|
92
170
|
return false;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// src/updater/utils.ts
|
|
96
|
-
import { readFileSync } from "node:fs";
|
|
97
|
-
import { dirname, join } from "node:path";
|
|
98
|
-
import { app } from "electron";
|
|
99
|
-
function getProductAsarPath(name) {
|
|
100
|
-
return app.isPackaged ? join(dirname(app.getAppPath()), `${name}.asar`) : "dev";
|
|
101
|
-
}
|
|
102
|
-
function getEntryVersion() {
|
|
103
|
-
return app.getVersion();
|
|
104
|
-
}
|
|
105
|
-
function getProductVersion(name) {
|
|
106
|
-
return app.isPackaged ? readFileSync(join(getProductAsarPath(name), "version"), "utf-8") : getEntryVersion();
|
|
107
|
-
}
|
|
108
|
-
function requireNative(packageName) {
|
|
109
|
-
const path = app.isPackaged ? join(app.getAppPath(), "node_modules", packageName) : packageName;
|
|
110
|
-
return __require(path);
|
|
111
|
-
}
|
|
112
|
-
function parseGithubCdnURL(repository, cdnPrefix, relativeFilePath) {
|
|
113
|
-
if (!repository.startsWith("https://github.com/")) {
|
|
114
|
-
throw new Error("url must start with https://github.com/");
|
|
115
|
-
}
|
|
116
|
-
repository = repository.trim().replace(/\/?$/, "/").trim();
|
|
117
|
-
relativeFilePath = relativeFilePath.trim().replace(/^\/|\/?$/g, "").trim();
|
|
118
|
-
cdnPrefix = cdnPrefix.trim().replace(/^\/?|\/?$/g, "").trim();
|
|
119
|
-
return repository.replace("github.com", cdnPrefix) + relativeFilePath;
|
|
120
|
-
}
|
|
121
|
-
function getGithubReleaseCdnGroup() {
|
|
122
|
-
return [
|
|
123
|
-
{ cdnPrefix: "gh.gh2233.ml", maintainer: "@X.I.U/XIU2" },
|
|
124
|
-
{ cdnPrefix: "ghproxy.com", maintainer: "gh-proxy" },
|
|
125
|
-
{ cdnPrefix: "gh.ddlc.top", maintainer: "@mtr-static-official" },
|
|
126
|
-
{ cdnPrefix: "ghdl.feizhuqwq.cf", maintainer: "feizhuqwq.com" },
|
|
127
|
-
{ cdnPrefix: "slink.ltd", maintainer: "\u77E5\u4E86\u5C0F\u7AD9" },
|
|
128
|
-
{ cdnPrefix: "git.xfj0.cn", maintainer: "anonymous1" },
|
|
129
|
-
{ cdnPrefix: "gh.con.sh", maintainer: "anonymous2" },
|
|
130
|
-
{ cdnPrefix: "ghps.cc", maintainer: "anonymous3" },
|
|
131
|
-
{ cdnPrefix: "cors.isteed.cc/github.com", maintainer: "Lufs's" },
|
|
132
|
-
{ cdnPrefix: "hub.gitmirror.com", maintainer: "GitMirror" },
|
|
133
|
-
{ cdnPrefix: "js.xxooo.ml", maintainer: "\u996D\u592A\u786C" },
|
|
134
|
-
{ cdnPrefix: "download.njuu.cf", maintainer: "LibraryCloud-njuu" },
|
|
135
|
-
{ cdnPrefix: "download.yzuu.cf", maintainer: "LibraryCloud-yzuu" },
|
|
136
|
-
{ cdnPrefix: "download.nuaa.cf", maintainer: "LibraryCloud-nuaa" }
|
|
137
|
-
];
|
|
138
|
-
}
|
|
139
|
-
function restartApp() {
|
|
140
|
-
app.relaunch();
|
|
141
|
-
app.quit();
|
|
142
|
-
}
|
|
171
|
+
};
|
|
143
172
|
|
|
144
173
|
// src/updater/index.ts
|
|
145
174
|
function createUpdater({
|
|
@@ -149,15 +178,19 @@ function createUpdater({
|
|
|
149
178
|
releaseAsarURL: _release,
|
|
150
179
|
updateJsonURL: _update,
|
|
151
180
|
debug = false,
|
|
152
|
-
downloadConfig,
|
|
153
|
-
|
|
181
|
+
downloadConfig: { extraHeader, userAgent } = {},
|
|
182
|
+
overrideFunctions: {
|
|
183
|
+
compareVersion,
|
|
184
|
+
verifySignaure,
|
|
185
|
+
downloadBuffer,
|
|
186
|
+
downloadJSON
|
|
187
|
+
} = {}
|
|
154
188
|
}) {
|
|
155
189
|
const updater = new EventEmitter();
|
|
156
190
|
let signature = "";
|
|
157
191
|
const asarPath = getProductAsarPath(productName);
|
|
158
192
|
const gzipPath = `${asarPath}.gz`;
|
|
159
193
|
const tmpFilePath = gzipPath.replace(".asar.gz", ".tmp.asar");
|
|
160
|
-
const { downloadBuffer, downloadJSON, extraHeader, userAgent } = downloadConfig || {};
|
|
161
194
|
function log(msg) {
|
|
162
195
|
debug && updater.emit("debug", msg);
|
|
163
196
|
}
|
|
@@ -241,11 +274,12 @@ function createUpdater({
|
|
|
241
274
|
throw new Error(`invalid type at format '${format}': ${data}`);
|
|
242
275
|
}
|
|
243
276
|
}
|
|
277
|
+
updater.setDebug = (isDebug) => debug = isDebug;
|
|
244
278
|
updater.checkUpdate = async (data) => {
|
|
245
279
|
try {
|
|
246
280
|
const { signature: _sig, size, version } = await parseData("json", data);
|
|
247
|
-
log(`checked version: ${version}, size: ${size}`);
|
|
248
|
-
if (!
|
|
281
|
+
log(`checked version: ${version}, size: ${size}, signature: ${_sig}`);
|
|
282
|
+
if (!needUpdate(version)) {
|
|
249
283
|
log(`update unavailable: ${version}`);
|
|
250
284
|
return void 0;
|
|
251
285
|
} else {
|
|
@@ -266,12 +300,13 @@ function createUpdater({
|
|
|
266
300
|
}
|
|
267
301
|
const buffer = await parseData("buffer", data);
|
|
268
302
|
log("verify start");
|
|
269
|
-
const
|
|
303
|
+
const _verify = verifySignaure ?? verify;
|
|
304
|
+
const version = _verify(buffer, _sig, SIGNATURE_CERT);
|
|
270
305
|
if (!version) {
|
|
271
306
|
throw new Error("verify failed, invalid signature");
|
|
272
307
|
}
|
|
273
308
|
log("verify success");
|
|
274
|
-
if (!
|
|
309
|
+
if (!needUpdate(version)) {
|
|
275
310
|
throw new Error(`update unavailable: ${version}`);
|
|
276
311
|
}
|
|
277
312
|
log(`write file: ${gzipPath}`);
|
|
@@ -327,5 +362,6 @@ export {
|
|
|
327
362
|
isUpdateJSON,
|
|
328
363
|
parseGithubCdnURL,
|
|
329
364
|
requireNative,
|
|
330
|
-
restartApp
|
|
365
|
+
restartApp,
|
|
366
|
+
waitAppReady
|
|
331
367
|
};
|
package/dist/vite.cjs
CHANGED
|
@@ -55,14 +55,14 @@ function key(data, length) {
|
|
|
55
55
|
const hash = (0, import_node_crypto.createHash)("SHA256").update(data).digest("binary");
|
|
56
56
|
return import_node_buffer.Buffer.from(hash).subarray(0, length);
|
|
57
57
|
}
|
|
58
|
-
|
|
58
|
+
var signature = (buffer, privateKey, cert, version) => {
|
|
59
59
|
const sig = (0, import_node_crypto.createSign)("RSA-SHA256").update(buffer).sign({
|
|
60
60
|
key: privateKey,
|
|
61
61
|
padding: import_node_crypto.constants.RSA_PKCS1_PADDING,
|
|
62
62
|
saltLength: import_node_crypto.constants.RSA_PSS_SALTLEN_DIGEST
|
|
63
63
|
}, "base64");
|
|
64
64
|
return encrypt(`${sig}%${version}`, key(cert, 32), key(buffer, 16));
|
|
65
|
-
}
|
|
65
|
+
};
|
|
66
66
|
|
|
67
67
|
// src/build-plugins/build.ts
|
|
68
68
|
function gzipFile(filePath) {
|
|
@@ -106,11 +106,13 @@ async function buildVersion({
|
|
|
106
106
|
versionPath,
|
|
107
107
|
privateKey,
|
|
108
108
|
cert,
|
|
109
|
-
version
|
|
109
|
+
version,
|
|
110
|
+
generateSignature
|
|
110
111
|
}) {
|
|
111
112
|
const buffer = await (0, import_promises.readFile)(`${asarOutputPath}.gz`);
|
|
113
|
+
const _func = generateSignature ?? signature;
|
|
112
114
|
await (0, import_promises.writeFile)(versionPath, JSON.stringify({
|
|
113
|
-
signature:
|
|
115
|
+
signature: _func(buffer, privateKey, cert, version),
|
|
114
116
|
version,
|
|
115
117
|
size: buffer.length
|
|
116
118
|
}, null, 2));
|
|
@@ -136,23 +138,13 @@ var import_node_path = require("path");
|
|
|
136
138
|
var import_node_os = require("os");
|
|
137
139
|
var import_node_crypto2 = require("crypto");
|
|
138
140
|
var import_jscert = require("@cyyynthia/jscert");
|
|
139
|
-
function generateCert(privateKey) {
|
|
140
|
-
const dn = {
|
|
141
|
-
country: "zh-CN",
|
|
142
|
-
state: "zj",
|
|
143
|
-
locality: "hz",
|
|
144
|
-
organization: "test",
|
|
145
|
-
organizationalUnit: "test unit",
|
|
146
|
-
commonName: "test.test",
|
|
147
|
-
emailAddress: "test@example.com"
|
|
148
|
-
};
|
|
141
|
+
function generateCert(privateKey, dn, expires) {
|
|
149
142
|
const csr = new import_jscert.CertificateSigningRequest(dn, privateKey, { digest: "sha256" });
|
|
150
|
-
|
|
151
|
-
return csr.createSelfSignedCertificate(expiry).toPem();
|
|
143
|
+
return csr.createSelfSignedCertificate(expires).toPem();
|
|
152
144
|
}
|
|
153
|
-
function
|
|
145
|
+
function generateKeyPairDefault(length, subjects, expires) {
|
|
154
146
|
const { privateKey: _key } = (0, import_node_crypto2.generateKeyPairSync)("rsa", { modulusLength: length });
|
|
155
|
-
const cert = generateCert(_key);
|
|
147
|
+
const cert = generateCert(_key, subjects, expires);
|
|
156
148
|
const privateKey = _key.export({ type: "pkcs1", format: "pem" });
|
|
157
149
|
return {
|
|
158
150
|
privateKey,
|
|
@@ -188,13 +180,17 @@ function getKeys({
|
|
|
188
180
|
keyLength,
|
|
189
181
|
privateKeyPath,
|
|
190
182
|
certPath,
|
|
191
|
-
entryPath
|
|
183
|
+
entryPath,
|
|
184
|
+
subject,
|
|
185
|
+
expires,
|
|
186
|
+
generateKeyPair
|
|
192
187
|
}) {
|
|
193
188
|
const keysDir = (0, import_node_path.dirname)(privateKeyPath);
|
|
194
189
|
!(0, import_node_fs2.existsSync)(keysDir) && (0, import_node_fs2.mkdirSync)(keysDir);
|
|
195
190
|
let privateKey, cert;
|
|
196
191
|
if (!(0, import_node_fs2.existsSync)(privateKeyPath) || !(0, import_node_fs2.existsSync)(certPath)) {
|
|
197
|
-
const
|
|
192
|
+
const _func = generateKeyPair ?? generateKeyPairDefault;
|
|
193
|
+
const keys = _func(keyLength, subject, expires);
|
|
198
194
|
privateKey = keys.privateKey;
|
|
199
195
|
cert = keys.cert;
|
|
200
196
|
(0, import_node_fs2.writeFileSync)(privateKeyPath, privateKey);
|
|
@@ -213,28 +209,38 @@ function getKeys({
|
|
|
213
209
|
// src/build-plugins/option.ts
|
|
214
210
|
var import_ci_info = require("ci-info");
|
|
215
211
|
function parseOptions(options) {
|
|
216
|
-
const { isBuild, productName, version, minify = false, paths = {}, keys = {} } = options;
|
|
217
212
|
const {
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
213
|
+
isBuild,
|
|
214
|
+
productName,
|
|
215
|
+
version,
|
|
216
|
+
minify = false,
|
|
217
|
+
paths: {
|
|
218
|
+
entryPath = "electron/app.ts",
|
|
219
|
+
entryOutputPath = "app.js",
|
|
220
|
+
asarOutputPath = `release/${productName}-${version}.asar`,
|
|
221
|
+
electronDistPath = "dist-electron",
|
|
222
|
+
rendererDistPath = "dist",
|
|
223
|
+
versionPath = "version.json"
|
|
224
|
+
} = {},
|
|
225
|
+
keys: {
|
|
226
|
+
privateKeyPath = "keys/private.pem",
|
|
227
|
+
certPath = "keys/cert.pem",
|
|
228
|
+
keyLength = 2048,
|
|
229
|
+
certInfo = {},
|
|
230
|
+
overrideFunctions = {}
|
|
231
|
+
} = {}
|
|
232
|
+
} = options;
|
|
225
233
|
const {
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
certInfo
|
|
230
|
-
} = keys;
|
|
234
|
+
generateKeyPair,
|
|
235
|
+
generateSignature
|
|
236
|
+
} = overrideFunctions;
|
|
231
237
|
let {
|
|
232
238
|
subject = {
|
|
233
239
|
commonName: productName,
|
|
234
240
|
organization: `org.${productName}`
|
|
235
241
|
},
|
|
236
242
|
expires = Date.now() + 365 * 864e5
|
|
237
|
-
} = certInfo
|
|
243
|
+
} = certInfo;
|
|
238
244
|
const buildAsarOption = {
|
|
239
245
|
version,
|
|
240
246
|
asarOutputPath,
|
|
@@ -257,14 +263,16 @@ function parseOptions(options) {
|
|
|
257
263
|
certPath,
|
|
258
264
|
entryPath,
|
|
259
265
|
subject,
|
|
260
|
-
expires
|
|
266
|
+
expires,
|
|
267
|
+
generateKeyPair
|
|
261
268
|
});
|
|
262
269
|
buildVersionOption = {
|
|
263
270
|
version,
|
|
264
271
|
asarOutputPath,
|
|
265
272
|
privateKey,
|
|
266
273
|
cert,
|
|
267
|
-
versionPath
|
|
274
|
+
versionPath,
|
|
275
|
+
generateSignature
|
|
268
276
|
};
|
|
269
277
|
}
|
|
270
278
|
return { isBuild, buildAsarOption, buildEntryOption, buildVersionOption };
|
package/dist/vite.d.ts
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { Plugin } from 'vite';
|
|
2
|
+
import { Buffer } from 'node:buffer';
|
|
2
3
|
import { DistinguishedName } from '@cyyynthia/jscert';
|
|
3
4
|
|
|
5
|
+
type FunctionGenerateKeyPair = (keyLength: number, subject: DistinguishedName, expires: Date) => {
|
|
6
|
+
privateKey: string;
|
|
7
|
+
cert: string;
|
|
8
|
+
};
|
|
9
|
+
type FunctionGenerateSignature = (buffer: Buffer, privateKey: string, cert: string, version: string) => string;
|
|
4
10
|
type Options = {
|
|
5
11
|
/**
|
|
6
12
|
* whether is in build mode
|
|
@@ -38,7 +44,7 @@ type Options = {
|
|
|
38
44
|
entryOutputPath?: string;
|
|
39
45
|
/**
|
|
40
46
|
* Path to asar file
|
|
41
|
-
* @default `release/${
|
|
47
|
+
* @default `release/${productName}.asar`
|
|
42
48
|
*/
|
|
43
49
|
asarOutputPath?: string;
|
|
44
50
|
/**
|
|
@@ -99,6 +105,22 @@ type Options = {
|
|
|
99
105
|
*/
|
|
100
106
|
expires?: Date | number;
|
|
101
107
|
};
|
|
108
|
+
overrideFunctions?: {
|
|
109
|
+
/**
|
|
110
|
+
* custom key pair generate function {@link FunctionGenerateKeyPair}
|
|
111
|
+
* @param keyLength key length
|
|
112
|
+
* @param subject subject info
|
|
113
|
+
* @param expires expire date
|
|
114
|
+
*/
|
|
115
|
+
generateKeyPair?: FunctionGenerateKeyPair;
|
|
116
|
+
/**
|
|
117
|
+
* custom signature generate function {@link FunctionGenerateSignature}
|
|
118
|
+
* @param buffer file buffer
|
|
119
|
+
* @param privateKey private key
|
|
120
|
+
* @param cert certificate
|
|
121
|
+
*/
|
|
122
|
+
generateSignature?: FunctionGenerateSignature;
|
|
123
|
+
};
|
|
102
124
|
};
|
|
103
125
|
};
|
|
104
126
|
|
package/dist/vite.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
signature
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-KMBSE4OO.mjs";
|
|
4
4
|
|
|
5
5
|
// src/vite.ts
|
|
6
6
|
import { createLogger } from "vite";
|
|
@@ -51,11 +51,13 @@ async function buildVersion({
|
|
|
51
51
|
versionPath,
|
|
52
52
|
privateKey,
|
|
53
53
|
cert,
|
|
54
|
-
version
|
|
54
|
+
version,
|
|
55
|
+
generateSignature
|
|
55
56
|
}) {
|
|
56
57
|
const buffer = await readFile(`${asarOutputPath}.gz`);
|
|
58
|
+
const _func = generateSignature ?? signature;
|
|
57
59
|
await writeFile(versionPath, JSON.stringify({
|
|
58
|
-
signature:
|
|
60
|
+
signature: _func(buffer, privateKey, cert, version),
|
|
59
61
|
version,
|
|
60
62
|
size: buffer.length
|
|
61
63
|
}, null, 2));
|
|
@@ -81,23 +83,13 @@ import { dirname } from "node:path";
|
|
|
81
83
|
import { EOL } from "node:os";
|
|
82
84
|
import { generateKeyPairSync } from "node:crypto";
|
|
83
85
|
import { CertificateSigningRequest } from "@cyyynthia/jscert";
|
|
84
|
-
function generateCert(privateKey) {
|
|
85
|
-
const dn = {
|
|
86
|
-
country: "zh-CN",
|
|
87
|
-
state: "zj",
|
|
88
|
-
locality: "hz",
|
|
89
|
-
organization: "test",
|
|
90
|
-
organizationalUnit: "test unit",
|
|
91
|
-
commonName: "test.test",
|
|
92
|
-
emailAddress: "test@example.com"
|
|
93
|
-
};
|
|
86
|
+
function generateCert(privateKey, dn, expires) {
|
|
94
87
|
const csr = new CertificateSigningRequest(dn, privateKey, { digest: "sha256" });
|
|
95
|
-
|
|
96
|
-
return csr.createSelfSignedCertificate(expiry).toPem();
|
|
88
|
+
return csr.createSelfSignedCertificate(expires).toPem();
|
|
97
89
|
}
|
|
98
|
-
function
|
|
90
|
+
function generateKeyPairDefault(length, subjects, expires) {
|
|
99
91
|
const { privateKey: _key } = generateKeyPairSync("rsa", { modulusLength: length });
|
|
100
|
-
const cert = generateCert(_key);
|
|
92
|
+
const cert = generateCert(_key, subjects, expires);
|
|
101
93
|
const privateKey = _key.export({ type: "pkcs1", format: "pem" });
|
|
102
94
|
return {
|
|
103
95
|
privateKey,
|
|
@@ -133,13 +125,17 @@ function getKeys({
|
|
|
133
125
|
keyLength,
|
|
134
126
|
privateKeyPath,
|
|
135
127
|
certPath,
|
|
136
|
-
entryPath
|
|
128
|
+
entryPath,
|
|
129
|
+
subject,
|
|
130
|
+
expires,
|
|
131
|
+
generateKeyPair
|
|
137
132
|
}) {
|
|
138
133
|
const keysDir = dirname(privateKeyPath);
|
|
139
134
|
!existsSync(keysDir) && mkdirSync(keysDir);
|
|
140
135
|
let privateKey, cert;
|
|
141
136
|
if (!existsSync(privateKeyPath) || !existsSync(certPath)) {
|
|
142
|
-
const
|
|
137
|
+
const _func = generateKeyPair ?? generateKeyPairDefault;
|
|
138
|
+
const keys = _func(keyLength, subject, expires);
|
|
143
139
|
privateKey = keys.privateKey;
|
|
144
140
|
cert = keys.cert;
|
|
145
141
|
writeFileSync(privateKeyPath, privateKey);
|
|
@@ -158,28 +154,38 @@ function getKeys({
|
|
|
158
154
|
// src/build-plugins/option.ts
|
|
159
155
|
import { isCI } from "ci-info";
|
|
160
156
|
function parseOptions(options) {
|
|
161
|
-
const { isBuild, productName, version, minify = false, paths = {}, keys = {} } = options;
|
|
162
157
|
const {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
158
|
+
isBuild,
|
|
159
|
+
productName,
|
|
160
|
+
version,
|
|
161
|
+
minify = false,
|
|
162
|
+
paths: {
|
|
163
|
+
entryPath = "electron/app.ts",
|
|
164
|
+
entryOutputPath = "app.js",
|
|
165
|
+
asarOutputPath = `release/${productName}-${version}.asar`,
|
|
166
|
+
electronDistPath = "dist-electron",
|
|
167
|
+
rendererDistPath = "dist",
|
|
168
|
+
versionPath = "version.json"
|
|
169
|
+
} = {},
|
|
170
|
+
keys: {
|
|
171
|
+
privateKeyPath = "keys/private.pem",
|
|
172
|
+
certPath = "keys/cert.pem",
|
|
173
|
+
keyLength = 2048,
|
|
174
|
+
certInfo = {},
|
|
175
|
+
overrideFunctions = {}
|
|
176
|
+
} = {}
|
|
177
|
+
} = options;
|
|
170
178
|
const {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
certInfo
|
|
175
|
-
} = keys;
|
|
179
|
+
generateKeyPair,
|
|
180
|
+
generateSignature
|
|
181
|
+
} = overrideFunctions;
|
|
176
182
|
let {
|
|
177
183
|
subject = {
|
|
178
184
|
commonName: productName,
|
|
179
185
|
organization: `org.${productName}`
|
|
180
186
|
},
|
|
181
187
|
expires = Date.now() + 365 * 864e5
|
|
182
|
-
} = certInfo
|
|
188
|
+
} = certInfo;
|
|
183
189
|
const buildAsarOption = {
|
|
184
190
|
version,
|
|
185
191
|
asarOutputPath,
|
|
@@ -202,14 +208,16 @@ function parseOptions(options) {
|
|
|
202
208
|
certPath,
|
|
203
209
|
entryPath,
|
|
204
210
|
subject,
|
|
205
|
-
expires
|
|
211
|
+
expires,
|
|
212
|
+
generateKeyPair
|
|
206
213
|
});
|
|
207
214
|
buildVersionOption = {
|
|
208
215
|
version,
|
|
209
216
|
asarOutputPath,
|
|
210
217
|
privateKey,
|
|
211
218
|
cert,
|
|
212
|
-
versionPath
|
|
219
|
+
versionPath,
|
|
220
|
+
generateSignature
|
|
213
221
|
};
|
|
214
222
|
}
|
|
215
223
|
return { isBuild, buildAsarOption, buildEntryOption, buildVersionOption };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "electron-incremental-update",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.2",
|
|
4
4
|
"description": "electron incremental update tools, powered by vite",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"build": "tsup",
|
|
@@ -64,4 +64,4 @@
|
|
|
64
64
|
"@cyyynthia/jscert": "^0.1.2",
|
|
65
65
|
"ci-info": "^3.8.0"
|
|
66
66
|
}
|
|
67
|
-
}
|
|
67
|
+
}
|