electron-incremental-update 3.0.0-beta.4 → 3.0.0-beta.6

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.
@@ -1,50 +1,5 @@
1
- import { r as isUpdateJSON } from "./version--eVB2A7n.mjs";
1
+ import { u as isUpdateJSON } from "./zip-DUK3opmV.mjs";
2
2
  import { app, net } from "electron";
3
- import crypto from "node:crypto";
4
- import zlib from "node:zlib";
5
-
6
- //#region src/utils/crypto.ts
7
- function hashBuffer(data, length) {
8
- const hash = crypto.createHash("SHA256").update(data).digest("binary");
9
- return Buffer.from(hash).subarray(0, length);
10
- }
11
- function aesEncrypt(plainText, key, iv) {
12
- const cipher = crypto.createCipheriv("aes-256-cbc", key, iv);
13
- return cipher.update(plainText, "utf8", "base64url") + cipher.final("base64url");
14
- }
15
- /**
16
- * Default function to generate asar signature, returns generated signature
17
- * @param buffer file buffer
18
- * @param privateKey primary key
19
- * @param cert certificate
20
- * @param version target version
21
- */
22
- function defaultSignature(buffer, privateKey, cert, version) {
23
- return aesEncrypt(`${crypto.createSign("RSA-SHA256").update(buffer).sign(crypto.createPrivateKey(privateKey), "base64")}%${version}`, hashBuffer(cert, 32), hashBuffer(buffer, 16));
24
- }
25
- function aesDecrypt(encryptedText, key, iv) {
26
- const decipher = crypto.createDecipheriv("aes-256-cbc", key, iv);
27
- return decipher.update(encryptedText, "base64url", "utf8") + decipher.final("utf8");
28
- }
29
- /**
30
- * Default function to verify asar signature,
31
- * if signature is valid, returns the version, otherwise returns `undefined`
32
- * @param buffer file buffer
33
- * @param version target version
34
- * @param signature signature
35
- * @param cert certificate
36
- */
37
- function defaultVerifySignature(buffer, version, signature, cert) {
38
- try {
39
- const [sig, ver] = aesDecrypt(signature, hashBuffer(cert, 32), hashBuffer(buffer, 16)).split("%");
40
- if (ver !== version) return false;
41
- return crypto.createVerify("RSA-SHA256").update(buffer).verify(cert, sig, "base64");
42
- } catch {
43
- return false;
44
- }
45
- }
46
-
47
- //#endregion
48
3
  //#region src/utils/download.ts
49
4
  /**
50
5
  * Safe get value from header
@@ -59,6 +14,19 @@ function getHeader(headers, key) {
59
14
  async function downloadUtil(url, headers, onResponse) {
60
15
  await app.whenReady();
61
16
  return new Promise((resolve, reject) => {
17
+ const rejectUnexpectedStatus = (resp) => {
18
+ const statusCode = resp.statusCode ?? 0;
19
+ if (statusCode >= 200 && statusCode < 300) return false;
20
+ let data = "";
21
+ resp.on("data", (chunk) => {
22
+ data += chunk;
23
+ data = trimData(data);
24
+ });
25
+ resp.on("end", () => {
26
+ reject(/* @__PURE__ */ new Error(`Unexpected response status ${statusCode}${resp.statusMessage ? ` ${resp.statusMessage}` : ""} from ${url}: "${data}"`));
27
+ });
28
+ return true;
29
+ };
62
30
  const request = net.request({
63
31
  cache: "no-cache",
64
32
  headers,
@@ -69,6 +37,7 @@ async function downloadUtil(url, headers, onResponse) {
69
37
  request.on("response", (resp) => {
70
38
  resp.on("aborted", () => reject(/* @__PURE__ */ new Error("Aborted")));
71
39
  resp.on("error", reject);
40
+ if (rejectUnexpectedStatus(resp)) return;
72
41
  onResponse(request, resp, resolve, reject);
73
42
  });
74
43
  request.on("error", reject);
@@ -159,27 +128,5 @@ async function defaultDownloadAsar(url, headers, signal, onDownloading) {
159
128
  }, { once: true });
160
129
  });
