electron-incremental-update 1.3.0 → 2.0.0-beta.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 +7 -3
- package/dist/chunk-BG22XZAB.js +257 -0
- package/dist/decrypt-D9WdXYjH.d.cts +4 -0
- package/dist/decrypt-D9WdXYjH.d.ts +4 -0
- package/dist/index.cjs +164 -303
- package/dist/index.d.cts +81 -182
- package/dist/index.d.ts +81 -182
- package/dist/index.js +132 -237
- package/dist/provider.cjs +236 -0
- package/dist/provider.d.cts +37 -0
- package/dist/provider.d.ts +37 -0
- package/dist/provider.js +107 -0
- package/dist/types-COqp44eg.d.cts +69 -0
- package/dist/types-CPq1MrYZ.d.ts +69 -0
- package/dist/utils.cjs +159 -125
- package/dist/utils.d.cts +32 -77
- package/dist/utils.d.ts +32 -77
- package/dist/utils.js +35 -11
- package/dist/{pure-GoN_3MEj.d.cts → version-CffZWDhZ.d.cts} +8 -7
- package/dist/{pure-GoN_3MEj.d.ts → version-CffZWDhZ.d.ts} +8 -7
- package/dist/vite.js +101 -136
- package/package.json +13 -7
- package/provider.d.ts +1 -0
- package/provider.js +1 -0
- package/dist/chunk-7ET4GMTZ.js +0 -236
- package/dist/chunk-CXHA5TF7.js +0 -236
- package/dist/chunk-HWUYTDEF.js +0 -236
- package/dist/chunk-RQCTJY4L.js +0 -236
- package/dist/chunk-SBPTSLG7.js +0 -235
- package/dist/vite.d.ts +0 -372
package/README.md
CHANGED
|
@@ -10,6 +10,8 @@ The new `${electron.app.name}.asar`, which can download from remote or load from
|
|
|
10
10
|
|
|
11
11
|
All **native modules** should be packaged into `app.asar` to reduce `${electron.app.name}.asar` file size, [see usage](#use-native-modules). Therefore, auto upgrade of portable app is possible.
|
|
12
12
|
|
|
13
|
+
Support bytecode protection, [see details](#bytecode-protection)
|
|
14
|
+
|
|
13
15
|
No `vite-plugin-electron-renderer` config
|
|
14
16
|
|
|
15
17
|
- inspired by [Obsidian](https://obsidian.md/)'s upgrade strategy
|
|
@@ -179,7 +181,7 @@ initApp({
|
|
|
179
181
|
in `electron/main/index.ts`
|
|
180
182
|
|
|
181
183
|
```ts
|
|
182
|
-
import { startupWithUpdater } from 'electron-incremental-update'
|
|
184
|
+
import { UpdaterError, startupWithUpdater } from 'electron-incremental-update'
|
|
183
185
|
import { getPathFromAppNameAsar, getVersions } from 'electron-incremental-update/utils'
|
|
184
186
|
import { app } from 'electron'
|
|
185
187
|
|
|
@@ -196,10 +198,12 @@ export default startupWithUpdater((updater) => {
|
|
|
196
198
|
console.log(percent)
|
|
197
199
|
}
|
|
198
200
|
updater.logger = console
|
|
201
|
+
updater.receiveBeta = true
|
|
202
|
+
|
|
199
203
|
updater.checkUpdate().then(async (result) => {
|
|
200
204
|
if (result === undefined) {
|
|
201
205
|
console.log('Update Unavailable')
|
|
202
|
-
} else if (result instanceof
|
|
206
|
+
} else if (result instanceof UpdaterError) {
|
|
203
207
|
console.error(result)
|
|
204
208
|
} else {
|
|
205
209
|
console.log('new version: ', result.version)
|
|
@@ -272,7 +276,7 @@ import Database from 'better-sqlite3'
|
|
|
272
276
|
|
|
273
277
|
const db = new Database(':memory:', { nativeBinding: './better_sqlite3.node' })
|
|
274
278
|
|
|
275
|
-
export function test() {
|
|
279
|
+
export function test(): void {
|
|
276
280
|
db.exec(
|
|
277
281
|
'DROP TABLE IF EXISTS employees; '
|
|
278
282
|
+ 'CREATE TABLE IF NOT EXISTS employees (name TEXT, salary INTEGER)',
|
|
@@ -0,0 +1,257 @@
|
|
|
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/electron.ts
|
|
9
|
+
import { existsSync, mkdirSync, readFileSync } from "node:fs";
|
|
10
|
+
import { dirname, join } from "node:path";
|
|
11
|
+
import { app } from "electron";
|
|
12
|
+
var isDev = __EIU_IS_DEV__;
|
|
13
|
+
var isWin = process.platform === "win32";
|
|
14
|
+
var isMac = process.platform === "darwin";
|
|
15
|
+
var isLinux = process.platform === "linux";
|
|
16
|
+
function getPathFromAppNameAsar(...path) {
|
|
17
|
+
return isDev ? "DEV.asar" : join(dirname(app.getAppPath()), `${app.name}.asar`, ...path);
|
|
18
|
+
}
|
|
19
|
+
function getAppVersion() {
|
|
20
|
+
return isDev ? getEntryVersion() : readFileSync(getPathFromAppNameAsar("version"), "utf-8");
|
|
21
|
+
}
|
|
22
|
+
function getEntryVersion() {
|
|
23
|
+
return app.getVersion();
|
|
24
|
+
}
|
|
25
|
+
function requireNative(moduleName) {
|
|
26
|
+
return __require(join(app.getAppPath(), __EIU_ENTRY_DIST_PATH__, moduleName));
|
|
27
|
+
}
|
|
28
|
+
function restartApp() {
|
|
29
|
+
app.relaunch();
|
|
30
|
+
app.quit();
|
|
31
|
+
}
|
|
32
|
+
function setAppUserModelId(id) {
|
|
33
|
+
if (isWin) {
|
|
34
|
+
app.setAppUserModelId(id ?? `org.${app.name}`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function disableHWAccForWin7() {
|
|
38
|
+
if (__require("node:os").release().startsWith("6.1")) {
|
|
39
|
+
app.disableHardwareAcceleration();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function singleInstance(window) {
|
|
43
|
+
const result = app.requestSingleInstanceLock();
|
|
44
|
+
if (result) {
|
|
45
|
+
app.on("second-instance", () => {
|
|
46
|
+
if (window) {
|
|
47
|
+
window.show();
|
|
48
|
+
if (window.isMinimized()) {
|
|
49
|
+
window.restore();
|
|
50
|
+
}
|
|
51
|
+
window.focus();
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
} else {
|
|
55
|
+
app.quit();
|
|
56
|
+
}
|
|
57
|
+
return result;
|
|
58
|
+
}
|
|
59
|
+
function setPortableAppDataPath(dirName = "data") {
|
|
60
|
+
const portablePath = join(dirname(app.getPath("exe")), dirName);
|
|
61
|
+
if (!existsSync(portablePath)) {
|
|
62
|
+
mkdirSync(portablePath);
|
|
63
|
+
}
|
|
64
|
+
app.setPath("appData", portablePath);
|
|
65
|
+
}
|
|
66
|
+
function waitAppReady(timeout = 1e3) {
|
|
67
|
+
return app.isReady() ? Promise.resolve() : new Promise((resolve, reject) => {
|
|
68
|
+
const _ = setTimeout(() => {
|
|
69
|
+
reject(new Error("app is not ready"));
|
|
70
|
+
}, timeout);
|
|
71
|
+
app.whenReady().then(() => {
|
|
72
|
+
clearTimeout(_);
|
|
73
|
+
resolve();
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
function loadPage(win, htmlFilePath = "index.html") {
|
|
78
|
+
if (isDev) {
|
|
79
|
+
win.loadURL(process.env.VITE_DEV_SERVER_URL + htmlFilePath);
|
|
80
|
+
} else {
|
|
81
|
+
win.loadFile(getPathFromAppNameAsar("renderer", htmlFilePath));
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function getPathFromPreload(...paths) {
|
|
85
|
+
return isDev ? join(app.getAppPath(), __EIU_ELECTRON_DIST_PATH__, "preload", ...paths) : getPathFromAppNameAsar("preload", ...paths);
|
|
86
|
+
}
|
|
87
|
+
function getPathFromPublic(...paths) {
|
|
88
|
+
return isDev ? join(app.getAppPath(), "public", ...paths) : getPathFromAppNameAsar("renderer", ...paths);
|
|
89
|
+
}
|
|
90
|
+
function getPathFromEntryAsar(...paths) {
|
|
91
|
+
return join(app.getAppPath(), __EIU_ENTRY_DIST_PATH__, ...paths);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// src/utils/zip.ts
|
|
95
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync } from "node:fs";
|
|
96
|
+
import { brotliCompress } from "node:zlib";
|
|
97
|
+
async function zipFile(filePath, targetFilePath = `${filePath}.gz`) {
|
|
98
|
+
if (!existsSync2(filePath)) {
|
|
99
|
+
throw new Error(`path to be zipped not exist: ${filePath}`);
|
|
100
|
+
}
|
|
101
|
+
const buffer = readFileSync2(filePath);
|
|
102
|
+
return new Promise((resolve, reject) => {
|
|
103
|
+
brotliCompress(buffer, (err, buffer2) => {
|
|
104
|
+
if (err) {
|
|
105
|
+
reject(err);
|
|
106
|
+
}
|
|
107
|
+
writeFileSync(targetFilePath, buffer2);
|
|
108
|
+
resolve();
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// src/utils/unzip.ts
|
|
114
|
+
import { existsSync as existsSync3, readFileSync as readFileSync3, rmSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
115
|
+
import { brotliDecompress } from "node:zlib";
|
|
116
|
+
async function unzipFile(gzipPath, targetFilePath = gzipPath.slice(0, -3)) {
|
|
117
|
+
if (!existsSync3(gzipPath)) {
|
|
118
|
+
throw new Error(`path to zipped file not exist: ${gzipPath}`);
|
|
119
|
+
}
|
|
120
|
+
const compressedBuffer = readFileSync3(gzipPath);
|
|
121
|
+
return new Promise((resolve, reject) => {
|
|
122
|
+
brotliDecompress(compressedBuffer, (err, buffer) => {
|
|
123
|
+
rmSync(gzipPath);
|
|
124
|
+
if (err) {
|
|
125
|
+
reject(err);
|
|
126
|
+
}
|
|
127
|
+
writeFileSync2(targetFilePath, buffer);
|
|
128
|
+
resolve();
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// src/utils/version.ts
|
|
134
|
+
function handleUnexpectedErrors(callback) {
|
|
135
|
+
process.on("uncaughtException", callback);
|
|
136
|
+
process.on("unhandledRejection", callback);
|
|
137
|
+
}
|
|
138
|
+
function parseVersion(version) {
|
|
139
|
+
const match = /^(\d+)\.(\d+)\.(\d+)(?:-([a-z0-9.-]+))?/i.exec(version);
|
|
140
|
+
if (!match) {
|
|
141
|
+
throw new TypeError(`invalid version: ${version}`);
|
|
142
|
+
}
|
|
143
|
+
const [major, minor, patch] = match.slice(1, 4).map(Number);
|
|
144
|
+
const ret = {
|
|
145
|
+
major,
|
|
146
|
+
minor,
|
|
147
|
+
patch,
|
|
148
|
+
stage: "",
|
|
149
|
+
stageVersion: -1
|
|
150
|
+
};
|
|
151
|
+
if (match[4]) {
|
|
152
|
+
let [stage, _v] = match[4].split(".");
|
|
153
|
+
ret.stage = stage;
|
|
154
|
+
ret.stageVersion = Number(_v) || -1;
|
|
155
|
+
}
|
|
156
|
+
if (Number.isNaN(major) || Number.isNaN(minor) || Number.isNaN(patch) || Number.isNaN(ret.stageVersion)) {
|
|
157
|
+
throw new TypeError(`invalid version: ${version}`);
|
|
158
|
+
}
|
|
159
|
+
return ret;
|
|
160
|
+
}
|
|
161
|
+
function isLowerVersionDefault(oldVer, newVer) {
|
|
162
|
+
const oldV = parseVersion(oldVer);
|
|
163
|
+
const newV = parseVersion(newVer);
|
|
164
|
+
function compareStrings(str1, str2) {
|
|
165
|
+
if (str1 === "") {
|
|
166
|
+
return str2 !== "";
|
|
167
|
+
} else if (str2 === "") {
|
|
168
|
+
return true;
|
|
169
|
+
}
|
|
170
|
+
return str1 < str2;
|
|
171
|
+
}
|
|
172
|
+
for (let key of Object.keys(oldV)) {
|
|
173
|
+
if (key === "stage" && compareStrings(oldV[key], newV[key])) {
|
|
174
|
+
return true;
|
|
175
|
+
} else if (oldV[key] !== newV[key]) {
|
|
176
|
+
return oldV[key] < newV[key];
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
function isUpdateJSON(json) {
|
|
182
|
+
const is = (j) => !!(j && j.minimumVersion && j.signature && j.size && j.version);
|
|
183
|
+
return is(json) && is(json?.beta);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// src/utils/crypto/decrypt.ts
|
|
187
|
+
import { createDecipheriv, createVerify } from "node:crypto";
|
|
188
|
+
|
|
189
|
+
// src/utils/crypto/utils.ts
|
|
190
|
+
import { createHash } from "node:crypto";
|
|
191
|
+
function hashString(data, length) {
|
|
192
|
+
const hash = createHash("SHA256").update(data).digest("binary");
|
|
193
|
+
return Buffer.from(hash).subarray(0, length);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// src/utils/crypto/decrypt.ts
|
|
197
|
+
function decrypt(encryptedText, key, iv) {
|
|
198
|
+
const decipher = createDecipheriv("aes-256-cbc", key, iv);
|
|
199
|
+
let decrypted = decipher.update(encryptedText, "base64url", "utf8");
|
|
200
|
+
decrypted += decipher.final("utf8");
|
|
201
|
+
return decrypted;
|
|
202
|
+
}
|
|
203
|
+
function verifySignatureDefault(buffer, signature2, cert) {
|
|
204
|
+
try {
|
|
205
|
+
const [sig, version] = decrypt(signature2, hashString(cert, 32), hashString(buffer, 16)).split("%");
|
|
206
|
+
const result = createVerify("RSA-SHA256").update(buffer).verify(cert, sig, "base64");
|
|
207
|
+
return result ? version : void 0;
|
|
208
|
+
} catch {
|
|
209
|
+
return void 0;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// src/utils/crypto/encrypt.ts
|
|
214
|
+
import { createCipheriv, createPrivateKey, createSign } from "node:crypto";
|
|
215
|
+
function encrypt(plainText, key, iv) {
|
|
216
|
+
const cipher = createCipheriv("aes-256-cbc", key, iv);
|
|
217
|
+
let encrypted = cipher.update(plainText, "utf8", "base64url");
|
|
218
|
+
encrypted += cipher.final("base64url");
|
|
219
|
+
return encrypted;
|
|
220
|
+
}
|
|
221
|
+
function signature(buffer, privateKey, cert, version) {
|
|
222
|
+
const sig = createSign("RSA-SHA256").update(buffer).sign(createPrivateKey(privateKey), "base64");
|
|
223
|
+
return encrypt(`${sig}%${version}`, hashString(cert, 32), hashString(buffer, 16));
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
export {
|
|
227
|
+
__require,
|
|
228
|
+
handleUnexpectedErrors,
|
|
229
|
+
parseVersion,
|
|
230
|
+
isLowerVersionDefault,
|
|
231
|
+
isUpdateJSON,
|
|
232
|
+
isDev,
|
|
233
|
+
isWin,
|
|
234
|
+
isMac,
|
|
235
|
+
isLinux,
|
|
236
|
+
getPathFromAppNameAsar,
|
|
237
|
+
getAppVersion,
|
|
238
|
+
getEntryVersion,
|
|
239
|
+
requireNative,
|
|
240
|
+
restartApp,
|
|
241
|
+
setAppUserModelId,
|
|
242
|
+
disableHWAccForWin7,
|
|
243
|
+
singleInstance,
|
|
244
|
+
setPortableAppDataPath,
|
|
245
|
+
waitAppReady,
|
|
246
|
+
loadPage,
|
|
247
|
+
getPathFromPreload,
|
|
248
|
+
getPathFromPublic,
|
|
249
|
+
getPathFromEntryAsar,
|
|
250
|
+
unzipFile,
|
|
251
|
+
zipFile,
|
|
252
|
+
hashString,
|
|
253
|
+
decrypt,
|
|
254
|
+
verifySignatureDefault,
|
|
255
|
+
encrypt,
|
|
256
|
+
signature
|
|
257
|
+
};
|