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

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,21 @@
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-RCRKUKFX.js';
3
+ import { URL } from 'node:url';
4
+ import electron 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, signal, onResponse) {
15
+ await electron.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 = electron.net.request({ url, method: "GET", redirect: "follow", headers, cache: "no-cache" });
18
+ signal.addEventListener("abort", () => request.abort(), { once: true });
15
19
  request.on("response", (resp) => {
16
20
  resp.on("aborted", () => reject(new Error("aborted")));
17
21
  resp.on("error", () => reject(new Error("download error")));
@@ -21,78 +25,128 @@ async function downlaodFn(url, headers, onResponse) {
21
25
  request.end();
22
26
  });
23
27
  }
24
- async function downloadUpdateJSONDefault(url, headers) {
25
- return await downlaodFn(url, headers, (resp, resolve, reject) => {
26
- let data = "";
27
- resp.on("data", (chunk) => data += chunk);
28
- resp.on("end", () => {
29
- try {
30
- const json = JSON.parse(data);
31
- if (isUpdateJSON(json)) {
32
- resolve(json);
33
- } else {
34
- throw Error;
28
+ async function defaultDownloadUpdateJSON(url, headers, signal) {
29
+ return await downloadFn(
30
+ url,
31
+ headers,
32
+ signal,
33
+ (resp, resolve, reject) => {
34
+ let data = "";
35
+ resp.on("data", (chunk) => data += chunk);
36
+ resp.on("end", () => {
37
+ try {
38
+ const json = JSON.parse(data);
39
+ if (isUpdateJSON(json)) {
40
+ resolve(json);
41
+ } else {
42
+ throw Error;
43
+ }
44
+ } catch {
45
+ reject(new Error("invalid update json " + data));
35
46
  }
36
- } catch (ignore) {
37
- reject(new Error("invalid update json"));
38
- }
39
- });
40
- });
47
+ });
48
+ }
49
+ );
41
50
  }
42
- async function downloadAsarBufferDefault(url, headers, total, onDownloading) {
43
- let current = 0;
44
- return await downlaodFn(url, headers, (resp, resolve) => {
45
- let data = [];
46
- resp.on("data", (chunk) => {
47
- current += chunk.length;
48
- onDownloading?.({ percent: `${+(current / total).toFixed(2) * 100}%`, total, current });
49
- data.push(chunk);
50
- });
51
- resp.on("end", () => resolve(Buffer.concat(data)));
52
- });
51
+ async function defaultDownloadAsar(url, headers, signal, onDownloading) {
52
+ let transferred = 0;
53
+ let time = Date.now();
54
+ return await downloadFn(
55
+ url,
56
+ headers,
57
+ signal,
58
+ (resp, resolve) => {
59
+ const total = +getHeader(resp.headers, "content-length") || -1;
60
+ let data = [];
61
+ resp.on("data", (chunk) => {
62
+ const delta = chunk.length;
63
+ transferred += delta;
64
+ const current = Date.now();
65
+ onDownloading?.({
66
+ percent: total ? +(transferred / total).toFixed(2) * 100 : -1,
67
+ total,
68
+ transferred,
69
+ delta,
70
+ bps: delta / ((current - time) * 1e3)
71
+ });
72
+ time = current;
73
+ data.push(chunk);
74
+ });
75
+ resp.on("end", () => resolve(Buffer.concat(data)));
76
+ }
77
+ );
53
78
  }
54
79
 
80
+ // src/provider/base.ts
81
+ var BaseProvider = class {
82
+ name = "BaseProvider";
83
+ /**
84
+ * @inheritdoc
85
+ */
86
+ isLowerVersion = defaultIsLowerVersion;
87
+ /**
88
+ * @inheritdoc
89
+ */
90
+ verifySignaure = defaultVerifySignature;
91
+ /**
92
+ * @inheritdoc
93
+ */
94
+ unzipFile = defaultUnzipFile;
95
+ };
96
+
55
97
  // 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";
98
+ var GitHubProvider = class extends BaseProvider {
58
99
  name = "GithubProvider";
59
- urlHandler;
60
- url;
61
- extraHeaders;
100
+ options;
101
+ /**
102
+ * Update Provider for Github repo
103
+ * - download update json from `https://raw.githubusercontent.com/{user}/{repo}/HEAD/{versionPath}`
104
+ * - download update asar from `https://github.com/{user}/{repo}/releases/download/v{version}/{name}-{version}.asar.gz`
105
+ *
106
+ * you can setup `urlHandler` in {@link GitHubProviderOptions} to modify url before request
107
+ * @param options provider options
108
+ */
62
109
  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 += "/";
110
+ super();
111
+ this.options = options;
112
+ if (!options.branch) {
113
+ this.options.branch = "HEAD";
71
114
  }
72
115
  }
73
- parseURL(isDownloadAsar, path) {
74
- const url = this.url.href + path;
75
- return this.urlHandler ? this.urlHandler(url, isDownloadAsar) : url;
116
+ get urlHandler() {
117
+ return this.options.urlHandler;
118
+ }
119
+ set urlHandler(handler) {
120
+ this.options.urlHandler = handler;
76
121
  }
77
- isLowerVersion = isLowerVersionDefault;
78
- verifySignaure = verifySignatureDefault;
79
- async downloadJSON(versionPath) {
80
- return await downloadUpdateJSONDefault(
81
- this.parseURL(false, `HEAD/${versionPath}`),
82
- { userAgent: this.ua, accept: "application/json", ...this.extraHeaders }
122
+ async parseURL(isDownloadAsar, extraPath) {
123
+ const url = new URL(
124
+ `/${this.options.user}/${this.options.repo}/${extraPath}`,
125
+ "https://" + (isDownloadAsar ? "github.com" : "raw.githubusercontent.com")
83
126
  );
127
+ return (await this.urlHandler?.(url, isDownloadAsar) || url).toString();
84
128
  }
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,
129
+ /**
130
+ * @inheritdoc
131
+ */
132
+ async downloadJSON(versionPath, signal) {
133
+ return await defaultDownloadUpdateJSON(
134
+ await this.parseURL(false, `${this.options.branch}/${versionPath}`),
135
+ { Accept: "application/json", ...this.options.extraHeaders },
136
+ signal
137
+ );
138
+ }
139
+ /**
140
+ * @inheritdoc
141
+ */
142
+ async downloadAsar(name, info, signal, onDownloading) {
143
+ return await defaultDownloadAsar(
144
+ await this.parseURL(true, `releases/download/v${info.version}/${name}-${info.version}.asar.gz`),
145
+ { Accept: "application/octet-stream", ...this.options.extraHeaders },
146
+ signal,
90
147
  onDownloading
91
148
  );
92
149
  }
93
150
  };
94
- export {
95
- GitHubProvider,
96
- downloadAsarBufferDefault,
97
- downloadUpdateJSONDefault
98
- };
151
+
152
+ export { BaseProvider, GitHubProvider, defaultDownloadAsar, defaultDownloadUpdateJSON, getHeader };
@@ -0,0 +1,80 @@
1
+ import { Promisable } from '@subframe7536/type-utils';
2
+ import { a as UpdateJSON, U as UpdateInfo } from './version-BYVQ367i.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 -1
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
+ * @param signal abort signal
48
+ */
49
+ downloadJSON: (versionPath: string, signal: AbortSignal) => Promise<UpdateJSON>;
50
+ /**
51
+ * Download update asar
52
+ * @param name app name
53
+ * @param updateInfo existing update info
54
+ * @param signal abort signal
55
+ * @param onDownloading hook for on downloading
56
+ */
57
+ downloadAsar: (name: string, updateInfo: UpdateInfo, signal: AbortSignal, onDownloading?: (info: DownloadingInfo) => void) => Promise<Buffer>;
58
+ /**
59
+ * Check the old version is less than new version
60
+ * @param oldVer old version string
61
+ * @param newVer new version string
62
+ */
63
+ isLowerVersion: (oldVer: string, newVer: string) => boolean;
64
+ /**
65
+ * Function to decompress file using brotli
66
+ * @param buffer compressed file buffer
67
+ */
68
+ unzipFile: (buffer: Buffer) => Promise<Buffer>;
69
+ /**
70
+ * Verify asar signature,
71
+ * if signature is valid, returns the version, otherwise returns `undefined`
72
+ * @param buffer file buffer
73
+ * @param version target version
74
+ * @param signature signature
75
+ * @param cert certificate
76
+ */
77
+ verifySignaure: (buffer: Buffer, version: string, signature: string, cert: string) => Promisable<boolean>;
78
+ }
79
+
80
+ export type { DownloadingInfo as D, IProvider as I, OnDownloading as O, URLHandler as U };
@@ -0,0 +1,80 @@
1
+ import { Promisable } from '@subframe7536/type-utils';
2
+ import { a as UpdateJSON, U as UpdateInfo } from './version-BYVQ367i.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 -1
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
+ * @param signal abort signal
48
+ */
49
+ downloadJSON: (versionPath: string, signal: AbortSignal) => Promise<UpdateJSON>;
50
+ /**
51
+ * Download update asar
52
+ * @param name app name
53
+ * @param updateInfo existing update info
54
+ * @param signal abort signal
55
+ * @param onDownloading hook for on downloading
56
+ */
57
+ downloadAsar: (name: string, updateInfo: UpdateInfo, signal: AbortSignal, onDownloading?: (info: DownloadingInfo) => void) => Promise<Buffer>;
58
+ /**
59
+ * Check the old version is less than new version
60
+ * @param oldVer old version string
61
+ * @param newVer new version string
62
+ */
63
+ isLowerVersion: (oldVer: string, newVer: string) => boolean;
64
+ /**
65
+ * Function to decompress file using brotli
66
+ * @param buffer compressed file buffer
67
+ */
68
+ unzipFile: (buffer: Buffer) => Promise<Buffer>;
69
+ /**
70
+ * Verify asar signature,
71
+ * if signature is valid, returns the version, otherwise returns `undefined`
72
+ * @param buffer file buffer
73
+ * @param version target version
74
+ * @param signature signature
75
+ * @param cert certificate
76
+ */
77
+ verifySignaure: (buffer: Buffer, version: string, signature: string, cert: string) => Promisable<boolean>;
78
+ }
79
+
80
+ export type { DownloadingInfo as D, IProvider as I, OnDownloading as O, URLHandler as U };