electron-version-deployer-cli 0.4.3 → 0.4.5

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.
Files changed (3) hide show
  1. package/dist/cli.cjs +88 -16
  2. package/dist/main.js +51 -12
  3. package/package.json +1 -1
package/dist/cli.cjs CHANGED
@@ -19,11 +19,12 @@ const marked = require("marked");
19
19
  const jsdom = require("jsdom");
20
20
  const DOMPurify = require("dompurify");
21
21
  const archiver = require("archiver");
22
+ const fs = require("fs");
23
+ const path = require("path");
24
+ const os = require("os");
22
25
  const prompts = require("@inquirer/prompts");
23
26
  const electron = require("electron");
24
27
  const node_os = require("node:os");
25
- const fs = require("fs");
26
- const path = require("path");
27
28
  const download = require("download");
28
29
  const pkgPath = pkgUp.sync();
29
30
  function r(...paths) {
@@ -172,6 +173,32 @@ function archiveFiles(outputPath, files) {
172
173
  archive.finalize();
173
174
  });
174
175
  }
176
+ function countLineEndings(text) {
177
+ const crlf = (text.match(/\r\n/g) || []).length;
178
+ const noCRLF = text.replace(/\r\n/g, "");
179
+ const lf = (noCRLF.match(/\n/g) || []).length;
180
+ const cr = (noCRLF.match(/\r/g) || []).length;
181
+ return { crlf, lf, cr };
182
+ }
183
+ function normalizeToOSEOL(text, opts = {}) {
184
+ const { stripBOM = true, ensureFinalNewline = false } = opts;
185
+ if (stripBOM && text.charCodeAt(0) === 65279) {
186
+ text = text.slice(1);
187
+ }
188
+ const target = os.EOL;
189
+ const before = text;
190
+ let normalized = text.replace(/\r\n|\r|\n/g, target);
191
+ if (ensureFinalNewline && normalized.length > 0 && !normalized.endsWith(target)) {
192
+ normalized += target;
193
+ }
194
+ const changed = normalized !== before;
195
+ return {
196
+ text: normalized,
197
+ changed,
198
+ stats: countLineEndings(before),
199
+ target: target === "\r\n" ? "crlf" : target === "\r" ? "cr" : "lf"
200
+ };
201
+ }
175
202
  commander.program.command("prepare").description(
176
203
  "部署前的准备工作,如获取编译软件获取逻辑代码,生成 changelog 等"
177
204
  ).action(async (source, destination) => {
@@ -256,8 +283,14 @@ async function genChangelog(configs) {
256
283
  }
257
284
  const pkgContent = JSON.parse(node_fs.readFileSync(outputPackageJSONPath, "utf-8"));
258
285
  const currentVersion = pkgContent.version;
286
+ const changelogText = node_fs.readFileSync(r(configs.changelogsPath), "utf-8");
259
287
  const changes = await parseChangelog({
260
- filePath: r(configs.changelogsPath),
288
+ // 将 changelog 文件转换为 os.EOL
289
+ // https://github.com/ungoldman/changelog-parser/issues/34
290
+ text: normalizeToOSEOL(changelogText, {
291
+ stripBOM: true,
292
+ ensureFinalNewline: true
293
+ }).text,
261
294
  removeMarkdown: false
262
295
  });
263
296
  const currentChange = changes.versions.find((change) => {
@@ -336,33 +369,68 @@ function genTmpFolder() {
336
369
  if (!node_fs.existsSync(folderPath))
337
370
  node_fs.mkdirSync(folderPath);
338
371
  }
372
+ const TIMEOUT_MS = 5e3;
339
373
  async function netRequest(options) {
340
374
  if (!electron.net) {
341
- const response = await fetch(options.url);
342
- if (options.responseType === "json") {
343
- try {
344
- return await response.json();
345
- } catch (e) {
346
- return null;
375
+ const abortController = new AbortController();
376
+ const timeoutId = setTimeout(() => {
377
+ abortController.abort();
378
+ }, TIMEOUT_MS);
379
+ try {
380
+ const response = await fetch(options.url, {
381
+ signal: abortController.signal
382
+ });
383
+ clearTimeout(timeoutId);
384
+ if (options.responseType === "json") {
385
+ try {
386
+ return await response.json();
387
+ } catch (e) {
388
+ return null;
389
+ }
390
+ } else if (options.responseType === "stream") {
391
+ return response.body;
392
+ } else {
393
+ return await response.text();
347
394
  }
348
- } else if (options.responseType === "stream") {
349
- return response.body;
350
- } else {
351
- return await response.text();
395
+ } catch (error) {
396
+ clearTimeout(timeoutId);
397
+ if (error.name === "AbortError") {
398
+ throw new Error("网络请求超时,请检查网络连接或使用 VPN 后重试");
399
+ }
400
+ throw error;
352
401
  }
353
402
  }
354
403
  return new Promise((resolve, reject) => {
355
404
  const request = electron.net.request(options.url);
356
405
  let data = "";
406
+ let isResolved = false;
407
+ const timeoutId = setTimeout(() => {
408
+ if (!isResolved) {
409
+ isResolved = true;
410
+ request.abort();
411
+ reject(new Error("网络请求超时,请检查网络连接或使用 VPN 后重试"));
412
+ }
413
+ }, TIMEOUT_MS);
414
+ const cleanup = () => {
415
+ clearTimeout(timeoutId);
416
+ };
357
417
  request.on("response", (response) => {
358
418
  response.on("data", (chunk) => {
359
419
  if (options.responseType === "stream") {
360
- resolve(response);
420
+ if (!isResolved) {
421
+ isResolved = true;
422
+ cleanup();
423
+ resolve(response);
424
+ }
361
425
  return;
362
426
  }
363
427
  data += chunk;
364
428
  });
365
429
  response.on("end", () => {
430
+ if (isResolved)
431
+ return;
432
+ isResolved = true;
433
+ cleanup();
366
434
  if (options.responseType === "stream")
367
435
  return;
368
436
  if (options.responseType === "json") {
@@ -377,7 +445,11 @@ async function netRequest(options) {
377
445
  });
378
446
  });
379
447
  request.on("error", (error) => {
380
- reject(error);
448
+ if (!isResolved) {
449
+ isResolved = true;
450
+ cleanup();
451
+ reject(error);
452
+ }
381
453
  });
382
454
  request.end();
383
455
  });
@@ -726,4 +798,4 @@ async function installPrebuilt(configs) {
726
798
  }
727
799
  commander.program.description(
728
800
  "Electron 版本部署 CLI,简化你的 Electron 软件更新,让一切变得简单。"
729
- ).helpOption("-h, --help", "使用帮助").version("0.4.3", "-V, --version", "显示版本号").parse(process.argv);
801
+ ).helpOption("-h, --help", "使用帮助").version("0.4.5", "-V, --version", "显示版本号").parse(process.argv);
package/dist/main.js CHANGED
@@ -8,33 +8,68 @@ const node_process = require("node:process");
8
8
  const fs = require("fs");
9
9
  const path = require("path");
10
10
  const extract = require("extract-zip");
11
+ const TIMEOUT_MS = 5e3;
11
12
  async function netRequest(options) {
12
13
  if (!electron.net) {
13
- const response = await fetch(options.url);
14
- if (options.responseType === "json") {
15
- try {
16
- return await response.json();
17
- } catch (e) {
18
- return null;
14
+ const abortController = new AbortController();
15
+ const timeoutId = setTimeout(() => {
16
+ abortController.abort();
17
+ }, TIMEOUT_MS);
18
+ try {
19
+ const response = await fetch(options.url, {
20
+ signal: abortController.signal
21
+ });
22
+ clearTimeout(timeoutId);
23
+ if (options.responseType === "json") {
24
+ try {
25
+ return await response.json();
26
+ } catch (e) {
27
+ return null;
28
+ }
29
+ } else if (options.responseType === "stream") {
30
+ return response.body;
31
+ } else {
32
+ return await response.text();
19
33
  }
20
- } else if (options.responseType === "stream") {
21
- return response.body;
22
- } else {
23
- return await response.text();
34
+ } catch (error) {
35
+ clearTimeout(timeoutId);
36
+ if (error.name === "AbortError") {
37
+ throw new Error("网络请求超时,请检查网络连接或使用 VPN 后重试");
38
+ }
39
+ throw error;
24
40
  }
25
41
  }
26
42
  return new Promise((resolve, reject) => {
27
43
  const request = electron.net.request(options.url);
28
44
  let data = "";
45
+ let isResolved = false;
46
+ const timeoutId = setTimeout(() => {
47
+ if (!isResolved) {
48
+ isResolved = true;
49
+ request.abort();
50
+ reject(new Error("网络请求超时,请检查网络连接或使用 VPN 后重试"));
51
+ }
52
+ }, TIMEOUT_MS);
53
+ const cleanup2 = () => {
54
+ clearTimeout(timeoutId);
55
+ };
29
56
  request.on("response", (response) => {
30
57
  response.on("data", (chunk) => {
31
58
  if (options.responseType === "stream") {
32
- resolve(response);
59
+ if (!isResolved) {
60
+ isResolved = true;
61
+ cleanup2();
62
+ resolve(response);
63
+ }
33
64
  return;
34
65
  }
35
66
  data += chunk;
36
67
  });
37
68
  response.on("end", () => {
69
+ if (isResolved)
70
+ return;
71
+ isResolved = true;
72
+ cleanup2();
38
73
  if (options.responseType === "stream")
39
74
  return;
40
75
  if (options.responseType === "json") {
@@ -49,7 +84,11 @@ async function netRequest(options) {
49
84
  });
50
85
  });
51
86
  request.on("error", (error) => {
52
- reject(error);
87
+ if (!isResolved) {
88
+ isResolved = true;
89
+ cleanup2();
90
+ reject(error);
91
+ }
53
92
  });
54
93
  request.end();
55
94
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "electron-version-deployer-cli",
3
3
  "private": false,
4
- "version": "0.4.3",
4
+ "version": "0.4.5",
5
5
  "types": "./dist/index.d.ts",
6
6
  "main": "./dist/index.cjs.js",
7
7
  "module": "./dist/index.es.js",