electron-incremental-update 2.2.2 → 2.2.4

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
@@ -197,19 +197,6 @@ export default startupWithUpdater((updater) => {
197
197
  updater.onDownloading = ({ percent }) => {
198
198
  console.log(percent)
199
199
  }
200
- updater.logger = console
201
- updater.receiveBeta = true
202
- // setup provider later
203
- updater.provider = new GitHubProvider({
204
- user: 'yourname',
205
- repo: 'electron',
206
- // setup url handler
207
- urlHandler: (url) => {
208
- url.hostname = 'mirror.ghproxy.com'
209
- url.pathname = `https://github.com${url.pathname}`
210
- return url
211
- }
212
- })
213
200
 
214
201
  updater.on('update-available', async ({ version }) => {
215
202
  const { response } = await dialog.showMessageBox({
@@ -222,25 +209,56 @@ export default startupWithUpdater((updater) => {
222
209
  }
223
210
  await updater.downloadUpdate()
224
211
  })
212
+
225
213
  updater.on('update-not-available', (code, reason, info) => console.log(code, reason, info))
214
+
226
215
  updater.on('download-progress', (data) => {
227
216
  console.log(data)
228
217
  main.send(BrowserWindow.getAllWindows()[0], 'msg', data)
229
218
  })
219
+
230
220
  updater.on('update-downloaded', () => {
231
221
  updater.quitAndInstall()
232
222
  })
223
+
233
224
  updater.checkForUpdates()
234
225
  })
235
226
  ```
236
227
 
228
+ #### Dynamicly setup `UpdateProvider`
229
+
230
+ ```ts
231
+ updater.provider = new GitHubProvider({
232
+ user: 'yourname',
233
+ repo: 'electron',
234
+ // setup url handler
235
+ urlHandler: (url) => {
236
+ url.hostname = 'mirror.ghproxy.com'
237
+ url.pathname = `https://github.com${url.pathname}`
238
+ return url
239
+ }
240
+ })
241
+ ```
242
+
243
+ #### Custom logger
244
+
245
+ ```ts
246
+ updater.logger = console
247
+ ```
248
+
249
+ #### Setup Beta Channel
250
+
251
+ ```ts
252
+ updater.receiveBeta = true
253
+ ```
254
+
237
255
  ### Use Native Modules
238
256
 
239
257
  To reduce production size, it is recommended that all the **native modules** should be set as `dependency` in `package.json` and other packages should be set as `devDependencies`. Also, `electron-rebuild` only check dependencies inside `dependency` field.
240
258
 
241
259
  If you are using `electron-builder` to build distributions, all the native modules with its **large relavent `node_modiles`** will be packaged into `app.asar` by default.
242
260
 
243
- Luckily, `Esbuild` can bundle all the dependencies. Just follow the steps:
261
+ Luckily, `vite` can bundle all the dependencies. Just follow the steps:
244
262
 
245
263
  1. setup `nativeModuleEntryMap` option
246
264
  2. Manually copy the native binaries in `postBuild` callback
@@ -472,6 +490,60 @@ function getPathFromEntryAsar(...paths: string[]): string
472
490
  * @param callback callback function
473
491
  */
474
492
  function handleUnexpectedErrors(callback: (err: unknown) => void): void
493
+ /**
494
+ * Safe get value from header
495
+ * @param headers response header
496
+ * @param key target header key
497
+ */
498
+ function getHeader(headers: Record<string, Arrayable<string>>, key: any): any
499
+ function downloadUtil<T>(
500
+ url: string,
501
+ headers: Record<string, any>,
502
+ signal: AbortSignal,
503
+ onResponse: (
504
+ resp: IncomingMessage,
505
+ resolve: (data: T) => void,
506
+ reject: (e: any) => void
507
+ ) => void
508
+ ): Promise<T>
509
+ /**
510
+ * Default function to download json and parse to UpdateJson
511
+ * @param url target url
512
+ * @param headers extra headers
513
+ * @param signal abort signal
514
+ * @param resolveData on resolve
515
+ */
516
+ function defaultDownloadJSON<T>(
517
+ url: string,
518
+ headers: Record<string, any>,
519
+ signal: AbortSignal,
520
+ resolveData?: ResolveDataFn
521
+ ): Promise<T>
522
+ /**
523
+ * Default function to download json and parse to UpdateJson
524
+ * @param url target url
525
+ * @param headers extra headers
526
+ * @param signal abort signal
527
+ */
528
+ function defaultDownloadUpdateJSON(
529
+ url: string,
530
+ headers: Record<string, any>,
531
+ signal: AbortSignal
532
+ ): Promise<UpdateJSON>
533
+ /**
534
+ * Default function to download asar buffer,
535
+ * get total size from `Content-Length` header
536
+ * @param url target url
537
+ * @param headers extra headers
538
+ * @param signal abort signal
539
+ * @param onDownloading on downloading callback
540
+ */
541
+ function defaultDownloadAsar(
542
+ url: string,
543
+ headers: Record<string, any>,
544
+ signal: AbortSignal,
545
+ onDownloading?: (progress: DownloadingInfo) => void
546
+ ): Promise<Buffer>
475
547
  ```
476
548
 
477
549
  ### Types
@@ -925,15 +997,14 @@ export interface GeneratorOverrideFunctions {
925
997
  version: string
926
998
  ) => Promisable<string>
927
999
  /**
928
- * Custom generate version json function
1000
+ * Custom generate update json function
929
1001
  * @param existingJson The existing JSON object.
930
1002
  * @param buffer file buffer
931
1003
  * @param signature generated signature
932
1004
  * @param version current version
933
1005
  * @param minVersion The minimum version
934
- * @returns The updated version json
935
1006
  */
936
- generateVersionJson?: (
1007
+ generateUpdateJson?: (
937
1008
  existingJson: UpdateJSON,
938
1009
  signature: string,
939
1010
  version: string,
@@ -1,5 +1,5 @@
1
1
  import { readableSize } from './chunk-TPTWE33H.js';
2
- import { convertLiteral, bytecodeModuleLoaderCode, bytecodeModuleLoader, convertArrowFunctionAndTemplate, compileToBytecode, useStrict, toRelativePath } from './chunk-LR7LR5WG.js';
2
+ import { convertArrowFunctionAndTemplate, bytecodeModuleLoader, bytecodeModuleLoaderCode, convertLiteral, compileToBytecode, useStrict, toRelativePath } from './chunk-LR7LR5WG.js';
3
3
  import { bytecodeLog, bytecodeId } from './chunk-5NKEXGI3.js';
4
4
  import fs from 'node:fs';
5
5
  import path from 'node:path';
@@ -0,0 +1,135 @@
1
+ import { isUpdateJSON } from './chunk-AAAM44NW.js';
2
+ import crypto from 'node:crypto';
3
+ import electron from 'electron';
4
+ import zlib from 'node:zlib';
5
+
6
+ function hashBuffer(data, length) {
7
+ const hash = crypto.createHash("SHA256").update(data).digest("binary");
8
+ return Buffer.from(hash).subarray(0, length);
9
+ }
10
+ function aesEncrypt(plainText, key, iv) {
11
+ const cipher = crypto.createCipheriv("aes-256-cbc", key, iv);
12
+ return cipher.update(plainText, "utf8", "base64url") + cipher.final("base64url");
13
+ }
14
+ function defaultSignature(buffer, privateKey, cert, version) {
15
+ const sig = crypto.createSign("RSA-SHA256").update(buffer).sign(crypto.createPrivateKey(privateKey), "base64");
16
+ return aesEncrypt(`${sig}%${version}`, hashBuffer(cert, 32), hashBuffer(buffer, 16));
17
+ }
18
+ function aesDecrypt(encryptedText, key, iv) {
19
+ const decipher = crypto.createDecipheriv("aes-256-cbc", key, iv);
20
+ return decipher.update(encryptedText, "base64url", "utf8") + decipher.final("utf8");
21
+ }
22
+ function defaultVerifySignature(buffer, version, signature, cert) {
23
+ try {
24
+ const [sig, ver] = aesDecrypt(signature, hashBuffer(cert, 32), hashBuffer(buffer, 16)).split("%");
25
+ if (ver !== version) {
26
+ return false;
27
+ }
28
+ return crypto.createVerify("RSA-SHA256").update(buffer).verify(cert, sig, "base64");
29
+ } catch {
30
+ return false;
31
+ }
32
+ }
33
+ function getHeader(headers, key) {
34
+ const value = headers[key];
35
+ if (Array.isArray(value)) {
36
+ return value.length === 0 ? null : value[value.length - 1];
37
+ } else {
38
+ return value;
39
+ }
40
+ }
41
+ async function downloadUtil(url, headers, signal, onResponse) {
42
+ await electron.app.whenReady();
43
+ return new Promise((resolve, reject) => {
44
+ const request = electron.net.request({ url, method: "GET", redirect: "follow", headers, cache: "no-cache" });
45
+ signal.addEventListener("abort", () => request.abort(), { once: true });
46
+ request.on("response", (resp) => {
47
+ resp.on("aborted", () => reject(new Error("aborted")));
48
+ resp.on("error", () => reject(new Error("download error")));
49
+ onResponse(resp, resolve, reject);
50
+ });
51
+ request.on("error", reject);
52
+ request.end();
53
+ });
54
+ }
55
+ function trimData(data) {
56
+ return data.trim().slice(0, 5e3).replace(/\s+/g, " ");
57
+ }
58
+ var defaultResolveDataFn = (data, resolve, reject) => {
59
+ try {
60
+ resolve(JSON.parse(data));
61
+ } catch {
62
+ reject(new Error(`Invalid json, "${trimData(data)}"`));
63
+ }
64
+ };
65
+ async function defaultDownloadJSON(url, headers, signal, resolveData = defaultResolveDataFn) {
66
+ return await downloadUtil(
67
+ url,
68
+ headers,
69
+ signal,
70
+ (resp, resolve, reject) => {
71
+ let data = "";
72
+ resp.on("data", (chunk) => data += chunk);
73
+ resp.on("end", () => resolveData(data, resolve, reject));
74
+ }
75
+ );
76
+ }
77
+ async function defaultDownloadUpdateJSON(url, headers, signal) {
78
+ return await defaultDownloadJSON(
79
+ url,
80
+ headers,
81
+ signal,
82
+ (data, resolve, reject) => {
83
+ try {
84
+ const json = JSON.parse(data);
85
+ if (isUpdateJSON(json)) {
86
+ resolve(json);
87
+ } else {
88
+ throw Error;
89
+ }
90
+ } catch {
91
+ reject(new Error(`Invalid update json, "${trimData(data)}"`));
92
+ }
93
+ }
94
+ );
95
+ }
96
+ async function defaultDownloadAsar(url, headers, signal, onDownloading) {
97
+ let transferred = 0;
98
+ let time = Date.now();
99
+ return await downloadUtil(
100
+ url,
101
+ headers,
102
+ signal,
103
+ (resp, resolve) => {
104
+ const total = +getHeader(resp.headers, "content-length") || -1;
105
+ const data = [];
106
+ resp.on("data", (chunk) => {
107
+ const delta = chunk.length;
108
+ transferred += delta;
109
+ const current = Date.now();
110
+ onDownloading?.({
111
+ percent: total > 0 ? +(transferred / total).toFixed(2) * 100 : -1,
112
+ total,
113
+ transferred,
114
+ delta,
115
+ bps: delta / (current - time)
116
+ });
117
+ time = current;
118
+ data.push(chunk);
119
+ });
120
+ resp.on("end", () => resolve(Buffer.concat(data)));
121
+ }
122
+ );
123
+ }
124
+ async function defaultZipFile(buffer) {
125
+ return new Promise((resolve, reject) => {
126
+ zlib.brotliCompress(buffer, (err, buffer2) => err ? reject(err) : resolve(buffer2));
127
+ });
128
+ }
129
+ async function defaultUnzipFile(buffer) {
130
+ return new Promise((resolve, reject) => {
131
+ zlib.brotliDecompress(buffer, (err, buffer2) => err ? reject(err) : resolve(buffer2));
132
+ });
133
+ }
134
+
135
+ export { aesDecrypt, aesEncrypt, defaultDownloadAsar, defaultDownloadJSON, defaultDownloadUpdateJSON, defaultSignature, defaultUnzipFile, defaultVerifySignature, defaultZipFile, downloadUtil, getHeader, hashBuffer };
@@ -71,13 +71,13 @@ function loadPage(win, htmlFilePath = "index.html") {
71
71
  }
72
72
  function beautifyDevTools(win, options) {
73
73
  const { mono, sans, scrollbar = true } = options;
74
- win.webContents.on("devtools-opened", () => {
75
- let css = `:root{--sans: ${sans};--mono: ${mono}}:root,body{--source-code-font-family: var(--mono) !important;--source-code-font-size: 12px !important;--monospace-font-family: var(--mono) !important;--monospace-font-size: 12px !important;--default-font-family: var(--sans), sans-serif !important;--default-font-size: 12px !important}button,input,select,.undisplayable-text,.expandable-inline-button{font-family:var(--sans)!important}`;
74
+ win.webContents.on("devtools-opened", async () => {
75
+ let css = `:root{--sans:${sans};--mono:${mono}}:root,body{--source-code-font-family:var(--mono)!important;--source-code-font-size:12px!important;--monospace-font-family:var(--mono)!important;--monospace-font-size:12px!important;--default-font-family:var(--sans), sans-serif!important;--default-font-size:12px!important}button,input,select,.undisplayable-text,.expandable-inline-button{font-family:var(--sans)!important}`;
76
76
  if (scrollbar) {
77
- css += ":root{--scrollbar-width: max(.85vw, 10px)}@media (prefers-color-scheme: light){:root{--scrollbar-color-rgb: 0, 0, 0}}@media (prefers-color-scheme: dark){:root{--scrollbar-color-rgb: 255, 255, 255}}*::-webkit-scrollbar{width:var(--scrollbar-width)!important;height:var(--scrollbar-width)!important}*::-webkit-scrollbar-track{background-color:transparent!important;border-radius:var(--scrollbar-width)!important;box-shadow:none!important}*::-webkit-scrollbar-thumb{box-shadow:inset 0 0 0 var(--scrollbar-width)!important;border-radius:var(--scrollbar-width)!important;border:calc(var(--scrollbar-width) * 2 / 9) solid transparent!important;background-clip:content-box;background-color:transparent!important;color:rgba(var(--scrollbar-color-rgb),30%)!important}*::-webkit-scrollbar-thumb:hover{color:rgba(var(--scrollbar-color-rgb),45%)!important}*::-webkit-scrollbar-thumb:active{color:rgba(var(--scrollbar-color-rgb),60%)!important}@supports not selector(::-webkit-scrollbar){html{scrollbar-color:rgb(var(--scrollbar-color-rgb));scrollbar-width:thin}}";
77
+ css += ":root{--scrollbar-width:max(.85vw,10px)}@media (prefers-color-scheme:light){:root{--scrollbar-color-rgb:0,0,0}}@media (prefers-color-scheme:dark){:root{--scrollbar-color-rgb:255,255,255}}*::-webkit-scrollbar{width:var(--scrollbar-width)!important;height:var(--scrollbar-width)!important}*::-webkit-scrollbar-track{background-color:transparent!important;border-radius:var(--scrollbar-width)!important;box-shadow:none!important}*::-webkit-scrollbar-thumb{box-shadow:inset 0 0 0 var(--scrollbar-width)!important;border-radius:var(--scrollbar-width)!important;border:calc(var(--scrollbar-width) * 2/9) solid transparent!important;background-clip:content-box;background-color:transparent!important;color:rgba(var(--scrollbar-color-rgb),30%)!important}*::-webkit-scrollbar-thumb:hover{color:rgba(var(--scrollbar-color-rgb),45%)!important}*::-webkit-scrollbar-thumb:active{color:rgba(var(--scrollbar-color-rgb),60%)!important}@supports not selector(::-webkit-scrollbar){html{scrollbar-color:rgb(var(--scrollbar-color-rgb));scrollbar-width:thin}}";
78
78
  }
79
- const js = `let overriddenStyle=document.createElement('style');overriddenStyle.innerHTML='${css}';document.body.append(overriddenStyle);document.body.classList.remove('platform-windows','platform-mac','platform-linux');`;
80
- win?.webContents.devToolsWebContents?.executeJavaScript(js);
79
+ const js = `${'function run(n){let d=document.createElement("style");d.innerHTML=n,document.body.append(d),["platform-windows","platform-mac","platform-linux"].forEach(t=>document.querySelectorAll(`.${t}`).forEach(o=>o.classList.remove(t))),l();const r=new MutationObserver(t=>{for(const o of t)if(o.type==="childList")for(let e=0;e<o.addedNodes.length;e++)o.addedNodes[e].classList.contains("editor-tooltip-host")&&l()});r.observe(document.body,{childList:!0});function l(){document.querySelectorAll(".editor-tooltip-host").forEach(t=>{if(t?.shadowRoot?.querySelectorAll(\'[data-key="overridden-dev-tools-font"]\').length===0){const o=document.createElement("style");o.setAttribute("data-key","overridden-dev-tools-font"),o.innerHTML=`${n}.cm-tooltip-autocomplete ul[role=listbox]{font-family:var(--mono)!important;}`,t.shadowRoot.append(o)}})}document.onclose=()=>r.disconnect()}'};run(\`${css}\`)`;
80
+ await win?.webContents.devToolsWebContents?.executeJavaScript(js);
81
81
  });
82
82
  }
83
83
  function getPathFromMain(...paths) {
@@ -96,5 +96,16 @@ function handleUnexpectedErrors(callback) {
96
96
  process.on("uncaughtException", callback);
97
97
  process.on("unhandledRejection", callback);
98
98
  }
99
+ function reloadOnPreloadScriptChanged() {
100
+ if (isDev) {
101
+ process.on("message", (msg) => {
102
+ if (msg === "electron-vite&type=hot-reload") {
103
+ for (const window of electron.BrowserWindow.getAllWindows()) {
104
+ window.reload();
105
+ }
106
+ }
107
+ });
108
+ }
109
+ }
99
110
 
100
- export { beautifyDevTools, disableHWAccForWin7, getAppVersion, getEntryVersion, getPathFromAppNameAsar, getPathFromEntryAsar, getPathFromMain, getPathFromPreload, getPathFromPublic, handleUnexpectedErrors, importNative, isDev, isLinux, isMac, isWin, loadPage, requireNative, restartApp, setAppUserModelId, setPortableAppDataPath, singleInstance };
111
+ export { beautifyDevTools, disableHWAccForWin7, getAppVersion, getEntryVersion, getPathFromAppNameAsar, getPathFromEntryAsar, getPathFromMain, getPathFromPreload, getPathFromPublic, handleUnexpectedErrors, importNative, isDev, isLinux, isMac, isWin, loadPage, reloadOnPreloadScriptChanged, requireNative, restartApp, setAppUserModelId, setPortableAppDataPath, singleInstance };
@@ -185,7 +185,7 @@ function convertLiteral(code, sourcemap, offset) {
185
185
  }
186
186
  return {
187
187
  code: s.toString(),
188
- map: sourcemap ? s.generateMap({ hires: true }) : void 0
188
+ map: sourcemap ? s.generateMap({ hires: true }) : undefined
189
189
  };
190
190
  }
191
191
 
package/dist/index.cjs CHANGED
@@ -177,7 +177,7 @@ var Updater = class extends events.EventEmitter {
177
177
  this.err("Download failed", "ERR_PARAM", "No update asar buffer and provider");
178
178
  return false;
179
179
  }
180
- const buffer = await this.fetch("buffer", data ? Buffer.from(data) : void 0);
180
+ const buffer = await this.fetch("buffer", data ? Buffer.from(data) : undefined);
181
181
  if (!buffer) {
182
182
  this.err("Download failed", "ERR_PARAM", "No update asar file buffer");
183
183
  return false;
@@ -256,7 +256,7 @@ async function createElectronApp(appOptions = {}) {
256
256
  __require(mainPath)(updaterInstance);
257
257
  }
258
258
  } catch (error) {
259
- logger?.error("startup error", error);
259
+ logger?.error("startup error, exit", error);
260
260
  onStartError?.(error, logger);
261
261
  electron__default.default.app.quit();
262
262
  }
package/dist/index.d.cts CHANGED
@@ -1,6 +1,5 @@
1
1
  import { Promisable } from '@subframe7536/type-utils';
2
- import { I as IProvider, D as DownloadingInfo, U as UpdateJSONWithURL } from './types-CWtySwqA.cjs';
3
- import { U as UpdateInfo, a as UpdateJSON } from './version-Bl_0oO5f.cjs';
2
+ import { U as UpdateInfo, I as IProvider, D as DownloadingInfo, a as UpdateJSON, b as UpdateJSONWithURL } from './types-C5M2xRjF.cjs';
4
3
  import { EventEmitter } from 'node:events';
5
4
  import 'node:url';
6
5
 
package/dist/index.d.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  import { Promisable } from '@subframe7536/type-utils';
2
- import { I as IProvider, D as DownloadingInfo, U as UpdateJSONWithURL } from './types-CStrrQPl.js';
3
- import { U as UpdateInfo, a as UpdateJSON } from './version-Bl_0oO5f.js';
2
+ import { U as UpdateInfo, I as IProvider, D as DownloadingInfo, a as UpdateJSON, b as UpdateJSONWithURL } from './types-C5M2xRjF.js';
4
3
  import { EventEmitter } from 'node:events';
5
4
  import 'node:url';
6
5
 
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { isDev, getAppVersion, getEntryVersion, getPathFromAppNameAsar, restartApp } from './chunk-JI27JWJN.js';
1
+ import { isDev, getEntryVersion, getAppVersion, getPathFromAppNameAsar, restartApp } from './chunk-K4N2OHNS.js';
2
2
  import { isUpdateJSON, __require } from './chunk-AAAM44NW.js';
3
3
  import fs2 from 'node:fs';
4
4
  import path from 'node:path';
@@ -141,7 +141,7 @@ var Updater = class extends EventEmitter {
141
141
  this.err("Download failed", "ERR_PARAM", "No update asar buffer and provider");
142
142
  return false;
143
143
  }
144
- const buffer = await this.fetch("buffer", data ? Buffer.from(data) : void 0);
144
+ const buffer = await this.fetch("buffer", data ? Buffer.from(data) : undefined);
145
145
  if (!buffer) {
146
146
  this.err("Download failed", "ERR_PARAM", "No update asar file buffer");
147
147
  return false;
@@ -220,7 +220,7 @@ async function createElectronApp(appOptions = {}) {
220
220
  __require(mainPath)(updaterInstance);
221
221
  }
222
222
  } catch (error) {
223
- logger?.error("startup error", error);
223
+ logger?.error("startup error, exit", error);
224
224
  onStartError?.(error, logger);
225
225
  electron2.app.quit();
226
226
  }
package/dist/provider.cjs CHANGED
@@ -1,36 +1,17 @@
1
1
  'use strict';
2
2
 
3
+ var electron = require('electron');
3
4
  var crypto = require('crypto');
4
5
  var zlib = require('zlib');
5
- var electron = require('electron');
6
6
  var url = require('url');
7
7
 
8
8
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
9
9
 
10
+ var electron__default = /*#__PURE__*/_interopDefault(electron);
10
11
  var crypto__default = /*#__PURE__*/_interopDefault(crypto);
11
12
  var zlib__default = /*#__PURE__*/_interopDefault(zlib);
12
- var electron__default = /*#__PURE__*/_interopDefault(electron);
13
13
 
14
- // src/utils/crypto.ts
15
- function hashBuffer(data, length) {
16
- const hash = crypto__default.default.createHash("SHA256").update(data).digest("binary");
17
- return Buffer.from(hash).subarray(0, length);
18
- }
19
- function aesDecrypt(encryptedText, key, iv) {
20
- const decipher = crypto__default.default.createDecipheriv("aes-256-cbc", key, iv);
21
- return decipher.update(encryptedText, "base64url", "utf8") + decipher.final("utf8");
22
- }
23
- function defaultVerifySignature(buffer, version, signature, cert) {
24
- try {
25
- const [sig, ver] = aesDecrypt(signature, hashBuffer(cert, 32), hashBuffer(buffer, 16)).split("%");
26
- if (ver !== version) {
27
- return false;
28
- }
29
- return crypto__default.default.createVerify("RSA-SHA256").update(buffer).verify(cert, sig, "base64");
30
- } catch {
31
- return false;
32
- }
33
- }
14
+ // src/utils/download.ts
34
15
 
35
16
  // src/utils/version.ts
36
17
  function parseVersion(version) {
@@ -80,28 +61,8 @@ var is = (j) => !!(j && j.minimumVersion && j.signature && j.version);
80
61
  function isUpdateJSON(json) {
81
62
  return is(json) && is(json?.beta);
82
63
  }
83
- async function defaultUnzipFile(buffer) {
84
- return new Promise((resolve, reject) => {
85
- zlib__default.default.brotliDecompress(buffer, (err, buffer2) => err ? reject(err) : resolve(buffer2));
86
- });
87
- }
88
64
 
89
- // src/provider/base.ts
90
- var BaseProvider = class {
91
- name = "BaseProvider";
92
- /**
93
- * @inheritdoc
94
- */
95
- isLowerVersion = defaultIsLowerVersion;
96
- /**
97
- * @inheritdoc
98
- */
99
- verifySignaure = defaultVerifySignature;
100
- /**
101
- * @inheritdoc
102
- */
103
- unzipFile = defaultUnzipFile;
104
- };
65
+ // src/utils/download.ts
105
66
  function getHeader(headers, key) {
106
67
  const value = headers[key];
107
68
  if (Array.isArray(value)) {
@@ -110,7 +71,7 @@ function getHeader(headers, key) {
110
71
  return value;
111
72
  }
112
73
  }
113
- async function downloadFn(url, headers, signal, onResponse) {
74
+ async function downloadUtil(url, headers, signal, onResponse) {
114
75
  await electron__default.default.app.whenReady();
115
76
  return new Promise((resolve, reject) => {
116
77
  const request = electron__default.default.net.request({ url, method: "GET", redirect: "follow", headers, cache: "no-cache" });
@@ -135,7 +96,7 @@ var defaultResolveDataFn = (data, resolve, reject) => {
135
96
  }
136
97
  };
137
98
  async function defaultDownloadJSON(url, headers, signal, resolveData = defaultResolveDataFn) {
138
- return await downloadFn(
99
+ return await downloadUtil(
139
100
  url,
140
101
  headers,
141
102
  signal,
@@ -168,7 +129,7 @@ async function defaultDownloadUpdateJSON(url, headers, signal) {
168
129
  async function defaultDownloadAsar(url, headers, signal, onDownloading) {
169
130
  let transferred = 0;
170
131
  let time = Date.now();
171
- return await downloadFn(
132
+ return await downloadUtil(
172
133
  url,
173
134
  headers,
174
135
  signal,
@@ -193,6 +154,47 @@ async function defaultDownloadAsar(url, headers, signal, onDownloading) {
193
154
  }
194
155
  );
195
156
  }
157
+ function hashBuffer(data, length) {
158
+ const hash = crypto__default.default.createHash("SHA256").update(data).digest("binary");
159
+ return Buffer.from(hash).subarray(0, length);
160
+ }
161
+ function aesDecrypt(encryptedText, key, iv) {
162
+ const decipher = crypto__default.default.createDecipheriv("aes-256-cbc", key, iv);
163
+ return decipher.update(encryptedText, "base64url", "utf8") + decipher.final("utf8");
164
+ }
165
+ function defaultVerifySignature(buffer, version, signature, cert) {
166
+ try {
167
+ const [sig, ver] = aesDecrypt(signature, hashBuffer(cert, 32), hashBuffer(buffer, 16)).split("%");
168
+ if (ver !== version) {
169
+ return false;
170
+ }
171
+ return crypto__default.default.createVerify("RSA-SHA256").update(buffer).verify(cert, sig, "base64");
172
+ } catch {
173
+ return false;
174
+ }
175
+ }
176
+ async function defaultUnzipFile(buffer) {
177
+ return new Promise((resolve, reject) => {
178
+ zlib__default.default.brotliDecompress(buffer, (err, buffer2) => err ? reject(err) : resolve(buffer2));
179
+ });
180
+ }
181
+
182
+ // src/provider/base.ts
183
+ var BaseProvider = class {
184
+ name = "BaseProvider";
185
+ /**
186
+ * @inheritdoc
187
+ */
188
+ isLowerVersion = defaultIsLowerVersion;
189
+ /**
190
+ * @inheritdoc
191
+ */
192
+ verifySignaure = defaultVerifySignature;
193
+ /**
194
+ * @inheritdoc
195
+ */
196
+ unzipFile = defaultUnzipFile;
197
+ };
196
198
  var GitHubProvider = class extends BaseProvider {
197
199
  name = "GithubProvider";
198
200
  options;
@@ -355,4 +357,5 @@ exports.GitHubProvider = GitHubProvider;
355
357
  exports.defaultDownloadAsar = defaultDownloadAsar;
356
358
  exports.defaultDownloadJSON = defaultDownloadJSON;
357
359
  exports.defaultDownloadUpdateJSON = defaultDownloadUpdateJSON;
360
+ exports.downloadUtil = downloadUtil;
358
361
  exports.getHeader = getHeader;
@@ -1,10 +1,12 @@
1
- import { I as IProvider, U as UpdateJSONWithURL, a as UpdateInfoWithURL, D as DownloadingInfo, O as OnDownloading, b as URLHandler } from './types-CWtySwqA.cjs';
2
- import { c as defaultVerifySignature, f as defaultUnzipFile } from './zip-DQdr8pFv.cjs';
3
- import { d as defaultIsLowerVersion, a as UpdateJSON } from './version-Bl_0oO5f.cjs';
4
- import { Arrayable } from '@subframe7536/type-utils';
1
+ import { c as defaultVerifySignature, l as defaultUnzipFile } from './zip-BQS8qbGA.cjs';
2
+ export { j as defaultDownloadAsar, f as defaultDownloadJSON, i as defaultDownloadUpdateJSON, e as downloadUtil, g as getHeader } from './zip-BQS8qbGA.cjs';
3
+ import { e as UpdateInfoWithURL, I as IProvider, d as defaultIsLowerVersion, D as DownloadingInfo, f as URLHandler } from './types-C5M2xRjF.cjs';
4
+ export { b as UpdateJSONWithURL } from './types-C5M2xRjF.cjs';
5
+ import '@subframe7536/type-utils';
6
+ import 'electron';
5
7
  import 'node:url';
6
8
 
7
- declare abstract class BaseProvider implements IProvider {
9
+ declare abstract class BaseProvider<T extends UpdateInfoWithURL = UpdateInfoWithURL> implements IProvider<T> {
8
10
  name: string;
9
11
  /**
10
12
  * @inheritdoc
@@ -21,45 +23,13 @@ declare abstract class BaseProvider implements IProvider {
21
23
  /**
22
24
  * @inheritdoc
23
25
  */
24
- abstract downloadJSON(name: string, versionPath: string, signal: AbortSignal): Promise<UpdateJSONWithURL>;
26
+ abstract downloadJSON(name: string, versionPath: string, signal: AbortSignal): Promise<T>;
25
27
  /**
26
28
  * @inheritdoc
27
29
  */
28
30
  abstract downloadAsar(info: UpdateInfoWithURL, signal: AbortSignal, onDownloading?: (info: DownloadingInfo) => void): Promise<Buffer>;
29
31
  }
30
32
 
31
- /**
32
- * Safe get value from header
33
- * @param headers response header
34
- * @param key target header key
35
- */
36
- declare function getHeader(headers: Record<string, Arrayable<string>>, key: any): any;
37
- type ResolveDataFn = (data: string, resolve: (data: any) => void, reject: (e: any) => void) => void;
38
- /**
39
- * Default function to download json and parse to UpdateJson
40
- * @param url target url
41
- * @param headers extra headers
42
- * @param signal abort signal
43
- * @param resolveData on resolve
44
- */
45
- declare function defaultDownloadJSON<T>(url: string, headers: Record<string, any>, signal: AbortSignal, resolveData?: ResolveDataFn): Promise<T>;
46
- /**
47
- * Default function to download json and parse to UpdateJson
48
- * @param url target url
49
- * @param headers extra headers
50
- * @param signal abort signal
51
- */
52
- declare function defaultDownloadUpdateJSON(url: string, headers: Record<string, any>, signal: AbortSignal): Promise<UpdateJSON>;
53
- /**
54
- * Default function to download asar buffer,
55
- * get total size from `Content-Length` header
56
- * @param url target url
57
- * @param headers extra headers
58
- * @param signal abort signal
59
- * @param onDownloading on downloading callback
60
- */
61
- declare function defaultDownloadAsar(url: string, headers: Record<string, any>, signal: AbortSignal, onDownloading?: OnDownloading): Promise<Buffer>;
62
-
63
33
  interface GitHubProviderOptions {
64
34
  /**
65
35
  * Github user name
@@ -89,7 +59,7 @@ interface GitHubProviderOptions {
89
59
  */
90
60
  urlHandler?: URLHandler;
91
61
  }
92
- declare class GitHubProvider extends BaseProvider {
62
+ declare class GitHubProvider<T extends UpdateInfoWithURL = UpdateInfoWithURL> extends BaseProvider<T> {
93
63
  name: string;
94
64
  private options;
95
65
  /**
@@ -108,7 +78,7 @@ declare class GitHubProvider extends BaseProvider {
108
78
  /**
109
79
  * @inheritdoc
110
80
  */
111
- downloadJSON(name: string, versionPath: string, signal: AbortSignal): Promise<UpdateJSONWithURL>;
81
+ downloadJSON(name: string, versionPath: string, signal: AbortSignal): Promise<T>;
112
82
  /**
113
83
  * @inheritdoc
114
84
  */
@@ -137,7 +107,7 @@ interface GitHubApiProviderOptions {
137
107
  */
138
108
  urlHandler?: URLHandler;
139
109
  }
140
- declare class GitHubApiProvider extends BaseProvider {
110
+ declare class GitHubApiProvider<T extends UpdateInfoWithURL = UpdateInfoWithURL> extends BaseProvider<T> {
141
111
  name: string;
142
112
  private options;
143
113
  /**
@@ -157,11 +127,11 @@ declare class GitHubApiProvider extends BaseProvider {
157
127
  /**
158
128
  * @inheritdoc
159
129
  */
160
- downloadJSON(name: string, versionPath: string, signal: AbortSignal): Promise<UpdateJSONWithURL>;
130
+ downloadJSON(name: string, versionPath: string, signal: AbortSignal): Promise<T>;
161
131
  /**
162
132
  * @inheritdoc
163
133
  */
164
134
  downloadAsar(info: UpdateInfoWithURL, signal: AbortSignal, onDownloading?: (info: DownloadingInfo) => void): Promise<Buffer>;
165
135
  }
166
136
 
167
- export { BaseProvider, DownloadingInfo, GitHubApiProvider, type GitHubApiProviderOptions, GitHubProvider, type GitHubProviderOptions, IProvider, OnDownloading, URLHandler, UpdateInfoWithURL, UpdateJSONWithURL, defaultDownloadAsar, defaultDownloadJSON, defaultDownloadUpdateJSON, getHeader };
137
+ export { BaseProvider, DownloadingInfo, GitHubApiProvider, type GitHubApiProviderOptions, GitHubProvider, type GitHubProviderOptions, IProvider, URLHandler, UpdateInfoWithURL };