electron-incremental-update 1.1.0 → 1.3.0
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 +162 -25
- package/dist/chunk-7ET4GMTZ.js +236 -0
- package/dist/chunk-HWUYTDEF.js +236 -0
- package/dist/chunk-RQCTJY4L.js +236 -0
- package/dist/chunk-SBPTSLG7.js +235 -0
- package/dist/index.cjs +109 -168
- package/dist/index.d.cts +78 -59
- package/dist/index.d.ts +78 -59
- package/dist/index.js +104 -164
- package/dist/utils.cjs +5 -6
- package/dist/utils.d.cts +4 -4
- package/dist/utils.d.ts +4 -4
- package/dist/utils.js +1 -1
- package/dist/vite.d.ts +32 -6
- package/dist/vite.js +441 -80
- package/package.json +7 -2
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ 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
|
-
|
|
13
|
+
No `vite-plugin-electron-renderer` config
|
|
14
14
|
|
|
15
15
|
- inspired by [Obsidian](https://obsidian.md/)'s upgrade strategy
|
|
16
16
|
|
|
@@ -57,16 +57,17 @@ import { initApp } from 'electron-incremental-update'
|
|
|
57
57
|
import { parseGithubCdnURL } from 'electron-incremental-update/utils'
|
|
58
58
|
import { repository } from '../package.json'
|
|
59
59
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
60
|
+
initApp({
|
|
61
|
+
// can be updater option or function that return updater
|
|
62
|
+
updater: {
|
|
63
|
+
SIGNATURE_CERT: 'custom certificate',
|
|
64
|
+
repository,
|
|
65
|
+
updateJsonURL: parseGithubCdnURL(repository, jsonPrefix, 'version.json'),
|
|
66
|
+
releaseAsarURL: parseGithubCdnURL(repository, asarPrefix, `download/latest/${app.name}.asar.gz`),
|
|
67
|
+
receiveBeta: true,
|
|
68
|
+
},
|
|
69
|
+
onStart: console.log
|
|
70
|
+
})
|
|
70
71
|
```
|
|
71
72
|
|
|
72
73
|
- [some CDN resources](https://github.com/XIU2/UserScript/blob/master/GithubEnhanced-High-Speed-Download.user.js#L34):
|
|
@@ -83,14 +84,12 @@ in `vite.config.mts`
|
|
|
83
84
|
```ts
|
|
84
85
|
import { defineConfig } from 'vite'
|
|
85
86
|
import { debugStartup, electronWithUpdater } from 'electron-incremental-update/vite'
|
|
86
|
-
import pkg from './package.json'
|
|
87
87
|
|
|
88
88
|
export default defineConfig(async ({ command }) => {
|
|
89
89
|
const isBuild = command === 'build'
|
|
90
90
|
return {
|
|
91
91
|
plugins: [
|
|
92
92
|
electronWithUpdater({
|
|
93
|
-
pkg,
|
|
94
93
|
isBuild,
|
|
95
94
|
logParsedOptions: true,
|
|
96
95
|
main: {
|
|
@@ -160,12 +159,23 @@ module.exports = {
|
|
|
160
159
|
|
|
161
160
|
### Use in main process
|
|
162
161
|
|
|
163
|
-
To use electron's `net` module for updating, the `checkUpdate` and `download` functions must be called after the app is ready by default.
|
|
164
|
-
|
|
165
|
-
However, you have the option to customize the download function when creating the updater.
|
|
162
|
+
To use electron's `net` module for updating, the `checkUpdate` and `download` functions must be called after the app is ready by default. You have the option to customize the download function when creating the updater.
|
|
166
163
|
|
|
167
164
|
**NOTE: There should only one function and should be default export in the entry file**
|
|
168
165
|
|
|
166
|
+
in `electron/entry.ts`
|
|
167
|
+
|
|
168
|
+
```ts
|
|
169
|
+
initApp({
|
|
170
|
+
updater: {
|
|
171
|
+
overrideFunctions: {
|
|
172
|
+
downloadJSON: (url: string, headers: Record<string, any>) => {}
|
|
173
|
+
// ...
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
})
|
|
177
|
+
```
|
|
178
|
+
|
|
169
179
|
in `electron/main/index.ts`
|
|
170
180
|
|
|
171
181
|
```ts
|
|
@@ -214,7 +224,16 @@ export default startupWithUpdater((updater) => {
|
|
|
214
224
|
|
|
215
225
|
All the **native modules** should be set as `dependency` in `package.json`. `electron-rebuild` only check dependencies inside `dependency` field.
|
|
216
226
|
|
|
217
|
-
If you are using `electron-builder` to build distributions, all the native modules with its **large relavent `node_modiles`** will be packaged into `app.asar` by default.
|
|
227
|
+
If you are using `electron-builder` to build distributions, all the native modules with its **large relavent `node_modiles`** will be packaged into `app.asar` by default.
|
|
228
|
+
|
|
229
|
+
Luckily, `Esbuild` can bundle all the dependencies. Just follow the steps:
|
|
230
|
+
|
|
231
|
+
1. setup `nativeModuleEntryMap` option
|
|
232
|
+
2. Manually copy the native binaries in `postBuild` callback
|
|
233
|
+
3. Exclude all the dependencies in `electron-builder`'s config
|
|
234
|
+
4. call the native functions with `loadNativeModuleFromEntry` in your code
|
|
235
|
+
|
|
236
|
+
#### Example
|
|
218
237
|
|
|
219
238
|
in `vite.config.ts`
|
|
220
239
|
|
|
@@ -225,6 +244,7 @@ const plugin = electronWithUpdater({
|
|
|
225
244
|
entry: {
|
|
226
245
|
nativeModuleEntryMap: {
|
|
227
246
|
db: './electron/native/db.ts',
|
|
247
|
+
img: './electron/native/img.ts',
|
|
228
248
|
},
|
|
229
249
|
postBuild: async ({ copyToEntryOutputDir }) => {
|
|
230
250
|
// for better-sqlite3
|
|
@@ -249,9 +269,8 @@ in `electron/native/db.ts`
|
|
|
249
269
|
|
|
250
270
|
```ts
|
|
251
271
|
import Database from 'better-sqlite3'
|
|
252
|
-
import { getPaths } from 'electron-incremental-update/utils'
|
|
253
272
|
|
|
254
|
-
const db = new Database(':memory:', { nativeBinding:
|
|
273
|
+
const db = new Database(':memory:', { nativeBinding: './better_sqlite3.node' })
|
|
255
274
|
|
|
256
275
|
export function test() {
|
|
257
276
|
db.exec(
|
|
@@ -296,14 +315,119 @@ module.exports = {
|
|
|
296
315
|
|
|
297
316
|
### Bytecode protection
|
|
298
317
|
|
|
299
|
-
|
|
318
|
+
From v1.2, the vite plugin is able to generate bytecode to protect your application.
|
|
300
319
|
|
|
301
|
-
|
|
320
|
+
It will automatically protect your `SIGNATURE_CERT` by default.
|
|
302
321
|
|
|
303
|
-
|
|
322
|
+
credit to [electron-vite](https://github.com/alex8088/electron-vite/blob/master/src/plugins/bytecode.ts), and improve the string protection (see [original issue](https://github.com/alex8088/electron-vite/issues/552))
|
|
323
|
+
|
|
324
|
+
```ts
|
|
325
|
+
electronWithUpdater({
|
|
326
|
+
// ...
|
|
327
|
+
bytecode: true,
|
|
328
|
+
})
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
#### Limitation
|
|
332
|
+
|
|
333
|
+
- only support commonjs
|
|
334
|
+
- only for main process by default, if you want to use in preload script, please use `electronWithUpdater({ bytecode: { enablePreload: true } })` and set `sandbox: false` when creating window
|
|
304
335
|
|
|
305
336
|
### Types
|
|
306
337
|
|
|
338
|
+
#### Updater
|
|
339
|
+
|
|
340
|
+
```ts
|
|
341
|
+
export interface UpdaterOption {
|
|
342
|
+
/**
|
|
343
|
+
* public key of signature, which will be auto generated by plugin,
|
|
344
|
+
* generate by `selfsigned` if not set
|
|
345
|
+
*/
|
|
346
|
+
SIGNATURE_CERT?: string
|
|
347
|
+
/**
|
|
348
|
+
* repository url, e.g. `https://github.com/electron/electron`
|
|
349
|
+
*
|
|
350
|
+
* you can use the `repository` in `package.json`
|
|
351
|
+
*
|
|
352
|
+
* if `updateJsonURL` or `releaseAsarURL` are absent,
|
|
353
|
+
* `repository` will be used to determine the url
|
|
354
|
+
*/
|
|
355
|
+
repository?: string
|
|
356
|
+
/**
|
|
357
|
+
* URL of version info json
|
|
358
|
+
* @default `${repository.replace('github.com', 'raw.githubusercontent.com')}/master/version.json`
|
|
359
|
+
* @throws if `updateJsonURL` and `repository` are all not set
|
|
360
|
+
*/
|
|
361
|
+
updateJsonURL?: string
|
|
362
|
+
/**
|
|
363
|
+
* URL of release asar.gz
|
|
364
|
+
* @default `${repository}/releases/download/v${version}/${app.name}-${version}.asar.gz`
|
|
365
|
+
* @throws if `releaseAsarURL` and `repository` are all not set
|
|
366
|
+
*/
|
|
367
|
+
releaseAsarURL?: string
|
|
368
|
+
/**
|
|
369
|
+
* whether to receive beta update
|
|
370
|
+
*/
|
|
371
|
+
receiveBeta?: boolean
|
|
372
|
+
overrideFunctions?: UpdaterOverrideFunctions
|
|
373
|
+
downloadConfig?: UpdaterDownloadConfig
|
|
374
|
+
}
|
|
375
|
+
export type Logger = {
|
|
376
|
+
info: (msg: string) => void
|
|
377
|
+
debug: (msg: string) => void
|
|
378
|
+
warn: (msg: string) => void
|
|
379
|
+
error: (msg: string, e?: Error) => void
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
export type UpdaterOverrideFunctions = {
|
|
383
|
+
/**
|
|
384
|
+
* custom version compare function
|
|
385
|
+
* @param version1 old version string
|
|
386
|
+
* @param version2 new version string
|
|
387
|
+
* @returns if version1 < version2
|
|
388
|
+
*/
|
|
389
|
+
isLowerVersion?: (version1: string, version2: string) => boolean | Promise<boolean>
|
|
390
|
+
/**
|
|
391
|
+
* custom verify signature function
|
|
392
|
+
* @param buffer file buffer
|
|
393
|
+
* @param signature signature
|
|
394
|
+
* @param cert certificate
|
|
395
|
+
* @returns if signature is valid, returns the version or `true` , otherwise returns `false`
|
|
396
|
+
*/
|
|
397
|
+
verifySignaure?: (buffer: Buffer, signature: string, cert: string) => string | false | Promise<string | false>
|
|
398
|
+
/**
|
|
399
|
+
* custom download JSON function
|
|
400
|
+
* @param url download url
|
|
401
|
+
* @param header download header
|
|
402
|
+
* @returns `UpdateJSON`
|
|
403
|
+
*/
|
|
404
|
+
downloadJSON?: (url: string, headers: Record<string, any>) => Promise<UpdateJSON>
|
|
405
|
+
/**
|
|
406
|
+
* custom download buffer function
|
|
407
|
+
* @param url download url
|
|
408
|
+
* @param headers download header
|
|
409
|
+
* @param total precaculated file total size
|
|
410
|
+
* @param onDownloading on downloading callback
|
|
411
|
+
* @returns `Buffer`
|
|
412
|
+
*/
|
|
413
|
+
downloadBuffer?: (url: string, headers: Record<string, any>, total: number, onDownloading?: (progress: DownloadingInfo) => void) => Promise<Buffer>
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
export type UpdaterDownloadConfig = {
|
|
417
|
+
/**
|
|
418
|
+
* download user agent
|
|
419
|
+
* @default 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36'
|
|
420
|
+
*/
|
|
421
|
+
userAgent?: string
|
|
422
|
+
/**
|
|
423
|
+
* extra download header, `accept` and `user-agent` is set by default
|
|
424
|
+
*/
|
|
425
|
+
extraHeader?: Record<string, string>
|
|
426
|
+
}
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
#### Plugin
|
|
430
|
+
|
|
307
431
|
```ts
|
|
308
432
|
type ElectronWithUpdaterOptions = {
|
|
309
433
|
/**
|
|
@@ -316,7 +440,7 @@ type ElectronWithUpdaterOptions = {
|
|
|
316
440
|
*/
|
|
317
441
|
isBuild: boolean
|
|
318
442
|
/**
|
|
319
|
-
*
|
|
443
|
+
* manually setup package.json, read name, version and main
|
|
320
444
|
* ```ts
|
|
321
445
|
* import pkg from './package.json'
|
|
322
446
|
* ```
|
|
@@ -330,6 +454,14 @@ type ElectronWithUpdaterOptions = {
|
|
|
330
454
|
* whether to minify the code
|
|
331
455
|
*/
|
|
332
456
|
minify?: boolean
|
|
457
|
+
/**
|
|
458
|
+
* whether to generate bytecode
|
|
459
|
+
*
|
|
460
|
+
* **only support commonjs**
|
|
461
|
+
*
|
|
462
|
+
* only main process by default, if you want to use in preload script, please use `electronWithUpdater({ bytecode: { enablePreload: true } })` and set `sandbox: false` when creating window
|
|
463
|
+
*/
|
|
464
|
+
bytecode?: boolean | BytecodeOptions
|
|
333
465
|
/**
|
|
334
466
|
* use NotBundle() plugin in main
|
|
335
467
|
* @default true
|
|
@@ -337,8 +469,10 @@ type ElectronWithUpdaterOptions = {
|
|
|
337
469
|
useNotBundle?: boolean
|
|
338
470
|
/**
|
|
339
471
|
* Whether to log parsed options
|
|
472
|
+
*
|
|
473
|
+
* to show certificate and private keys, set `logParsedOptions: { showKeys: true }`
|
|
340
474
|
*/
|
|
341
|
-
logParsedOptions?: boolean
|
|
475
|
+
logParsedOptions?: boolean | { showKeys: boolean }
|
|
342
476
|
/**
|
|
343
477
|
* main options
|
|
344
478
|
*/
|
|
@@ -471,7 +605,7 @@ type BuildEntryOption = {
|
|
|
471
605
|
*/
|
|
472
606
|
nativeModuleEntryMap?: Record<string, string>
|
|
473
607
|
/**
|
|
474
|
-
*
|
|
608
|
+
* override options for esbuild
|
|
475
609
|
* ```ts
|
|
476
610
|
* // default options
|
|
477
611
|
* const options = {
|
|
@@ -490,6 +624,9 @@ type BuildEntryOption = {
|
|
|
490
624
|
* loader: {
|
|
491
625
|
* '.node': 'empty',
|
|
492
626
|
* },
|
|
627
|
+
* define: {
|
|
628
|
+
* __SIGNATURE_CERT__: JSON.stringify(cert),
|
|
629
|
+
* },
|
|
493
630
|
* }
|
|
494
631
|
* ```
|
|
495
632
|
*/
|
|
@@ -0,0 +1,236 @@
|
|
|
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 { basename, dirname, join } from "node:path";
|
|
11
|
+
import { release } from "node:os";
|
|
12
|
+
import { app } from "electron";
|
|
13
|
+
var is = {
|
|
14
|
+
dev: !app.isPackaged,
|
|
15
|
+
win: process.platform === "win32",
|
|
16
|
+
mac: process.platform === "darwin",
|
|
17
|
+
linux: process.platform === "linux"
|
|
18
|
+
};
|
|
19
|
+
function getPathFromAppNameAsar(...path) {
|
|
20
|
+
return is.dev ? "DEV.asar" : join(dirname(app.getAppPath()), `${electron.app.name}.asar`, ...path);
|
|
21
|
+
}
|
|
22
|
+
function getVersions() {
|
|
23
|
+
const platform = is.win ? "Windows" : is.mac ? "MacOS" : process.platform.toUpperCase();
|
|
24
|
+
return {
|
|
25
|
+
appVersion: is.dev ? app.getVersion() : readFileSync(getPathFromAppNameAsar("version"), "utf-8"),
|
|
26
|
+
entryVersion: app.getVersion(),
|
|
27
|
+
electronVersion: process.versions.electron,
|
|
28
|
+
nodeVersion: process.versions.node,
|
|
29
|
+
systemVersion: `${platform} ${release()}`
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function loadNativeModuleFromEntry(devEntryDirPath = "../../dist-entry", entryDirPath = join(app.getAppPath(), basename(devEntryDirPath))) {
|
|
33
|
+
const path = is.dev ? devEntryDirPath : entryDirPath;
|
|
34
|
+
return (moduleName) => {
|
|
35
|
+
try {
|
|
36
|
+
return __require(join(path, moduleName));
|
|
37
|
+
} catch (error) {
|
|
38
|
+
console.error("fail to load module", error);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function restartApp() {
|
|
43
|
+
app.relaunch();
|
|
44
|
+
app.quit();
|
|
45
|
+
}
|
|
46
|
+
function setAppUserModelId(id) {
|
|
47
|
+
app.setAppUserModelId(is.dev ? process.execPath : id ?? `org.${electron.app.name}`);
|
|
48
|
+
}
|
|
49
|
+
function disableHWAccForWin7() {
|
|
50
|
+
if (release().startsWith("6.1")) {
|
|
51
|
+
app.disableHardwareAcceleration();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function singleInstance(window) {
|
|
55
|
+
const result = app.requestSingleInstanceLock();
|
|
56
|
+
result ? app.on("second-instance", () => {
|
|
57
|
+
if (window) {
|
|
58
|
+
window.show();
|
|
59
|
+
if (window.isMinimized()) {
|
|
60
|
+
window.restore();
|
|
61
|
+
}
|
|
62
|
+
window.focus();
|
|
63
|
+
}
|
|
64
|
+
}) : app.quit();
|
|
65
|
+
return result;
|
|
66
|
+
}
|
|
67
|
+
function setPortableAppDataPath(dirName = "data") {
|
|
68
|
+
const portablePath = join(dirname(app.getPath("exe")), dirName);
|
|
69
|
+
if (!existsSync(portablePath)) {
|
|
70
|
+
mkdirSync(portablePath);
|
|
71
|
+
}
|
|
72
|
+
app.setPath("appData", portablePath);
|
|
73
|
+
}
|
|
74
|
+
function waitAppReady(timeout = 1e3) {
|
|
75
|
+
return app.isReady() ? Promise.resolve() : new Promise((resolve, reject) => {
|
|
76
|
+
const _ = setTimeout(() => {
|
|
77
|
+
reject(new Error("app is not ready"));
|
|
78
|
+
}, timeout);
|
|
79
|
+
app.whenReady().then(() => {
|
|
80
|
+
clearTimeout(_);
|
|
81
|
+
resolve();
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
function getPaths(entryDirName = "dist-entry") {
|
|
86
|
+
const root = join(__dirname, "..");
|
|
87
|
+
const mainDirPath = join(root, "main");
|
|
88
|
+
const preloadDirPath = join(root, "preload");
|
|
89
|
+
const rendererDirPath = join(root, "renderer");
|
|
90
|
+
const devServerURL = process.env.VITE_DEV_SERVER_URL;
|
|
91
|
+
const indexHTMLPath = join(rendererDirPath, "index.html");
|
|
92
|
+
const publicDirPath = devServerURL ? join(root, "../public") : rendererDirPath;
|
|
93
|
+
return {
|
|
94
|
+
/**
|
|
95
|
+
* @example
|
|
96
|
+
* ```ts
|
|
97
|
+
* devServerURL && win.loadURL(devServerURL)
|
|
98
|
+
* ```
|
|
99
|
+
*/
|
|
100
|
+
devServerURL,
|
|
101
|
+
/**
|
|
102
|
+
* @example
|
|
103
|
+
* ```ts
|
|
104
|
+
* win.loadFile(indexHTMLPath)
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
indexHTMLPath,
|
|
108
|
+
/**
|
|
109
|
+
* get path inside entry asar
|
|
110
|
+
* @param paths joined path
|
|
111
|
+
*/
|
|
112
|
+
getPathFromEntryAsar(...paths) {
|
|
113
|
+
return join(app.getAppPath(), entryDirName, ...paths);
|
|
114
|
+
},
|
|
115
|
+
/**
|
|
116
|
+
* get path inside `${electron.app.name}.asar/main`
|
|
117
|
+
* @param paths joined path
|
|
118
|
+
*/
|
|
119
|
+
getPathFromMain(...paths) {
|
|
120
|
+
return join(mainDirPath, ...paths);
|
|
121
|
+
},
|
|
122
|
+
/**
|
|
123
|
+
* get path inside `${electron.app.name}.asar/preload`
|
|
124
|
+
* @param paths joined path
|
|
125
|
+
*/
|
|
126
|
+
getPathFromPreload(...paths) {
|
|
127
|
+
return join(preloadDirPath, ...paths);
|
|
128
|
+
},
|
|
129
|
+
/**
|
|
130
|
+
* get path inside public dir
|
|
131
|
+
* @param paths joined path
|
|
132
|
+
*/
|
|
133
|
+
getPathFromPublic(...paths) {
|
|
134
|
+
return join(publicDirPath, ...paths);
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// src/utils/zip.ts
|
|
140
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2, rmSync, writeFileSync } from "node:fs";
|
|
141
|
+
import { brotliCompress, brotliDecompress } from "node:zlib";
|
|
142
|
+
async function unzipFile(gzipPath, targetFilePath = gzipPath.slice(0, -3)) {
|
|
143
|
+
if (!existsSync2(gzipPath)) {
|
|
144
|
+
throw new Error(`path to zipped file not exist: ${gzipPath}`);
|
|
145
|
+
}
|
|
146
|
+
const compressedBuffer = readFileSync2(gzipPath);
|
|
147
|
+
return new Promise((resolve, reject) => {
|
|
148
|
+
brotliDecompress(compressedBuffer, (err, buffer) => {
|
|
149
|
+
rmSync(gzipPath);
|
|
150
|
+
if (err) {
|
|
151
|
+
reject(err);
|
|
152
|
+
}
|
|
153
|
+
writeFileSync(targetFilePath, buffer);
|
|
154
|
+
resolve(null);
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
async function zipFile(filePath, targetFilePath = `${filePath}.gz`) {
|
|
159
|
+
if (!existsSync2(filePath)) {
|
|
160
|
+
throw new Error(`path to be zipped not exist: ${filePath}`);
|
|
161
|
+
}
|
|
162
|
+
const buffer = readFileSync2(filePath);
|
|
163
|
+
return new Promise((resolve, reject) => {
|
|
164
|
+
brotliCompress(buffer, (err, buffer2) => {
|
|
165
|
+
if (err) {
|
|
166
|
+
reject(err);
|
|
167
|
+
}
|
|
168
|
+
writeFileSync(targetFilePath, buffer2);
|
|
169
|
+
resolve(null);
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// src/utils/pure.ts
|
|
175
|
+
function parseGithubCdnURL(originRepoURL, cdnPrefix, relativeFilePath) {
|
|
176
|
+
if (!originRepoURL.startsWith("https://github.com/")) {
|
|
177
|
+
throw new Error("origin url must start with https://github.com/");
|
|
178
|
+
}
|
|
179
|
+
originRepoURL = originRepoURL.trim().replace(/\/?$/, "/").trim();
|
|
180
|
+
relativeFilePath = relativeFilePath.trim().replace(/^\/|\/?$/g, "").trim();
|
|
181
|
+
cdnPrefix = cdnPrefix.trim().replace(/^\/?|\/?$/g, "").trim();
|
|
182
|
+
return originRepoURL.replace("github.com", cdnPrefix) + relativeFilePath;
|
|
183
|
+
}
|
|
184
|
+
function handleUnexpectedErrors(callback) {
|
|
185
|
+
process.on("uncaughtException", callback);
|
|
186
|
+
process.on("unhandledRejection", callback);
|
|
187
|
+
}
|
|
188
|
+
function parseVersion(version) {
|
|
189
|
+
const semver = /^(\d+)\.(\d+)\.(\d+)(?:-([a-z0-9.-]+))?/i;
|
|
190
|
+
const match = semver.exec(version);
|
|
191
|
+
if (!match) {
|
|
192
|
+
throw new TypeError(`invalid version: ${version}`);
|
|
193
|
+
}
|
|
194
|
+
const [major, minor, patch] = match.slice(1, 4).map(Number);
|
|
195
|
+
const ret = {
|
|
196
|
+
major,
|
|
197
|
+
minor,
|
|
198
|
+
patch,
|
|
199
|
+
stage: "",
|
|
200
|
+
stageVersion: -1
|
|
201
|
+
};
|
|
202
|
+
if (match[4]) {
|
|
203
|
+
let [stage, _v] = match[4].split(".");
|
|
204
|
+
ret.stage = stage;
|
|
205
|
+
ret.stageVersion = Number(_v) || -1;
|
|
206
|
+
}
|
|
207
|
+
if (Number.isNaN(major) || Number.isNaN(minor) || Number.isNaN(patch) || Number.isNaN(ret.stageVersion)) {
|
|
208
|
+
throw new TypeError(`invalid version: ${version}`);
|
|
209
|
+
}
|
|
210
|
+
return ret;
|
|
211
|
+
}
|
|
212
|
+
function isUpdateJSON(json) {
|
|
213
|
+
const is2 = (j) => !!(j && j.minimumVersion && j.signature && j.size && j.version);
|
|
214
|
+
return is2(json) && is2(json?.beta);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
export {
|
|
218
|
+
__require,
|
|
219
|
+
is,
|
|
220
|
+
getPathFromAppNameAsar,
|
|
221
|
+
getVersions,
|
|
222
|
+
loadNativeModuleFromEntry,
|
|
223
|
+
restartApp,
|
|
224
|
+
setAppUserModelId,
|
|
225
|
+
disableHWAccForWin7,
|
|
226
|
+
singleInstance,
|
|
227
|
+
setPortableAppDataPath,
|
|
228
|
+
waitAppReady,
|
|
229
|
+
getPaths,
|
|
230
|
+
unzipFile,
|
|
231
|
+
zipFile,
|
|
232
|
+
parseGithubCdnURL,
|
|
233
|
+
handleUnexpectedErrors,
|
|
234
|
+
parseVersion,
|
|
235
|
+
isUpdateJSON
|
|
236
|
+
};
|