161
130
  }
162
-
163
- //#endregion
164
- //#region src/utils/zip.ts
165
- /**
166
- * Default function to compress file using brotli
167
- * @param buffer uncompressed file buffer
168
- */
169
- async function defaultZipFile(buffer) {
170
- return new Promise((resolve, reject) => {
171
- zlib.brotliCompress(buffer, (err, buffer) => err ? reject(err) : resolve(buffer));
172
- });
173
- }
174
- /**
175
- * Default function to decompress file using brotli
176
- * @param buffer compressed file buffer
177
- */
178
- async function defaultUnzipFile(buffer) {
179
- return new Promise((resolve, reject) => {
180
- zlib.brotliDecompress(buffer, (err, buffer) => err ? reject(err) : resolve(buffer));
181
- });
182
- }
183
-
184
131
  //#endregion
185
- export { defaultDownloadUpdateJSON as a, resolveJson as c, defaultSignature as d, defaultVerifySignature as f, defaultDownloadText as i, aesDecrypt as l, defaultZipFile as n, downloadUtil as o, hashBuffer as p, defaultDownloadAsar as r, getHeader as s, defaultUnzipFile as t, aesEncrypt as u };
132
+ export { getHeader as a, downloadUtil as i, defaultDownloadText as n, resolveJson as o, defaultDownloadUpdateJSON as r, defaultDownloadAsar as t };
@@ -0,0 +1,167 @@
1
+ const require_zip = require("./zip-D1dbBzw4.cjs");
2
+ let electron = require("electron");
3
+ //#region src/utils/download.ts
4
+ /**
5
+ * Safe get value from header
6
+ * @param headers response header
7
+ * @param key target header key
8
+ */
9
+ function getHeader(headers, key) {
10
+ const value = headers[key];
11
+ if (Array.isArray(value)) return value.length === 0 ? null : value[value.length - 1];
12
+ else return value;
13
+ }
14
+ async function downloadUtil(url, headers, onResponse) {
15
+ await electron.app.whenReady();
16
+ return new Promise((resolve, reject) => {
17
+ const rejectUnexpectedStatus = (resp) => {
18
+ const statusCode = resp.statusCode ?? 0;
19
+ if (statusCode >= 200 && statusCode < 300) return false;
20
+ let data = "";
21
+ resp.on("data", (chunk) => {
22
+ data += chunk;
23
+ data = trimData(data);
24
+ });
25
+ resp.on("end", () => {
26
+ reject(/* @__PURE__ */ new Error(`Unexpected response status ${statusCode}${resp.statusMessage ? ` ${resp.statusMessage}` : ""} from ${url}: "${data}"`));
27
+ });
28
+ return true;
29
+ };
30
+ const request = electron.net.request({
31
+ cache: "no-cache",
32
+ headers,
33
+ method: "GET",
34
+ redirect: "follow",
35
+ url
36
+ });
37
+ request.on("response", (resp) => {
38
+ resp.on("aborted", () => reject(/* @__PURE__ */ new Error("Aborted")));
39
+ resp.on("error", reject);
40
+ if (rejectUnexpectedStatus(resp)) return;
41
+ onResponse(request, resp, resolve, reject);
42
+ });
43
+ request.on("error", reject);
44
+ request.end();
45
+ });
46
+ }
47
+ /**
48
+ * trim length to 5000
49
+ */
50
+ function trimData(data) {
51
+ return data.trim().slice(0, 5e3).replace(/\s+/g, " ");
52
+ }
53
+ const resolveJson = (data, resolve, reject) => {
54
+ try {
55
+ resolve(JSON.parse(data));
56
+ } catch {
57
+ reject(/* @__PURE__ */ new Error(`Invalid json, "${trimData(data)}"`));
58
+ }
59
+ };
60
+ /**
61
+ * Default function to download json and parse to UpdateJson
62
+ * @param url target url
63
+ * @param headers extra headers
64
+ * @param signal abort signal
65
+ * @param resolveData on resolve
66
+ */
67
+ async function defaultDownloadText(url, headers, signal, resolveData) {
68
+ return await downloadUtil(url, headers, (request, resp, resolve, reject) => {
69
+ let data = "";
70
+ resp.on("data", (chunk) => data += chunk);
71
+ resp.on("end", () => resolveData(data, resolve, reject));
72
+ signal.addEventListener("abort", () => {
73
+ request.abort();
74
+ data = null;
75
+ }, { once: true });
76
+ });
77
+ }
78
+ /**
79
+ * Default function to download json and parse to UpdateJson
80
+ * @param url target url
81
+ * @param headers extra headers
82
+ * @param signal abort signal
83
+ */
84
+ async function defaultDownloadUpdateJSON(url, headers, signal) {
85
+ return await defaultDownloadText(url, headers, signal, (data, resolve, reject) => {
86
+ try {
87
+ const json = JSON.parse(data);
88
+ if (require_zip.isUpdateJSON(json)) resolve(json);
89
+ else throw Error;
90
+ } catch {
91
+ reject(/* @__PURE__ */ new Error(`Invalid update json, "${trimData(data)}"`));
92
+ }
93
+ });
94
+ }
95
+ /**
96
+ * Default function to download asar buffer,
97
+ * get total size from `Content-Length` header
98
+ * @param url target url
99
+ * @param headers extra headers
100
+ * @param signal abort signal
101
+ * @param onDownloading on downloading callback
102
+ */
103
+ async function defaultDownloadAsar(url, headers, signal, onDownloading) {
104
+ let transferred = 0;
105
+ let time = Date.now();
106
+ return await downloadUtil(url, headers, (request, resp, resolve) => {
107
+ const total = +getHeader(resp.headers, "content-length") || -1;
108
+ let data = [];
109
+ resp.on("data", (chunk) => {
110
+ const delta = chunk.length;
111
+ transferred += delta;
112
+ const current = Date.now();
113
+ onDownloading?.({
114
+ bps: delta / (current - time),
115
+ delta,
116
+ percent: total > 0 ? +(transferred / total).toFixed(2) * 100 : -1,
117
+ total,
118
+ transferred
119
+ });
120
+ time = current;
121
+ data.push(chunk);
122
+ });
123
+ resp.on("end", () => resolve(Buffer.concat(data)));
124
+ signal.addEventListener("abort", () => {
125
+ request.abort();
126
+ data.length = 0;
127
+ data = null;
128
+ }, { once: true });
129
+ });
130
+ }
131
+ //#endregion
132
+ Object.defineProperty(exports, "defaultDownloadAsar", {
133
+ enumerable: true,
134
+ get: function() {
135
+ return defaultDownloadAsar;
136
+ }
137
+ });
138
+ Object.defineProperty(exports, "defaultDownloadText", {
139
+ enumerable: true,
140
+ get: function() {
141
+ return defaultDownloadText;
142
+ }
143
+ });
144
+ Object.defineProperty(exports, "defaultDownloadUpdateJSON", {
145
+ enumerable: true,
146
+ get: function() {
147
+ return defaultDownloadUpdateJSON;
148
+ }
149
+ });
150
+ Object.defineProperty(exports, "downloadUtil", {
151
+ enumerable: true,
152
+ get: function() {
153
+ return downloadUtil;
154
+ }
155
+ });
156
+ Object.defineProperty(exports, "getHeader", {
157
+ enumerable: true,
158
+ get: function() {
159
+ return getHeader;
160
+ }
161
+ });
162
+ Object.defineProperty(exports, "resolveJson", {
163
+ enumerable: true,
164
+ get: function() {
165
+ return resolveJson;
166
+ }
167
+ });
@@ -1,4 +1,4 @@
1
- import { p as Arrayable, s as UpdateJSON, t as DownloadingInfo } from "./types-DASqEPXE.mjs";
1
+ import { p as Arrayable, s as UpdateJSON, t as DownloadingInfo } from "./types-BOqQ_r5Q.cjs";
2
2
  import { ClientRequest, IncomingMessage } from "electron";
