electron-incremental-update 2.0.0-beta.9 → 2.0.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 +307 -198
- package/dist/chunk-IABBXJFB.js +87 -0
- package/dist/{chunk-72ZAJ7AF.js → chunk-RCRKUKFX.js} +1 -1
- package/dist/index.cjs +91 -71
- package/dist/index.d.cts +64 -80
- package/dist/index.d.ts +64 -80
- package/dist/index.js +88 -70
- package/dist/provider.cjs +72 -52
- package/dist/provider.d.cts +47 -30
- package/dist/provider.d.ts +47 -30
- package/dist/provider.js +72 -53
- package/dist/{types-D7OK98ln.d.ts → types-BLdN9rkY.d.ts} +20 -27
- package/dist/{types-mEfMjnlV.d.cts → types-DkCn03M3.d.cts} +20 -27
- package/dist/utils.cjs +25 -17
- package/dist/utils.d.cts +37 -16
- package/dist/utils.d.ts +37 -16
- package/dist/utils.js +2 -2
- package/dist/version-BYVQ367i.d.cts +62 -0
- package/dist/version-BYVQ367i.d.ts +62 -0
- package/dist/vite.d.ts +58 -94
- package/dist/vite.js +57 -39
- package/dist/{zip-DPF5IFkK.d.ts → zip-rm9ED9nU.d.cts} +23 -0
- package/dist/{zip-DPF5IFkK.d.cts → zip-rm9ED9nU.d.ts} +23 -0
- package/package.json +10 -7
- package/dist/chunk-4MH6ZXCY.js +0 -81
- package/dist/version-DgfjJQUx.d.cts +0 -27
- package/dist/version-DgfjJQUx.d.ts +0 -27
package/README.md
CHANGED
|
@@ -1,41 +1,45 @@
|
|
|
1
|
-
## Electron Incremental
|
|
1
|
+
## Electron Incremental Update
|
|
2
2
|
|
|
3
|
-
This project is
|
|
3
|
+
This project is built on top of [vite-plugin-electron](https://github.com/electron-vite/vite-plugin-electron), offers a lightweight update solution for Electron applications without using native executables.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
### Key Features
|
|
6
6
|
|
|
7
|
-
The
|
|
7
|
+
The solution includes a Vite plugin, a startup entry function, an `Updater` class, and a set of utilities for Electron.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
It use 2 asar file structure for updates:
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
- `app.asar`: The application entry, loads the `${electron.app.name}.asar` and initializes the updater on startup
|
|
12
|
+
- `${electron.app.name}.asar`: The package that contains main / preload / renderer process code
|
|
12
13
|
|
|
13
|
-
|
|
14
|
+
### Update Steps
|
|
14
15
|
|
|
15
|
-
|
|
16
|
+
1. Check update from remote server
|
|
17
|
+
2. If update available, download the update asar, verify by presigned RSA + Signature and write to disk
|
|
18
|
+
3. Quit and restart the app
|
|
19
|
+
4. Replace the old `${electron.app.name}.asar` on startup and load the new one
|
|
16
20
|
|
|
17
|
-
|
|
21
|
+
### Other Features
|
|
18
22
|
|
|
19
|
-
|
|
23
|
+
- Update size reduction: All **native modules** should be packaged into `app.asar` to reduce `${electron.app.name}.asar` file size, [see usage](#use-native-modules)
|
|
24
|
+
- Bytecode protection: Use V8 cache to protect source code, [see details](#bytecode-protection)
|
|
20
25
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
26
|
+
## Getting Started
|
|
27
|
+
|
|
28
|
+
### Install
|
|
29
|
+
|
|
30
|
+
```sh
|
|
31
|
+
npm install -D electron-incremental-update
|
|
24
32
|
```
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
yarn add -D vite-plugin-electron electron-incremental-update
|
|
33
|
+
```sh
|
|
34
|
+
yarn add -D electron-incremental-update
|
|
28
35
|
```
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
pnpm add -D vite-plugin-electron electron-incremental-update
|
|
36
|
+
```sh
|
|
37
|
+
pnpm add -D electron-incremental-update
|
|
32
38
|
```
|
|
33
39
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
### Project structure
|
|
40
|
+
### Project Structure
|
|
37
41
|
|
|
38
|
-
|
|
42
|
+
Base on [electron-vite-vue](https://github.com/electron-vite/electron-vite-vue)
|
|
39
43
|
|
|
40
44
|
```
|
|
41
45
|
electron
|
|
@@ -50,37 +54,43 @@ src
|
|
|
50
54
|
└── ...
|
|
51
55
|
```
|
|
52
56
|
|
|
53
|
-
### Setup
|
|
57
|
+
### Setup Entry
|
|
54
58
|
|
|
55
|
-
|
|
59
|
+
The entry is used to load the application and initialize the `Updater`
|
|
60
|
+
|
|
61
|
+
`Updater` use the `provider` to check and download the update. The built-in `GithubProvider` is based on `BaseProvider`, which implements the `IProvider` interface (see [types](#provider)). And the `provider` is optional, you can setup later
|
|
62
|
+
|
|
63
|
+
in `electron/entry.ts`
|
|
56
64
|
|
|
57
65
|
```ts
|
|
58
|
-
import {
|
|
59
|
-
import {
|
|
60
|
-
import { repository } from '../package.json'
|
|
66
|
+
import { createElectronApp } from 'electron-incremental-update'
|
|
67
|
+
import { GitHubProvider } from 'electron-incremental-update/provider'
|
|
61
68
|
|
|
62
|
-
|
|
63
|
-
// can be updater option or function that return updater
|
|
69
|
+
createElectronApp({
|
|
64
70
|
updater: {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
71
|
+
// optinal, you can setup later
|
|
72
|
+
provider: new GitHubProvider({
|
|
73
|
+
username: 'yourname',
|
|
74
|
+
repo: 'electron',
|
|
75
|
+
}),
|
|
76
|
+
},
|
|
77
|
+
beforeStart(mainFilePath, logger) {
|
|
78
|
+
logger?.debug(mainFilePath)
|
|
70
79
|
},
|
|
71
|
-
onStart: console.log
|
|
72
80
|
})
|
|
73
81
|
```
|
|
74
82
|
|
|
75
|
-
- [some CDN resources](https://github.com/XIU2/UserScript/blob/master/GithubEnhanced-High-Speed-Download.user.js#L34)
|
|
83
|
+
- [some Github CDN resources](https://github.com/XIU2/UserScript/blob/master/GithubEnhanced-High-Speed-Download.user.js#L34)
|
|
76
84
|
|
|
77
85
|
### Setup `vite.config.ts`
|
|
78
86
|
|
|
79
|
-
|
|
87
|
+
The plugin config, `main` and `preload` parts are reference from [electron-vite-vue](https://github.com/electron-vite/electron-vite-vue)
|
|
80
88
|
|
|
81
89
|
- certificate will read from `process.env.UPDATER_CERT` first, if absend, read config
|
|
82
90
|
- privatekey will read from `process.env.UPDATER_PK` first, if absend, read config
|
|
83
91
|
|
|
92
|
+
See all config in [types](#plugin)
|
|
93
|
+
|
|
84
94
|
in `vite.config.mts`
|
|
85
95
|
|
|
86
96
|
```ts
|
|
@@ -126,7 +136,7 @@ export default defineConfig(async ({ command }) => {
|
|
|
126
136
|
}
|
|
127
137
|
```
|
|
128
138
|
|
|
129
|
-
### Config electron-builder
|
|
139
|
+
### Config `electron-builder`
|
|
130
140
|
|
|
131
141
|
```js
|
|
132
142
|
const { name } = require('./package.json')
|
|
@@ -159,24 +169,13 @@ module.exports = {
|
|
|
159
169
|
|
|
160
170
|
## Usage
|
|
161
171
|
|
|
162
|
-
### Use
|
|
172
|
+
### Use In Main Process
|
|
163
173
|
|
|
164
|
-
|
|
174
|
+
In most cases, you should also setup the `UpdateProvider` before updating, unless you setup params when calling `checkUpdate` or `downloadUpdate`.
|
|
165
175
|
|
|
166
|
-
|
|
176
|
+
The update steps are similar to [electron-updater](https://github.com/electron-userland/electron-updater) and have same methods and events on `Updater`
|
|
167
177
|
|
|
168
|
-
in
|
|
169
|
-
|
|
170
|
-
```ts
|
|
171
|
-
initApp({
|
|
172
|
-
updater: {
|
|
173
|
-
overrideFunctions: {
|
|
174
|
-
downloadJSON: (url: string, headers: Record<string, any>) => {}
|
|
175
|
-
// ...
|
|
176
|
-
}
|
|
177
|
-
},
|
|
178
|
-
})
|
|
179
|
-
```
|
|
178
|
+
**NOTE: There should only one function and should be default export in the main index file**
|
|
180
179
|
|
|
181
180
|
in `electron/main/index.ts`
|
|
182
181
|
|
|
@@ -188,45 +187,56 @@ import { app } from 'electron'
|
|
|
188
187
|
export default startupWithUpdater((updater) => {
|
|
189
188
|
await app.whenReady()
|
|
190
189
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
190
|
+
console.table({
|
|
191
|
+
[`${app.name}.asar path:`]: getPathFromAppNameAsar(),
|
|
192
|
+
'app version:': getAppVersion(),
|
|
193
|
+
'entry (installer) version:': getEntryVersion(),
|
|
194
|
+
'electron version:': process.versions.electron,
|
|
195
|
+
})
|
|
196
196
|
|
|
197
197
|
updater.onDownloading = ({ percent }) => {
|
|
198
198
|
console.log(percent)
|
|
199
199
|
}
|
|
200
200
|
updater.logger = console
|
|
201
201
|
updater.receiveBeta = true
|
|
202
|
+
// setup provider later
|
|
203
|
+
updater.provider = new GitHubProvider({
|
|
204
|
+
user: 'yourname',
|
|
205
|
+
repo: 'electron',
|
|
206
|
+
// setup url handler
|
|
207
|
+
urlHandler: (url) => {
|
|
208
|
+
url.hostname = 'mirror.ghproxy.com'
|
|
209
|
+
url.pathname = `https://github.com${url.pathname}`
|
|
210
|
+
return url
|
|
211
|
+
}
|
|
212
|
+
})
|
|
202
213
|
|
|
203
|
-
updater.
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
type: 'info',
|
|
212
|
-
buttons: ['Download', 'Later'],
|
|
213
|
-
message: 'Application update available!',
|
|
214
|
-
})
|
|
215
|
-
if (response !== 0) {
|
|
216
|
-
return
|
|
217
|
-
}
|
|
218
|
-
const downloadResult = await updater.download()
|
|
219
|
-
if (downloadResult) {
|
|
220
|
-
updater.quitAndInstall()
|
|
221
|
-
}
|
|
214
|
+
updater.on('update-available', async ({ version }) => {
|
|
215
|
+
const { response } = await dialog.showMessageBox({
|
|
216
|
+
type: 'info',
|
|
217
|
+
buttons: ['Download', 'Later'],
|
|
218
|
+
message: `v${version} update available!`,
|
|
219
|
+
})
|
|
220
|
+
if (response !== 0) {
|
|
221
|
+
return
|
|
222
222
|
}
|
|
223
|
+
await updater.downloadUpdate()
|
|
224
|
+
})
|
|
225
|
+
updater.on('update-not-available', (reason, info) => console.log(reason, info))
|
|
226
|
+
updater.on('download-progress', (data) => {
|
|
227
|
+
console.log(data)
|
|
228
|
+
main.send(BrowserWindow.getAllWindows()[0], 'msg', data)
|
|
229
|
+
})
|
|
230
|
+
updater.on('update-downloaded', () => {
|
|
231
|
+
updater.quitAndInstall()
|
|
223
232
|
})
|
|
233
|
+
updater.checkForUpdates()
|
|
224
234
|
})
|
|
225
235
|
```
|
|
226
236
|
|
|
227
|
-
### Use
|
|
237
|
+
### Use Native Modules
|
|
228
238
|
|
|
229
|
-
|
|
239
|
+
To reduce production size, it is recommended that all the **native modules** should be set as `dependency` in `package.json` and other packages should be set as `devDependencies`. Also, `electron-rebuild` only check dependencies inside `dependency` field.
|
|
230
240
|
|
|
231
241
|
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.
|
|
232
242
|
|
|
@@ -235,7 +245,7 @@ Luckily, `Esbuild` can bundle all the dependencies. Just follow the steps:
|
|
|
235
245
|
1. setup `nativeModuleEntryMap` option
|
|
236
246
|
2. Manually copy the native binaries in `postBuild` callback
|
|
237
247
|
3. Exclude all the dependencies in `electron-builder`'s config
|
|
238
|
-
4. call the native functions with `
|
|
248
|
+
4. call the native functions with `requireNative` in your code
|
|
239
249
|
|
|
240
250
|
#### Example
|
|
241
251
|
|
|
@@ -298,9 +308,7 @@ export function test(): void {
|
|
|
298
308
|
in `electron/main/service.ts`
|
|
299
309
|
|
|
300
310
|
```ts
|
|
301
|
-
import {
|
|
302
|
-
|
|
303
|
-
const requireNative = loadNativeModuleFromEntry()
|
|
311
|
+
import { requireNative } from 'electron-incremental-update/utils'
|
|
304
312
|
|
|
305
313
|
requireNative<typeof import('../native/db')>('db').test()
|
|
306
314
|
```
|
|
@@ -311,131 +319,201 @@ in `electron-builder.config.js`
|
|
|
311
319
|
module.exports = {
|
|
312
320
|
files: [
|
|
313
321
|
'dist-entry',
|
|
314
|
-
// exclude dependencies in electron-builder config
|
|
322
|
+
// exclude all dependencies in electron-builder config
|
|
315
323
|
'!node_modules/**',
|
|
316
324
|
]
|
|
317
325
|
}
|
|
318
326
|
```
|
|
319
327
|
|
|
320
|
-
### Bytecode
|
|
321
|
-
|
|
322
|
-
From v1.2, the vite plugin is able to generate bytecode to protect your application.
|
|
323
|
-
|
|
324
|
-
It will automatically protect your `SIGNATURE_CERT` by default.
|
|
328
|
+
### Bytecode Protection
|
|
325
329
|
|
|
326
|
-
|
|
330
|
+
Use V8 cache to protect the source code
|
|
327
331
|
|
|
328
332
|
```ts
|
|
329
333
|
electronWithUpdater({
|
|
330
334
|
// ...
|
|
331
|
-
bytecode: true,
|
|
335
|
+
bytecode: true, // or options
|
|
332
336
|
})
|
|
333
337
|
```
|
|
334
338
|
|
|
339
|
+
#### Benifits
|
|
340
|
+
|
|
341
|
+
https://electron-vite.org/guide/source-code-protection
|
|
342
|
+
|
|
343
|
+
- Improve the string protection (see [original issue](https://github.com/alex8088/electron-vite/issues/552)) and protect all strings by default
|
|
344
|
+
- Minification is allowed
|
|
345
|
+
|
|
335
346
|
#### Limitation
|
|
336
347
|
|
|
337
|
-
-
|
|
338
|
-
-
|
|
348
|
+
- Only support commonjs
|
|
349
|
+
- 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
|
|
339
350
|
|
|
340
351
|
### Types
|
|
341
352
|
|
|
342
|
-
####
|
|
353
|
+
#### Entry
|
|
343
354
|
|
|
344
355
|
```ts
|
|
345
|
-
export interface
|
|
356
|
+
export interface AppOption {
|
|
346
357
|
/**
|
|
347
|
-
*
|
|
348
|
-
*
|
|
358
|
+
* Path to index file that make {@link startupWithUpdater} as default export
|
|
359
|
+
*
|
|
360
|
+
* Generate from plugin configuration by default
|
|
349
361
|
*/
|
|
350
|
-
|
|
362
|
+
mainPath?: string
|
|
351
363
|
/**
|
|
352
|
-
*
|
|
353
|
-
*
|
|
354
|
-
* you can use the `repository` in `package.json`
|
|
355
|
-
*
|
|
356
|
-
* if `updateJsonURL` or `releaseAsarURL` are absent,
|
|
357
|
-
* `repository` will be used to determine the url
|
|
364
|
+
* Updater options
|
|
358
365
|
*/
|
|
359
|
-
|
|
366
|
+
updater?: (() => Promisable<Updater>) | UpdaterOption
|
|
360
367
|
/**
|
|
361
|
-
*
|
|
362
|
-
* @default `${repository.replace('github.com', 'raw.githubusercontent.com')}/master/version.json`
|
|
363
|
-
* @throws if `updateJsonURL` and `repository` are all not set
|
|
368
|
+
* Hooks on rename temp asar path to `${app.name}.asar`
|
|
364
369
|
*/
|
|
365
|
-
|
|
370
|
+
onInstall?: OnInstallFunction
|
|
366
371
|
/**
|
|
367
|
-
*
|
|
368
|
-
* @
|
|
369
|
-
* @
|
|
372
|
+
* Hooks before app startup
|
|
373
|
+
* @param mainFilePath main file path of `${app.name}.asar`
|
|
374
|
+
* @param logger logger
|
|
370
375
|
*/
|
|
371
|
-
|
|
376
|
+
beforeStart?: (mainFilePath: string, logger?: Logger) => Promisable<void>
|
|
372
377
|
/**
|
|
373
|
-
*
|
|
378
|
+
* Hooks on app startup error
|
|
379
|
+
* @param err installing or startup error
|
|
380
|
+
* @param logger logger
|
|
381
|
+
*/
|
|
382
|
+
onStartError?: (err: unknown, logger?: Logger) => void
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* Hooks on rename temp asar path to `${app.name}.asar`
|
|
386
|
+
* @param install `() => renameSync(tempAsarPath, appNameAsarPath)`
|
|
387
|
+
* @param tempAsarPath temp(updated) asar path
|
|
388
|
+
* @param appNameAsarPath `${app.name}.asar` path
|
|
389
|
+
* @param logger logger
|
|
390
|
+
* @default install(); logger.info('update success!')
|
|
391
|
+
*/
|
|
392
|
+
type OnInstallFunction = (
|
|
393
|
+
install: VoidFunction,
|
|
394
|
+
tempAsarPath: string,
|
|
395
|
+
appNameAsarPath: string,
|
|
396
|
+
logger?: Logger
|
|
397
|
+
) => Promisable<void>
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
#### Updater
|
|
401
|
+
|
|
402
|
+
```ts
|
|
403
|
+
export interface UpdaterOption {
|
|
404
|
+
/**
|
|
405
|
+
* Update provider
|
|
406
|
+
*
|
|
407
|
+
* If you will not setup `UpdateJSON` or `Buffer` in params when checking update or download, this option is **required**
|
|
408
|
+
*/
|
|
409
|
+
provider?: IProvider
|
|
410
|
+
/**
|
|
411
|
+
* Certifaction key of signature, which will be auto generated by plugin,
|
|
412
|
+
* generate by `selfsigned` if not set
|
|
413
|
+
*/
|
|
414
|
+
SIGNATURE_CERT?: string
|
|
415
|
+
/**
|
|
416
|
+
* Whether to receive beta update
|
|
374
417
|
*/
|
|
375
418
|
receiveBeta?: boolean
|
|
376
|
-
|
|
377
|
-
|
|
419
|
+
/**
|
|
420
|
+
* Updater logger
|
|
421
|
+
*/
|
|
422
|
+
logger?: Logger
|
|
378
423
|
}
|
|
424
|
+
|
|
379
425
|
export type Logger = {
|
|
380
426
|
info: (msg: string) => void
|
|
381
427
|
debug: (msg: string) => void
|
|
382
428
|
warn: (msg: string) => void
|
|
383
429
|
error: (msg: string, e?: Error) => void
|
|
384
430
|
}
|
|
431
|
+
```
|
|
432
|
+
#### Provider
|
|
433
|
+
|
|
434
|
+
```ts
|
|
435
|
+
export type OnDownloading = (progress: DownloadingInfo) => void
|
|
385
436
|
|
|
386
|
-
export
|
|
437
|
+
export interface DownloadingInfo {
|
|
387
438
|
/**
|
|
388
|
-
*
|
|
389
|
-
* @param version1 old version string
|
|
390
|
-
* @param version2 new version string
|
|
391
|
-
* @returns if version1 < version2
|
|
439
|
+
* Download buffer delta
|
|
392
440
|
*/
|
|
393
|
-
|
|
441
|
+
delta: number
|
|
394
442
|
/**
|
|
395
|
-
*
|
|
396
|
-
*
|
|
397
|
-
*
|
|
398
|
-
|
|
399
|
-
|
|
443
|
+
* Downloaded percent, 0 ~ 100
|
|
444
|
+
*
|
|
445
|
+
* If no `Content-Length` header, will be -1
|
|
446
|
+
*/
|
|
447
|
+
percent: number
|
|
448
|
+
/**
|
|
449
|
+
* Total size
|
|
450
|
+
*
|
|
451
|
+
* If not `Content-Length` header, will be -1
|
|
400
452
|
*/
|
|
401
|
-
|
|
453
|
+
total: number
|
|
402
454
|
/**
|
|
403
|
-
*
|
|
404
|
-
* @param url download url
|
|
405
|
-
* @param header download header
|
|
406
|
-
* @returns `UpdateJSON`
|
|
455
|
+
* Downloaded size
|
|
407
456
|
*/
|
|
408
|
-
|
|
457
|
+
transferred: number
|
|
409
458
|
/**
|
|
410
|
-
*
|
|
411
|
-
* @param url download url
|
|
412
|
-
* @param headers download header
|
|
413
|
-
* @param total precaculated file total size
|
|
414
|
-
* @param onDownloading on downloading callback
|
|
415
|
-
* @returns `Buffer`
|
|
459
|
+
* Download speed, bytes per second
|
|
416
460
|
*/
|
|
417
|
-
|
|
461
|
+
bps: number
|
|
418
462
|
}
|
|
419
463
|
|
|
420
|
-
export
|
|
464
|
+
export interface IProvider {
|
|
421
465
|
/**
|
|
422
|
-
*
|
|
423
|
-
* @default 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36'
|
|
466
|
+
* Provider name
|
|
424
467
|
*/
|
|
425
|
-
|
|
468
|
+
name: string
|
|
426
469
|
/**
|
|
427
|
-
*
|
|
470
|
+
* Download update json
|
|
471
|
+
* @param versionPath parsed version path in project
|
|
472
|
+
* @param signal abort signal
|
|
428
473
|
*/
|
|
429
|
-
|
|
474
|
+
downloadJSON: (versionPath: string, signal: AbortSignal) => Promise<UpdateJSON>
|
|
475
|
+
/**
|
|
476
|
+
* Download update asar
|
|
477
|
+
* @param name app name
|
|
478
|
+
* @param updateInfo existing update info
|
|
479
|
+
* @param signal abort signal
|
|
480
|
+
* @param onDownloading hook for on downloading
|
|
481
|
+
*/
|
|
482
|
+
downloadAsar: (
|
|
483
|
+
name: string,
|
|
484
|
+
updateInfo: UpdateInfo,
|
|
485
|
+
signal: AbortSignal,
|
|
486
|
+
onDownloading?: (info: DownloadingInfo) => void
|
|
487
|
+
) => Promise<Buffer>
|
|
488
|
+
/**
|
|
489
|
+
* Check the old version is less than new version
|
|
490
|
+
* @param oldVer old version string
|
|
491
|
+
* @param newVer new version string
|
|
492
|
+
*/
|
|
493
|
+
isLowerVersion: (oldVer: string, newVer: string) => boolean
|
|
494
|
+
/**
|
|
495
|
+
* Function to decompress file using brotli
|
|
496
|
+
* @param buffer compressed file buffer
|
|
497
|
+
*/
|
|
498
|
+
unzipFile: (buffer: Buffer) => Promise<Buffer>
|
|
499
|
+
/**
|
|
500
|
+
* Verify asar signature,
|
|
501
|
+
* if signature is valid, returns the version, otherwise returns `undefined`
|
|
502
|
+
* @param buffer file buffer
|
|
503
|
+
* @param version target version
|
|
504
|
+
* @param signature signature
|
|
505
|
+
* @param cert certificate
|
|
506
|
+
*/
|
|
507
|
+
verifySignaure: (buffer: Buffer, version: string, signature: string, cert: string) => Promisable<boolean>
|
|
430
508
|
}
|
|
431
509
|
```
|
|
432
510
|
|
|
433
511
|
#### Plugin
|
|
434
512
|
|
|
435
513
|
```ts
|
|
436
|
-
|
|
514
|
+
export interface ElectronWithUpdaterOptions {
|
|
437
515
|
/**
|
|
438
|
-
*
|
|
516
|
+
* Whether is in build mode
|
|
439
517
|
* ```ts
|
|
440
518
|
* export default defineConfig(({ command }) => {
|
|
441
519
|
* const isBuild = command === 'build'
|
|
@@ -444,65 +522,77 @@ type ElectronWithUpdaterOptions = {
|
|
|
444
522
|
*/
|
|
445
523
|
isBuild: boolean
|
|
446
524
|
/**
|
|
447
|
-
*
|
|
525
|
+
* Manually setup package.json, read name, version and main,
|
|
526
|
+
* use `local-pkg` of `loadPackageJSON()` to load package.json by default
|
|
448
527
|
* ```ts
|
|
449
528
|
* import pkg from './package.json'
|
|
450
529
|
* ```
|
|
451
530
|
*/
|
|
452
531
|
pkg?: PKG
|
|
453
532
|
/**
|
|
454
|
-
*
|
|
533
|
+
* Whether to generate sourcemap
|
|
534
|
+
* @default !isBuild
|
|
455
535
|
*/
|
|
456
536
|
sourcemap?: boolean
|
|
457
537
|
/**
|
|
458
|
-
*
|
|
538
|
+
* Whether to minify the code
|
|
539
|
+
* @default isBuild
|
|
459
540
|
*/
|
|
460
541
|
minify?: boolean
|
|
461
542
|
/**
|
|
462
|
-
*
|
|
543
|
+
* Whether to generate bytecode
|
|
463
544
|
*
|
|
464
|
-
* **
|
|
545
|
+
* **Only support CommonJS**
|
|
465
546
|
*
|
|
466
|
-
*
|
|
547
|
+
* 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
|
|
467
548
|
*/
|
|
468
549
|
bytecode?: boolean | BytecodeOptions
|
|
469
550
|
/**
|
|
470
|
-
*
|
|
551
|
+
* Use `NotBundle()` plugin in main
|
|
471
552
|
* @default true
|
|
472
553
|
*/
|
|
473
554
|
useNotBundle?: boolean
|
|
555
|
+
/**
|
|
556
|
+
* Whether to generate version json
|
|
557
|
+
* @default isCI
|
|
558
|
+
*/
|
|
559
|
+
buildVersionJson?: boolean
|
|
474
560
|
/**
|
|
475
561
|
* Whether to log parsed options
|
|
476
562
|
*
|
|
477
|
-
*
|
|
563
|
+
* To show certificate and private keys, set `logParsedOptions: { showKeys: true }`
|
|
478
564
|
*/
|
|
479
565
|
logParsedOptions?: boolean | { showKeys: boolean }
|
|
480
566
|
/**
|
|
481
|
-
*
|
|
567
|
+
* Main process options
|
|
568
|
+
*
|
|
569
|
+
* To change output directories, use `options.updater.paths.electronDistPath` instead
|
|
482
570
|
*/
|
|
483
|
-
main: MakeRequiredAndReplaceKey<ElectronSimpleOptions['main'], 'entry', 'files'>
|
|
571
|
+
main: MakeRequiredAndReplaceKey<ElectronSimpleOptions['main'], 'entry', 'files'> & ExcludeOutputDirOptions
|
|
484
572
|
/**
|
|
485
|
-
*
|
|
573
|
+
* Preload process options
|
|
574
|
+
*
|
|
575
|
+
* To change output directories, use `options.updater.paths.electronDistPath` instead
|
|
486
576
|
*/
|
|
487
|
-
preload: MakeRequiredAndReplaceKey<Exclude<ElectronSimpleOptions['preload'], undefined>, 'input', 'files'>
|
|
577
|
+
preload: MakeRequiredAndReplaceKey<Exclude<ElectronSimpleOptions['preload'], undefined>, 'input', 'files'> & ExcludeOutputDirOptions
|
|
488
578
|
/**
|
|
489
|
-
*
|
|
579
|
+
* Updater options
|
|
490
580
|
*/
|
|
491
581
|
updater?: ElectronUpdaterOptions
|
|
492
582
|
}
|
|
493
583
|
|
|
494
|
-
|
|
584
|
+
export interface ElectronUpdaterOptions {
|
|
495
585
|
/**
|
|
496
|
-
*
|
|
586
|
+
* Minimum version of entry
|
|
497
587
|
* @default '0.0.0'
|
|
498
588
|
*/
|
|
499
589
|
minimumVersion?: string
|
|
500
590
|
/**
|
|
501
|
-
*
|
|
591
|
+
* Options for entry (app.asar)
|
|
502
592
|
*/
|
|
503
593
|
entry?: BuildEntryOption
|
|
504
594
|
/**
|
|
505
|
-
* paths
|
|
595
|
+
* Options for paths
|
|
506
596
|
*/
|
|
507
597
|
paths?: {
|
|
508
598
|
/**
|
|
@@ -536,23 +626,23 @@ type ElectronUpdaterOptions = {
|
|
|
536
626
|
*/
|
|
537
627
|
keys?: {
|
|
538
628
|
/**
|
|
539
|
-
*
|
|
540
|
-
*
|
|
629
|
+
* Path to the pem file that contains private key
|
|
630
|
+
* If not ended with .pem, it will be appended
|
|
541
631
|
*
|
|
542
|
-
* **
|
|
632
|
+
* **If `UPDATER_PK` is set, will read it instead of read from `privateKeyPath`**
|
|
543
633
|
* @default 'keys/private.pem'
|
|
544
634
|
*/
|
|
545
635
|
privateKeyPath?: string
|
|
546
636
|
/**
|
|
547
|
-
*
|
|
548
|
-
*
|
|
637
|
+
* Path to the pem file that contains public key
|
|
638
|
+
* If not ended with .pem, it will be appended
|
|
549
639
|
*
|
|
550
|
-
* **
|
|
640
|
+
* **If `UPDATER_CERT` is set, will read it instead of read from `certPath`**
|
|
551
641
|
* @default 'keys/cert.pem'
|
|
552
642
|
*/
|
|
553
643
|
certPath?: string
|
|
554
644
|
/**
|
|
555
|
-
*
|
|
645
|
+
* Length of the key
|
|
556
646
|
* @default 2048
|
|
557
647
|
*/
|
|
558
648
|
keyLength?: number
|
|
@@ -563,45 +653,44 @@ type ElectronUpdaterOptions = {
|
|
|
563
653
|
*/
|
|
564
654
|
certInfo?: {
|
|
565
655
|
/**
|
|
566
|
-
*
|
|
656
|
+
* The subject of the certificate
|
|
567
657
|
*
|
|
568
658
|
* @default { commonName: `${app.name}`, organizationName: `org.${app.name}` }
|
|
569
659
|
*/
|
|
570
660
|
subject?: DistinguishedName
|
|
571
661
|
/**
|
|
572
|
-
*
|
|
662
|
+
* Expire days of the certificate
|
|
573
663
|
*
|
|
574
664
|
* @default 3650
|
|
575
665
|
*/
|
|
576
666
|
days?: number
|
|
577
667
|
}
|
|
578
|
-
overrideGenerator?: GeneratorOverrideFunctions
|
|
579
668
|
}
|
|
669
|
+
overrideGenerator?: GeneratorOverrideFunctions
|
|
580
670
|
}
|
|
581
671
|
|
|
582
|
-
|
|
672
|
+
export interface BuildEntryOption {
|
|
583
673
|
/**
|
|
584
|
-
*
|
|
674
|
+
* Override to minify on entry
|
|
585
675
|
* @default isBuild
|
|
586
676
|
*/
|
|
587
677
|
minify?: boolean
|
|
588
678
|
/**
|
|
589
|
-
*
|
|
590
|
-
* @default isBuild
|
|
679
|
+
* Override to generate sourcemap on entry
|
|
591
680
|
*/
|
|
592
681
|
sourcemap?: boolean
|
|
593
682
|
/**
|
|
594
|
-
*
|
|
683
|
+
* Path to app entry output file
|
|
595
684
|
* @default 'dist-entry'
|
|
596
685
|
*/
|
|
597
686
|
entryOutputDirPath?: string
|
|
598
687
|
/**
|
|
599
|
-
*
|
|
688
|
+
* Path to app entry file
|
|
600
689
|
* @default 'electron/entry.ts'
|
|
601
690
|
*/
|
|
602
691
|
appEntryPath?: string
|
|
603
692
|
/**
|
|
604
|
-
*
|
|
693
|
+
* Esbuild path map of native modules in entry directory
|
|
605
694
|
*
|
|
606
695
|
* @default {}
|
|
607
696
|
* @example
|
|
@@ -609,7 +698,7 @@ type BuildEntryOption = {
|
|
|
609
698
|
*/
|
|
610
699
|
nativeModuleEntryMap?: Record<string, string>
|
|
611
700
|
/**
|
|
612
|
-
*
|
|
701
|
+
* Custom options for esbuild
|
|
613
702
|
* ```ts
|
|
614
703
|
* // default options
|
|
615
704
|
* const options = {
|
|
@@ -628,34 +717,32 @@ type BuildEntryOption = {
|
|
|
628
717
|
* loader: {
|
|
629
718
|
* '.node': 'empty',
|
|
630
719
|
* },
|
|
631
|
-
* define
|
|
632
|
-
* __SIGNATURE_CERT__: JSON.stringify(cert),
|
|
633
|
-
* },
|
|
720
|
+
* define,
|
|
634
721
|
* }
|
|
635
722
|
* ```
|
|
636
723
|
*/
|
|
637
724
|
overrideEsbuildOptions?: BuildOptions
|
|
638
725
|
/**
|
|
639
|
-
*
|
|
726
|
+
* Resolve extra files on startup, such as `.node`
|
|
640
727
|
* @remark won't trigger will reload
|
|
641
728
|
*/
|
|
642
729
|
postBuild?: (args: {
|
|
643
730
|
/**
|
|
644
|
-
*
|
|
731
|
+
* Get path from `entryOutputDirPath`
|
|
645
732
|
*/
|
|
646
733
|
getPathFromEntryOutputDir: (...paths: string[]) => string
|
|
647
734
|
/**
|
|
648
|
-
*
|
|
735
|
+
* Check exist and copy file to `entryOutputDirPath`
|
|
649
736
|
*
|
|
650
|
-
*
|
|
737
|
+
* If `to` absent, set to `basename(from)`
|
|
651
738
|
*
|
|
652
|
-
*
|
|
739
|
+
* If `skipIfExist` absent, skip copy if `to` exist
|
|
653
740
|
*/
|
|
654
741
|
copyToEntryOutputDir: (options: {
|
|
655
742
|
from: string
|
|
656
743
|
to?: string
|
|
657
744
|
/**
|
|
658
|
-
*
|
|
745
|
+
* Skip copy if `to` exist
|
|
659
746
|
* @default true
|
|
660
747
|
*/
|
|
661
748
|
skipIfExist?: boolean
|
|
@@ -663,17 +750,22 @@ type BuildEntryOption = {
|
|
|
663
750
|
}) => Promisable<void>
|
|
664
751
|
}
|
|
665
752
|
|
|
666
|
-
|
|
753
|
+
export interface GeneratorOverrideFunctions {
|
|
667
754
|
/**
|
|
668
|
-
*
|
|
755
|
+
* Custom signature generate function
|
|
669
756
|
* @param buffer file buffer
|
|
670
757
|
* @param privateKey private key
|
|
671
758
|
* @param cert certificate string, **EOL must be '\n'**
|
|
672
759
|
* @param version current version
|
|
673
760
|
*/
|
|
674
|
-
generateSignature?: (
|
|
761
|
+
generateSignature?: (
|
|
762
|
+
buffer: Buffer,
|
|
763
|
+
privateKey: string,
|
|
764
|
+
cert: string,
|
|
765
|
+
version: string
|
|
766
|
+
) => Promisable<string>
|
|
675
767
|
/**
|
|
676
|
-
*
|
|
768
|
+
* Custom generate version json function
|
|
677
769
|
* @param existingJson The existing JSON object.
|
|
678
770
|
* @param buffer file buffer
|
|
679
771
|
* @param signature generated signature
|
|
@@ -681,10 +773,27 @@ type GeneratorOverrideFunctions = {
|
|
|
681
773
|
* @param minVersion The minimum version
|
|
682
774
|
* @returns The updated version json
|
|
683
775
|
*/
|
|
684
|
-
generateVersionJson?: (
|
|
776
|
+
generateVersionJson?: (
|
|
777
|
+
existingJson: UpdateJSON,
|
|
778
|
+
signature: string,
|
|
779
|
+
version: string,
|
|
780
|
+
minVersion: string
|
|
781
|
+
) => Promisable<UpdateJSON>
|
|
782
|
+
/**
|
|
783
|
+
* Custom generate zip file buffer
|
|
784
|
+
* @param buffer source buffer
|
|
785
|
+
*/
|
|
786
|
+
generateGzipFile?: (buffer: Buffer) => Promisable<Buffer>
|
|
685
787
|
}
|
|
686
788
|
```
|
|
687
789
|
|
|
790
|
+
## Credits
|
|
791
|
+
|
|
792
|
+
- [Obsidian](https://obsidian.md/) for upgrade strategy
|
|
793
|
+
- [vite-plugin-electron](https://github.com/electron-vite/vite-plugin-electron) for vite plugin
|
|
794
|
+
- [electron-builder](https://github.com/electron-userland/electron-builder) for update api
|
|
795
|
+
- [electron-vite](https://github.com/alex8088/electron-vite) for bytecode plugin inspiration
|
|
796
|
+
|
|
688
797
|
## License
|
|
689
798
|
|
|
690
799
|
MIT
|