1import type {
2 OrchestrationV2ProjectedTurnItem,
3 OrchestrationV2ThreadProjection,
4} from "@t3tools/contracts";
5
6/** Local timeline rows also carry their item in `projection.turnItems`. */
7function isLocalTimelineRow(
8 projection: Pick<OrchestrationV2ThreadProjection, "thread">,
9 row: OrchestrationV2ProjectedTurnItem,
10): boolean {
11 return row.visibility === "local" || row.sourceThreadId === projection.thread.id;
12}
13
14/**
15 * Server half of the opt-in compact bounded snapshot. Bounded `turnItems` start
16 * with the items of the window's local visible rows, so those entries can be
17 * dropped and rebuilt by `restoreLocalVisibleTurnItems`. Returns null when the
18 * projection does not have that exact shape, or when nothing would be omitted;
19 * callers then send the unchanged projection without a marker.
20 */
21export function omitLocalVisibleTurnItems(
22 projection: OrchestrationV2ThreadProjection,
23): OrchestrationV2ThreadProjection | null {
24 let omitted = 0;
25 for (const row of projection.visibleTurnItems) {
26 if (!isLocalTimelineRow(projection, row)) continue;
27 // Same object, not merely the same id: restoring from the row must
28 // reproduce the original entry exactly.
29 if (projection.turnItems[omitted] !== row.item) return null;
30 omitted += 1;
31 }
32 if (omitted === 0) return null;
33 return { ...projection, turnItems: projection.turnItems.slice(omitted) };
34}
35
36/**
37 * Client half: call on a decoded snapshot that carries the
38 * `turnItemsOmitLocalVisible` marker, before reducers or caches see it.
39 */
40export function restoreLocalVisibleTurnItems(
41 projection: OrchestrationV2ThreadProjection,
42): OrchestrationV2ThreadProjection {
43 const local = projection.visibleTurnItems
44 .filter((row) => isLocalTimelineRow(projection, row))
45 .map((row) => row.item);
46 if (local.length === 0) return projection;
47 return { ...projection, turnItems: [...local, ...projection.turnItems] };
48}
49
50/** The usable projection of a decoded bounded snapshot, compact or not. */
51export function boundedSnapshotProjection(snapshot: {
52 readonly projection: OrchestrationV2ThreadProjection;
53 readonly turnItemsOmitLocalVisible?: true | undefined;
54}): OrchestrationV2ThreadProjection {
55 return snapshot.turnItemsOmitLocalVisible === true
56 ? restoreLocalVisibleTurnItems(snapshot.projection)
57 : snapshot.projection;
58}