3
3
 
4
4
  //#region src/utils/download.d.ts
@@ -1,4 +1,4 @@
1
- import { p as Arrayable, s as UpdateJSON, t as DownloadingInfo } from "./types-BM9Jfu7q.cjs";
1
+ import { p as Arrayable, s as UpdateJSON, t as DownloadingInfo } from "./types-BOqQ_r5Q.mjs";
2
2
  import { ClientRequest, IncomingMessage } from "electron";
3
3
 
4
4
  //#region src/utils/download.d.ts
@@ -1,7 +1,16 @@
1
- import { app } from "electron";
2
1
  import fs from "node:fs";
3
2
  import path from "node:path";
4
-
3
+ import { app } from "electron";
4
+ import { pathToFileURL } from "node:url";
5
+ //#region src/utils/devtools/font.css?inline
6
+ var font_default = ":root,body{--source-code-font-family:var(--mono)!important;--source-code-font-size:12px!important;--monospace-font-family:var(--mono)!important;--monospace-font-size:12px!important;--default-font-family:var(--sans), sans-serif!important;--default-font-size:12px!important}button,input,select,.undisplayable-text,.expandable-inline-button{font-family:var(--sans)!important}\n";
7
+ //#endregion
8
+ //#region src/utils/devtools/js.ts?inject
9
+ var js_default = "export { };";
10
+ //#endregion
11
+ //#region src/utils/devtools/scrollbar.css?inline
12
+ var scrollbar_default = ":root{--scrollbar-width:max(.85vw, 10px)}@media (prefers-color-scheme:light){:root{--scrollbar-color-rgb:0, 0, 0}}@media (prefers-color-scheme:dark){:root{--scrollbar-color-rgb:255, 255, 255}}::-webkit-scrollbar{width:var(--scrollbar-width)!important;height:var(--scrollbar-width)!important}::-webkit-scrollbar-track{border-radius:var(--scrollbar-width)!important;box-shadow:none!important;background-color:#0000!important}::-webkit-scrollbar-thumb{background-clip:content-box;box-shadow:inset 0 0 0 var(--scrollbar-width)!important;border-radius:var(--scrollbar-width)!important;border:calc(var(--scrollbar-width) * 2 / 9) solid transparent!important;color:rgba(var(--scrollbar-color-rgb), 30%)!important;background-color:#0000!important}::-webkit-scrollbar-thumb:hover{color:rgba(var(--scrollbar-color-rgb), 45%)!important}::-webkit-scrollbar-thumb:active{color:rgba(var(--scrollbar-color-rgb), 60%)!important}@supports not selector(::-webkit-scrollbar){html{scrollbar-color:rgb(var(--scrollbar-color-rgb));scrollbar-width:thin}}\n";
13
+ //#endregion
5
14
  //#region src/utils/electron.ts
