electron-incremental-update 1.2.0 → 1.3.0

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
@@ -8,7 +8,7 @@ import {
8
8
  restartApp,
9
9
  unzipFile,
10
10
  waitAppReady
11
- } from "./chunk-RQCTJY4L.js";
11
+ } from "./chunk-SBPTSLG7.js";
12
12
 
13
13
  // src/index.ts
14
14
  import { resolve } from "node:path";
@@ -47,100 +47,67 @@ var verify = (buffer, signature, cert) => {
47
47
  };
48
48
 
49
49
  // src/updater/types.ts
50
- var MinimumVersionError = class extends Error {
51
- currentVersion;
52
- minVersion;
53
- constructor(version, minimumVersion) {
54
- super(`current entry version is ${version}, less than the minimumVersion ${minimumVersion}`);
55
- this.currentVersion = version;
56
- this.minVersion = minimumVersion;
57
- }
58
- };
59
- var VerifyFailedError = class extends Error {
60
- signature;
61
- cert;
62
- constructor(signature, cert) {
63
- super("verify failed, invalid signature or certificate");
64
- this.signature = signature;
65
- this.cert = cert;
66
- }
50
+ var ErrorInfo = {
51
+ downlaod: "Download failed",
52
+ validate: "Validate failed",
53
+ param: "Missing params",
54
+ version: "Unsatisfied version"
67
55
  };
68
- var DownloadError = class extends Error {
69
- constructor(msg) {
70
- super(`download update error, ${msg}`);
56
+ var UpdaterError = class extends Error {
57
+ constructor(msg, info) {
58
+ super(msg + ": " + info);
71
59
  }
72
60
  };
73
61
 
74
62
  // src/updater/defaultFunctions/download.ts
75
63
  import { net } from "electron";
76
- var downloadJSONDefault = async (url, headers) => {
64
+ async function downlaodFn(url, headers, onResponse) {
77
65
  await waitAppReady();
78
66
  return new Promise((resolve2, reject) => {
79
- const request = net.request({
80
- url,
81
- method: "GET",
82
- redirect: "follow"
83
- });
84
- Object.keys(headers).forEach((key) => {
85
- request.setHeader(key, headers[key]);
86
- });
87
- request.on("response", (res) => {
88
- let data = "";
89
- res.on("data", (chunk) => data += chunk);
90
- res.on("end", () => {
91
- try {
92
- const json = JSON.parse(data);
93
- if (isUpdateJSON(json)) {
94
- resolve2(json);
95
- } else {
96
- throw Error;
97
- }
98
- } catch (e) {
99
- reject(new Error("invalid json"));
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;
100
85
  }
101
- });
102
- });
103
- request.on("error", (e) => {
104
- reject(e);
86
+ } catch (ignore) {
87
+ reject(new Error("invalid update json"));
88
+ }
105
89
  });
106
- request.end();
90
+ resp.on("aborted", () => reject(new Error("aborted")));
91
+ resp.on("error", () => reject(new Error("download error")));
107
92
  });
108
93
  };
109
94
  var downloadBufferDefault = async (url, headers, total, onDownloading) => {
110
- await waitAppReady();
111
95
  let current = 0;
112
- return new Promise((resolve2, reject) => {
113
- const request = net.request({
114
- url,
115
- method: "GET",
116
- redirect: "follow"
117
- });
118
- Object.keys(headers).forEach((key) => {
119
- request.setHeader(key, headers[key]);
120
- });
121
- request.on("response", (res) => {
122
- let data = [];
123
- res.on("data", (chunk) => {
124
- current += chunk.length;
125
- onDownloading?.({
126
- percent: `${+(current / total).toFixed(2) * 100}%`,
127
- total,
128
- current
129
- });
130
- data.push(chunk);
131
- });
132
- res.on("end", () => {
133
- resolve2(Buffer.concat(data));
134
- });
135
- }).on("error", (e) => {
136
- reject(e);
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);
137
102
  });
138
- request.end();
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")));
139
106
  });
140
107
  };
141
108
 
142
109
  // src/updater/defaultFunctions/compareVersion.ts
143
- var compareVersionDefault = (version1, version2) => {
110
+ var isLowerVersionDefault = (version1, version2) => {
144
111
  const oldV = parseVersion(version1);
145
112
  const newV = parseVersion(version2);
146
113
  function compareStrings(str1, str2) {
@@ -205,13 +172,13 @@ var Updater = class {
205
172
  this.tmpFilePath = `${this.asarPath}.tmp`;
206
173
  }
207
174
  async needUpdate(version, minVersion) {
208
- const compare = this.option.overrideFunctions?.compareVersion ?? compareVersionDefault;
175
+ const isLowerVersion = this.option.overrideFunctions?.isLowerVersion ?? isLowerVersionDefault;
209
176
  const { appVersion, entryVersion } = getVersions();
210
- if (await compare(entryVersion, minVersion)) {
211
- throw new MinimumVersionError(entryVersion, minVersion);
177
+ if (await isLowerVersion(entryVersion, minVersion)) {
178
+ throw new UpdaterError(ErrorInfo.version, `entry version (${entryVersion}) < minimumVersion (${minVersion})`);
212
179
  }
213
180
  this.logger?.info(`check update: current version is ${appVersion}, new version is ${version}`);
214
- return await compare(appVersion, version);
181
+ return await isLowerVersion(appVersion, version);
215
182
  }
216
183
  async parseData(format, data) {
217
184
  if (existsSync(this.tmpFilePath)) {
@@ -222,14 +189,12 @@ var Updater = class {
222
189
  this.logger?.warn(`remove .gz file: ${this.gzipPath}`);
223
190
  rmSync(this.gzipPath);
224
191
  }
225
- if (!["string", "object", "undefined"].includes(typeof data)) {
226
- throw new TypeError(`invalid type at format '${format}': ${data}`);
227
- }
228
- if (typeof data === "object" && (format === "json" && isUpdateJSON(data) || format === "buffer" && Buffer.isBuffer(data))) {
229
- return data;
230
- }
231
192
  if (typeof data === "object") {
232
- throw new TypeError(`invalid type at format '${format}': ${data}`);
193
+ if (format === "json" && isUpdateJSON(data) || format === "buffer" && Buffer.isBuffer(data)) {
194
+ return data;
195
+ } else {
196
+ throw new UpdaterError(ErrorInfo.param, `invalid type at format '${format}': ${JSON.stringify(data)}`);
197
+ }
233
198
  }
234
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";
235
200
  const headers = {
@@ -237,11 +202,11 @@ var Updater = class {
237
202
  UserAgent: ua,
238
203
  ...this.option.downloadConfig?.extraHeader
239
204
  };
240
- this.logger?.info(`download headers: ${JSON.stringify(headers, null, 2)}`);
205
+ this.logger?.debug(`download headers: ${JSON.stringify(headers)}`);
241
206
  const config = format === "json" ? {
242
207
  name: "updateJsonURL",
243
208
  url: this.option.updateJsonURL,
244
- repoFallback: `${this.option.repository.replace("github.com", "raw.githubusercontent.com")}/master/version.json`,
209
+ repoFallback: `${this.option.repository?.replace("github.com", "raw.githubusercontent.com")}/master/version.json`,
245
210
  fn: this.option.overrideFunctions?.downloadJSON ?? downloadJSONDefault
246
211
  } : {
247
212
  name: "releaseAsarURL",
@@ -253,32 +218,22 @@ var Updater = class {
253
218
  if (!data) {
254
219
  this.logger?.debug(`no ${config.name}, fallback to use repository`);
255
220
  if (!this.option.repository) {
256
- throw new Error(`${config.name} or repository are not set`);
221
+ throw new UpdaterError(ErrorInfo.param, `${config.name} or repository is not set`);
257
222
  }
258
223
  if (format === "buffer" && !this.info?.version) {
259
- throw new Error("version are not set");
224
+ throw new UpdaterError(ErrorInfo.param, "version is not set");
260
225
  }
261
226
  data = config.repoFallback;
262
227
  }
263
- this.logger?.info(`download ${format} from ${data}`);
228
+ this.logger?.debug(`download ${format} from ${data}`);
264
229
  try {
265
230
  const ret = format === "json" ? await config.fn(data, headers) : await config.fn(data, headers, this.info.size, this.onDownloading);
266
- this.logger?.info(`download ${format} success${format === "buffer" ? `, file size: ${ret.length}` : ""}`);
231
+ this.logger?.debug(`download ${format} success${format === "buffer" ? `, file size: ${ret.length}` : ""}`);
267
232
  return ret;
268
233
  } catch (e) {
269
- throw new DownloadError(e.toString());
234
+ throw new UpdaterError(ErrorInfo.downlaod, e.toString());
270
235
  }
271
236
  }
272
- /**
273
- * check update info
274
- *
275
- * if you want to update **offline**, you can set `data` and `sig` add update info
276
- * @param data custom download URL of `updatejson` or existing update json
277
- * @returns
278
- * - Available:`{size: number, version: string}`
279
- * - Unavailable: `undefined`
280
- * - Fail: `CheckResultError`
281
- */
282
237
  async checkUpdate(data) {
283
238
  try {
284
239
  let { signature, size, version, minimumVersion, beta } = await this.parseData("json", data);
@@ -288,7 +243,7 @@ var Updater = class {
288
243
  minimumVersion = beta.minimumVersion;
289
244
  size = beta.size;
290
245
  }
291
- this.logger?.info(`checked version: ${version}, size: ${size}, signature: ${signature}`);
246
+ this.logger?.debug(`checked version: ${version}, size: ${size}, signature: ${signature}`);
292
247
  if (!await this.needUpdate(version, minimumVersion)) {
293
248
  this.logger?.info(`update unavailable: ${version} is the latest version`);
294
249
  return void 0;
@@ -307,33 +262,23 @@ var Updater = class {
307
262
  return error;
308
263
  }
309
264
  }
310
- /**
311
- * download update
312
- *
313
- * if you want to update **offline**, you can set both `data` and `sig` to verify and install
314
- * @param data custom download URL of `asar.gz` or existing `asar.gz` buffer
315
- * @param sig signature
316
- * @returns
317
- * - `true`: success
318
- * - `DownloadResultError`: fail
319
- */
320
265
  async download(data, sig) {
321
266
  try {
322
267
  const _sig = sig ?? this.info?.signature;
323
268
  if (!_sig) {
324
- throw new Error("signature are not set, please checkUpdate first or set the second parameter");
269
+ throw new UpdaterError(ErrorInfo.param, "signature is empty");
325
270
  }
326
271
  const buffer = await this.parseData("buffer", data);
327
- this.logger?.info("verify start");
272
+ this.logger?.debug("verify start");
328
273
  const _verify = this.option.overrideFunctions?.verifySignaure ?? verify;
329
274
  const _ver = await _verify(buffer, _sig, this.CERT);
330
275
  if (!_ver) {
331
- throw new VerifyFailedError(_sig, this.CERT);
276
+ throw new UpdaterError(ErrorInfo.validate, "invalid signature or certificate");
332
277
  }
333
- this.logger?.info("verify success");
334
- this.logger?.info(`write to ${this.gzipPath}`);
278
+ this.logger?.debug("verify success");
279
+ this.logger?.debug(`write to ${this.gzipPath}`);
335
280
  writeFileSync(this.gzipPath, buffer);
336
- this.logger?.info(`extract to ${this.tmpFilePath}`);
281
+ this.logger?.debug(`extract to ${this.tmpFilePath}`);
337
282
  await unzipFile(this.gzipPath, this.tmpFilePath);
338
283
  this.logger?.info(`download success, version: ${_ver}`);
339
284
  this.info = void 0;
@@ -405,11 +350,13 @@ async function initApp(appOptions = {}) {
405
350
  }
406
351
  }
407
352
  export {
408
- DownloadError,
409
- MinimumVersionError,
353
+ ErrorInfo,
410
354
  Updater,
411
- VerifyFailedError,
355
+ UpdaterError,
412
356
  createUpdater,
357
+ downloadBufferDefault,
358
+ downloadJSONDefault,
413
359
  initApp,
360
+ isLowerVersionDefault,
414
361
  startupWithUpdater
415
362
  };
package/dist/utils.cjs CHANGED
@@ -221,8 +221,7 @@ function handleUnexpectedErrors(callback) {
221
221
  process.on("unhandledRejection", callback);
222
222
  }
223
223
  function parseVersion(version) {
224
- const semver = /^(\d+)\.(\d+)\.(\d+)(?:-([a-z0-9.-]+))?/i;
225
- const match = semver.exec(version);
224
+ const match = /^(\d+)\.(\d+)\.(\d+)(?:-([a-z0-9.-]+))?/i.exec(version);
226
225
  if (!match) {
227
226
  throw new TypeError(`invalid version: ${version}`);
228
227
  }
package/dist/utils.js CHANGED
@@ -16,7 +16,7 @@ import {
16
16
  unzipFile,
17
17
  waitAppReady,
18
18
  zipFile
19
- } from "./chunk-RQCTJY4L.js";
19
+ } from "./chunk-SBPTSLG7.js";
20
20
  export {
21
21
  disableHWAccForWin7,
22
22
  getPathFromAppNameAsar,
package/dist/vite.js CHANGED
@@ -36,8 +36,7 @@ var signature = (buffer, privateKey, cert, version) => {
36
36
 
37
37
  // src/utils/pure.ts
38
38
  function parseVersion(version) {
39
- const semver = /^(\d+)\.(\d+)\.(\d+)(?:-([a-z0-9.-]+))?/i;
40
- const match = semver.exec(version);
39
+ const match = /^(\d+)\.(\d+)\.(\d+)(?:-([a-z0-9.-]+))?/i.exec(version);
41
40
  if (!match) {
42
41
  throw new TypeError(`invalid version: ${version}`);
43
42
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "electron-incremental-update",
3
3
  "type": "module",
4
- "version": "1.2.0",
4
+ "version": "1.3.0",
5
5
  "description": "electron incremental update tools, powered by vite",
6
6
  "author": "subframe7536",
7
7
  "license": "MIT",