electron-incremental-update 2.0.0-beta.9 → 2.0.1
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 +326 -198
- package/dist/chunk-GTDMND3I.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 +62 -94
- package/dist/vite.js +61 -43
- 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
|
-
|
|
40
|
+
### Project Structure
|
|
35
41
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
base on [electron-vite-vue](https://github.com/electron-vite/electron-vite-vue)
|
|
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
|
|
58
|
+
|
|
59
|
+
The entry is used to load the application and initialize the `Updater`
|
|
54
60
|
|
|
55
|
-
|
|
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)
|
|
223
229
|
})
|
|
230
|
+
updater.on('update-downloaded', () => {
|
|
231
|
+
updater.quitAndInstall()
|
|
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,202 @@ 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.
|
|
328
|
+
### Bytecode Protection
|
|
323
329
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
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))
|
|
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))
|
|
344
|
+
- Protect all strings by default
|
|
345
|
+
- Minification is allowed
|
|
346
|
+
|
|
335
347
|
#### Limitation
|
|
336
348
|
|
|
337
|
-
-
|
|
338
|
-
-
|
|
349
|
+
- Only support commonjs
|
|
350
|
+
- 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
351
|
|
|
340
352
|
### Types
|
|
341
353
|
|
|
342
|
-
####
|
|
354
|
+
#### Entry
|
|
343
355
|
|
|
344
356
|
```ts
|
|
345
|
-
export interface
|
|
357
|
+
export interface AppOption {
|
|
346
358
|
/**
|
|
347
|
-
*
|
|
348
|
-
*
|
|
359
|
+
* Path to index file that make {@link startupWithUpdater} as default export
|
|
360
|
+
*
|
|
361
|
+
* Generate from plugin configuration by default
|
|
349
362
|
*/
|
|
350
|
-
|
|
363
|
+
mainPath?: string
|
|
351
364
|
/**
|
|
352
|
-
*
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
*
|
|
357
|
-
* `repository` will be used to determine the url
|
|
365
|
+
* Updater options
|
|
366
|
+
*/
|
|
367
|
+
updater?: (() => Promisable<Updater>) | UpdaterOption
|
|
368
|
+
/**
|
|
369
|
+
* Hooks on rename temp asar path to `${app.name}.asar`
|
|
358
370
|
*/
|
|
359
|
-
|
|
371
|
+
onInstall?: OnInstallFunction
|
|
360
372
|
/**
|
|
361
|
-
*
|
|
362
|
-
* @
|
|
363
|
-
* @
|
|
373
|
+
* Hooks before app startup
|
|
374
|
+
* @param mainFilePath main file path of `${app.name}.asar`
|
|
375
|
+
* @param logger logger
|
|
364
376
|
*/
|
|
365
|
-
|
|
377
|
+
beforeStart?: (mainFilePath: string, logger?: Logger) => Promisable<void>
|
|
366
378
|
/**
|
|
367
|
-
*
|
|
368
|
-
* @
|
|
369
|
-
* @
|
|
379
|
+
* Hooks on app startup error
|
|
380
|
+
* @param err installing or startup error
|
|
381
|
+
* @param logger logger
|
|
370
382
|
*/
|
|
371
|
-
|
|
383
|
+
onStartError?: (err: unknown, logger?: Logger) => void
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* Hooks on rename temp asar path to `${app.name}.asar`
|
|
387
|
+
* @param install `() => renameSync(tempAsarPath, appNameAsarPath)`
|
|
388
|
+
* @param tempAsarPath temp(updated) asar path
|
|
389
|
+
* @param appNameAsarPath `${app.name}.asar` path
|
|
390
|
+
* @param logger logger
|
|
391
|
+
* @default install(); logger.info('update success!')
|
|
392
|
+
*/
|
|
393
|
+
type OnInstallFunction = (
|
|
394
|
+
install: VoidFunction,
|
|
395
|
+
tempAsarPath: string,
|
|
396
|
+
appNameAsarPath: string,
|
|
397
|
+
logger?: Logger
|
|
398
|
+
) => Promisable<void>
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
#### Updater
|
|
402
|
+
|
|
403
|
+
```ts
|
|
404
|
+
export interface UpdaterOption {
|
|
372
405
|
/**
|
|
373
|
-
*
|
|
406
|
+
* Update provider
|
|
407
|
+
*
|
|
408
|
+
* If you will not setup `UpdateJSON` or `Buffer` in params when checking update or download, this option is **required**
|
|
409
|
+
*/
|
|
410
|
+
provider?: IProvider
|
|
411
|
+
/**
|
|
412
|
+
* Certifaction key of signature, which will be auto generated by plugin,
|
|
413
|
+
* generate by `selfsigned` if not set
|
|
414
|
+
*/
|
|
415
|
+
SIGNATURE_CERT?: string
|
|
416
|
+
/**
|
|
417
|
+
* Whether to receive beta update
|
|
374
418
|
*/
|
|
375
419
|
receiveBeta?: boolean
|
|
376
|
-
|
|
377
|
-
|
|
420
|
+
/**
|
|
421
|
+
* Updater logger
|
|
422
|
+
*/
|
|
423
|
+
logger?: Logger
|
|
378
424
|
}
|
|
425
|
+
|
|
379
426
|
export type Logger = {
|
|
380
427
|
info: (msg: string) => void
|
|
381
428
|
debug: (msg: string) => void
|
|
382
429
|
warn: (msg: string) => void
|
|
383
430
|
error: (msg: string, e?: Error) => void
|
|
384
431
|
}
|
|
432
|
+
```
|
|
433
|
+
#### Provider
|
|
385
434
|
|
|
386
|
-
|
|
435
|
+
```ts
|
|
436
|
+
export type OnDownloading = (progress: DownloadingInfo) => void
|
|
437
|
+
|
|
438
|
+
export interface DownloadingInfo {
|
|
387
439
|
/**
|
|
388
|
-
*
|
|
389
|
-
* @param version1 old version string
|
|
390
|
-
* @param version2 new version string
|
|
391
|
-
* @returns if version1 < version2
|
|
440
|
+
* Download buffer delta
|
|
392
441
|
*/
|
|
393
|
-
|
|
442
|
+
delta: number
|
|
394
443
|
/**
|
|
395
|
-
*
|
|
396
|
-
*
|
|
397
|
-
*
|
|
398
|
-
|
|
399
|
-
|
|
444
|
+
* Downloaded percent, 0 ~ 100
|
|
445
|
+
*
|
|
446
|
+
* If no `Content-Length` header, will be -1
|
|
447
|
+
*/
|
|
448
|
+
percent: number
|
|
449
|
+
/**
|
|
450
|
+
* Total size
|
|
451
|
+
*
|
|
452
|
+
* If not `Content-Length` header, will be -1
|
|
400
453
|
*/
|
|
401
|
-
|
|
454
|
+
total: number
|
|
402
455
|
/**
|
|
403
|
-
*
|
|
404
|
-
* @param url download url
|
|
405
|
-
* @param header download header
|
|
406
|
-
* @returns `UpdateJSON`
|
|
456
|
+
* Downloaded size
|
|
407
457
|
*/
|
|
408
|
-
|
|
458
|
+
transferred: number
|
|
409
459
|
/**
|
|
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`
|
|
460
|
+
* Download speed, bytes per second
|
|
416
461
|
*/
|
|
417
|
-
|
|
462
|
+
bps: number
|
|
418
463
|
}
|
|
419
464
|
|
|
420
|
-
export
|
|
465
|
+
export interface IProvider {
|
|
466
|
+
/**
|
|
467
|
+
* Provider name
|
|
468
|
+
*/
|
|
469
|
+
name: string
|
|
470
|
+
/**
|
|
471
|
+
* Download update json
|
|
472
|
+
* @param versionPath parsed version path in project
|
|
473
|
+
* @param signal abort signal
|
|
474
|
+
*/
|
|
475
|
+
downloadJSON: (versionPath: string, signal: AbortSignal) => Promise<UpdateJSON>
|
|
476
|
+
/**
|
|
477
|
+
* Download update asar
|
|
478
|
+
* @param name app name
|
|
479
|
+
* @param updateInfo existing update info
|
|
480
|
+
* @param signal abort signal
|
|
481
|
+
* @param onDownloading hook for on downloading
|
|
482
|
+
*/
|
|
483
|
+
downloadAsar: (
|
|
484
|
+
name: string,
|
|
485
|
+
updateInfo: UpdateInfo,
|
|
486
|
+
signal: AbortSignal,
|
|
487
|
+
onDownloading?: (info: DownloadingInfo) => void
|
|
488
|
+
) => Promise<Buffer>
|
|
421
489
|
/**
|
|
422
|
-
*
|
|
423
|
-
* @
|
|
490
|
+
* Check the old version is less than new version
|
|
491
|
+
* @param oldVer old version string
|
|
492
|
+
* @param newVer new version string
|
|
424
493
|
*/
|
|
425
|
-
|
|
494
|
+
isLowerVersion: (oldVer: string, newVer: string) => boolean
|
|
426
495
|
/**
|
|
427
|
-
*
|
|
496
|
+
* Function to decompress file using brotli
|
|
497
|
+
* @param buffer compressed file buffer
|
|
428
498
|
*/
|
|
429
|
-
|
|
499
|
+
unzipFile: (buffer: Buffer) => Promise<Buffer>
|
|
500
|
+
/**
|
|
501
|
+
* Verify asar signature,
|
|
502
|
+
* if signature is valid, returns the version, otherwise returns `undefined`
|
|
503
|
+
* @param buffer file buffer
|
|
504
|
+
* @param version target version
|
|
505
|
+
* @param signature signature
|
|
506
|
+
* @param cert certificate
|
|
507
|
+
*/
|
|
508
|
+
verifySignaure: (buffer: Buffer, version: string, signature: string, cert: string) => Promisable<boolean>
|
|
430
509
|
}
|
|
431
510
|
```
|
|
432
511
|
|
|
433
512
|
#### Plugin
|
|
434
513
|
|
|
435
514
|
```ts
|
|
436
|
-
|
|
515
|
+
export interface ElectronWithUpdaterOptions {
|
|
437
516
|
/**
|
|
438
|
-
*
|
|
517
|
+
* Whether is in build mode
|
|
439
518
|
* ```ts
|
|
440
519
|
* export default defineConfig(({ command }) => {
|
|
441
520
|
* const isBuild = command === 'build'
|
|
@@ -444,65 +523,77 @@ type ElectronWithUpdaterOptions = {
|
|
|
444
523
|
*/
|
|
445
524
|
isBuild: boolean
|
|
446
525
|
/**
|
|
447
|
-
*
|
|
526
|
+
* Manually setup package.json, read name, version and main,
|
|
527
|
+
* use `local-pkg` of `loadPackageJSON()` to load package.json by default
|
|
448
528
|
* ```ts
|
|
449
529
|
* import pkg from './package.json'
|
|
450
530
|
* ```
|
|
451
531
|
*/
|
|
452
532
|
pkg?: PKG
|
|
453
533
|
/**
|
|
454
|
-
*
|
|
534
|
+
* Whether to generate sourcemap
|
|
535
|
+
* @default !isBuild
|
|
455
536
|
*/
|
|
456
537
|
sourcemap?: boolean
|
|
457
538
|
/**
|
|
458
|
-
*
|
|
539
|
+
* Whether to minify the code
|
|
540
|
+
* @default isBuild
|
|
459
541
|
*/
|
|
460
542
|
minify?: boolean
|
|
461
543
|
/**
|
|
462
|
-
*
|
|
544
|
+
* Whether to generate bytecode
|
|
463
545
|
*
|
|
464
|
-
* **
|
|
546
|
+
* **Only support CommonJS**
|
|
465
547
|
*
|
|
466
|
-
*
|
|
548
|
+
* 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
549
|
*/
|
|
468
550
|
bytecode?: boolean | BytecodeOptions
|
|
469
551
|
/**
|
|
470
|
-
*
|
|
552
|
+
* Use `NotBundle()` plugin in main
|
|
471
553
|
* @default true
|
|
472
554
|
*/
|
|
473
555
|
useNotBundle?: boolean
|
|
556
|
+
/**
|
|
557
|
+
* Whether to generate version json
|
|
558
|
+
* @default isCI
|
|
559
|
+
*/
|
|
560
|
+
buildVersionJson?: boolean
|
|
474
561
|
/**
|
|
475
562
|
* Whether to log parsed options
|
|
476
563
|
*
|
|
477
|
-
*
|
|
564
|
+
* To show certificate and private keys, set `logParsedOptions: { showKeys: true }`
|
|
478
565
|
*/
|
|
479
566
|
logParsedOptions?: boolean | { showKeys: boolean }
|
|
480
567
|
/**
|
|
481
|
-
*
|
|
568
|
+
* Main process options
|
|
569
|
+
*
|
|
570
|
+
* To change output directories, use `options.updater.paths.electronDistPath` instead
|
|
482
571
|
*/
|
|
483
|
-
main: MakeRequiredAndReplaceKey<ElectronSimpleOptions['main'], 'entry', 'files'>
|
|
572
|
+
main: MakeRequiredAndReplaceKey<ElectronSimpleOptions['main'], 'entry', 'files'> & ExcludeOutputDirOptions
|
|
484
573
|
/**
|
|
485
|
-
*
|
|
574
|
+
* Preload process options
|
|
575
|
+
*
|
|
576
|
+
* To change output directories, use `options.updater.paths.electronDistPath` instead
|
|
486
577
|
*/
|
|
487
|
-
preload: MakeRequiredAndReplaceKey<Exclude<ElectronSimpleOptions['preload'], undefined>, 'input', 'files'>
|
|
578
|
+
preload: MakeRequiredAndReplaceKey<Exclude<ElectronSimpleOptions['preload'], undefined>, 'input', 'files'> & ExcludeOutputDirOptions
|
|
488
579
|
/**
|
|
489
|
-
*
|
|
580
|
+
* Updater options
|
|
490
581
|
*/
|
|
491
582
|
updater?: ElectronUpdaterOptions
|
|
492
583
|
}
|
|
493
584
|
|
|
494
|
-
|
|
585
|
+
export interface ElectronUpdaterOptions {
|
|
495
586
|
/**
|
|
496
|
-
*
|
|
587
|
+
* Minimum version of entry
|
|
497
588
|
* @default '0.0.0'
|
|
498
589
|
*/
|
|
499
590
|
minimumVersion?: string
|
|
500
591
|
/**
|
|
501
|
-
*
|
|
592
|
+
* Options for entry (app.asar)
|
|
502
593
|
*/
|
|
503
594
|
entry?: BuildEntryOption
|
|
504
595
|
/**
|
|
505
|
-
* paths
|
|
596
|
+
* Options for paths
|
|
506
597
|
*/
|
|
507
598
|
paths?: {
|
|
508
599
|
/**
|
|
@@ -536,23 +627,23 @@ type ElectronUpdaterOptions = {
|
|
|
536
627
|
*/
|
|
537
628
|
keys?: {
|
|
538
629
|
/**
|
|
539
|
-
*
|
|
540
|
-
*
|
|
630
|
+
* Path to the pem file that contains private key
|
|
631
|
+
* If not ended with .pem, it will be appended
|
|
541
632
|
*
|
|
542
|
-
* **
|
|
633
|
+
* **If `UPDATER_PK` is set, will read it instead of read from `privateKeyPath`**
|
|
543
634
|
* @default 'keys/private.pem'
|
|
544
635
|
*/
|
|
545
636
|
privateKeyPath?: string
|
|
546
637
|
/**
|
|
547
|
-
*
|
|
548
|
-
*
|
|
638
|
+
* Path to the pem file that contains public key
|
|
639
|
+
* If not ended with .pem, it will be appended
|
|
549
640
|
*
|
|
550
|
-
* **
|
|
641
|
+
* **If `UPDATER_CERT` is set, will read it instead of read from `certPath`**
|
|
551
642
|
* @default 'keys/cert.pem'
|
|
552
643
|
*/
|
|
553
644
|
certPath?: string
|
|
554
645
|
/**
|
|
555
|
-
*
|
|
646
|
+
* Length of the key
|
|
556
647
|
* @default 2048
|
|
557
648
|
*/
|
|
558
649
|
keyLength?: number
|
|
@@ -563,45 +654,62 @@ type ElectronUpdaterOptions = {
|
|
|
563
654
|
*/
|
|
564
655
|
certInfo?: {
|
|
565
656
|
/**
|
|
566
|
-
*
|
|
657
|
+
* The subject of the certificate
|
|
567
658
|
*
|
|
568
659
|
* @default { commonName: `${app.name}`, organizationName: `org.${app.name}` }
|
|
569
660
|
*/
|
|
570
661
|
subject?: DistinguishedName
|
|
571
662
|
/**
|
|
572
|
-
*
|
|
663
|
+
* Expire days of the certificate
|
|
573
664
|
*
|
|
574
665
|
* @default 3650
|
|
575
666
|
*/
|
|
576
667
|
days?: number
|
|
577
668
|
}
|
|
578
|
-
overrideGenerator?: GeneratorOverrideFunctions
|
|
579
669
|
}
|
|
670
|
+
overrideGenerator?: GeneratorOverrideFunctions
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
export interface BytecodeOptions {
|
|
674
|
+
enable: boolean
|
|
675
|
+
/**
|
|
676
|
+
* Enable in preload script. Remember to set `sandbox: false` when creating window
|
|
677
|
+
*/
|
|
678
|
+
preload?: boolean
|
|
679
|
+
/**
|
|
680
|
+
* Custom electron binary path
|
|
681
|
+
*/
|
|
682
|
+
electronPath?: string
|
|
683
|
+
/**
|
|
684
|
+
* Before transformed code compile function. If return `Falsy` value, it will be ignored
|
|
685
|
+
* @param code transformed code
|
|
686
|
+
* @param id file path
|
|
687
|
+
*/
|
|
688
|
+
beforeCompile?: (code: string, id: string) => Promisable<string | null | undefined | void>
|
|
580
689
|
}
|
|
581
690
|
|
|
582
|
-
|
|
691
|
+
export interface BuildEntryOption {
|
|
583
692
|
/**
|
|
584
|
-
*
|
|
693
|
+
* Override to minify on entry
|
|
585
694
|
* @default isBuild
|
|
586
695
|
*/
|
|
587
696
|
minify?: boolean
|
|
588
697
|
/**
|
|
589
|
-
*
|
|
590
|
-
* @default isBuild
|
|
698
|
+
* Override to generate sourcemap on entry
|
|
591
699
|
*/
|
|
592
700
|
sourcemap?: boolean
|
|
593
701
|
/**
|
|
594
|
-
*
|
|
702
|
+
* Path to app entry output file
|
|
595
703
|
* @default 'dist-entry'
|
|
596
704
|
*/
|
|
597
705
|
entryOutputDirPath?: string
|
|
598
706
|
/**
|
|
599
|
-
*
|
|
707
|
+
* Path to app entry file
|
|
600
708
|
* @default 'electron/entry.ts'
|
|
601
709
|
*/
|
|
602
710
|
appEntryPath?: string
|
|
603
711
|
/**
|
|
604
|
-
*
|
|
712
|
+
* Esbuild path map of native modules in entry directory
|
|
605
713
|
*
|
|
606
714
|
* @default {}
|
|
607
715
|
* @example
|
|
@@ -609,7 +717,7 @@ type BuildEntryOption = {
|
|
|
609
717
|
*/
|
|
610
718
|
nativeModuleEntryMap?: Record<string, string>
|
|
611
719
|
/**
|
|
612
|
-
*
|
|
720
|
+
* Custom options for esbuild
|
|
613
721
|
* ```ts
|
|
614
722
|
* // default options
|
|
615
723
|
* const options = {
|
|
@@ -628,34 +736,32 @@ type BuildEntryOption = {
|
|
|
628
736
|
* loader: {
|
|
629
737
|
* '.node': 'empty',
|
|
630
738
|
* },
|
|
631
|
-
* define
|
|
632
|
-
* __SIGNATURE_CERT__: JSON.stringify(cert),
|
|
633
|
-
* },
|
|
739
|
+
* define,
|
|
634
740
|
* }
|
|
635
741
|
* ```
|
|
636
742
|
*/
|
|
637
743
|
overrideEsbuildOptions?: BuildOptions
|
|
638
744
|
/**
|
|
639
|
-
*
|
|
745
|
+
* Resolve extra files on startup, such as `.node`
|
|
640
746
|
* @remark won't trigger will reload
|
|
641
747
|
*/
|
|
642
748
|
postBuild?: (args: {
|
|
643
749
|
/**
|
|
644
|
-
*
|
|
750
|
+
* Get path from `entryOutputDirPath`
|
|
645
751
|
*/
|
|
646
752
|
getPathFromEntryOutputDir: (...paths: string[]) => string
|
|
647
753
|
/**
|
|
648
|
-
*
|
|
754
|
+
* Check exist and copy file to `entryOutputDirPath`
|
|
649
755
|
*
|
|
650
|
-
*
|
|
756
|
+
* If `to` absent, set to `basename(from)`
|
|
651
757
|
*
|
|
652
|
-
*
|
|
758
|
+
* If `skipIfExist` absent, skip copy if `to` exist
|
|
653
759
|
*/
|
|
654
760
|
copyToEntryOutputDir: (options: {
|
|
655
761
|
from: string
|
|
656
762
|
to?: string
|
|
657
763
|
/**
|
|
658
|
-
*
|
|
764
|
+
* Skip copy if `to` exist
|
|
659
765
|
* @default true
|
|
660
766
|
*/
|
|
661
767
|
skipIfExist?: boolean
|
|
@@ -663,17 +769,22 @@ type BuildEntryOption = {
|
|
|
663
769
|
}) => Promisable<void>
|
|
664
770
|
}
|
|
665
771
|
|
|
666
|
-
|
|
772
|
+
export interface GeneratorOverrideFunctions {
|
|
667
773
|
/**
|
|
668
|
-
*
|
|
774
|
+
* Custom signature generate function
|
|
669
775
|
* @param buffer file buffer
|
|
670
776
|
* @param privateKey private key
|
|
671
777
|
* @param cert certificate string, **EOL must be '\n'**
|
|
672
778
|
* @param version current version
|
|
673
779
|
*/
|
|
674
|
-
generateSignature?: (
|
|
780
|
+
generateSignature?: (
|
|
781
|
+
buffer: Buffer,
|
|
782
|
+
privateKey: string,
|
|
783
|
+
cert: string,
|
|
784
|
+
version: string
|
|
785
|
+
) => Promisable<string>
|
|
675
786
|
/**
|
|
676
|
-
*
|
|
787
|
+
* Custom generate version json function
|
|
677
788
|
* @param existingJson The existing JSON object.
|
|
678
789
|
* @param buffer file buffer
|
|
679
790
|
* @param signature generated signature
|
|
@@ -681,10 +792,27 @@ type GeneratorOverrideFunctions = {
|
|
|
681
792
|
* @param minVersion The minimum version
|
|
682
793
|
* @returns The updated version json
|
|
683
794
|
*/
|
|
684
|
-
generateVersionJson?: (
|
|
795
|
+
generateVersionJson?: (
|
|
796
|
+
existingJson: UpdateJSON,
|
|
797
|
+
signature: string,
|
|
798
|
+
version: string,
|
|
799
|
+
minVersion: string
|
|
800
|
+
) => Promisable<UpdateJSON>
|
|
801
|
+
/**
|
|
802
|
+
* Custom generate zip file buffer
|
|
803
|
+
* @param buffer source buffer
|
|
804
|
+
*/
|
|
805
|
+
generateGzipFile?: (buffer: Buffer) => Promisable<Buffer>
|
|
685
806
|
}
|
|
686
807
|
```
|
|
687
808
|
|
|
809
|
+
## Credits
|
|
810
|
+
|
|
811
|
+
- [Obsidian](https://obsidian.md/) for upgrade strategy
|
|
812
|
+
- [vite-plugin-electron](https://github.com/electron-vite/vite-plugin-electron) for vite plugin
|
|
813
|
+
- [electron-builder](https://github.com/electron-userland/electron-builder) for update api
|
|
814
|
+
- [electron-vite](https://github.com/alex8088/electron-vite) for bytecode plugin inspiration
|
|
815
|
+
|
|
688
816
|
## License
|
|
689
817
|
|
|
690
818
|
MIT
|