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

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/index.js CHANGED
@@ -1,17 +1,16 @@
1
1
  import {
2
2
  __require,
3
+ getAppVersion,
4
+ getEntryVersion,
3
5
  getPathFromAppNameAsar,
4
- getVersions,
5
- is,
6
+ isDev,
6
7
  isUpdateJSON,
7
- parseVersion,
8
8
  restartApp,
9
- unzipFile,
10
- waitAppReady
11
- } from "./chunk-SBPTSLG7.js";
9
+ unzipFile
10
+ } from "./chunk-RSLOPAIZ.js";
12
11
 
13
- // src/index.ts
14
- import { resolve } from "node:path";
12
+ // src/entry.ts
13
+ import { join } from "node:path";
15
14
  import { existsSync as existsSync2, renameSync } from "node:fs";
16
15
  import { app as app2 } from "electron";
17
16
 
@@ -19,36 +18,9 @@ import { app as app2 } from "electron";
19
18
  import { existsSync, rmSync, writeFileSync } from "node:fs";
20
19
  import { app } from "electron";
21
20
 
22
- // src/crypto/dec.ts
23
- import { createDecipheriv, createVerify } from "node:crypto";
24
-
25
- // src/crypto/utils.ts
26
- import { createHash } from "node:crypto";
27
- function hashString(data, length) {
28
- const hash = createHash("SHA256").update(data).digest("binary");
29
- return Buffer.from(hash).subarray(0, length);
30
- }
31
-
32
- // src/crypto/dec.ts
33
- function decrypt(encryptedText, key, iv) {
34
- const decipher = createDecipheriv("aes-256-cbc", key, iv);
35
- let decrypted = decipher.update(encryptedText, "base64url", "utf8");
36
- decrypted += decipher.final("utf8");
37
- return decrypted;
38
- }
39
- var verify = (buffer, signature, cert) => {
40
- try {
41
- const [sig, version] = decrypt(signature, hashString(cert, 32), hashString(buffer, 16)).split("%");
42
- const result = createVerify("RSA-SHA256").update(buffer).verify(cert, sig, "base64");
43
- return result ? version : false;
44
- } catch (error) {
45
- return false;
46
- }
47
- };
48
-
49
21
  // src/updater/types.ts
50
22
  var ErrorInfo = {
51
- downlaod: "Download failed",
23
+ download: "Download failed",
52
24
  validate: "Validate failed",
53
25
  param: "Missing params",
54
26
  version: "Unsatisfied version"
@@ -59,83 +31,15 @@ var UpdaterError = class extends Error {
59
31
  }
60
32
  };
61
33
 
62
- // src/updater/defaultFunctions/download.ts
63
- import { net } from "electron";
64
- async function downlaodFn(url, headers, onResponse) {
65
- await waitAppReady();
66
- return new Promise((resolve2, reject) => {
67
- const request = net.request({ url, method: "GET", redirect: "follow" });
68
- Object.keys(headers).forEach((key) => request.setHeader(key, headers[key]));
69
- request.on("response", (res) => onResponse(res, resolve2, reject));
70
- request.on("error", reject);
71
- request.end();
72
- });
73
- }
74
- var downloadJSONDefault = async (url, headers) => {
75
- return await downlaodFn(url, headers, (resp, resolve2, reject) => {
76
- let data = "";
77
- resp.on("data", (chunk) => data += chunk);
78
- resp.on("end", () => {
79
- try {
80
- const json = JSON.parse(data);
81
- if (isUpdateJSON(json)) {
82
- resolve2(json);
83
- } else {
84
- throw Error;
85
- }
86
- } catch (ignore) {
87
- reject(new Error("invalid update json"));
88
- }
89
- });
90
- resp.on("aborted", () => reject(new Error("aborted")));
91
- resp.on("error", () => reject(new Error("download error")));
92
- });
93
- };
94
- var downloadBufferDefault = async (url, headers, total, onDownloading) => {
95
- let current = 0;
96
- return await downlaodFn(url, headers, (resp, resolve2, reject) => {
97
- let data = [];
98
- resp.on("data", (chunk) => {
99
- current += chunk.length;
100
- onDownloading?.({ percent: `${+(current / total).toFixed(2) * 100}%`, total, current });
101
- data.push(chunk);
102
- });
103
- resp.on("end", () => resolve2(Buffer.concat(data)));
104
- resp.on("aborted", () => reject(new Error("aborted")));
105
- resp.on("error", () => reject(new Error("download error")));
106
- });
107
- };
108
-
109
- // src/updater/defaultFunctions/compareVersion.ts
110
- var isLowerVersionDefault = (version1, version2) => {
111
- const oldV = parseVersion(version1);
112
- const newV = parseVersion(version2);
113
- function compareStrings(str1, str2) {
114
- if (str1 === "") {
115
- return str2 !== "";
116
- } else if (str2 === "") {
117
- return true;
118
- }
119
- return str1 < str2;
120
- }
121
- for (let key of Object.keys(oldV)) {
122
- if (key === "stage" && compareStrings(oldV[key], newV[key])) {
123
- return true;
124
- } else if (oldV[key] !== newV[key]) {
125
- return oldV[key] < newV[key];
126
- }
127
- }
128
- return false;
129
- };
130
-
131
34
  // src/updater/core.ts
