createParseTreeStore()
Factory function that creates a ParseTreeStore — a bridge between the @cacheplane/partial-json parser and Angular's signal-based Spec rendering. It materializes the parse tree into a Spec signal with structural sharing on each push.
Import:
import { createParseTreeStore } from '@threadplane/chat';
import type { ParseTreeStore, ElementAccumulationState } from '@threadplane/chat';Signature
function createParseTreeStore(parser: PartialJsonParser): ParseTreeStore| Parameter | Type | Description |
|---|---|---|
parser | PartialJsonParser | A parser instance from createPartialJsonParser() in @cacheplane/partial-json |
Returns: ParseTreeStore — must be called within an Angular injection context.
ParseTreeStore Interface
interface ParseTreeStore {
/** Push characters to the parser and update signals. */
push(chunk: string): void;
/** Current materialized spec (structurally shared between updates). */
readonly spec: Signal<Spec | null>;
/** Per-element accumulation tracking. */
readonly elementStates: Signal<Map<string, ElementAccumulationState>>;
}ElementAccumulationState
interface ElementAccumulationState {
hasType: boolean; // /elements/{key}/type received
hasProps: boolean; // /elements/{key}/props received
hasChildren: boolean; // /elements/{key}/children received
streaming: boolean; // still receiving data for this element
}Usage
import { createPartialJsonParser } from '@cacheplane/partial-json';
import { createParseTreeStore } from '@threadplane/chat';
const parser = createPartialJsonParser();
const store = createParseTreeStore(parser);
store.push('{"root":"r1","elements":{"r1":{"type":"Text"');
store.spec(); // partial Spec — r1 has type "Text" but no props yet
store.push(',"props":{"label":"Hello"}}}}');
store.spec(); // complete Spec
// Element tracking
store.elementStates().get('r1');
// { hasType: true, hasProps: true, hasChildren: false, streaming: false }The spec signal uses structural sharing. When a new token updates one element, sibling elements keep the same object reference. Angular's computed() with Object.is equality skips re-evaluation for unchanged elements.