electron-incremental-update 0.8.0 → 0.8.2

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 CHANGED
@@ -1,22 +1,20 @@
1
1
  ## electron incremental updater
2
2
 
3
- provider a vite plugin and useful functions to generate updater and split entry file and real app
3
+ This project provide a vite plugin, `Updater` class and some useful functions to generate incremental update.
4
4
 
5
- ### principle
5
+ There will be two asar in production, `app.asar` and `main.asar` (if "main" is your app's name).
6
6
 
7
- using two asar, `app.asar` and `main.asar` (if "main" is your app's name)
7
+ The `app.asar` is used to load `main.asar` and initialize the `updater`. Also, all the **native modules**, which are set as `dependencies` in `package.json`, will be packaged into `app.asar` by `electron-builder`, [see usage](#use-native-modules).
8
8
 
9
- the `app.asar` is used to load `main.asar` and initialize the updater
10
-
11
- using RSA + Signature to sign the new `main.asar` downloaded from remote and replace the old one when verified
9
+ The new `main.asar` downloaded from remote will be verified by presigned RSA + Signature. When pass the check and restart, the old `main.asar` will be replaced by the new one. Hooks like `beforeDoUpdate` are provided.
12
10
 
13
11
  - inspired by Obsidian's update strategy
14
12
 
15
13
  ### notice
16
14
 
17
- develop with [vite-plugin-electron](https://github.com/electron-vite/vite-plugin-electron), and may be effect in other electron vite frameworks
18
-
19
- **all options are documented in the jsdoc**
15
+ - this plugin is developed with [vite-plugin-electron](https://github.com/electron-vite/vite-plugin-electron), and may be effect in other electron vite frameworks
16
+ - **all options are documented in the jsdoc**
17
+ - entry file's EOL will force to `\n`
20
18
 
21
19
  ## install
22
20
 
@@ -33,7 +31,7 @@ yarn add electron-incremental-update
33
31
  pnpm add electron-incremental-update
34
32
  ```
35
33
 
36
- ## usage
34
+ ## setup
37
35
 
38
36
  base on [electron-vite-vue](https://github.com/electron-vite/electron-vite-vue)
39
37
 
@@ -52,7 +50,6 @@ src
52
50
 
53
51
  ### setup app
54
52
 
55
-
56
53
  ```ts
57
54
  // electron/app.ts
58
55
  import { getGithubReleaseCdnGroup, initApp, parseGithubCdnURL } from 'electron-incremental-update'
@@ -74,80 +71,11 @@ initApp({ onStart: console.log })
74
71
  })
75
72
  ```
76
73
 
77
- ### usage in main process
78
-
79
- To utilize the electron `net` module for requesting update information, the `checkUpdate` and `download` functions must be called after the app is ready by default.
80
-
81
- However, you have the option to customize the download function when creating the updater.
82
-
83
- **NOTE: There can only be one function and should be default export in the entry file**
84
-
85
- ```ts
86
- // electron/main/index.ts
87
- import type { StartupWithUpdater, Updater } from 'electron-incremental-update'
88
- import { getEntryVersion, getProductAsarPath, getProductVersion } from 'electron-incremental-update'
89
- import { app } from 'electron'
90
- import { name } from '../../package.json'
91
-
92
- const startup: StartupWithUpdater = (updater: Updater) => {
93
- await app.whenReady()
94
- console.log('\ncurrent:')
95
- console.log(`\tasar path: ${getProductAsarPath(name)}`)
96
- console.log(`\tentry: ${getEntryVersion()}`)
97
- console.log(`\tapp: ${getProductVersion(name)}`)
98
- updater.onDownloading = ({ percent }) => {
99
- console.log(percent)
100
- }
101
- updater.logger = console
102
- updater.checkUpdate().then(async (result) => {
103
- if (result === undefined) {
104
- console.log('Update Unavailable')
105
- } else if (result instanceof Error) {
106
- console.error(result)
107
- } else {
108
- console.log('new version: ', result.version)
109
- const { response } = await dialog.showMessageBox({
110
- type: 'info',
111
- buttons: ['Download', 'Later'],
112
- message: 'Application update available!',
113
- })
114
- response === 0 && console.log(await updater.download())
115
- }
116
- })
117
- }
118
- export default startup
119
- ```
120
-
121
- ### use native modules
122
-
123
- ```ts
124
- // db.ts
125
- import { requireNative } from 'electron-incremental-update'
126
-
127
- const Database = requireNative<typeof import('better-sqlite3')>('better-sqlite3')
128
- const db = new Database(':memory:')
129
- db.exec(
130
- 'DROP TABLE IF EXISTS employees; '
131
- + 'CREATE TABLE IF NOT EXISTS employees (name TEXT, salary INTEGER)',
132
- )
133
-
134
- db.prepare('INSERT INTO employees VALUES (:n, :s)').run({
135
- n: 'James',
136
- s: 50000,
137
- })
138
-
139
- const r = db.prepare('SELECT * from employees').all()
140
- console.log(r)
141
- // [ { name: 'James', salary: 50000 } ]
142
-
143
- db.close()
144
- ```
145
-
146
74
  ### setup vite.config.ts
147
75
 
148
- make sure the plugin is set in the **last** build task plugin option
76
+ make sure the plugin is set in the **last** build task
149
77
 
150
- - set it to preload task plugin, as the end of build task
78
+ - for `vite-plugin-electron`, set it to `preload` (the second object in the plugin option array)
151
79
 
152
80
  ```ts
153
81
  // vite.config.ts
@@ -177,10 +105,14 @@ export default defineConfig(({ command }) => {
177
105
  // ...
178
106
  }
179
107
  },
108
+ // when using vite-plugin-electron-renderer
109
+ {
110
+ // ...
111
+ }
180
112
  ]),
181
- // ... other plugins
113
+ //...
182
114
  ],
