@scenetest/dashboard 0.11.0 → 0.12.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.
Files changed (77) hide show
  1. package/README.md +87 -35
  2. package/dist/app.d.ts +10 -7
  3. package/dist/app.d.ts.map +1 -1
  4. package/dist/app.js +12 -130
  5. package/dist/app.js.map +1 -1
  6. package/dist/collections/index.d.ts +19 -0
  7. package/dist/collections/index.d.ts.map +1 -0
  8. package/dist/collections/index.js +18 -0
  9. package/dist/collections/index.js.map +1 -0
  10. package/dist/collections/options.d.ts +29 -0
  11. package/dist/collections/options.d.ts.map +1 -0
  12. package/dist/collections/options.js +68 -0
  13. package/dist/collections/options.js.map +1 -0
  14. package/dist/collections/projections.d.ts +117 -0
  15. package/dist/collections/projections.d.ts.map +1 -0
  16. package/dist/collections/projections.js +228 -0
  17. package/dist/collections/projections.js.map +1 -0
  18. package/dist/collections/source.d.ts +32 -0
  19. package/dist/collections/source.d.ts.map +1 -0
  20. package/dist/collections/source.js +84 -0
  21. package/dist/collections/source.js.map +1 -0
  22. package/dist/collections/types.d.ts +87 -0
  23. package/dist/collections/types.d.ts.map +1 -0
  24. package/dist/collections/types.js +2 -0
  25. package/dist/collections/types.js.map +1 -0
  26. package/dist/dashboard.d.ts +20 -0
  27. package/dist/dashboard.d.ts.map +1 -0
  28. package/dist/dashboard.js +114 -0
  29. package/dist/dashboard.js.map +1 -0
  30. package/dist/dev-transport.d.ts +3 -3
  31. package/dist/dev-transport.d.ts.map +1 -1
  32. package/dist/dev-transport.js +3 -7
  33. package/dist/dev-transport.js.map +1 -1
  34. package/dist/index.d.ts +6 -3
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +4 -2
  37. package/dist/index.js.map +1 -1
  38. package/dist/runner.d.ts +8 -0
  39. package/dist/runner.d.ts.map +1 -0
  40. package/dist/runner.js +249 -0
  41. package/dist/runner.js.map +1 -0
  42. package/dist/select-helpers.d.ts +50 -0
  43. package/dist/select-helpers.d.ts.map +1 -0
  44. package/dist/select-helpers.js +48 -0
  45. package/dist/select-helpers.js.map +1 -0
  46. package/dist/select-runner.d.ts +55 -0
  47. package/dist/select-runner.d.ts.map +1 -0
  48. package/dist/select-runner.js +108 -0
  49. package/dist/select-runner.js.map +1 -0
  50. package/dist/select-waterfall.d.ts +12 -0
  51. package/dist/select-waterfall.d.ts.map +1 -0
  52. package/dist/select-waterfall.js +79 -0
  53. package/dist/select-waterfall.js.map +1 -0
  54. package/dist/style.css +878 -0
  55. package/dist/types.d.ts +6 -20
  56. package/dist/types.d.ts.map +1 -1
  57. package/dist/use-live-query.d.ts +28 -0
  58. package/dist/use-live-query.d.ts.map +1 -0
  59. package/dist/use-live-query.js +25 -0
  60. package/dist/use-live-query.js.map +1 -0
  61. package/dist/use-run-slice.d.ts +25 -0
  62. package/dist/use-run-slice.d.ts.map +1 -0
  63. package/dist/use-run-slice.js +48 -0
  64. package/dist/use-run-slice.js.map +1 -0
  65. package/package.json +10 -5
  66. package/dist/mount.d.ts +0 -14
  67. package/dist/mount.d.ts.map +0 -1
  68. package/dist/mount.js +0 -50
  69. package/dist/mount.js.map +0 -1
  70. package/dist/store.d.ts +0 -19
  71. package/dist/store.d.ts.map +0 -1
  72. package/dist/store.js +0 -164
  73. package/dist/store.js.map +0 -1
  74. package/dist/styles.d.ts +0 -10
  75. package/dist/styles.d.ts.map +0 -1
  76. package/dist/styles.js +0 -152
  77. package/dist/styles.js.map +0 -1
package/README.md CHANGED
@@ -1,64 +1,116 @@
1
1
  # @scenetest/dashboard
2
2
 
