{"version":3,"file":"use-projection.cjs","names":[],"sources":["../src/use-projection.ts"],"sourcesContent":["/* __LC_ALLOW_ENTRYPOINT_SIDE_EFFECTS__ */\n\n\"use client\";\n\nimport { useEffect, useState, useSyncExternalStore } from \"react\";\nimport type {\n  ChannelRegistry,\n  ProjectionSpec,\n  StreamStore,\n} from \"@langchain/langgraph-sdk/stream\";\n\n/**\n * React-side primitive that composes {@link ChannelRegistry.acquire}\n * with {@link useSyncExternalStore}.\n *\n * Contract:\n *  - On mount (or when `key` changes) this hook acquires a\n *    ref-counted projection from the registry and subscribes to its\n *    store. React re-renders automatically whenever the store's\n *    snapshot changes.\n *  - On unmount (or when `key` changes) the previous acquisition is\n *    released. If this was the last consumer of that spec, the\n *    registry closes the underlying server subscription.\n *\n * The first render (before `useEffect` runs) returns `initialValue`.\n * Subsequent renders read from the acquired store.\n *\n * Framework bindings for Vue/Svelte/Angular follow the same shape —\n * acquire on setup/mount, release on scope-dispose/unmount — but use\n * their own reactivity primitive instead of `useSyncExternalStore`.\n */\nexport function useProjection<T>(\n  registry: ChannelRegistry | null | undefined,\n  specFactory: () => ProjectionSpec<T>,\n  key: string,\n  initialValue: T\n): T {\n  const [store, setStore] = useState<StreamStore<T> | null>(null);\n\n  useEffect(() => {\n    if (registry == null) return undefined;\n    const acquired = registry.acquire(specFactory());\n    setStore(acquired.store);\n    return () => {\n      acquired.release();\n      setStore(null);\n    };\n    // `specFactory` is intentionally not in the dep array: identity\n    // of the factory function is not meaningful — only the `key` is.\n    // Callers construct the spec inline and rely on the key to dedupe.\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, [registry, key]);\n\n  return useSyncExternalStore<T>(\n    store != null ? store.subscribe : NOOP_SUBSCRIBE,\n    () => (store != null ? store.getSnapshot() : initialValue),\n    () => initialValue\n  );\n}\n\nconst NOOP_SUBSCRIBE: (listener: () => void) => () => void = () => () => {};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AA+BA,SAAgB,cACd,UACA,aACA,KACA,cACG;CACH,MAAM,CAAC,OAAO,aAAA,GAAA,MAAA,UAA4C,KAAK;AAE/D,EAAA,GAAA,MAAA,iBAAgB;AACd,MAAI,YAAY,KAAM,QAAO,KAAA;EAC7B,MAAM,WAAW,SAAS,QAAQ,aAAa,CAAC;AAChD,WAAS,SAAS,MAAM;AACxB,eAAa;AACX,YAAS,SAAS;AAClB,YAAS,KAAK;;IAMf,CAAC,UAAU,IAAI,CAAC;AAEnB,SAAA,GAAA,MAAA,sBACE,SAAS,OAAO,MAAM,YAAY,sBAC3B,SAAS,OAAO,MAAM,aAAa,GAAG,oBACvC,aACP;;AAGH,MAAM,6BAAmE"}