183
- // ... other config
115
+ // ...
184
116
  }
185
117
  })
186
118
  ```
@@ -194,7 +126,7 @@ export default defineConfig(({ command }) => {
194
126
  }
195
127
  ```
196
128
 
197
- ### electron-builder config
129
+ ### config electron-builder
198
130
 
199
131
  ```js
200
132
  const { name } = require('./package.json')
@@ -225,7 +157,78 @@ module.exports = {
225
157
  extraResources: [
226
158
  { from: `release/${target}`, to: target }, // <- asar file
227
159
  ],
228
- publish: null,
160
+ publish: null, // <- disable publish
229
161
  // ...
230
162
  }
231
- ```
163
+ ```
164
+
165
+ ## Usage
166
+
167
+ ### use in main process
168
+
169
+ To use electron's `net` module for updating, the `checkUpdate` and `download` functions must be called after the app is ready by default.
170
+
171
+ However, you have the option to customize the download function when creating the updater.
172
+
173
+ **NOTE: There can only be one function and should be default export in the entry file**
174
+
175
+ ```ts
176
+ // electron/main/index.ts
177
+ import type { StartupWithUpdater, Updater } from 'electron-incremental-update'
178
+ import { getEntryVersion, getProductAsarPath, getProductVersion } from 'electron-incremental-update'
179
+ import { app } from 'electron'
180
+ import { name } from '../../package.json'
181
+
182
+ const startup: StartupWithUpdater = (updater: Updater) => {
183
+ await app.whenReady()
184
+ console.log('\ncurrent:')
185
+ console.log(`\tasar path: ${getProductAsarPath(name)}`)
186
+ console.log(`\tentry: ${getEntryVersion()}`)
187
+ console.log(`\tapp: ${getProductVersion(name)}`)
188
+ updater.onDownloading = ({ percent }) => {
189
+ console.log(percent)
190
+ }
191
+ updater.logger = console
192
+ updater.checkUpdate().then(async (result) => {
193
+ if (result === undefined) {
194
+ console.log('Update Unavailable')
195
+ } else if (result instanceof Error) {
196
+ console.error(result)
197
+ } else {
198
+ console.log('new version: ', result.version)
199
+ const { response } = await dialog.showMessageBox({
200
+ type: 'info',
201
+ buttons: ['Download', 'Later'],
202
+ message: 'Application update available!',
203
+ })
204
+ response === 0 && console.log(await updater.download())
205
+ }
206
+ })
207
+ }
208
+ export default startup
209
+ ```
210
+
211
+ ### use native modules
212
+
213
+ ```ts
214
+ // db.ts
215
+ import { requireNative } from 'electron-incremental-update'
216
+
217
+ const Database = requireNative<typeof import('better-sqlite3')>('better-sqlite3')
218
+ const db = new Database(':memory:')
219
+ db.exec(
220
+ 'DROP TABLE IF EXISTS employees; '
221
+ + 'CREATE TABLE IF NOT EXISTS employees (name TEXT, salary INTEGER)',
222
+ )
223
+
224
+ db.prepare('INSERT INTO employees VALUES (:n, :s)').run({
225
+ n: 'James',
226
+ s: 50000,
227
+ })
228
+
229
+ const r = db.prepare('SELECT * from employees').all()
230
+ console.log(r)
231
+ // [ { name: 'James', salary: 50000 } ]
232
+
233
+ db.close()
234
+ ```
@@ -1,6 +1,5 @@
1
1
  // src/crypto.ts
2
2
  import { createCipheriv, createDecipheriv, createHash, createPrivateKey, createSign, createVerify } from "node:crypto";
3
- import { Buffer } from "node:buffer";
4
3
  function encrypt(plainText, key2, iv) {
5
4
  const cipher = createCipheriv("aes-256-cbc", key2, iv);
6
5
  let encrypted = cipher.update(plainText, "utf8", "base64url");
@@ -140,7 +140,7 @@ function parseVersion(version) {
140
140
  ret.stage = stage;
141
141
  ret.stageVersion = Number(_v) || -1;
142
142
  }
143
- if (isNaN(major) || isNaN(minor) || isNaN(patch) || isNaN(ret.stageVersion)) {
143
+ if (Number.isNaN(major) || Number.isNaN(minor) || Number.isNaN(patch) || Number.isNaN(ret.stageVersion)) {
144
144
  throw new TypeError(`invalid version: ${version}`);
145
145
  }
146
146
  return ret;
package/dist/index.d.mts CHANGED
@@ -1,4 +1,3 @@
1
- import { Buffer } from 'node:buffer';
2
1
  import { UpdateJSON } from './updateJson.mjs';
3
2
 
4
3
  declare class MinimumVersionError extends Error {
@@ -14,31 +13,6 @@ declare class VerifyFailedError extends Error {
14
13
  declare class DownloadError extends Error {
15
14
  constructor(msg: string);
16
15
  }
17
- declare class IncrementalUpdater implements Updater {
18
- private info?;
19
- private option;
20
- private asarPath;
21
- private gzipPath;
22
- private tmpFilePath;
23
- logger?: Logger;
24
- onDownloading?: (progress: DownloadingInfo) => void;
25
- get productName(): string;
26
- set productName(name: string);
27
- get receiveBeta(): boolean;
28
- set receiveBeta(receiveBeta: boolean);
29
- constructor(option: UpdaterOption);
30
- private needUpdate;
31
- private parseData;
32
- checkUpdate(data?: string | UpdateJSON): Promise<CheckResultType>;
33
- download(data?: string | Buffer, sig?: string): Promise<DownloadResult>;
34
- }
35
- /**
36
- * create updater instance
37
- * @param option updater option
38
- * @returns updater
39
- */
40
- declare function createUpdater(option: UpdaterOption): IncrementalUpdater;
41
-
42
16
  type CheckResultError = MinimumVersionError | DownloadError | TypeError | Error;
43
17
  type DownloadResultError = DownloadError | VerifyFailedError | TypeError | Error;
44
18
  type CheckResultType = {
@@ -67,7 +41,13 @@ type Logger = {
67
41
  error: (msg: string, e?: Error) => void;
68
42
  };
69
43
  interface Updater {
44
+ /**
45
+ * the name of the product, also the basename of the asar
46
+ */
70
47
  productName: string;
48
+ /**
49
+ * whether receive beta version
50
+ */
71
51
  receiveBeta: boolean;
72
52
  /**
73
53
  * check update info
@@ -94,6 +74,11 @@ interface Updater {
94
74
  * @param data log info
95
75
  */
96
76
  logger?: Logger;
77
+ /**
78
+ * download progress function
79
+ * @param progress download progress info
80
+ * @returns void
81
+ */
97
82
  onDownloading?: (progress: DownloadingInfo) => void;
98
83
  }
99
84
  type UpdaterOverrideFunctions = {
@@ -115,7 +100,6 @@ type UpdaterOverrideFunctions = {
115
100
  /**
116
101
  * custom download JSON function
117
102
  * @param url download url
118
- * @param updater updater, to trigger events
119
103
  * @param header download header
120
104
  * @returns `UpdateJSON`
121
105
  */
@@ -123,8 +107,9 @@ type UpdaterOverrideFunctions = {
123
107
  /**
124
108
  * custom download buffer function
125
109
  * @param url download url
126
- * @param updater updater, to trigger events
127
- * @param header download header
110
+ * @param headers download header
111
+ * @param total precaculated file total size
112
+ * @param onDownloading on downloading callback
128
113
  * @returns `Buffer`
129
114
  */
130
115
  downloadBuffer?: (url: string, headers: Record<string, any>, total: number, onDownloading?: (progress: DownloadingInfo) => void) => Promise<Buffer>;
@@ -190,6 +175,32 @@ interface UpdaterOption {
190
175
  downloadConfig?: UpdaterDownloadConfig;
191
176
  }
192
177
 
178
+ declare class IncrementalUpdater implements Updater {
179
+ private info?;
180
+ private option;
181
+ private asarPath;
182
+ private gzipPath;
183
+ private tmpFilePath;
184
+ logger?: Logger;
185
+ onDownloading?: (progress: DownloadingInfo) => void;
186
+ get productName(): string;
187
+ set productName(name: string);
188
+ get receiveBeta(): boolean;
189
+ set receiveBeta(receiveBeta: boolean);
190
+ constructor(option: UpdaterOption);
191
+ private needUpdate;
192
+ private parseData;
193
+ checkUpdate(data?: string | UpdateJSON): Promise<CheckResultType>;
194
+ download(data?: string | Buffer, sig?: string): Promise<DownloadResult>;
195
+ }
196
+ /**
197
+ * create updater instance
198
+ * @param option updater option
199
+ * @returns updater
200
+ */
201
+ declare function createUpdater(option: UpdaterOption): IncrementalUpdater;
202
+
203
+ type Promisable<T> = T | Promise<T>;
193
204
  type AppOption = {
194
205
  /**
195
206
  * path of electron output dist when in development
@@ -204,12 +215,15 @@ type AppOption = {
204
215
  hooks?: {
205
216
  /**
206
217
  * hooks before replace the old asar is replaced by the new asar
218
+ *
219
+ * @param oldAsarPath old asar path
220
+ * @param updateTempAsarPath new asar path, end with .tmp
207
221
  */
208
- beforeDoUpdate?: (updateTempAsarPath: string) => void | Promise<void>;
222
+ beforeDoUpdate?: (oldAsarPath: string, updateTempAsarPath: string) => Promisable<void>;
209
223
  /**
210
- * hooks on start up
224
+ * hooks before start up
211
225
  */
212
- onStart?: (productAsarPath: string) => void;
226
+ beforeStart?: (productAsarPath: string) => Promisable<void>;
213
227
  /**
214
228
  * hooks on start up error
215
229
  */
@@ -221,7 +235,7 @@ type SetUpdater = {
221
235
  /**
222
236
  * set updater option or create function
223
237
  */
224
- setUpdater: (updater: (() => Updater | Promise<Updater>) | UpdaterOption) => void;
238
+ setUpdater: (updater: (() => Promisable<Updater>) | UpdaterOption) => void;
225
239
  };
226
240
  /**
227
241
  * initialize app
@@ -247,4 +261,4 @@ type SetUpdater = {
247
261
  */
248
262
  declare function initApp(appOptions?: AppOption): SetUpdater;
249
263
 
250
- export { AppOption, DownloadError, IncrementalUpdater, MinimumVersionError, StartupWithUpdater, Updater, UpdaterOption, VerifyFailedError, createUpdater, initApp };
264
+ export { AppOption, IncrementalUpdater, StartupWithUpdater, Updater, UpdaterOption, createUpdater, initApp };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- import { Buffer } from 'node:buffer';
2
1
  import { UpdateJSON } from './updateJson.js';
3
2
 
4
3
  declare class MinimumVersionError extends Error {
@@ -14,31 +13,6 @@ declare class VerifyFailedError extends Error {
14
13
  declare class DownloadError extends Error {
15
14
  constructor(msg: string);
16
15
  }
17
- declare class IncrementalUpdater implements Updater {
18
- private info?;
19
- private option;
20
- private asarPath;
21
- private gzipPath;
22
- private tmpFilePath;
23
- logger?: Logger;
24
- onDownloading?: (progress: DownloadingInfo) => void;
25
- get productName(): string;
26
- set productName(name: string);
27
- get receiveBeta(): boolean;
28
- set receiveBeta(receiveBeta: boolean);
29
- constructor(option: UpdaterOption);
30
- private needUpdate;
31
- private parseData;
32
- checkUpdate(data?: string | UpdateJSON): Promise<CheckResultType>;
33
- download(data?: string | Buffer, sig?: string): Promise<DownloadResult>;
34
- }
35
- /**
36
- * create updater instance
37
- * @param option updater option
38
- * @returns updater
39
- */
40
- declare function createUpdater(option: UpdaterOption): IncrementalUpdater;
41
-
42
16
  type CheckResultError = MinimumVersionError | DownloadError | TypeError | Error;
43
17
  type DownloadResultError = DownloadError | VerifyFailedError | TypeError | Error;
44
18
  type CheckResultType = {
@@ -67,7 +41,13 @@ type Logger = {
67
41
  error: (msg: string, e?: Error) => void;
68
42
  };
69
43
  interface Updater {
44
+ /**
45
+ * the name of the product, also the basename of the asar
46
+ */
70
47
  productName: string;
48
+ /**
49
+ * whether receive beta version
50
+ */
71
51
  receiveBeta: boolean;
72
52
  /**
73
53
  * check update info
@@ -94,6 +74,11 @@ interface Updater {
94
74
  * @param data log info
95
75
  */
96
76
  logger?: Logger;
77
+ /**
78
+ * download progress function
79
+ * @param progress download progress info
80
+ * @returns void
81
+ */
97
82
  onDownloading?: (progress: DownloadingInfo) => void;
98
83
  }
99
84
  type UpdaterOverrideFunctions = {
@@ -115,7 +100,6 @@ type UpdaterOverrideFunctions = {
115
100
  /**
116
101
  * custom download JSON function
117
102
  * @param url download url
118
- * @param updater updater, to trigger events
119
103
  * @param header download header
120
104
  * @returns `UpdateJSON`
121
105
  */
@@ -123,8 +107,9 @@ type UpdaterOverrideFunctions = {
123
107
  /**
124
108
  * custom download buffer function
125
109
  * @param url download url
126
- * @param updater updater, to trigger events
127
- * @param header download header
110
+ * @param headers download header
111
+ * @param total precaculated file total size
112
+ * @param onDownloading on downloading callback
128
113
  * @returns `Buffer`
129
114
  */
130
115
  downloadBuffer?: (url: string, headers: Record<string, any>, total: number, onDownloading?: (progress: DownloadingInfo) => void) => Promise<Buffer>;
@@ -190,6 +175,32 @@ interface UpdaterOption {
190
175
  downloadConfig?: UpdaterDownloadConfig;
191
176
  }
192
177
 
178
+ declare class IncrementalUpdater implements Updater {
179
+ private info?;
180
+ private option;
181
+ private asarPath;
182
+ private gzipPath;
183
+ private tmpFilePath;
184
+ logger?: Logger;
185
+ onDownloading?: (progress: DownloadingInfo) => void;
186
+ get productName(): string;
187
+ set productName(name: string);
188
+ get receiveBeta(): boolean;
189
+ set receiveBeta(receiveBeta: boolean);
190
+ constructor(option: UpdaterOption);
191
+ private needUpdate;
192
+ private parseData;
193
+ checkUpdate(data?: string | UpdateJSON): Promise<CheckResultType>;
194
+ download(data?: string | Buffer, sig?: string): Promise<DownloadResult>;
195
+ }
196
+ /**
197
+ * create updater instance
198
+ * @param option updater option
199
+ * @returns updater
200
+ */
201
+ declare function createUpdater(option: UpdaterOption): IncrementalUpdater;
202
+
203
+ type Promisable<T> = T | Promise<T>;
193
204
  type AppOption = {
194
205
  /**
195
206
  * path of electron output dist when in development
@@ -204,12 +215,15 @@ type AppOption = {
204
215
  hooks?: {
205
216
  /**
206
217
  * hooks before replace the old asar is replaced by the new asar
218
+ *
219
+ * @param oldAsarPath old asar path
220
+ * @param updateTempAsarPath new asar path, end with .tmp
207
221
  */
208
- beforeDoUpdate?: (updateTempAsarPath: string) => void | Promise<void>;
222
+ beforeDoUpdate?: (oldAsarPath: string, updateTempAsarPath: string) => Promisable<void>;
209
223
  /**
210
- * hooks on start up
224
+ * hooks before start up
211
225
  */
212
- onStart?: (productAsarPath: string) => void;
226
+ beforeStart?: (productAsarPath: string) => Promisable<void>;
213
227
  /**
214
228
  * hooks on start up error
215
229
  */
@@ -221,7 +235,7 @@ type SetUpdater = {
221
235
  /**
222
236
  * set updater option or create function
223
237
  */
224
- setUpdater: (updater: (() => Updater | Promise<Updater>) | UpdaterOption) => void;
238
+ setUpdater: (updater: (() => Promisable<Updater>) | UpdaterOption) => void;
225
239
  };
226
240
  /**
227
241
  * initialize app
@@ -247,4 +261,4 @@ type SetUpdater = {
247
261
  */
248
262
  declare function initApp(appOptions?: AppOption): SetUpdater;
249
263
 
250
- export { AppOption, DownloadError, IncrementalUpdater, MinimumVersionError, StartupWithUpdater, Updater, UpdaterOption, VerifyFailedError, createUpdater, initApp };
264
+ export { AppOption, IncrementalUpdater, StartupWithUpdater, Updater, UpdaterOption, createUpdater, initApp };
package/dist/index.js CHANGED
@@ -20,10 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var src_exports = {};
22
22
  __export(src_exports, {
23
- DownloadError: () => DownloadError,
24
23
  IncrementalUpdater: () => IncrementalUpdater,
25
- MinimumVersionError: () => MinimumVersionError,
26
- VerifyFailedError: () => VerifyFailedError,
27
24
  createUpdater: () => createUpdater,
28
25
  initApp: () => initApp
29
26
  });
@@ -34,7 +31,6 @@ var import_electron3 = require("electron");
34
31
 
35
32
  // src/updater/index.ts
36
33
  var import_node_fs2 = require("fs");
37
- var import_node_buffer3 = require("buffer");
38
34
  var import_promises = require("fs/promises");
39
35
 
40
36
  // src/utils.ts
@@ -97,7 +93,7 @@ function parseVersion(version) {
97
93
  ret.stage = stage;
98
94
  ret.stageVersion = Number(_v) || -1;
99
95
  }
100
- if (isNaN(major) || isNaN(minor) || isNaN(patch) || isNaN(ret.stageVersion)) {
96
+ if (Number.isNaN(major) || Number.isNaN(minor) || Number.isNaN(patch) || Number.isNaN(ret.stageVersion)) {
101
97
  throw new TypeError(`invalid version: ${version}`);
102
98
  }
103
99
  return ret;
@@ -105,7 +101,6 @@ function parseVersion(version) {
105
101
 
106
102
  // src/crypto.ts
107
103
  var import_node_crypto = require("crypto");
108
- var import_node_buffer = require("buffer");
109
104
  function decrypt(encryptedText, key2, iv) {
110
105
  const decipher = (0, import_node_crypto.createDecipheriv)("aes-256-cbc", key2, iv);
111
106
  let decrypted = decipher.update(encryptedText, "base64url", "utf8");
@@ -114,7 +109,7 @@ function decrypt(encryptedText, key2, iv) {
114
109
  }
115
110
  function key(data, length) {
116
111
  const hash = (0, import_node_crypto.createHash)("SHA256").update(data).digest("binary");
117
- return import_node_buffer.Buffer.from(hash).subarray(0, length);
112
+ return Buffer.from(hash).subarray(0, length);
118
113
  }
119
114
  var verify = (buffer, signature, cert) => {
120
115
  try {
@@ -132,8 +127,32 @@ function isUpdateJSON(json) {
132
127
  return is(json) && "beta" in json && is(json.beta);
133
128
  }
134
129
 
130
+ // src/updater/types.ts
131
+ var MinimumVersionError = class extends Error {
132
+ currentVersion;
133
+ minVersion;
134
+ constructor(version, minimumVersion) {
135
+ super(`current entry version is ${version}, less than the minimumVersion ${minimumVersion}`);
136
+ this.currentVersion = version;
137
+ this.minVersion = minimumVersion;
138
+ }
139
+ };
140
+ var VerifyFailedError = class extends Error {
141
+ signature;
142
+ cert;
143
+ constructor(signature, cert) {
144
+ super("verify failed, invalid signature or certificate");
145
+ this.signature = signature;
146
+ this.cert = cert;
147
+ }
148
+ };
149
+ var DownloadError = class extends Error {
150
+ constructor(msg) {
151
+ super(`download update error, ${msg}`);
152
+ }
153
+ };
154
+
135
155
  // src/updater/defaultFunctions.ts
136
- var import_node_buffer2 = require("buffer");
137
156
  var import_electron2 = require("electron");
138
157
  var downloadJSONDefault = async (url, headers) => {
139
158
  await waitAppReady();
@@ -192,7 +211,7 @@ var downloadBufferDefault = async (url, headers, total, onDownloading) => {
192
211
  data.push(chunk);
193
212
  });
194
213
  res.on("end", () => {
195
- resolve2(import_node_buffer2.Buffer.concat(data));
214
+ resolve2(Buffer.concat(data));
196
215
  });
197
216
  }).on("error", (e) => {
198
217
  reject(e);
@@ -222,29 +241,6 @@ var compareVersionDefault = (version1, version2) => {
222
241
  };
223
242
 
224
243
  // src/updater/index.ts
225
- var MinimumVersionError = class extends Error {
226
- currentVersion;
227
- minVersion;
228
- constructor(version, minimumVersion) {
229
- super(`current entry version is ${version}, less than the minimumVersion ${minimumVersion}`);
230
- this.currentVersion = version;
231
- this.minVersion = minimumVersion;
232
- }
233
- };
234
- var VerifyFailedError = class extends Error {
235
- signature;
236
- cert;
237
- constructor(signature, cert) {
238
- super("verify failed, invalid signature or certificate");
239
- this.signature = signature;
240
- this.cert = cert;
241
- }
242
- };
243
- var DownloadError = class extends Error {
244
- constructor(msg) {
245
- super(`download update error, ${msg}`);
246
- }
247
- };
248
244
  var IncrementalUpdater = class {
249
245
  info;
250
246
  option;
@@ -293,7 +289,7 @@ var IncrementalUpdater = class {
293
289
  if (!["string", "object", "undefined"].includes(typeof data)) {
294
290
  throw new TypeError(`invalid type at format '${format}': ${data}`);
295
291
  }
296
- if (typeof data === "object" && (format === "json" && isUpdateJSON(data) || format === "buffer" && import_node_buffer3.Buffer.isBuffer(data))) {
292
+ if (typeof data === "object" && (format === "json" && isUpdateJSON(data) || format === "buffer" && Buffer.isBuffer(data))) {
297
293
  return data;
298
294
  }
299
295
  if (typeof data === "object") {
@@ -405,7 +401,7 @@ function initApp(appOptions) {
405
401
  } = appOptions || {};
406
402
  const {
407
403
  beforeDoUpdate,
408
- onStart,
404
+ beforeStart,
409
405
  onStartError
410
406
  } = hooks || {};
411
407
  function handleError(msg) {
@@ -415,13 +411,14 @@ function initApp(appOptions) {
415
411
  async function startup(updater) {
416
412
  try {
417
413
  const asarPath = getProductAsarPath(updater.productName);
418
- if ((0, import_node_fs3.existsSync)(`${asarPath}.tmp`)) {
419
- await beforeDoUpdate?.(asarPath);
420
- (0, import_node_fs3.renameSync)(`${asarPath}.tmp`, asarPath);
414
+ const updateAsarPath = `${asarPath}.tmp`;
415
+ if ((0, import_node_fs3.existsSync)(updateAsarPath)) {
416
+ await beforeDoUpdate?.(asarPath, updateAsarPath);
417
+ (0, import_node_fs3.renameSync)(updateAsarPath, asarPath);
421
418
  }
422
419
  const mainDir = import_electron3.app.isPackaged ? asarPath : electronDevDistPath;
423
420
  const entry = (0, import_node_path2.resolve)(__dirname, mainDir, mainPath);
424
- onStart?.(entry);
421
+ await beforeStart?.(entry);
425
422
  require(entry)(updater);
426
423
  } catch (error) {
427
424
  handleError(`failed to start app, ${error}`);
@@ -445,10 +442,7 @@ function initApp(appOptions) {
445
442
  }
446
443
  // Annotate the CommonJS export names for ESM import in node:
447
444
  0 && (module.exports = {
448
- DownloadError,
449
445
  IncrementalUpdater,
450
- MinimumVersionError,
451
- VerifyFailedError,
452
446
  createUpdater,
453
447
  initApp
454
448
  });
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  verify
3
- } from "./chunk-Q2K52LOG.mjs";
3
+ } from "./chunk-GXZSAUBR.mjs";
4
4
  import {
5
5
  getEntryVersion,
6
6
  getProductAsarPath,
@@ -8,7 +8,7 @@ import {
8
8
  parseVersion,
9
9
  unzipFile,
10
10
  waitAppReady
11
- } from "./chunk-4TION32M.mjs";
11
+ } from "./chunk-WM2PHOMB.mjs";
12
12
  import {
13
13
  isUpdateJSON
14
14
  } from "./chunk-2JVXVTC5.mjs";
@@ -23,11 +23,34 @@ import { app } from "electron";
23
23
 
24
24
  // src/updater/index.ts
25
25
  import { existsSync } from "node:fs";
26
- import { Buffer as Buffer2 } from "node:buffer";
27
26
  import { rm, writeFile } from "node:fs/promises";
28
27
 
28
+ // src/updater/types.ts
29
+ var MinimumVersionError = class extends Error {
30
+ currentVersion;
31
+ minVersion;
32
+ constructor(version, minimumVersion) {
33
+ super(`current entry version is ${version}, less than the minimumVersion ${minimumVersion}`);
34
+ this.currentVersion = version;
35
+ this.minVersion = minimumVersion;
36
+ }
37
+ };
38
+ var VerifyFailedError = class extends Error {
39
+ signature;
40
+ cert;
41
+ constructor(signature, cert) {
42
+ super("verify failed, invalid signature or certificate");
43
+ this.signature = signature;
44
+ this.cert = cert;
45
+ }
46
+ };
47
+ var DownloadError = class extends Error {
48
+ constructor(msg) {
49
+ super(`download update error, ${msg}`);
50
+ }
51
+ };
52
+
29
53
  // src/updater/defaultFunctions.ts
30
- import { Buffer } from "node:buffer";
31
54
  import { net } from "electron";
32
55
  var downloadJSONDefault = async (url, headers) => {
33
56
  await waitAppReady();
@@ -116,29 +139,6 @@ var compareVersionDefault = (version1, version2) => {
116
139
  };
117
140
 
118
141
  // src/updater/index.ts
119
- var MinimumVersionError = class extends Error {
120
- currentVersion;
121
- minVersion;
122
- constructor(version, minimumVersion) {
123
- super(`current entry version is ${version}, less than the minimumVersion ${minimumVersion}`);
124
- this.currentVersion = version;
125
- this.minVersion = minimumVersion;
126
- }
127
- };
128
- var VerifyFailedError = class extends Error {
129
- signature;
130
- cert;
131
- constructor(signature, cert) {
132
- super("verify failed, invalid signature or certificate");
133
- this.signature = signature;
134
- this.cert = cert;
135
- }
136
- };
137
- var DownloadError = class extends Error {
138
- constructor(msg) {
139
- super(`download update error, ${msg}`);
140
- }
141
- };
142
142
  var IncrementalUpdater = class {
143
143
  info;
144
144
  option;
@@ -187,7 +187,7 @@ var IncrementalUpdater = class {
187
187
  if (!["string", "object", "undefined"].includes(typeof data)) {
188
188
  throw new TypeError(`invalid type at format '${format}': ${data}`);
189
189
  }
190
- if (typeof data === "object" && (format === "json" && isUpdateJSON(data) || format === "buffer" && Buffer2.isBuffer(data))) {
190
+ if (typeof data === "object" && (format === "json" && isUpdateJSON(data) || format === "buffer" && Buffer.isBuffer(data))) {
191
191
  return data;
192
192
  }
193
193
  if (typeof data === "object") {
@@ -299,7 +299,7 @@ function initApp(appOptions) {
299
299
  } = appOptions || {};
300
300
  const {
301
301
  beforeDoUpdate,
302
- onStart,
302
+ beforeStart,
303
303
  onStartError
304
304
  } = hooks || {};
305
305
  function handleError(msg) {
@@ -309,13 +309,14 @@ function initApp(appOptions) {
309
309
  async function startup(updater) {
310
310
  try {
311
311
  const asarPath = getProductAsarPath(updater.productName);
312
- if (existsSync2(`${asarPath}.tmp`)) {
313
- await beforeDoUpdate?.(asarPath);
314
- renameSync(`${asarPath}.tmp`, asarPath);
312
+ const updateAsarPath = `${asarPath}.tmp`;
313
+ if (existsSync2(updateAsarPath)) {
314
+ await beforeDoUpdate?.(asarPath, updateAsarPath);
315
+ renameSync(updateAsarPath, asarPath);
315
316
  }
316
317
  const mainDir = app.isPackaged ? asarPath : electronDevDistPath;
317
318
  const entry = resolve(__dirname, mainDir, mainPath);
318
- onStart?.(entry);
319
+ await beforeStart?.(entry);
319
320
  __require(entry)(updater);
320
321
  } catch (error) {
321
322
  handleError(`failed to start app, ${error}`);
@@ -338,10 +339,7 @@ function initApp(appOptions) {
338
339
  };
339
340
  }
340
341
  export {
341
- DownloadError,
342
342
  IncrementalUpdater,
343
- MinimumVersionError,
344
- VerifyFailedError,
345
343
  createUpdater,
346
344
  initApp
347
345
  };
package/dist/utils.d.mts CHANGED
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * get the application asar absolute path
3
3
  * @param name The name of the application
4
+ * @todo support v8 bytecode
4
5
  */
5
6
  declare function getProductAsarPath(name: string): string;
6
7
  /**
package/dist/utils.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * get the application asar absolute path
3
3
  * @param name The name of the application
4
+ * @todo support v8 bytecode
4
5
  */
5
6
  declare function getProductAsarPath(name: string): string;
6
7
  /**
package/dist/utils.js CHANGED
@@ -173,7 +173,7 @@ function parseVersion(version) {
173
173
  ret.stage = stage;
174
174
  ret.stageVersion = Number(_v) || -1;
175
175
  }
176
- if (isNaN(major) || isNaN(minor) || isNaN(patch) || isNaN(ret.stageVersion)) {
176
+ if (Number.isNaN(major) || Number.isNaN(minor) || Number.isNaN(patch) || Number.isNaN(ret.stageVersion)) {
177
177
  throw new TypeError(`invalid version: ${version}`);
178
178
  }
179
179
  return ret;
package/dist/utils.mjs CHANGED
@@ -13,7 +13,7 @@ import {
13
13
  unzipFile,
14
14
  waitAppReady,
15
15
  zipFile
16
- } from "./chunk-4TION32M.mjs";
16
+ } from "./chunk-WM2PHOMB.mjs";
17
17
  import "./chunk-ZFXKCRJC.mjs";
18
18
  export {
19
19
  NoSuchNativeModuleError,
package/dist/vite.d.mts CHANGED
@@ -1,5 +1,4 @@
1
1
  import { Plugin } from 'vite';
2
- import { Buffer } from 'node:buffer';
3
2
  import { UpdateJSON } from './updateJson.mjs';
4
3
 
5
4
  type DistinguishedName = {
package/dist/vite.d.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import { Plugin } from 'vite';
2
- import { Buffer } from 'node:buffer';
3
2
  import { UpdateJSON } from './updateJson.js';
4
3
 
5
4
  type DistinguishedName = {
package/dist/vite.js CHANGED
@@ -33,7 +33,6 @@ var import_esbuild = require("esbuild");
33
33
 
34
34
  // src/crypto.ts
35
35
  var import_node_crypto = require("crypto");
36
- var import_node_buffer = require("buffer");
37
36
  function encrypt(plainText, key2, iv) {
38
37
  const cipher = (0, import_node_crypto.createCipheriv)("aes-256-cbc", key2, iv);
39
38
  let encrypted = cipher.update(plainText, "utf8", "base64url");
@@ -42,7 +41,7 @@ function encrypt(plainText, key2, iv) {
42
41
  }
43
42
  function key(data, length) {
44
43
  const hash = (0, import_node_crypto.createHash)("SHA256").update(data).digest("binary");
45
- return import_node_buffer.Buffer.from(hash).subarray(0, length);
44
+ return Buffer.from(hash).subarray(0, length);
46
45
  }
47
46
  var signature = (buffer, privateKey, cert, version) => {
48
47
  const sig = (0, import_node_crypto.createSign)("RSA-SHA256").update(buffer).sign((0, import_node_crypto.createPrivateKey)(privateKey), "base64");
@@ -88,7 +87,7 @@ function parseVersion(version) {
88
87
  ret.stage = stage;
89
88
  ret.stageVersion = Number(_v) || -1;
90
89
  }
91
- if (isNaN(major) || isNaN(minor) || isNaN(patch) || isNaN(ret.stageVersion)) {
90
+ if (Number.isNaN(major) || Number.isNaN(minor) || Number.isNaN(patch) || Number.isNaN(ret.stageVersion)) {
92
91
  throw new TypeError(`invalid version: ${version}`);
93
92
  }
94
93
  return ret;
@@ -203,7 +202,7 @@ function generateKeyPair(keyLength, subject, days, privateKeyPath, certPath) {
203
202
  }
204
203
  function writeCertToMain(entryPath, cert) {
205
204
  const file = (0, import_node_fs3.readFileSync)(entryPath, "utf-8");
206
- const regex = /const SIGNATURE_CERT = ['`][\s\S]*?['`]/;
205
+ const regex = /const SIGNATURE_CERT\s*=\s*['"`][\s\S]*?['"`]/;
207
206
  const replacement = `const SIGNATURE_CERT = \`${cert}\``;
208
207
  let replaced = file;
209
208
  const signaturePubExists = regex.test(file);
package/dist/vite.mjs CHANGED
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  signature
3
- } from "./chunk-Q2K52LOG.mjs";
3
+ } from "./chunk-GXZSAUBR.mjs";
4
4
  import {
5
5
  parseVersion,
6
6
  zipFile
7
- } from "./chunk-4TION32M.mjs";
7
+ } from "./chunk-WM2PHOMB.mjs";
8
8
  import {
9
9
  isUpdateJSON
10
10
  } from "./chunk-2JVXVTC5.mjs";
