electron-incremental-update 0.6.1 → 0.6.3
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 +14 -2
- package/dist/{chunk-VADH6AZA.mjs → chunk-XQ4Z2OVN.mjs} +5 -5
- package/dist/index.cjs +14 -8
- package/dist/index.d.cts +237 -0
- package/dist/index.d.ts +32 -19
- package/dist/index.mjs +13 -7
- package/dist/vite.cjs +44 -36
- package/dist/vite.d.cts +129 -0
- package/dist/vite.d.ts +22 -0
- package/dist/vite.mjs +43 -35
- package/package.json +24 -22
package/README.md
CHANGED
|
@@ -82,14 +82,16 @@ To utilize the electron `net` module for requesting update information, the `che
|
|
|
82
82
|
|
|
83
83
|
However, you have the option to customize the download function when creating the updater.
|
|
84
84
|
|
|
85
|
+
**NOTE: There can only be one function and should be default export in the entry file**
|
|
86
|
+
|
|
85
87
|
```ts
|
|
86
88
|
// electron/main/index.ts
|
|
87
|
-
import type { Updater } from 'electron-incremental-update'
|
|
89
|
+
import type { StartupWithUpdater, Updater } from 'electron-incremental-update'
|
|
88
90
|
import { getEntryVersion, getProductAsarPath, getProductVersion } from 'electron-incremental-update'
|
|
89
91
|
import { app } from 'electron'
|
|
90
92
|
import { name } from '../../package.json'
|
|
91
93
|
|
|
92
|
-
|
|
94
|
+
const startup: StartupWithUpdater = (updater: Updater) => {
|
|
93
95
|
await app.whenReady()
|
|
94
96
|
console.log('\ncurrent:')
|
|
95
97
|
console.log(`\tasar path: ${getProductAsarPath(name)}`)
|
|
@@ -117,6 +119,7 @@ export default function (updater: Updater) {
|
|
|
117
119
|
}
|
|
118
120
|
})
|
|
119
121
|
}
|
|
122
|
+
export default startup
|
|
120
123
|
```
|
|
121
124
|
|
|
122
125
|
### use native modules
|
|
@@ -186,6 +189,15 @@ export default defineConfig(({ command }) => {
|
|
|
186
189
|
})
|
|
187
190
|
```
|
|
188
191
|
|
|
192
|
+
### modify package.json
|
|
193
|
+
|
|
194
|
+
```json
|
|
195
|
+
{
|
|
196
|
+
// ...
|
|
197
|
+
"main": "app.js" // <- app entry file
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
189
201
|
### electron-builder config
|
|
190
202
|
|
|
191
203
|
```js
|
|
@@ -3,7 +3,7 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
3
3
|
}) : x)(function(x) {
|
|
4
4
|
if (typeof require !== "undefined")
|
|
5
5
|
return require.apply(this, arguments);
|
|
6
|
-
throw
|
|
6
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
7
7
|
});
|
|
8
8
|
|
|
9
9
|
// src/crypto.ts
|
|
@@ -26,15 +26,15 @@ function key(data, length) {
|
|
|
26
26
|
const hash = createHash("SHA256").update(data).digest("binary");
|
|
27
27
|
return Buffer2.from(hash).subarray(0, length);
|
|
28
28
|
}
|
|
29
|
-
|
|
29
|
+
var signature = (buffer, privateKey, cert, version) => {
|
|
30
30
|
const sig = createSign("RSA-SHA256").update(buffer).sign({
|
|
31
31
|
key: privateKey,
|
|
32
32
|
padding: constants.RSA_PKCS1_PADDING,
|
|
33
33
|
saltLength: constants.RSA_PSS_SALTLEN_DIGEST
|
|
34
34
|
}, "base64");
|
|
35
35
|
return encrypt(`${sig}%${version}`, key(cert, 32), key(buffer, 16));
|
|
36
|
-
}
|
|
37
|
-
|
|
36
|
+
};
|
|
37
|
+
var verify = (buffer, signature2, cert) => {
|
|
38
38
|
try {
|
|
39
39
|
const [sig, version] = decrypt(signature2, key(cert, 32), key(buffer, 16)).split("%");
|
|
40
40
|
const result = createVerify("RSA-SHA256").update(buffer).verify(cert, sig, "base64");
|
|
@@ -42,7 +42,7 @@ function verify(buffer, signature2, cert) {
|
|
|
42
42
|
} catch (error) {
|
|
43
43
|
return false;
|
|
44
44
|
}
|
|
45
|
-
}
|
|
45
|
+
};
|
|
46
46
|
|
|
47
47
|
export {
|
|
48
48
|
__require,
|
package/dist/index.cjs
CHANGED
|
@@ -59,7 +59,7 @@ function key(data, length) {
|
|
|
59
59
|
const hash = (0, import_node_crypto.createHash)("SHA256").update(data).digest("binary");
|
|
60
60
|
return import_node_buffer.Buffer.from(hash).subarray(0, length);
|
|
61
61
|
}
|
|
62
|
-
|
|
62
|
+
var verify = (buffer, signature, cert) => {
|
|
63
63
|
try {
|
|
64
64
|
const [sig, version] = decrypt(signature, key(cert, 32), key(buffer, 16)).split("%");
|
|
65
65
|
const result = (0, import_node_crypto.createVerify)("RSA-SHA256").update(buffer).verify(cert, sig, "base64");
|
|
@@ -67,7 +67,7 @@ function verify(buffer, signature, cert) {
|
|
|
67
67
|
} catch (error) {
|
|
68
68
|
return false;
|
|
69
69
|
}
|
|
70
|
-
}
|
|
70
|
+
};
|
|
71
71
|
|
|
72
72
|
// src/updater/defaultFunctions.ts
|
|
73
73
|
var import_node_buffer2 = require("buffer");
|
|
@@ -200,7 +200,7 @@ async function downloadBufferDefault(url, updater, headers) {
|
|
|
200
200
|
request.end();
|
|
201
201
|
});
|
|
202
202
|
}
|
|
203
|
-
|
|
203
|
+
var compareVersionDefault = (oldVersion, newVersion) => {
|
|
204
204
|
if (!oldVersion || !newVersion) {
|
|
205
205
|
throw new TypeError("invalid version");
|
|
206
206
|
}
|
|
@@ -221,7 +221,7 @@ function compareVersionDefault(oldVersion, newVersion) {
|
|
|
221
221
|
return true;
|
|
222
222
|
}
|
|
223
223
|
return false;
|
|
224
|
-
}
|
|
224
|
+
};
|
|
225
225
|
|
|
226
226
|
// src/updater/index.ts
|
|
227
227
|
function createUpdater({
|
|
@@ -231,15 +231,19 @@ function createUpdater({
|
|
|
231
231
|
releaseAsarURL: _release,
|
|
232
232
|
updateJsonURL: _update,
|
|
233
233
|
debug = false,
|
|
234
|
-
downloadConfig,
|
|
235
|
-
|
|
234
|
+
downloadConfig: { extraHeader, userAgent } = {},
|
|
235
|
+
overrideFunctions: {
|
|
236
|
+
compareVersion,
|
|
237
|
+
verifySignaure,
|
|
238
|
+
downloadBuffer,
|
|
239
|
+
downloadJSON
|
|
240
|
+
} = {}
|
|
236
241
|
}) {
|
|
237
242
|
const updater = new import_node_events.EventEmitter();
|
|
238
243
|
let signature = "";
|
|
239
244
|
const asarPath = getProductAsarPath(productName);
|
|
240
245
|
const gzipPath = `${asarPath}.gz`;
|
|
241
246
|
const tmpFilePath = gzipPath.replace(".asar.gz", ".tmp.asar");
|
|
242
|
-
const { downloadBuffer, downloadJSON, extraHeader, userAgent } = downloadConfig || {};
|
|
243
247
|
function log(msg) {
|
|
244
248
|
debug && updater.emit("debug", msg);
|
|
245
249
|
}
|
|
@@ -323,6 +327,7 @@ function createUpdater({
|
|
|
323
327
|
throw new Error(`invalid type at format '${format}': ${data}`);
|
|
324
328
|
}
|
|
325
329
|
}
|
|
330
|
+
updater.setDebug = (isDebug) => debug = isDebug;
|
|
326
331
|
updater.checkUpdate = async (data) => {
|
|
327
332
|
try {
|
|
328
333
|
const { signature: _sig, size, version } = await parseData("json", data);
|
|
@@ -348,7 +353,8 @@ function createUpdater({
|
|
|
348
353
|
}
|
|
349
354
|
const buffer = await parseData("buffer", data);
|
|
350
355
|
log("verify start");
|
|
351
|
-
const
|
|
356
|
+
const _verify = verifySignaure ?? verify;
|
|
357
|
+
const version = _verify(buffer, _sig, SIGNATURE_CERT);
|
|
352
358
|
if (!version) {
|
|
353
359
|
throw new Error("verify failed, invalid signature");
|
|
354
360
|
}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import { Buffer } from 'node:buffer';
|
|
2
|
+
|
|
3
|
+
type CheckResultType = Omit<UpdateJSON, 'signature'> | undefined | Error;
|
|
4
|
+
type InstallResult = true | Error;
|
|
5
|
+
type UpdateEvents = {
|
|
6
|
+
downloading: [progress: number];
|
|
7
|
+
debug: [msg: string | Error];
|
|
8
|
+
};
|
|
9
|
+
type UpdateJSON = {
|
|
10
|
+
signature: string;
|
|
11
|
+
version: string;
|
|
12
|
+
size: number;
|
|
13
|
+
};
|
|
14
|
+
declare function isUpdateJSON(json: any): json is UpdateJSON;
|
|
15
|
+
type MaybeArray<T> = T extends undefined | null | never ? [] : T extends any[] ? T['length'] extends 1 ? [data: T[0]] : T : [data: T];
|
|
16
|
+
interface TypedUpdater<T extends Record<string | symbol, MaybeArray<any>>, Event extends Exclude<keyof T, number> = Exclude<keyof T, number>> {
|
|
17
|
+
removeAllListeners<E extends Event>(event?: E): this;
|
|
18
|
+
listeners<E extends Event>(eventName: E): Function[];
|
|
19
|
+
eventNames(): (Event)[];
|
|
20
|
+
on<E extends Event>(eventName: E, listener: (...data: MaybeArray<T[E]>) => void): this;
|
|
21
|
+
once<E extends Event>(eventName: E, listener: (...data: MaybeArray<T[E]>) => void): this;
|
|
22
|
+
emit<E extends Event>(eventName: E, ...args: MaybeArray<T[E]>): boolean;
|
|
23
|
+
off<E extends Event>(eventName: E, listener: (...args: MaybeArray<T[E]>) => void): this;
|
|
24
|
+
/**
|
|
25
|
+
* check update info
|
|
26
|
+
* @param data update json url
|
|
27
|
+
* @returns
|
|
28
|
+
* - `{size: number, version: string}`: available
|
|
29
|
+
* - `false`: unavailable
|
|
30
|
+
* - `Error`: fail
|
|
31
|
+
*/
|
|
32
|
+
checkUpdate(data?: string | UpdateJSON): Promise<CheckResultType>;
|
|
33
|
+
/**
|
|
34
|
+
* download update and install
|
|
35
|
+
*
|
|
36
|
+
* if you want to update **offline**, you can set both `src` and `sig` to verify and install
|
|
37
|
+
* @param data asar download url or buffer
|
|
38
|
+
* @param sig signature
|
|
39
|
+
* @returns
|
|
40
|
+
* - `true`: success
|
|
41
|
+
* - `Error`: fail
|
|
42
|
+
*/
|
|
43
|
+
downloadAndInstall(data?: string | Buffer, sig?: string): Promise<InstallResult>;
|
|
44
|
+
setDebug(debug: boolean): void;
|
|
45
|
+
}
|
|
46
|
+
type FunctionVerifySignature = (buffer: Buffer, signature: string, cert: string) => string | false;
|
|
47
|
+
type FunctionCompareVersion = (oldVersion: string, newVersion: string) => boolean;
|
|
48
|
+
type Updater = TypedUpdater<UpdateEvents>;
|
|
49
|
+
interface UpdaterOption {
|
|
50
|
+
/**
|
|
51
|
+
* public key of signature
|
|
52
|
+
*
|
|
53
|
+
* it will be auto generated by plugin
|
|
54
|
+
* @example
|
|
55
|
+
* ```ts
|
|
56
|
+
* // auto filled by plugin
|
|
57
|
+
* const SIGNATURE_CERT = ''
|
|
58
|
+
*
|
|
59
|
+
* const updater = createUpdater({
|
|
60
|
+
* SIGNATURE_CERT,
|
|
61
|
+
* ...
|
|
62
|
+
* })
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
SIGNATURE_CERT: string;
|
|
66
|
+
/**
|
|
67
|
+
* name of your application
|
|
68
|
+
*
|
|
69
|
+
* you can use the `name` in `package.json`
|
|
70
|
+
*/
|
|
71
|
+
productName: string;
|
|
72
|
+
/**
|
|
73
|
+
* repository url, e.g. `https://github.com/electron/electron`
|
|
74
|
+
*
|
|
75
|
+
* you can use the `repository` in `package.json`
|
|
76
|
+
*
|
|
77
|
+
* if `updateJsonURL` or `releaseAsarURL` are absent,
|
|
78
|
+
* `repository` will be used to determine the url
|
|
79
|
+
*/
|
|
80
|
+
repository?: string;
|
|
81
|
+
/**
|
|
82
|
+
* URL of version info json
|
|
83
|
+
* @default `${repository.replace('github.com', 'raw.githubusercontent.com')}/master/version.json`
|
|
84
|
+
* @throws if `updateJsonURL` and `repository` are all not set
|
|
85
|
+
*/
|
|
86
|
+
updateJsonURL?: string;
|
|
87
|
+
/**
|
|
88
|
+
* URL of release asar.gz
|
|
89
|
+
* @default `${repository}/releases/download/latest/${productName}.asar.gz`
|
|
90
|
+
* @throws if `releaseAsarURL` and `repository` are all not set
|
|
91
|
+
*/
|
|
92
|
+
releaseAsarURL?: string;
|
|
93
|
+
/**
|
|
94
|
+
* whether to enable debug listener
|
|
95
|
+
*/
|
|
96
|
+
debug?: boolean;
|
|
97
|
+
overrideFunctions?: {
|
|
98
|
+
/**
|
|
99
|
+
* custom version compare function {@link FunctionCompareVersion}
|
|
100
|
+
* @param oldVersion old version string
|
|
101
|
+
* @param newVersion new version string
|
|
102
|
+
* @returns whether to update
|
|
103
|
+
*/
|
|
104
|
+
compareVersion?: FunctionCompareVersion;
|
|
105
|
+
/**
|
|
106
|
+
* custom verify signature function {@link FunctionVerifySignature}
|
|
107
|
+
* @param buffer file buffer
|
|
108
|
+
* @param signature signature
|
|
109
|
+
* @param cert certificate
|
|
110
|
+
*/
|
|
111
|
+
verifySignaure?: FunctionVerifySignature;
|
|
112
|
+
/**
|
|
113
|
+
* custom download JSON function
|
|
114
|
+
* @param url download url
|
|
115
|
+
* @param updater updater, to trigger events
|
|
116
|
+
* @param header download header
|
|
117
|
+
* @returns `UpdateJSON`
|
|
118
|
+
*/
|
|
119
|
+
downloadJSON?: (url: string, updater: Updater, headers: Record<string, any>) => Promise<UpdateJSON>;
|
|
120
|
+
/**
|
|
121
|
+
* custom download buffer function
|
|
122
|
+
* @param url download url
|
|
123
|
+
* @param updater updater, to trigger events
|
|
124
|
+
* @param header download header
|
|
125
|
+
* @returns `Buffer`
|
|
126
|
+
*/
|
|
127
|
+
downloadBuffer?: (url: string, updater: Updater, headers: Record<string, any>) => Promise<Buffer>;
|
|
128
|
+
};
|
|
129
|
+
downloadConfig?: {
|
|
130
|
+
/**
|
|
131
|
+
* download user agent
|
|
132
|
+
* @default 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36'
|
|
133
|
+
*/
|
|
134
|
+
userAgent?: string;
|
|
135
|
+
/**
|
|
136
|
+
* extra download header, `accept` and `user-agent` is set by default
|
|
137
|
+
*/
|
|
138
|
+
extraHeader?: Record<string, string>;
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* get the application asar absolute path
|
|
144
|
+
* @param name The name of the application
|
|
145
|
+
*/
|
|
146
|
+
declare function getProductAsarPath(name: string): string;
|
|
147
|
+
/**
|
|
148
|
+
* get the version of entry (app.asar)
|
|
149
|
+
*/
|
|
150
|
+
declare function getEntryVersion(): string;
|
|
151
|
+
/**
|
|
152
|
+
* get the version of application (name.asar)
|
|
153
|
+
* @param name - The name of the application
|
|
154
|
+
*/
|
|
155
|
+
declare function getProductVersion(name: string): string;
|
|
156
|
+
/**
|
|
157
|
+
* require native package from app.asar
|
|
158
|
+
* @param packageName native package name
|
|
159
|
+
*/
|
|
160
|
+
declare function requireNative<T = any>(packageName: string): T;
|
|
161
|
+
/**
|
|
162
|
+
* get github version.json CDN URL for accelerating the speed of downloading version info
|
|
163
|
+
*/
|
|
164
|
+
declare function parseGithubCdnURL(repository: string, cdnPrefix: string, relativeFilePath: string): string;
|
|
165
|
+
/**
|
|
166
|
+
* get group of github release CDN prefix for accelerating the speed of downloading release
|
|
167
|
+
*/
|
|
168
|
+
declare function getGithubReleaseCdnGroup(): {
|
|
169
|
+
cdnPrefix: string;
|
|
170
|
+
maintainer: string;
|
|
171
|
+
}[];
|
|
172
|
+
declare function restartApp(): void;
|
|
173
|
+
declare function waitAppReady(duration?: number): Promise<unknown>;
|
|
174
|
+
|
|
175
|
+
declare function createUpdater({ SIGNATURE_CERT, repository, productName, releaseAsarURL: _release, updateJsonURL: _update, debug, downloadConfig: { extraHeader, userAgent }, overrideFunctions: { compareVersion, verifySignaure, downloadBuffer, downloadJSON, }, }: UpdaterOption): Updater;
|
|
176
|
+
|
|
177
|
+
type AppOption = {
|
|
178
|
+
/**
|
|
179
|
+
* name of your application
|
|
180
|
+
*
|
|
181
|
+
* you can use the `name` in `package.json`
|
|
182
|
+
*/
|
|
183
|
+
name: string;
|
|
184
|
+
/**
|
|
185
|
+
* path of electron output dist
|
|
186
|
+
* @default 'dist-electron'
|
|
187
|
+
*/
|
|
188
|
+
electronDistPath?: string;
|
|
189
|
+
/**
|
|
190
|
+
* relative path of main entry in electron dist
|
|
191
|
+
* @default 'main/index.js'
|
|
192
|
+
*/
|
|
193
|
+
mainPath?: string;
|
|
194
|
+
};
|
|
195
|
+
type OptionalProperty<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
|
|
196
|
+
type InitUpdaterOptions = OptionalProperty<UpdaterOption, 'productName'>;
|
|
197
|
+
type StartupWithUpdater = (updater: Updater) => void;
|
|
198
|
+
/**
|
|
199
|
+
* create updater manually
|
|
200
|
+
* @example
|
|
201
|
+
* ```ts
|
|
202
|
+
* import { createUpdater, getGithubReleaseCdnGroup, initApp, parseGithubCdnURL } from 'electron-incremental-update'
|
|
203
|
+
* import { name, repository } from '../package.json'
|
|
204
|
+
*
|
|
205
|
+
* const SIGNATURE_CERT = '' // auto generate
|
|
206
|
+
*
|
|
207
|
+
* const { cdnPrefix } = getGithubReleaseCdnGroup()[0]
|
|
208
|
+
* const updater = createUpdater({
|
|
209
|
+
* SIGNATURE_CERT,
|
|
210
|
+
* productName: name,
|
|
211
|
+
* repository,
|
|
212
|
+
* updateJsonURL: parseGithubCdnURL(repository, 'fastly.jsdelivr.net/gh', 'version.json'),
|
|
213
|
+
* releaseAsarURL: parseGithubCdnURL(repository, cdnPrefix, `download/latest/${name}.asar.gz`),
|
|
214
|
+
* debug: true,
|
|
215
|
+
* })
|
|
216
|
+
* initApp({ name }).setUpdater(updater)
|
|
217
|
+
* ```
|
|
218
|
+
*/
|
|
219
|
+
declare function initApp(appOptions: AppOption): {
|
|
220
|
+
setUpdater: (updater: Updater) => void;
|
|
221
|
+
};
|
|
222
|
+
/**
|
|
223
|
+
* create updater when init, no need to set productName
|
|
224
|
+
*
|
|
225
|
+
* @example
|
|
226
|
+
* ```ts
|
|
227
|
+
* import { initApp } from 'electron-incremental-update'
|
|
228
|
+
* import { name, repository } from '../package.json'
|
|
229
|
+
*
|
|
230
|
+
* const SIGNATURE_CERT = '' // auto generate
|
|
231
|
+
*
|
|
232
|
+
* initApp({ name }, { SIGNATURE_CERT, repository })
|
|
233
|
+
* ```
|
|
234
|
+
*/
|
|
235
|
+
declare function initApp(appOptions: AppOption, updaterOptions: InitUpdaterOptions): undefined;
|
|
236
|
+
|
|
237
|
+
export { AppOption, CheckResultType, FunctionCompareVersion, FunctionVerifySignature, InitUpdaterOptions, InstallResult, StartupWithUpdater, UpdateJSON, Updater, UpdaterOption, createUpdater, getEntryVersion, getGithubReleaseCdnGroup, getProductAsarPath, getProductVersion, initApp, isUpdateJSON, parseGithubCdnURL, requireNative, restartApp, waitAppReady };
|
package/dist/index.d.ts
CHANGED
|
@@ -41,7 +41,10 @@ interface TypedUpdater<T extends Record<string | symbol, MaybeArray<any>>, Event
|
|
|
41
41
|
* - `Error`: fail
|
|
42
42
|
*/
|
|
43
43
|
downloadAndInstall(data?: string | Buffer, sig?: string): Promise<InstallResult>;
|
|
44
|
+
setDebug(debug: boolean): void;
|
|
44
45
|
}
|
|
46
|
+
type FunctionVerifySignature = (buffer: Buffer, signature: string, cert: string) => string | false;
|
|
47
|
+
type FunctionCompareVersion = (oldVersion: string, newVersion: string) => boolean;
|
|
45
48
|
type Updater = TypedUpdater<UpdateEvents>;
|
|
46
49
|
interface UpdaterOption {
|
|
47
50
|
/**
|
|
@@ -91,25 +94,23 @@ interface UpdaterOption {
|
|
|
91
94
|
* whether to enable debug listener
|
|
92
95
|
*/
|
|
93
96
|
debug?: boolean;
|
|
94
|
-
|
|
95
|
-
* custom version compare function
|
|
96
|
-
* @param oldVersion old version string
|
|
97
|
-
* @param newVersion new version string
|
|
98
|
-
* @returns whether to update
|
|
99
|
-
*/
|
|
100
|
-
compareVersion?: (oldVersion: string, newVersion: string) => boolean;
|
|
101
|
-
downloadConfig?: {
|
|
97
|
+
overrideFunctions?: {
|
|
102
98
|
/**
|
|
103
|
-
*
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
99
|
+
* custom version compare function {@link FunctionCompareVersion}
|
|
100
|
+
* @param oldVersion old version string
|
|
101
|
+
* @param newVersion new version string
|
|
102
|
+
* @returns whether to update
|
|
103
|
+
*/
|
|
104
|
+
compareVersion?: FunctionCompareVersion;
|
|
107
105
|
/**
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
106
|
+
* custom verify signature function {@link FunctionVerifySignature}
|
|
107
|
+
* @param buffer file buffer
|
|
108
|
+
* @param signature signature
|
|
109
|
+
* @param cert certificate
|
|
110
|
+
*/
|
|
111
|
+
verifySignaure?: FunctionVerifySignature;
|
|
111
112
|
/**
|
|
112
|
-
* download JSON function
|
|
113
|
+
* custom download JSON function
|
|
113
114
|
* @param url download url
|
|
114
115
|
* @param updater updater, to trigger events
|
|
115
116
|
* @param header download header
|
|
@@ -117,7 +118,7 @@ interface UpdaterOption {
|
|
|
117
118
|
*/
|
|
118
119
|
downloadJSON?: (url: string, updater: Updater, headers: Record<string, any>) => Promise<UpdateJSON>;
|
|
119
120
|
/**
|
|
120
|
-
* download buffer function
|
|
121
|
+
* custom download buffer function
|
|
121
122
|
* @param url download url
|
|
122
123
|
* @param updater updater, to trigger events
|
|
123
124
|
* @param header download header
|
|
@@ -125,6 +126,17 @@ interface UpdaterOption {
|
|
|
125
126
|
*/
|
|
126
127
|
downloadBuffer?: (url: string, updater: Updater, headers: Record<string, any>) => Promise<Buffer>;
|
|
127
128
|
};
|
|
129
|
+
downloadConfig?: {
|
|
130
|
+
/**
|
|
131
|
+
* download user agent
|
|
132
|
+
* @default 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36'
|
|
133
|
+
*/
|
|
134
|
+
userAgent?: string;
|
|
135
|
+
/**
|
|
136
|
+
* extra download header, `accept` and `user-agent` is set by default
|
|
137
|
+
*/
|
|
138
|
+
extraHeader?: Record<string, string>;
|
|
139
|
+
};
|
|
128
140
|
}
|
|
129
141
|
|
|
130
142
|
/**
|
|
@@ -160,7 +172,7 @@ declare function getGithubReleaseCdnGroup(): {
|
|
|
160
172
|
declare function restartApp(): void;
|
|
161
173
|
declare function waitAppReady(duration?: number): Promise<unknown>;
|
|
162
174
|
|
|
163
|
-
declare function createUpdater({ SIGNATURE_CERT, repository, productName, releaseAsarURL: _release, updateJsonURL: _update, debug, downloadConfig, compareVersion, }: UpdaterOption): Updater;
|
|
175
|
+
declare function createUpdater({ SIGNATURE_CERT, repository, productName, releaseAsarURL: _release, updateJsonURL: _update, debug, downloadConfig: { extraHeader, userAgent }, overrideFunctions: { compareVersion, verifySignaure, downloadBuffer, downloadJSON, }, }: UpdaterOption): Updater;
|
|
164
176
|
|
|
165
177
|
type AppOption = {
|
|
166
178
|
/**
|
|
@@ -182,6 +194,7 @@ type AppOption = {
|
|
|
182
194
|
};
|
|
183
195
|
type OptionalProperty<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
|
|
184
196
|
type InitUpdaterOptions = OptionalProperty<UpdaterOption, 'productName'>;
|
|
197
|
+
type StartupWithUpdater = (updater: Updater) => void;
|
|
185
198
|
/**
|
|
186
199
|
* create updater manually
|
|
187
200
|
* @example
|
|
@@ -221,4 +234,4 @@ declare function initApp(appOptions: AppOption): {
|
|
|
221
234
|
*/
|
|
222
235
|
declare function initApp(appOptions: AppOption, updaterOptions: InitUpdaterOptions): undefined;
|
|
223
236
|
|
|
224
|
-
export { AppOption, CheckResultType, InitUpdaterOptions, InstallResult, UpdateJSON, Updater, UpdaterOption, createUpdater, getEntryVersion, getGithubReleaseCdnGroup, getProductAsarPath, getProductVersion, initApp, isUpdateJSON, parseGithubCdnURL, requireNative, restartApp, waitAppReady };
|
|
237
|
+
export { AppOption, CheckResultType, FunctionCompareVersion, FunctionVerifySignature, InitUpdaterOptions, InstallResult, StartupWithUpdater, UpdateJSON, Updater, UpdaterOption, createUpdater, getEntryVersion, getGithubReleaseCdnGroup, getProductAsarPath, getProductVersion, initApp, isUpdateJSON, parseGithubCdnURL, requireNative, restartApp, waitAppReady };
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
__require,
|
|
3
3
|
verify
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-XQ4Z2OVN.mjs";
|
|
5
5
|
|
|
6
6
|
// src/index.ts
|
|
7
7
|
import { resolve as resolve2 } from "node:path";
|
|
@@ -147,7 +147,7 @@ async function downloadBufferDefault(url, updater, headers) {
|
|
|
147
147
|
request.end();
|
|
148
148
|
});
|
|
149
149
|
}
|
|
150
|
-
|
|
150
|
+
var compareVersionDefault = (oldVersion, newVersion) => {
|
|
151
151
|
if (!oldVersion || !newVersion) {
|
|
152
152
|
throw new TypeError("invalid version");
|
|
153
153
|
}
|
|
@@ -168,7 +168,7 @@ function compareVersionDefault(oldVersion, newVersion) {
|
|
|
168
168
|
return true;
|
|
169
169
|
}
|
|
170
170
|
return false;
|
|
171
|
-
}
|
|
171
|
+
};
|
|
172
172
|
|
|
173
173
|
// src/updater/index.ts
|
|
174
174
|
function createUpdater({
|
|
@@ -178,15 +178,19 @@ function createUpdater({
|
|
|
178
178
|
releaseAsarURL: _release,
|
|
179
179
|
updateJsonURL: _update,
|
|
180
180
|
debug = false,
|
|
181
|
-
downloadConfig,
|
|
182
|
-
|
|
181
|
+
downloadConfig: { extraHeader, userAgent } = {},
|
|
182
|
+
overrideFunctions: {
|
|
183
|
+
compareVersion,
|
|
184
|
+
verifySignaure,
|
|
185
|
+
downloadBuffer,
|
|
186
|
+
downloadJSON
|
|
187
|
+
} = {}
|
|
183
188
|
}) {
|
|
184
189
|
const updater = new EventEmitter();
|
|
185
190
|
let signature = "";
|
|
186
191
|
const asarPath = getProductAsarPath(productName);
|
|
187
192
|
const gzipPath = `${asarPath}.gz`;
|
|
188
193
|
const tmpFilePath = gzipPath.replace(".asar.gz", ".tmp.asar");
|
|
189
|
-
const { downloadBuffer, downloadJSON, extraHeader, userAgent } = downloadConfig || {};
|
|
190
194
|
function log(msg) {
|
|
191
195
|
debug && updater.emit("debug", msg);
|
|
192
196
|
}
|
|
@@ -270,6 +274,7 @@ function createUpdater({
|
|
|
270
274
|
throw new Error(`invalid type at format '${format}': ${data}`);
|
|
271
275
|
}
|
|
272
276
|
}
|
|
277
|
+
updater.setDebug = (isDebug) => debug = isDebug;
|
|
273
278
|
updater.checkUpdate = async (data) => {
|
|
274
279
|
try {
|
|
275
280
|
const { signature: _sig, size, version } = await parseData("json", data);
|
|
@@ -295,7 +300,8 @@ function createUpdater({
|
|
|
295
300
|
}
|
|
296
301
|
const buffer = await parseData("buffer", data);
|
|
297
302
|
log("verify start");
|
|
298
|
-
const
|
|
303
|
+
const _verify = verifySignaure ?? verify;
|
|
304
|
+
const version = _verify(buffer, _sig, SIGNATURE_CERT);
|
|
299
305
|
if (!version) {
|
|
300
306
|
throw new Error("verify failed, invalid signature");
|
|
301
307
|
}
|
package/dist/vite.cjs
CHANGED
|
@@ -55,14 +55,14 @@ function key(data, length) {
|
|
|
55
55
|
const hash = (0, import_node_crypto.createHash)("SHA256").update(data).digest("binary");
|
|
56
56
|
return import_node_buffer.Buffer.from(hash).subarray(0, length);
|
|
57
57
|
}
|
|
58
|
-
|
|
58
|
+
var signature = (buffer, privateKey, cert, version) => {
|
|
59
59
|
const sig = (0, import_node_crypto.createSign)("RSA-SHA256").update(buffer).sign({
|
|
60
60
|
key: privateKey,
|
|
61
61
|
padding: import_node_crypto.constants.RSA_PKCS1_PADDING,
|
|
62
62
|
saltLength: import_node_crypto.constants.RSA_PSS_SALTLEN_DIGEST
|
|
63
63
|
}, "base64");
|
|
64
64
|
return encrypt(`${sig}%${version}`, key(cert, 32), key(buffer, 16));
|
|
65
|
-
}
|
|
65
|
+
};
|
|
66
66
|
|
|
67
67
|
// src/build-plugins/build.ts
|
|
68
68
|
function gzipFile(filePath) {
|
|
@@ -106,11 +106,13 @@ async function buildVersion({
|
|
|
106
106
|
versionPath,
|
|
107
107
|
privateKey,
|
|
108
108
|
cert,
|
|
109
|
-
version
|
|
109
|
+
version,
|
|
110
|
+
generateSignature
|
|
110
111
|
}) {
|
|
111
112
|
const buffer = await (0, import_promises.readFile)(`${asarOutputPath}.gz`);
|
|
113
|
+
const _func = generateSignature ?? signature;
|
|
112
114
|
await (0, import_promises.writeFile)(versionPath, JSON.stringify({
|
|
113
|
-
signature:
|
|
115
|
+
signature: _func(buffer, privateKey, cert, version),
|
|
114
116
|
version,
|
|
115
117
|
size: buffer.length
|
|
116
118
|
}, null, 2));
|
|
@@ -136,23 +138,13 @@ var import_node_path = require("path");
|
|
|
136
138
|
var import_node_os = require("os");
|
|
137
139
|
var import_node_crypto2 = require("crypto");
|
|
138
140
|
var import_jscert = require("@cyyynthia/jscert");
|
|
139
|
-
function generateCert(privateKey) {
|
|
140
|
-
const dn = {
|
|
141
|
-
country: "zh-CN",
|
|
142
|
-
state: "zj",
|
|
143
|
-
locality: "hz",
|
|
144
|
-
organization: "test",
|
|
145
|
-
organizationalUnit: "test unit",
|
|
146
|
-
commonName: "test.test",
|
|
147
|
-
emailAddress: "test@example.com"
|
|
148
|
-
};
|
|
141
|
+
function generateCert(privateKey, dn, expires) {
|
|
149
142
|
const csr = new import_jscert.CertificateSigningRequest(dn, privateKey, { digest: "sha256" });
|
|
150
|
-
|
|
151
|
-
return csr.createSelfSignedCertificate(expiry).toPem();
|
|
143
|
+
return csr.createSelfSignedCertificate(expires).toPem();
|
|
152
144
|
}
|
|
153
|
-
function
|
|
145
|
+
function generateKeyPairDefault(length, subjects, expires) {
|
|
154
146
|
const { privateKey: _key } = (0, import_node_crypto2.generateKeyPairSync)("rsa", { modulusLength: length });
|
|
155
|
-
const cert = generateCert(_key);
|
|
147
|
+
const cert = generateCert(_key, subjects, expires);
|
|
156
148
|
const privateKey = _key.export({ type: "pkcs1", format: "pem" });
|
|
157
149
|
return {
|
|
158
150
|
privateKey,
|
|
@@ -188,13 +180,17 @@ function getKeys({
|
|
|
188
180
|
keyLength,
|
|
189
181
|
privateKeyPath,
|
|
190
182
|
certPath,
|
|
191
|
-
entryPath
|
|
183
|
+
entryPath,
|
|
184
|
+
subject,
|
|
185
|
+
expires,
|
|
186
|
+
generateKeyPair
|
|
192
187
|
}) {
|
|
193
188
|
const keysDir = (0, import_node_path.dirname)(privateKeyPath);
|
|
194
189
|
!(0, import_node_fs2.existsSync)(keysDir) && (0, import_node_fs2.mkdirSync)(keysDir);
|
|
195
190
|
let privateKey, cert;
|
|
196
191
|
if (!(0, import_node_fs2.existsSync)(privateKeyPath) || !(0, import_node_fs2.existsSync)(certPath)) {
|
|
197
|
-
const
|
|
192
|
+
const _func = generateKeyPair ?? generateKeyPairDefault;
|
|
193
|
+
const keys = _func(keyLength, subject, expires);
|
|
198
194
|
privateKey = keys.privateKey;
|
|
199
195
|
cert = keys.cert;
|
|
200
196
|
(0, import_node_fs2.writeFileSync)(privateKeyPath, privateKey);
|
|
@@ -213,28 +209,38 @@ function getKeys({
|
|
|
213
209
|
// src/build-plugins/option.ts
|
|
214
210
|
var import_ci_info = require("ci-info");
|
|
215
211
|
function parseOptions(options) {
|
|
216
|
-
const { isBuild, productName, version, minify = false, paths = {}, keys = {} } = options;
|
|
217
212
|
const {
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
213
|
+
isBuild,
|
|
214
|
+
productName,
|
|
215
|
+
version,
|
|
216
|
+
minify = false,
|
|
217
|
+
paths: {
|
|
218
|
+
entryPath = "electron/app.ts",
|
|
219
|
+
entryOutputPath = "app.js",
|
|
220
|
+
asarOutputPath = `release/${productName}-${version}.asar`,
|
|
221
|
+
electronDistPath = "dist-electron",
|
|
222
|
+
rendererDistPath = "dist",
|
|
223
|
+
versionPath = "version.json"
|
|
224
|
+
} = {},
|
|
225
|
+
keys: {
|
|
226
|
+
privateKeyPath = "keys/private.pem",
|
|
227
|
+
certPath = "keys/cert.pem",
|
|
228
|
+
keyLength = 2048,
|
|
229
|
+
certInfo = {},
|
|
230
|
+
overrideFunctions = {}
|
|
231
|
+
} = {}
|
|
232
|
+
} = options;
|
|
225
233
|
const {
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
certInfo
|
|
230
|
-
} = keys;
|
|
234
|
+
generateKeyPair,
|
|
235
|
+
generateSignature
|
|
236
|
+
} = overrideFunctions;
|
|
231
237
|
let {
|
|
232
238
|
subject = {
|
|
233
239
|
commonName: productName,
|
|
234
240
|
organization: `org.${productName}`
|
|
235
241
|
},
|
|
236
242
|
expires = Date.now() + 365 * 864e5
|
|
237
|
-
} = certInfo
|
|
243
|
+
} = certInfo;
|
|
238
244
|
const buildAsarOption = {
|
|
239
245
|
version,
|
|
240
246
|
asarOutputPath,
|
|
@@ -257,14 +263,16 @@ function parseOptions(options) {
|
|
|
257
263
|
certPath,
|
|
258
264
|
entryPath,
|
|
259
265
|
subject,
|
|
260
|
-
expires
|
|
266
|
+
expires,
|
|
267
|
+
generateKeyPair
|
|
261
268
|
});
|
|
262
269
|
buildVersionOption = {
|
|
263
270
|
version,
|
|
264
271
|
asarOutputPath,
|
|
265
272
|
privateKey,
|
|
266
273
|
cert,
|
|
267
|
-
versionPath
|
|
274
|
+
versionPath,
|
|
275
|
+
generateSignature
|
|
268
276
|
};
|
|
269
277
|
}
|
|
270
278
|
return { isBuild, buildAsarOption, buildEntryOption, buildVersionOption };
|
package/dist/vite.d.cts
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { Plugin } from 'vite';
|
|
2
|
+
import { Buffer } from 'node:buffer';
|
|
3
|
+
import { DistinguishedName } from '@cyyynthia/jscert';
|
|
4
|
+
|
|
5
|
+
type FunctionGenerateKeyPair = (keyLength: number, subject: DistinguishedName, expires: Date) => {
|
|
6
|
+
privateKey: string;
|
|
7
|
+
cert: string;
|
|
8
|
+
};
|
|
9
|
+
type FunctionGenerateSignature = (buffer: Buffer, privateKey: string, cert: string, version: string) => string;
|
|
10
|
+
type Options = {
|
|
11
|
+
/**
|
|
12
|
+
* whether is in build mode
|
|
13
|
+
*/
|
|
14
|
+
isBuild: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* the name of you application
|
|
17
|
+
*
|
|
18
|
+
* you can set as 'name' in `package.json`
|
|
19
|
+
*/
|
|
20
|
+
productName: string;
|
|
21
|
+
/**
|
|
22
|
+
* the version of you application
|
|
23
|
+
*
|
|
24
|
+
* you can set as 'version' in `package.json`
|
|
25
|
+
*/
|
|
26
|
+
version: string;
|
|
27
|
+
/**
|
|
28
|
+
* Whether to minify entry file
|
|
29
|
+
*/
|
|
30
|
+
minify?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* paths config
|
|
33
|
+
*/
|
|
34
|
+
paths?: {
|
|
35
|
+
/**
|
|
36
|
+
* Path to app entry file
|
|
37
|
+
* @default 'electron/app.ts'
|
|
38
|
+
*/
|
|
39
|
+
entryPath?: string;
|
|
40
|
+
/**
|
|
41
|
+
* Path to app entry output file
|
|
42
|
+
* @default 'app.js'
|
|
43
|
+
*/
|
|
44
|
+
entryOutputPath?: string;
|
|
45
|
+
/**
|
|
46
|
+
* Path to asar file
|
|
47
|
+
* @default `release/${productName}.asar`
|
|
48
|
+
*/
|
|
49
|
+
asarOutputPath?: string;
|
|
50
|
+
/**
|
|
51
|
+
* Path to electron build output
|
|
52
|
+
* @default `dist-electron`
|
|
53
|
+
*/
|
|
54
|
+
electronDistPath?: string;
|
|
55
|
+
/**
|
|
56
|
+
* Path to renderer build output
|
|
57
|
+
* @default `dist`
|
|
58
|
+
*/
|
|
59
|
+
rendererDistPath?: string;
|
|
60
|
+
/**
|
|
61
|
+
* Path to version info output
|
|
62
|
+
* @default `version.json`
|
|
63
|
+
*/
|
|
64
|
+
versionPath?: string;
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* signature config
|
|
68
|
+
*/
|
|
69
|
+
keys?: {
|
|
70
|
+
/**
|
|
71
|
+
* Path to the pem file that contains private key
|
|
72
|
+
* if not ended with .pem, it will be appended
|
|
73
|
+
* @default 'keys/private.pem'
|
|
74
|
+
*/
|
|
75
|
+
privateKeyPath?: string;
|
|
76
|
+
/**
|
|
77
|
+
* Path to the pem file that contains public key
|
|
78
|
+
* if not ended with .pem, it will be appended
|
|
79
|
+
* @default 'keys/cert.pem'
|
|
80
|
+
*/
|
|
81
|
+
certPath?: string;
|
|
82
|
+
/**
|
|
83
|
+
* Length of the key
|
|
84
|
+
* @default 2048
|
|
85
|
+
*/
|
|
86
|
+
keyLength?: number;
|
|
87
|
+
/**
|
|
88
|
+
* X509 certificate info
|
|
89
|
+
*
|
|
90
|
+
* only generate simple **self-signed** certificate **without extensions**
|
|
91
|
+
*/
|
|
92
|
+
certInfo?: {
|
|
93
|
+
/**
|
|
94
|
+
* the subject of the certificate
|
|
95
|
+
*
|
|
96
|
+
* @default { commonName: productName, organization: `org.${productName}` }
|
|
97
|
+
*/
|
|
98
|
+
subject?: DistinguishedName;
|
|
99
|
+
/**
|
|
100
|
+
* expires of the certificate
|
|
101
|
+
* - `Date`: expire date
|
|
102
|
+
* - `number`: expire duration in seconds
|
|
103
|
+
*
|
|
104
|
+
* @default Date.now() + 365 * 864e5 (1 year)
|
|
105
|
+
*/
|
|
106
|
+
expires?: Date | number;
|
|
107
|
+
};
|
|
108
|
+
overrideFunctions?: {
|
|
109
|
+
/**
|
|
110
|
+
* custom key pair generate function {@link FunctionGenerateKeyPair}
|
|
111
|
+
* @param keyLength key length
|
|
112
|
+
* @param subject subject info
|
|
113
|
+
* @param expires expire date
|
|
114
|
+
*/
|
|
115
|
+
generateKeyPair?: FunctionGenerateKeyPair;
|
|
116
|
+
/**
|
|
117
|
+
* custom signature generate function {@link FunctionGenerateSignature}
|
|
118
|
+
* @param buffer file buffer
|
|
119
|
+
* @param privateKey private key
|
|
120
|
+
* @param cert certificate
|
|
121
|
+
*/
|
|
122
|
+
generateSignature?: FunctionGenerateSignature;
|
|
123
|
+
};
|
|
124
|
+
};
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
declare function export_default(options: Options): Plugin;
|
|
128
|
+
|
|
129
|
+
export { export_default as default };
|
package/dist/vite.d.ts
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { Plugin } from 'vite';
|
|
2
|
+
import { Buffer } from 'node:buffer';
|
|
2
3
|
import { DistinguishedName } from '@cyyynthia/jscert';
|
|
3
4
|
|
|
5
|
+
type FunctionGenerateKeyPair = (keyLength: number, subject: DistinguishedName, expires: Date) => {
|
|
6
|
+
privateKey: string;
|
|
7
|
+
cert: string;
|
|
8
|
+
};
|
|
9
|
+
type FunctionGenerateSignature = (buffer: Buffer, privateKey: string, cert: string, version: string) => string;
|
|
4
10
|
type Options = {
|
|
5
11
|
/**
|
|
6
12
|
* whether is in build mode
|
|
@@ -99,6 +105,22 @@ type Options = {
|
|
|
99
105
|
*/
|
|
100
106
|
expires?: Date | number;
|
|
101
107
|
};
|
|
108
|
+
overrideFunctions?: {
|
|
109
|
+
/**
|
|
110
|
+
* custom key pair generate function {@link FunctionGenerateKeyPair}
|
|
111
|
+
* @param keyLength key length
|
|
112
|
+
* @param subject subject info
|
|
113
|
+
* @param expires expire date
|
|
114
|
+
*/
|
|
115
|
+
generateKeyPair?: FunctionGenerateKeyPair;
|
|
116
|
+
/**
|
|
117
|
+
* custom signature generate function {@link FunctionGenerateSignature}
|
|
118
|
+
* @param buffer file buffer
|
|
119
|
+
* @param privateKey private key
|
|
120
|
+
* @param cert certificate
|
|
121
|
+
*/
|
|
122
|
+
generateSignature?: FunctionGenerateSignature;
|
|
123
|
+
};
|
|
102
124
|
};
|
|
103
125
|
};
|
|
104
126
|
|
package/dist/vite.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
signature
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-XQ4Z2OVN.mjs";
|
|
4
4
|
|
|
5
5
|
// src/vite.ts
|
|
6
6
|
import { createLogger } from "vite";
|
|
@@ -51,11 +51,13 @@ async function buildVersion({
|
|
|
51
51
|
versionPath,
|
|
52
52
|
privateKey,
|
|
53
53
|
cert,
|
|
54
|
-
version
|
|
54
|
+
version,
|
|
55
|
+
generateSignature
|
|
55
56
|
}) {
|
|
56
57
|
const buffer = await readFile(`${asarOutputPath}.gz`);
|
|
58
|
+
const _func = generateSignature ?? signature;
|
|
57
59
|
await writeFile(versionPath, JSON.stringify({
|
|
58
|
-
signature:
|
|
60
|
+
signature: _func(buffer, privateKey, cert, version),
|
|
59
61
|
version,
|
|
60
62
|
size: buffer.length
|
|
61
63
|
}, null, 2));
|
|
@@ -81,23 +83,13 @@ import { dirname } from "node:path";
|
|
|
81
83
|
import { EOL } from "node:os";
|
|
82
84
|
import { generateKeyPairSync } from "node:crypto";
|
|
83
85
|
import { CertificateSigningRequest } from "@cyyynthia/jscert";
|
|
84
|
-
function generateCert(privateKey) {
|
|
85
|
-
const dn = {
|
|
86
|
-
country: "zh-CN",
|
|
87
|
-
state: "zj",
|
|
88
|
-
locality: "hz",
|
|
89
|
-
organization: "test",
|
|
90
|
-
organizationalUnit: "test unit",
|
|
91
|
-
commonName: "test.test",
|
|
92
|
-
emailAddress: "test@example.com"
|
|
93
|
-
};
|
|
86
|
+
function generateCert(privateKey, dn, expires) {
|
|
94
87
|
const csr = new CertificateSigningRequest(dn, privateKey, { digest: "sha256" });
|
|
95
|
-
|
|
96
|
-
return csr.createSelfSignedCertificate(expiry).toPem();
|
|
88
|
+
return csr.createSelfSignedCertificate(expires).toPem();
|
|
97
89
|
}
|
|
98
|
-
function
|
|
90
|
+
function generateKeyPairDefault(length, subjects, expires) {
|
|
99
91
|
const { privateKey: _key } = generateKeyPairSync("rsa", { modulusLength: length });
|
|
100
|
-
const cert = generateCert(_key);
|
|
92
|
+
const cert = generateCert(_key, subjects, expires);
|
|
101
93
|
const privateKey = _key.export({ type: "pkcs1", format: "pem" });
|
|
102
94
|
return {
|
|
103
95
|
privateKey,
|
|
@@ -133,13 +125,17 @@ function getKeys({
|
|
|
133
125
|
keyLength,
|
|
134
126
|
privateKeyPath,
|
|
135
127
|
certPath,
|
|
136
|
-
entryPath
|
|
128
|
+
entryPath,
|
|
129
|
+
subject,
|
|
130
|
+
expires,
|
|
131
|
+
generateKeyPair
|
|
137
132
|
}) {
|
|
138
133
|
const keysDir = dirname(privateKeyPath);
|
|
139
134
|
!existsSync(keysDir) && mkdirSync(keysDir);
|
|
140
135
|
let privateKey, cert;
|
|
141
136
|
if (!existsSync(privateKeyPath) || !existsSync(certPath)) {
|
|
142
|
-
const
|
|
137
|
+
const _func = generateKeyPair ?? generateKeyPairDefault;
|
|
138
|
+
const keys = _func(keyLength, subject, expires);
|
|
143
139
|
privateKey = keys.privateKey;
|
|
144
140
|
cert = keys.cert;
|
|
145
141
|
writeFileSync(privateKeyPath, privateKey);
|
|
@@ -158,28 +154,38 @@ function getKeys({
|
|
|
158
154
|
// src/build-plugins/option.ts
|
|
159
155
|
import { isCI } from "ci-info";
|
|
160
156
|
function parseOptions(options) {
|
|
161
|
-
const { isBuild, productName, version, minify = false, paths = {}, keys = {} } = options;
|
|
162
157
|
const {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
158
|
+
isBuild,
|
|
159
|
+
productName,
|
|
160
|
+
version,
|
|
161
|
+
minify = false,
|
|
162
|
+
paths: {
|
|
163
|
+
entryPath = "electron/app.ts",
|
|
164
|
+
entryOutputPath = "app.js",
|
|
165
|
+
asarOutputPath = `release/${productName}-${version}.asar`,
|
|
166
|
+
electronDistPath = "dist-electron",
|
|
167
|
+
rendererDistPath = "dist",
|
|
168
|
+
versionPath = "version.json"
|
|
169
|
+
} = {},
|
|
170
|
+
keys: {
|
|
171
|
+
privateKeyPath = "keys/private.pem",
|
|
172
|
+
certPath = "keys/cert.pem",
|
|
173
|
+
keyLength = 2048,
|
|
174
|
+
certInfo = {},
|
|
175
|
+
overrideFunctions = {}
|
|
176
|
+
} = {}
|
|
177
|
+
} = options;
|
|
170
178
|
const {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
certInfo
|
|
175
|
-
} = keys;
|
|
179
|
+
generateKeyPair,
|
|
180
|
+
generateSignature
|
|
181
|
+
} = overrideFunctions;
|
|
176
182
|
let {
|
|
177
183
|
subject = {
|
|
178
184
|
commonName: productName,
|
|
179
185
|
organization: `org.${productName}`
|
|
180
186
|
},
|
|
181
187
|
expires = Date.now() + 365 * 864e5
|
|
182
|
-
} = certInfo
|
|
188
|
+
} = certInfo;
|
|
183
189
|
const buildAsarOption = {
|
|
184
190
|
version,
|
|
185
191
|
asarOutputPath,
|
|
@@ -202,14 +208,16 @@ function parseOptions(options) {
|
|
|
202
208
|
certPath,
|
|
203
209
|
entryPath,
|
|
204
210
|
subject,
|
|
205
|
-
expires
|
|
211
|
+
expires,
|
|
212
|
+
generateKeyPair
|
|
206
213
|
});
|
|
207
214
|
buildVersionOption = {
|
|
208
215
|
version,
|
|
209
216
|
asarOutputPath,
|
|
210
217
|
privateKey,
|
|
211
218
|
cert,
|
|
212
|
-
versionPath
|
|
219
|
+
versionPath,
|
|
220
|
+
generateSignature
|
|
213
221
|
};
|
|
214
222
|
}
|
|
215
223
|
return { isBuild, buildAsarOption, buildEntryOption, buildVersionOption };
|
package/package.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "electron-incremental-update",
|
|
3
|
-
"
|
|
3
|
+
"author": "subframe7536",
|
|
4
|
+
"version": "0.6.3",
|
|
4
5
|
"description": "electron incremental update tools, powered by vite",
|
|
5
6
|
"scripts": {
|
|
6
7
|
"build": "tsup",
|
|
7
|
-
"release": "pnpm test && pnpm run build && bumpp && npm publish",
|
|
8
|
+
"release": "pnpm test && pnpm run build && bumpp --all && npm publish",
|
|
8
9
|
"test": "vitest --run"
|
|
9
10
|
},
|
|
10
11
|
"publishConfig": {
|
|
@@ -22,22 +23,24 @@
|
|
|
22
23
|
"types": "dist/index.d.ts",
|
|
23
24
|
"exports": {
|
|
24
25
|
".": {
|
|
25
|
-
"
|
|
26
|
-
|
|
26
|
+
"import": {
|
|
27
|
+
"default": "./dist/index.mjs",
|
|
28
|
+
"types": "./dist/index.d.mts"
|
|
29
|
+
},
|
|
30
|
+
"require": {
|
|
31
|
+
"default": "./dist/index.cjs",
|
|
32
|
+
"types": "./dist/index.d.ts"
|
|
33
|
+
}
|
|
27
34
|
},
|
|
28
35
|
"./vite": {
|
|
29
|
-
"
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
],
|
|
38
|
-
"vite": [
|
|
39
|
-
"dist/vite.d.ts"
|
|
40
|
-
]
|
|
36
|
+
"import": {
|
|
37
|
+
"default": "./dist/index.mjs",
|
|
38
|
+
"types": "./dist/index.d.mts"
|
|
39
|
+
},
|
|
40
|
+
"require": {
|
|
41
|
+
"default": "./dist/index.cjs",
|
|
42
|
+
"types": "./dist/index.d.ts"
|
|
43
|
+
}
|
|
41
44
|
}
|
|
42
45
|
},
|
|
43
46
|
"keywords": [
|
|
@@ -45,18 +48,17 @@
|
|
|
45
48
|
"incremental update",
|
|
46
49
|
"updater"
|
|
47
50
|
],
|
|
48
|
-
"author": "",
|
|
49
51
|
"devDependencies": {
|
|
50
52
|
"@electron/asar": "^3.2.4",
|
|
51
53
|
"@subframe7536/eslint-config": "^0.1.9",
|
|
52
|
-
"@types/node": "^20.2
|
|
54
|
+
"@types/node": "^20.3.2",
|
|
53
55
|
"asar": "^3.2.0",
|
|
54
56
|
"bumpp": "^9.1.1",
|
|
55
|
-
"electron": "^25.0
|
|
56
|
-
"eslint": "^8.
|
|
57
|
+
"electron": "^25.2.0",
|
|
58
|
+
"eslint": "^8.43.0",
|
|
57
59
|
"fs-jetpack": "^5.1.0",
|
|
58
|
-
"tsup": "^
|
|
59
|
-
"typescript": "^5.1.
|
|
60
|
+
"tsup": "^7.1.0",
|
|
61
|
+
"typescript": "^5.1.5",
|
|
60
62
|
"vite": "^4.3.9",
|
|
61
63
|
"vitest": "^0.32.2"
|
|
62
64
|
},
|