6
15
  /**
7
16
  * Compile time dev check
@@ -16,13 +25,19 @@ const isLinux = process.platform === "linux";
16
25
  * If is in dev, **always** return `'DEV.asar'`
17
26
  */
18
27
  function getPathFromAppNameAsar(...paths) {
19
- return isDev ? "DEV.asar" : path.join(path.dirname(app.getAppPath()), `${app.name}.asar`, ...paths);
28
+ return isDev ? path.join(__EIU_LOCAL_DEV_UPDATE_ASAR_PATH__ || "DEV.asar", ...paths) : path.join(path.dirname(app.getAppPath()), `${app.name}.asar`, ...paths);
20
29
  }
21
30
  /**
22
31
  * Get app version, if is in dev, return `getEntryVersion()`
23
32
  */
24
33
  function getAppVersion() {
25
- return isDev ? getEntryVersion() : fs.readFileSync(getPathFromAppNameAsar("version"), "utf-8");
34
+ if (!isDev) return fs.readFileSync(getPathFromAppNameAsar("version"), "utf-8");
35
+ if (!__EIU_LOCAL_DEV_UPDATE__) return getEntryVersion();
36
+ try {
37
+ return fs.readFileSync(getPathFromAppNameAsar("version"), "utf-8").trim();
38
+ } catch {
39
+ return getEntryVersion();
40
+ }
26
41
  }
