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/README.md
CHANGED
|
@@ -181,7 +181,7 @@ initApp({
|
|
|
181
181
|
in `electron/main/index.ts`
|
|
182
182
|
|
|
183
183
|
```ts
|
|
184
|
-
import {
|
|
184
|
+
import { UpdaterError, startupWithUpdater } from 'electron-incremental-update'
|
|
185
185
|
import { getPathFromAppNameAsar, getVersions } from 'electron-incremental-update/utils'
|
|
186
186
|
import { app } from 'electron'
|
|
187
187
|
|
|
@@ -199,7 +199,7 @@ export default startupWithUpdater((updater) => {
|
|
|
199
199
|
}
|
|
200
200
|
updater.logger = console
|
|
201
201
|
updater.receiveBeta = true
|
|
202
|
-
|
|
202
|
+
|
|
203
203
|
updater.checkUpdate().then(async (result) => {
|
|
204
204
|
if (result === undefined) {
|
|
205
205
|
console.log('Update Unavailable')
|
|
@@ -276,7 +276,7 @@ import Database from 'better-sqlite3'
|
|
|
276
276
|
|
|
277
277
|
const db = new Database(':memory:', { nativeBinding: './better_sqlite3.node' })
|
|
278
278
|
|
|
279
|
-
export function test() {
|
|
279
|
+
export function test(): void {
|
|
280
280
|
db.exec(
|
|
281
281
|
'DROP TABLE IF EXISTS employees; '
|
|
282
282
|
+ 'CREATE TABLE IF NOT EXISTS employees (name TEXT, salary INTEGER)',
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { writeFileSync } from 'node:fs';
|
|
2
|
+
import { brotliDecompress } from 'node:zlib';
|
|
3
|
+
import { createHash, createCipheriv, createSign, createPrivateKey, createDecipheriv, createVerify } from 'node:crypto';
|
|
4
|
+
|
|
5
|
+
// src/utils/unzip.ts
|
|
6
|
+
async function defaultUnzipFile(buffer, targetFilePath) {
|
|
7
|
+
return new Promise((resolve, reject) => {
|
|
8
|
+
brotliDecompress(buffer, (err, buffer2) => {
|
|
9
|
+
if (err) {
|
|
10
|
+
reject(err);
|
|
11
|
+
}
|
|
12
|
+
writeFileSync(targetFilePath, buffer2);
|
|
13
|
+
resolve();
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
function hashBuffer(data, length) {
|
|
18
|
+
const hash = createHash("SHA256").update(data).digest("binary");
|
|
19
|
+
return Buffer.from(hash).subarray(0, length);
|
|
20
|
+
}
|
|
21
|
+
function aesEncrypt(plainText, key, iv) {
|
|
22
|
+
const cipher = createCipheriv("aes-256-cbc", key, iv);
|
|
23
|
+
return cipher.update(plainText, "utf8", "base64url") + cipher.final("base64url");
|
|
24
|
+
}
|
|
25
|
+
function defaultSignature(buffer, privateKey, cert, version) {
|
|
26
|
+
const sig = createSign("RSA-SHA256").update(buffer).sign(createPrivateKey(privateKey), "base64");
|
|
27
|
+
return aesEncrypt(`${sig}%${version}`, hashBuffer(cert, 32), hashBuffer(buffer, 16));
|
|
28
|
+
}
|
|
29
|
+
function aesDecrypt(encryptedText, key, iv) {
|
|
30
|
+
const decipher = createDecipheriv("aes-256-cbc", key, iv);
|
|
31
|
+
return decipher.update(encryptedText, "base64url", "utf8") + decipher.final("utf8");
|
|
32
|
+
}
|
|
33
|
+
function defaultVerify(buffer, signature, cert) {
|
|
34
|
+
try {
|
|
35
|
+
const [sig, version] = aesDecrypt(signature, hashBuffer(cert, 32), hashBuffer(buffer, 16)).split("%");
|
|
36
|
+
const result = createVerify("RSA-SHA256").update(buffer).verify(cert, sig, "base64");
|
|
37
|
+
return result ? version : void 0;
|
|
38
|
+
} catch {
|
|
39
|
+
return void 0;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export { aesDecrypt, aesEncrypt, defaultSignature, defaultUnzipFile, defaultVerify, hashBuffer };
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
+
}) : x)(function(x) {
|
|
4
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
5
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
// src/utils/version.ts
|
|
9
|
+
function handleUnexpectedErrors(callback) {
|
|
10
|
+
process.on("uncaughtException", callback);
|
|
11
|
+
process.on("unhandledRejection", callback);
|
|
12
|
+
}
|
|
13
|
+
function parseVersion(version) {
|
|
14
|
+
const match = /^(\d+)\.(\d+)\.(\d+)(?:-([a-z0-9.-]+))?/i.exec(version);
|
|
15
|
+
if (!match) {
|
|
16
|
+
throw new TypeError(`invalid version: ${version}`);
|
|
17
|
+
}
|
|
18
|
+
const [major, minor, patch] = match.slice(1, 4).map(Number);
|
|
19
|
+
const ret = {
|
|
20
|
+
major,
|
|
21
|
+
minor,
|
|
22
|
+
patch,
|
|
23
|
+
stage: "",
|
|
24
|
+
stageVersion: -1
|
|
25
|
+
};
|
|
26
|
+
if (match[4]) {
|
|
27
|
+
let [stage, _v] = match[4].split(".");
|
|
28
|
+
ret.stage = stage;
|
|
29
|
+
ret.stageVersion = Number(_v) || -1;
|
|
30
|
+
}
|
|
31
|
+
if (Number.isNaN(major) || Number.isNaN(minor) || Number.isNaN(patch) || Number.isNaN(ret.stageVersion)) {
|
|
32
|
+
throw new TypeError(`invalid version: ${version}`);
|
|
33
|
+
}
|
|
34
|
+
return ret;
|
|
35
|
+
}
|
|
36
|
+
function defaultIsLowerVersion(oldVer, newVer) {
|
|
37
|
+
const oldV = parseVersion(oldVer);
|
|
38
|
+
const newV = parseVersion(newVer);
|
|
39
|
+
function compareStrings(str1, str2) {
|
|
40
|
+
if (str1 === "") {
|
|
41
|
+
return str2 !== "";
|
|
42
|
+
} else if (str2 === "") {
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
return str1 < str2;
|
|
46
|
+
}
|
|
47
|
+
for (let key of Object.keys(oldV)) {
|
|
48
|
+
if (key === "stage" && compareStrings(oldV[key], newV[key])) {
|
|
49
|
+
return true;
|
|
50
|
+
} else if (oldV[key] !== newV[key]) {
|
|
51
|
+
return oldV[key] < newV[key];
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
function isUpdateJSON(json) {
|
|
57
|
+
const is = (j) => !!(j && j.minimumVersion && j.signature && j.size && j.version);
|
|
58
|
+
return is(json) && is(json?.beta);
|
|
59
|
+
}
|
|
60
|
+
function defaultVersionJsonGenerator(existingJson, buffer, signature, version, minimumVersion) {
|
|
61
|
+
existingJson.beta = {
|
|
62
|
+
version,
|
|
63
|
+
minimumVersion,
|
|
64
|
+
signature,
|
|
65
|
+
size: buffer.length
|
|
66
|
+
};
|
|
67
|
+
if (!parseVersion(version).stage) {
|
|
68
|
+
existingJson.version = version;
|
|
69
|
+
existingJson.minimumVersion = minimumVersion;
|
|
70
|
+
existingJson.signature = signature;
|
|
71
|
+
existingJson.size = buffer.length;
|
|
72
|
+
}
|
|
73
|
+
return existingJson;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export { __require, defaultIsLowerVersion, defaultVersionJsonGenerator, handleUnexpectedErrors, isUpdateJSON, parseVersion };
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { __require } from './chunk-BVFQWBLK.js';
|
|
2
|
+
import { readFileSync, existsSync, mkdirSync } from 'node:fs';
|
|
3
|
+
import { join, dirname } from 'node:path';
|
|
4
|
+
import { app } from 'electron';
|
|
5
|
+
|
|
6
|
+
var isDev = __EIU_IS_DEV__;
|
|
7
|
+
var isWin = process.platform === "win32";
|
|
8
|
+
var isMac = process.platform === "darwin";
|
|
9
|
+
var isLinux = process.platform === "linux";
|
|
10
|
+
function getPathFromAppNameAsar(...path) {
|
|
11
|
+
return isDev ? "DEV.asar" : join(dirname(app.getAppPath()), `${app.name}.asar`, ...path);
|
|
12
|
+
}
|
|
13
|
+
function getAppVersion() {
|
|
14
|
+
return isDev ? getEntryVersion() : readFileSync(getPathFromAppNameAsar("version"), "utf-8");
|
|
15
|
+
}
|
|
16
|
+
function getEntryVersion() {
|
|
17
|
+
return app.getVersion();
|
|
18
|
+
}
|
|
19
|
+
function requireNative(moduleName) {
|
|
20
|
+
return __require(join(app.getAppPath(), __EIU_ENTRY_DIST_PATH__, moduleName));
|
|
21
|
+
}
|
|
22
|
+
function restartApp() {
|
|
23
|
+
app.relaunch();
|
|
24
|
+
app.quit();
|
|
25
|
+
}
|
|
26
|
+
function setAppUserModelId(id) {
|
|
27
|
+
if (isWin) {
|
|
28
|
+
app.setAppUserModelId(id ?? `org.${app.name}`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function disableHWAccForWin7() {
|
|
32
|
+
if (__require("node:os").release().startsWith("6.1")) {
|
|
33
|
+
app.disableHardwareAcceleration();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function singleInstance(window) {
|
|
37
|
+
const result = app.requestSingleInstanceLock();
|
|
38
|
+
if (result) {
|
|
39
|
+
app.on("second-instance", () => {
|
|
40
|
+
if (window) {
|
|
41
|
+
window.show();
|
|
42
|
+
if (window.isMinimized()) {
|
|
43
|
+
window.restore();
|
|
44
|
+
}
|
|
45
|
+
window.focus();
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
} else {
|
|
49
|
+
app.quit();
|
|
50
|
+
}
|
|
51
|
+
return result;
|
|
52
|
+
}
|
|
53
|
+
function setPortableAppDataPath(dirName = "data") {
|
|
54
|
+
const portablePath = join(dirname(app.getPath("exe")), dirName);
|
|
55
|
+
if (!existsSync(portablePath)) {
|
|
56
|
+
mkdirSync(portablePath);
|
|
57
|
+
}
|
|
58
|
+
app.setPath("appData", portablePath);
|
|
59
|
+
}
|
|
60
|
+
function loadPage(win, htmlFilePath = "index.html") {
|
|
61
|
+
if (isDev) {
|
|
62
|
+
win.loadURL(process.env.VITE_DEV_SERVER_URL + htmlFilePath);
|
|
63
|
+
} else {
|
|
64
|
+
win.loadFile(getPathFromAppNameAsar("renderer", htmlFilePath));
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
function getPathFromPreload(...paths) {
|
|
68
|
+
return isDev ? join(app.getAppPath(), __EIU_ELECTRON_DIST_PATH__, "preload", ...paths) : getPathFromAppNameAsar("preload", ...paths);
|
|
69
|
+
}
|
|
70
|
+
function getPathFromPublic(...paths) {
|
|
71
|
+
return isDev ? join(app.getAppPath(), "public", ...paths) : getPathFromAppNameAsar("renderer", ...paths);
|
|
72
|
+
}
|
|
73
|
+
function getPathFromEntryAsar(...paths) {
|
|
74
|
+
return join(app.getAppPath(), __EIU_ENTRY_DIST_PATH__, ...paths);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export { disableHWAccForWin7, getAppVersion, getEntryVersion, getPathFromAppNameAsar, getPathFromEntryAsar, getPathFromPreload, getPathFromPublic, isDev, isLinux, isMac, isWin, loadPage, requireNative, restartApp, setAppUserModelId, setPortableAppDataPath, singleInstance };
|
package/dist/index.cjs
CHANGED
|
@@ -1,86 +1,38 @@
|
|
|
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);
|
|
1
|
+
'use strict';
|
|
19
2
|
|
|
20
|
-
|
|
21
|
-
var
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
Updater: () => Updater,
|
|
25
|
-
UpdaterError: () => UpdaterError,
|
|
26
|
-
initApp: () => initApp,
|
|
27
|
-
startupWithUpdater: () => startupWithUpdater
|
|
28
|
-
});
|
|
29
|
-
module.exports = __toCommonJS(entry_exports);
|
|
30
|
-
var import_node_path2 = require("path");
|
|
31
|
-
var import_node_fs5 = require("fs");
|
|
32
|
-
var import_electron4 = require("electron");
|
|
3
|
+
var path = require('path');
|
|
4
|
+
var fs = require('fs');
|
|
5
|
+
var electron = require('electron');
|
|
6
|
+
var events = require('events');
|
|
33
7
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
8
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
9
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
10
|
+
}) : x)(function(x) {
|
|
11
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
12
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
13
|
+
});
|
|
37
14
|
|
|
38
15
|
// src/utils/version.ts
|
|
39
16
|
function isUpdateJSON(json) {
|
|
40
17
|
const is = (j) => !!(j && j.minimumVersion && j.signature && j.size && j.version);
|
|
41
18
|
return is(json) && is(json?.beta);
|
|
42
19
|
}
|
|
43
|
-
|
|
44
|
-
// src/utils/electron.ts
|
|
45
|
-
var import_node_fs = require("fs");
|
|
46
|
-
var import_node_path = require("path");
|
|
47
|
-
var import_electron = require("electron");
|
|
48
20
|
var isDev = __EIU_IS_DEV__;
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
function getPathFromAppNameAsar(...path) {
|
|
53
|
-
return isDev ? "DEV.asar" :
|
|
21
|
+
process.platform === "win32";
|
|
22
|
+
process.platform === "darwin";
|
|
23
|
+
process.platform === "linux";
|
|
24
|
+
function getPathFromAppNameAsar(...path$1) {
|
|
25
|
+
return isDev ? "DEV.asar" : path.join(path.dirname(electron.app.getAppPath()), `${electron.app.name}.asar`, ...path$1);
|
|
54
26
|
}
|
|
55
27
|
function getAppVersion() {
|
|
56
|
-
return isDev ? getEntryVersion() :
|
|
28
|
+
return isDev ? getEntryVersion() : fs.readFileSync(getPathFromAppNameAsar("version"), "utf-8");
|
|
57
29
|
}
|
|
58
30
|
function getEntryVersion() {
|
|
59
|
-
return
|
|
31
|
+
return electron.app.getVersion();
|
|
60
32
|
}
|
|
61
33
|
function restartApp() {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// src/utils/unzip.ts
|
|
67
|
-
var import_node_fs2 = require("fs");
|
|
68
|
-
var import_node_zlib = require("zlib");
|
|
69
|
-
async function unzipFile(gzipPath, targetFilePath = gzipPath.slice(0, -3)) {
|
|
70
|
-
if (!(0, import_node_fs2.existsSync)(gzipPath)) {
|
|
71
|
-
throw new Error(`path to zipped file not exist: ${gzipPath}`);
|
|
72
|
-
}
|
|
73
|
-
const compressedBuffer = (0, import_node_fs2.readFileSync)(gzipPath);
|
|
74
|
-
return new Promise((resolve, reject) => {
|
|
75
|
-
(0, import_node_zlib.brotliDecompress)(compressedBuffer, (err, buffer) => {
|
|
76
|
-
(0, import_node_fs2.rmSync)(gzipPath);
|
|
77
|
-
if (err) {
|
|
78
|
-
reject(err);
|
|
79
|
-
}
|
|
80
|
-
(0, import_node_fs2.writeFileSync)(targetFilePath, buffer);
|
|
81
|
-
resolve(null);
|
|
82
|
-
});
|
|
83
|
-
});
|
|
34
|
+
electron.app.relaunch();
|
|
35
|
+
electron.app.quit();
|
|
84
36
|
}
|
|
85
37
|
|
|
86
38
|
// src/updater/types.ts
|
|
@@ -88,21 +40,21 @@ var ErrorInfo = {
|
|
|
88
40
|
download: "Download failed",
|
|
89
41
|
validate: "Validate failed",
|
|
90
42
|
param: "Missing params",
|
|
91
|
-
|
|
43
|
+
network: "Network error"
|
|
92
44
|
};
|
|
93
45
|
var UpdaterError = class extends Error {
|
|
46
|
+
code;
|
|
94
47
|
constructor(msg, info) {
|
|
95
|
-
super(msg + ": " + info);
|
|
48
|
+
super(ErrorInfo[msg] + ": " + info);
|
|
49
|
+
this.code = msg;
|
|
96
50
|
}
|
|
97
51
|
};
|
|
98
52
|
|
|
99
53
|
// src/updater/core.ts
|
|
100
|
-
var Updater = class {
|
|
54
|
+
var Updater = class extends events.EventEmitter {
|
|
101
55
|
CERT = __EIU_SIGNATURE_CERT__;
|
|
102
56
|
info;
|
|
103
|
-
options;
|
|
104
57
|
asarPath;
|
|
105
|
-
gzipPath;
|
|
106
58
|
tmpFilePath;
|
|
107
59
|
provider;
|
|
108
60
|
/**
|
|
@@ -110,141 +62,134 @@ var Updater = class {
|
|
|
110
62
|
*/
|
|
111
63
|
logger;
|
|
112
64
|
/**
|
|
113
|
-
*
|
|
114
|
-
* @param progress download progress
|
|
115
|
-
* @example
|
|
116
|
-
* updater.onDownloading = ({ percent, total, current }) => {
|
|
117
|
-
* console.log(`download progress: ${percent}, total: ${total}, current: ${current}`)
|
|
118
|
-
* }
|
|
65
|
+
* whether to receive beta update
|
|
119
66
|
*/
|
|
120
|
-
|
|
67
|
+
receiveBeta;
|
|
121
68
|
/**
|
|
122
|
-
*
|
|
123
|
-
*
|
|
124
|
-
* for Github, there are some {@link https://github.com/XIU2/UserScript/blob/master/GithubEnhanced-High-Speed-Download.user.js#L34 public CDN links}
|
|
125
|
-
* @param url source url
|
|
126
|
-
* @param isDownloadAsar whether is download asar
|
|
69
|
+
* whether force update in DEV
|
|
127
70
|
*/
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* whether receive beta version
|
|
131
|
-
*/
|
|
132
|
-
get receiveBeta() {
|
|
133
|
-
return !!this.options.receiveBeta;
|
|
134
|
-
}
|
|
135
|
-
set receiveBeta(receiveBeta) {
|
|
136
|
-
this.options.receiveBeta = receiveBeta;
|
|
137
|
-
}
|
|
71
|
+
forceUpdate;
|
|
138
72
|
/**
|
|
139
73
|
* initialize incremental updater
|
|
140
74
|
* @param provider update provider
|
|
141
75
|
* @param option UpdaterOption
|
|
142
76
|
*/
|
|
143
77
|
constructor(provider, option = {}) {
|
|
78
|
+
super();
|
|
144
79
|
this.provider = provider;
|
|
145
|
-
this.
|
|
80
|
+
this.receiveBeta = option.receiveBeta;
|
|
146
81
|
if (option.SIGNATURE_CERT) {
|
|
147
82
|
this.CERT = option.SIGNATURE_CERT;
|
|
148
83
|
}
|
|
149
84
|
if (option.logger) {
|
|
150
85
|
this.logger = option.logger;
|
|
151
86
|
}
|
|
87
|
+
if (isDev && !this.logger) {
|
|
88
|
+
this.logger = {
|
|
89
|
+
info: (...args) => console.log("[EIU-INFO ]", ...args),
|
|
90
|
+
debug: (...args) => console.log("[EIU-DEBUG]", ...args),
|
|
91
|
+
warn: (...args) => console.log("[EIU-WARN ]", ...args),
|
|
92
|
+
error: (...args) => console.error("[EIU-ERROR]", ...args)
|
|
93
|
+
};
|
|
94
|
+
this.logger.info("no logger set, enable dev-only logger");
|
|
95
|
+
}
|
|
152
96
|
this.asarPath = getPathFromAppNameAsar();
|
|
153
|
-
this.gzipPath = `${this.asarPath}.gz`;
|
|
154
97
|
this.tmpFilePath = `${this.asarPath}.tmp`;
|
|
155
98
|
}
|
|
156
|
-
async
|
|
157
|
-
if (
|
|
158
|
-
this.logger?.warn(`in dev mode, skip check update`);
|
|
159
|
-
return false;
|
|
160
|
-
}
|
|
161
|
-
const isLowerVersion = this.provider.isLowerVersion;
|
|
162
|
-
const entryVersion = getEntryVersion();
|
|
163
|
-
const appVersion = getAppVersion();
|
|
164
|
-
if (await isLowerVersion(entryVersion, minVersion)) {
|
|
165
|
-
throw new UpdaterError(ErrorInfo.version, `entry version (${entryVersion}) < minimumVersion (${minVersion})`);
|
|
166
|
-
}
|
|
167
|
-
this.logger?.info(`check update: current version is ${appVersion}, new version is ${version}`);
|
|
168
|
-
return await isLowerVersion(appVersion, version);
|
|
169
|
-
}
|
|
170
|
-
async parseData(format, data) {
|
|
171
|
-
if ((0, import_node_fs3.existsSync)(this.tmpFilePath)) {
|
|
99
|
+
async fetch(format, data) {
|
|
100
|
+
if (fs.existsSync(this.tmpFilePath)) {
|
|
172
101
|
this.logger?.warn(`remove tmp file: ${this.tmpFilePath}`);
|
|
173
|
-
|
|
174
|
-
}
|
|
175
|
-
if ((0, import_node_fs3.existsSync)(this.gzipPath)) {
|
|
176
|
-
this.logger?.warn(`remove .gz file: ${this.gzipPath}`);
|
|
177
|
-
(0, import_node_fs3.rmSync)(this.gzipPath);
|
|
102
|
+
fs.rmSync(this.tmpFilePath);
|
|
178
103
|
}
|
|
179
104
|
if (typeof data === "object") {
|
|
180
105
|
if (format === "json" && isUpdateJSON(data) || format === "buffer" && Buffer.isBuffer(data)) {
|
|
181
106
|
return data;
|
|
182
107
|
} else {
|
|
183
|
-
|
|
108
|
+
this.err("invalid type", "param", `invalid type at format '${format}': ${JSON.stringify(data)}`);
|
|
109
|
+
return;
|
|
184
110
|
}
|
|
185
111
|
}
|
|
186
112
|
this.logger?.debug(`download from ${this.provider.name}`);
|
|
187
113
|
try {
|
|
188
|
-
const result = format === "json" ? await this.provider.downloadJSON(data ?? __EIU_VERSION_PATH__) : await this.provider.
|
|
114
|
+
const result = format === "json" ? await this.provider.downloadJSON(data ?? __EIU_VERSION_PATH__) : await this.provider.downloadAsar(electron.app.name, this.info, (data2) => this.emit("download-progress", data2));
|
|
189
115
|
this.logger?.debug(`download ${format} success${format === "buffer" ? `, file size: ${result.length}` : ""}`);
|
|
190
116
|
return result;
|
|
191
117
|
} catch (e) {
|
|
192
|
-
this.
|
|
193
|
-
throw new UpdaterError(ErrorInfo.download, `download ${format} failed: ${e}`);
|
|
118
|
+
this.err(`fetch ${format} failed`, "network", `download ${format} failed: ${e}`);
|
|
194
119
|
}
|
|
195
120
|
}
|
|
121
|
+
/**
|
|
122
|
+
* handle error message and emit error event
|
|
123
|
+
*/
|
|
124
|
+
err(msg, code, errorInfo) {
|
|
125
|
+
const err = new UpdaterError(code, errorInfo);
|
|
126
|
+
this.logger?.error(msg, err);
|
|
127
|
+
this.emit("error", err);
|
|
128
|
+
}
|
|
196
129
|
async checkUpdate(data) {
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
return { success: true, data: this.info };
|
|
213
|
-
}
|
|
214
|
-
} catch (error) {
|
|
215
|
-
this.logger?.error("check update failed", error);
|
|
216
|
-
return {
|
|
217
|
-
success: false,
|
|
218
|
-
data: error instanceof UpdaterError ? error : new UpdaterError(ErrorInfo.download, error.toString())
|
|
219
|
-
};
|
|
130
|
+
const emitUnavailable = (msg) => {
|
|
131
|
+
this.logger?.info(msg);
|
|
132
|
+
this.emit("update-unavailable", msg);
|
|
133
|
+
return false;
|
|
134
|
+
};
|
|
135
|
+
const _data = await this.fetch("json", data);
|
|
136
|
+
if (!_data) {
|
|
137
|
+
return emitUnavailable("failed to get update info");
|
|
138
|
+
}
|
|
139
|
+
let { signature, size, version, minimumVersion, beta } = _data;
|
|
140
|
+
if (this.receiveBeta) {
|
|
141
|
+
version = beta.version;
|
|
142
|
+
signature = beta.signature;
|
|
143
|
+
minimumVersion = beta.minimumVersion;
|
|
144
|
+
size = beta.size;
|
|
220
145
|
}
|
|
146
|
+
this.logger?.debug(`checked update, version: ${version}, size: ${size}, signature: ${signature}`);
|
|
147
|
+
if (isDev && !this.forceUpdate && !data) {
|
|
148
|
+
return emitUnavailable("skip check update in dev mode, to force update, set `updater.forceUpdate` to true or call checkUpdate with UpdateJSON");
|
|
149
|
+
}
|
|
150
|
+
const isLowerVersion = this.provider.isLowerVersion;
|
|
151
|
+
const entryVersion = getEntryVersion();
|
|
152
|
+
const appVersion = getAppVersion();
|
|
153
|
+
if (isLowerVersion(entryVersion, minimumVersion)) {
|
|
154
|
+
return emitUnavailable(`entry version (${entryVersion}) < minimumVersion (${minimumVersion})`);
|
|
155
|
+
}
|
|
156
|
+
this.logger?.info(`check update: current version is ${appVersion}, new version is ${version}`);
|
|
157
|
+
if (!isLowerVersion(appVersion, version)) {
|
|
158
|
+
return emitUnavailable(`current version (${appVersion}) < new version (${version})`);
|
|
159
|
+
}
|
|
160
|
+
this.logger?.info(`update available: ${version}`);
|
|
161
|
+
this.info = { signature, minimumVersion, version, size };
|
|
162
|
+
this.emit("update-available", this.info);
|
|
163
|
+
return true;
|
|
221
164
|
}
|
|
222
165
|
async download(data, sig) {
|
|
166
|
+
const _sig = sig ?? this.info?.signature;
|
|
167
|
+
if (!_sig) {
|
|
168
|
+
this.err("download failed", "param", "no update signature, please call `checkUpdate` first");
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
const buffer = await this.fetch("buffer", data ? Buffer.from(data) : void 0);
|
|
172
|
+
if (!buffer) {
|
|
173
|
+
this.err("download failed", "param", "no update asar file buffer");
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
this.logger?.debug("verify start");
|
|
177
|
+
const _ver = await this.provider.verifySignaure(buffer, _sig, this.CERT);
|
|
178
|
+
if (!_ver) {
|
|
179
|
+
this.err("download failed", "validate", "invalid signature / certificate pair");
|
|
180
|
+
return false;
|
|
181
|
+
}
|
|
182
|
+
this.logger?.debug("verify success");
|
|
223
183
|
try {
|
|
224
|
-
if (!this.info) {
|
|
225
|
-
throw new UpdaterError(ErrorInfo.param, "no update info");
|
|
226
|
-
}
|
|
227
|
-
const _sig = sig ?? this.info.signature;
|
|
228
|
-
const buffer = await this.parseData("buffer", data);
|
|
229
|
-
this.logger?.debug("verify start");
|
|
230
|
-
const _ver = await this.provider.verifySignaure(buffer, _sig, this.CERT);
|
|
231
|
-
if (!_ver) {
|
|
232
|
-
throw new UpdaterError(ErrorInfo.validate, "invalid signature or certificate");
|
|
233
|
-
}
|
|
234
|
-
this.logger?.debug("verify success");
|
|
235
|
-
this.logger?.debug(`write to ${this.gzipPath}`);
|
|
236
|
-
(0, import_node_fs3.writeFileSync)(this.gzipPath, buffer);
|
|
237
184
|
this.logger?.debug(`extract to ${this.tmpFilePath}`);
|
|
238
|
-
await unzipFile(
|
|
185
|
+
await this.provider.unzipFile(buffer, this.tmpFilePath);
|
|
239
186
|
this.logger?.info(`download success, version: ${_ver}`);
|
|
240
187
|
this.info = void 0;
|
|
241
|
-
|
|
188
|
+
this.emit("update-downloaded");
|
|
189
|
+
return true;
|
|
242
190
|
} catch (error) {
|
|
243
|
-
this.
|
|
244
|
-
return
|
|
245
|
-
success: false,
|
|
246
|
-
data: error instanceof UpdaterError ? error : new UpdaterError(ErrorInfo.download, error.toString())
|
|
247
|
-
};
|
|
191
|
+
this.err("download failed", "download", `fail to unwrap asar file, ${error}`);
|
|
192
|
+
return false;
|
|
248
193
|
}
|
|
249
194
|
}
|
|
250
195
|
/**
|
|
@@ -254,28 +199,28 @@ var Updater = class {
|
|
|
254
199
|
this.logger?.info("quit and install");
|
|
255
200
|
restartApp();
|
|
256
201
|
}
|
|
202
|
+
/**
|
|
203
|
+
* setup provider URL handler
|
|
204
|
+
*
|
|
205
|
+
* @example
|
|
206
|
+
* updater.setURLHandler((url, isDownloadingAsar) => {
|
|
207
|
+
* if (isDownloadingAsar) {
|
|
208
|
+
* return url.replace('https://raw.githubusercontent.com', 'https://cdn.jsdelivr.net/gh')
|
|
209
|
+
* }
|
|
210
|
+
* })
|
|
211
|
+
*/
|
|
212
|
+
setURLHandler(handler) {
|
|
213
|
+
this.provider.urlHandler = handler;
|
|
214
|
+
}
|
|
257
215
|
};
|
|
258
216
|
|
|
259
|
-
// src/utils/zip.ts
|
|
260
|
-
var import_node_fs4 = require("fs");
|
|
261
|
-
var import_node_zlib2 = require("zlib");
|
|
262
|
-
|
|
263
|
-
// src/utils/crypto/decrypt.ts
|
|
264
|
-
var import_node_crypto2 = require("crypto");
|
|
265
|
-
|
|
266
|
-
// src/utils/crypto/utils.ts
|
|
267
|
-
var import_node_crypto = require("crypto");
|
|
268
|
-
|
|
269
|
-
// src/utils/crypto/encrypt.ts
|
|
270
|
-
var import_node_crypto3 = require("crypto");
|
|
271
|
-
|
|
272
217
|
// src/entry.ts
|
|
273
218
|
function startupWithUpdater(fn) {
|
|
274
219
|
return fn;
|
|
275
220
|
}
|
|
276
221
|
var defaultOnInstall = (install, _, __, logger) => {
|
|
277
222
|
install();
|
|
278
|
-
logger
|
|
223
|
+
logger?.info(`update success!`);
|
|
279
224
|
};
|
|
280
225
|
async function initApp(appOptions) {
|
|
281
226
|
const {
|
|
@@ -291,32 +236,38 @@ async function initApp(appOptions) {
|
|
|
291
236
|
} else {
|
|
292
237
|
updaterInstance = await updater();
|
|
293
238
|
}
|
|
294
|
-
|
|
239
|
+
let logger = updaterInstance.logger;
|
|
240
|
+
if (isDev && !logger) {
|
|
241
|
+
logger = {
|
|
242
|
+
info: (...args) => console.log("[EIU-INFO ]", ...args),
|
|
243
|
+
debug: (...args) => console.log("[EIU-DEBUG]", ...args),
|
|
244
|
+
warn: (...args) => console.log("[EIU-WARN ]", ...args),
|
|
245
|
+
error: (...args) => console.error("[EIU-ERROR]", ...args)
|
|
246
|
+
};
|
|
247
|
+
}
|
|
295
248
|
try {
|
|
296
249
|
const appNameAsarPath = getPathFromAppNameAsar();
|
|
297
250
|
const tempAsarPath = `${appNameAsarPath}.tmp`;
|
|
298
|
-
if (
|
|
299
|
-
logger
|
|
300
|
-
await onInstall(() =>
|
|
251
|
+
if (fs.existsSync(tempAsarPath)) {
|
|
252
|
+
logger?.info(`installing new asar: ${tempAsarPath}`);
|
|
253
|
+
await onInstall(() => fs.renameSync(tempAsarPath, appNameAsarPath), tempAsarPath, appNameAsarPath, logger);
|
|
301
254
|
}
|
|
302
|
-
const mainFilePath =
|
|
303
|
-
isDev ?
|
|
255
|
+
const mainFilePath = path.join(
|
|
256
|
+
isDev ? path.join(electron.app.getAppPath(), __EIU_MAIN_DEV_DIR__) : appNameAsarPath,
|
|
304
257
|
"main",
|
|
305
258
|
__EIU_MAIN_FILE__
|
|
306
259
|
);
|
|
307
260
|
await beforeStart?.(mainFilePath, logger);
|
|
308
|
-
|
|
261
|
+
__require(mainFilePath)(updaterInstance);
|
|
309
262
|
} catch (error) {
|
|
310
|
-
logger
|
|
263
|
+
logger?.error("startup error", error);
|
|
311
264
|
onStartError?.(error, logger);
|
|
312
|
-
|
|
265
|
+
electron.app.quit();
|
|
313
266
|
}
|
|
314
267
|
}
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
startupWithUpdater
|
|
322
|
-
});
|
|
268
|
+
|
|
269
|
+
exports.ErrorInfo = ErrorInfo;
|
|
270
|
+
exports.Updater = Updater;
|
|
271
|
+
exports.UpdaterError = UpdaterError;
|
|
272
|
+
exports.initApp = initApp;
|
|
273
|
+
exports.startupWithUpdater = startupWithUpdater;
|