3
- The scenetest dashboard as a mountable widget. The same Preact UI renders the
4
- live run in dev (inside the Vite plugin's `/__scenetest` page) and in
5
- scenetest-cloud (a Worker-served page) — the host supplies a DOM element and a
6
- transport adapter, nothing else.
3
+ The scenetest dashboard as a **Preact component**. The same UI renders the live
4
+ run in dev (inside the Vite plugin's `/__scenetest` page) and in scenetest-cloud
5
+ (a Worker-served page) — the host supplies a transport adapter, nothing else.
7
6
 
8
- ```ts
9
- import { mountDashboard, createDevTransport } from '@scenetest/dashboard'
7
+ ```tsx
8
+ import { render } from 'preact'
9
+ import { Dashboard, createDevTransport } from '@scenetest/dashboard'
10
+ import '@scenetest/dashboard/style.css'
10
11
 
11
- const handle = mountDashboard(document.getElementById('root'), {
12
- transport: createDevTransport(),
13
- })
14
- // later: handle.unmount()
12
+ render(<Dashboard transport={createDevTransport()} />, document.getElementById('root'))
15
13
  ```
16
14
 
17
- The widget renders into a **shadow root** with its own styles and fonts, so it
18
- drops into any host without leaking styles in either direction and without the
19
- host using Preact.
15
+ It's a plain light-DOM Preact component no shadow root. Styles ship as a
16
+ stylesheet the host imports (`@scenetest/dashboard/style.css`), scoped under the
17
+ `.scenetest-dashboard` root so they don't leak. Both hosts are Preact, so they
18
+ render `<Dashboard>` directly; there's no imperative mount wrapper.
20
19
 
21
20
  ## Transport adapter
22
21
 
23
- The only thing that differs between dev and cloud. The widget calls the
24
- adapter to fetch a snapshot and subscribe to live events, and pushes user
25
- actions back as protocol commands:
22
+ The only thing that differs between dev and cloud. The dashboard subscribes to
23
+ the run stream and pushes user actions back as protocol commands:
26
24
 
27
25
  ```ts
28
26
  interface Transport {
29
- fetchState(): Promise<RunEvent[]>
30
27
  subscribe(onEvent: (e: RunEvent) => void, onStatus?: (s: ConnectionStatus) => void): () => void
31
28
  sendCommand(command: Command): Promise<void>
32
29
  }
33
30
  ```
34
31
 
35
32
  Events and commands are the `@scenetest/protocol` vocabulary. `createDevTransport()`
36
- speaks to the Vite middleware (fetch + SSE); a cloud adapter speaks to the
37
- worker (fetch + WebSocket). History may arrive through either `fetchState`
38
- (snapshot) or the initial `subscribe` burst the store folds both the same
39
- way, so a transport picks whichever its backend makes natural (SSE replays the
40
- buffer through `subscribe`, so the dev adapter's `fetchState` returns empty).
33
+ speaks to the Vite middleware (SSE); a cloud adapter speaks to the worker
34
+ (WebSocket). History and live events both flow through `subscribe`: the
35
+ transport replays the run so far on connect (SSE replays its buffer; the cloud
36
+ WebSocket replays from a `sinceSeq`) and then streams live ones the read model
37
+ folds both the same way, so there's no separate snapshot fetch.
41
38
 
42
39
  ## Theming
43
40
 
44
- The widget's only theming surface is a small set of CSS custom properties,
45
- passed as `theme` and applied to the shadow host:
41
+ The only theming surface is a small set of CSS custom properties, passed as
42
+ `theme` and applied as inline `--st-*` variables on the `.scenetest-dashboard`
43
+ root:
46
44
 
47
- ```ts
48
- mountDashboard(el, {
49
- transport,
50
- theme: { bg: '#0b0d12', accent: '#7c93ff', font: 'IBM Plex Mono, monospace', fontSize: '12px' },
51
- })
45
+ ```tsx
46
+ <Dashboard
47
+ transport={transport}
48
+ theme={{ bg: '#0b0d12', accent: '#7c93ff', font: 'IBM Plex Mono, monospace', fontSize: '12px' }}
49
+ />
52
50
  ```
53
51
 
54
52
  These map to `--st-bg`, `--st-accent`, `--st-font`, `--st-font-size`. Nothing
55
- else is reachable; they are versioned with the widget, like the wire protocol.
53
+ else is reachable; they are versioned with the component, like the wire protocol.
56
54
 
57
- ## Store
55
+ ## Selectors
58
56
 
59
- `mountDashboard` is the entry point, but the event-folding logic is exported
60
- separately and is DOM-free — useful for tests, SSR, or computing a rollup:
57
+ `<Dashboard>` reads the run stream through the collections read model (below),
58
+ but the view-projection logic is exported separately and is DOM-free — useful
59
+ for tests, SSR, or computing a rollup:
61
60
 
62
- - `foldEvents(events)` / `applyEvent(state, event)` — reduce protocol events into `DashboardState`
63
- - `initialState()`, `completedSceneCount(state)`, `withConnection(state, status)`
61
+ - `selectWaterfall(slice)` / `selectSnapshot(slice)` — project a latest-run `RunSlice` into the Waterfall / Runner view shapes
62
+ - `mapReportToSnapshot(report)` adapt a past-run JSON report into the Runner shape
63
+ - `completedSceneCount(state)` — count of finished scenes
64
64
  - `sceneSummary(scene)` — the plain-text "copy failures" summary
65
+
66
+ ## Collections (`@scenetest/dashboard/collections`)
67
+
68
+ A read-only [TanStack DB](https://tanstack.com/db) read model over the run
69
+ stream — **the store `<Dashboard>` itself reads from** (dev and cloud), with
70
+ **live queries** (filter / aggregate / sort, recomputed incrementally). It's
71
+ also a subpath export so a cloud consumer can build the same collections with
72
+ **its own** `@tanstack/db` instance (e.g. fed by a Durable Object's WebSocket).
73
+
74
+ `createRunSource(transport)` wraps the transport as one shared, fan-out stream;
75
+ `runCollectionOptions({ source, projection })` returns a `CollectionConfig` you
76
+ pass to **your own** `createCollection` — so the collection is built by the same
77
+ `@tanstack/db` instance your `useLiveQuery` uses. Several collections ride
78
+ **one** connection ("subscribe to the stream, attach the tables"), and each is
79
+ a server-owned replica: the projection is the sole writer, so client
80
+ `.insert()`/`.update()` throws.
81
+
82
+ ```ts
83
+ import { createCollection, count } from '@tanstack/db'
84
+ import { useLiveQuery } from '@tanstack/react-db'
85
+ import { createDevTransport } from '@scenetest/dashboard'
86
+ import { createRunSource, runCollectionOptions, scenesProjection, assertionsProjection } from '@scenetest/dashboard/collections'
87
+
88
+ const source = createRunSource(createDevTransport()) // one connection…
89
+ const scenes = createCollection(runCollectionOptions({ source, projection: scenesProjection() }))
90
+ const assertions = createCollection(runCollectionOptions({ source, projection: assertionsProjection() })) // …two tables
91
+
92
+ const { data } = useLiveQuery((q) =>
93
+ q.from({ s: scenes }).groupBy(({ s }) => s.status)
94
+ .select(({ s }) => ({ status: s.status, n: count(s.id) }))
95
+ )
96
+ // on teardown: source.close()
97
+ ```
98
+
99
+ A projection speaks a tiny `RowOp` vocabulary (`insert`/`update`/`delete`/`reset`),
100
+ so `scenesProjection()` / `assertionsProjection()` / `runsProjection()` are
101
+ testable without TanStack DB at all. `@tanstack/db` is a **runtime dependency**
102
+ of the package (the dashboard calls `createCollection` to build its store), but
103
+ this `./collections` subpath itself only `import type`s `CollectionConfig` — so
104
+ a cloud consumer can build the collections with its own `@tanstack/db` instance
105
+ (one instance, so its `useLiveQuery` can join across them).
106
+
107
+ **Multi-run.** Rows are partitioned by `runId` (the `run:start` timestamp), so
108
+ one collection holds a whole PR's history — a new `run:start` opens a new
109
+ partition rather than truncating. `runsProjection()` gives one row per run
110
+ (status, counts, duration), which is the run picker / "most recent" rollup /
111
+ flaky surface as plain live queries; the live timeline is `where runId = <latest>`.
112
+ See `docs/public/design/unified-console.md`.
113
+
114
+ History/ordering/de-duplication remain the transport's contract (SSE replay in
115
+ dev, WebSocket `sinceSeq` replay in cloud); the source just consumes `onEvent`
116
+ and resets its replay buffer on `run:start`.
package/dist/app.d.ts CHANGED
@@ -1,12 +1,15 @@
1
- import type { Scene, Transport } from './types.js';
1
+ import type { Command } from '@scenetest/protocol';
2
+ import type { DashboardState, Scene } from './types.js';
2
3
  /**
3
- * The dashboard root. Owns the folded state, drives it from the transport,
4
- * and turns header controls into protocol commands. The same component
5
- * renders in dev and cloud only the injected `transport` differs.
4
+ * The Waterfall view the live timeline of actors and inline assertions. It's
5
+ * a pure view: the Dashboard root computes `state` from the shared read model
6
+ * (`selectWaterfall` over the collections) and passes it in, along with `send`
7
+ * for header controls. Same component renders in dev and cloud.
6
8
  */
7
- export declare function Dashboard({ transport }: {
8
- transport: Transport;
9
- }): import("preact").VNode<import("preact").Attributes> | import("preact").VNode<import("preact").Attributes>[];
9
+ export declare function Waterfall({ state, send }: {
10
+ state: DashboardState;
11
+ send: (c: Command) => void;
12
+ }): import("preact").JSX.Element;
10
13
  /** Build the plain-text "copy failures" summary, matching the original dashboard. */
11
14
  export declare function sceneSummary(scene: Scene): string;
12
15
  //# sourceMappingURL=app.d.ts.map
package/dist/app.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAoC,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAYpF;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,EAAE,SAAS,EAAE,EAAE;IAAE,SAAS,EAAE,SAAS,CAAA;CAAE,+GAoChE;AAiJD,qFAAqF;AACrF,wBAAgB,YAAY,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CA0BjD"}
1
+ {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAElD,OAAO,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAEvD;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;IAAE,KAAK,EAAE,cAAc,CAAC;IAAC,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,CAAA;CAAE,gCAkB/F;AAgJD,qFAAqF;AACrF,wBAAgB,YAAY,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CA0BjD"}
package/dist/app.js CHANGED
@@ -1,50 +1,14 @@
1
- import { h } from 'preact';
2
- import { useEffect, useReducer, useState } from 'preact/hooks';
3
- import htm from 'htm';
4
- import { applyEvent, completedSceneCount, initialState, withConnection } from './store.js';
5
- const html = htm.bind(h);
6
- function reducer(state, action) {
7
- return action.kind === 'event'
8
- ? applyEvent(state, action.event)
9
- : withConnection(state, action.status);
10
- }
1
+ import { jsx as _jsx, jsxs as _jsxs } from "preact/jsx-runtime";
2
+ import { useEffect, useState } from 'preact/hooks';
3
+ import { completedSceneCount } from './select-waterfall.js';
11
4
  /**
12
- * The dashboard root. Owns the folded state, drives it from the transport,
13
- * and turns header controls into protocol commands. The same component
14
- * renders in dev and cloud only the injected `transport` differs.
5
+ * The Waterfall view the live timeline of actors and inline assertions. It's
6
+ * a pure view: the Dashboard root computes `state` from the shared read model
7
+ * (`selectWaterfall` over the collections) and passes it in, along with `send`
8
+ * for header controls. Same component renders in dev and cloud.
15
9
  */
16
- export function Dashboard({ transport }) {
17
- const [state, dispatch] = useReducer(reducer, undefined, initialState);
18
- useEffect(() => {
19
- let alive = true;
20
- transport.fetchState().then((events) => {
21
- if (!alive)
22
- return;
23
- for (const event of events)
24
- dispatch({ kind: 'event', event });
25
- });
26
- const unsubscribe = transport.subscribe((event) => dispatch({ kind: 'event', event }), (status) => dispatch({ kind: 'status', status }));
27
- return () => {
28
- alive = false;
29
- unsubscribe();
30
- };
31
- }, [transport]);
32
- const send = (command) => {
33
- void transport.sendCommand(command);
34
- };
35
- return html `
36
- <div class="root">
37
- ${Header({ state, send })}
38
- <main>
39
- ${state.scenes.length === 0
40
- ? html `<div class="waiting">
41
- <h2>Waiting for scene run…</h2>
42
- <p>Run <code>scenetest</code> to see the live timeline here.</p>
43
- </div>`
44
- : state.scenes.map((scene, i) => SceneCard({ scene, index: i, send }))}
45
- </main>
46
- </div>
47
- `;
10
+ export function Waterfall({ state, send }) {
11
+ return (_jsxs("div", { class: "root", children: [_jsx(Header, { state: state, send: send }), _jsx("main", { children: state.scenes.length === 0 ? (_jsxs("div", { class: "waiting", children: [_jsx("h2", { children: "Waiting for scene run\u2026" }), _jsxs("p", { children: ["Run ", _jsx("code", { children: "scenetest" }), " to see the live timeline here."] })] })) : (state.scenes.map((scene) => _jsx(SceneCard, { scene: scene, send: send }, scene.name))) })] }));
48
12
  }
49
13
  function Header({ state, send }) {
50
14
  const [team, setTeam] = useState('');
@@ -70,40 +34,9 @@ function Header({ state, send }) {
70
34
  ? 'progress done'
71
35
  : 'progress';
72
36
  const replay = () => send({ type: 'run:replay', ...(team ? { team } : {}) });
73
- return html `
74
- <header class=${running ? 'running' : ''}>
75
- <h1><span class="logo">S</span> Scenetest Dashboard</h1>
76
- <button class="replay-all-btn" disabled=${running} onClick=${replay}>▶ Replay All</button>
77
- <label class="team-select-wrap">
78
- Team:
79
- <select
80
- value=${team}
81
- onChange=${(e) => setTeam(e.target.value)}
82
- >
83
- <option value="">all teams</option>
84
- ${state.teams.map((t) => html `<option value=${t}>${t}</option>`)}
85
- </select>
86
- </label>
87
- <button onClick=${() => send({ type: 'run:pause' })}>❚❚ Pause</button>
88
- <button class="stop-btn" onClick=${() => send({ type: 'run:stop' })}>■ Stop</button>
89
- <div class="spacer"></div>
90
- <div class="stats">
91
- <div class="stat"><span class="label">Scenes:</span><span class="value">${completed}/${state.sceneCount}</span></div>
92
- <div class="stat pass"><span class="label">Pass:</span><span class="value">${state.passCount}</span></div>
93
- <div class="stat fail"><span class="label">Fail:</span><span class="value">${state.failCount}</span></div>
94
- <div class="stat"><span class="label">Time:</span><span class="value">${elapsed}</span></div>
95
- <div
96
- class=${'conn ' + state.connection}
97
- title=${'SSE ' + state.connection}
98
- ></div>
99
- </div>
100
- ${state.sceneCount > 0
101
- ? html `<div class=${progressClass}><div class="progress-fill" style=${`width:${pct}%`}></div></div>`
102
- : null}
103
- </header>
104
- `;
37
+ return (_jsxs("header", { class: running ? 'running' : '', children: [_jsxs("h1", { children: [_jsx("span", { class: "logo", children: "S" }), " Scenetest Dashboard"] }), _jsx("button", { class: "replay-all-btn", disabled: running, onClick: replay, children: "\u25B6 Replay All" }), _jsxs("label", { class: "team-select-wrap", children: ["Team:", _jsxs("select", { value: team, onChange: (e) => setTeam(e.target.value), children: [_jsx("option", { value: "", children: "all teams" }), state.teams.map((t) => (_jsx("option", { value: t, children: t }, t)))] })] }), _jsx("button", { onClick: () => send({ type: 'run:pause' }), children: "\u275A\u275A Pause" }), _jsx("button", { class: "stop-btn", onClick: () => send({ type: 'run:stop' }), children: "\u25A0 Stop" }), _jsx("div", { class: "spacer" }), _jsxs("div", { class: "stats", children: [_jsxs("div", { class: "stat", children: [_jsx("span", { class: "label", children: "Scenes:" }), _jsxs("span", { class: "value", children: [completed, "/", state.sceneCount] })] }), _jsxs("div", { class: "stat pass", children: [_jsx("span", { class: "label", children: "Pass:" }), _jsx("span", { class: "value", children: state.passCount })] }), _jsxs("div", { class: "stat fail", children: [_jsx("span", { class: "label", children: "Fail:" }), _jsx("span", { class: "value", children: state.failCount })] }), _jsxs("div", { class: "stat", children: [_jsx("span", { class: "label", children: "Time:" }), _jsx("span", { class: "value", children: elapsed })] }), _jsx("div", { class: 'conn ' + state.connection, title: 'SSE ' + state.connection })] }), state.sceneCount > 0 ? (_jsx("div", { class: progressClass, children: _jsx("div", { class: "progress-fill", style: `width:${pct}%` }) })) : null] }));
105
38
  }
106
- function SceneCard({ scene, index, send, }) {
39
+ function SceneCard({ scene, send }) {
107
40
  const [copied, setCopied] = useState(false);
108
41
  const statusMark = scene.status === 'completed' ? '✓' : scene.status === 'running' ? '◷' : '✗';
109
42
  const copy = () => {
@@ -111,58 +44,7 @@ function SceneCard({ scene, index, send, }) {
111
44
  setCopied(true);
112
45
  setTimeout(() => setCopied(false), 1200);
113
46
  };
114
- return html `
115
- <div class=${'scene ' + (scene.status === 'failed' || scene.status === 'timeout' ? 'failed' : '')}>
116
- <div class="scene-head">
117
- <span class=${'scene-status ' + scene.status}>${statusMark}</span>
118
- <span class="scene-name">${scene.name}</span>
119
- ${scene.file ? html `<span class="scene-file">${scene.file}</span>` : null}
120
- ${scene.team?.name ? html `<span class="scene-team">${scene.team.name}</span>` : null}
121
- ${scene.duration != null ? html `<span class="scene-dur">${scene.duration}ms</span>` : null}
122
- <button
123
- class=${'copy-btn' + (copied ? ' copied' : '')}
124
- title="Copy scene summary"
125
- onClick=${copy}
126
- >
127
- ${copied ? '✓ Copied' : '⧉ Copy'}
128
- </button>
129
- ${scene.file
130
- ? html `<button
131
- class="copy-btn"
132
- onClick=${() => send({ type: 'run:replay', file: scene.file })}
133
- >▶ Replay</button>`
134
- : null}
135
- </div>
136
- <div class="lanes">
137
- ${scene.lanes.map((lane) => html `
138
- <div class="lane">
139
- <span class="lane-actor">${lane.actor}</span>
140
- <div class="lane-items">
141
- ${lane.items.map((item) => html `
142
- <span class=${'pill ' + item.status} title=${item.error ?? ''}>
143
- ${item.action}${item.target
144
- ? html `<span class="tgt"> ${item.target}</span>`
145
- : null}
146
- </span>
147
- `)}
148
- </div>
149
- </div>
150
- `)}
151
- </div>
152
- ${scene.assertions.length > 0
153
- ? html `<div class="assertions">
154
- ${scene.assertions.map((a) => html `
155
- <div class=${'assert ' + (a.result ? 'ok' : 'bad')}>
156
- <span class="mark">${a.result ? '✓' : '✗'}</span>
157
- ${a.actor ? html `<span class="who">[${a.actor}]</span>` : null}
158
- <span>${a.description}</span>
159
- </div>
160
- `)}
161
- </div>`
162
- : null}
163
- ${scene.error ? html `<div class="scene-error">${scene.error}</div>` : null}
164
- </div>
165
- `;
47
+ return (_jsxs("div", { class: 'scene ' + (scene.status === 'failed' || scene.status === 'timeout' ? 'failed' : ''), children: [_jsxs("div", { class: "scene-head", children: [_jsx("span", { class: 'scene-status ' + scene.status, children: statusMark }), _jsx("span", { class: "scene-name", children: scene.name }), scene.file ? _jsx("span", { class: "scene-file", children: scene.file }) : null, scene.team?.name ? _jsx("span", { class: "scene-team", children: scene.team.name }) : null, scene.duration != null ? _jsxs("span", { class: "scene-dur", children: [scene.duration, "ms"] }) : null, _jsx("button", { class: 'copy-btn' + (copied ? ' copied' : ''), title: "Copy scene summary", onClick: copy, children: copied ? '✓ Copied' : '⧉ Copy' }), scene.file ? (_jsx("button", { class: "copy-btn", onClick: () => send({ type: 'run:replay', file: scene.file }), children: "\u25B6 Replay" })) : null] }), _jsx("div", { class: "lanes", children: scene.lanes.map((lane) => (_jsxs("div", { class: "lane", children: [_jsx("span", { class: "lane-actor", children: lane.actor }), _jsx("div", { class: "lane-items", children: lane.items.map((item, i) => (_jsxs("span", { class: 'pill ' + item.status, title: item.error ?? '', children: [item.action, item.target ? _jsxs("span", { class: "tgt", children: [" ", item.target] }) : null] }, i))) })] }, lane.actor))) }), scene.assertions.length > 0 ? (_jsx("div", { class: "assertions", children: scene.assertions.map((a, i) => (_jsxs("div", { class: 'assert ' + (a.result ? 'ok' : 'bad'), children: [_jsx("span", { class: "mark", children: a.result ? '✓' : '✗' }), a.actor ? _jsxs("span", { class: "who", children: ["[", a.actor, "]"] }) : null, _jsx("span", { children: a.description })] }, i))) })) : null, scene.error ? _jsx("div", { class: "scene-error", children: scene.error }) : null] }));
166
48
  }
167
49
  /** Build the plain-text "copy failures" summary, matching the original dashboard. */
168
50
  export function sceneSummary(scene) {
package/dist/app.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAElD,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAA;AAG3D;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,EAAE,KAAK,EAAE,IAAI,EAAyD;IAC9F,OAAO,CACL,eAAK,KAAK,EAAC,MAAM,aACf,KAAC,MAAM,IAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,GAAI,EACpC,yBACG,KAAK,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAC3B,eAAK,KAAK,EAAC,SAAS,aAClB,uDAA+B,EAC/B,gCACM,uCAAsB,uCACxB,IACA,CACP,CAAC,CAAC,CAAC,CACF,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAC,SAAS,IAAkB,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,IAApC,KAAK,CAAC,IAAI,CAA8B,CAAC,CACtF,GACI,IACH,CACP,CAAA;AACH,CAAC;AAED,SAAS,MAAM,CAAC,EAAE,KAAK,EAAE,IAAI,EAAyD;IACpF,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAA;IACpC,MAAM,CAAC,EAAE,KAAK,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAA;IAC7B,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAA;IAE7B,qDAAqD;IACrD,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,OAAO;YAAE,OAAM;QACpB,MAAM,EAAE,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;QACtD,OAAO,GAAG,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,CAAA;IAChC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAA;IAEb,MAAM,SAAS,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAA;IAC5C,MAAM,OAAO,GACX,KAAK,CAAC,aAAa,IAAI,IAAI;QACzB,CAAC,CAAC,GAAG,KAAK,CAAC,aAAa,IAAI;QAC5B,CAAC,CAAC,KAAK,CAAC,YAAY;YAClB,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,YAAY,IAAI;YACxC,CAAC,CAAC,GAAG,CAAA;IAEX,MAAM,GAAG,GAAG,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,SAAS,GAAG,KAAK,CAAC,UAAU,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IACvF,MAAM,aAAa,GACjB,KAAK,CAAC,SAAS,GAAG,CAAC;QACjB,CAAC,CAAC,uBAAuB;QACzB,CAAC,CAAC,SAAS,KAAK,KAAK,CAAC,UAAU,IAAI,KAAK,CAAC,UAAU,GAAG,CAAC;YACtD,CAAC,CAAC,eAAe;YACjB,CAAC,CAAC,UAAU,CAAA;IAElB,MAAM,MAAM,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAA;IAE5E,OAAO,CACL,kBAAQ,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,aACrC,yBACE,eAAM,KAAK,EAAC,MAAM,kBAAS,4BACxB,EACL,iBAAQ,KAAK,EAAC,gBAAgB,EAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,kCAExD,EACT,iBAAO,KAAK,EAAC,kBAAkB,sBAE7B,kBAAQ,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAE,CAAC,CAAC,MAA4B,CAAC,KAAK,CAAC,aAClF,iBAAQ,KAAK,EAAC,EAAE,0BAAmB,EAClC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CACtB,iBAAgB,KAAK,EAAE,CAAC,YACrB,CAAC,IADS,CAAC,CAEL,CACV,CAAC,IACK,IACH,EACR,iBAAQ,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,mCAAmB,EACrE,iBAAQ,KAAK,EAAC,UAAU,EAAC,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,4BAEzD,EACT,cAAK,KAAK,EAAC,QAAQ,GAAO,EAC1B,eAAK,KAAK,EAAC,OAAO,aAChB,eAAK,KAAK,EAAC,MAAM,aACf,eAAM,KAAK,EAAC,OAAO,wBAAe,EAClC,gBAAM,KAAK,EAAC,OAAO,aAChB,SAAS,OAAG,KAAK,CAAC,UAAU,IACxB,IACH,EACN,eAAK,KAAK,EAAC,WAAW,aACpB,eAAM,KAAK,EAAC,OAAO,sBAAa,EAChC,eAAM,KAAK,EAAC,OAAO,YAAE,KAAK,CAAC,SAAS,GAAQ,IACxC,EACN,eAAK,KAAK,EAAC,WAAW,aACpB,eAAM,KAAK,EAAC,OAAO,sBAAa,EAChC,eAAM,KAAK,EAAC,OAAO,YAAE,KAAK,CAAC,SAAS,GAAQ,IACxC,EACN,eAAK,KAAK,EAAC,MAAM,aACf,eAAM,KAAK,EAAC,OAAO,sBAAa,EAChC,eAAM,KAAK,EAAC,OAAO,YAAE,OAAO,GAAQ,IAChC,EACN,cAAK,KAAK,EAAE,OAAO,GAAG,KAAK,CAAC,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,KAAK,CAAC,UAAU,GAAQ,IAC5E,EACL,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,CACtB,cAAK,KAAK,EAAE,aAAa,YACvB,cAAK,KAAK,EAAC,eAAe,EAAC,KAAK,EAAE,SAAS,GAAG,GAAG,GAAQ,GACrD,CACP,CAAC,CAAC,CAAC,IAAI,IACD,CACV,CAAA;AACH,CAAC;AAED,SAAS,SAAS,CAAC,EAAE,KAAK,EAAE,IAAI,EAAgD;IAC9E,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;IAC3C,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAA;IAE9F,MAAM,IAAI,GAAG,GAAG,EAAE;QAChB,eAAe,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAA;QACpC,SAAS,CAAC,IAAI,CAAC,CAAA;QACf,UAAU,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,CAAA;IAC1C,CAAC,CAAA;IAED,OAAO,CACL,eAAK,KAAK,EAAE,QAAQ,GAAG,CAAC,KAAK,CAAC,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,aAC9F,eAAK,KAAK,EAAC,YAAY,aACrB,eAAM,KAAK,EAAE,eAAe,GAAG,KAAK,CAAC,MAAM,YAAG,UAAU,GAAQ,EAChE,eAAM,KAAK,EAAC,YAAY,YAAE,KAAK,CAAC,IAAI,GAAQ,EAC3C,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,eAAM,KAAK,EAAC,YAAY,YAAE,KAAK,CAAC,IAAI,GAAQ,CAAC,CAAC,CAAC,IAAI,EAChE,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,eAAM,KAAK,EAAC,YAAY,YAAE,KAAK,CAAC,IAAI,CAAC,IAAI,GAAQ,CAAC,CAAC,CAAC,IAAI,EAC3E,KAAK,CAAC,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,gBAAM,KAAK,EAAC,WAAW,aAAE,KAAK,CAAC,QAAQ,UAAU,CAAC,CAAC,CAAC,IAAI,EAClF,iBAAQ,KAAK,EAAE,UAAU,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAC,oBAAoB,EAAC,OAAO,EAAE,IAAI,YAC5F,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,GACxB,EACR,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CACZ,iBAAQ,KAAK,EAAC,UAAU,EAAC,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,8BAE7E,CACV,CAAC,CAAC,CAAC,IAAI,IACJ,EACN,cAAK,KAAK,EAAC,OAAO,YACf,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CACzB,eAAK,KAAK,EAAC,MAAM,aACf,eAAM,KAAK,EAAC,YAAY,YAAE,IAAI,CAAC,KAAK,GAAQ,EAC5C,cAAK,KAAK,EAAC,YAAY,YACpB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAC3B,gBAAM,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,EAAE,aACxD,IAAI,CAAC,MAAM,EACX,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,gBAAM,KAAK,EAAC,KAAK,kBAAG,IAAI,CAAC,MAAM,IAAQ,CAAC,CAAC,CAAC,IAAI,KAFG,CAAC,CAG5D,CACR,CAAC,GACE,KATe,IAAI,CAAC,KAAK,CAU3B,CACP,CAAC,GACE,EACL,KAAK,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAC7B,cAAK,KAAK,EAAC,YAAY,YACpB,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAC9B,eAAK,KAAK,EAAE,SAAS,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,aAC/C,eAAM,KAAK,EAAC,MAAM,YAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,GAAQ,EAC/C,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,gBAAM,KAAK,EAAC,KAAK,kBAAG,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,EACtD,yBAAO,CAAC,CAAC,WAAW,GAAQ,KAH0B,CAAC,CAInD,CACP,CAAC,GACE,CACP,CAAC,CAAC,CAAC,IAAI,EACP,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,cAAK,KAAK,EAAC,aAAa,YAAE,KAAK,CAAC,KAAK,GAAO,CAAC,CAAC,CAAC,IAAI,IAC9D,CACP,CAAA;AACH,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,YAAY,CAAC,KAAY;IACvC,MAAM,KAAK,GAAa,CAAC,UAAU,KAAK,CAAC,IAAI,EAAE,CAAC,CAAA;IAChD,IAAI,KAAK,CAAC,IAAI;QAAE,KAAK,CAAC,IAAI,CAAC,SAAS,KAAK,CAAC,IAAI,EAAE,CAAC,CAAA;IACjD,IAAI,KAAK,CAAC,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,WAAW,KAAK,CAAC,MAAM,EAAE,CAAC,CAAA;IACvD,IAAI,KAAK,CAAC,QAAQ,IAAI,IAAI;QAAE,KAAK,CAAC,IAAI,CAAC,aAAa,KAAK,CAAC,QAAQ,IAAI,CAAC,CAAA;IAEvE,MAAM,IAAI,GAAa,EAAE,CAAA;IACzB,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QAC/B,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAC9B,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;gBACf,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC,CAAA;YACzF,CAAC;QACH,CAAC;IACH,CAAC;IACD,IAAI,KAAK,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAe,CAAC,CAAC,EAAE,CAAC;QACxE,IAAI,CAAC,IAAI,CAAC,OAAO,KAAK,CAAC,KAAK,EAAE,CAAC,CAAA;IACjC,CAAC;IACD,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpB,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC,CAAA;IACpC,CAAC;IAED,MAAM,MAAM,GAAG,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAA;IACxD,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,oBAAoB,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,KAAK,IAAI,EAAE,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAA;IACvG,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACzB,CAAC;AAED,SAAS,eAAe,CAAC,IAAY;IACnC,IAAI,OAAO,SAAS,KAAK,WAAW,IAAI,SAAS,CAAC,SAAS,EAAE,SAAS,EAAE,CAAC;QACvE,SAAS,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAA;IACrE,CAAC;SAAM,CAAC;QACN,YAAY,CAAC,IAAI,CAAC,CAAA;IACpB,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,IAAY;IAChC,IAAI,OAAO,QAAQ,KAAK,WAAW;QAAE,OAAM;IAC3C,MAAM,EAAE,GAAG,QAAQ,CAAC,aAAa,CAAC,UAAU,CAAC,CAAA;IAC7C,EAAE,CAAC,KAAK,GAAG,IAAI,CAAA;IACf,EAAE,CAAC,KAAK,CAAC,QAAQ,GAAG,OAAO,CAAA;IAC3B,EAAE,CAAC,KAAK,CAAC,OAAO,GAAG,GAAG,CAAA;IACtB,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,CAAA;IAC7B,EAAE,CAAC,MAAM,EAAE,CAAA;IACX,IAAI,CAAC;QACH,QAAQ,CAAC,WAAW,CAAC,MAAM,CAAC,CAAA;IAC9B,CAAC;IAAC,MAAM,CAAC;QACP,YAAY;IACd,CAAC;IACD,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,CAAA;AAC/B,CAAC"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * A read-only TanStack DB read model over the run event stream.
3
+ *
4
+ * `createRunSource(transport)` wraps the widget's existing transport (SSE in
5
+ * dev, WebSocket in cloud) as a shared, fan-out stream; `runCollectionOptions`
6
+ * turns a projection of that stream into a `CollectionConfig` you pass to your
7
+ * own `createCollection` (so the collection is built by the same `@tanstack/db`
8
+ * your `useLiveQuery` uses). Several collections share one source — one
9
+ * connection, many tables — and each is a server-owned replica with no client
10
+ * writes.
11
+ *
12
+ * This is the *read* half of the pipeline (a client of the broadcast layer),
13
+ * distinct from `@scenetest/receiver`, which is the *ingest* half.
14
+ */
15
+ export { createRunSource } from './source.js';
16
+ export { runCollectionOptions } from './options.js';
17
+ export { scenesProjection, assertionsProjection, actionsProjection, runsProjection, attributeToScene, type SceneRow, type AssertionRecord, type ActionRecord, type RunRow, } from './projections.js';
18
+ export type { RowOp, RunProjection, RunSource, RunCollectionOptions, } from './types.js';
19
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/collections/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAC7C,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AACnD,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,iBAAiB,EACjB,cAAc,EACd,gBAAgB,EAChB,KAAK,QAAQ,EACb,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,MAAM,GACZ,MAAM,kBAAkB,CAAA;AACzB,YAAY,EACV,KAAK,EACL,aAAa,EACb,SAAS,EACT,oBAAoB,GACrB,MAAM,YAAY,CAAA"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * A read-only TanStack DB read model over the run event stream.
3
+ *
4
+ * `createRunSource(transport)` wraps the widget's existing transport (SSE in
5
+ * dev, WebSocket in cloud) as a shared, fan-out stream; `runCollectionOptions`
6
+ * turns a projection of that stream into a `CollectionConfig` you pass to your
7
+ * own `createCollection` (so the collection is built by the same `@tanstack/db`
8
+ * your `useLiveQuery` uses). Several collections share one source — one
9
+ * connection, many tables — and each is a server-owned replica with no client
10
+ * writes.
11
+ *
12
+ * This is the *read* half of the pipeline (a client of the broadcast layer),
13
+ * distinct from `@scenetest/receiver`, which is the *ingest* half.
14
+ */
15
+ export { createRunSource } from './source.js';
16
+ export { runCollectionOptions } from './options.js';
17
+ export { scenesProjection, assertionsProjection, actionsProjection, runsProjection, attributeToScene, } from './projections.js';
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/collections/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAC7C,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AACnD,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,iBAAiB,EACjB,cAAc,EACd,gBAAgB,GAKjB,MAAM,kBAAkB,CAAA"}
@@ -0,0 +1,29 @@
1
+ import type { CollectionConfig } from '@tanstack/db';
2
+ import type { RunCollectionOptions } from './types.js';
3
+ /**
4
+ * Build TanStack DB collection options that turn the read-only run stream
5
+ * into a reactive table — pass the result to `createCollection`.
6
+ *
7
+ * The projection is the sole writer: a sync transaction is opened per event,
8
+ * the projection's row ops are applied, and the transaction commits. There
9
+ * are no mutation handlers (`onInsert`/`onUpdate`/`onDelete`), so a stray
10
+ * client `.insert()`/`.update()` throws — this is a replica of the run, not
11
+ * a writable store. Validation, if any, is a read-time concern; the sync
12
+ * path lands rows raw, which is exactly right for a server-owned read model.
13
+ *
14
+ * Many collections can share one {@link RunCollectionOptions.source}, each
15
+ * with its own projection, so several tables ride one transport connection.
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * const source = createRunSource(transport)
20
+ * const scenes = createCollection(
21
+ * runCollectionOptions({ source, projection: scenesProjection() })
22
+ * )
23
+ * const assertions = createCollection(
24
+ * runCollectionOptions({ source, projection: assertionsProjection() })
25
+ * )
26
+ * ```
27
+ */
28
+ export declare function runCollectionOptions<T extends object, TKey extends string | number>(options: RunCollectionOptions<T, TKey>): CollectionConfig<T, TKey>;
29
+ //# sourceMappingURL=options.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../src/collections/options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AACpD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAA;AAEtD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,MAAM,EAAE,IAAI,SAAS,MAAM,GAAG,MAAM,EACjF,OAAO,EAAE,oBAAoB,CAAC,CAAC,EAAE,IAAI,CAAC,GACrC,gBAAgB,CAAC,CAAC,EAAE,IAAI,CAAC,CA0C3B"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Build TanStack DB collection options that turn the read-only run stream
3
+ * into a reactive table — pass the result to `createCollection`.
4
+ *
5
+ * The projection is the sole writer: a sync transaction is opened per event,
6
+ * the projection's row ops are applied, and the transaction commits. There
7
+ * are no mutation handlers (`onInsert`/`onUpdate`/`onDelete`), so a stray
8
+ * client `.insert()`/`.update()` throws — this is a replica of the run, not
9
+ * a writable store. Validation, if any, is a read-time concern; the sync
10
+ * path lands rows raw, which is exactly right for a server-owned read model.
11
+ *
12
+ * Many collections can share one {@link RunCollectionOptions.source}, each
13
+ * with its own projection, so several tables ride one transport connection.
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * const source = createRunSource(transport)
18
+ * const scenes = createCollection(
19
+ * runCollectionOptions({ source, projection: scenesProjection() })
20
+ * )
21
+ * const assertions = createCollection(
22
+ * runCollectionOptions({ source, projection: assertionsProjection() })
23
+ * )
24
+ * ```
25
+ */
26
+ export function runCollectionOptions(options) {
27
+ const { source, projection } = options;
28
+ return {
29
+ id: projection.id,
30
+ getKey: projection.getKey,
31
+ startSync: options.startSync ?? true,
32
+ sync: {
33
+ sync: ({ begin, write, commit, truncate, markReady }) => {
34
+ // A shadow map of what this projection has written, so the projection
35
+ // can read prior rows (`get`) without reaching into TanStack DB
36
+ // internals — and so a `reset` clears it in lockstep with `truncate`.
37
+ const rows = new Map();
38
+ const handle = (event) => {
39
+ const ops = projection.project(event, (key) => rows.get(key));
40
+ if (ops.length === 0)
41
+ return;
42
+ begin();
43
+ for (const op of ops) {
44
+ if (op.type === 'reset') {
45
+ rows.clear();
46
+ truncate();
47
+ }
48
+ else if (op.type === 'delete') {
49
+ rows.delete(op.key);
50
+ write({ type: 'delete', key: op.key });
51
+ }
52
+ else {
53
+ rows.set(projection.getKey(op.value), op.value);
54
+ write({ type: op.type, value: op.value });
55
+ }
56
+ }
57
+ commit();
58
+ };
59
+ const unsubscribe = source.subscribe(handle);
60
+ // The read model is ready immediately; rows stream in as events arrive
61
+ // (the source replays the current run synchronously on subscribe).
62
+ markReady();
63
+ return unsubscribe;
64
+ },
65
+ },
66
+ };
67
+ }
68
+ //# sourceMappingURL=options.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"options.js","sourceRoot":"","sources":["../../src/collections/options.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,UAAU,oBAAoB,CAClC,OAAsC;IAEtC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,OAAO,CAAA;IAEtC,OAAO;QACL,EAAE,EAAE,UAAU,CAAC,EAAE;QACjB,MAAM,EAAE,UAAU,CAAC,MAAM;QACzB,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,IAAI;QACpC,IAAI,EAAE;YACJ,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,EAAE;gBACtD,sEAAsE;gBACtE,gEAAgE;gBAChE,sEAAsE;gBACtE,MAAM,IAAI,GAAG,IAAI,GAAG,EAAW,CAAA;gBAE/B,MAAM,MAAM,GAAG,CAAC,KAA+C,EAAE,EAAE;oBACjE,MAAM,GAAG,GAAG,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAA;oBAC7D,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;wBAAE,OAAM;oBAE5B,KAAK,EAAE,CAAA;oBACP,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;wBACrB,IAAI,EAAE,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;4BACxB,IAAI,CAAC,KAAK,EAAE,CAAA;4BACZ,QAAQ,EAAE,CAAA;wBACZ,CAAC;6BAAM,IAAI,EAAE,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;4BAChC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,CAAA;4BACnB,KAAK,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,EAAE,CAAC,CAAA;wBACxC,CAAC;6BAAM,CAAC;4BACN,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAA;4BAC/C,KAAK,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,CAAA;wBAC3C,CAAC;oBACH,CAAC;oBACD,MAAM,EAAE,CAAA;gBACV,CAAC,CAAA;gBAED,MAAM,WAAW,GAAG,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;gBAC5C,uEAAuE;gBACvE,mEAAmE;gBACnE,SAAS,EAAE,CAAA;gBACX,OAAO,WAAW,CAAA;YACpB,CAAC;SACF;KACF,CAAA;AACH,CAAC"}