@ai-matrx/content-ir-react 0.7.1 → 0.8.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/CHANGELOG.md +61 -0
- package/dist/component-resolution.types-BS1ySIg-.d.cts +104 -0
- package/dist/component-resolution.types-BS1ySIg-.d.ts +104 -0
- package/dist/component-resolution.types-fvR92hW7.d.cts +142 -0
- package/dist/component-resolution.types-fvR92hW7.d.ts +142 -0
- package/dist/db-component.cjs +226 -0
- package/dist/db-component.cjs.map +1 -0
- package/dist/db-component.d.cts +267 -0
- package/dist/db-component.d.ts +267 -0
- package/dist/db-component.js +194 -0
- package/dist/db-component.js.map +1 -0
- package/dist/host-types-CZ_Bkp4R.d.ts +131 -0
- package/dist/host-types-DvGv8s9L.d.cts +131 -0
- package/dist/host.cjs +74 -0
- package/dist/host.cjs.map +1 -0
- package/dist/host.d.cts +24 -0
- package/dist/host.d.ts +24 -0
- package/dist/host.js +52 -0
- package/dist/host.js.map +1 -0
- package/dist/index.cjs +356 -90
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +280 -672
- package/dist/index.d.ts +280 -672
- package/dist/index.js +316 -31
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +361 -0
- package/dist/react.cjs.map +1 -0
- package/dist/react.d.cts +195 -0
- package/dist/react.d.ts +195 -0
- package/dist/react.js +344 -0
- package/dist/react.js.map +1 -0
- package/dist/resolver.cjs +327 -0
- package/dist/resolver.cjs.map +1 -0
- package/dist/resolver.d.cts +133 -0
- package/dist/resolver.d.ts +133 -0
- package/dist/resolver.js +304 -0
- package/dist/resolver.js.map +1 -0
- package/dist/route-C1XNcubB.d.ts +433 -0
- package/dist/route-C55jsF4B.d.cts +433 -0
- package/dist/route.cjs +259 -0
- package/dist/route.cjs.map +1 -0
- package/dist/route.d.cts +4 -0
- package/dist/route.d.ts +4 -0
- package/dist/route.js +247 -0
- package/dist/route.js.map +1 -0
- package/package.json +75 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,66 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.8.0 — 2026-08-30
|
|
4
|
+
|
|
5
|
+
The CONTENT-IR-REACT row of the C23 all-inclusive retrofit register: the
|
|
6
|
+
DB-component compile cache moves IN, the default error boundary ships, and the
|
|
7
|
+
five areas become subpath entries.
|
|
8
|
+
|
|
9
|
+
- **`/db-component` — the DB-component compile cache is package policy.**
|
|
10
|
+
matrx-frontend's 316-line `dbKindComponentCache.ts` (session compile cache
|
|
11
|
+
keyed per winning row VERSION, the scream-once console latch, loud-but-never-
|
|
12
|
+
fatal `props_transform` recovery, config narrowing, allowed-imports
|
|
13
|
+
resolution, key-family invalidation) was pure C22 violation living in one
|
|
14
|
+
host. `createDbKindComponentCache(ports)` now owns all of it; the host
|
|
15
|
+
injects only what is host-shaped: the sandbox COMPILER (security-shaped —
|
|
16
|
+
the package never bundles Babel), the default allowlist, the error reporter,
|
|
17
|
+
the durable incident sink, and the invalidation TRIGGER via the
|
|
18
|
+
`registerInvalidation` port (the host wires its invalidation-registry keys;
|
|
19
|
+
the cache owns what invalidation means). Also ships the kind prop contract
|
|
20
|
+
(`DbKindComponentRenderProps`, `KindComponentUiOptions`, `ResolveKindValue`,
|
|
21
|
+
`RunDbKindAction`) and `isDbKindComponentBodyPending`.
|
|
22
|
+
- **`DbKindComponentErrorBoundary` — the default error boundary the register
|
|
23
|
+
named.** Catch → fallback (never a blank hole) → scream through the
|
|
24
|
+
`onCaught` seam (host binds structured capture + incident filing; the
|
|
25
|
+
default is an honest console scream). `resetSignal` (the row's `updated_at`)
|
|
26
|
+
un-latches the boundary when a NEW component version arrives, so a fixed
|
|
27
|
+
component renders without a full unmount.
|
|
28
|
+
- **Subpath entries for the five areas:** `/host`, `/resolver`, `/route`,
|
|
29
|
+
`/react`, `/db-component` — dual ESM/CJS with matching declarations, per the
|
|
30
|
+
fleet banner rule: `/host`, `/react`, `/db-component` are stamped
|
|
31
|
+
`"use client"`; `/resolver` and `/route` are pure and deliberately
|
|
32
|
+
unstamped; the root `.` keeps the full surface, unstamped (it mixes pure
|
|
33
|
+
route logic that server modules import with client components — parity with
|
|
34
|
+
every existing consumer). tsup moved to the two-config kit shape
|
|
35
|
+
(`treeshake: false` so the banner survives to dist).
|
|
36
|
+
- **`createKindRouteBinding(env, options)`** — the per-host partial
|
|
37
|
+
application every host was hand-writing as wrapper modules
|
|
38
|
+
(`applyIrKindRoute` / `kindServerDataFromStoredValue` /
|
|
39
|
+
`isPartialReadyKind` / `resolveProvisionalKindRender` with env + ownedTypes
|
|
40
|
+
threaded). Host route wrappers collapse to injection + re-export.
|
|
41
|
+
- **Session latches moved to `globalThis` slots**
|
|
42
|
+
(`Symbol.for("ai-matrx.content-ir-react.partial-unsafe-kinds")`, same for
|
|
43
|
+
the sourceless-db-row report latch): with `splitting: false` dual-format
|
|
44
|
+
subpath builds, a module-level Set would silently split the
|
|
45
|
+
`markKindPartialUnsafe` writer (in `/react`'s graph) from the
|
|
46
|
+
`isPartialReadyKind` reader (in `/route`'s) — the kit confirm-opener
|
|
47
|
+
precedent. The tarball canary now proves the slot across loader graphs and
|
|
48
|
+
the `"use client"` stamp per chunk.
|
|
49
|
+
- 20 new tests (cache policy, boundary latch/un-latch, route binding).
|
|
50
|
+
|
|
51
|
+
### Consumer action
|
|
52
|
+
|
|
53
|
+
- Hosts that carry their own DB-component compile cache (matrx-frontend:
|
|
54
|
+
`features/content-ir/react/db-component/dbKindComponentCache.ts`) must
|
|
55
|
+
collapse it to `createDbKindComponentCache` port wiring and delete the
|
|
56
|
+
mechanics; a host error boundary around compiled DB components becomes a
|
|
57
|
+
binding of `DbKindComponentErrorBoundary` with `onCaught`.
|
|
58
|
+
- Host route wrapper modules should re-export from `createKindRouteBinding`
|
|
59
|
+
instead of hand-forwarding env/ownedTypes (signatures unchanged for their
|
|
60
|
+
own call sites).
|
|
61
|
+
- No import-path changes are REQUIRED — the root export keeps the full
|
|
62
|
+
surface. New code (and any RSC-adjacent graph) should prefer the subpaths.
|
|
63
|
+
|
|
3
64
|
## 0.7.1 — 2026-08-30
|
|
4
65
|
|
|
5
66
|
- `@ai-matrx/content-ir` is now a REAL dependency (`^0.9.0`) instead of a peer
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE SCREAM SEAM.
|
|
3
|
+
*
|
|
4
|
+
* Every recovery path in this package is loud: a defective component row, a
|
|
5
|
+
* failed resolver load, a kind whose component throws on a provisional value.
|
|
6
|
+
* The package refuses to own where those screams land — matrx-frontend routes
|
|
7
|
+
* them to the Error Inspector, the dashboard to its own log, the extension to
|
|
8
|
+
* its background page. Each host binds one function.
|
|
9
|
+
*
|
|
10
|
+
* A host that binds a no-op has chosen silence, which is a defect in itself;
|
|
11
|
+
* {@link consoleErrorReporter} is the honest default.
|
|
12
|
+
*/
|
|
13
|
+
interface ContentIrErrorReport {
|
|
14
|
+
/** Always `"content-ir"` — hosts key their capture stores on it. */
|
|
15
|
+
source: "content-ir";
|
|
16
|
+
message: string;
|
|
17
|
+
name?: string;
|
|
18
|
+
stack?: string;
|
|
19
|
+
/** Free-form grouping key (the host's `relation`), e.g. `"partial-kind"`. */
|
|
20
|
+
relation?: string;
|
|
21
|
+
raw?: unknown;
|
|
22
|
+
}
|
|
23
|
+
type ContentIrErrorReporter = (report: ContentIrErrorReport) => void;
|
|
24
|
+
/** The default when a host binds nothing: never silent. */
|
|
25
|
+
declare const consoleErrorReporter: ContentIrErrorReporter;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* The (kind, platform, role) → component vocabulary — the Shape System's
|
|
29
|
+
* resolver contract (rulings R1 + R6), stated once for every UI.
|
|
30
|
+
*
|
|
31
|
+
* Cross-repo system-of-record:
|
|
32
|
+
* `common-docs/systems/content-ir-twin/FEATURE.md` (package boundary) and
|
|
33
|
+
* `matrx-frontend/features/content-ir/docs/SHAPE_SYSTEM.md` (the semantics).
|
|
34
|
+
*
|
|
35
|
+
* Nothing here knows where a row comes from. A host supplies rows from
|
|
36
|
+
* `content_ir.kind_component` (Supabase, a REST call, a fixture); the resolver
|
|
37
|
+
* only knows the shape.
|
|
38
|
+
*/
|
|
39
|
+
/** JSON object, restated locally so this package depends on no host type. */
|
|
40
|
+
type JsonObject = Record<string, unknown>;
|
|
41
|
+
/**
|
|
42
|
+
* Which face of the shape a component draws.
|
|
43
|
+
*
|
|
44
|
+
* - `output` — the shape's finished value, the component a reader sees.
|
|
45
|
+
* - `input` — the authoring form for a value of this shape.
|
|
46
|
+
* - `loading` — the shape's LOADING face: what renders from the instant the
|
|
47
|
+
* kind is identified until its output component has a renderable frame.
|
|
48
|
+
* Authored per kind like any other component and fed the region's partial
|
|
49
|
+
* value each frame, so it can PERFORM the arrival (surface real text as it
|
|
50
|
+
* lands) instead of drawing a shapeless skeleton. Optional: a kind with no
|
|
51
|
+
* `loading` component falls back to the host's loading library.
|
|
52
|
+
*/
|
|
53
|
+
type ComponentRole = "output" | "input" | "loading";
|
|
54
|
+
/** The resolver's answer for one (kind, platform, role). */
|
|
55
|
+
interface ComponentResolution {
|
|
56
|
+
/** The component key the renderer routes on (e.g. "flashcards"). */
|
|
57
|
+
componentKey: string;
|
|
58
|
+
source: string;
|
|
59
|
+
config: JsonObject;
|
|
60
|
+
/**
|
|
61
|
+
* Render-trust verdict (R6). Compiled entries are always active (trusted at
|
|
62
|
+
* bootstrap); DB rows carry their own `is_active`.
|
|
63
|
+
*/
|
|
64
|
+
isActive: boolean;
|
|
65
|
+
/** Which tier produced this answer — the verification hook's `by`. */
|
|
66
|
+
resolvedBy: "compiled" | "db";
|
|
67
|
+
componentSource: string | null;
|
|
68
|
+
propsTransform: string | null;
|
|
69
|
+
/**
|
|
70
|
+
* TRUE when the row owns a real component body — even if `componentSource`
|
|
71
|
+
* is null because the host's warm list is body-less and the cold fetch has
|
|
72
|
+
* not landed it yet. THE routing gate: `routeToDbComponent` re-types on
|
|
73
|
+
* this flag, never on body presence, so a body-less row still routes and
|
|
74
|
+
* the renderer fetches/compiles the body lazily.
|
|
75
|
+
*/
|
|
76
|
+
hasComponentSource: boolean;
|
|
77
|
+
pinnedKindVersion: number | null;
|
|
78
|
+
/** The db row's `updated_at` — the compile-cache staleness key. */
|
|
79
|
+
updatedAt: string | null;
|
|
80
|
+
createdBy: string | null;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* The read side of a component resolver, as the render layer consumes it.
|
|
84
|
+
* The package ships {@link ComponentResolver}; a host with its own resolver
|
|
85
|
+
* only has to satisfy this.
|
|
86
|
+
*/
|
|
87
|
+
interface ComponentResolutionSource {
|
|
88
|
+
/** Synchronous — the render seam's per-block call. */
|
|
89
|
+
resolve(kind: string, platform: string, role: ComponentRole): ComponentResolution | null;
|
|
90
|
+
/** Eager targeted fetch for one kind; fire-and-forget, never awaited on the hot path. */
|
|
91
|
+
requestComponent(kind: string, platform: string, role: ComponentRole): void;
|
|
92
|
+
/** One list fetch per session. */
|
|
93
|
+
ensureWarm(): Promise<void>;
|
|
94
|
+
/** Refresh-on-view; rate-limited and deduped by the implementation. */
|
|
95
|
+
refresh(maxAgeMs?: number): Promise<void>;
|
|
96
|
+
/** Monotonic tier version — has anything at all changed? */
|
|
97
|
+
getVersion(): number;
|
|
98
|
+
/** Monotonic per-kind version (+ wholesale epoch) — the granular repaint key. */
|
|
99
|
+
getKindVersion(kind: string): number;
|
|
100
|
+
subscribe(listener: () => void): () => void;
|
|
101
|
+
subscribeKind(kind: string, listener: () => void): () => void;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export { type ComponentResolution as C, type ContentIrErrorReporter as a, type ContentIrErrorReport as b, consoleErrorReporter as c, type ComponentResolutionSource as d };
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE SCREAM SEAM.
|
|
3
|
+
*
|
|
4
|
+
* Every recovery path in this package is loud: a defective component row, a
|
|
5
|
+
* failed resolver load, a kind whose component throws on a provisional value.
|
|
6
|
+
* The package refuses to own where those screams land — matrx-frontend routes
|
|
7
|
+
* them to the Error Inspector, the dashboard to its own log, the extension to
|
|
8
|
+
* its background page. Each host binds one function.
|
|
9
|
+
*
|
|
10
|
+
* A host that binds a no-op has chosen silence, which is a defect in itself;
|
|
11
|
+
* {@link consoleErrorReporter} is the honest default.
|
|
12
|
+
*/
|
|
13
|
+
interface ContentIrErrorReport {
|
|
14
|
+
/** Always `"content-ir"` — hosts key their capture stores on it. */
|
|
15
|
+
source: "content-ir";
|
|
16
|
+
message: string;
|
|
17
|
+
name?: string;
|
|
18
|
+
stack?: string;
|
|
19
|
+
/** Free-form grouping key (the host's `relation`), e.g. `"partial-kind"`. */
|
|
20
|
+
relation?: string;
|
|
21
|
+
raw?: unknown;
|
|
22
|
+
}
|
|
23
|
+
type ContentIrErrorReporter = (report: ContentIrErrorReport) => void;
|
|
24
|
+
/** The default when a host binds nothing: never silent. */
|
|
25
|
+
declare const consoleErrorReporter: ContentIrErrorReporter;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* The (kind, platform, role) → component vocabulary — the Shape System's
|
|
29
|
+
* resolver contract (rulings R1 + R6), stated once for every UI.
|
|
30
|
+
*
|
|
31
|
+
* Cross-repo system-of-record:
|
|
32
|
+
* `common-docs/systems/content-ir-twin/FEATURE.md` (package boundary) and
|
|
33
|
+
* `matrx-frontend/features/content-ir/docs/SHAPE_SYSTEM.md` (the semantics).
|
|
34
|
+
*
|
|
35
|
+
* Nothing here knows where a row comes from. A host supplies rows from
|
|
36
|
+
* `content_ir.kind_component` (Supabase, a REST call, a fixture); the resolver
|
|
37
|
+
* only knows the shape.
|
|
38
|
+
*/
|
|
39
|
+
/** JSON object, restated locally so this package depends on no host type. */
|
|
40
|
+
type JsonObject = Record<string, unknown>;
|
|
41
|
+
/**
|
|
42
|
+
* Which face of the shape a component draws.
|
|
43
|
+
*
|
|
44
|
+
* - `output` — the shape's finished value, the component a reader sees.
|
|
45
|
+
* - `input` — the authoring form for a value of this shape.
|
|
46
|
+
* - `loading` — the shape's LOADING face: what renders from the instant the
|
|
47
|
+
* kind is identified until its output component has a renderable frame.
|
|
48
|
+
* Authored per kind like any other component and fed the region's partial
|
|
49
|
+
* value each frame, so it can PERFORM the arrival (surface real text as it
|
|
50
|
+
* lands) instead of drawing a shapeless skeleton. Optional: a kind with no
|
|
51
|
+
* `loading` component falls back to the host's loading library.
|
|
52
|
+
*/
|
|
53
|
+
type ComponentRole = "output" | "input" | "loading";
|
|
54
|
+
/** The resolver's answer for one (kind, platform, role). */
|
|
55
|
+
interface ComponentResolution {
|
|
56
|
+
/** The component key the renderer routes on (e.g. "flashcards"). */
|
|
57
|
+
componentKey: string;
|
|
58
|
+
source: string;
|
|
59
|
+
config: JsonObject;
|
|
60
|
+
/**
|
|
61
|
+
* Render-trust verdict (R6). Compiled entries are always active (trusted at
|
|
62
|
+
* bootstrap); DB rows carry their own `is_active`.
|
|
63
|
+
*/
|
|
64
|
+
isActive: boolean;
|
|
65
|
+
/** Which tier produced this answer — the verification hook's `by`. */
|
|
66
|
+
resolvedBy: "compiled" | "db";
|
|
67
|
+
componentSource: string | null;
|
|
68
|
+
propsTransform: string | null;
|
|
69
|
+
/**
|
|
70
|
+
* TRUE when the row owns a real component body — even if `componentSource`
|
|
71
|
+
* is null because the host's warm list is body-less and the cold fetch has
|
|
72
|
+
* not landed it yet. THE routing gate: `routeToDbComponent` re-types on
|
|
73
|
+
* this flag, never on body presence, so a body-less row still routes and
|
|
74
|
+
* the renderer fetches/compiles the body lazily.
|
|
75
|
+
*/
|
|
76
|
+
hasComponentSource: boolean;
|
|
77
|
+
pinnedKindVersion: number | null;
|
|
78
|
+
/** The db row's `updated_at` — the compile-cache staleness key. */
|
|
79
|
+
updatedAt: string | null;
|
|
80
|
+
createdBy: string | null;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* The read side of a component resolver, as the render layer consumes it.
|
|
84
|
+
* The package ships {@link ComponentResolver}; a host with its own resolver
|
|
85
|
+
* only has to satisfy this.
|
|
86
|
+
*/
|
|
87
|
+
interface ComponentResolutionSource {
|
|
88
|
+
/** Synchronous — the render seam's per-block call. */
|
|
89
|
+
resolve(kind: string, platform: string, role: ComponentRole): ComponentResolution | null;
|
|
90
|
+
/** Eager targeted fetch for one kind; fire-and-forget, never awaited on the hot path. */
|
|
91
|
+
requestComponent(kind: string, platform: string, role: ComponentRole): void;
|
|
92
|
+
/** One list fetch per session. */
|
|
93
|
+
ensureWarm(): Promise<void>;
|
|
94
|
+
/** Refresh-on-view; rate-limited and deduped by the implementation. */
|
|
95
|
+
refresh(maxAgeMs?: number): Promise<void>;
|
|
96
|
+
/** Monotonic tier version — has anything at all changed? */
|
|
97
|
+
getVersion(): number;
|
|
98
|
+
/** Monotonic per-kind version (+ wholesale epoch) — the granular repaint key. */
|
|
99
|
+
getKindVersion(kind: string): number;
|
|
100
|
+
subscribe(listener: () => void): () => void;
|
|
101
|
+
subscribeKind(kind: string, listener: () => void): () => void;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export { type ComponentResolution as C, type ContentIrErrorReporter as a, type ContentIrErrorReport as b, consoleErrorReporter as c, type ComponentResolutionSource as d };
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE SCREAM SEAM.
|
|
3
|
+
*
|
|
4
|
+
* Every recovery path in this package is loud: a defective component row, a
|
|
5
|
+
* failed resolver load, a kind whose component throws on a provisional value.
|
|
6
|
+
* The package refuses to own where those screams land — matrx-frontend routes
|
|
7
|
+
* them to the Error Inspector, the dashboard to its own log, the extension to
|
|
8
|
+
* its background page. Each host binds one function.
|
|
9
|
+
*
|
|
10
|
+
* A host that binds a no-op has chosen silence, which is a defect in itself;
|
|
11
|
+
* {@link consoleErrorReporter} is the honest default.
|
|
12
|
+
*/
|
|
13
|
+
interface ContentIrErrorReport {
|
|
14
|
+
/** Always `"content-ir"` — hosts key their capture stores on it. */
|
|
15
|
+
source: "content-ir";
|
|
16
|
+
message: string;
|
|
17
|
+
name?: string;
|
|
18
|
+
stack?: string;
|
|
19
|
+
/** Free-form grouping key (the host's `relation`), e.g. `"partial-kind"`. */
|
|
20
|
+
relation?: string;
|
|
21
|
+
raw?: unknown;
|
|
22
|
+
}
|
|
23
|
+
type ContentIrErrorReporter = (report: ContentIrErrorReport) => void;
|
|
24
|
+
/** The default when a host binds nothing: never silent. */
|
|
25
|
+
declare const consoleErrorReporter: ContentIrErrorReporter;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* The (kind, platform, role) → component vocabulary — the Shape System's
|
|
29
|
+
* resolver contract (rulings R1 + R6), stated once for every UI.
|
|
30
|
+
*
|
|
31
|
+
* Cross-repo system-of-record:
|
|
32
|
+
* `common-docs/systems/content-ir-twin/FEATURE.md` (package boundary) and
|
|
33
|
+
* `matrx-frontend/features/content-ir/docs/SHAPE_SYSTEM.md` (the semantics).
|
|
34
|
+
*
|
|
35
|
+
* Nothing here knows where a row comes from. A host supplies rows from
|
|
36
|
+
* `content_ir.kind_component` (Supabase, a REST call, a fixture); the resolver
|
|
37
|
+
* only knows the shape.
|
|
38
|
+
*/
|
|
39
|
+
/** JSON object, restated locally so this package depends on no host type. */
|
|
40
|
+
type JsonObject = Record<string, unknown>;
|
|
41
|
+
/**
|
|
42
|
+
* Which face of the shape a component draws.
|
|
43
|
+
*
|
|
44
|
+
* - `output` — the shape's finished value, the component a reader sees.
|
|
45
|
+
* - `input` — the authoring form for a value of this shape.
|
|
46
|
+
* - `loading` — the shape's LOADING face: what renders from the instant the
|
|
47
|
+
* kind is identified until its output component has a renderable frame.
|
|
48
|
+
* Authored per kind like any other component and fed the region's partial
|
|
49
|
+
* value each frame, so it can PERFORM the arrival (surface real text as it
|
|
50
|
+
* lands) instead of drawing a shapeless skeleton. Optional: a kind with no
|
|
51
|
+
* `loading` component falls back to the host's loading library.
|
|
52
|
+
*/
|
|
53
|
+
type ComponentRole = "output" | "input" | "loading";
|
|
54
|
+
/**
|
|
55
|
+
* One `content_ir.kind_component` row, projected to exactly what rendering
|
|
56
|
+
* needs. Hosts map their own query result onto this.
|
|
57
|
+
*/
|
|
58
|
+
interface KindComponentRow {
|
|
59
|
+
kind: string;
|
|
60
|
+
platform: string;
|
|
61
|
+
role: ComponentRole;
|
|
62
|
+
componentKey: string;
|
|
63
|
+
/** `source` column vocabulary: "bundled" | "db" (db = web sandbox only). */
|
|
64
|
+
source: string;
|
|
65
|
+
config: JsonObject;
|
|
66
|
+
isActive: boolean;
|
|
67
|
+
componentSource: string | null;
|
|
68
|
+
propsTransform: string | null;
|
|
69
|
+
/**
|
|
70
|
+
* Whether the row carries a real `component_source` body — supplied by the
|
|
71
|
+
* host when its warm list is BODY-LESS (the lazy design: metadata travels
|
|
72
|
+
* on the list, the body arrives per kind via the cold fetch). Omitted →
|
|
73
|
+
* derived from `componentSource` itself, so eager hosts change nothing.
|
|
74
|
+
*/
|
|
75
|
+
hasComponentSource?: boolean;
|
|
76
|
+
pinnedKindVersion: number | null;
|
|
77
|
+
updatedAt: string | null;
|
|
78
|
+
createdBy: string | null;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* One COMPILED bootstrap entry — the trusted-at-boot floor a host ships in its
|
|
82
|
+
* bundle, available synchronously from the first streamed byte.
|
|
83
|
+
*/
|
|
84
|
+
interface SystemComponentEntry {
|
|
85
|
+
kind: string;
|
|
86
|
+
platform: string;
|
|
87
|
+
role: ComponentRole;
|
|
88
|
+
componentKey: string;
|
|
89
|
+
source: string;
|
|
90
|
+
config: JsonObject;
|
|
91
|
+
}
|
|
92
|
+
/** The resolver's answer for one (kind, platform, role). */
|
|
93
|
+
interface ComponentResolution {
|
|
94
|
+
/** The component key the renderer routes on (e.g. "flashcards"). */
|
|
95
|
+
componentKey: string;
|
|
96
|
+
source: string;
|
|
97
|
+
config: JsonObject;
|
|
98
|
+
/**
|
|
99
|
+
* Render-trust verdict (R6). Compiled entries are always active (trusted at
|
|
100
|
+
* bootstrap); DB rows carry their own `is_active`.
|
|
101
|
+
*/
|
|
102
|
+
isActive: boolean;
|
|
103
|
+
/** Which tier produced this answer — the verification hook's `by`. */
|
|
104
|
+
resolvedBy: "compiled" | "db";
|
|
105
|
+
componentSource: string | null;
|
|
106
|
+
propsTransform: string | null;
|
|
107
|
+
/**
|
|
108
|
+
* TRUE when the row owns a real component body — even if `componentSource`
|
|
109
|
+
* is null because the host's warm list is body-less and the cold fetch has
|
|
110
|
+
* not landed it yet. THE routing gate: `routeToDbComponent` re-types on
|
|
111
|
+
* this flag, never on body presence, so a body-less row still routes and
|
|
112
|
+
* the renderer fetches/compiles the body lazily.
|
|
113
|
+
*/
|
|
114
|
+
hasComponentSource: boolean;
|
|
115
|
+
pinnedKindVersion: number | null;
|
|
116
|
+
/** The db row's `updated_at` — the compile-cache staleness key. */
|
|
117
|
+
updatedAt: string | null;
|
|
118
|
+
createdBy: string | null;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* The read side of a component resolver, as the render layer consumes it.
|
|
122
|
+
* The package ships {@link ComponentResolver}; a host with its own resolver
|
|
123
|
+
* only has to satisfy this.
|
|
124
|
+
*/
|
|
125
|
+
interface ComponentResolutionSource {
|
|
126
|
+
/** Synchronous — the render seam's per-block call. */
|
|
127
|
+
resolve(kind: string, platform: string, role: ComponentRole): ComponentResolution | null;
|
|
128
|
+
/** Eager targeted fetch for one kind; fire-and-forget, never awaited on the hot path. */
|
|
129
|
+
requestComponent(kind: string, platform: string, role: ComponentRole): void;
|
|
130
|
+
/** One list fetch per session. */
|
|
131
|
+
ensureWarm(): Promise<void>;
|
|
132
|
+
/** Refresh-on-view; rate-limited and deduped by the implementation. */
|
|
133
|
+
refresh(maxAgeMs?: number): Promise<void>;
|
|
134
|
+
/** Monotonic tier version — has anything at all changed? */
|
|
135
|
+
getVersion(): number;
|
|
136
|
+
/** Monotonic per-kind version (+ wholesale epoch) — the granular repaint key. */
|
|
137
|
+
getKindVersion(kind: string): number;
|
|
138
|
+
subscribe(listener: () => void): () => void;
|
|
139
|
+
subscribeKind(kind: string, listener: () => void): () => void;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export { type ComponentResolutionSource as C, type JsonObject as J, type KindComponentRow as K, type SystemComponentEntry as S, type ComponentResolution as a, type ContentIrErrorReporter as b, type ComponentRole as c, type ContentIrErrorReport as d, consoleErrorReporter as e };
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE SCREAM SEAM.
|
|
3
|
+
*
|
|
4
|
+
* Every recovery path in this package is loud: a defective component row, a
|
|
5
|
+
* failed resolver load, a kind whose component throws on a provisional value.
|
|
6
|
+
* The package refuses to own where those screams land — matrx-frontend routes
|
|
7
|
+
* them to the Error Inspector, the dashboard to its own log, the extension to
|
|
8
|
+
* its background page. Each host binds one function.
|
|
9
|
+
*
|
|
10
|
+
* A host that binds a no-op has chosen silence, which is a defect in itself;
|
|
11
|
+
* {@link consoleErrorReporter} is the honest default.
|
|
12
|
+
*/
|
|
13
|
+
interface ContentIrErrorReport {
|
|
14
|
+
/** Always `"content-ir"` — hosts key their capture stores on it. */
|
|
15
|
+
source: "content-ir";
|
|
16
|
+
message: string;
|
|
17
|
+
name?: string;
|
|
18
|
+
stack?: string;
|
|
19
|
+
/** Free-form grouping key (the host's `relation`), e.g. `"partial-kind"`. */
|
|
20
|
+
relation?: string;
|
|
21
|
+
raw?: unknown;
|
|
22
|
+
}
|
|
23
|
+
type ContentIrErrorReporter = (report: ContentIrErrorReport) => void;
|
|
24
|
+
/** The default when a host binds nothing: never silent. */
|
|
25
|
+
declare const consoleErrorReporter: ContentIrErrorReporter;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* The (kind, platform, role) → component vocabulary — the Shape System's
|
|
29
|
+
* resolver contract (rulings R1 + R6), stated once for every UI.
|
|
30
|
+
*
|
|
31
|
+
* Cross-repo system-of-record:
|
|
32
|
+
* `common-docs/systems/content-ir-twin/FEATURE.md` (package boundary) and
|
|
33
|
+
* `matrx-frontend/features/content-ir/docs/SHAPE_SYSTEM.md` (the semantics).
|
|
34
|
+
*
|
|
35
|
+
* Nothing here knows where a row comes from. A host supplies rows from
|
|
36
|
+
* `content_ir.kind_component` (Supabase, a REST call, a fixture); the resolver
|
|
37
|
+
* only knows the shape.
|
|
38
|
+
*/
|
|
39
|
+
/** JSON object, restated locally so this package depends on no host type. */
|
|
40
|
+
type JsonObject = Record<string, unknown>;
|
|
41
|
+
/**
|
|
42
|
+
* Which face of the shape a component draws.
|
|
43
|
+
*
|
|
44
|
+
* - `output` — the shape's finished value, the component a reader sees.
|
|
45
|
+
* - `input` — the authoring form for a value of this shape.
|
|
46
|
+
* - `loading` — the shape's LOADING face: what renders from the instant the
|
|
47
|
+
* kind is identified until its output component has a renderable frame.
|
|
48
|
+
* Authored per kind like any other component and fed the region's partial
|
|
49
|
+
* value each frame, so it can PERFORM the arrival (surface real text as it
|
|
50
|
+
* lands) instead of drawing a shapeless skeleton. Optional: a kind with no
|
|
51
|
+
* `loading` component falls back to the host's loading library.
|
|
52
|
+
*/
|
|
53
|
+
type ComponentRole = "output" | "input" | "loading";
|
|
54
|
+
/**
|
|
55
|
+
* One `content_ir.kind_component` row, projected to exactly what rendering
|
|
56
|
+
* needs. Hosts map their own query result onto this.
|
|
57
|
+
*/
|
|
58
|
+
interface KindComponentRow {
|
|
59
|
+
kind: string;
|
|
60
|
+
platform: string;
|
|
61
|
+
role: ComponentRole;
|
|
62
|
+
componentKey: string;
|
|
63
|
+
/** `source` column vocabulary: "bundled" | "db" (db = web sandbox only). */
|
|
64
|
+
source: string;
|
|
65
|
+
config: JsonObject;
|
|
66
|
+
isActive: boolean;
|
|
67
|
+
componentSource: string | null;
|
|
68
|
+
propsTransform: string | null;
|
|
69
|
+
/**
|
|
70
|
+
* Whether the row carries a real `component_source` body — supplied by the
|
|
71
|
+
* host when its warm list is BODY-LESS (the lazy design: metadata travels
|
|
72
|
+
* on the list, the body arrives per kind via the cold fetch). Omitted →
|
|
73
|
+
* derived from `componentSource` itself, so eager hosts change nothing.
|
|
74
|
+
*/
|
|
75
|
+
hasComponentSource?: boolean;
|
|
76
|
+
pinnedKindVersion: number | null;
|
|
77
|
+
updatedAt: string | null;
|
|
78
|
+
createdBy: string | null;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* One COMPILED bootstrap entry — the trusted-at-boot floor a host ships in its
|
|
82
|
+
* bundle, available synchronously from the first streamed byte.
|
|
83
|
+
*/
|
|
84
|
+
interface SystemComponentEntry {
|
|
85
|
+
kind: string;
|
|
86
|
+
platform: string;
|
|
87
|
+
role: ComponentRole;
|
|
88
|
+
componentKey: string;
|
|
89
|
+
source: string;
|
|
90
|
+
config: JsonObject;
|
|
91
|
+
}
|
|
92
|
+
/** The resolver's answer for one (kind, platform, role). */
|
|
93
|
+
interface ComponentResolution {
|
|
94
|
+
/** The component key the renderer routes on (e.g. "flashcards"). */
|
|
95
|
+
componentKey: string;
|
|
96
|
+
source: string;
|
|
97
|
+
config: JsonObject;
|
|
98
|
+
/**
|
|
99
|
+
* Render-trust verdict (R6). Compiled entries are always active (trusted at
|
|
100
|
+
* bootstrap); DB rows carry their own `is_active`.
|
|
101
|
+
*/
|
|
102
|
+
isActive: boolean;
|
|
103
|
+
/** Which tier produced this answer — the verification hook's `by`. */
|
|
104
|
+
resolvedBy: "compiled" | "db";
|
|
105
|
+
componentSource: string | null;
|
|
106
|
+
propsTransform: string | null;
|
|
107
|
+
/**
|
|
108
|
+
* TRUE when the row owns a real component body — even if `componentSource`
|
|
109
|
+
* is null because the host's warm list is body-less and the cold fetch has
|
|
110
|
+
* not landed it yet. THE routing gate: `routeToDbComponent` re-types on
|
|
111
|
+
* this flag, never on body presence, so a body-less row still routes and
|
|
112
|
+
* the renderer fetches/compiles the body lazily.
|
|
113
|
+
*/
|
|
114
|
+
hasComponentSource: boolean;
|
|
115
|
+
pinnedKindVersion: number | null;
|
|
116
|
+
/** The db row's `updated_at` — the compile-cache staleness key. */
|
|
117
|
+
updatedAt: string | null;
|
|
118
|
+
createdBy: string | null;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* The read side of a component resolver, as the render layer consumes it.
|
|
122
|
+
* The package ships {@link ComponentResolver}; a host with its own resolver
|
|
123
|
+
* only has to satisfy this.
|
|
124
|
+
*/
|
|
125
|
+
interface ComponentResolutionSource {
|
|
126
|
+
/** Synchronous — the render seam's per-block call. */
|
|
127
|
+
resolve(kind: string, platform: string, role: ComponentRole): ComponentResolution | null;
|
|
128
|
+
/** Eager targeted fetch for one kind; fire-and-forget, never awaited on the hot path. */
|
|
129
|
+
requestComponent(kind: string, platform: string, role: ComponentRole): void;
|
|
130
|
+
/** One list fetch per session. */
|
|
131
|
+
ensureWarm(): Promise<void>;
|
|
132
|
+
/** Refresh-on-view; rate-limited and deduped by the implementation. */
|
|
133
|
+
refresh(maxAgeMs?: number): Promise<void>;
|
|
134
|
+
/** Monotonic tier version — has anything at all changed? */
|
|
135
|
+
getVersion(): number;
|
|
136
|
+
/** Monotonic per-kind version (+ wholesale epoch) — the granular repaint key. */
|
|
137
|
+
getKindVersion(kind: string): number;
|
|
138
|
+
subscribe(listener: () => void): () => void;
|
|
139
|
+
subscribeKind(kind: string, listener: () => void): () => void;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export { type ComponentResolutionSource as C, type JsonObject as J, type KindComponentRow as K, type SystemComponentEntry as S, type ComponentResolution as a, type ContentIrErrorReporter as b, type ComponentRole as c, type ContentIrErrorReport as d, consoleErrorReporter as e };
|