132
35
  var Updater = class {
133
- CERT = __SIGNATURE_CERT__;
36
+ CERT = __EIU_SIGNATURE_CERT__;
134
37
  info;
135
- option;
38
+ options;
136
39
  asarPath;
137
40
  gzipPath;
138
41
  tmpFilePath;
42
+ provider;
139
43
  /**
140
44
  * updater logger
141
45
  */
@@ -149,31 +53,49 @@ var Updater = class {
149
53
  * }
150
54
  */
151
55
  onDownloading;
56
+ /**
57
+ * URL handler hook
58
+ *
59
+ * for Github, there are some {@link https://github.com/XIU2/UserScript/blob/master/GithubEnhanced-High-Speed-Download.user.js#L34 public CDN links}
60
+ * @param url source url
61
+ * @param isDownloadAsar whether is download asar
62
+ */
63
+ handleURL;
152
64
  /**
153
65
  * whether receive beta version
154
66
  */
155
67
  get receiveBeta() {
156
- return !!this.option.receiveBeta;
68
+ return !!this.options.receiveBeta;
157
69
  }
158
70
  set receiveBeta(receiveBeta) {
159
- this.option.receiveBeta = receiveBeta;
71
+ this.options.receiveBeta = receiveBeta;
160
72
  }
161
73
  /**
162
74
  * initialize incremental updater
75
+ * @param provider update provider
163
76
  * @param option UpdaterOption
164
77
  */
165
- constructor(option = {}) {
166
- this.option = option;
78
+ constructor(provider, option = {}) {
79
+ this.provider = provider;
80
+ this.options = option;
167
81
  if (option.SIGNATURE_CERT) {
168
82
  this.CERT = option.SIGNATURE_CERT;
169
83
  }
84
+ if (option.logger) {
85
+ this.logger = option.logger;
86
+ }
170
87
  this.asarPath = getPathFromAppNameAsar();
171
88
  this.gzipPath = `${this.asarPath}.gz`;
172
89
  this.tmpFilePath = `${this.asarPath}.tmp`;
173
90
  }
174
91
  async needUpdate(version, minVersion) {
175
- const isLowerVersion = this.option.overrideFunctions?.isLowerVersion ?? isLowerVersionDefault;
176
- const { appVersion, entryVersion } = getVersions();
92
+ if (isDev) {
93
+ this.logger?.warn(`in dev mode, skip check update`);
94
+ return false;
95
+ }
96
+ const isLowerVersion = this.provider.isLowerVersion;
97
+ const entryVersion = getEntryVersion();
98
+ const appVersion = getAppVersion();
177
99
  if (await isLowerVersion(entryVersion, minVersion)) {
178
100
  throw new UpdaterError(ErrorInfo.version, `entry version (${entryVersion}) < minimumVersion (${minVersion})`);
179
101
  }
@@ -196,42 +118,14 @@ var Updater = class {
196
118
  throw new UpdaterError(ErrorInfo.param, `invalid type at format '${format}': ${JSON.stringify(data)}`);
197
119
  }
198
120
  }
199
- const ua = this.option.downloadConfig?.userAgent || "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36";
200
- const headers = {
201
- Accept: `application/${format === "json" ? "json" : "octet-stream"}`,
202
- UserAgent: ua,
203
- ...this.option.downloadConfig?.extraHeader
204
- };
205
- this.logger?.debug(`download headers: ${JSON.stringify(headers)}`);
206
- const config = format === "json" ? {
207
- name: "updateJsonURL",
208
- url: this.option.updateJsonURL,
209
- repoFallback: `${this.option.repository?.replace("github.com", "raw.githubusercontent.com")}/master/version.json`,
210
- fn: this.option.overrideFunctions?.downloadJSON ?? downloadJSONDefault
211
- } : {
212
- name: "releaseAsarURL",
213
- url: this.option.releaseAsarURL,
214
- repoFallback: `${this.option.repository}/releases/download/v${this.info?.version}/${app.name}-${this.info?.version}.asar.gz`,
215
- fn: this.option.overrideFunctions?.downloadBuffer ?? downloadBufferDefault
216
- };
217
- data ??= config.url;
218
- if (!data) {
219
- this.logger?.debug(`no ${config.name}, fallback to use repository`);
220
- if (!this.option.repository) {
221
- throw new UpdaterError(ErrorInfo.param, `${config.name} or repository is not set`);
222
- }
223
- if (format === "buffer" && !this.info?.version) {
224
- throw new UpdaterError(ErrorInfo.param, "version is not set");
225
- }
226
- data = config.repoFallback;
227
- }
228
- this.logger?.debug(`download ${format} from ${data}`);
121
+ this.logger?.debug(`download from ${this.provider.name}`);
229
122
  try {
230
- const ret = format === "json" ? await config.fn(data, headers) : await config.fn(data, headers, this.info.size, this.onDownloading);
231
- this.logger?.debug(`download ${format} success${format === "buffer" ? `, file size: ${ret.length}` : ""}`);
232
- return ret;
123
+ const result = format === "json" ? await this.provider.downloadJSON(data ?? __EIU_VERSION_PATH__) : await this.provider.downloadBuffer(app.name, this.info, this.onDownloading);
124
+ this.logger?.debug(`download ${format} success${format === "buffer" ? `, file size: ${result.length}` : ""}`);
125
+ return result;
233
126
  } catch (e) {
234
- throw new UpdaterError(ErrorInfo.downlaod, e.toString());
127
+ this.logger?.warn(`download ${format} failed: ${e}`);
128
+ throw new UpdaterError(ErrorInfo.download, `download ${format} failed: ${e}`);
235
129
  }
236
130
  }
237
131
  async checkUpdate(data) {
@@ -243,35 +137,32 @@ var Updater = class {
243
137
  minimumVersion = beta.minimumVersion;
244
138
  size = beta.size;
245
139
  }
246
- this.logger?.debug(`checked version: ${version}, size: ${size}, signature: ${signature}`);
140
+ this.logger?.debug(`checked update, version: ${version}, size: ${size}, signature: ${signature}`);
247
141
  if (!await this.needUpdate(version, minimumVersion)) {
248
142
  this.logger?.info(`update unavailable: ${version} is the latest version`);
249
- return void 0;
143
+ return { success: false, data: version };
250
144
  } else {
251
145
  this.logger?.info(`update available: ${version}`);
252
- this.info = {
253
- signature,
254
- minimumVersion,
255
- version,
256
- size
257
- };
258
- return this.info;
146
+ this.info = { signature, minimumVersion, version, size };
147
+ return { success: true, data: this.info };
259
148
  }
260
149
  } catch (error) {
261
150
  this.logger?.error("check update failed", error);
262
- return error;
151
+ return {
152
+ success: false,
153
+ data: error instanceof UpdaterError ? error : new UpdaterError(ErrorInfo.download, error.toString())
154
+ };
263
155
  }
264
156
  }