@@ -120,7 +120,7 @@ function generateKeyPair(keyLength, subject, days, privateKeyPath, certPath) {
120
120
  }
121
121
  function writeCertToMain(entryPath, cert) {
122
122
  const file = readFileSync(entryPath, "utf-8");
123
- const regex = /const SIGNATURE_CERT = ['`][\s\S]*?['`]/;
123
+ const regex = /const SIGNATURE_CERT\s*=\s*['"`][\s\S]*?['"`]/;
124
124
  const replacement = `const SIGNATURE_CERT = \`${cert}\``;
125
125
  let replaced = file;
126
126
  const signaturePubExists = regex.test(file);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "electron-incremental-update",
3
3
  "author": "subframe7536",
4
- "version": "0.8.0",
4
+ "version": "0.8.2",
5
5
  "description": "electron incremental update tools, powered by vite",
6
6
  "scripts": {
7
7
  "build": "tsup && node fix-module.js",
@@ -43,19 +43,19 @@
43
43
  "updater"
44
44
  ],
45
45
  "devDependencies": {
46
- "@subframe7536/eslint-config": "^0.1.9",
47
- "@types/node": "^20.3.2",
46
+ "@subframe7536/eslint-config": "^0.2.5",
47
+ "@types/node": "^20.5.1",
48
48
  "bumpp": "^9.1.1",
49
- "electron": "^25.2.0",
50
- "eslint": "^8.43.0",
51
- "tsup": "^7.1.0",
52
- "typescript": "^5.1.5",
53
- "vite": "^4.3.9",
54
- "vitest": "^0.32.2"
49
+ "electron": "^26.0.0",
50
+ "eslint": "^8.47.0",
51
+ "tsup": "^7.2.0",
52
+ "typescript": "^5.1.6",
53
+ "vitest": "^0.34.2"
55
54
  },
56
55
  "dependencies": {
57
56
  "@electron/asar": "^3.2.4",
58
57
  "ci-info": "^3.8.0",
59
- "selfsigned": "^2.1.1"
58
+ "selfsigned": "^2.1.1",
59
+ "vite": "^4.4.9"
60
60
  }
61
61
  }