@bobfrankston/rmfmail 1.2.69 → 1.2.70
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/bin/build-bundles.mjs +42 -0
- package/client/compose/compose.html +1 -1
- package/client/index.html +2 -2
- package/package.json +1 -1
package/bin/build-bundles.mjs
CHANGED
|
@@ -18,11 +18,52 @@
|
|
|
18
18
|
*/
|
|
19
19
|
import * as esbuild from "esbuild";
|
|
20
20
|
import path from "node:path";
|
|
21
|
+
import fs from "node:fs";
|
|
22
|
+
import crypto from "node:crypto";
|
|
21
23
|
import { fileURLToPath } from "node:url";
|
|
22
24
|
|
|
23
25
|
const root = path.resolve(fileURLToPath(import.meta.url), "..", "..");
|
|
24
26
|
const watch = process.argv.includes("--watch");
|
|
25
27
|
|
|
28
|
+
/** Cache-bust the bundle references in the HTML entry points with a content
|
|
29
|
+
* hash. The msger custom protocol serves bundles with no cache headers, so
|
|
30
|
+
* WebView2 caches `app.bundle.js` and keeps serving the OLD bundle across
|
|
31
|
+
* daemon relaunches — every client-side fix silently failed to reach the user
|
|
32
|
+
* until the cache happened to evict (Bob 2026-06-26: flag/Ctrl+A fixes "still
|
|
33
|
+
* happening" while the daemon was already on the new version). Stamping a
|
|
34
|
+
* per-build `?v=<hash>` makes the URL change whenever the bundle changes, so
|
|
35
|
+
* the WebView is forced to fetch the new one. */
|
|
36
|
+
function shortHash(file) {
|
|
37
|
+
try { return crypto.createHash("sha1").update(fs.readFileSync(file)).digest("hex").slice(0, 10); }
|
|
38
|
+
catch { return String(Date.now()); }
|
|
39
|
+
}
|
|
40
|
+
function stampHtml(htmlFile, refs) {
|
|
41
|
+
let html;
|
|
42
|
+
try { html = fs.readFileSync(htmlFile, "utf8"); } catch { return; }
|
|
43
|
+
let changed = false;
|
|
44
|
+
for (const { name, file } of refs) {
|
|
45
|
+
const v = shortHash(file);
|
|
46
|
+
// Match the bundle name + optional existing ?v=… up to the closing
|
|
47
|
+
// quote, so re-runs replace the prior hash instead of stacking.
|
|
48
|
+
const re = new RegExp(`(${name.replace(/[.\\/]/g, m => "\\" + m)})(\\?v=[a-z0-9]+)?(")`, "g");
|
|
49
|
+
const next = html.replace(re, `$1?v=${v}$3`);
|
|
50
|
+
if (next !== html) { html = next; changed = true; }
|
|
51
|
+
}
|
|
52
|
+
if (changed) {
|
|
53
|
+
fs.writeFileSync(htmlFile, html);
|
|
54
|
+
console.log(` stamped ${path.relative(root, htmlFile)}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function stampAll() {
|
|
58
|
+
stampHtml(path.join(root, "client", "index.html"), [
|
|
59
|
+
{ name: "./app.bundle.js", file: path.join(root, "client", "app.bundle.js") },
|
|
60
|
+
{ name: "./android-bootstrap.bundle.js", file: path.join(root, "client", "android-bootstrap.bundle.js") },
|
|
61
|
+
]);
|
|
62
|
+
stampHtml(path.join(root, "client", "compose", "compose.html"), [
|
|
63
|
+
{ name: "compose.bundle.js", file: path.join(root, "client", "compose", "compose.bundle.js") },
|
|
64
|
+
]);
|
|
65
|
+
}
|
|
66
|
+
|
|
26
67
|
// Each entry has its own external list because the Android bootstrap bundle
|
|
27
68
|
// needs to INCLUDE @bobfrankston/mailx-store-web (entire purpose of the
|
|
28
69
|
// bundle), while app.bundle.js externalizes it so the desktop build doesn't
|
|
@@ -132,6 +173,7 @@ async function buildAll() {
|
|
|
132
173
|
}
|
|
133
174
|
const failed = results.filter(r => !r.ok).length;
|
|
134
175
|
if (failed) process.exit(1);
|
|
176
|
+
stampAll();
|
|
135
177
|
console.log(`build-bundles: done in ${Date.now() - t0} ms`);
|
|
136
178
|
}
|
|
137
179
|
|
|
@@ -557,7 +557,7 @@
|
|
|
557
557
|
Replaces a multi-file ES module cascade through msger's custom
|
|
558
558
|
protocol IPC that was visibly slow on compose-open. Source remains
|
|
559
559
|
compose.ts; the .js is for fallback / debugging only. -->
|
|
560
|
-
<script type="module" src="compose.bundle.js"></script>
|
|
560
|
+
<script type="module" src="compose.bundle.js?v=4c3aed9911"></script>
|
|
561
561
|
</head>
|
|
562
562
|
<body>
|
|
563
563
|
<div class="compose-header">
|
package/client/index.html
CHANGED
|
@@ -677,7 +677,7 @@
|
|
|
677
677
|
// dynamically imported module" bootstrap failure). The bundle inlines
|
|
678
678
|
// every transitive dep, so no further import-map resolution is needed
|
|
679
679
|
// after this fetch.
|
|
680
|
-
const m = await import("./android-bootstrap.bundle.js");
|
|
680
|
+
const m = await import("./android-bootstrap.bundle.js?v=7e151728fb");
|
|
681
681
|
window.__btick && window.__btick("android-bootstrap module loaded");
|
|
682
682
|
await m.initAndroid();
|
|
683
683
|
window.__btick && window.__btick("initAndroid done");
|
|
@@ -692,7 +692,7 @@
|
|
|
692
692
|
// bundle is regenerated by `npm run build` via
|
|
693
693
|
// bin/build-bundles.mjs; dynamic `await import()` of optional
|
|
694
694
|
// adapters (rmf-tiny, android-bootstrap) stays external.
|
|
695
|
-
await import("./app.bundle.js");
|
|
695
|
+
await import("./app.bundle.js?v=14fc25b74f");
|
|
696
696
|
window.__btick && window.__btick("app.bundle.js loaded");
|
|
697
697
|
} catch (e) {
|
|
698
698
|
const msg = "BOOTSTRAP FAILED: " + (e.message || e) + "\n" + (e.stack || "");
|