electron-incremental-update 1.1.0 → 1.2.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 +38 -18
- package/dist/chunk-7ET4GMTZ.js +236 -0
- package/dist/chunk-HWUYTDEF.js +236 -0
- package/dist/chunk-RQCTJY4L.js +236 -0
- package/dist/index.cjs +34 -41
- package/dist/index.d.cts +18 -27
- package/dist/index.d.ts +18 -27
- package/dist/index.js +35 -42
- package/dist/utils.cjs +4 -4
- 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 +440 -78
- package/package.json +7 -2
package/README.md
CHANGED
|
@@ -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: {
|
|
@@ -296,11 +295,19 @@ module.exports = {
|
|
|
296
295
|
|
|
297
296
|
### Bytecode protection
|
|
298
297
|
|
|
299
|
-
|
|
298
|
+
credit to [electron-vite](https://github.com/alex8088/electron-vite/blob/master/src/plugins/bytecode.ts)
|
|
299
|
+
|
|
300
|
+
```ts
|
|
301
|
+
electronWithUpdater({
|
|
302
|
+
// ...
|
|
303
|
+
bytecode: true,
|
|
304
|
+
})
|
|
305
|
+
```
|
|
300
306
|
|
|
301
|
-
|
|
307
|
+
#### Limitation
|
|
302
308
|
|
|
303
|
-
|
|
309
|
+
- only support commonjs
|
|
310
|
+
- 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
311
|
|
|
305
312
|
### Types
|
|
306
313
|
|
|
@@ -316,7 +323,7 @@ type ElectronWithUpdaterOptions = {
|
|
|
316
323
|
*/
|
|
317
324
|
isBuild: boolean
|
|
318
325
|
/**
|
|
319
|
-
*
|
|
326
|
+
* manually setup package.json, read name, version and main
|
|
320
327
|
* ```ts
|
|
321
328
|
* import pkg from './package.json'
|
|
322
329
|
* ```
|
|
@@ -330,6 +337,14 @@ type ElectronWithUpdaterOptions = {
|
|
|
330
337
|
* whether to minify the code
|
|
331
338
|
*/
|
|
332
339
|
minify?: boolean
|
|
340
|
+
/**
|
|
341
|
+
* whether to generate bytecode
|
|
342
|
+
*
|
|
343
|
+
* **only support commonjs**
|
|
344
|
+
*
|
|
345
|
+
* 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
|
|
346
|
+
*/
|
|
347
|
+
bytecode?: boolean | BytecodeOptions
|
|
333
348
|
/**
|
|
334
349
|
* use NotBundle() plugin in main
|
|
335
350
|
* @default true
|
|
@@ -337,8 +352,10 @@ type ElectronWithUpdaterOptions = {
|
|
|
337
352
|
useNotBundle?: boolean
|
|
338
353
|
/**
|
|
339
354
|
* Whether to log parsed options
|
|
355
|
+
*
|
|
356
|
+
* to show certificate and private keys, set `logParsedOptions: { showKeys: true }`
|
|
340
357
|
*/
|
|
341
|
-
logParsedOptions?: boolean
|
|
358
|
+
logParsedOptions?: boolean | { showKeys: boolean }
|
|
342
359
|
/**
|
|
343
360
|
* main options
|
|
344
361
|
*/
|
|
@@ -471,7 +488,7 @@ type BuildEntryOption = {
|
|
|
471
488
|
*/
|
|
472
489
|
nativeModuleEntryMap?: Record<string, string>
|
|
473
490
|
/**
|
|
474
|
-
*
|
|
491
|
+
* override options for esbuild
|
|
475
492
|
* ```ts
|
|
476
493
|
* // default options
|
|
477
494
|
* const options = {
|
|
@@ -490,6 +507,9 @@ type BuildEntryOption = {
|
|
|
490
507
|
* loader: {
|
|
491
508
|
* '.node': 'empty',
|
|
492
509
|
* },
|
|
510
|
+
* define: {
|
|
511
|
+
* __SIGNATURE_CERT__: JSON.stringify(cert),
|
|
512
|
+
* },
|
|
493
513
|
* }
|
|
494
514
|
* ```
|
|
495
515
|
*/
|
|
@@ -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
|
+
};
|
|
@@ -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()), `${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.${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 `${app.name}.asar/main`
|
|
117
|
+
* @param paths joined path
|
|
118
|
+
*/
|
|
119
|
+
getPathFromMain(...paths) {
|
|
120
|
+
return join(mainDirPath, ...paths);
|
|
121
|
+
},
|
|
122
|
+
/**
|
|
123
|
+
* get path inside `${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
|
+
};
|