5.12 Frame hooks and beforeCommit ​

Contract 2.0.0 · package sha256 a857eca95b35921109faf997094bb4192f12527d9d0fcd4be7e97f06425bad6e · generated from examples/section-5/5.12-frame-hooks-and-beforecommit.ts by services/onsite-scripter/scripts/build-contract-docs.mjs; edit the source, not this file.

Imports: values (has, validate, the Holo*Error classes, the pure helpers) from @holostep-configurators/runtime-client, types from @holostep-configurators/runtime-client/contract, /math and /testing names from those entries; boot from the runtime module the root's loadRuntimeAtFloor resolves to. A type your page defines is your app's: declare it there, never import it from the package.

ts
import { has } from '@holostep-configurators/runtime-client';
import type { DeepReadonly, GeometryData, GeometryWrite, PoseInput, Query, SceneModel, Session, Writer } from '@holostep-configurators/runtime-client/contract';
declare const session: Session;
declare const signal: AbortSignal;
declare const bedId: string;
declare const mattressId: string;
declare function planLegWrites(legs: readonly GeometryData[], model: DeepReadonly<SceneModel>):
  ReadonlyArray<{ query: Query; data: GeometryWrite }>;
declare function centreMattress(writer: Writer): PoseInput;
export function installBedLayout(session: Session, signal: AbortSignal): () => void {
  const authoredLegs = new Map<string, GeometryData[]>();               // by asset version: one engine query per asset
  const posed = new Set<string>();                                      // what the layout posed, for the cleanup
  const layout = async (writer: Writer): Promise<void> => {             // the hook's tx, else the session
    if (!writer.node(bedId).exists) return;                             // removed: describe() would throw 'unknown-id'
    await writer.animations.reset(bedId);                               // the reads below see the bed closed
    const asset = session.describe(bedId)?.asset;                       // the GLB this commit shows (O11)
    const version = asset?.version ?? asset?.url ?? 'none';             // an unstamped GLB keys by URL
    let legs = authoredLegs.get(version);
    if (!legs) authoredLegs.set(version, legs = await writer.labs.geometry.read({ node: bedId, tag: 'leg' }, ['position', 'index'], { from: 'authored' }));
    for (const w of planLegWrites(legs, writer.getSceneModel()!)) await writer.labs.geometry.write(w.query, w.data);
    await writer.node(mattressId).set({ pose: centreMattress(writer) }); // the model's root; joins this commit
    posed.add(mattressId);
  };
  const off = has(session, 'beforeCommit')
    ? session.beforeCommit('bed-layout', ({ tx }) => layout(tx), { signal })
    : session.on('committed', ({ recorded }) => { if (recorded) void layout(session); }, { signal });   // no hook: one frame late
  void session.transaction((tx) => layout(tx));                         // the bed as it is now, once: registering replays nothing
  return () => { off(); for (const id of posed) void session.node(id).set({ pose: null }); };   // rules outlive the hook
}

Back to the examples · llms.txt