electron-incremental-update 2.0.0-beta.1 → 2.0.0-beta.10

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/dist/provider.js CHANGED
@@ -1,17 +1,20 @@
1
- import {
2
- isLowerVersionDefault,
3
- isUpdateJSON,
4
- verifySignatureDefault,
5
- waitAppReady
6
- } from "./chunk-RSLOPAIZ.js";
1
+ import { defaultVerifySignature, defaultUnzipFile } from './chunk-KZSYEXLO.js';
2
+ import { defaultIsLowerVersion, isUpdateJSON } from './chunk-72ZAJ7AF.js';
3
+ import { URL } from 'node:url';
4
+ import { app, net } from 'electron';
7
5
 
8
- // src/provider/download.ts
9
- import { net } from "electron";
10
- async function downlaodFn(url, headers, onResponse) {
11
- await waitAppReady();
6
+ function getHeader(headers, key) {
7
+ const value = headers[key];
8
+ if (Array.isArray(value)) {
9
+ return value.length === 0 ? null : value[value.length - 1];
10
+ } else {
11
+ return value;
12
+ }
13
+ }
14
+ async function downloadFn(url, headers, onResponse) {
15
+ await app.whenReady();
12
16
  return new Promise((resolve, reject) => {
13
- const request = net.request({ url, method: "GET", redirect: "follow" });
14
- Object.keys(headers).forEach((key) => request.setHeader(key, headers[key]));
17
+ const request = net.request({ url, method: "GET", redirect: "follow", headers });
15
18
  request.on("response", (resp) => {
16
19
  resp.on("aborted", () => reject(new Error("aborted")));
17
20
  resp.on("error", () => reject(new Error("download error")));
@@ -21,8 +24,8 @@ async function downlaodFn(url, headers, onResponse) {
21
24
  request.end();
22
25
  });
23
26
  }
24
- async function downloadUpdateJSONDefault(url, headers) {
25
- return await downlaodFn(url, headers, (resp, resolve, reject) => {
27
+ async function defaultDownloadUpdateJSON(url, headers) {
28
+ return await downloadFn(url, headers, (resp, resolve, reject) => {
26
29
  let data = "";
27
30
  resp.on("data", (chunk) => data += chunk);
28
31
  resp.on("end", () => {
@@ -33,66 +36,104 @@ async function downloadUpdateJSONDefault(url, headers) {
33
36
  } else {
34
37
  throw Error;
35
38
  }
36
- } catch (ignore) {
39
+ } catch {
37
40
  reject(new Error("invalid update json"));
38
41
  }
39
42
  });
40
43
  });
41
44
  }
42
- async function downloadAsarBufferDefault(url, headers, total, onDownloading) {
43
- let current = 0;
44
- return await downlaodFn(url, headers, (resp, resolve) => {
45
+ async function defaultDownloadAsar(url, headers, onDownloading) {
46
+ let transferred = 0;
47
+ let time = Date.now();
48
+ return await downloadFn(url, headers, (resp, resolve) => {
49
+ const total = getHeader(resp.headers, "content-length") || -1;
45
50
  let data = [];
46
51
  resp.on("data", (chunk) => {
47
- current += chunk.length;
48
- onDownloading?.({ percent: `${+(current / total).toFixed(2) * 100}%`, total, current });
52
+ const delta = chunk.length;
53
+ transferred += delta;
54
+ const current = Date.now();
55
+ onDownloading?.({
56
+ percent: +(transferred / total).toFixed(2) * 100,
57
+ total,
58
+ transferred,
59
+ delta,
60
+ bps: delta / ((current - time) * 1e3)
61
+ });
62
+ time = current;
49
63
  data.push(chunk);
50
64
  });
51
65
  resp.on("end", () => resolve(Buffer.concat(data)));
52
66
  });
53
67
  }
54
68
 
69
+ // src/provider/base.ts
70
+ var BaseProvider = class {
71
+ name = "BaseProvider";
72
+ /**
73
+ * @inheritdoc
74
+ */
75
+ isLowerVersion = defaultIsLowerVersion;
76
+ /**
77
+ * @inheritdoc
78
+ */
79
+ verifySignaure = defaultVerifySignature;
80
+ /**
81
+ * @inheritdoc
82
+ */
83
+ unzipFile = defaultUnzipFile;
84
+ };
85
+
55
86
  // src/provider/github.ts
56
- var GitHubProvider = class {
57
- ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36";
87
+ var GitHubProvider = class extends BaseProvider {
58
88
  name = "GithubProvider";
59
- urlHandler;
60
- url;
61
- extraHeaders;
89
+ options;
90
+ /**
91
+ * Update Provider for Github repo
92
+ * - download update json from `https://raw.githubusercontent.com/{user}/{repo}/HEAD/{versionPath}`
93
+ * - download update asar from `https://github.com/{user}/{repo}/releases/download/v{version}/{name}-{version}.asar.gz`
94
+ *
95
+ * you can setup `urlHandler` in {@link GitHubProviderOptions} or `Updater` to modify url before request
96
+ * @param options provider options
97
+ */
62
98
  constructor(options) {
63
- this.url = new URL(options.url);
64
- this.extraHeaders = options.extraHeaders;
65
- this.urlHandler = options.urlHandler;
66
- if (this.url.host !== "github.com") {
67
- throw new Error(`${this.name}: invalid github url: ${options.url}`);
68
- }
69
- if (!this.url.pathname.endsWith("/")) {
70
- this.url.pathname += "/";
99
+ super();
100
+ this.options = options;
101
+ if (!options.branch) {
102
+ this.options.branch = "HEAD";
71
103
  }
72
104
  }
73
- parseURL(isDownloadAsar, path) {
74
- const url = this.url.href + path;
75
- return this.urlHandler ? this.urlHandler(url, isDownloadAsar) : url;
105
+ get urlHandler() {
106
+ return this.options.urlHandler;
76
107
  }
77
- isLowerVersion = isLowerVersionDefault;
78
- verifySignaure = verifySignatureDefault;
108
+ set urlHandler(handler) {
109
+ this.options.urlHandler = handler;
110
+ }
111
+ async parseURL(isDownloadAsar, extraPath) {
112
+ const url = new URL(
113
+ `/${this.options.username}/${this.options.repo}/${extraPath}`,
114
+ "https://" + (isDownloadAsar ? "github.com" : "raw.githubusercontent.com")
115
+ );
116
+ return (await this.urlHandler?.(url, isDownloadAsar) || url).toString();
117
+ }
118
+ /**
119
+ * @inheritdoc
120
+ */
79
121
  async downloadJSON(versionPath) {
80
- return await downloadUpdateJSONDefault(
81
- this.parseURL(false, `HEAD/${versionPath}`),
82
- { userAgent: this.ua, accept: "application/json", ...this.extraHeaders }
122
+ return await defaultDownloadUpdateJSON(
123
+ await this.parseURL(false, `${this.options.branch}/${versionPath}`),
124
+ { Accept: "application/json", ...this.options.extraHeaders }
83
125
  );
84
126
  }
85
- async downloadBuffer(name, { version, size }, onDownloading) {
86
- return await downloadAsarBufferDefault(
87
- this.parseURL(true, `releases/download/v${version}/${name}-${version}.asar.gz`),
88
- { userAgent: this.ua, accept: "application/octet-stream", ...this.extraHeaders },
89
- size,
127
+ /**
128
+ * @inheritdoc
129
+ */
130
+ async downloadAsar(name, info, onDownloading) {
131
+ return await defaultDownloadAsar(
132
+ await this.parseURL(true, `releases/download/v${info.version}/${name}-${info.version}.asar.gz`),
133
+ { Accept: "application/octet-stream", ...this.options.extraHeaders },
90
134
  onDownloading
91
135
  );
92
136
  }
93
137
  };
94
- export {
95
- GitHubProvider,
96
- downloadAsarBufferDefault,
97
- downloadUpdateJSONDefault
98
- };
138
+
139
+ export { BaseProvider, GitHubProvider, defaultDownloadAsar, defaultDownloadUpdateJSON, getHeader };
@@ -0,0 +1,78 @@
1
+ import { Promisable } from '@subframe7536/type-utils';
2
+ import { a as UpdateJSON, U as UpdateInfo } from './version-C4tF_trh.js';
3
+
4
+ type URLHandler = (url: URL, isDownloadAsar: boolean) => Promisable<URL | string | undefined | null>;
5
+ type OnDownloading = (progress: DownloadingInfo) => void;
6
+ interface DownloadingInfo {
7
+ /**
8
+ * Download buffer delta
9
+ */
10
+ delta: number;
11
+ /**
12
+ * Downloaded percent, 0 ~ 100
13
+ *
14
+ * If no `Content-Length` header, will be nagative
15
+ */
16
+ percent: number;
17
+ /**
18
+ * Total size
19
+ *
20
+ * If not `Content-Length` header, will be -1
21
+ */
22
+ total: number;
23
+ /**
24
+ * Downloaded size
25
+ */
26
+ transferred: number;
27
+ /**
28
+ * Download speed, bytes per second
29
+ */
30
+ bps: number;
31
+ }
32
+ interface IProvider {
33
+ /**
34
+ * Provider name
35
+ */
36
+ name: string;
37
+ /**
38
+ * Custom url handler
39
+ *
40
+ * for Github, there are some {@link https://github.com/XIU2/UserScript/blob/master/GithubEnhanced-High-Speed-Download.user.js#L34 public CDN links}
41
+ */
42
+ urlHandler?: URLHandler;
43
+ onDownloading?: OnDownloading;
44
+ /**
45
+ * Download update json
46
+ * @param versionPath parsed version path in project
47
+ */
48
+ downloadJSON: (versionPath: string) => Promise<UpdateJSON>;
49
+ /**
50
+ * Download update asar
51
+ * @param name app name
52
+ * @param updateInfo existing update info
53
+ * @param onDownloading hook for on downloading
54
+ */
55
+ downloadAsar: (name: string, updateInfo: UpdateInfo, onDownloading?: (info: DownloadingInfo) => void) => Promise<Buffer>;
56
+ /**
57
+ * Check the old version is less than new version
58
+ * @param oldVer old version string
59
+ * @param newVer new version string
60
+ */
61
+ isLowerVersion: (oldVer: string, newVer: string) => boolean;
62
+ /**
63
+ * Function to decompress file using brotli
64
+ * @param buffer compressed file buffer
65
+ */
66
+ unzipFile: (buffer: Buffer) => Promise<Buffer>;
67
+ /**
68
+ * Verify asar signature,
69
+ * if signature is valid, returns the version, otherwise returns `undefined`
70
+ * @param buffer file buffer
71
+ * @param version target version
72
+ * @param signature signature
73
+ * @param cert certificate
74
+ */
75
+ verifySignaure: (buffer: Buffer, version: string, signature: string, cert: string) => Promisable<boolean>;
76
+ }
77
+
78
+ export type { DownloadingInfo as D, IProvider as I, OnDownloading as O, URLHandler as U };
@@ -0,0 +1,78 @@
1
+ import { Promisable } from '@subframe7536/type-utils';
2
+ import { a as UpdateJSON, U as UpdateInfo } from './version-C4tF_trh.cjs';
3
+
4
+ type URLHandler = (url: URL, isDownloadAsar: boolean) => Promisable<URL | string | undefined | null>;
5
+ type OnDownloading = (progress: DownloadingInfo) => void;
6
+ interface DownloadingInfo {
7
+ /**
8
+ * Download buffer delta
9
+ */
10
+ delta: number;
11
+ /**
12
+ * Downloaded percent, 0 ~ 100
13
+ *
14
+ * If no `Content-Length` header, will be nagative
15
+ */
16
+ percent: number;
17
+ /**
18
+ * Total size
19
+ *
20
+ * If not `Content-Length` header, will be -1
21
+ */
22
+ total: number;
23
+ /**
24
+ * Downloaded size
25
+ */
26
+ transferred: number;
27
+ /**
28
+ * Download speed, bytes per second
29
+ */
30
+ bps: number;
31
+ }
32
+ interface IProvider {
33
+ /**
34
+ * Provider name
35
+ */
36
+ name: string;
37
+ /**
38
+ * Custom url handler
39
+ *
40
+ * for Github, there are some {@link https://github.com/XIU2/UserScript/blob/master/GithubEnhanced-High-Speed-Download.user.js#L34 public CDN links}
41
+ */
42
+ urlHandler?: URLHandler;
43
+ onDownloading?: OnDownloading;
44
+ /**
45
+ * Download update json
46
+ * @param versionPath parsed version path in project
47
+ */
48
+ downloadJSON: (versionPath: string) => Promise<UpdateJSON>;
49
+ /**
50
+ * Download update asar
51
+ * @param name app name
52
+ * @param updateInfo existing update info
53
+ * @param onDownloading hook for on downloading
54
+ */
55
+ downloadAsar: (name: string, updateInfo: UpdateInfo, onDownloading?: (info: DownloadingInfo) => void) => Promise<Buffer>;
56
+ /**
57
+ * Check the old version is less than new version
58
+ * @param oldVer old version string
59
+ * @param newVer new version string
60
+ */
61
+ isLowerVersion: (oldVer: string, newVer: string) => boolean;
62
+ /**
63
+ * Function to decompress file using brotli
64
+ * @param buffer compressed file buffer
65
+ */
66
+ unzipFile: (buffer: Buffer) => Promise<Buffer>;
67
+ /**
68
+ * Verify asar signature,
69
+ * if signature is valid, returns the version, otherwise returns `undefined`
70
+ * @param buffer file buffer
71
+ * @param version target version
72
+ * @param signature signature
73
+ * @param cert certificate
74
+ */
75
+ verifySignaure: (buffer: Buffer, version: string, signature: string, cert: string) => Promisable<boolean>;
76
+ }
77
+
78
+ export type { DownloadingInfo as D, IProvider as I, OnDownloading as O, URLHandler as U };