@danhachuel/thunderbolt 0.7.35 → 0.7.36

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 (2) hide show
  1. package/package.json +1 -1
  2. package/scripts/cli.mjs +51 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danhachuel/thunderbolt",
3
- "version": "0.7.35",
3
+ "version": "0.7.36",
4
4
  "description": "Thunderbolt — interface local para operação de canais faceless e motor MoneyPrinterTurbo",
5
5
  "license": "MIT",
6
6
  "main": "scripts/cli.mjs",
package/scripts/cli.mjs CHANGED
@@ -9,6 +9,10 @@ import { fileURLToPath } from "node:url";
9
9
 
10
10
  const root = resolve(fileURLToPath(new URL(".", import.meta.url)), "..");
11
11
  const args = process.argv.slice(2);
12
+ const packageVersion = (() => {
13
+ try { return JSON.parse(readFileSync(join(root, "package.json"), "utf8")).version || "dev"; }
14
+ catch { return "dev"; }
15
+ })();
12
16
 
13
17
  function getUserHome() {
14
18
  if (platform() !== "win32") return homedir();
@@ -200,6 +204,33 @@ const backendPort = await new Promise((resolve, reject) => {
200
204
  });
201
205
  });
202
206
  const supportedLanguages = new Set(["en", "zh", "de", "vi", "tr", "pt", "ru", "es", "id", "it"]);
207
+ const dynamicChunkRecoveryScript = `<script data-thunderbolt-recovery="${packageVersion}">
208
+ (() => {
209
+ const key = "thunderbolt-dynamic-chunk-recovery";
210
+ const recover = () => {
211
+ try {
212
+ const now = Date.now();
213
+ const previous = Number(sessionStorage.getItem(key) || 0);
214
+ if (now - previous < 30000) return;
215
+ sessionStorage.setItem(key, String(now));
216
+ const url = new URL(window.location.href);
217
+ url.searchParams.set("tb_refresh", String(now));
218
+ window.location.replace(url.href);
219
+ } catch (_) {
220
+ window.location.reload();
221
+ }
222
+ };
223
+ window.addEventListener("unhandledrejection", (event) => {
224
+ const message = String(event.reason?.message || event.reason || "");
225
+ if (/Failed to fetch dynamically imported module|Importing a module script failed/i.test(message)) recover();
226
+ });
227
+ window.addEventListener("error", (event) => {
228
+ const message = String(event.message || "");
229
+ if (/dynamically imported module|module script failed/i.test(message)) recover();
230
+ });
231
+ window.setTimeout(() => { try { sessionStorage.removeItem(key); } catch (_) {} }, 3500);
232
+ })();
233
+ </script>`;
203
234
 
204
235
  const proxy = http.createServer((request, response) => {
205
236
  const requestUrl = new URL(request.url || "/", `http://localhost:${publicPort}`);
@@ -240,8 +271,26 @@ const proxy = http.createServer((request, response) => {
240
271
  responseHeaders["cache-control"] = "no-store, no-cache, must-revalidate, max-age=0";
241
272
  responseHeaders.pragma = "no-cache";
242
273
  responseHeaders.expires = "0";
243
- response.writeHead(upstreamResponse.statusCode || 502, responseHeaders);
244
- upstreamResponse.pipe(response);
274
+ const contentType = String(responseHeaders["content-type"] || "").toLowerCase();
275
+ const isHtml = contentType.includes("text/html") && !responseHeaders["content-encoding"];
276
+ if (!isHtml) {
277
+ response.writeHead(upstreamResponse.statusCode || 502, responseHeaders);
278
+ upstreamResponse.pipe(response);
279
+ return;
280
+ }
281
+ const chunks = [];
282
+ let totalBytes = 0;
283
+ upstreamResponse.on("data", (chunk) => {
284
+ chunks.push(chunk);
285
+ totalBytes += chunk.length;
286
+ });
287
+ upstreamResponse.on("end", () => {
288
+ let body = Buffer.concat(chunks, totalBytes).toString("utf8");
289
+ if (body.includes("</body>")) body = body.replace("</body>", `${dynamicChunkRecoveryScript}</body>`);
290
+ delete responseHeaders["content-length"];
291
+ response.writeHead(upstreamResponse.statusCode || 502, responseHeaders);
292
+ response.end(body);
293
+ });
245
294
  });
246
295
  upstream.on("error", (error) => {
247
296
  response.writeHead(502, { "content-type": "text/plain; charset=utf-8" });