27
42
  /**
28
43
  * Get entry version
@@ -38,7 +53,7 @@ function getEntryVersion() {
38
53
  */
39
54
  function requireNative(moduleName) {
40
55
  const m = getPathFromEntryAsar(moduleName);
41
- if (__EIU_IS_ESM__) throw new Error(`Cannot require "${m}", \`requireNative\` only support CommonJS, use \`importNative\` instead`);
56
+ if (__EIU_IS_ESM__) throw new Error(`Cannot require "${m}", \`requireNative\` only supports CommonJS. Use \`importNative\` instead`);
42
57
  return require(m);
43
58
  }
44
59
  /**
@@ -49,13 +64,24 @@ function requireNative(moduleName) {
49
64
  */
50
65
  async function importNative(moduleName) {
51
66
  const m = getPathFromEntryAsar(moduleName);
52
- if (!__EIU_IS_ESM__) throw new Error(`Cannot import "${m}", \`importNative\` only support ESModule, use \`requireNative\` instead`);
53
- return await import(`file://${m}.js`);
67
+ if (!__EIU_IS_ESM__) throw new Error(`Cannot import "${m}", \`importNative\` only supports ESModule. Use \`requireNative\` instead`);
68
+ return await import(pathToFileURL(path.extname(m) ? m : `${m}.mjs`).href);
54
69
  }
55
70
  /**
56
71
  * Restarts the Electron app.
57
72
  */
58
73
  function restartApp() {
74
+ if (isDev && __EIU_LOCAL_DEV_UPDATE__ && process.send) {
75
+ const forceExit = setTimeout(() => app.exit(0), 5e3);
76
+ process.once("message", (message) => {
77
+ if (message === "eiu:restart-ready") {
78
+ clearTimeout(forceExit);
79
+ app.exit(0);
80
+ }
81
+ });
82
+ process.send("eiu:restart");
83
+ return;
84
+ }
59
85
  app.relaunch();
60
86
  app.quit();
61
87
  }