265
157
  async download(data, sig) {
266
158
  try {
267
- const _sig = sig ?? this.info?.signature;
268
- if (!_sig) {
269
- throw new UpdaterError(ErrorInfo.param, "signature is empty");
159
+ if (!this.info) {
160
+ throw new UpdaterError(ErrorInfo.param, "no update info");
270
161
  }
162
+ const _sig = sig ?? this.info.signature;
271
163
  const buffer = await this.parseData("buffer", data);
272
164
  this.logger?.debug("verify start");
273
- const _verify = this.option.overrideFunctions?.verifySignaure ?? verify;
274
- const _ver = await _verify(buffer, _sig, this.CERT);
165
+ const _ver = await this.provider.verifySignaure(buffer, _sig, this.CERT);
275
166
  if (!_ver) {
276
167
  throw new UpdaterError(ErrorInfo.validate, "invalid signature or certificate");
277
168
  }
@@ -282,10 +173,13 @@ var Updater = class {
282
173
  await unzipFile(this.gzipPath, this.tmpFilePath);
283
174
  this.logger?.info(`download success, version: ${_ver}`);
284
175
  this.info = void 0;
285
- return true;
176
+ return { success: true };
286
177
  } catch (error) {
287
178
  this.logger?.error("download asar failed", error);
288
- return error;
179
+ return {
180
+ success: false,
181
+ data: error instanceof UpdaterError ? error : new UpdaterError(ErrorInfo.download, error.toString())
182
+ };
289
183
  }
290
184
  }
291
185
  /**
@@ -297,66 +191,53 @@ var Updater = class {
297
191
  }
298
192
  };
299
193
 
300
- // src/updater/index.ts
301
- function createUpdater(option) {
302
- return new Updater(option);
303
- }
304
-
305
- // src/index.ts
194
+ // src/entry.ts
306
195
  function startupWithUpdater(fn) {
307
196
  return fn;
308
197
  }
309
198
  var defaultOnInstall = (install, _, __, logger) => {
310
199
  install();
311
- logger?.info(`update success!`);
200
+ logger.info(`update success!`);
312
201
  };
313
- async function initApp(appOptions = {}) {
202
+ async function initApp(appOptions) {
314
203
  const {
204
+ provider,
315
205
  updater,
316
- electronDevDistPath = "../dist-electron",
317
- mainPath = "main/index.js",
318
- hooks
319
- } = appOptions || {};
320
- const {
321
206
  onInstall = defaultOnInstall,
322
207
  beforeStart,
323
208
  onStartError
324
- } = hooks || {};
325
- function handleError(err, logger2) {
326
- console.error(err);
327
- onStartError?.(err, logger2);
328
- app2.quit();
329
- }
209
+ } = appOptions;
330
210
  let updaterInstance;
331
211
  if (typeof updater === "object" || !updater) {
332
- updaterInstance = createUpdater(updater);
212
+ updaterInstance = new Updater(provider, updater);
333
213
  } else {
334
214
  updaterInstance = await updater();
335
215
  }
336
- const logger = updaterInstance.logger;
216
+ const logger = updaterInstance.logger || console;
337
217
  try {
338
218
  const appNameAsarPath = getPathFromAppNameAsar();
339
219
  const tempAsarPath = `${appNameAsarPath}.tmp`;
340
220
  if (existsSync2(tempAsarPath)) {
341
- logger?.info(`installing new asar: ${tempAsarPath}`);
221
+ logger.info(`installing new asar: ${tempAsarPath}`);
342
222
  await onInstall(() => renameSync(tempAsarPath, appNameAsarPath), tempAsarPath, appNameAsarPath, logger);
343
223
  }
344
- const mainDir = is.dev ? electronDevDistPath : appNameAsarPath;
345
- const entry = resolve(__dirname, mainDir, mainPath);
346
- await beforeStart?.(entry, logger);
347
- __require(entry)(updaterInstance);
224
+ const mainFilePath = join(
225
+ isDev ? join(app2.getAppPath(), __EIU_MAIN_DEV_DIR__) : appNameAsarPath,
226
+ "main",
227
+ __EIU_MAIN_FILE__
228
+ );
229
+ await beforeStart?.(mainFilePath, logger);
230
+ __require(mainFilePath)(updaterInstance);
348
231
  } catch (error) {
349
- handleError(error, logger);
232
+ logger.error("startup error", error);
233
+ onStartError?.(error, logger);
234
+ app2.quit();
350
235
  }
351
236
  }
352
237
  export {
353
238
  ErrorInfo,
354
239
  Updater,
355
240
  UpdaterError,
356
- createUpdater,
357
- downloadBufferDefault,
358
- downloadJSONDefault,
359
241
  initApp,
360
- isLowerVersionDefault,
361
242
  startupWithUpdater
362
243
  };
@@ -0,0 +1,227 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/provider/index.ts
21
+ var provider_exports = {};
22
+ __export(provider_exports, {
23
+ GitHubProvider: () => GitHubProvider,
24
+ downloadAsarBufferDefault: () => downloadAsarBufferDefault,
25
+ downloadUpdateJSONDefault: () => downloadUpdateJSONDefault
26
+ });
27
+ module.exports = __toCommonJS(provider_exports);
28
+
29
+ // src/utils/electron.ts
30
+ var import_node_fs = require("fs");
31
+ var import_node_path = require("path");
32
+ var import_electron = require("electron");
33
+ var isDev = __EIU_IS_DEV__;
34
+ var isWin = process.platform === "win32";
35
+ var isMac = process.platform === "darwin";
36
+ var isLinux = process.platform === "linux";
37
+ function waitAppReady(timeout = 1e3) {
38
+ return import_electron.app.isReady() ? Promise.resolve() : new Promise((resolve, reject) => {
39
+ const _ = setTimeout(() => {
40
+ reject(new Error("app is not ready"));
41
+ }, timeout);
42
+ import_electron.app.whenReady().then(() => {
43
+ clearTimeout(_);
44
+ resolve();
45
+ });
46
+ });
47
+ }
48
+
49
+ // src/utils/zip.ts
50
+ var import_node_fs2 = require("fs");
51
+ var import_node_zlib = require("zlib");
52
+
53
+ // src/utils/unzip.ts
54
+ var import_node_fs3 = require("fs");
55
+ var import_node_zlib2 = require("zlib");
56
+
57
+ // src/utils/version.ts
58
+ function parseVersion(version) {
59
+ const match = /^(\d+)\.(\d+)\.(\d+)(?:-([a-z0-9.-]+))?/i.exec(version);
60
+ if (!match) {
61
+ throw new TypeError(`invalid version: ${version}`);
62
+ }
63
+ const [major, minor, patch] = match.slice(1, 4).map(Number);
64
+ const ret = {
65
+ major,
66
+ minor,
67
+ patch,
68
+ stage: "",
69
+ stageVersion: -1
70
+ };
71
+ if (match[4]) {
72
+ let [stage, _v] = match[4].split(".");
73
+ ret.stage = stage;
74
+ ret.stageVersion = Number(_v) || -1;
75
+ }
76
+ if (Number.isNaN(major) || Number.isNaN(minor) || Number.isNaN(patch) || Number.isNaN(ret.stageVersion)) {
77
+ throw new TypeError(`invalid version: ${version}`);
78
+ }
79
+ return ret;
80
+ }
81
+ function isLowerVersionDefault(oldVer, newVer) {
82
+ const oldV = parseVersion(oldVer);
83
+ const newV = parseVersion(newVer);
84
+ function compareStrings(str1, str2) {
85
+ if (str1 === "") {
86
+ return str2 !== "";
87
+ } else if (str2 === "") {
88
+ return true;
89
+ }
90
+ return str1 < str2;
91
+ }
92
+ for (let key of Object.keys(oldV)) {
93
+ if (key === "stage" && compareStrings(oldV[key], newV[key])) {
94
+ return true;
95
+ } else if (oldV[key] !== newV[key]) {
96
+ return oldV[key] < newV[key];
97
+ }
98
+ }
99
+ return false;
100
+ }
101
+ function isUpdateJSON(json) {
102
+ const is = (j) => !!(j && j.minimumVersion && j.signature && j.size && j.version);
103
+ return is(json) && is(json?.beta);
104
+ }
105
+
106
+ // src/utils/crypto/decrypt.ts
107
+ var import_node_crypto2 = require("crypto");
108
+
109
+ // src/utils/crypto/utils.ts
110
+ var import_node_crypto = require("crypto");
111
+ function hashString(data, length) {
112
+ const hash = (0, import_node_crypto.createHash)("SHA256").update(data).digest("binary");
113
+ return Buffer.from(hash).subarray(0, length);
114
+ }
115
+
116
+ // src/utils/crypto/decrypt.ts
117
+ function decrypt(encryptedText, key, iv) {
118
+ const decipher = (0, import_node_crypto2.createDecipheriv)("aes-256-cbc", key, iv);
119
+ let decrypted = decipher.update(encryptedText, "base64url", "utf8");
120
+ decrypted += decipher.final("utf8");
121
+ return decrypted;
122
+ }
123
+ function verifySignatureDefault(buffer, signature, cert) {
124
+ try {
125
+ const [sig, version] = decrypt(signature, hashString(cert, 32), hashString(buffer, 16)).split("%");
126
+ const result = (0, import_node_crypto2.createVerify)("RSA-SHA256").update(buffer).verify(cert, sig, "base64");
127
+ return result ? version : void 0;
128
+ } catch (error) {
129
+ return void 0;
130
+ }
131
+ }
132
+
133
+ // src/utils/crypto/encrypt.ts
134
+ var import_node_crypto3 = require("crypto");
135
+
136
+ // src/provider/download.ts
137
+ var import_electron2 = require("electron");
138
+ async function downlaodFn(url, headers, onResponse) {
139
+ await waitAppReady();
140
+ return new Promise((resolve, reject) => {
141
+ const request = import_electron2.net.request({ url, method: "GET", redirect: "follow" });
142
+ Object.keys(headers).forEach((key) => request.setHeader(key, headers[key]));
143
+ request.on("response", (resp) => {
144
+ resp.on("aborted", () => reject(new Error("aborted")));
145
+ resp.on("error", () => reject(new Error("download error")));
146
+ onResponse(resp, resolve, reject);
147
+ });
148
+ request.on("error", reject);
149
+ request.end();
150
+ });
151
+ }
152
+ async function downloadUpdateJSONDefault(url, headers) {
153
+ return await downlaodFn(url, headers, (resp, resolve, reject) => {
154
+ let data = "";
155
+ resp.on("data", (chunk) => data += chunk);
156
+ resp.on("end", () => {
157
+ try {
158
+ const json = JSON.parse(data);
159
+ if (isUpdateJSON(json)) {
160
+ resolve(json);
161
+ } else {
162
+ throw Error;
163
+ }
164
+ } catch (ignore) {
165
+ reject(new Error("invalid update json"));
166
+ }
167
+ });
168
+ });
169
+ }
170
+ async function downloadAsarBufferDefault(url, headers, total, onDownloading) {
171
+ let current = 0;
172
+ return await downlaodFn(url, headers, (resp, resolve) => {
173
+ let data = [];
174
+ resp.on("data", (chunk) => {
175
+ current += chunk.length;
176
+ onDownloading?.({ percent: `${+(current / total).toFixed(2) * 100}%`, total, current });
177
+ data.push(chunk);
178
+ });
179
+ resp.on("end", () => resolve(Buffer.concat(data)));
180
+ });
181
+ }
182
+
183
+ // src/provider/github.ts
184
+ var GitHubProvider = class {
185
+ ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36";
186
+ name = "GithubProvider";
187
+ urlHandler;
188
+ url;
189
+ extraHeaders;
190
+ constructor(options) {
191
+ this.url = new URL(options.url);
192
+ this.extraHeaders = options.extraHeaders;
193
+ this.urlHandler = options.urlHandler;
194
+ if (this.url.host !== "github.com") {
195
+ throw new Error(`${this.name}: invalid github url: ${options.url}`);
196
+ }
197
+ if (!this.url.pathname.endsWith("/")) {
198
+ this.url.pathname += "/";
199
+ }
200
+ }
201
+ parseURL(isDownloadAsar, path) {
202
+ const url = this.url.href + path;
203
+ return this.urlHandler ? this.urlHandler(url, isDownloadAsar) : url;
204
+ }
205
+ isLowerVersion = isLowerVersionDefault;
206
+ verifySignaure = verifySignatureDefault;
207
+ async downloadJSON(versionPath) {
208
+ return await downloadUpdateJSONDefault(
209
+ this.parseURL(false, `HEAD/${versionPath}`),
210
+ { userAgent: this.ua, accept: "application/json", ...this.extraHeaders }
211
+ );
212
+ }
213
+ async downloadBuffer(name, { version, size }, onDownloading) {
214
+ return await downloadAsarBufferDefault(
215
+ this.parseURL(true, `releases/download/v${version}/${name}-${version}.asar.gz`),
216
+ { userAgent: this.ua, accept: "application/octet-stream", ...this.extraHeaders },
217
+ size,
218
+ onDownloading
219
+ );
220
+ }
221
+ };
222
+ // Annotate the CommonJS export names for ESM import in node:
223
+ 0 && (module.exports = {
224
+ GitHubProvider,
225
+ downloadAsarBufferDefault,
226
+ downloadUpdateJSONDefault
227
+ });
@@ -0,0 +1,37 @@
1
+ import { i as isLowerVersionDefault, U as UpdateJSON, a as UpdateInfo } from './version-CffZWDhZ.cjs';
2
+ import { v as verifySignatureDefault } from './decrypt-BNBcodiO.cjs';
3
+ import { U as URLHandler, I as IProvider, D as DownloadingInfo, O as OnDownloading } from './types-DxPmQmaq.cjs';
4
+ import '@subframe7536/type-utils';
5
+
6
+ interface GitHubProviderOptions {
7
+ /**
8
+ * github repo root url
9
+ * @example 'https://github.com/electron/electron'
10
+ */
11
+ url: string;
12
+ extraHeaders?: Record<string, string>;
13
+ /**
14
+ * custom url handler
15
+ *
16
+ * for Github, there are some {@link https://github.com/XIU2/UserScript/blob/master/GithubEnhanced-High-Speed-Download.user.js#L34 public CDN links}
17
+ */
18
+ urlHandler?: URLHandler;
19
+ }
20
+ declare class GitHubProvider implements IProvider {
21
+ private ua;
22
+ name: string;
23
+ urlHandler?: URLHandler;
24
+ private url;
25
+ private extraHeaders?;
26
+ constructor(options: GitHubProviderOptions);
27
+ private parseURL;
28
+ isLowerVersion: typeof isLowerVersionDefault;
29
+ verifySignaure: typeof verifySignatureDefault;
30
+ downloadJSON(versionPath: string): Promise<UpdateJSON>;
31
+ downloadBuffer(name: string, { version, size }: UpdateInfo, onDownloading?: (info: DownloadingInfo) => void): Promise<Buffer>;
32
+ }
33
+
34
+ declare function downloadUpdateJSONDefault(url: string, headers: Record<string, any>): Promise<UpdateJSON>;
35
+ declare function downloadAsarBufferDefault(url: string, headers: Record<string, any>, total: number, onDownloading?: OnDownloading): Promise<Buffer>;
36
+
37
+ export { DownloadingInfo, GitHubProvider, type GitHubProviderOptions, IProvider, OnDownloading, URLHandler, downloadAsarBufferDefault, downloadUpdateJSONDefault };