@codebelt/classy-store 0.0.2 → 0.1.1

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 (41) hide show
  1. package/dist/equality-5F2bPn7E.d.mts +13 -0
  2. package/dist/equality-5F2bPn7E.d.mts.map +1 -0
  3. package/dist/equality-BA46H9AL.mjs +27 -0
  4. package/dist/equality-BA46H9AL.mjs.map +1 -0
  5. package/dist/equality-C1s0kqxg.d.cts +13 -0
  6. package/dist/equality-C1s0kqxg.d.cts.map +1 -0
  7. package/dist/equality-Cz6riknL.cjs +33 -0
  8. package/dist/equality-Cz6riknL.cjs.map +1 -0
  9. package/dist/index.cjs +10 -34
  10. package/dist/index.cjs.map +1 -1
  11. package/dist/index.d.cts +16 -21
  12. package/dist/index.d.cts.map +1 -1
  13. package/dist/index.d.mts +17 -22
  14. package/dist/index.d.mts.map +1 -1
  15. package/dist/index.mjs +9 -33
  16. package/dist/index.mjs.map +1 -1
  17. package/dist/react/react.cjs +30 -1
  18. package/dist/react/react.cjs.map +1 -1
  19. package/dist/react/react.d.cts +26 -1
  20. package/dist/react/react.d.cts.map +1 -1
  21. package/dist/react/react.d.mts +27 -2
  22. package/dist/react/react.d.mts.map +1 -1
  23. package/dist/react/react.mjs +31 -3
  24. package/dist/react/react.mjs.map +1 -1
  25. package/dist/{snapshot-C8JDLu8L.mjs → snapshot-COzEerMu.mjs} +45 -15
  26. package/dist/snapshot-COzEerMu.mjs.map +1 -0
  27. package/dist/{snapshot-CR8nA2Ob.cjs → snapshot-CbVbxG7s.cjs} +50 -20
  28. package/dist/snapshot-CbVbxG7s.cjs.map +1 -0
  29. package/dist/{types-vWYkF3tH.d.mts → types-Cf8Fp7kA.d.mts} +1 -1
  30. package/dist/{types-vWYkF3tH.d.mts.map → types-Cf8Fp7kA.d.mts.map} +1 -1
  31. package/dist/utils/index.cjs +177 -6
  32. package/dist/utils/index.cjs.map +1 -1
  33. package/dist/utils/index.d.cts +90 -2
  34. package/dist/utils/index.d.cts.map +1 -1
  35. package/dist/utils/index.d.mts +90 -2
  36. package/dist/utils/index.d.mts.map +1 -1
  37. package/dist/utils/index.mjs +174 -7
  38. package/dist/utils/index.mjs.map +1 -1
  39. package/package.json +4 -3
  40. package/dist/snapshot-C8JDLu8L.mjs.map +0 -1
  41. package/dist/snapshot-CR8nA2Ob.cjs.map +0 -1
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
- const require_snapshot = require('../snapshot-CR8nA2Ob.cjs');
2
+ const require_snapshot = require('../snapshot-CbVbxG7s.cjs');
3
3
  let proxy_compare = require("proxy-compare");
4
4
  let react = require("react");
5
5
 
@@ -55,7 +55,36 @@ function getAutoTrackSnapshot(proxyStore, affected, proxyCache, prevSnapRef, wra
55
55
  wrappedRef.current = wrapped;
56
56
  return wrapped;
57
57
  }
58
+ /**
59
+ * Create a component-scoped reactive store that lives for the lifetime of the
60
+ * component. When the component unmounts, the store becomes unreferenced and is
61
+ * garbage collected (all internal bookkeeping uses `WeakMap`).
62
+ *
63
+ * The factory function runs **once** per mount (via `useState` initializer).
64
+ * Each component instance gets its own isolated store.
65
+ *
66
+ * Use the returned proxy with `useStore()` to read state in the same component
67
+ * or pass it down via props/context to share within a subtree.
68
+ *
69
+ * @param factory - A function that returns a class instance (or plain object).
70
+ * Called once per component mount.
71
+ * @returns A reactive store proxy scoped to the component's lifetime.
72
+ *
73
+ * @example
74
+ * ```tsx
75
+ * function Counter() {
76
+ * const store = useLocalStore(() => new CounterStore());
77
+ * const count = useStore(store, s => s.count);
78
+ * return <button onClick={() => store.increment()}>{count}</button>;
79
+ * }
80
+ * ```
81
+ */
82
+ function useLocalStore(factory) {
83
+ const [store] = (0, react.useState)(() => require_snapshot.createClassyStore(factory()));
84
+ return store;
85
+ }
58
86
 
59
87
  //#endregion
88
+ exports.useLocalStore = useLocalStore;
60
89
  exports.useStore = useStore;
61
90
  //# sourceMappingURL=react.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"react.cjs","names":["subscribe","coreSubscribe","snapshot"],"sources":["../../src/react/react.ts"],"sourcesContent":["import {createProxy, isChanged} from 'proxy-compare';\nimport {useCallback, useRef, useSyncExternalStore} from 'react';\nimport {subscribe as coreSubscribe, getInternal} from '../core/core';\nimport {snapshot} from '../snapshot/snapshot';\nimport type {Snapshot} from '../types';\n\n// ── Overloads ─────────────────────────────────────────────────────────────────\n\n/**\n * Subscribe to a store proxy with an explicit selector.\n *\n * Re-renders only when the selected value changes (compared via `Object.is`\n * by default, or a custom `isEqual`).\n *\n * @param proxyStore - A reactive proxy created by `store()`.\n * @param selector - Picks data from the immutable snapshot.\n * @param isEqual - Optional custom equality function (default: `Object.is`).\n */\nexport function useStore<T extends object, S>(\n proxyStore: T,\n selector: (snap: Snapshot<T>) => S,\n isEqual?: (a: S, b: S) => boolean,\n): S;\n\n/**\n * Subscribe to a store proxy **without** a selector (auto-tracked mode).\n *\n * Returns a `proxy-compare` tracking proxy over the immutable snapshot.\n * The component only re-renders when a property it actually read changes.\n *\n * @param proxyStore - A reactive proxy created by `store()`.\n */\nexport function useStore<T extends object>(proxyStore: T): Snapshot<T>;\n\n// ── Implementation ────────────────────────────────────────────────────────────\n\nexport function useStore<T extends object, S>(\n proxyStore: T,\n selector?: (snap: Snapshot<T>) => S,\n isEqual?: (a: S, b: S) => boolean,\n): Snapshot<T> | S {\n // Validate that the argument is actually a store proxy (throws if not).\n getInternal(proxyStore);\n\n // Stable subscribe function (internal identity never changes for a given store).\n const subscribe = useCallback(\n (onStoreChange: () => void) => coreSubscribe(proxyStore, onStoreChange),\n [proxyStore],\n );\n\n // ── Refs used by both modes (always allocated to satisfy Rules of Hooks) ──\n\n // Selector mode refs\n const snapRef = useRef<Snapshot<T> | undefined>(undefined);\n const resultRef = useRef<S | undefined>(undefined);\n\n // Auto-track mode refs\n const affected = useRef(new WeakMap<object, unknown>()).current;\n const proxyCache = useRef(new WeakMap<object, unknown>()).current;\n const prevSnapRef = useRef<Snapshot<T> | undefined>(undefined);\n const wrappedRef = useRef<Snapshot<T> | undefined>(undefined);\n\n // ── Single getSnapshot for useSyncExternalStore ───────────────────────────\n\n const getSnapshot = (): Snapshot<T> | S =>\n selector\n ? getSelectorSnapshot(proxyStore, snapRef, resultRef, selector, isEqual)\n : getAutoTrackSnapshot(\n proxyStore,\n affected,\n proxyCache,\n prevSnapRef,\n wrappedRef,\n );\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n\n// ── Selector mode logic (pure function, no hooks) ─────────────────────────────\n\n/**\n * `getSnapshot` implementation for selector mode.\n *\n * Fast-paths when the snapshot reference hasn't changed (O(1)). Otherwise\n * runs the selector against the new snapshot and compares the result to the\n * previous one via `Object.is` (or a custom `isEqual`). Returns the previous\n * result reference when equal, preventing unnecessary React re-renders.\n *\n * Pure function -- no hooks, safe to call from `useSyncExternalStore`.\n */\nfunction getSelectorSnapshot<T extends object, S>(\n proxyStore: T,\n snapRef: React.RefObject<Snapshot<T> | undefined>,\n resultRef: React.RefObject<S | undefined>,\n selector: (snap: Snapshot<T>) => S,\n isEqual?: (a: S, b: S) => boolean,\n): S {\n const nextSnap = snapshot(proxyStore);\n\n // Fast path: same snapshot reference → same result.\n if (snapRef.current === nextSnap && resultRef.current !== undefined) {\n return resultRef.current;\n }\n\n const nextResult = selector(nextSnap);\n snapRef.current = nextSnap;\n\n // Check equality with previous result.\n if (\n resultRef.current !== undefined &&\n (isEqual\n ? isEqual(resultRef.current, nextResult)\n : Object.is(resultRef.current, nextResult))\n ) {\n return resultRef.current;\n }\n\n resultRef.current = nextResult;\n return nextResult;\n}\n\n// ── Auto-tracked (selectorless) mode logic (pure function, no hooks) ──────────\n\n/**\n * `getSnapshot` implementation for auto-tracked (selectorless) mode.\n *\n * Uses `proxy-compare` to diff only the properties the component actually read.\n * If the snapshot reference is the same, returns the cached tracking proxy.\n * If the snapshot changed but no tracked property differs (`isChanged` returns\n * false), also returns the cached proxy -- avoiding re-render. Only when a\n * relevant property changed does it create a new `createProxy` wrapper.\n *\n * Pure function -- no hooks, safe to call from `useSyncExternalStore`.\n */\nfunction getAutoTrackSnapshot<T extends object>(\n proxyStore: T,\n affected: WeakMap<object, unknown>,\n proxyCache: WeakMap<object, unknown>,\n prevSnapRef: React.RefObject<Snapshot<T> | undefined>,\n wrappedRef: React.RefObject<Snapshot<T> | undefined>,\n): Snapshot<T> {\n const nextSnap = snapshot(proxyStore);\n\n // If the raw snapshot is the same reference, nothing changed.\n if (prevSnapRef.current === nextSnap) {\n return wrappedRef.current as Snapshot<T>;\n }\n\n // Check if any property the component actually read has changed.\n if (\n prevSnapRef.current !== undefined &&\n !isChanged(prevSnapRef.current, nextSnap, affected)\n ) {\n // No property the component cares about changed → return same wrapped proxy.\n return wrappedRef.current as Snapshot<T>;\n }\n\n // Something relevant changed — create a new tracking proxy.\n prevSnapRef.current = nextSnap;\n const wrapped = createProxy(nextSnap, affected, proxyCache) as Snapshot<T>;\n wrappedRef.current = wrapped;\n return wrapped;\n}\n"],"mappings":";;;;;;AAoCA,SAAgB,SACd,YACA,UACA,SACiB;AAEjB,8BAAY,WAAW;CAGvB,MAAMA,sCACH,kBAA8BC,2BAAc,YAAY,cAAc,EACvE,CAAC,WAAW,CACb;CAKD,MAAM,4BAA0C,OAAU;CAC1D,MAAM,8BAAkC,OAAU;CAGlD,MAAM,6CAAkB,IAAI,SAA0B,CAAC,CAAC;CACxD,MAAM,+CAAoB,IAAI,SAA0B,CAAC,CAAC;CAC1D,MAAM,gCAA8C,OAAU;CAC9D,MAAM,+BAA6C,OAAU;CAI7D,MAAM,oBACJ,WACI,oBAAoB,YAAY,SAAS,WAAW,UAAU,QAAQ,GACtE,qBACE,YACA,UACA,YACA,aACA,WACD;AAEP,wCAA4BD,aAAW,aAAa,YAAY;;;;;;;;;;;;AAelE,SAAS,oBACP,YACA,SACA,WACA,UACA,SACG;CACH,MAAM,WAAWE,0BAAS,WAAW;AAGrC,KAAI,QAAQ,YAAY,YAAY,UAAU,YAAY,OACxD,QAAO,UAAU;CAGnB,MAAM,aAAa,SAAS,SAAS;AACrC,SAAQ,UAAU;AAGlB,KACE,UAAU,YAAY,WACrB,UACG,QAAQ,UAAU,SAAS,WAAW,GACtC,OAAO,GAAG,UAAU,SAAS,WAAW,EAE5C,QAAO,UAAU;AAGnB,WAAU,UAAU;AACpB,QAAO;;;;;;;;;;;;;AAgBT,SAAS,qBACP,YACA,UACA,YACA,aACA,YACa;CACb,MAAM,WAAWA,0BAAS,WAAW;AAGrC,KAAI,YAAY,YAAY,SAC1B,QAAO,WAAW;AAIpB,KACE,YAAY,YAAY,UACxB,8BAAW,YAAY,SAAS,UAAU,SAAS,CAGnD,QAAO,WAAW;AAIpB,aAAY,UAAU;CACtB,MAAM,yCAAsB,UAAU,UAAU,WAAW;AAC3D,YAAW,UAAU;AACrB,QAAO"}