@@ -128,10 +154,10 @@ function loadPage(win, htmlFilePath = "index.html") {
128
154
  function beautifyDevTools(win, options) {
129
155
  const { mono, sans, scrollbar = true } = options;
130
156
  win.webContents.on("devtools-opened", async () => {
131
- let css = `:root{--sans:${sans};--mono:${mono}}:root, body { --source-code-font-family: var(--mono) !important; --source-code-font-size: 12px !important; --monospace-font-family: var(--mono) !important; --monospace-font-size: 12px !important; --default-font-family: var(--sans), sans-serif !important; --default-font-size: 12px !important; } button, input, select, .undisplayable-text, .expandable-inline-button { font-family: var(--sans) !important; } `;
132
- if (scrollbar) css += ":root { --scrollbar-width: max(0.85vw, 10px); } @media (prefers-color-scheme: light) { :root { --scrollbar-color-rgb: 0, 0, 0; } } @media (prefers-color-scheme: dark) { :root { --scrollbar-color-rgb: 255, 255, 255; } } *::-webkit-scrollbar { width: var(--scrollbar-width) !important; height: var(--scrollbar-width) !important; } *::-webkit-scrollbar-track { background-color: transparent !important; border-radius: var(--scrollbar-width) !important; box-shadow: none !important; } *::-webkit-scrollbar-thumb { box-shadow: inset 0 0 0 var(--scrollbar-width) !important; border-radius: var(--scrollbar-width) !important; border: calc(var(--scrollbar-width) * 2 / 9) solid transparent !important; background-clip: content-box; background-color: transparent !important; color: rgba(var(--scrollbar-color-rgb), 30%) !important; } *::-webkit-scrollbar-thumb:hover { color: rgba(var(--scrollbar-color-rgb), 45%) !important; } *::-webkit-scrollbar-thumb:active { color: rgba(var(--scrollbar-color-rgb), 60%) !important; } @supports not selector(::-webkit-scrollbar) { html { scrollbar-color: rgb(var(--scrollbar-color-rgb)); scrollbar-width: thin; } } ";
133
- const js = `const __CSS__='${css}';function e(e){let t=document.createElement(\`style\`);t.innerHTML=e,document.body.append(t),[\`platform-windows\`,\`platform-mac\`,\`platform-linux\`].forEach(e=>document.querySelectorAll(\`.\${e}\`).forEach(t=>t.classList.remove(e))),r();let n=new MutationObserver(e=>{for(let t of e)if(t.type===\`childList\`)for(let e=0;e<t.addedNodes.length;e++)t.addedNodes[e].classList.contains(\`editor-tooltip-host\`)&&r()});n.observe(document.body,{childList:!0});function r(){document.querySelectorAll(\`.editor-tooltip-host\`).forEach(t=>{if(t?.shadowRoot?.querySelectorAll(\`[data-key="overridden-dev-tools-font"]\`).length===0){let n=document.createElement(\`style\`);n.dataset.key=\`overridden-dev-tools-font\`,n.innerHTML=\`\${e}.cm-tooltip-autocomplete ul[role=listbox]{font-family:var(--mono)!important;}\`,t.shadowRoot.append(n)}})}window.onbeforeunload=()=>n.disconnect()}e(__CSS__);`;
134
- await win?.webContents.devToolsWebContents?.executeJavaScript(js);
157
+ let css = `:root{--sans:${sans};--mono:${mono}}${font_default}`;
158
+ if (scrollbar) css += scrollbar_default;
159
+ const js = `const __CSS__=\`${css}\`;${js_default}`;
160
+ await win?.webContents.devToolsWebContents?.executeJavaScript(js).catch((e) => console.log(`Failed to execute js: ${js}.\n`, e));
135
161
  });
136
162
  }
137
163
  /**
@@ -176,6 +202,5 @@ function handleUnexpectedErrors(callback) {
176
202
  function reloadOnPreloadScriptChanged() {
177
203
  console.warn("`reloadOnPreloadScriptChange()` is no longer needed. It is embeded in `startupWithUpdater()`");
178
204
  }
179
-
180
205
  //#endregion
181
- export { singleInstance as C, setPortableDataPath as S, reloadOnPreloadScriptChanged as _, getPathFromAppNameAsar as a, setAppUserModelId as b, getPathFromPreload as c, importNative as d, isDev as f, loadPage as g, isWin as h, getEntryVersion as i, getPathFromPublic as l, isMac as m, disableHWAccForWin7 as n, getPathFromEntryAsar as o, isLinux as p, getAppVersion as r, getPathFromMain as s, beautifyDevTools as t, handleUnexpectedErrors as u, requireNative as v, setPortableAppDataPath as x, restartApp as y };
206
+ export { singleInstance as C, setPortableDataPath as S, reloadOnPreloadScriptChanged as _, getPathFromAppNameAsar as a, setAppUserModelId as b, getPathFromPreload as c, importNative as d, isDev as f, loadPage as g, isWin as h, getEntryVersion as i, getPathFromPublic as l, isMac as m, disableHWAccForWin7 as n, getPathFromEntryAsar as o, isLinux as p, getAppVersion as r, getPathFromMain as s, beautifyDevTools as t, handleUnexpectedErrors as u, requireNative as v, setPortableAppDataPath as x, restartApp as y };