cursedbelt 5.76.0 → 5.77.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/react/components/BuildFreshness.d.ts +2 -1
- package/dist/react/components/BuildFreshness.d.ts.map +1 -1
- package/dist/react/components/BuildFreshness.js +11 -4
- package/dist/react/components/BuildFreshness.js.map +1 -1
- package/package.json +1 -1
- package/src/react/components/BuildFreshness.spec.tsx +10 -0
- package/src/react/components/BuildFreshness.tsx +13 -4
|
@@ -35,7 +35,8 @@ import './buildFreshness.css';
|
|
|
35
35
|
export interface UseBuildFreshnessOptions {
|
|
36
36
|
/**
|
|
37
37
|
* Where the serving build identifies itself. Any JSON answering
|
|
38
|
-
* `{ build: { commitFull } }` — every satellite's health route does
|
|
38
|
+
* `{ build: { commitFull } }` — every satellite's health route does — or a client build
|
|
39
|
+
* stamp's `{ commit }` (`/build.json`, `forge-client stamp`).
|
|
39
40
|
*/
|
|
40
41
|
probeUrl?: string;
|
|
41
42
|
/** Poll interval for a visible tab, in ms. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BuildFreshness.d.ts","sourceRoot":"","sources":["../../../src/react/components/BuildFreshness.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAGjC,OAAO,sBAAsB,CAAC;AAgB9B,MAAM,WAAW,wBAAwB;IACvC
|
|
1
|
+
{"version":3,"file":"BuildFreshness.d.ts","sourceRoot":"","sources":["../../../src/react/components/BuildFreshness.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAGjC,OAAO,sBAAsB,CAAC;AAgB9B,MAAM,WAAW,wBAAwB;IACvC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8CAA8C;IAC9C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6EAA6E;IAC7E,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,8EAA8E;IAC9E,KAAK,EAAE,OAAO,CAAC;IACf,iEAAiE;IACjE,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,wDAAwD;IACxD,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAuBD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,QAAqB,EACrB,UAAoB,EACpB,OAAc,GACf,GAAE,wBAA6B,GAAG,cAAc,CAoDhD;AAED,MAAM,WAAW,yBAA0B,SAAQ,wBAAwB;IACzE,oEAAoE;IACpE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sFAAsF;IACtF,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,EACnC,QAAqB,EACrB,QAAQ,EACR,GAAG,OAAO,EACX,GAAE,yBAA8B,GAAG,GAAG,CAAC,OAAO,GAAG,IAAI,CA+BrD"}
|
|
@@ -14,13 +14,20 @@ const POLL_MS = 5 * 60_000;
|
|
|
14
14
|
* fast as the events land.
|
|
15
15
|
*/
|
|
16
16
|
const MIN_GAP_MS = 30_000;
|
|
17
|
-
/**
|
|
17
|
+
/**
|
|
18
|
+
* The commit out of a health payload or a client build stamp, defensively.
|
|
19
|
+
*
|
|
20
|
+
* Two shapes, one identity: a satellite's `/healthz` nests it (`{ build: { commitFull } }`), and
|
|
21
|
+
* the CLIENT's own stamp — `forge-client stamp`'s `dist/build.json` (cursedops `stagedClient.ts`)
|
|
22
|
+
* — carries it at the top (`{ commit }`). The stamp is the better probe for an app whose health
|
|
23
|
+
* route answers for a server that ships on its own clock (roms' `/healthz` is its Mac's): it is a
|
|
24
|
+
* static file of the very build this tab loaded (forge 2026-10-10, task 3022).
|
|
25
|
+
*/
|
|
18
26
|
function commitOf(payload) {
|
|
19
27
|
if (typeof payload !== 'object' || payload === null)
|
|
20
28
|
return null;
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
return null;
|
|
29
|
+
const nested = payload.build;
|
|
30
|
+
const build = typeof nested === 'object' && nested !== null ? nested : payload;
|
|
24
31
|
const full = build.commitFull;
|
|
25
32
|
const short = build.commit;
|
|
26
33
|
const value = typeof full === 'string' && full ? full : typeof short === 'string' ? short : '';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BuildFreshness.js","sourceRoot":"","sources":["../../../src/react/components/BuildFreshness.tsx"],"names":[],"mappings":";AAiCA,OAAO,EAAE,CAAC,EAAE,MAAM,cAAc,CAAC;AACjC,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjE,OAAO,sBAAsB,CAAC;AAC9B,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,0DAA0D;AAC1D,MAAM,OAAO,GAAG,CAAC,GAAG,MAAM,CAAC;AAE3B;;;;;;GAMG;AACH,MAAM,UAAU,GAAG,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"BuildFreshness.js","sourceRoot":"","sources":["../../../src/react/components/BuildFreshness.tsx"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cursedbelt",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.77.0",
|
|
4
4
|
"license": "ISC",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "The React design system of the cursedbelt split — components, styles, theme. cursedbelt-core below it; server tier in cursedbelt-server.",
|
|
@@ -62,6 +62,16 @@ describe('BuildFreshnessNotice', () => {
|
|
|
62
62
|
expect(screen.getByRole('button', { name: /Reload/i })).toBeDefined();
|
|
63
63
|
});
|
|
64
64
|
|
|
65
|
+
test('🔴 speaks off a CLIENT build stamp too — `/build.json`\'s top-level `{ commit }`', async () => {
|
|
66
|
+
// `forge-client stamp` writes the client's own commit at the top of `dist/build.json`. roms
|
|
67
|
+
// probes it (its `/healthz` is its Mac's), and a TV tab kept the old build for 84 minutes
|
|
68
|
+
// after a fast-lane ship because nothing read it twice (forge task 3022, 2026-10-10).
|
|
69
|
+
const stamp = (commit: string) => ({ commit, dirty: false });
|
|
70
|
+
healthzServing([stamp('a'.repeat(40)), stamp('b'.repeat(40))]);
|
|
71
|
+
render(<BuildFreshnessNotice intervalMs={5} probeUrl='/build.json' appLabel='ROMs' />);
|
|
72
|
+
await waitFor(() => expect(screen.queryByText(/ROMs was updated/i)).not.toBeNull(), { timeout: 2_000 });
|
|
73
|
+
});
|
|
74
|
+
|
|
65
75
|
test('stays silent when the probe fails — offline, or a 502 mid-deploy', async () => {
|
|
66
76
|
healthzServing([build('aaaaaaaaaaaa'), new TypeError('Failed to fetch')]);
|
|
67
77
|
render(<BuildFreshnessNotice intervalMs={5} />);
|
|
@@ -52,7 +52,8 @@ const MIN_GAP_MS = 30_000;
|
|
|
52
52
|
export interface UseBuildFreshnessOptions {
|
|
53
53
|
/**
|
|
54
54
|
* Where the serving build identifies itself. Any JSON answering
|
|
55
|
-
* `{ build: { commitFull } }` — every satellite's health route does
|
|
55
|
+
* `{ build: { commitFull } }` — every satellite's health route does — or a client build
|
|
56
|
+
* stamp's `{ commit }` (`/build.json`, `forge-client stamp`).
|
|
56
57
|
*/
|
|
57
58
|
probeUrl?: string;
|
|
58
59
|
/** Poll interval for a visible tab, in ms. */
|
|
@@ -70,11 +71,19 @@ export interface BuildFreshness {
|
|
|
70
71
|
servingCommit: string | null;
|
|
71
72
|
}
|
|
72
73
|
|
|
73
|
-
/**
|
|
74
|
+
/**
|
|
75
|
+
* The commit out of a health payload or a client build stamp, defensively.
|
|
76
|
+
*
|
|
77
|
+
* Two shapes, one identity: a satellite's `/healthz` nests it (`{ build: { commitFull } }`), and
|
|
78
|
+
* the CLIENT's own stamp — `forge-client stamp`'s `dist/build.json` (cursedops `stagedClient.ts`)
|
|
79
|
+
* — carries it at the top (`{ commit }`). The stamp is the better probe for an app whose health
|
|
80
|
+
* route answers for a server that ships on its own clock (roms' `/healthz` is its Mac's): it is a
|
|
81
|
+
* static file of the very build this tab loaded (forge 2026-10-10, task 3022).
|
|
82
|
+
*/
|
|
74
83
|
function commitOf(payload: unknown): string | null {
|
|
75
84
|
if (typeof payload !== 'object' || payload === null) return null;
|
|
76
|
-
const
|
|
77
|
-
|
|
85
|
+
const nested = (payload as { build?: unknown }).build;
|
|
86
|
+
const build = typeof nested === 'object' && nested !== null ? nested : payload;
|
|
78
87
|
const full = (build as { commitFull?: unknown }).commitFull;
|
|
79
88
|
const short = (build as { commit?: unknown }).commit;
|
|
80
89
|
const value = typeof full === 'string' && full ? full : typeof short === 'string' ? short : '';
|