electron-incremental-update 0.2.0 → 0.2.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/dist/index.cjs +81 -36
- package/dist/index.d.ts +14 -8
- package/dist/index.mjs +78 -34
- package/package.json +9 -7
package/dist/index.cjs
CHANGED
|
@@ -33,9 +33,10 @@ __export(src_exports, {
|
|
|
33
33
|
createUpdater: () => createUpdater,
|
|
34
34
|
getAppAsarPath: () => getAppAsarPath,
|
|
35
35
|
getAppVersion: () => getAppVersion,
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
getEntryVersion: () => getEntryVersion,
|
|
37
|
+
getGithubReleaseCdnGroup: () => getGithubReleaseCdnGroup,
|
|
38
38
|
initApp: () => initApp,
|
|
39
|
+
parseGithubCdnURL: () => parseGithubCdnURL,
|
|
39
40
|
requireNative: () => requireNative
|
|
40
41
|
});
|
|
41
42
|
module.exports = __toCommonJS(src_exports);
|
|
@@ -50,7 +51,7 @@ var import_node_fs2 = require("fs");
|
|
|
50
51
|
var import_promises = require("fs/promises");
|
|
51
52
|
var import_electron2 = require("electron");
|
|
52
53
|
|
|
53
|
-
// src/updater/
|
|
54
|
+
// src/updater/defaultFunctions.ts
|
|
54
55
|
var import_node_buffer = require("buffer");
|
|
55
56
|
var import_node_https = __toESM(require("https"), 1);
|
|
56
57
|
function downloadJSONDefault(url, updater, headers) {
|
|
@@ -96,6 +97,28 @@ function downloadBufferDefault(url, updater, headers) {
|
|
|
96
97
|
});
|
|
97
98
|
});
|
|
98
99
|
}
|
|
100
|
+
function compareVersionDefault(oldVersion, newVersion) {
|
|
101
|
+
if (!oldVersion || !newVersion) {
|
|
102
|
+
throw new TypeError("invalid version");
|
|
103
|
+
}
|
|
104
|
+
const parseVersion = (version) => {
|
|
105
|
+
const [versionNumber, stage] = version.split("-");
|
|
106
|
+
const [major, minor, patch] = versionNumber.split(".").map(Number);
|
|
107
|
+
if (isNaN(major) || isNaN(minor) || isNaN(patch)) {
|
|
108
|
+
throw new TypeError("invalid version");
|
|
109
|
+
}
|
|
110
|
+
return { major, minor, patch, stage };
|
|
111
|
+
};
|
|
112
|
+
const oldV = parseVersion(oldVersion);
|
|
113
|
+
const newV = parseVersion(newVersion);
|
|
114
|
+
if (oldV.major < newV.major || oldV.major === newV.major && oldV.minor < newV.minor || oldV.major === newV.major && oldV.minor === newV.minor && oldV.patch < newV.patch) {
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
if (oldV.stage < newV.stage || !newV.stage && oldV.stage) {
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
99
122
|
|
|
100
123
|
// src/updater/utils.ts
|
|
101
124
|
var import_node_fs = require("fs");
|
|
@@ -104,41 +127,41 @@ var import_electron = require("electron");
|
|
|
104
127
|
function getAppAsarPath(name) {
|
|
105
128
|
return import_electron.app.isPackaged ? (0, import_node_path.join)((0, import_node_path.dirname)(import_electron.app.getAppPath()), `${name}.asar`) : "dev";
|
|
106
129
|
}
|
|
107
|
-
function
|
|
130
|
+
function getEntryVersion() {
|
|
108
131
|
return import_electron.app.getVersion();
|
|
109
132
|
}
|
|
110
133
|
function getAppVersion(name) {
|
|
111
|
-
return import_electron.app.isPackaged ? (0, import_node_fs.readFileSync)((0, import_node_path.join)(getAppAsarPath(name), "version"), "utf-8")
|
|
134
|
+
return import_electron.app.isPackaged ? (0, import_node_fs.readFileSync)((0, import_node_path.join)(getAppAsarPath(name), "version"), "utf-8") : getEntryVersion();
|
|
112
135
|
}
|
|
113
136
|
function requireNative(packageName) {
|
|
114
137
|
const path = import_electron.app.isPackaged ? (0, import_node_path.join)(import_electron.app.getAppPath(), "node_modules", packageName) : packageName;
|
|
115
138
|
return require(path);
|
|
116
139
|
}
|
|
117
|
-
function
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
throw new Error("URL must start with 'https://github.com/'");
|
|
140
|
+
function parseGithubCdnURL(repository, cdnPrefix, relativeFilePath) {
|
|
141
|
+
if (!repository.startsWith("https://github.com/")) {
|
|
142
|
+
throw new Error("url must start with https://github.com/");
|
|
121
143
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
144
|
+
repository = repository.trim().replace(/\/?$/, "/").trim();
|
|
145
|
+
relativeFilePath = relativeFilePath.trim().replace(/^\/|\/?$/g, "").trim();
|
|
146
|
+
cdnPrefix = cdnPrefix.trim().replace(/^\/?|\/?$/g, "").trim();
|
|
147
|
+
return repository.replace("github.com", cdnPrefix) + relativeFilePath;
|
|
148
|
+
}
|
|
149
|
+
function getGithubReleaseCdnGroup() {
|
|
126
150
|
return [
|
|
127
|
-
{
|
|
128
|
-
{
|
|
129
|
-
{
|
|
130
|
-
{
|
|
131
|
-
{
|
|
132
|
-
{
|
|
133
|
-
{
|
|
134
|
-
{
|
|
135
|
-
{
|
|
136
|
-
{
|
|
137
|
-
{
|
|
138
|
-
{
|
|
139
|
-
{
|
|
140
|
-
{
|
|
141
|
-
{ url: `https://download.nuaa.cf/${_url}`, maintainer: "LibraryCloud-nuaa" }
|
|
151
|
+
{ cdnPrefix: "gh.gh2233.ml", maintainer: "@X.I.U/XIU2" },
|
|
152
|
+
{ cdnPrefix: "ghproxy.com", maintainer: "gh-proxy" },
|
|
153
|
+
{ cdnPrefix: "gh.ddlc.top", maintainer: "@mtr-static-official" },
|
|
154
|
+
{ cdnPrefix: "ghdl.feizhuqwq.cf", maintainer: "feizhuqwq.com" },
|
|
155
|
+
{ cdnPrefix: "slink.ltd", maintainer: "\u77E5\u4E86\u5C0F\u7AD9" },
|
|
156
|
+
{ cdnPrefix: "git.xfj0.cn", maintainer: "anonymous1" },
|
|
157
|
+
{ cdnPrefix: "gh.con.sh", maintainer: "anonymous2" },
|
|
158
|
+
{ cdnPrefix: "ghps.cc", maintainer: "anonymous3" },
|
|
159
|
+
{ cdnPrefix: "cors.isteed.cc/github.com", maintainer: "Lufs's" },
|
|
160
|
+
{ cdnPrefix: "hub.gitmirror.com", maintainer: "GitMirror" },
|
|
161
|
+
{ cdnPrefix: "js.xxooo.ml", maintainer: "\u996D\u592A\u786C" },
|
|
162
|
+
{ cdnPrefix: "download.njuu.cf", maintainer: "LibraryCloud-njuu" },
|
|
163
|
+
{ cdnPrefix: "download.yzuu.cf", maintainer: "LibraryCloud-yzuu" },
|
|
164
|
+
{ cdnPrefix: "download.nuaa.cf", maintainer: "LibraryCloud-nuaa" }
|
|
142
165
|
];
|
|
143
166
|
}
|
|
144
167
|
|
|
@@ -149,10 +172,15 @@ function createUpdater({
|
|
|
149
172
|
productName,
|
|
150
173
|
releaseAsarURL: _release,
|
|
151
174
|
updateJsonURL: _update,
|
|
152
|
-
|
|
175
|
+
debug = false,
|
|
176
|
+
downloadConfig,
|
|
177
|
+
compareVersion
|
|
153
178
|
}) {
|
|
154
179
|
const updater = new import_node_events.EventEmitter();
|
|
155
180
|
const { downloadBuffer, downloadJSON, extraHeader, userAgent } = downloadConfig || {};
|
|
181
|
+
function log(...args) {
|
|
182
|
+
debug && console.log(...args);
|
|
183
|
+
}
|
|
156
184
|
async function download(url, format) {
|
|
157
185
|
const ua = userAgent || "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36";
|
|
158
186
|
const headers = {
|
|
@@ -160,6 +188,7 @@ function createUpdater({
|
|
|
160
188
|
UserAgent: ua,
|
|
161
189
|
...extraHeader
|
|
162
190
|
};
|
|
191
|
+
log("[updater] headers", headers);
|
|
163
192
|
const downloadFn = format === "json" ? downloadJSON ?? downloadJSONDefault : downloadBuffer ?? downloadBufferDefault;
|
|
164
193
|
return await downloadFn(url, updater, headers);
|
|
165
194
|
}
|
|
@@ -173,25 +202,32 @@ function createUpdater({
|
|
|
173
202
|
const input = (0, import_node_fs2.createReadStream)(gzipFilePath);
|
|
174
203
|
const outputFilePath = gzipFilePath.replace(".tmp.gz", ".asar");
|
|
175
204
|
const output = (0, import_node_fs2.createWriteStream)(outputFilePath);
|
|
205
|
+
log("[updater] outputFilePath", outputFilePath);
|
|
176
206
|
input.pipe(gunzip).pipe(output).on("finish", async () => {
|
|
177
207
|
await (0, import_promises.rm)(gzipFilePath);
|
|
208
|
+
log("[updater] finish");
|
|
178
209
|
resolve2(outputFilePath);
|
|
179
210
|
}).on("error", async (err) => {
|
|
180
211
|
await (0, import_promises.rm)(gzipFilePath);
|
|
212
|
+
log("[updater] error", err);
|
|
181
213
|
output.destroy(err);
|
|
182
214
|
reject(err);
|
|
183
215
|
});
|
|
184
216
|
});
|
|
185
217
|
}
|
|
186
218
|
function verify(buffer, signature) {
|
|
219
|
+
log("[updater] signature", signature);
|
|
187
220
|
return (0, import_node_crypto.createVerify)("RSA-SHA256").update(buffer).verify(SIGNATURE_PUB, signature, "base64");
|
|
188
221
|
}
|
|
189
222
|
function needUpdate(version) {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
223
|
+
if (!version || !import_electron2.app.isPackaged) {
|
|
224
|
+
return false;
|
|
225
|
+
}
|
|
226
|
+
const currentVersion = getEntryVersion();
|
|
227
|
+
log("[updater] currentVersion", currentVersion);
|
|
228
|
+
log("[updater] newVersion", version);
|
|
229
|
+
const _compare = compareVersion ?? compareVersionDefault;
|
|
230
|
+
return _compare(currentVersion, version);
|
|
195
231
|
}
|
|
196
232
|
async function checkUpdate(option) {
|
|
197
233
|
let {
|
|
@@ -199,15 +235,19 @@ function createUpdater({
|
|
|
199
235
|
releaseAsarURL = _release
|
|
200
236
|
} = option || {};
|
|
201
237
|
if (!updateJsonURL || !releaseAsarURL) {
|
|
238
|
+
log("[updater] no updateJsonURL or releaseAsarURL, use repository");
|
|
202
239
|
if (!repository) {
|
|
203
240
|
throw new Error("updateJsonURL or releaseAsarURL are not set");
|
|
204
241
|
}
|
|
205
242
|
updateJsonURL = `${repository.replace("github.com", "raw.githubusercontent.com")}/version.json`;
|
|
206
243
|
releaseAsarURL = `${repository}/releases/download/latest/${productName}.asar.gz`;
|
|
207
244
|
}
|
|
245
|
+
log("[updater] updateJsonURL", updateJsonURL);
|
|
246
|
+
log("[updater] releaseAsarURL", releaseAsarURL);
|
|
208
247
|
const gzipPath = `../${productName}.asar.gz`;
|
|
209
248
|
const tmpFile = gzipPath.replace(".asar.gz", ".tmp.gz");
|
|
210
249
|
if ((0, import_node_fs2.existsSync)(tmpFile)) {
|
|
250
|
+
log("[updater] remove tmp file", tmpFile);
|
|
211
251
|
await (0, import_promises.rm)(tmpFile);
|
|
212
252
|
}
|
|
213
253
|
const json = await download(updateJsonURL, "json");
|
|
@@ -219,15 +259,19 @@ function createUpdater({
|
|
|
219
259
|
version,
|
|
220
260
|
size
|
|
221
261
|
} = json;
|
|
262
|
+
log("[updater] UpdateJSON", json);
|
|
222
263
|
if (!needUpdate(version)) {
|
|
223
264
|
return "unavailable";
|
|
224
265
|
}
|
|
225
266
|
updater.emit("downloadStart", size);
|
|
226
267
|
const buffer = await download(releaseAsarURL, "buffer");
|
|
268
|
+
log("[updater] start verify");
|
|
227
269
|
if (!verify(buffer, signature)) {
|
|
228
270
|
throw new Error("file broken, invalid signature!");
|
|
229
271
|
}
|
|
272
|
+
log("[updater] write file", gzipPath);
|
|
230
273
|
await (0, import_promises.writeFile)(gzipPath, buffer);
|
|
274
|
+
log("[updater] extract file", gzipPath);
|
|
231
275
|
await extractFile(gzipPath);
|
|
232
276
|
return "success";
|
|
233
277
|
}
|
|
@@ -266,8 +310,9 @@ function initApp(productName, updater, option) {
|
|
|
266
310
|
createUpdater,
|
|
267
311
|
getAppAsarPath,
|
|
268
312
|
getAppVersion,
|
|
269
|
-
|
|
270
|
-
|
|
313
|
+
getEntryVersion,
|
|
314
|
+
getGithubReleaseCdnGroup,
|
|
271
315
|
initApp,
|
|
316
|
+
parseGithubCdnURL,
|
|
272
317
|
requireNative
|
|
273
318
|
});
|
package/dist/index.d.ts
CHANGED
|
@@ -72,6 +72,8 @@ interface UpdaterOption extends BaseOption {
|
|
|
72
72
|
* `repository` will be used to determine the url
|
|
73
73
|
*/
|
|
74
74
|
repository?: string;
|
|
75
|
+
debug?: boolean;
|
|
76
|
+
compareVersion?: (oldVersion: string, newVersion: string) => boolean;
|
|
75
77
|
downloadConfig?: {
|
|
76
78
|
/**
|
|
77
79
|
* download user agent
|
|
@@ -107,11 +109,11 @@ interface UpdaterOption extends BaseOption {
|
|
|
107
109
|
*/
|
|
108
110
|
declare function getAppAsarPath(name: string): string;
|
|
109
111
|
/**
|
|
110
|
-
* get the version of
|
|
112
|
+
* get the version of entry (app.asar)
|
|
111
113
|
*/
|
|
112
|
-
declare function
|
|
114
|
+
declare function getEntryVersion(): string;
|
|
113
115
|
/**
|
|
114
|
-
* get the version of application
|
|
116
|
+
* get the version of application (name.asar)
|
|
115
117
|
* @param name - The name of the application
|
|
116
118
|
*/
|
|
117
119
|
declare function getAppVersion(name: string): string;
|
|
@@ -121,14 +123,18 @@ declare function getAppVersion(name: string): string;
|
|
|
121
123
|
*/
|
|
122
124
|
declare function requireNative<T = any>(packageName: string): T;
|
|
123
125
|
/**
|
|
124
|
-
* get
|
|
126
|
+
* get github version.json CDN URL for accelerating the speed of downloading version info
|
|
125
127
|
*/
|
|
126
|
-
declare function
|
|
127
|
-
|
|
128
|
+
declare function parseGithubCdnURL(repository: string, cdnPrefix: string, relativeFilePath: string): string;
|
|
129
|
+
/**
|
|
130
|
+
* get group of github release CDN prefix for accelerating the speed of downloading release
|
|
131
|
+
*/
|
|
132
|
+
declare function getGithubReleaseCdnGroup(): {
|
|
133
|
+
cdnPrefix: string;
|
|
128
134
|
maintainer: string;
|
|
129
135
|
}[];
|
|
130
136
|
|
|
131
|
-
declare function createUpdater({ SIGNATURE_PUB, repository, productName, releaseAsarURL: _release, updateJsonURL: _update, downloadConfig, }: UpdaterOption): Updater;
|
|
137
|
+
declare function createUpdater({ SIGNATURE_PUB, repository, productName, releaseAsarURL: _release, updateJsonURL: _update, debug, downloadConfig, compareVersion, }: UpdaterOption): Updater;
|
|
132
138
|
|
|
133
139
|
interface AppOption {
|
|
134
140
|
/**
|
|
@@ -187,4 +193,4 @@ declare function initApp(productName: string, updater: Updater | Omit<UpdaterOpt
|
|
|
187
193
|
productName?: string;
|
|
188
194
|
}, option?: AppOption): any;
|
|
189
195
|
|
|
190
|
-
export { BaseOption, CheckResultType, UpdateJSON, Updater, UpdaterOption, createUpdater, getAppAsarPath, getAppVersion,
|
|
196
|
+
export { BaseOption, CheckResultType, UpdateJSON, Updater, UpdaterOption, createUpdater, getAppAsarPath, getAppVersion, getEntryVersion, getGithubReleaseCdnGroup, initApp, parseGithubCdnURL, requireNative };
|
package/dist/index.mjs
CHANGED
|
@@ -14,7 +14,7 @@ import { createReadStream, createWriteStream, existsSync } from "node:fs";
|
|
|
14
14
|
import { rm, writeFile } from "node:fs/promises";
|
|
15
15
|
import { app as app2 } from "electron";
|
|
16
16
|
|
|
17
|
-
// src/updater/
|
|
17
|
+
// src/updater/defaultFunctions.ts
|
|
18
18
|
import { Buffer } from "node:buffer";
|
|
19
19
|
import https from "node:https";
|
|
20
20
|
function downloadJSONDefault(url, updater, headers) {
|
|
@@ -60,6 +60,28 @@ function downloadBufferDefault(url, updater, headers) {
|
|
|
60
60
|
});
|
|
61
61
|
});
|
|
62
62
|
}
|
|
63
|
+
function compareVersionDefault(oldVersion, newVersion) {
|
|
64
|
+
if (!oldVersion || !newVersion) {
|
|
65
|
+
throw new TypeError("invalid version");
|
|
66
|
+
}
|
|
67
|
+
const parseVersion = (version) => {
|
|
68
|
+
const [versionNumber, stage] = version.split("-");
|
|
69
|
+
const [major, minor, patch] = versionNumber.split(".").map(Number);
|
|
70
|
+
if (isNaN(major) || isNaN(minor) || isNaN(patch)) {
|
|
71
|
+
throw new TypeError("invalid version");
|
|
72
|
+
}
|
|
73
|
+
return { major, minor, patch, stage };
|
|
74
|
+
};
|
|
75
|
+
const oldV = parseVersion(oldVersion);
|
|
76
|
+
const newV = parseVersion(newVersion);
|
|
77
|
+
if (oldV.major < newV.major || oldV.major === newV.major && oldV.minor < newV.minor || oldV.major === newV.major && oldV.minor === newV.minor && oldV.patch < newV.patch) {
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
if (oldV.stage < newV.stage || !newV.stage && oldV.stage) {
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
63
85
|
|
|
64
86
|
// src/updater/utils.ts
|
|
65
87
|
import { readFileSync } from "node:fs";
|
|
@@ -68,41 +90,41 @@ import { app } from "electron";
|
|
|
68
90
|
function getAppAsarPath(name) {
|
|
69
91
|
return app.isPackaged ? join(dirname(app.getAppPath()), `${name}.asar`) : "dev";
|
|
70
92
|
}
|
|
71
|
-
function
|
|
93
|
+
function getEntryVersion() {
|
|
72
94
|
return app.getVersion();
|
|
73
95
|
}
|
|
74
96
|
function getAppVersion(name) {
|
|
75
|
-
return app.isPackaged ? readFileSync(join(getAppAsarPath(name), "version"), "utf-8")
|
|
97
|
+
return app.isPackaged ? readFileSync(join(getAppAsarPath(name), "version"), "utf-8") : getEntryVersion();
|
|
76
98
|
}
|
|
77
99
|
function requireNative(packageName) {
|
|
78
100
|
const path = app.isPackaged ? join(app.getAppPath(), "node_modules", packageName) : packageName;
|
|
79
101
|
return __require(path);
|
|
80
102
|
}
|
|
81
|
-
function
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
throw new Error("URL must start with 'https://github.com/'");
|
|
103
|
+
function parseGithubCdnURL(repository, cdnPrefix, relativeFilePath) {
|
|
104
|
+
if (!repository.startsWith("https://github.com/")) {
|
|
105
|
+
throw new Error("url must start with https://github.com/");
|
|
85
106
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
107
|
+
repository = repository.trim().replace(/\/?$/, "/").trim();
|
|
108
|
+
relativeFilePath = relativeFilePath.trim().replace(/^\/|\/?$/g, "").trim();
|
|
109
|
+
cdnPrefix = cdnPrefix.trim().replace(/^\/?|\/?$/g, "").trim();
|
|
110
|
+
return repository.replace("github.com", cdnPrefix) + relativeFilePath;
|
|
111
|
+
}
|
|
112
|
+
function getGithubReleaseCdnGroup() {
|
|
90
113
|
return [
|
|
91
|
-
{
|
|
92
|
-
{
|
|
93
|
-
{
|
|
94
|
-
{
|
|
95
|
-
{
|
|
96
|
-
{
|
|
97
|
-
{
|
|
98
|
-
{
|
|
99
|
-
{
|
|
100
|
-
{
|
|
101
|
-
{
|
|
102
|
-
{
|
|
103
|
-
{
|
|
104
|
-
{
|
|
105
|
-
{ url: `https://download.nuaa.cf/${_url}`, maintainer: "LibraryCloud-nuaa" }
|
|
114
|
+
{ cdnPrefix: "gh.gh2233.ml", maintainer: "@X.I.U/XIU2" },
|
|
115
|
+
{ cdnPrefix: "ghproxy.com", maintainer: "gh-proxy" },
|
|
116
|
+
{ cdnPrefix: "gh.ddlc.top", maintainer: "@mtr-static-official" },
|
|
117
|
+
{ cdnPrefix: "ghdl.feizhuqwq.cf", maintainer: "feizhuqwq.com" },
|
|
118
|
+
{ cdnPrefix: "slink.ltd", maintainer: "\u77E5\u4E86\u5C0F\u7AD9" },
|
|
119
|
+
{ cdnPrefix: "git.xfj0.cn", maintainer: "anonymous1" },
|
|
120
|
+
{ cdnPrefix: "gh.con.sh", maintainer: "anonymous2" },
|
|
121
|
+
{ cdnPrefix: "ghps.cc", maintainer: "anonymous3" },
|
|
122
|
+
{ cdnPrefix: "cors.isteed.cc/github.com", maintainer: "Lufs's" },
|
|
123
|
+
{ cdnPrefix: "hub.gitmirror.com", maintainer: "GitMirror" },
|
|
124
|
+
{ cdnPrefix: "js.xxooo.ml", maintainer: "\u996D\u592A\u786C" },
|
|
125
|
+
{ cdnPrefix: "download.njuu.cf", maintainer: "LibraryCloud-njuu" },
|
|
126
|
+
{ cdnPrefix: "download.yzuu.cf", maintainer: "LibraryCloud-yzuu" },
|
|
127
|
+
{ cdnPrefix: "download.nuaa.cf", maintainer: "LibraryCloud-nuaa" }
|
|
106
128
|
];
|
|
107
129
|
}
|
|
108
130
|
|
|
@@ -113,10 +135,15 @@ function createUpdater({
|
|
|
113
135
|
productName,
|
|
114
136
|
releaseAsarURL: _release,
|
|
115
137
|
updateJsonURL: _update,
|
|
116
|
-
|
|
138
|
+
debug = false,
|
|
139
|
+
downloadConfig,
|
|
140
|
+
compareVersion
|
|
117
141
|
}) {
|
|
118
142
|
const updater = new EventEmitter();
|
|
119
143
|
const { downloadBuffer, downloadJSON, extraHeader, userAgent } = downloadConfig || {};
|
|
144
|
+
function log(...args) {
|
|
145
|
+
debug && console.log(...args);
|
|
146
|
+
}
|
|
120
147
|
async function download(url, format) {
|
|
121
148
|
const ua = userAgent || "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36";
|
|
122
149
|
const headers = {
|
|
@@ -124,6 +151,7 @@ function createUpdater({
|
|
|
124
151
|
UserAgent: ua,
|
|
125
152
|
...extraHeader
|
|
126
153
|
};
|
|
154
|
+
log("[updater] headers", headers);
|
|
127
155
|
const downloadFn = format === "json" ? downloadJSON ?? downloadJSONDefault : downloadBuffer ?? downloadBufferDefault;
|
|
128
156
|
return await downloadFn(url, updater, headers);
|
|
129
157
|
}
|
|
@@ -137,25 +165,32 @@ function createUpdater({
|
|
|
137
165
|
const input = createReadStream(gzipFilePath);
|
|
138
166
|
const outputFilePath = gzipFilePath.replace(".tmp.gz", ".asar");
|
|
139
167
|
const output = createWriteStream(outputFilePath);
|
|
168
|
+
log("[updater] outputFilePath", outputFilePath);
|
|
140
169
|
input.pipe(gunzip).pipe(output).on("finish", async () => {
|
|
141
170
|
await rm(gzipFilePath);
|
|
171
|
+
log("[updater] finish");
|
|
142
172
|
resolve2(outputFilePath);
|
|
143
173
|
}).on("error", async (err) => {
|
|
144
174
|
await rm(gzipFilePath);
|
|
175
|
+
log("[updater] error", err);
|
|
145
176
|
output.destroy(err);
|
|
146
177
|
reject(err);
|
|
147
178
|
});
|
|
148
179
|
});
|
|
149
180
|
}
|
|
150
181
|
function verify(buffer, signature) {
|
|
182
|
+
log("[updater] signature", signature);
|
|
151
183
|
return createVerify("RSA-SHA256").update(buffer).verify(SIGNATURE_PUB, signature, "base64");
|
|
152
184
|
}
|
|
153
185
|
function needUpdate(version) {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
186
|
+
if (!version || !app2.isPackaged) {
|
|
187
|
+
return false;
|
|
188
|
+
}
|
|
189
|
+
const currentVersion = getEntryVersion();
|
|
190
|
+
log("[updater] currentVersion", currentVersion);
|
|
191
|
+
log("[updater] newVersion", version);
|
|
192
|
+
const _compare = compareVersion ?? compareVersionDefault;
|
|
193
|
+
return _compare(currentVersion, version);
|
|
159
194
|
}
|
|
160
195
|
async function checkUpdate(option) {
|
|
161
196
|
let {
|
|
@@ -163,15 +198,19 @@ function createUpdater({
|
|
|
163
198
|
releaseAsarURL = _release
|
|
164
199
|
} = option || {};
|
|
165
200
|
if (!updateJsonURL || !releaseAsarURL) {
|
|
201
|
+
log("[updater] no updateJsonURL or releaseAsarURL, use repository");
|
|
166
202
|
if (!repository) {
|
|
167
203
|
throw new Error("updateJsonURL or releaseAsarURL are not set");
|
|
168
204
|
}
|
|
169
205
|
updateJsonURL = `${repository.replace("github.com", "raw.githubusercontent.com")}/version.json`;
|
|
170
206
|
releaseAsarURL = `${repository}/releases/download/latest/${productName}.asar.gz`;
|
|
171
207
|
}
|
|
208
|
+
log("[updater] updateJsonURL", updateJsonURL);
|
|
209
|
+
log("[updater] releaseAsarURL", releaseAsarURL);
|
|
172
210
|
const gzipPath = `../${productName}.asar.gz`;
|
|
173
211
|
const tmpFile = gzipPath.replace(".asar.gz", ".tmp.gz");
|
|
174
212
|
if (existsSync(tmpFile)) {
|
|
213
|
+
log("[updater] remove tmp file", tmpFile);
|
|
175
214
|
await rm(tmpFile);
|
|
176
215
|
}
|
|
177
216
|
const json = await download(updateJsonURL, "json");
|
|
@@ -183,15 +222,19 @@ function createUpdater({
|
|
|
183
222
|
version,
|
|
184
223
|
size
|
|
185
224
|
} = json;
|
|
225
|
+
log("[updater] UpdateJSON", json);
|
|
186
226
|
if (!needUpdate(version)) {
|
|
187
227
|
return "unavailable";
|
|
188
228
|
}
|
|
189
229
|
updater.emit("downloadStart", size);
|
|
190
230
|
const buffer = await download(releaseAsarURL, "buffer");
|
|
231
|
+
log("[updater] start verify");
|
|
191
232
|
if (!verify(buffer, signature)) {
|
|
192
233
|
throw new Error("file broken, invalid signature!");
|
|
193
234
|
}
|
|
235
|
+
log("[updater] write file", gzipPath);
|
|
194
236
|
await writeFile(gzipPath, buffer);
|
|
237
|
+
log("[updater] extract file", gzipPath);
|
|
195
238
|
await extractFile(gzipPath);
|
|
196
239
|
return "success";
|
|
197
240
|
}
|
|
@@ -229,8 +272,9 @@ export {
|
|
|
229
272
|
createUpdater,
|
|
230
273
|
getAppAsarPath,
|
|
231
274
|
getAppVersion,
|
|
232
|
-
|
|
233
|
-
|
|
275
|
+
getEntryVersion,
|
|
276
|
+
getGithubReleaseCdnGroup,
|
|
234
277
|
initApp,
|
|
278
|
+
parseGithubCdnURL,
|
|
235
279
|
requireNative
|
|
236
280
|
};
|
package/package.json
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "electron-incremental-update",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "electron incremental update tools, powered by vite",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"build": "tsup",
|
|
7
|
-
"release": "
|
|
7
|
+
"release": "pnpm test && pnpm run build && bumpp && npm publish",
|
|
8
|
+
"test": "vitest --run"
|
|
9
|
+
},
|
|
10
|
+
"publishConfig": {
|
|
11
|
+
"access": "public",
|
|
12
|
+
"registry": "https://registry.npmjs.org/"
|
|
8
13
|
},
|
|
9
14
|
"repository": "https://github.com/subframe7536/electron-incremental-update",
|
|
10
15
|
"type": "module",
|
|
@@ -52,13 +57,10 @@
|
|
|
52
57
|
"fs-jetpack": "^5.1.0",
|
|
53
58
|
"tsup": "^6.7.0",
|
|
54
59
|
"typescript": "^5.1.3",
|
|
55
|
-
"vite": "^4.3.9"
|
|
60
|
+
"vite": "^4.3.9",
|
|
61
|
+
"vitest": "^0.32.2"
|
|
56
62
|
},
|
|
57
63
|
"dependencies": {
|
|
58
64
|
"ci-info": "^3.8.0"
|
|
59
|
-
},
|
|
60
|
-
"peerDependencies": {
|
|
61
|
-
"@electron/asar": "*",
|
|
62
|
-
"asar": "*"
|
|
63
65
|
}
|
|
64
66
|
}
|