1
+ {"version":3,"file":"react.cjs","names":["subscribe","coreSubscribe","snapshot","createClassyStore"],"sources":["../../src/react/react.ts"],"sourcesContent":["import {createProxy, isChanged} from 'proxy-compare';\nimport {useCallback, useRef, useState, useSyncExternalStore} from 'react';\nimport {\n subscribe as coreSubscribe,\n createClassyStore,\n getInternal,\n} from '../core/core';\nimport {snapshot} from '../snapshot/snapshot';\nimport type {Snapshot} from '../types';\n\n// ── Overloads ─────────────────────────────────────────────────────────────────\n\n/**\n * Subscribe to a store proxy with an explicit selector.\n *\n * Re-renders only when the selected value changes (compared via `Object.is`\n * by default, or a custom `isEqual`).\n *\n * @param proxyStore - A reactive proxy created by `store()`.\n * @param selector - Picks data from the immutable snapshot.\n * @param isEqual - Optional custom equality function (default: `Object.is`).\n */\nexport function useStore<T extends object, S>(\n proxyStore: T,\n selector: (snap: Snapshot<T>) => S,\n isEqual?: (a: S, b: S) => boolean,\n): S;\n\n/**\n * Subscribe to a store proxy **without** a selector (auto-tracked mode).\n *\n * Returns a `proxy-compare` tracking proxy over the immutable snapshot.\n * The component only re-renders when a property it actually read changes.\n *\n * @param proxyStore - A reactive proxy created by `store()`.\n */\nexport function useStore<T extends object>(proxyStore: T): Snapshot<T>;\n\n// ── Implementation ────────────────────────────────────────────────────────────\n\nexport function useStore<T extends object, S>(\n proxyStore: T,\n selector?: (snap: Snapshot<T>) => S,\n isEqual?: (a: S, b: S) => boolean,\n): Snapshot<T> | S {\n // Validate that the argument is actually a store proxy (throws if not).\n getInternal(proxyStore);\n\n // Stable subscribe function (internal identity never changes for a given store).\n const subscribe = useCallback(\n (onStoreChange: () => void) => coreSubscribe(proxyStore, onStoreChange),\n [proxyStore],\n );\n\n // ── Refs used by both modes (always allocated to satisfy Rules of Hooks) ──\n\n // Selector mode refs\n const snapRef = useRef<Snapshot<T> | undefined>(undefined);\n const resultRef = useRef<S | undefined>(undefined);\n\n // Auto-track mode refs\n const affected = useRef(new WeakMap<object, unknown>()).current;\n const proxyCache = useRef(new WeakMap<object, unknown>()).current;\n const prevSnapRef = useRef<Snapshot<T> | undefined>(undefined);\n const wrappedRef = useRef<Snapshot<T> | undefined>(undefined);\n\n // ── Single getSnapshot for useSyncExternalStore ───────────────────────────\n\n const getSnapshot = (): Snapshot<T> | S =>\n selector\n ? getSelectorSnapshot(proxyStore, snapRef, resultRef, selector, isEqual)\n : getAutoTrackSnapshot(\n proxyStore,\n affected,\n proxyCache,\n prevSnapRef,\n wrappedRef,\n );\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n\n// ── Selector mode logic (pure function, no hooks) ─────────────────────────────\n\n/**\n * `getSnapshot` implementation for selector mode.\n *\n * Fast-paths when the snapshot reference hasn't changed (O(1)). Otherwise\n * runs the selector against the new snapshot and compares the result to the\n * previous one via `Object.is` (or a custom `isEqual`). Returns the previous\n * result reference when equal, preventing unnecessary React re-renders.\n *\n * Pure function -- no hooks, safe to call from `useSyncExternalStore`.\n */\nfunction getSelectorSnapshot<T extends object, S>(\n proxyStore: T,\n snapRef: React.RefObject<Snapshot<T> | undefined>,\n resultRef: React.RefObject<S | undefined>,\n selector: (snap: Snapshot<T>) => S,\n isEqual?: (a: S, b: S) => boolean,\n): S {\n const nextSnap = snapshot(proxyStore);\n\n // Fast path: same snapshot reference → same result.\n if (snapRef.current === nextSnap && resultRef.current !== undefined) {\n return resultRef.current;\n }\n\n const nextResult = selector(nextSnap);\n snapRef.current = nextSnap;\n\n // Check equality with previous result.\n if (\n resultRef.current !== undefined &&\n (isEqual\n ? isEqual(resultRef.current, nextResult)\n : Object.is(resultRef.current, nextResult))\n ) {\n return resultRef.current;\n }\n\n resultRef.current = nextResult;\n return nextResult;\n}\n\n// ── Auto-tracked (selectorless) mode logic (pure function, no hooks) ──────────\n\n/**\n * `getSnapshot` implementation for auto-tracked (selectorless) mode.\n *\n * Uses `proxy-compare` to diff only the properties the component actually read.\n * If the snapshot reference is the same, returns the cached tracking proxy.\n * If the snapshot changed but no tracked property differs (`isChanged` returns\n * false), also returns the cached proxy -- avoiding re-render. Only when a\n * relevant property changed does it create a new `createProxy` wrapper.\n *\n * Pure function -- no hooks, safe to call from `useSyncExternalStore`.\n */\nfunction getAutoTrackSnapshot<T extends object>(\n proxyStore: T,\n affected: WeakMap<object, unknown>,\n proxyCache: WeakMap<object, unknown>,\n prevSnapRef: React.RefObject<Snapshot<T> | undefined>,\n wrappedRef: React.RefObject<Snapshot<T> | undefined>,\n): Snapshot<T> {\n const nextSnap = snapshot(proxyStore);\n\n // If the raw snapshot is the same reference, nothing changed.\n if (prevSnapRef.current === nextSnap) {\n return wrappedRef.current as Snapshot<T>;\n }\n\n // Check if any property the component actually read has changed.\n if (\n prevSnapRef.current !== undefined &&\n !isChanged(prevSnapRef.current, nextSnap, affected)\n ) {\n // No property the component cares about changed → return same wrapped proxy.\n return wrappedRef.current as Snapshot<T>;\n }\n\n // Something relevant changed — create a new tracking proxy.\n prevSnapRef.current = nextSnap;\n const wrapped = createProxy(nextSnap, affected, proxyCache) as Snapshot<T>;\n wrappedRef.current = wrapped;\n return wrapped;\n}\n\n// ── Component-scoped store ────────────────────────────────────────────────────\n\n/**\n * Create a component-scoped reactive store that lives for the lifetime of the\n * component. When the component unmounts, the store becomes unreferenced and is\n * garbage collected (all internal bookkeeping uses `WeakMap`).\n *\n * The factory function runs **once** per mount (via `useState` initializer).\n * Each component instance gets its own isolated store.\n *\n * Use the returned proxy with `useStore()` to read state in the same component\n * or pass it down via props/context to share within a subtree.\n *\n * @param factory - A function that returns a class instance (or plain object).\n * Called once per component mount.\n * @returns A reactive store proxy scoped to the component's lifetime.\n *\n * @example\n * ```tsx\n * function Counter() {\n * const store = useLocalStore(() => new CounterStore());\n * const count = useStore(store, s => s.count);\n * return <button onClick={() => store.increment()}>{count}</button>;\n * }\n * ```\n */\nexport function useLocalStore<T extends object>(factory: () => T): T {\n const [store] = useState(() => createClassyStore(factory()));\n return store;\n}\n"],"mappings":";;;;;;AAwCA,SAAgB,SACd,YACA,UACA,SACiB;AAEjB,8BAAY,WAAW;CAGvB,MAAMA,sCACH,kBAA8BC,2BAAc,YAAY,cAAc,EACvE,CAAC,WAAW,CACb;CAKD,MAAM,4BAA0C,OAAU;CAC1D,MAAM,8BAAkC,OAAU;CAGlD,MAAM,6CAAkB,IAAI,SAA0B,CAAC,CAAC;CACxD,MAAM,+CAAoB,IAAI,SAA0B,CAAC,CAAC;CAC1D,MAAM,gCAA8C,OAAU;CAC9D,MAAM,+BAA6C,OAAU;CAI7D,MAAM,oBACJ,WACI,oBAAoB,YAAY,SAAS,WAAW,UAAU,QAAQ,GACtE,qBACE,YACA,UACA,YACA,aACA,WACD;AAEP,wCAA4BD,aAAW,aAAa,YAAY;;;;;;;;;;;;AAelE,SAAS,oBACP,YACA,SACA,WACA,UACA,SACG;CACH,MAAM,WAAWE,0BAAS,WAAW;AAGrC,KAAI,QAAQ,YAAY,YAAY,UAAU,YAAY,OACxD,QAAO,UAAU;CAGnB,MAAM,aAAa,SAAS,SAAS;AACrC,SAAQ,UAAU;AAGlB,KACE,UAAU,YAAY,WACrB,UACG,QAAQ,UAAU,SAAS,WAAW,GACtC,OAAO,GAAG,UAAU,SAAS,WAAW,EAE5C,QAAO,UAAU;AAGnB,WAAU,UAAU;AACpB,QAAO;;;;;;;;;;;;;AAgBT,SAAS,qBACP,YACA,UACA,YACA,aACA,YACa;CACb,MAAM,WAAWA,0BAAS,WAAW;AAGrC,KAAI,YAAY,YAAY,SAC1B,QAAO,WAAW;AAIpB,KACE,YAAY,YAAY,UACxB,8BAAW,YAAY,SAAS,UAAU,SAAS,CAGnD,QAAO,WAAW;AAIpB,aAAY,UAAU;CACtB,MAAM,yCAAsB,UAAU,UAAU,WAAW;AAC3D,YAAW,UAAU;AACrB,QAAO;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BT,SAAgB,cAAgC,SAAqB;CACnE,MAAM,CAAC,mCAAwBC,mCAAkB,SAAS,CAAC,CAAC;AAC5D,QAAO"}
@@ -21,6 +21,31 @@ declare function useStore<T extends object, S>(proxyStore: T, selector: (snap: S
21
21
  * @param proxyStore - A reactive proxy created by `store()`.
22
22
  */
23
23
  declare function useStore<T extends object>(proxyStore: T): Snapshot<T>;
24
+ /**
25
+ * Create a component-scoped reactive store that lives for the lifetime of the
26
+ * component. When the component unmounts, the store becomes unreferenced and is
27
+ * garbage collected (all internal bookkeeping uses `WeakMap`).
28
+ *
29
+ * The factory function runs **once** per mount (via `useState` initializer).
30
+ * Each component instance gets its own isolated store.
31
+ *
32
+ * Use the returned proxy with `useStore()` to read state in the same component
33
+ * or pass it down via props/context to share within a subtree.
34
+ *
35
+ * @param factory - A function that returns a class instance (or plain object).
36
+ * Called once per component mount.
37
+ * @returns A reactive store proxy scoped to the component's lifetime.
38
+ *
39
+ * @example
40
+ * ```tsx
41
+ * function Counter() {
42
+ * const store = useLocalStore(() => new CounterStore());
43
+ * const count = useStore(store, s => s.count);
44
+ * return <button onClick={() => store.increment()}>{count}</button>;
45
+ * }
46
+ * ```
47
+ */
48
+ declare function useLocalStore<T extends object>(factory: () => T): T;
24
49
  //#endregion
25
- export { useStore };
50
+ export { useLocalStore, useStore };
26
51
  //# sourceMappingURL=react.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"react.d.cts","names":[],"sources":["../../src/react/react.ts"],"mappings":";;;;;AAkBA;;;;;;;;iBAAgB,QAAA,qBAAA,CACd,UAAA,EAAY,CAAA,EACZ,QAAA,GAAW,IAAA,EAAM,QAAA,CAAS,CAAA,MAAO,CAAA,EACjC,OAAA,IAAW,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA,eACnB,CAAA;;;;;;;;;iBAUa,QAAA,kBAAA,CAA2B,UAAA,EAAY,CAAA,GAAI,QAAA,CAAS,CAAA"}
1
+ {"version":3,"file":"react.d.cts","names":[],"sources":["../../src/react/react.ts"],"mappings":";;;;;AAsBA;;;;;;;;iBAAgB,QAAA,qBAAA,CACd,UAAA,EAAY,CAAA,EACZ,QAAA,GAAW,IAAA,EAAM,QAAA,CAAS,CAAA,MAAO,CAAA,EACjC,OAAA,IAAW,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA,eACnB,CAAA;;;;;;;;;iBAUa,QAAA,kBAAA,CAA2B,UAAA,EAAY,CAAA,GAAI,QAAA,CAAS,CAAA;;;;;;;;;;;;AAApE;;;;;;;;;;;;;iBA8JgB,aAAA,kBAAA,CAAgC,OAAA,QAAe,CAAA,GAAI,CAAA"}
@@ -1,4 +1,4 @@
1
- import { t as Snapshot } from "../types-vWYkF3tH.mjs";
1
+ import { t as Snapshot } from "../types-Cf8Fp7kA.mjs";
2
2
 
3
3
  //#region src/react/react.d.ts
4
4
  /**
@@ -21,6 +21,31 @@ declare function useStore<T extends object, S>(proxyStore: T, selector: (snap: S
21
21
  * @param proxyStore - A reactive proxy created by `store()`.
22
22
  */
23
23
  declare function useStore<T extends object>(proxyStore: T): Snapshot<T>;
24
+ /**
25
+ * Create a component-scoped reactive store that lives for the lifetime of the
26
+ * component. When the component unmounts, the store becomes unreferenced and is
27
+ * garbage collected (all internal bookkeeping uses `WeakMap`).
28
+ *
29
+ * The factory function runs **once** per mount (via `useState` initializer).
30
+ * Each component instance gets its own isolated store.
31
+ *
32
+ * Use the returned proxy with `useStore()` to read state in the same component
33
+ * or pass it down via props/context to share within a subtree.
34
+ *
35
+ * @param factory - A function that returns a class instance (or plain object).
36
+ * Called once per component mount.
37
+ * @returns A reactive store proxy scoped to the component's lifetime.
38
+ *
39
+ * @example
40
+ * ```tsx
41
+ * function Counter() {
42
+ * const store = useLocalStore(() => new CounterStore());
43
+ * const count = useStore(store, s => s.count);
44
+ * return <button onClick={() => store.increment()}>{count}</button>;
45
+ * }
46
+ * ```
47
+ */
48
+ declare function useLocalStore<T extends object>(factory: () => T): T;
24
49
  //#endregion
25
- export { useStore };
50
+ export { useLocalStore, useStore };
26
51
  //# sourceMappingURL=react.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"react.d.mts","names":[],"sources":["../../src/react/react.ts"],"mappings":";;;;;AAkBA;;;;;;;;iBAAgB,QAAA,qBAAA,CACd,UAAA,EAAY,CAAA,EACZ,QAAA,GAAW,IAAA,EAAM,QAAA,CAAS,CAAA,MAAO,CAAA,EACjC,OAAA,IAAW,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA,eACnB,CAAA;;;;;;;;;iBAUa,QAAA,kBAAA,CAA2B,UAAA,EAAY,CAAA,GAAI,QAAA,CAAS,CAAA"}
1
+ {"version":3,"file":"react.d.mts","names":[],"sources":["../../src/react/react.ts"],"mappings":";;;;;AAsBA;;;;;;;;iBAAgB,QAAA,qBAAA,CACd,UAAA,EAAY,CAAA,EACZ,QAAA,GAAW,IAAA,EAAM,QAAA,CAAS,CAAA,MAAO,CAAA,EACjC,OAAA,IAAW,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA,eACnB,CAAA;;;;;;;;;iBAUa,QAAA,kBAAA,CAA2B,UAAA,EAAY,CAAA,GAAI,QAAA,CAAS,CAAA;;;;;;;;;;;;AAApE;;;;;;;;;;;;;iBA8JgB,aAAA,kBAAA,CAAgC,OAAA,QAAe,CAAA,GAAI,CAAA"}
@@ -1,6 +1,6 @@
1
- import { a as subscribe, n as getInternal, t as snapshot } from "../snapshot-C8JDLu8L.mjs";
1
+ import { a as subscribe, n as createClassyStore, r as getInternal, t as snapshot } from "../snapshot-COzEerMu.mjs";
2
2
  import { createProxy, isChanged } from "proxy-compare";
3
- import { useCallback, useRef, useSyncExternalStore } from "react";
3
+ import { useCallback, useRef, useState, useSyncExternalStore } from "react";
4
4
 
5
5
  //#region src/react/react.ts
6
6
  function useStore(proxyStore, selector, isEqual) {
@@ -54,7 +54,35 @@ function getAutoTrackSnapshot(proxyStore, affected, proxyCache, prevSnapRef, wra
54
54
  wrappedRef.current = wrapped;
55
55
  return wrapped;
56
56
  }
57
+ /**
58
+ * Create a component-scoped reactive store that lives for the lifetime of the
59
+ * component. When the component unmounts, the store becomes unreferenced and is
60
+ * garbage collected (all internal bookkeeping uses `WeakMap`).
61
+ *
62
+ * The factory function runs **once** per mount (via `useState` initializer).
63
+ * Each component instance gets its own isolated store.
64
+ *
65
+ * Use the returned proxy with `useStore()` to read state in the same component
66
+ * or pass it down via props/context to share within a subtree.
67
+ *
68
+ * @param factory - A function that returns a class instance (or plain object).
69
+ * Called once per component mount.
70
+ * @returns A reactive store proxy scoped to the component's lifetime.
71
+ *
72
+ * @example
73
+ * ```tsx
74
+ * function Counter() {
75
+ * const store = useLocalStore(() => new CounterStore());
76
+ * const count = useStore(store, s => s.count);
77
+ * return <button onClick={() => store.increment()}>{count}</button>;
78
+ * }
79
+ * ```
80
+ */
81
+ function useLocalStore(factory) {
82
+ const [store] = useState(() => createClassyStore(factory()));
83
+ return store;
84
+ }
57
85
 
58
86
  //#endregion
59
- export { useStore };
87
+ export { useLocalStore, useStore };
60
88
  //# sourceMappingURL=react.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"react.mjs","names":["subscribe","coreSubscribe"],"sources":["../../src/react/react.ts"],"sourcesContent":["import {createProxy, isChanged} from 'proxy-compare';\nimport {useCallback, useRef, useSyncExternalStore} from 'react';\nimport {subscribe as coreSubscribe, getInternal} from '../core/core';\nimport {snapshot} from '../snapshot/snapshot';\nimport type {Snapshot} from '../types';\n\n// ── Overloads ─────────────────────────────────────────────────────────────────\n\n/**\n * Subscribe to a store proxy with an explicit selector.\n *\n * Re-renders only when the selected value changes (compared via `Object.is`\n * by default, or a custom `isEqual`).\n *\n * @param proxyStore - A reactive proxy created by `store()`.\n * @param selector - Picks data from the immutable snapshot.\n * @param isEqual - Optional custom equality function (default: `Object.is`).\n */\nexport function useStore<T extends object, S>(\n proxyStore: T,\n selector: (snap: Snapshot<T>) => S,\n isEqual?: (a: S, b: S) => boolean,\n): S;\n\n/**\n * Subscribe to a store proxy **without** a selector (auto-tracked mode).\n *\n * Returns a `proxy-compare` tracking proxy over the immutable snapshot.\n * The component only re-renders when a property it actually read changes.\n *\n * @param proxyStore - A reactive proxy created by `store()`.\n */\nexport function useStore<T extends object>(proxyStore: T): Snapshot<T>;\n\n// ── Implementation ────────────────────────────────────────────────────────────\n\nexport function useStore<T extends object, S>(\n proxyStore: T,\n selector?: (snap: Snapshot<T>) => S,\n isEqual?: (a: S, b: S) => boolean,\n): Snapshot<T> | S {\n // Validate that the argument is actually a store proxy (throws if not).\n getInternal(proxyStore);\n\n // Stable subscribe function (internal identity never changes for a given store).\n const subscribe = useCallback(\n (onStoreChange: () => void) => coreSubscribe(proxyStore, onStoreChange),\n [proxyStore],\n );\n\n // ── Refs used by both modes (always allocated to satisfy Rules of Hooks) ──\n\n // Selector mode refs\n const snapRef = useRef<Snapshot<T> | undefined>(undefined);\n const resultRef = useRef<S | undefined>(undefined);\n\n // Auto-track mode refs\n const affected = useRef(new WeakMap<object, unknown>()).current;\n const proxyCache = useRef(new WeakMap<object, unknown>()).current;\n const prevSnapRef = useRef<Snapshot<T> | undefined>(undefined);\n const wrappedRef = useRef<Snapshot<T> | undefined>(undefined);\n\n // ── Single getSnapshot for useSyncExternalStore ───────────────────────────\n\n const getSnapshot = (): Snapshot<T> | S =>\n selector\n ? getSelectorSnapshot(proxyStore, snapRef, resultRef, selector, isEqual)\n : getAutoTrackSnapshot(\n proxyStore,\n affected,\n proxyCache,\n prevSnapRef,\n wrappedRef,\n );\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n\n// ── Selector mode logic (pure function, no hooks) ─────────────────────────────\n\n/**\n * `getSnapshot` implementation for selector mode.\n *\n * Fast-paths when the snapshot reference hasn't changed (O(1)). Otherwise\n * runs the selector against the new snapshot and compares the result to the\n * previous one via `Object.is` (or a custom `isEqual`). Returns the previous\n * result reference when equal, preventing unnecessary React re-renders.\n *\n * Pure function -- no hooks, safe to call from `useSyncExternalStore`.\n */\nfunction getSelectorSnapshot<T extends object, S>(\n proxyStore: T,\n snapRef: React.RefObject<Snapshot<T> | undefined>,\n resultRef: React.RefObject<S | undefined>,\n selector: (snap: Snapshot<T>) => S,\n isEqual?: (a: S, b: S) => boolean,\n): S {\n const nextSnap = snapshot(proxyStore);\n\n // Fast path: same snapshot reference → same result.\n if (snapRef.current === nextSnap && resultRef.current !== undefined) {\n return resultRef.current;\n }\n\n const nextResult = selector(nextSnap);\n snapRef.current = nextSnap;\n\n // Check equality with previous result.\n if (\n resultRef.current !== undefined &&\n (isEqual\n ? isEqual(resultRef.current, nextResult)\n : Object.is(resultRef.current, nextResult))\n ) {\n return resultRef.current;\n }\n\n resultRef.current = nextResult;\n return nextResult;\n}\n\n// ── Auto-tracked (selectorless) mode logic (pure function, no hooks) ──────────\n\n/**\n * `getSnapshot` implementation for auto-tracked (selectorless) mode.\n *\n * Uses `proxy-compare` to diff only the properties the component actually read.\n * If the snapshot reference is the same, returns the cached tracking proxy.\n * If the snapshot changed but no tracked property differs (`isChanged` returns\n * false), also returns the cached proxy -- avoiding re-render. Only when a\n * relevant property changed does it create a new `createProxy` wrapper.\n *\n * Pure function -- no hooks, safe to call from `useSyncExternalStore`.\n */\nfunction getAutoTrackSnapshot<T extends object>(\n proxyStore: T,\n affected: WeakMap<object, unknown>,\n proxyCache: WeakMap<object, unknown>,\n prevSnapRef: React.RefObject<Snapshot<T> | undefined>,\n wrappedRef: React.RefObject<Snapshot<T> | undefined>,\n): Snapshot<T> {\n const nextSnap = snapshot(proxyStore);\n\n // If the raw snapshot is the same reference, nothing changed.\n if (prevSnapRef.current === nextSnap) {\n return wrappedRef.current as Snapshot<T>;\n }\n\n // Check if any property the component actually read has changed.\n if (\n prevSnapRef.current !== undefined &&\n !isChanged(prevSnapRef.current, nextSnap, affected)\n ) {\n // No property the component cares about changed → return same wrapped proxy.\n return wrappedRef.current as Snapshot<T>;\n }\n\n // Something relevant changed — create a new tracking proxy.\n prevSnapRef.current = nextSnap;\n const wrapped = createProxy(nextSnap, affected, proxyCache) as Snapshot<T>;\n wrappedRef.current = wrapped;\n return wrapped;\n}\n"],"mappings":";;;;;AAoCA,SAAgB,SACd,YACA,UACA,SACiB;AAEjB,aAAY,WAAW;CAGvB,MAAMA,cAAY,aACf,kBAA8BC,UAAc,YAAY,cAAc,EACvE,CAAC,WAAW,CACb;CAKD,MAAM,UAAU,OAAgC,OAAU;CAC1D,MAAM,YAAY,OAAsB,OAAU;CAGlD,MAAM,WAAW,uBAAO,IAAI,SAA0B,CAAC,CAAC;CACxD,MAAM,aAAa,uBAAO,IAAI,SAA0B,CAAC,CAAC;CAC1D,MAAM,cAAc,OAAgC,OAAU;CAC9D,MAAM,aAAa,OAAgC,OAAU;CAI7D,MAAM,oBACJ,WACI,oBAAoB,YAAY,SAAS,WAAW,UAAU,QAAQ,GACtE,qBACE,YACA,UACA,YACA,aACA,WACD;AAEP,QAAO,qBAAqBD,aAAW,aAAa,YAAY;;;;;;;;;;;;AAelE,SAAS,oBACP,YACA,SACA,WACA,UACA,SACG;CACH,MAAM,WAAW,SAAS,WAAW;AAGrC,KAAI,QAAQ,YAAY,YAAY,UAAU,YAAY,OACxD,QAAO,UAAU;CAGnB,MAAM,aAAa,SAAS,SAAS;AACrC,SAAQ,UAAU;AAGlB,KACE,UAAU,YAAY,WACrB,UACG,QAAQ,UAAU,SAAS,WAAW,GACtC,OAAO,GAAG,UAAU,SAAS,WAAW,EAE5C,QAAO,UAAU;AAGnB,WAAU,UAAU;AACpB,QAAO;;;;;;;;;;;;;AAgBT,SAAS,qBACP,YACA,UACA,YACA,aACA,YACa;CACb,MAAM,WAAW,SAAS,WAAW;AAGrC,KAAI,YAAY,YAAY,SAC1B,QAAO,WAAW;AAIpB,KACE,YAAY,YAAY,UACxB,CAAC,UAAU,YAAY,SAAS,UAAU,SAAS,CAGnD,QAAO,WAAW;AAIpB,aAAY,UAAU;CACtB,MAAM,UAAU,YAAY,UAAU,UAAU,WAAW;AAC3D,YAAW,UAAU;AACrB,QAAO"}
1
+ {"version":3,"file":"react.mjs","names":["subscribe","coreSubscribe"],"sources":["../../src/react/react.ts"],"sourcesContent":["import {createProxy, isChanged} from 'proxy-compare';\nimport {useCallback, useRef, useState, useSyncExternalStore} from 'react';\nimport {\n subscribe as coreSubscribe,\n createClassyStore,\n getInternal,\n} from '../core/core';\nimport {snapshot} from '../snapshot/snapshot';\nimport type {Snapshot} from '../types';\n\n// ── Overloads ─────────────────────────────────────────────────────────────────\n\n/**\n * Subscribe to a store proxy with an explicit selector.\n *\n * Re-renders only when the selected value changes (compared via `Object.is`\n * by default, or a custom `isEqual`).\n *\n * @param proxyStore - A reactive proxy created by `store()`.\n * @param selector - Picks data from the immutable snapshot.\n * @param isEqual - Optional custom equality function (default: `Object.is`).\n */\nexport function useStore<T extends object, S>(\n proxyStore: T,\n selector: (snap: Snapshot<T>) => S,\n isEqual?: (a: S, b: S) => boolean,\n): S;\n\n/**\n * Subscribe to a store proxy **without** a selector (auto-tracked mode).\n *\n * Returns a `proxy-compare` tracking proxy over the immutable snapshot.\n * The component only re-renders when a property it actually read changes.\n *\n * @param proxyStore - A reactive proxy created by `store()`.\n */\nexport function useStore<T extends object>(proxyStore: T): Snapshot<T>;\n\n// ── Implementation ────────────────────────────────────────────────────────────\n\nexport function useStore<T extends object, S>(\n proxyStore: T,\n selector?: (snap: Snapshot<T>) => S,\n isEqual?: (a: S, b: S) => boolean,\n): Snapshot<T> | S {\n // Validate that the argument is actually a store proxy (throws if not).\n getInternal(proxyStore);\n\n // Stable subscribe function (internal identity never changes for a given store).\n const subscribe = useCallback(\n (onStoreChange: () => void) => coreSubscribe(proxyStore, onStoreChange),\n [proxyStore],\n );\n\n // ── Refs used by both modes (always allocated to satisfy Rules of Hooks) ──\n\n // Selector mode refs\n const snapRef = useRef<Snapshot<T> | undefined>(undefined);\n const resultRef = useRef<S | undefined>(undefined);\n\n // Auto-track mode refs\n const affected = useRef(new WeakMap<object, unknown>()).current;\n const proxyCache = useRef(new WeakMap<object, unknown>()).current;\n const prevSnapRef = useRef<Snapshot<T> | undefined>(undefined);\n const wrappedRef = useRef<Snapshot<T> | undefined>(undefined);\n\n // ── Single getSnapshot for useSyncExternalStore ───────────────────────────\n\n const getSnapshot = (): Snapshot<T> | S =>\n selector\n ? getSelectorSnapshot(proxyStore, snapRef, resultRef, selector, isEqual)\n : getAutoTrackSnapshot(\n proxyStore,\n affected,\n proxyCache,\n prevSnapRef,\n wrappedRef,\n );\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n\n// ── Selector mode logic (pure function, no hooks) ─────────────────────────────\n\n/**\n * `getSnapshot` implementation for selector mode.\n *\n * Fast-paths when the snapshot reference hasn't changed (O(1)). Otherwise\n * runs the selector against the new snapshot and compares the result to the\n * previous one via `Object.is` (or a custom `isEqual`). Returns the previous\n * result reference when equal, preventing unnecessary React re-renders.\n *\n * Pure function -- no hooks, safe to call from `useSyncExternalStore`.\n */\nfunction getSelectorSnapshot<T extends object, S>(\n proxyStore: T,\n snapRef: React.RefObject<Snapshot<T> | undefined>,\n resultRef: React.RefObject<S | undefined>,\n selector: (snap: Snapshot<T>) => S,\n isEqual?: (a: S, b: S) => boolean,\n): S {\n const nextSnap = snapshot(proxyStore);\n\n // Fast path: same snapshot reference → same result.\n if (snapRef.current === nextSnap && resultRef.current !== undefined) {\n return resultRef.current;\n }\n\n const nextResult = selector(nextSnap);\n snapRef.current = nextSnap;\n\n // Check equality with previous result.\n if (\n resultRef.current !== undefined &&\n (isEqual\n ? isEqual(resultRef.current, nextResult)\n : Object.is(resultRef.current, nextResult))\n ) {\n return resultRef.current;\n }\n\n resultRef.current = nextResult;\n return nextResult;\n}\n\n// ── Auto-tracked (selectorless) mode logic (pure function, no hooks) ──────────\n\n/**\n * `getSnapshot` implementation for auto-tracked (selectorless) mode.\n *\n * Uses `proxy-compare` to diff only the properties the component actually read.\n * If the snapshot reference is the same, returns the cached tracking proxy.\n * If the snapshot changed but no tracked property differs (`isChanged` returns\n * false), also returns the cached proxy -- avoiding re-render. Only when a\n * relevant property changed does it create a new `createProxy` wrapper.\n *\n * Pure function -- no hooks, safe to call from `useSyncExternalStore`.\n */\nfunction getAutoTrackSnapshot<T extends object>(\n proxyStore: T,\n affected: WeakMap<object, unknown>,\n proxyCache: WeakMap<object, unknown>,\n prevSnapRef: React.RefObject<Snapshot<T> | undefined>,\n wrappedRef: React.RefObject<Snapshot<T> | undefined>,\n): Snapshot<T> {\n const nextSnap = snapshot(proxyStore);\n\n // If the raw snapshot is the same reference, nothing changed.\n if (prevSnapRef.current === nextSnap) {\n return wrappedRef.current as Snapshot<T>;\n }\n\n // Check if any property the component actually read has changed.\n if (\n prevSnapRef.current !== undefined &&\n !isChanged(prevSnapRef.current, nextSnap, affected)\n ) {\n // No property the component cares about changed → return same wrapped proxy.\n return wrappedRef.current as Snapshot<T>;\n }\n\n // Something relevant changed — create a new tracking proxy.\n prevSnapRef.current = nextSnap;\n const wrapped = createProxy(nextSnap, affected, proxyCache) as Snapshot<T>;\n wrappedRef.current = wrapped;\n return wrapped;\n}\n\n// ── Component-scoped store ────────────────────────────────────────────────────\n\n/**\n * Create a component-scoped reactive store that lives for the lifetime of the\n * component. When the component unmounts, the store becomes unreferenced and is\n * garbage collected (all internal bookkeeping uses `WeakMap`).\n *\n * The factory function runs **once** per mount (via `useState` initializer).\n * Each component instance gets its own isolated store.\n *\n * Use the returned proxy with `useStore()` to read state in the same component\n * or pass it down via props/context to share within a subtree.\n *\n * @param factory - A function that returns a class instance (or plain object).\n * Called once per component mount.\n * @returns A reactive store proxy scoped to the component's lifetime.\n *\n * @example\n * ```tsx\n * function Counter() {\n * const store = useLocalStore(() => new CounterStore());\n * const count = useStore(store, s => s.count);\n * return <button onClick={() => store.increment()}>{count}</button>;\n * }\n * ```\n */\nexport function useLocalStore<T extends object>(factory: () => T): T {\n const [store] = useState(() => createClassyStore(factory()));\n return store;\n}\n"],"mappings":";;;;;AAwCA,SAAgB,SACd,YACA,UACA,SACiB;AAEjB,aAAY,WAAW;CAGvB,MAAMA,cAAY,aACf,kBAA8BC,UAAc,YAAY,cAAc,EACvE,CAAC,WAAW,CACb;CAKD,MAAM,UAAU,OAAgC,OAAU;CAC1D,MAAM,YAAY,OAAsB,OAAU;CAGlD,MAAM,WAAW,uBAAO,IAAI,SAA0B,CAAC,CAAC;CACxD,MAAM,aAAa,uBAAO,IAAI,SAA0B,CAAC,CAAC;CAC1D,MAAM,cAAc,OAAgC,OAAU;CAC9D,MAAM,aAAa,OAAgC,OAAU;CAI7D,MAAM,oBACJ,WACI,oBAAoB,YAAY,SAAS,WAAW,UAAU,QAAQ,GACtE,qBACE,YACA,UACA,YACA,aACA,WACD;AAEP,QAAO,qBAAqBD,aAAW,aAAa,YAAY;;;;;;;;;;;;AAelE,SAAS,oBACP,YACA,SACA,WACA,UACA,SACG;CACH,MAAM,WAAW,SAAS,WAAW;AAGrC,KAAI,QAAQ,YAAY,YAAY,UAAU,YAAY,OACxD,QAAO,UAAU;CAGnB,MAAM,aAAa,SAAS,SAAS;AACrC,SAAQ,UAAU;AAGlB,KACE,UAAU,YAAY,WACrB,UACG,QAAQ,UAAU,SAAS,WAAW,GACtC,OAAO,GAAG,UAAU,SAAS,WAAW,EAE5C,QAAO,UAAU;AAGnB,WAAU,UAAU;AACpB,QAAO;;;;;;;;;;;;;AAgBT,SAAS,qBACP,YACA,UACA,YACA,aACA,YACa;CACb,MAAM,WAAW,SAAS,WAAW;AAGrC,KAAI,YAAY,YAAY,SAC1B,QAAO,WAAW;AAIpB,KACE,YAAY,YAAY,UACxB,CAAC,UAAU,YAAY,SAAS,UAAU,SAAS,CAGnD,QAAO,WAAW;AAIpB,aAAY,UAAU;CACtB,MAAM,UAAU,YAAY,UAAU,UAAU,WAAW;AAC3D,YAAW,UAAU;AACrB,QAAO;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BT,SAAgB,cAAgC,SAAqB;CACnE,MAAM,CAAC,SAAS,eAAe,kBAAkB,SAAS,CAAC,CAAC;AAC5D,QAAO"}
@@ -87,12 +87,33 @@ function recordDep(internal, prop, value) {
87
87
  });
88
88
  }
89
89
  /**
90
+ * Record a computed getter dependency on the active tracker (if any).
91
+ * Unlike `recordDep`, this creates a `'computed'` dep entry that validates
92
+ * through the computed cache rather than re-executing the raw getter.
93
+ */
94
+ function recordComputedDep(internal, prop, value) {
95
+ const tracker = activeTracker();
96
+ if (!tracker) return;
97
+ if (tracker.internal !== internal) return;
98
+ tracker.deps.push({
99
+ kind: "computed",
100
+ internal,
101
+ prop,
102
+ value
103
+ });
104
+ }
105
+ /**
90
106
  * Check whether all dependencies from a previous computation are still valid.
91
107
  */
92
108
  function areDepsValid(deps) {
93
109
  for (const dep of deps) if (dep.kind === "version") {
94
110
  if (!Object.is(Reflect.get(dep.parentTarget, dep.prop), dep.internal.target)) return false;
95
111
  if (dep.internal.version !== dep.version) return false;
112
+ } else if (dep.kind === "computed") {
113
+ const cached = dep.internal.computedCache.get(dep.prop);
114
+ if (!cached) return false;
115
+ if (!areDepsValid(cached.deps)) return false;
116
+ if (!Object.is(cached.value, dep.value)) return false;
96
117
  } else {
97
118
  if (!Reflect.has(dep.target, dep.prop)) return false;
98
119
  if (!Object.is(Reflect.get(dep.target, dep.prop), dep.value)) return false;
@@ -125,7 +146,7 @@ function evaluateComputed(internal, prop, getterFn, receiver) {
125
146
  }
126
147
  /**
127
148
  * Retrieve the internal bookkeeping for a store proxy.
128
- * Throws if the object was not created with `store()`.
149
+ * Throws if the object was not created with `createClassyStore()`.
129
150
  */
130
151
  function getInternal(proxy) {
131
152
  const internal = internalsMap.get(proxy);
@@ -199,7 +220,11 @@ function createStoreProxy(target, parent) {
199
220
  },
200
221
  get(_target, prop, receiver) {
201
222
  const getterDesc = findGetterDescriptor(_target, prop);
202
- if (getterDesc?.get) return evaluateComputed(internal, prop, getterDesc.get, receiver);
223
+ if (getterDesc?.get) {
224
+ const value = evaluateComputed(internal, prop, getterDesc.get, receiver);
225
+ recordComputedDep(internal, prop, value);
226
+ return value;
227
+ }
203
228
  const value = Reflect.get(_target, prop);
204
229
  if (typeof value === "function") {
205
230
  if (Array.isArray(_target)) return value.bind(receiver);
@@ -247,15 +272,20 @@ function createStoreProxy(target, parent) {
247
272
  *
248
273
  * @param instance - A class instance (or plain object) to make reactive.
249
274
  * @returns The same object wrapped in a reactive Proxy.
275
+ *
276
+ * @example
277
+ * ```ts
278
+ * const myStore = createClassyStore(new MyClass());
279
+ * ```
250
280
  */
251
- function store(instance) {
281
+ function createClassyStore(instance) {
252
282
  return createStoreProxy(instance, null);
253
283
  }
254
284
  /**
255
285
  * Subscribe to store changes. The callback fires once per batched mutation
256
286
  * (coalesced via `queueMicrotask`), not once per individual property write.
257
287
  *
258
- * @param proxy - A reactive proxy created by `store()`.
288
+ * @param proxy - A reactive proxy created by `createClassyStore()`.
259
289
  * @param callback - Invoked after each batched mutation.
260
290
  * @returns An unsubscribe function. Call it to stop receiving notifications.
261
291
  */
@@ -283,7 +313,7 @@ function getVersion(proxy) {
283
313
  * Version-stamped snapshot cache for tracked (proxied) sub-trees.
284
314
  * Key: raw target object → [version, frozen snapshot].
285
315
  */
286
- const snapCache = /* @__PURE__ */ new WeakMap();
316
+ const snapshotCache = /* @__PURE__ */ new WeakMap();
287
317
  /**
288
318
  * Cache for untracked nested objects (never accessed through the proxy).
289
319
  * Key: the raw mutable object → frozen deep clone.
@@ -302,7 +332,7 @@ const snapshotGetterCache = /* @__PURE__ */ new WeakMap();
302
332
  * boundaries: if `this.items` hasn't changed between snapshots (same
303
333
  * reference via structural sharing), the getter returns the same result.
304
334
  */
305
- const crossSnapMemo = /* @__PURE__ */ new WeakMap();
335
+ const crossSnapshotMemo = /* @__PURE__ */ new WeakMap();
306
336
  /**
307
337
  * Run a getter against the snapshot with dependency tracking.
308
338
  *
@@ -336,7 +366,7 @@ function computeWithTracking(snap, getterFn) {
336
366
  * guarantees stable refs for unchanged sub-trees). For getter properties
337
367
  * this invokes the getter (which is itself memoized), then compares.
338
368
  */
339
- function areMemoedDepsValid(currentSnap, deps) {
369
+ function areMemoizedDepsValid(currentSnap, deps) {
340
370
  for (const dep of deps) {
341
371
  const currentValue = Reflect.get(currentSnap, dep.prop, currentSnap);
342
372
  if (!Object.is(currentValue, dep.value)) return false;
@@ -355,16 +385,16 @@ function areMemoedDepsValid(currentSnap, deps) {
355
385
  function evaluateSnapshotGetter(currentSnap, target, key, getterFn) {
356
386
  const perSnapCache = snapshotGetterCache.get(currentSnap);
357
387
  if (perSnapCache?.has(key)) return perSnapCache.get(key);
358
- let memoMap = crossSnapMemo.get(target);
388
+ let memoMap = crossSnapshotMemo.get(target);
359
389
  const prev = memoMap?.get(key);
360
390
  let result;
361
- if (prev && areMemoedDepsValid(currentSnap, prev.deps)) result = prev.result;
391
+ if (prev && areMemoizedDepsValid(currentSnap, prev.deps)) result = prev.result;
362
392
  else {
363
393
  const computation = computeWithTracking(currentSnap, getterFn);
364
394
  result = computation.result;
365
395
  if (!memoMap) {
366
396
  memoMap = /* @__PURE__ */ new Map();
367
- crossSnapMemo.set(target, memoMap);
397
+ crossSnapshotMemo.set(target, memoMap);
368
398
  }
369
399
  memoMap.set(key, {
370
400
  deps: computation.deps,
@@ -478,7 +508,7 @@ function installMemoizedGetters(snap, target) {
478
508
  * are installed as lazy-memoizing accessors via `installMemoizedGetters`.
479
509
  */
480
510
  function createSnapshotRecursive(target, internal) {
481
- const cached = snapCache.get(target);
511
+ const cached = snapshotCache.get(target);
482
512
  if (cached && cached[0] === internal.version) return cached[1];
483
513
  let snap;
484
514
  if (Array.isArray(target)) {
@@ -495,7 +525,7 @@ function createSnapshotRecursive(target, internal) {
495
525
  installMemoizedGetters(snap, target);
496
526
  }
497
527
  Object.freeze(snap);
498
- snapCache.set(target, [internal.version, snap]);
528
+ snapshotCache.set(target, [internal.version, snap]);
499
529
  return snap;
500
530
  }
501
531
  /**
@@ -511,7 +541,7 @@ function createSnapshotRecursive(target, internal) {
511
541
  * per snapshot and their results are stable across snapshots when dependencies
512
542
  * haven't changed (cross-snapshot memoization).
513
543
  *
514
- * @param proxyStore - A reactive proxy created by `store()`.
544
+ * @param proxyStore - A reactive proxy created by `createClassyStore()`.
515
545
  * @returns A deeply frozen plain-JS object (Snapshot<T>).
516
546
  */
517
547
  function snapshot(proxyStore) {
@@ -520,5 +550,5 @@ function snapshot(proxyStore) {
520
550
  }
521
551
 
522
552
  //#endregion
523
- export { subscribe as a, store as i, getInternal as n, PROXYABLE as o, getVersion as r, findGetterDescriptor as s, snapshot as t };
524
- //# sourceMappingURL=snapshot-C8JDLu8L.mjs.map
553
+ export { subscribe as a, getVersion as i, createClassyStore as n, PROXYABLE as o, getInternal as r, findGetterDescriptor as s, snapshot as t };
554
+ //# sourceMappingURL=snapshot-COzEerMu.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot-COzEerMu.mjs","names":[],"sources":["../src/utils/internal/internal.ts","../src/core/core.ts","../src/snapshot/snapshot.ts"],"sourcesContent":["const objectProto = Object.getPrototypeOf({});\n\n/**\n * Symbol that class instances can use to opt-in to deep proxying.\n * Classes with `static [PROXYABLE] = true` will be wrapped by the store proxy\n * just like plain objects, enabling nested reactivity.\n */\nexport const PROXYABLE = Symbol.for('@codebelt/classy-store.proxyable');\n\n/**\n * Returns `true` if `value` is a plain object (created via `{}` or `new Object()`).\n * Needed by `canProxy()` to distinguish plain objects (which should be deep-proxied)\n * from class instances, Date, Map, etc. (which should not).\n */\nexport function isPlainObject(\n value: unknown,\n): value is Record<string | symbol, unknown> {\n if (typeof value !== 'object' || value === null) return false;\n const proto = Object.getPrototypeOf(value);\n return proto === objectProto || proto === null;\n}\n\n/**\n * Central gatekeeper for the proxy system: determines which values get wrapped\n * in child proxies (`core.ts`) or deep-cloned in snapshots (`snapshot.ts`).\n *\n * Returns `true` for arrays, plain objects, and class instances that opt-in\n * via `static [PROXYABLE] = true`. Everything else (Date, Map, Set, class\n * instances without PROXYABLE, primitives) is left as-is.\n */\nexport function canProxy(value: unknown): value is object {\n if (typeof value !== 'object' || value === null) return false;\n if (Array.isArray(value)) return true;\n // Allow class instances that opt-in via the PROXYABLE symbol.\n const ctor = (value as {constructor?: unknown}).constructor;\n if (ctor && (ctor as Record<symbol, unknown>)[PROXYABLE]) {\n return true;\n }\n return isPlainObject(value);\n}\n\n/**\n * Walk the prototype chain of `target` looking for a getter descriptor for `prop`.\n * Returns the first (most-derived) getter found, or `undefined` if none exists.\n *\n * Used by `core.ts` (GET trap) to detect class getters for memoized evaluation,\n * and by `snapshot.ts` to skip own-property copying for getter-backed keys.\n */\nexport function findGetterDescriptor(\n target: object,\n prop: string | symbol,\n): PropertyDescriptor | undefined {\n let proto: object | null = target;\n while (proto) {\n const desc = Object.getOwnPropertyDescriptor(proto, prop);\n if (desc?.get) return desc;\n proto = Object.getPrototypeOf(proto);\n }\n return undefined;\n}\n","import type {DepEntry, StoreInternal} from '../types';\nimport {canProxy, findGetterDescriptor} from '../utils/internal/internal';\n\n// ── Global state ──────────────────────────────────────────────────────────────\n\n/** Global version counter shared across all stores. */\nlet globalVersion = 0;\n\n/** Maps every store proxy → its internal bookkeeping. */\nconst internalsMap = new WeakMap<object, StoreInternal>();\n\n// ── Dependency tracking for computed getters ──────────────────────────────────\n\n/**\n * Stack of active dependency trackers. Each entry records which properties\n * a getter reads during evaluation. A stack (not a single variable) is needed\n * because getter A can read getter B, which pushes a second tracker.\n */\nconst trackerStack: {internal: StoreInternal; deps: DepEntry[]}[] = [];\n\n/** Returns the tracker currently recording deps, or `null` if none is active. */\nfunction activeTracker() {\n return trackerStack.length > 0 ? trackerStack[trackerStack.length - 1] : null;\n}\n\n/**\n * Record a dependency on the active tracker (if any).\n * Called from the GET trap whenever a non-getter, non-method property is read.\n */\nfunction recordDep(\n internal: StoreInternal,\n prop: string | symbol,\n value: unknown,\n): void {\n const tracker = activeTracker();\n if (!tracker) return;\n\n // Only record deps for reads on the SAME proxy that owns the getter.\n // Child-proxy reads don't need explicit tracking because child mutations\n // bubble up via version numbers on the parent's childInternals.\n if (tracker.internal !== internal) return;\n\n const childInternal = internal.childInternals.get(prop);\n if (childInternal) {\n tracker.deps.push({\n kind: 'version',\n internal: childInternal,\n version: childInternal.version,\n parentTarget: internal.target,\n prop,\n });\n } else {\n tracker.deps.push({kind: 'value', target: internal.target, prop, value});\n }\n}\n\n/**\n * Record a computed getter dependency on the active tracker (if any).\n * Unlike `recordDep`, this creates a `'computed'` dep entry that validates\n * through the computed cache rather than re-executing the raw getter.\n */\nfunction recordComputedDep(\n internal: StoreInternal,\n prop: string | symbol,\n value: unknown,\n): void {\n const tracker = activeTracker();\n if (!tracker) return;\n if (tracker.internal !== internal) return;\n\n tracker.deps.push({kind: 'computed', internal, prop, value});\n}\n\n/**\n * Check whether all dependencies from a previous computation are still valid.\n */\nfunction areDepsValid(deps: DepEntry[]): boolean {\n for (const dep of deps) {\n if (dep.kind === 'version') {\n // Verify the parent property still references the same child object.\n // If the property was replaced entirely (e.g., store.items = newArray),\n // the old child internal is detached and its version never changes.\n // This check catches that case.\n if (\n !Object.is(Reflect.get(dep.parentTarget, dep.prop), dep.internal.target)\n )\n return false;\n if (dep.internal.version !== dep.version) return false;\n } else if (dep.kind === 'computed') {\n // Validate through the computed cache — never re-execute the raw getter.\n const cached = dep.internal.computedCache.get(dep.prop);\n if (!cached) return false; // no cache → must recompute\n if (!areDepsValid(cached.deps)) return false; // nested deps changed\n if (!Object.is(cached.value, dep.value)) return false; // value changed\n } else {\n // Check that the property still exists — if it was deleted and\n // dep.value was `undefined`, Object.is(undefined, undefined) would\n // incorrectly pass without this guard.\n if (!Reflect.has(dep.target, dep.prop)) return false;\n if (!Object.is(Reflect.get(dep.target, dep.prop), dep.value))\n return false;\n }\n }\n return true;\n}\n\n/**\n * Evaluate a computed getter with memoization.\n * Returns the cached value if dependencies haven't changed.\n * Otherwise re-evaluates with dependency tracking and caches the result.\n */\nfunction evaluateComputed(\n internal: StoreInternal,\n prop: string | symbol,\n getterFn: () => unknown,\n receiver: object,\n): unknown {\n const cached = internal.computedCache.get(prop);\n if (cached && areDepsValid(cached.deps)) {\n return cached.value;\n }\n\n // Push a new tracker frame for this getter evaluation.\n const frame = {internal, deps: [] as DepEntry[]};\n trackerStack.push(frame);\n try {\n const value = getterFn.call(receiver);\n internal.computedCache.set(prop, {value, deps: frame.deps});\n return value;\n } finally {\n trackerStack.pop();\n }\n}\n\n// ── Public helpers ────────────────────────────────────────────────────────────\n\n/**\n * Retrieve the internal bookkeeping for a store proxy.\n * Throws if the object was not created with `createClassyStore()`.\n */\nexport function getInternal(proxy: object): StoreInternal {\n const internal = internalsMap.get(proxy);\n if (!internal)\n throw new Error('@codebelt/classy-store: object is not a store proxy');\n return internal;\n}\n\n// ── Notification batching ─────────────────────────────────────────────────────\n\n/**\n * Bump version from the mutated node up to the root, invalidate snapshot caches,\n * and schedule a single microtask notification (deduped at the root level).\n *\n * Version propagation is what enables structural sharing in snapshots: unchanged\n * children keep their old version, so the snapshot cache returns the same frozen ref.\n */\nfunction scheduleNotify(internal: StoreInternal): void {\n let current: StoreInternal | null = internal;\n while (current) {\n current.version = ++globalVersion;\n current = current.parent;\n }\n\n const root = getRoot(internal);\n if (!root.notifyScheduled) {\n root.notifyScheduled = true;\n queueMicrotask(() => {\n root.notifyScheduled = false;\n for (const listener of root.listeners) {\n listener();\n }\n });\n }\n}\n\n/** Walk the parent chain to find the root StoreInternal (the notification hub). */\nfunction getRoot(internal: StoreInternal): StoreInternal {\n let current = internal;\n while (current.parent) {\n current = current.parent;\n }\n return current;\n}\n\n// ── Create proxy (recursive) ──────────────────────────────────────────────────\n\n/**\n * Create an ES6 Proxy around `target` with SET/GET/DELETE traps.\n *\n * This is the core of the library's reactivity. The proxy intercepts:\n * - **SET**: compares old/new with `Object.is`, cleans up child proxies on replacement,\n * forwards the write, and schedules a batched notification.\n * - **GET**: detects class getters (memoized), binds methods to the proxy, lazily wraps\n * nested objects/arrays in child proxies, and records dependencies for computed getters.\n * - **DELETE**: cleans up child proxies and schedules notification.\n *\n * Nested objects are recursively wrapped on first access (lazy deep proxy).\n */\nfunction createStoreProxy<T extends object>(\n target: T,\n parent: StoreInternal | null,\n): T {\n const internal: StoreInternal = {\n target,\n version: ++globalVersion,\n listeners: new Set(),\n childProxies: new Map(),\n childInternals: new Map(),\n parent,\n notifyScheduled: false,\n computedCache: new Map(),\n };\n\n /** Cache for bound methods so we return the same reference each time. */\n const boundMethods = new Map<\n string | symbol,\n (...args: unknown[]) => unknown\n >();\n\n const proxy = new Proxy(target, {\n set(_target, prop, value, _receiver) {\n const oldValue = Reflect.get(_target, prop);\n if (Object.is(oldValue, value)) return true; // noop — same value\n\n // If the new value replaces a child proxy, clean it up.\n if (internal.childProxies.has(prop)) {\n internal.childProxies.delete(prop);\n internal.childInternals.delete(prop);\n }\n\n Reflect.set(_target, prop, value);\n scheduleNotify(internal);\n return true;\n },\n\n get(_target, prop, receiver) {\n // 1. Check for getters on the prototype chain (computed values).\n const getterDesc = findGetterDescriptor(_target, prop);\n if (getterDesc?.get) {\n // Memoized: evaluate with dependency tracking, return cached if deps unchanged.\n const value = evaluateComputed(\n internal,\n prop,\n getterDesc.get,\n receiver,\n );\n // Record as a computed dependency for any parent getter currently tracking.\n // Uses 'computed' dep kind so validation goes through the cache, not raw getter.\n recordComputedDep(internal, prop, value);\n return value;\n }\n\n const value = Reflect.get(_target, prop);\n\n // 2. Methods: bind to the proxy so `this.prop = x` goes through SET trap.\n if (typeof value === 'function') {\n // Array prototype methods should not be cached the same way as class methods.\n if (Array.isArray(_target)) {\n return value.bind(receiver);\n }\n const cached = boundMethods.get(prop);\n if (cached) return cached;\n const bound = (value as (...args: unknown[]) => unknown).bind(receiver);\n boundMethods.set(prop, bound);\n return bound;\n }\n\n // 3. Nested plain objects/arrays: lazy-wrap in a child proxy.\n if (canProxy(value)) {\n let childProxy = internal.childProxies.get(prop);\n if (!childProxy) {\n childProxy = createStoreProxy(value as object, internal);\n internal.childProxies.set(prop, childProxy);\n const childInternal = internalsMap.get(childProxy) as StoreInternal;\n internal.childInternals.set(prop, childInternal);\n }\n // Record dependency AFTER ensuring child proxy/internal exists.\n recordDep(internal, prop, value);\n return childProxy;\n }\n\n // 4. Primitives — record dependency and return.\n recordDep(internal, prop, value);\n return value;\n },\n\n deleteProperty(_target, prop) {\n if (internal.childProxies.has(prop)) {\n internal.childProxies.delete(prop);\n internal.childInternals.delete(prop);\n }\n const deleted = Reflect.deleteProperty(_target, prop);\n if (deleted) {\n scheduleNotify(internal);\n }\n return deleted;\n },\n });\n\n internalsMap.set(proxy, internal);\n return proxy;\n}\n\n// ── Public API ────────────────────────────────────────────────────────────────\n\n/**\n * Wraps a class instance in a reactive proxy.\n *\n * - Mutations (property writes, array push/splice, etc.) are intercepted and\n * batched into a single notification per microtask.\n * - Class getters are automatically memoized — they only recompute when a\n * dependency they read changes.\n * - Methods are automatically bound so `this` mutations go through the proxy.\n *\n * @param instance - A class instance (or plain object) to make reactive.\n * @returns The same object wrapped in a reactive Proxy.\n *\n * @example\n * ```ts\n * const myStore = createClassyStore(new MyClass());\n * ```\n */\nexport function createClassyStore<T extends object>(instance: T): T {\n return createStoreProxy(instance, null);\n}\n\n/**\n * Subscribe to store changes. The callback fires once per batched mutation\n * (coalesced via `queueMicrotask`), not once per individual property write.\n *\n * @param proxy - A reactive proxy created by `createClassyStore()`.\n * @param callback - Invoked after each batched mutation.\n * @returns An unsubscribe function. Call it to stop receiving notifications.\n */\nexport function subscribe(proxy: object, callback: () => void): () => void {\n const internal = getInternal(proxy);\n // Always subscribe on the root so notifications fire regardless of\n // whether the user subscribes to the root proxy or a child proxy.\n const root = getRoot(internal);\n root.listeners.add(callback);\n return () => {\n root.listeners.delete(callback);\n };\n}\n\n/**\n * Returns the current version number of a store proxy.\n *\n * Versions are monotonically increasing and bump on any mutation in the\n * store's subtree (child mutations propagate up to the root). Useful for\n * debugging, custom cache invalidation, or testing whether a store has changed.\n */\nexport function getVersion(proxy: object): number {\n return getInternal(proxy).version;\n}\n","import {getInternal} from '../core/core';\nimport type {Snapshot, StoreInternal} from '../types';\nimport {canProxy, findGetterDescriptor} from '../utils/internal/internal';\n\n// ── Caches ────────────────────────────────────────────────────────────────────\n\n/**\n * Version-stamped snapshot cache for tracked (proxied) sub-trees.\n * Key: raw target object → [version, frozen snapshot].\n */\nconst snapshotCache = new WeakMap<object, [version: number, snap: object]>();\n\n/**\n * Cache for untracked nested objects (never accessed through the proxy).\n * Key: the raw mutable object → frozen deep clone.\n * Safe because untracked objects can't be mutated through the proxy.\n */\nconst untrackedCache = new WeakMap<object, object>();\n\n/**\n * Per-snapshot, per-getter cache. Ensures repeated access to the same getter\n * on the same frozen snapshot returns the identical reference.\n */\nconst snapshotGetterCache = new WeakMap<\n object,\n Map<string | symbol, unknown>\n>();\n\n// ── Cross-snapshot getter memoization ─────────────────────────────────────────\n\n/**\n * A dependency recorded during getter execution.\n * prop: the property name read on `this`.\n * value: the value returned (reference).\n */\ntype GetterDep = {prop: string | symbol; value: unknown};\n\n/**\n * Cached result of a snapshot getter with the dependencies it read,\n * used for cross-snapshot memoization. When a new snapshot is created,\n * we check if the deps are still reference-equal (via structural sharing)\n * and return the cached result if so -- avoiding re-execution of the getter.\n */\ntype GetterMemoEntry = {deps: GetterDep[]; result: unknown};\n\n/**\n * Cross-snapshot getter memoization cache.\n * Keyed by raw class instance (target), maps each getter name to its last\n * deps + result. This enables getter result stability across snapshot\n * boundaries: if `this.items` hasn't changed between snapshots (same\n * reference via structural sharing), the getter returns the same result.\n */\nconst crossSnapshotMemo = new WeakMap<\n object,\n Map<string | symbol, GetterMemoEntry>\n>();\n\n/**\n * Run a getter against the snapshot with dependency tracking.\n *\n * Creates a lightweight Proxy that intercepts `this.prop` reads and records\n * which properties (and their values/references) the getter accessed. The\n * Proxy delegates to the real frozen snapshot for actual values, so getters\n * that read other getters trigger the memoized getter chain correctly.\n */\nfunction computeWithTracking(\n snap: object,\n getterFn: () => unknown,\n): {deps: GetterDep[]; result: unknown} {\n const deps: GetterDep[] = [];\n const readProps = new Set<string | symbol>();\n\n // Use an empty non-frozen target — we delegate everything to `snap`.\n const handler: ProxyHandler<object> = {\n get(_dummyTarget, prop, _receiver) {\n // Delegate to the real snapshot (receiver = snap so installed getters\n // run with `this = snap`, triggering their own memoization chain).\n const value = Reflect.get(snap, prop, snap);\n if (!readProps.has(prop)) {\n readProps.add(prop);\n deps.push({prop, value});\n }\n return value;\n },\n };\n\n const tracked = new Proxy({}, handler);\n const result = getterFn.call(tracked);\n return {deps, result};\n}\n\n/**\n * Check if all previously recorded deps still hold on the current snapshot.\n * For data properties this is a reference comparison (structural sharing\n * guarantees stable refs for unchanged sub-trees). For getter properties\n * this invokes the getter (which is itself memoized), then compares.\n */\nfunction areMemoizedDepsValid(currentSnap: object, deps: GetterDep[]): boolean {\n for (const dep of deps) {\n const currentValue = Reflect.get(currentSnap, dep.prop, currentSnap);\n if (!Object.is(currentValue, dep.value)) return false;\n }\n return true;\n}\n\n/**\n * Evaluate a snapshot getter with two layers of caching:\n *\n * 1. **Per-snapshot cache** — same getter on the same frozen snapshot always\n * returns the same reference.\n * 2. **Cross-snapshot memo** — if the properties the getter read last time are\n * structurally the same (reference equality via structural sharing), the\n * previous result is returned without re-running the getter body.\n */\nfunction evaluateSnapshotGetter(\n currentSnap: object,\n target: object,\n key: string | symbol,\n getterFn: () => unknown,\n): unknown {\n // ── Per-snapshot fast path ──\n const perSnapCache = snapshotGetterCache.get(currentSnap);\n if (perSnapCache?.has(key)) return perSnapCache.get(key);\n\n // ── Cross-snapshot memo ──\n let memoMap = crossSnapshotMemo.get(target);\n const prev = memoMap?.get(key);\n\n let result: unknown;\n\n if (prev && areMemoizedDepsValid(currentSnap, prev.deps)) {\n // Dependencies unchanged → reuse previous result.\n result = prev.result;\n } else {\n // Compute fresh with dep tracking.\n const computation = computeWithTracking(currentSnap, getterFn);\n result = computation.result;\n\n // Save cross-snapshot memo.\n if (!memoMap) {\n memoMap = new Map();\n crossSnapshotMemo.set(target, memoMap);\n }\n memoMap.set(key, {deps: computation.deps, result});\n }\n\n // Save per-snapshot cache.\n let cache = snapshotGetterCache.get(currentSnap);\n if (!cache) {\n cache = new Map();\n snapshotGetterCache.set(currentSnap, cache);\n }\n cache.set(key, result);\n\n return result;\n}\n\n// ── Internal helpers ──────────────────────────────────────────────────────────\n\n/**\n * Resolve a single property value into its snapshot equivalent.\n *\n * - If the key has a tracked child internal → recurse (version-cached, structural sharing).\n * - If the value is a nested plain object/array without tracking → deep-clone & freeze (cached by identity).\n * - Otherwise → return the value as-is (primitive, Date, Map, function, etc.).\n */\nfunction snapshotValue(\n value: unknown,\n parentInternal: StoreInternal,\n key: string | symbol,\n): unknown {\n const childInternal = parentInternal.childInternals.get(key);\n if (childInternal) {\n return createSnapshotRecursive(childInternal.target, childInternal);\n }\n if (canProxy(value)) {\n return deepFreezeClone(value as object);\n }\n return value;\n}\n\n/**\n * Deep-clone and freeze a plain object or array that is NOT tracked by a proxy.\n * Cached by raw object identity for structural sharing across snapshots.\n */\nfunction deepFreezeClone(value: object): object {\n const cached = untrackedCache.get(value);\n if (cached) return cached;\n\n let clone: Record<string | symbol, unknown> | unknown[];\n\n if (Array.isArray(value)) {\n clone = [];\n for (let i = 0; i < value.length; i++) {\n const item = value[i];\n (clone as unknown[])[i] = canProxy(item)\n ? deepFreezeClone(item as object)\n : item;\n }\n } else {\n clone = Object.create(Object.getPrototypeOf(value));\n for (const key of Reflect.ownKeys(value)) {\n const desc = Object.getOwnPropertyDescriptor(value, key);\n if (!desc || !('value' in desc)) continue;\n const item = desc.value;\n (clone as Record<string | symbol, unknown>)[key] = canProxy(item)\n ? deepFreezeClone(item as object)\n : item;\n }\n }\n\n Object.freeze(clone);\n untrackedCache.set(value, clone);\n return clone;\n}\n\n/**\n * Collect all getter descriptors from the prototype chain of `target`.\n * Returns an array of [propertyName, getterFunction] pairs.\n *\n * Only includes getters defined on the prototype (class getters), not on the\n * instance itself. When a getter is overridden in a subclass, the most-derived\n * version wins (we walk from the instance's direct prototype upward and skip\n * keys already seen).\n */\nfunction collectGetters(\n target: object,\n): Array<[string | symbol, () => unknown]> {\n const getters: Array<[string | symbol, () => unknown]> = [];\n const seen = new Set<string | symbol>();\n let proto: object | null = Object.getPrototypeOf(target);\n while (proto && proto !== Object.prototype) {\n for (const key of Reflect.ownKeys(proto)) {\n if (key === 'constructor') continue;\n if (seen.has(key)) continue; // most-derived version already collected\n const desc = Object.getOwnPropertyDescriptor(proto, key);\n if (desc?.get) {\n getters.push([key, desc.get]);\n seen.add(key);\n }\n }\n proto = Object.getPrototypeOf(proto);\n }\n return getters;\n}\n\n/**\n * Install lazy-memoizing getters on a snapshot object.\n *\n * Each getter uses cross-snapshot memoization:\n * - Tracks which `this` properties the getter reads on first evaluation.\n * - On subsequent snapshots, if those properties are structurally the same\n * (thanks to structural sharing), the previous result is returned.\n * - Within the same snapshot, repeated accesses always return the same ref.\n */\nfunction installMemoizedGetters(\n snap: Record<string | symbol, unknown>,\n target: object,\n): void {\n const getters = collectGetters(target);\n for (const [key, getterFn] of getters) {\n Object.defineProperty(snap, key, {\n get() {\n return evaluateSnapshotGetter(this as object, target, key, getterFn);\n },\n enumerable: true,\n configurable: true, // required so Object.freeze can make it non-configurable\n });\n }\n}\n\n/**\n * Recursively creates a frozen snapshot from a tracked (proxied) sub-tree.\n *\n * Each node checks its version-stamped cache first (O(1) hit). On a miss,\n * it builds a new frozen object by recursing into child internals (tracked\n * sub-trees) and deep-cloning untracked nested objects. Unchanged children\n * return the same cached reference, achieving structural sharing -- the key\n * to efficient `Object.is` equality in selectors.\n *\n * For class instances, the prototype chain is preserved and class getters\n * are installed as lazy-memoizing accessors via `installMemoizedGetters`.\n */\nfunction createSnapshotRecursive<T extends object>(\n target: T,\n internal: StoreInternal,\n): T {\n // Cache hit: version unchanged → return the same frozen snapshot reference.\n const cached = snapshotCache.get(target);\n if (cached && cached[0] === internal.version) {\n return cached[1] as T;\n }\n\n let snap: Record<string | symbol, unknown> | unknown[];\n\n if (Array.isArray(target)) {\n snap = [];\n for (let i = 0; i < target.length; i++) {\n (snap as unknown[])[i] = snapshotValue(target[i], internal, String(i));\n }\n } else {\n // Preserve the prototype chain and install memoized getters on the snapshot.\n snap = Object.create(Object.getPrototypeOf(target));\n for (const key of Reflect.ownKeys(target)) {\n // Skip prototype getters — they re-evaluate via the preserved prototype.\n if (findGetterDescriptor(target, key)?.get) continue;\n\n const desc = Object.getOwnPropertyDescriptor(target, key);\n if (!desc || !('value' in desc)) continue;\n\n (snap as Record<string | symbol, unknown>)[key] = snapshotValue(\n desc.value,\n internal,\n key,\n );\n }\n\n // Install lazy-memoizing getters with cross-snapshot caching.\n installMemoizedGetters(snap as Record<string | symbol, unknown>, target);\n }\n\n Object.freeze(snap);\n // Cache AFTER populating + freezing. The reference is stable.\n snapshotCache.set(target, [internal.version, snap]);\n return snap as T;\n}\n\n// ── Public API ────────────────────────────────────────────────────────────────\n\n/**\n * Creates an immutable, deeply-frozen snapshot of the store proxy's current state.\n *\n * **Structural sharing:** unchanged sub-trees reuse the previous snapshot's\n * object reference, so `===` comparison can cheaply detect changes.\n *\n * **Version-cached:** calling `snapshot()` multiple times without intervening\n * mutations returns the identical snapshot object (O(1) cache hit).\n *\n * **Getters:** class getters are automatically memoized — they compute once\n * per snapshot and their results are stable across snapshots when dependencies\n * haven't changed (cross-snapshot memoization).\n *\n * @param proxyStore - A reactive proxy created by `createClassyStore()`.\n * @returns A deeply frozen plain-JS object (Snapshot<T>).\n */\nexport function snapshot<T extends object>(proxyStore: T): Snapshot<T> {\n const internal = getInternal(proxyStore);\n return createSnapshotRecursive(internal.target, internal) as Snapshot<T>;\n}\n"],"mappings":"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"}