electron-incremental-update 3.0.0-beta.5 → 3.0.0-beta.6
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 +552 -344
- package/dist/{zip-Dwm7s1C9.mjs → download-BGaAyi1Z.mjs} +16 -69
- package/dist/download-BYnkme_X.cjs +167 -0
- package/dist/{download-BN4uMS4_.d.mts → download-BjWmHHAu.d.cts} +1 -1
- package/dist/{download-DO7iuxEJ.d.cts → download-DVWJfV3S.d.mts} +1 -1
- package/dist/{electron-BJCk7uxG.mjs → electron-BInvFJ-W.mjs} +38 -13
- package/dist/electron-D_8AbLQ5.cjs +346 -0
- package/dist/index.cjs +64 -32
- package/dist/index.d.cts +10 -13
- package/dist/index.d.mts +10 -13
- package/dist/index.mjs +60 -29
- package/dist/local-Daf8naRn.cjs +118 -0
- package/dist/local-s1cw_vwb.mjs +105 -0
- package/dist/provider.cjs +21 -40
- package/dist/provider.d.cts +53 -9
- package/dist/provider.d.mts +53 -9
- package/dist/provider.mjs +9 -30
- package/dist/{types-BM9Jfu7q.d.cts → types-BOqQ_r5Q.d.cts} +5 -5
- package/dist/{types-DASqEPXE.d.mts → types-BOqQ_r5Q.d.mts} +5 -5
- package/dist/utils.cjs +15 -15
- package/dist/utils.d.cts +2 -2
- package/dist/utils.d.mts +2 -2
- package/dist/utils.mjs +4 -5
- package/dist/vite.d.mts +90 -101
- package/dist/vite.mjs +647 -725
- package/dist/zip-D1dbBzw4.cjs +254 -0
- package/dist/zip-DUK3opmV.mjs +159 -0
- package/package.json +29 -34
- package/dist/electron-C-qmVhAt.cjs +0 -321
- package/dist/version--eVB2A7n.mjs +0 -72
- package/dist/version-aPrLuz_-.cjs +0 -129
- package/dist/zip-BCC7FAQ_.cjs +0 -264
package/README.md
CHANGED
|
@@ -1,107 +1,108 @@
|
|
|
1
1
|
# Electron Incremental Update
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Lightweight incremental update tools for Electron applications built with Vite. The package provides a Vite plugin, an Electron startup wrapper, update providers, bytecode protection, and utilities for common Electron app paths.
|
|
4
|
+
|
|
5
|
+
## Contents
|
|
4
6
|
|
|
5
7
|
- [Electron Incremental Update](#electron-incremental-update)
|
|
6
|
-
- [
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
- [
|
|
11
|
-
- [
|
|
12
|
-
- [
|
|
13
|
-
|
|
14
|
-
- [
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
- [
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
- [
|
|
22
|
-
|
|
23
|
-
- [
|
|
24
|
-
- [
|
|
25
|
-
- [
|
|
26
|
-
- [
|
|
27
|
-
- [
|
|
28
|
-
|
|
29
|
-
- [
|
|
30
|
-
|
|
31
|
-
|
|
8
|
+
- [Contents](#contents)
|
|
9
|
+
- [Why](#why)
|
|
10
|
+
- [How It Works](#how-it-works)
|
|
11
|
+
- [Installation](#installation)
|
|
12
|
+
- [Quick Start](#quick-start)
|
|
13
|
+
- [Entry Process](#entry-process)
|
|
14
|
+
- [Main Process](#main-process)
|
|
15
|
+
- [Vite Configuration](#vite-configuration)
|
|
16
|
+
- [Plugin Options](#plugin-options)
|
|
17
|
+
- [Electron Builder](#electron-builder)
|
|
18
|
+
- [Runtime Usage](#runtime-usage)
|
|
19
|
+
- [Create The App](#create-the-app)
|
|
20
|
+
- [Updater API](#updater-api)
|
|
21
|
+
- [Providers](#providers)
|
|
22
|
+
- [GitHub](#github)
|
|
23
|
+
- [Default](#default)
|
|
24
|
+
- [Atom](#atom)
|
|
25
|
+
- [Api](#api)
|
|
26
|
+
- [URL Handling](#url-handling)
|
|
27
|
+
- [Local](#local)
|
|
28
|
+
- [Recommended Setup](#recommended-setup)
|
|
29
|
+
- [Custom Options](#custom-options)
|
|
30
|
+
- [Manual Provider](#manual-provider)
|
|
31
|
+
- [Testing The Local Flow](#testing-the-local-flow)
|
|
32
|
+
- [Update Artifacts](#update-artifacts)
|
|
33
|
+
- [Native Modules](#native-modules)
|
|
34
|
+
- [Result in app.asar](#result-in-appasar)
|
|
35
|
+
- [Bytecode Protection](#bytecode-protection)
|
|
36
|
+
- [Development Bundling](#development-bundling)
|
|
37
|
+
- [Utilities](#utilities)
|
|
32
38
|
- [Credits](#credits)
|
|
33
39
|
- [License](#license)
|
|
34
40
|
|
|
35
|
-
##
|
|
36
|
-
|
|
37
|
-
This solution provides a comprehensive update system for Electron applications, including:
|
|
38
|
-
|
|
39
|
-
- **Vite Plugin** - Seamlessly integrates with your existing Vite build process
|
|
40
|
-
- **Startup Entry Function** - Handles application initialization and update checking
|
|
41
|
-
- **Updater Class** - Manages the complete update workflow with event-driven API
|
|
42
|
-
- **Utility Functions** - Helper functions for file paths, version management, and more
|
|
43
|
-
|
|
44
|
-
### Dual Asar Architecture
|
|
41
|
+
## Why
|
|
45
42
|
|
|
46
|
-
|
|
43
|
+
Electron applications are commonly shipped as full installers. This package keeps the installer stable and updates only the application asar file, which makes update packages smaller and keeps the runtime workflow explicit.
|
|
47
44
|
|
|
48
|
-
|
|
49
|
-
- **`${electron.app.name}.asar`** - Contains your application code (main process, preload scripts, and renderer) that gets replaced during updates
|
|
45
|
+
Key features:
|
|
50
46
|
|
|
51
|
-
|
|
47
|
+
- Vite plugin based on `vite-plugin-electron/multi-env`
|
|
48
|
+
- Dual asar runtime layout
|
|
49
|
+
- Signed update metadata and asar verification
|
|
50
|
+
- GitHub and local development providers
|
|
51
|
+
- Optional V8 bytecode generation
|
|
52
|
+
- Utilities for app paths, native modules, renderer loading, and Electron startup
|
|
52
53
|
|
|
53
|
-
|
|
54
|
+
## How It Works
|
|
54
55
|
|
|
55
|
-
|
|
56
|
-
2. **Download and Verify** - Download the update asar file and verify it using RSA signatures
|
|
57
|
-
3. **Prepare for Update** - The application quits to prepare for the update
|
|
58
|
-
4. **Apply Update** - On next launch, replace the old `${electron.app.name}.asar` with the new version and load it
|
|
56
|
+
The packaged app uses two asar files:
|
|
59
57
|
|
|
60
|
-
|
|
58
|
+
- `app.asar`: the stable entry asar generated from `entry.files`
|
|
59
|
+
- `${app.name}.asar`: the replaceable application asar generated from the Electron main, preload, and renderer build outputs
|
|
61
60
|
|
|
62
|
-
|
|
63
|
-
- **Source Code Protection** - Leverage V8 bytecode compilation to obfuscate and protect your JavaScript source code [see details](#bytecode-protection)
|
|
61
|
+
The update flow is:
|
|
64
62
|
|
|
65
|
-
|
|
63
|
+
1. `createElectronApp()` starts from `app.asar`.
|
|
64
|
+
2. If `${app.name}.asar.tmp` exists, it is renamed to `${app.name}.asar`.
|
|
65
|
+
3. The configured main file is loaded from `${app.name}.asar`.
|
|
66
|
+
4. Your main process calls `updater.checkForUpdates()`.
|
|
67
|
+
5. The provider downloads `version.json`.
|
|
68
|
+
6. The updater compares versions and emits `update-available` when a newer update exists.
|
|
69
|
+
7. `updater.downloadUpdate()` downloads, decompresses, verifies, and writes `${app.name}.asar.tmp`.
|
|
70
|
+
8. `updater.quitAndInstall()` restarts the app so the new asar can be installed on next launch.
|
|
66
71
|
|
|
67
|
-
|
|
72
|
+
## Installation
|
|
68
73
|
|
|
69
74
|
```sh
|
|
70
|
-
npm install -D electron-incremental-update
|
|
75
|
+
npm install -D electron-incremental-update @electron/asar @babel/core
|
|
71
76
|
```
|
|
72
77
|
|
|
73
78
|
```sh
|
|
74
|
-
|
|
79
|
+
pnpm add -D electron-incremental-update @electron/asar @babel/core
|
|
75
80
|
```
|
|
76
81
|
|
|
77
82
|
```sh
|
|
78
|
-
|
|
83
|
+
yarn add -D electron-incremental-update @electron/asar @babel/core
|
|
79
84
|
```
|
|
80
85
|
|
|
81
|
-
|
|
86
|
+
## Quick Start
|
|
82
87
|
|
|
83
|
-
|
|
88
|
+
Recommended project layout:
|
|
84
89
|
|
|
85
|
-
```
|
|
90
|
+
```txt
|
|
86
91
|
electron
|
|
87
|
-
├── entry.ts
|
|
92
|
+
├── entry.ts
|
|
88
93
|
├── main
|
|
89
94
|
│ └── index.ts
|
|
90
95
|
├── preload
|
|
91
96
|
│ └── index.ts
|
|
92
|
-
└── native
|
|
93
|
-
└──
|
|
97
|
+
└── native
|
|
98
|
+
└── db.ts
|
|
94
99
|
src
|
|
95
100
|
└── ...
|
|
96
101
|
```
|
|
97
102
|
|
|
98
|
-
###
|
|
99
|
-
|
|
100
|
-
The entry is used to load the application and initialize the `Updater`
|
|
103
|
+
### Entry Process
|
|
101
104
|
|
|
102
|
-
`
|
|
103
|
-
|
|
104
|
-
in `electron/entry.ts`
|
|
105
|
+
`electron/entry.ts` is the stable startup file. It creates the updater and loads the real main process from `${app.name}.asar`.
|
|
105
106
|
|
|
106
107
|
```ts
|
|
107
108
|
import { createElectronApp } from 'electron-incremental-update'
|
|
@@ -109,123 +110,193 @@ import { GitHubProvider } from 'electron-incremental-update/provider'
|
|
|
109
110
|
|
|
110
111
|
createElectronApp({
|
|
111
112
|
updater: {
|
|
112
|
-
// optional, you can setup later
|
|
113
113
|
provider: new GitHubProvider({
|
|
114
|
-
|
|
115
|
-
repo: '
|
|
114
|
+
user: 'your-github-user',
|
|
115
|
+
repo: 'your-repo',
|
|
116
116
|
}),
|
|
117
117
|
},
|
|
118
118
|
beforeStart(mainFilePath, logger) {
|
|
119
|
-
logger?.debug(mainFilePath)
|
|
119
|
+
logger?.debug(`Starting app from ${mainFilePath}`)
|
|
120
120
|
},
|
|
121
121
|
})
|
|
122
122
|
```
|
|
123
123
|
|
|
124
|
-
|
|
124
|
+
### Main Process
|
|
125
125
|
|
|
126
|
-
|
|
126
|
+
The main entry must default-export one function wrapped with `startupWithUpdater()`.
|
|
127
127
|
|
|
128
|
-
|
|
128
|
+
```ts
|
|
129
|
+
import { app, BrowserWindow, dialog } from 'electron'
|
|
130
|
+
import { startupWithUpdater } from 'electron-incremental-update'
|
|
131
|
+
import { getAppVersion, getPathFromPreload, loadPage } from 'electron-incremental-update/utils'
|
|
129
132
|
|
|
130
|
-
|
|
131
|
-
|
|
133
|
+
export default startupWithUpdater(async (updater) => {
|
|
134
|
+
await app.whenReady()
|
|
132
135
|
|
|
133
|
-
|
|
136
|
+
const win = new BrowserWindow({
|
|
137
|
+
webPreferences: {
|
|
138
|
+
preload: getPathFromPreload('index.js'),
|
|
139
|
+
},
|
|
140
|
+
})
|
|
134
141
|
|
|
135
|
-
|
|
142
|
+
loadPage(win)
|
|
136
143
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
144
|
+
updater.on('update-available', async ({ version }) => {
|
|
145
|
+
const { response } = await dialog.showMessageBox({
|
|
146
|
+
type: 'info',
|
|
147
|
+
message: `Version ${version} is available. Current version is ${getAppVersion()}.`,
|
|
148
|
+
buttons: ['Download', 'Later'],
|
|
149
|
+
})
|
|
140
150
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
})(),
|
|
172
|
-
}
|
|
151
|
+
if (response === 0) {
|
|
152
|
+
await updater.downloadUpdate()
|
|
153
|
+
}
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
updater.on('download-progress', (info) => {
|
|
157
|
+
win.webContents.send('update-progress', info)
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
updater.on('update-downloaded', async () => {
|
|
161
|
+
const { response } = await dialog.showMessageBox({
|
|
162
|
+
type: 'info',
|
|
163
|
+
message: 'Update downloaded.',
|
|
164
|
+
buttons: ['Restart Now', 'Later'],
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
if (response === 0) {
|
|
168
|
+
updater.quitAndInstall()
|
|
169
|
+
}
|
|
170
|
+
})
|
|
171
|
+
|
|
172
|
+
updater.on('update-not-available', (code, message) => {
|
|
173
|
+
console.log(`[${code}] ${message}`)
|
|
174
|
+
})
|
|
175
|
+
|
|
176
|
+
updater.on('error', (error) => {
|
|
177
|
+
console.error(error)
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
await updater.checkForUpdates()
|
|
173
181
|
})
|
|
174
182
|
```
|
|
175
183
|
|
|
176
|
-
|
|
184
|
+
## Vite Configuration
|
|
185
|
+
|
|
186
|
+
Use `defineElectronConfig()` when the same Vite config owns the renderer and Electron processes.
|
|
177
187
|
|
|
178
188
|
```ts
|
|
179
189
|
import { defineElectronConfig } from 'electron-incremental-update/vite'
|
|
180
190
|
|
|
181
191
|
export default defineElectronConfig({
|
|
182
192
|
entry: {
|
|
183
|
-
files:
|
|
193
|
+
files: './electron/entry.ts',
|
|
184
194
|
},
|
|
185
195
|
main: {
|
|
186
|
-
files:
|
|
187
|
-
// see https://github.com/electron-vite/electron-vite-vue/blob/85ed267c4851bf59f32888d766c0071661d4b94c/vite.config.ts#L22-L28
|
|
188
|
-
onstart: debugStartup,
|
|
196
|
+
files: './electron/main/index.ts',
|
|
189
197
|
},
|
|
190
198
|
preload: {
|
|
191
199
|
files: './electron/preload/index.ts',
|
|
192
200
|
},
|
|
193
201
|
updater: {
|
|
194
|
-
|
|
202
|
+
minimumVersion: '0.0.0',
|
|
203
|
+
paths: {
|
|
204
|
+
asarOutputPath: 'release/my-app.asar',
|
|
205
|
+
gzipPath: 'release/my-app-1.0.0.asar.gz',
|
|
206
|
+
versionPath: 'release/version.json',
|
|
207
|
+
},
|
|
195
208
|
},
|
|
196
209
|
renderer: {
|
|
197
|
-
server:
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
return {
|
|
202
|
-
host: url.hostname,
|
|
203
|
-
port: +url.port,
|
|
210
|
+
server: process.env.VSCODE_DEBUG
|
|
211
|
+
? {
|
|
212
|
+
host: '127.0.0.1',
|
|
213
|
+
port: 5173,
|
|
204
214
|
}
|
|
205
|
-
|
|
215
|
+
: undefined,
|
|
206
216
|
},
|
|
207
217
|
})
|
|
208
218
|
```
|
|
209
219
|
|
|
210
|
-
|
|
220
|
+
Use `electronWithUpdater()` directly when you want to manage the renderer config yourself.
|
|
221
|
+
|
|
222
|
+
```ts
|
|
223
|
+
import { electronWithUpdater } from 'electron-incremental-update/vite'
|
|
224
|
+
import { defineConfig } from 'vite'
|
|
225
|
+
|
|
226
|
+
export default defineConfig({
|
|
227
|
+
plugins: [
|
|
228
|
+
electronWithUpdater({
|
|
229
|
+
entry: {
|
|
230
|
+
files: './electron/entry.ts',
|
|
231
|
+
},
|
|
232
|
+
main: {
|
|
233
|
+
files: './electron/main/index.ts',
|
|
234
|
+
},
|
|
235
|
+
preload: {
|
|
236
|
+
files: './electron/preload/index.ts',
|
|
237
|
+
},
|
|
238
|
+
}),
|
|
239
|
+
],
|
|
240
|
+
})
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### Plugin Options
|
|
244
|
+
|
|
245
|
+
Common options:
|
|
246
|
+
|
|
247
|
+
- `entry.files`: entry process input. Required.
|
|
248
|
+
- `main.files`: main process input. Required.
|
|
249
|
+
- `preload.files`: preload process input. Optional.
|
|
250
|
+
- `sourcemap`: defaults to development or `VSCODE_DEBUG`.
|
|
251
|
+
- `minify`: defaults to production builds.
|
|
252
|
+
- `bytecode`: `true` or bytecode options.
|
|
253
|
+
- `notBundle`: externalizes Node modules in development. Defaults to `true`.
|
|
254
|
+
- `external`: additional Vite/Rolldown externals. Use `true` to externalize `dependencies`.
|
|
255
|
+
- `buildVersionJson`: generates update JSON. Defaults to CI only.
|
|
256
|
+
- `localDevUpdate`: generates and serves a local update package during dev startup. Use `true`
|
|
257
|
+
for defaults, or pass `{ baseDir, packageJsonPath, chunkSize, chunkDelay }`. See [Local Development](#local-development) for details.
|
|
258
|
+
- `updater.minimumVersion`: minimum supported entry asar version. Defaults to `0.0.0`.
|
|
259
|
+
|
|
260
|
+
Default output paths:
|
|
261
|
+
|
|
262
|
+
- `updater.paths.asarOutputPath`: `release/${app.name}.asar`
|
|
263
|
+
- `updater.paths.gzipPath`: `release/${app.name}-${version}.asar.gz`
|
|
264
|
+
- `updater.paths.versionPath`: `release/version.json`
|
|
265
|
+
- `updater.paths.entryOutDir`: `dist-entry`
|
|
266
|
+
- `updater.paths.electronDistPath`: `dist-electron`
|
|
267
|
+
- `updater.paths.rendererDistPath`: `dist`
|
|
268
|
+
|
|
269
|
+
Signing keys:
|
|
270
|
+
|
|
271
|
+
- `updater.keys.privateKeyPath`: defaults to `keys/private.pem`
|
|
272
|
+
- `updater.keys.certPath`: defaults to `keys/cert.pem`
|
|
273
|
+
- `UPDATER_PK`: overrides `privateKeyPath`
|
|
274
|
+
- `UPDATER_CERT`: overrides `certPath`
|
|
275
|
+
|
|
276
|
+
The plugin creates a simple self-signed certificate when the key files are missing.
|
|
277
|
+
|
|
278
|
+
## Electron Builder
|
|
279
|
+
|
|
280
|
+
Set `package.json#main` to the entry output file:
|
|
211
281
|
|
|
212
282
|
```json
|
|
213
283
|
{
|
|
214
|
-
"main": "dist-entry/entry.js"
|
|
284
|
+
"main": "dist-entry/entry.js"
|
|
215
285
|
}
|
|
216
286
|
```
|
|
217
287
|
|
|
218
|
-
|
|
288
|
+
Minimal `electron-builder.config.cjs`:
|
|
219
289
|
|
|
220
290
|
```js
|
|
221
291
|
const { name } = require('./package.json')
|
|
222
292
|
|
|
223
293
|
const targetFile = `${name}.asar`
|
|
294
|
+
|
|
224
295
|
/**
|
|
225
296
|
* @type {import('electron-builder').Configuration}
|
|
226
297
|
*/
|
|
227
298
|
module.exports = {
|
|
228
|
-
appId:
|
|
299
|
+
appId: `org.${name}`,
|
|
229
300
|
productName: name,
|
|
230
301
|
files: [
|
|
231
302
|
// entry files
|
|
@@ -243,168 +314,327 @@ module.exports = {
|
|
|
243
314
|
}
|
|
244
315
|
```
|
|
245
316
|
|
|
246
|
-
## Usage
|
|
317
|
+
## Runtime Usage
|
|
247
318
|
|
|
248
|
-
###
|
|
319
|
+
### Create The App
|
|
249
320
|
|
|
250
|
-
|
|
321
|
+
```ts
|
|
322
|
+
import { createElectronApp } from 'electron-incremental-update'
|
|
251
323
|
|
|
252
|
-
|
|
324
|
+
createElectronApp({
|
|
325
|
+
updater: {
|
|
326
|
+
provider,
|
|
327
|
+
receiveBeta: false,
|
|
328
|
+
logger: console,
|
|
329
|
+
},
|
|
330
|
+
onInstall(install, tempAsarPath, appNameAsarPath, logger) {
|
|
331
|
+
logger?.info(`Installing ${tempAsarPath} to ${appNameAsarPath}`)
|
|
332
|
+
install()
|
|
333
|
+
},
|
|
334
|
+
onStartError(error, logger) {
|
|
335
|
+
logger?.error('Failed to start app', error)
|
|
336
|
+
},
|
|
337
|
+
})
|
|
338
|
+
```
|
|
253
339
|
|
|
254
|
-
|
|
340
|
+
`updater` can also be an async factory:
|
|
255
341
|
|
|
256
342
|
```ts
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
343
|
+
createElectronApp({
|
|
344
|
+
updater: async () => {
|
|
345
|
+
const { Updater } = await import('electron-incremental-update')
|
|
346
|
+
return new Updater({ provider })
|
|
347
|
+
},
|
|
348
|
+
})
|
|
349
|
+
```
|
|
264
350
|
|
|
265
|
-
|
|
266
|
-
await app.whenReady()
|
|
351
|
+
### Updater API
|
|
267
352
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
'entry (installer) version:': getEntryVersion(),
|
|
273
|
-
'electron version:': process.versions.electron,
|
|
274
|
-
})
|
|
353
|
+
```ts
|
|
354
|
+
updater.provider = provider
|
|
355
|
+
updater.receiveBeta = true
|
|
356
|
+
updater.logger = console
|
|
275
357
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
358
|
+
await updater.checkForUpdates()
|
|
359
|
+
await updater.downloadUpdate()
|
|
360
|
+
updater.cancel()
|
|
361
|
+
updater.quitAndInstall()
|
|
362
|
+
```
|
|
280
363
|
|
|
281
|
-
|
|
282
|
-
updater.on('update-available', async ({ version }) => {
|
|
283
|
-
const { response } = await dialog.showMessageBox({
|
|
284
|
-
type: 'info',
|
|
285
|
-
buttons: ['Download', 'Later'],
|
|
286
|
-
message: `Version ${version} update available!`,
|
|
287
|
-
})
|
|
288
|
-
if (response === 0) {
|
|
289
|
-
// 0 = Download button
|
|
290
|
-
await updater.downloadUpdate()
|
|
291
|
-
}
|
|
292
|
-
})
|
|
364
|
+
Events:
|
|
293
365
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
366
|
+
- `update-available`: emitted with update info and current app/entry versions.
|
|
367
|
+
- `update-not-available`: emitted with a code, message, and optional update info.
|
|
368
|
+
- `download-progress`: emitted while downloading.
|
|
369
|
+
- `update-downloaded`: emitted after the temporary asar is ready.
|
|
370
|
+
- `update-cancelled`: emitted after cancellation.
|
|
371
|
+
- `error`: emitted with `UpdaterError`.
|
|
298
372
|
|
|
299
|
-
|
|
300
|
-
updater.on('download-progress', (data) => {
|
|
301
|
-
console.log('Download progress:', data)
|
|
302
|
-
// Send progress to renderer if needed
|
|
303
|
-
const [mainWindow] = BrowserWindow.getAllWindows()
|
|
304
|
-
if (mainWindow) {
|
|
305
|
-
mainWindow.webContents.send('update-progress', data)
|
|
306
|
-
}
|
|
307
|
-
})
|
|
373
|
+
## Providers
|
|
308
374
|
|
|
309
|
-
|
|
310
|
-
updater.on('update-downloaded', () => {
|
|
311
|
-
dialog
|
|
312
|
-
.showMessageBox({
|
|
313
|
-
type: 'info',
|
|
314
|
-
message: 'Update downloaded successfully!',
|
|
315
|
-
buttons: ['Restart Now', 'Later'],
|
|
316
|
-
})
|
|
317
|
-
.then(({ response }) => {
|
|
318
|
-
if (response === 0) {
|
|
319
|
-
updater.quitAndInstall()
|
|
320
|
-
}
|
|
321
|
-
})
|
|
322
|
-
})
|
|
375
|
+
### GitHub
|
|
323
376
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
377
|
+
GitHub providers read update metadata from a repository or release and download the generated
|
|
378
|
+
`{name}-{version}.asar.gz` artifact from GitHub Releases.
|
|
379
|
+
|
|
380
|
+
#### Default
|
|
381
|
+
|
|
382
|
+
Reads `version.json` from the repository branch and downloads the asar from GitHub Releases.
|
|
383
|
+
|
|
384
|
+
```ts
|
|
385
|
+
import { GitHubProvider } from 'electron-incremental-update/provider'
|
|
386
|
+
|
|
387
|
+
const provider = new GitHubProvider({
|
|
388
|
+
user: 'your-github-user',
|
|
389
|
+
repo: 'your-repo',
|
|
390
|
+
branch: 'HEAD',
|
|
391
|
+
})
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
Default URLs:
|
|
395
|
+
|
|
396
|
+
- update JSON: `https://github.com/{user}/{repo}/raw/{branch}/{versionPath}`
|
|
397
|
+
- asar: `https://github.com/{user}/{repo}/releases/download/v{version}/{name}-{version}.asar.gz`
|
|
329
398
|
|
|
330
|
-
|
|
331
|
-
|
|
399
|
+
#### Atom
|
|
400
|
+
|
|
401
|
+
Reads the latest release tag from `releases.atom`, then downloads the update JSON and asar from that release.
|
|
402
|
+
|
|
403
|
+
```ts
|
|
404
|
+
import { GitHubAtomProvider } from 'electron-incremental-update/provider'
|
|
405
|
+
|
|
406
|
+
const provider = new GitHubAtomProvider({
|
|
407
|
+
user: 'your-github-user',
|
|
408
|
+
repo: 'your-repo',
|
|
409
|
+
})
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
#### Api
|
|
413
|
+
|
|
414
|
+
Uses the GitHub Releases API and can use a token for private repositories or higher rate limits.
|
|
415
|
+
|
|
416
|
+
```ts
|
|
417
|
+
import { GitHubApiProvider } from 'electron-incremental-update/provider'
|
|
418
|
+
|
|
419
|
+
const provider = new GitHubApiProvider({
|
|
420
|
+
user: 'your-github-user',
|
|
421
|
+
repo: 'your-repo',
|
|
422
|
+
token: process.env.GITHUB_TOKEN,
|
|
332
423
|
})
|
|
333
424
|
```
|
|
334
425
|
|
|
335
|
-
####
|
|
426
|
+
#### URL Handling
|
|
336
427
|
|
|
337
|
-
|
|
428
|
+
GitHub providers support `urlHandler` for mirrors, custom gateways, or request rewriting.
|
|
338
429
|
|
|
339
430
|
```ts
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
owner: 'your-username',
|
|
431
|
+
const provider = new GitHubProvider({
|
|
432
|
+
user: 'your-github-user',
|
|
343
433
|
repo: 'your-repo',
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
url.hostname = 'mirror.ghproxy.com'
|
|
434
|
+
urlHandler(url) {
|
|
435
|
+
url.hostname = 'mirror.example.com'
|
|
347
436
|
url.pathname = `https://github.com${url.pathname}`
|
|
348
437
|
return url
|
|
349
438
|
},
|
|
350
439
|
})
|
|
351
440
|
```
|
|
352
441
|
|
|
353
|
-
|
|
442
|
+
### Local
|
|
443
|
+
|
|
444
|
+
Local updates are for development and manual update-flow testing. They let you test
|
|
445
|
+
`checkForUpdates()`, download progress, `update-downloaded`, and restart/install behavior without
|
|
446
|
+
publishing a GitHub release.
|
|
447
|
+
|
|
448
|
+
Most projects should use the Vite `localDevUpdate` option instead of manually creating a
|
|
449
|
+
`LocalDevProvider`.
|
|
450
|
+
|
|
451
|
+
#### Recommended Setup
|
|
452
|
+
|
|
453
|
+
Enable local update generation in `vite.config.ts`:
|
|
354
454
|
|
|
355
455
|
```ts
|
|
356
|
-
|
|
456
|
+
import { electronWithUpdater } from 'electron-incremental-update/vite'
|
|
457
|
+
import { defineConfig } from 'vite'
|
|
458
|
+
|
|
459
|
+
export default defineConfig({
|
|
460
|
+
plugins: [
|
|
461
|
+
electronWithUpdater({
|
|
462
|
+
entry: {
|
|
463
|
+
files: './electron/entry.ts',
|
|
464
|
+
},
|
|
465
|
+
main: {
|
|
466
|
+
files: './electron/main/index.ts',
|
|
467
|
+
},
|
|
468
|
+
preload: {
|
|
469
|
+
files: './electron/preload/index.ts',
|
|
470
|
+
},
|
|
471
|
+
localDevUpdate: true,
|
|
472
|
+
}),
|
|
473
|
+
],
|
|
474
|
+
})
|
|
357
475
|
```
|
|
358
476
|
|
|
359
|
-
|
|
477
|
+
When `localDevUpdate` is enabled in development:
|
|
478
|
+
|
|
479
|
+
- the Vite plugin creates a local update package before Electron starts
|
|
480
|
+
- `createElectronApp()` auto-configures `LocalDevProvider` when no explicit `updater.provider` is set
|
|
481
|
+
- dev-only `forceUpdate` is enabled so update checks are not skipped in development
|
|
482
|
+
- production builds keep the normal provider and signature behavior
|
|
483
|
+
|
|
484
|
+
The default generated files are:
|
|
485
|
+
|
|
486
|
+
- `release/local-update/release/version.json`
|
|
487
|
+
- `release/local-update/{name}-{version}.asar.gz`
|
|
488
|
+
- `DEV.asar`
|
|
489
|
+
- `DEV.asar.tmp` after `downloadUpdate()`
|
|
490
|
+
|
|
491
|
+
The generated update version is the next patch version from the installed local dev asar. For
|
|
492
|
+
example, if `DEV.asar` contains version `1.2.3`, the generated update is `1.2.4`.
|
|
493
|
+
|
|
494
|
+
#### Custom Options
|
|
360
495
|
|
|
361
496
|
```ts
|
|
362
|
-
|
|
497
|
+
export default defineConfig({
|
|
498
|
+
plugins: [
|
|
499
|
+
electronWithUpdater({
|
|
500
|
+
// ...
|
|
501
|
+
localDevUpdate: {
|
|
502
|
+
baseDir: 'release/local-update',
|
|
503
|
+
packageJsonPath: 'playground/package.json',
|
|
504
|
+
chunkSize: 32 * 1024,
|
|
505
|
+
chunkDelay: 50,
|
|
506
|
+
},
|
|
507
|
+
}),
|
|
508
|
+
],
|
|
509
|
+
})
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
Options:
|
|
513
|
+
|
|
514
|
+
- `baseDir`: directory for generated local update resources. Defaults to `release/local-update`.
|
|
515
|
+
- `packageJsonPath`: package metadata used for update name/version. Defaults to the project
|
|
516
|
+
`package.json`.
|
|
517
|
+
- `chunkSize`: bytes per simulated download progress chunk. Defaults to `64 * 1024`.
|
|
518
|
+
- `chunkDelay`: delay between progress chunks in milliseconds. Defaults to `30`.
|
|
519
|
+
|
|
520
|
+
`chunkSize` must be greater than `0`, and `chunkDelay` must be greater than or equal to `0`.
|
|
521
|
+
|
|
522
|
+
#### Manual Provider
|
|
523
|
+
|
|
524
|
+
Use `LocalDevProvider` directly only when you need to wire local artifacts yourself.
|
|
525
|
+
|
|
526
|
+
```ts
|
|
527
|
+
import { LocalDevProvider } from 'electron-incremental-update/provider'
|
|
528
|
+
|
|
529
|
+
const provider = new LocalDevProvider({
|
|
530
|
+
baseDir: 'release/local-update',
|
|
531
|
+
chunkSize: 32 * 1024,
|
|
532
|
+
chunkDelay: 50,
|
|
533
|
+
})
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
It reads:
|
|
537
|
+
|
|
538
|
+
- `{baseDir}/{versionPath}`
|
|
539
|
+
- `{baseDir}/{name}-{version}.asar.gz`
|
|
540
|
+
|
|
541
|
+
#### Testing The Local Flow
|
|
542
|
+
|
|
543
|
+
Use the [playground](./playground) as a complete local update test:
|
|
544
|
+
|
|
545
|
+
```sh
|
|
546
|
+
bun run play
|
|
363
547
|
```
|
|
364
548
|
|
|
365
|
-
|
|
549
|
+
`bun run play` builds the package first, then starts the Vite dev server and Electron playground.
|
|
550
|
+
|
|
551
|
+
Expected flow:
|
|
366
552
|
|
|
367
|
-
|
|
553
|
+
1. The plugin builds the Electron main, preload, and entry outputs.
|
|
554
|
+
2. The plugin creates `DEV.asar` and a local update archive.
|
|
555
|
+
3. `createElectronApp()` installs any existing `DEV.asar.tmp`.
|
|
556
|
+
4. The app starts from `DEV.asar`.
|
|
557
|
+
5. The updater checks the generated `version.json`.
|
|
558
|
+
6. The playground shows an available local update.
|
|
559
|
+
7. Clicking download emits simulated progress events.
|
|
560
|
+
8. Clicking restart installs `DEV.asar.tmp` and restarts Electron.
|
|
368
561
|
|
|
369
|
-
|
|
562
|
+
Explicit `updater.provider` values still take priority. If you set a provider manually, automatic
|
|
563
|
+
local provider setup is skipped.
|
|
370
564
|
|
|
371
|
-
|
|
565
|
+
## Update Artifacts
|
|
372
566
|
|
|
373
|
-
|
|
374
|
-
2. Manually copy the native binaries in `entry.postBuild` callback
|
|
375
|
-
3. Exclude all the dependencies in `electron-builder`'s config
|
|
376
|
-
4. call the native functions with `requireNative` / `importNative` in your code
|
|
567
|
+
The Vite plugin can generate:
|
|
377
568
|
|
|
378
|
-
|
|
569
|
+
- `${app.name}.asar`
|
|
570
|
+
- `${app.name}-${version}.asar.gz`
|
|
571
|
+
- `version.json`
|
|
379
572
|
|
|
380
|
-
|
|
573
|
+
Default `version.json` shape:
|
|
574
|
+
|
|
575
|
+
```json
|
|
576
|
+
{
|
|
577
|
+
"version": "1.0.0",
|
|
578
|
+
"minimumVersion": "0.0.0",
|
|
579
|
+
"signature": "...",
|
|
580
|
+
"beta": {
|
|
581
|
+
"version": "1.0.1-beta.1",
|
|
582
|
+
"minimumVersion": "0.0.0",
|
|
583
|
+
"signature": "..."
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
```
|
|
587
|
+
|
|
588
|
+
Stable releases update both the top-level fields and `beta`. Prerelease versions update only `beta`.
|
|
589
|
+
|
|
590
|
+
Set `buildVersionJson: true` if you need metadata during non-CI builds.
|
|
591
|
+
|
|
592
|
+
## Native Modules
|
|
593
|
+
|
|
594
|
+
To keep update packages small, put native modules and their native binaries in `app.asar`, then load them from the main process with `requireNative()` or `importNative()`.
|
|
381
595
|
|
|
382
596
|
```ts
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
597
|
+
import { readdirSync } from 'node:fs'
|
|
598
|
+
|
|
599
|
+
import { electronWithUpdater } from 'electron-incremental-update/vite'
|
|
600
|
+
|
|
601
|
+
export default {
|
|
602
|
+
plugins: [
|
|
603
|
+
electronWithUpdater({
|
|
604
|
+
external: false,
|
|
605
|
+
entry: {
|
|
606
|
+
files: ['./electron/entry.ts', './electron/native/db.ts'],
|
|
607
|
+
postBuild({ isBuild, copyToEntryOutputDir }) {
|
|
608
|
+
if (!isBuild) {
|
|
609
|
+
return
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
copyToEntryOutputDir({
|
|
613
|
+
from: './node_modules/better-sqlite3/build/Release/better_sqlite3.node',
|
|
614
|
+
skipIfExist: false,
|
|
615
|
+
})
|
|
616
|
+
|
|
617
|
+
const packageName = readdirSync('./node_modules/.pnpm').find((name) =>
|
|
618
|
+
name.startsWith('@napi-rs+image-'),
|
|
619
|
+
)
|
|
620
|
+
|
|
621
|
+
if (packageName) {
|
|
622
|
+
const archName = packageName.substring('@napi-rs+image-'.length).split('@')[0]
|
|
623
|
+
copyToEntryOutputDir({
|
|
624
|
+
from: `./node_modules/.pnpm/${packageName}/node_modules/@napi-rs/image-${archName}/image.${archName}.node`,
|
|
625
|
+
})
|
|
626
|
+
}
|
|
627
|
+
},
|
|
628
|
+
},
|
|
629
|
+
main: {
|
|
630
|
+
files: './electron/main/index.ts',
|
|
631
|
+
},
|
|
632
|
+
}),
|
|
633
|
+
],
|
|
634
|
+
}
|
|
405
635
|
```
|
|
406
636
|
|
|
407
|
-
|
|
637
|
+
Use the copied native binding from entry asar:
|
|
408
638
|
|
|
409
639
|
```ts
|
|
410
640
|
import Database from 'better-sqlite3'
|
|
@@ -414,38 +644,27 @@ const db = new Database(':memory:', {
|
|
|
414
644
|
nativeBinding: getPathFromEntryAsar('./better_sqlite3.node'),
|
|
415
645
|
})
|
|
416
646
|
|
|
417
|
-
export function
|
|
418
|
-
db.exec(
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
db.prepare('INSERT INTO employees VALUES (:n, :s)').run({
|
|
424
|
-
n: 'James',
|
|
425
|
-
s: 5000,
|
|
647
|
+
export function testDatabase(): void {
|
|
648
|
+
db.exec('CREATE TABLE IF NOT EXISTS employees (name TEXT, salary INTEGER)')
|
|
649
|
+
db.prepare('INSERT INTO employees VALUES (:name, :salary)').run({
|
|
650
|
+
name: 'James',
|
|
651
|
+
salary: 5000,
|
|
426
652
|
})
|
|
427
|
-
|
|
428
|
-
const r = db.prepare('SELECT * from employees').all()
|
|
429
|
-
console.log(r)
|
|
430
|
-
// [ { name: 'James', salary: 50000 } ]
|
|
431
|
-
|
|
432
|
-
db.close()
|
|
433
653
|
}
|
|
434
654
|
```
|
|
435
655
|
|
|
436
|
-
|
|
656
|
+
Load native helper modules from main:
|
|
437
657
|
|
|
438
658
|
```ts
|
|
439
659
|
import { importNative, requireNative } from 'electron-incremental-update/utils'
|
|
440
660
|
|
|
441
|
-
|
|
442
|
-
requireNative<typeof import('../native/db')>('db').test()
|
|
661
|
+
requireNative<typeof import('../native/db')>('db').testDatabase()
|
|
443
662
|
|
|
444
|
-
|
|
445
|
-
|
|
663
|
+
const nativeDb = await importNative<typeof import('../native/db')>('db')
|
|
664
|
+
nativeDb.testDatabase()
|
|
446
665
|
```
|
|
447
666
|
|
|
448
|
-
|
|
667
|
+
For `electron-builder`, exclude `node_modules` when you have bundled dependencies manually:
|
|
449
668
|
|
|
450
669
|
```js
|
|
451
670
|
module.exports = {
|
|
@@ -525,114 +744,103 @@ After: Clean 😍
|
|
|
525
744
|
└── package.json
|
|
526
745
|
```
|
|
527
746
|
|
|
528
|
-
|
|
747
|
+
## Bytecode Protection
|
|
529
748
|
|
|
530
|
-
|
|
749
|
+
Bytecode protection compiles JavaScript into V8 bytecode.
|
|
531
750
|
|
|
532
751
|
```ts
|
|
533
752
|
electronWithUpdater({
|
|
534
|
-
|
|
535
|
-
|
|
753
|
+
bytecode: true,
|
|
754
|
+
entry: {
|
|
755
|
+
files: './electron/entry.ts',
|
|
756
|
+
},
|
|
757
|
+
main: {
|
|
758
|
+
files: './electron/main/index.ts',
|
|
759
|
+
},
|
|
536
760
|
})
|
|
537
761
|
```
|
|
538
762
|
|
|
539
|
-
|
|
763
|
+
Notes:
|
|
540
764
|
|
|
541
|
-
|
|
765
|
+
- CommonJS only. Remove `"type": "module"` from `package.json` when enabling bytecode.
|
|
766
|
+
- Main process bytecode is enabled by default.
|
|
767
|
+
- To include preload scripts, use `bytecode: { enablePreload: true }`.
|
|
768
|
+
- If preload bytecode is enabled, create the `BrowserWindow` with `sandbox: false`.
|
|
542
769
|
|
|
543
|
-
|
|
544
|
-
- Protect all strings by default
|
|
545
|
-
- Minification is allowed
|
|
770
|
+
## Development Bundling
|
|
546
771
|
|
|
547
|
-
|
|
772
|
+
`notBundle` is enabled by default in development. It externalizes Node modules in entry and main builds to improve startup speed.
|
|
548
773
|
|
|
549
|
-
|
|
550
|
-
|
|
774
|
+
```ts
|
|
775
|
+
electronWithUpdater({
|
|
776
|
+
notBundle: false,
|
|
777
|
+
entry: {
|
|
778
|
+
files: './electron/entry.ts',
|
|
779
|
+
},
|
|
780
|
+
main: {
|
|
781
|
+
files: './electron/main/index.ts',
|
|
782
|
+
},
|
|
783
|
+
})
|
|
784
|
+
```
|
|
551
785
|
|
|
552
|
-
|
|
786
|
+
## Utilities
|
|
553
787
|
|
|
554
|
-
|
|
788
|
+
Import from `electron-incremental-update/utils`:
|
|
555
789
|
|
|
556
790
|
```ts
|
|
557
791
|
import {
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
792
|
+
aesDecrypt,
|
|
793
|
+
aesEncrypt,
|
|
794
|
+
beautifyDevTools,
|
|
795
|
+
defaultIsLowerVersion,
|
|
796
|
+
defaultSignature,
|
|
797
|
+
defaultUnzipFile,
|
|
798
|
+
defaultVerifySignature,
|
|
799
|
+
defaultZipFile,
|
|
800
|
+
getAppVersion,
|
|
801
|
+
getEntryVersion,
|
|
563
802
|
getPathFromAppNameAsar,
|
|
564
803
|
getPathFromEntryAsar,
|
|
565
804
|
getPathFromMain,
|
|
566
805
|
getPathFromPreload,
|
|
567
806
|
getPathFromPublic,
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
requireNative,
|
|
807
|
+
handleUnexpectedErrors,
|
|
808
|
+
hashBuffer,
|
|
571
809
|
importNative,
|
|
810
|
+
isDev,
|
|
811
|
+
isLinux,
|
|
812
|
+
isMac,
|
|
813
|
+
isWin,
|
|
814
|
+
loadPage,
|
|
815
|
+
parseVersion,
|
|
816
|
+
requireNative,
|
|
572
817
|
restartApp,
|
|
573
818
|
setAppUserModelId,
|
|
574
|
-
disableHWAccForWin7,
|
|
575
|
-
singleInstance,
|
|
576
819
|
setPortableDataPath,
|
|
577
|
-
|
|
578
|
-
beautifyDevTools,
|
|
579
|
-
handleUnexpectedErrors,
|
|
580
|
-
|
|
581
|
-
// Crypto utilities
|
|
582
|
-
hashBuffer,
|
|
583
|
-
aesEncrypt,
|
|
584
|
-
aesDecrypt,
|
|
585
|
-
defaultSignature,
|
|
586
|
-
defaultVerifySignature,
|
|
587
|
-
|
|
588
|
-
// Zip utilities
|
|
589
|
-
defaultZipFile,
|
|
590
|
-
defaultUnzipFile,
|
|
820
|
+
singleInstance,
|
|
591
821
|
} from 'electron-incremental-update/utils'
|
|
592
822
|
```
|
|
593
823
|
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
-
|
|
597
|
-
-
|
|
598
|
-
-
|
|
599
|
-
-
|
|
600
|
-
-
|
|
601
|
-
-
|
|
602
|
-
-
|
|
603
|
-
-
|
|
604
|
-
-
|
|
605
|
-
-
|
|
606
|
-
-
|
|
607
|
-
-
|
|
608
|
-
- **importNative(moduleName)** - Load native module using import from entry asar
|
|
609
|
-
- **restartApp()** - Restart the Electron app
|
|
610
|
-
- **setAppUserModelId(id)** - Fix app model ID (Windows only)
|
|
611
|
-
- **disableHWAccForWin7()** - Disable hardware acceleration for Windows 7
|
|
612
|
-
- **singleInstance(window)** - Keep single instance and restore window
|
|
613
|
-
- **setPortableDataPath(dirName, create)** - Set userData dir to exe dir for portable apps
|
|
614
|
-
- **loadPage(win, htmlFilePath)** - Load dev server URL in dev or HTML file otherwise
|
|
615
|
-
- **beautifyDevTools(win, options)** - Beautify devtools font and scrollbar
|
|
616
|
-
- **handleUnexpectedErrors(callback)** - Handle all unhandled errors
|
|
617
|
-
|
|
618
|
-
#### Crypto Utilities
|
|
619
|
-
|
|
620
|
-
- **hashBuffer(data, length)** - Hash data using SHA-256
|
|
621
|
-
- **aesEncrypt(plainText, key, iv)** - Encrypt text using AES
|
|
622
|
-
- **aesDecrypt(encryptedText, key, iv)** - Decrypt text using AES
|
|
623
|
-
- **defaultSignature(buffer, privateKey, cert, version)** - Generate RSA signature for asar file
|
|
624
|
-
- **defaultVerifySignature(buffer, version, signature, cert)** - Verify RSA signature of asar file
|
|
625
|
-
|
|
626
|
-
#### Zip Utilities
|
|
627
|
-
|
|
628
|
-
- **defaultZipFile(buffer)** - Compress file using brotli
|
|
629
|
-
- **defaultUnzipFile(buffer)** - Decompress file using brotli
|
|
824
|
+
Common helpers:
|
|
825
|
+
|
|
826
|
+
- `getPathFromAppNameAsar(...paths)`: path inside `${app.name}.asar`.
|
|
827
|
+
- `getPathFromEntryAsar(...paths)`: path inside `app.asar`.
|
|
828
|
+
- `getPathFromMain(...paths)`: path inside the built main directory.
|
|
829
|
+
- `getPathFromPreload(...paths)`: path inside the built preload directory.
|
|
830
|
+
- `getPathFromPublic(...paths)`: path inside `public` in dev or renderer output in production.
|
|
831
|
+
- `getAppVersion()`: current app version. In dev, returns the entry version.
|
|
832
|
+
- `getEntryVersion()`: version from Electron app metadata.
|
|
833
|
+
- `loadPage(win, htmlFilePath)`: loads `VITE_DEV_SERVER_URL` in dev or renderer HTML in production.
|
|
834
|
+
- `singleInstance(window)`: restores and focuses the window on `second-instance`.
|
|
835
|
+
- `setPortableDataPath(dirName, create)`: stores user data beside the executable for portable apps.
|
|
836
|
+
- `requireNative(moduleName)`: loads a CommonJS native helper from entry asar.
|
|
837
|
+
- `importNative(moduleName)`: imports an ES module native helper from entry asar.
|
|
630
838
|
|
|
631
839
|
## Credits
|
|
632
840
|
|
|
633
|
-
- [Obsidian](https://obsidian.md/) for
|
|
634
|
-
- [vite-plugin-electron](https://github.com/electron-vite/vite-plugin-electron) for
|
|
635
|
-
- [electron-builder](https://github.com/electron-userland/electron-builder) for
|
|
841
|
+
- [Obsidian](https://obsidian.md/) for the dual asar update strategy
|
|
842
|
+
- [vite-plugin-electron](https://github.com/electron-vite/vite-plugin-electron) for the Vite Electron plugin foundation
|
|
843
|
+
- [electron-builder](https://github.com/electron-userland/electron-builder) for Electron packaging
|
|
636
844
|
- [electron-vite](https://github.com/alex8088/electron-vite) for bytecode plugin inspiration
|
|
637
845
|
|
|
638
846
|
## License
|