@codebelt/classy-store 0.0.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.
package/README.md ADDED
@@ -0,0 +1,48 @@
1
+ # @codebelt/classy-store
2
+
3
+ **Class-based reactive state management for React.**
4
+
5
+ [![npm version](https://img.shields.io/npm/v/@codebelt/classy-store.svg)](https://www.npmjs.com/package/@codebelt/classy-store)
6
+ [![CI](https://github.com/codebelt/classy-store/actions/workflows/ci.yml/badge.svg)](https://github.com/codebelt/classy-store/actions/workflows/ci.yml)
7
+ [![License](https://img.shields.io/npm/l/@codebelt/classy-store.svg)](https://github.com/codebelt/classy-store/blob/main/LICENSE)
8
+
9
+ ## 📚 Documentation
10
+
11
+ Visit the **[Documentation Website](https://codebelt.github.io/classy-store/)** for tutorials, API reference, and examples.
12
+
13
+ ## 🚀 Features
14
+
15
+ - **Class-Based**: Define state and logic using standard ES6 classes.
16
+ - **Reactive**: Automatic reactivity using Proxies.
17
+ - **React Integration**: Seamless integration with React 18+ hooks.
18
+ - **TypeScript**: Written in TypeScript with first-class type support.
19
+
20
+ ## 📦 Installation
21
+
22
+ ```bash
23
+ npm install @codebelt/classy-store
24
+ # or
25
+ bun add @codebelt/classy-store
26
+ ```
27
+
28
+ ## 🛠️ Development
29
+
30
+ This project uses [Bun](https://bun.sh) for development.
31
+
32
+ ```bash
33
+ # Install dependencies
34
+ bun install
35
+
36
+ # Run tests
37
+ bun run test
38
+
39
+ # Run build
40
+ bun run build
41
+
42
+ # Start docs website locally
43
+ bun run docs:dev
44
+ ```
45
+
46
+ ## 🤝 Contributing
47
+
48
+ See [CONTRIBUTING.md](./CONTRIBUTING.md) for details on how to contribute and the release workflow.
package/dist/index.cjs ADDED
@@ -0,0 +1,234 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+ const require_snapshot = require('./snapshot-TbHIUjvP.cjs');
3
+ let proxy_compare = require("proxy-compare");
4
+ let react = require("react");
5
+
6
+ //#region src/collections.ts
7
+ /**
8
+ * A Map-like class backed by a plain array so `store()` can proxy mutations.
9
+ *
10
+ * Native `Map` uses internal slots that ES6 Proxy can't intercept, so mutations
11
+ * like `.set()` would be invisible to the store. `ReactiveMap` solves this by
12
+ * storing entries in a plain array (`_entries`) that the proxy can track.
13
+ *
14
+ * Usage:
15
+ * ```ts
16
+ * const myStore = store({ users: reactiveMap<string, User>() });
17
+ * myStore.users.set('id1', { name: 'Alice' }); // reactive
18
+ * ```
19
+ */
20
+ var ReactiveMap = class {
21
+ static [require_snapshot.PROXYABLE] = true;
22
+ /** @internal Backing storage — proxied by store(). */
23
+ _entries = [];
24
+ /** Deduplicates initial entries by key (last value wins, matching native `Map`). */
25
+ constructor(initial) {
26
+ if (initial) for (const [k, v] of initial) {
27
+ const index = this._entries.findIndex(([ek]) => Object.is(ek, k));
28
+ if (index !== -1) this._entries[index] = [k, v];
29
+ else this._entries.push([k, v]);
30
+ }
31
+ }
32
+ /** Returns the number of entries. */
33
+ get size() {
34
+ return this._entries.length;
35
+ }
36
+ /** Returns the value for `key`, or `undefined`. O(n) linear scan. */
37
+ get(key) {
38
+ const entry = this._entries.find(([k]) => Object.is(k, key));
39
+ return entry ? entry[1] : void 0;
40
+ }
41
+ /** Returns `true` if `key` exists. O(n) linear scan. */
42
+ has(key) {
43
+ return this._entries.some(([k]) => Object.is(k, key));
44
+ }
45
+ /** Sets `key` to `value`. Updates in-place if key exists, appends otherwise. */
46
+ set(key, value) {
47
+ const index = this._entries.findIndex(([k]) => Object.is(k, key));
48
+ if (index !== -1) this._entries[index] = [key, value];
49
+ else this._entries.push([key, value]);
50
+ return this;
51
+ }
52
+ /** Removes the entry for `key`. Returns `true` if found. */
53
+ delete(key) {
54
+ const index = this._entries.findIndex(([k]) => Object.is(k, key));
55
+ if (index === -1) return false;
56
+ this._entries.splice(index, 1);
57
+ return true;
58
+ }
59
+ /** Removes all entries. Uses splice to trigger proxy notification. */
60
+ clear() {
61
+ this._entries.splice(0, this._entries.length);
62
+ }
63
+ /** Returns an iterator over the keys. */
64
+ keys() {
65
+ return this._entries.map(([k]) => k)[Symbol.iterator]();
66
+ }
67
+ /** Returns an iterator over the values. */
68
+ values() {
69
+ return this._entries.map(([, v]) => v)[Symbol.iterator]();
70
+ }
71
+ /** Returns an iterator over [key, value] pairs. */
72
+ entries() {
73
+ return this._entries.map(([k, v]) => [k, v])[Symbol.iterator]();
74
+ }
75
+ /** Calls `callback` for each entry, matching the native `Map.forEach` signature. */
76
+ forEach(callback) {
77
+ for (const [k, v] of this._entries) callback(v, k, this);
78
+ }
79
+ /** Enables `for...of` iteration over [key, value] pairs. */
80
+ [Symbol.iterator]() {
81
+ return this.entries();
82
+ }
83
+ };
84
+ /**
85
+ * A Set-like class backed by a plain array so `store()` can proxy mutations.
86
+ *
87
+ * Native `Set` uses internal slots that ES6 Proxy can't intercept, so mutations
88
+ * like `.add()` would be invisible to the store. `ReactiveSet` solves this by
89
+ * storing items in a plain array (`_items`) that the proxy can track.
90
+ *
91
+ * Usage:
92
+ * ```ts
93
+ * const myStore = store({ tags: reactiveSet<string>(['urgent']) });
94
+ * myStore.tags.add('bug'); // reactive
95
+ * ```
96
+ */
97
+ var ReactiveSet = class {
98
+ static [require_snapshot.PROXYABLE] = true;
99
+ /** @internal Backing storage — proxied by store(). */
100
+ _items = [];
101
+ /** Deduplicates initial values using `Object.is` comparison. */
102
+ constructor(initial) {
103
+ if (initial) {
104
+ for (const v of initial) if (!this._items.some((item) => Object.is(item, v))) this._items.push(v);
105
+ }
106
+ }
107
+ /** Returns the number of unique items. */
108
+ get size() {
109
+ return this._items.length;
110
+ }
111
+ /** Returns `true` if `value` exists. O(n) linear scan. */
112
+ has(value) {
113
+ return this._items.some((item) => Object.is(item, value));
114
+ }
115
+ /** Adds `value` if not already present (no-op for duplicates). */
116
+ add(value) {
117
+ if (!this.has(value)) this._items.push(value);
118
+ return this;
119
+ }
120
+ /** Removes `value`. Returns `true` if found. */
121
+ delete(value) {
122
+ const index = this._items.findIndex((item) => Object.is(item, value));
123
+ if (index === -1) return false;
124
+ this._items.splice(index, 1);
125
+ return true;
126
+ }
127
+ /** Removes all items. Uses splice to trigger proxy notification. */
128
+ clear() {
129
+ this._items.splice(0, this._items.length);
130
+ }
131
+ /** Returns an iterator over the values (same as `values()`, matching Set API). */
132
+ keys() {
133
+ return this._items[Symbol.iterator]();
134
+ }
135
+ /** Returns an iterator over the values. */
136
+ values() {
137
+ return this._items[Symbol.iterator]();
138
+ }
139
+ /** Returns an iterator over [value, value] pairs, matching the native Set API. */
140
+ entries() {
141
+ return this._items.map((v) => [v, v])[Symbol.iterator]();
142
+ }
143
+ /** Calls `callback` for each item, matching the native `Set.forEach` signature. */
144
+ forEach(callback) {
145
+ for (const v of this._items) callback(v, v, this);
146
+ }
147
+ /** Enables `for...of` iteration over values. */
148
+ [Symbol.iterator]() {
149
+ return this.values();
150
+ }
151
+ };
152
+ /**
153
+ * Creates a reactive Map-like collection backed by a plain array.
154
+ * Wrap the parent object with `store()` for full reactivity.
155
+ *
156
+ * @param initial - Optional iterable of `[key, value]` pairs.
157
+ */
158
+ function reactiveMap(initial) {
159
+ return new ReactiveMap(initial);
160
+ }
161
+ /**
162
+ * Creates a reactive Set-like collection backed by a plain array.
163
+ * Wrap the parent object with `store()` for full reactivity.
164
+ *
165
+ * @param initial - Optional iterable of values.
166
+ */
167
+ function reactiveSet(initial) {
168
+ return new ReactiveSet(initial);
169
+ }
170
+
171
+ //#endregion
172
+ //#region src/useStore.ts
173
+ function useStore(proxyStore, selector, isEqual) {
174
+ require_snapshot.getInternal(proxyStore);
175
+ const subscribe$1 = (0, react.useCallback)((onStoreChange) => require_snapshot.subscribe(proxyStore, onStoreChange), [proxyStore]);
176
+ const snapRef = (0, react.useRef)(void 0);
177
+ const resultRef = (0, react.useRef)(void 0);
178
+ const affected = (0, react.useRef)(/* @__PURE__ */ new WeakMap()).current;
179
+ const proxyCache = (0, react.useRef)(/* @__PURE__ */ new WeakMap()).current;
180
+ const prevSnapRef = (0, react.useRef)(void 0);
181
+ const wrappedRef = (0, react.useRef)(void 0);
182
+ const getSnapshot = () => selector ? getSelectorSnapshot(proxyStore, snapRef, resultRef, selector, isEqual) : getAutoTrackSnapshot(proxyStore, affected, proxyCache, prevSnapRef, wrappedRef);
183
+ return (0, react.useSyncExternalStore)(subscribe$1, getSnapshot, getSnapshot);
184
+ }
185
+ /**
186
+ * `getSnapshot` implementation for selector mode.
187
+ *
188
+ * Fast-paths when the snapshot reference hasn't changed (O(1)). Otherwise
189
+ * runs the selector against the new snapshot and compares the result to the
190
+ * previous one via `Object.is` (or a custom `isEqual`). Returns the previous
191
+ * result reference when equal, preventing unnecessary React re-renders.
192
+ *
193
+ * Pure function -- no hooks, safe to call from `useSyncExternalStore`.
194
+ */
195
+ function getSelectorSnapshot(proxyStore, snapRef, resultRef, selector, isEqual) {
196
+ const nextSnap = require_snapshot.snapshot(proxyStore);
197
+ if (snapRef.current === nextSnap && resultRef.current !== void 0) return resultRef.current;
198
+ const nextResult = selector(nextSnap);
199
+ snapRef.current = nextSnap;
200
+ if (resultRef.current !== void 0 && (isEqual ? isEqual(resultRef.current, nextResult) : Object.is(resultRef.current, nextResult))) return resultRef.current;
201
+ resultRef.current = nextResult;
202
+ return nextResult;
203
+ }
204
+ /**
205
+ * `getSnapshot` implementation for auto-tracked (selectorless) mode.
206
+ *
207
+ * Uses `proxy-compare` to diff only the properties the component actually read.
208
+ * If the snapshot reference is the same, returns the cached tracking proxy.
209
+ * If the snapshot changed but no tracked property differs (`isChanged` returns
210
+ * false), also returns the cached proxy -- avoiding re-render. Only when a
211
+ * relevant property changed does it create a new `createProxy` wrapper.
212
+ *
213
+ * Pure function -- no hooks, safe to call from `useSyncExternalStore`.
214
+ */
215
+ function getAutoTrackSnapshot(proxyStore, affected, proxyCache, prevSnapRef, wrappedRef) {
216
+ const nextSnap = require_snapshot.snapshot(proxyStore);
217
+ if (prevSnapRef.current === nextSnap) return wrappedRef.current;
218
+ if (prevSnapRef.current !== void 0 && !(0, proxy_compare.isChanged)(prevSnapRef.current, nextSnap, affected)) return wrappedRef.current;
219
+ prevSnapRef.current = nextSnap;
220
+ const wrapped = (0, proxy_compare.createProxy)(nextSnap, affected, proxyCache);
221
+ wrappedRef.current = wrapped;
222
+ return wrapped;
223
+ }
224
+
225
+ //#endregion
226
+ exports.getVersion = require_snapshot.getVersion;
227
+ exports.reactiveMap = reactiveMap;
228
+ exports.reactiveSet = reactiveSet;
229
+ exports.shallowEqual = require_snapshot.shallowEqual;
230
+ exports.snapshot = require_snapshot.snapshot;
231
+ exports.store = require_snapshot.store;
232
+ exports.subscribe = require_snapshot.subscribe;
233
+ exports.useStore = useStore;
234
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","names":["PROXYABLE","subscribe","coreSubscribe","snapshot"],"sources":["../src/collections.ts","../src/useStore.ts"],"sourcesContent":["import {PROXYABLE} from './utils';\n\n// ── ReactiveMap ───────────────────────────────────────────────────────────────\n\n/**\n * A Map-like class backed by a plain array so `store()` can proxy mutations.\n *\n * Native `Map` uses internal slots that ES6 Proxy can't intercept, so mutations\n * like `.set()` would be invisible to the store. `ReactiveMap` solves this by\n * storing entries in a plain array (`_entries`) that the proxy can track.\n *\n * Usage:\n * ```ts\n * const myStore = store({ users: reactiveMap<string, User>() });\n * myStore.users.set('id1', { name: 'Alice' }); // reactive\n * ```\n */\nexport class ReactiveMap<K, V> {\n static [PROXYABLE] = true;\n\n /** @internal Backing storage — proxied by store(). */\n _entries: [K, V][] = [];\n\n /** Deduplicates initial entries by key (last value wins, matching native `Map`). */\n constructor(initial?: Iterable<[K, V]>) {\n if (initial) {\n for (const [k, v] of initial) {\n const index = this._entries.findIndex(([ek]) => Object.is(ek, k));\n if (index !== -1) {\n this._entries[index] = [k, v];\n } else {\n this._entries.push([k, v]);\n }\n }\n }\n }\n\n /** Returns the number of entries. */\n get size(): number {\n return this._entries.length;\n }\n\n /** Returns the value for `key`, or `undefined`. O(n) linear scan. */\n get(key: K): V | undefined {\n const entry = this._entries.find(([k]) => Object.is(k, key));\n return entry ? entry[1] : undefined;\n }\n\n /** Returns `true` if `key` exists. O(n) linear scan. */\n has(key: K): boolean {\n return this._entries.some(([k]) => Object.is(k, key));\n }\n\n /** Sets `key` to `value`. Updates in-place if key exists, appends otherwise. */\n set(key: K, value: V): this {\n const index = this._entries.findIndex(([k]) => Object.is(k, key));\n if (index !== -1) {\n this._entries[index] = [key, value];\n } else {\n this._entries.push([key, value]);\n }\n return this;\n }\n\n /** Removes the entry for `key`. Returns `true` if found. */\n delete(key: K): boolean {\n const index = this._entries.findIndex(([k]) => Object.is(k, key));\n if (index === -1) return false;\n this._entries.splice(index, 1);\n return true;\n }\n\n /** Removes all entries. Uses splice to trigger proxy notification. */\n clear(): void {\n this._entries.splice(0, this._entries.length);\n }\n\n /** Returns an iterator over the keys. */\n keys(): IterableIterator<K> {\n return this._entries.map(([k]) => k)[Symbol.iterator]();\n }\n\n /** Returns an iterator over the values. */\n values(): IterableIterator<V> {\n return this._entries.map(([, v]) => v)[Symbol.iterator]();\n }\n\n /** Returns an iterator over [key, value] pairs. */\n entries(): IterableIterator<[K, V]> {\n return this._entries.map(([k, v]) => [k, v] as [K, V])[Symbol.iterator]();\n }\n\n /** Calls `callback` for each entry, matching the native `Map.forEach` signature. */\n forEach(callback: (value: V, key: K, map: ReactiveMap<K, V>) => void): void {\n for (const [k, v] of this._entries) {\n callback(v, k, this);\n }\n }\n\n /** Enables `for...of` iteration over [key, value] pairs. */\n [Symbol.iterator](): IterableIterator<[K, V]> {\n return this.entries();\n }\n}\n\n// ── ReactiveSet ───────────────────────────────────────────────────────────────\n\n/**\n * A Set-like class backed by a plain array so `store()` can proxy mutations.\n *\n * Native `Set` uses internal slots that ES6 Proxy can't intercept, so mutations\n * like `.add()` would be invisible to the store. `ReactiveSet` solves this by\n * storing items in a plain array (`_items`) that the proxy can track.\n *\n * Usage:\n * ```ts\n * const myStore = store({ tags: reactiveSet<string>(['urgent']) });\n * myStore.tags.add('bug'); // reactive\n * ```\n */\nexport class ReactiveSet<T> {\n static [PROXYABLE] = true;\n\n /** @internal Backing storage — proxied by store(). */\n _items: T[] = [];\n\n /** Deduplicates initial values using `Object.is` comparison. */\n constructor(initial?: Iterable<T>) {\n if (initial) {\n for (const v of initial) {\n if (!this._items.some((item) => Object.is(item, v))) {\n this._items.push(v);\n }\n }\n }\n }\n\n /** Returns the number of unique items. */\n get size(): number {\n return this._items.length;\n }\n\n /** Returns `true` if `value` exists. O(n) linear scan. */\n has(value: T): boolean {\n return this._items.some((item) => Object.is(item, value));\n }\n\n /** Adds `value` if not already present (no-op for duplicates). */\n add(value: T): this {\n if (!this.has(value)) {\n this._items.push(value);\n }\n return this;\n }\n\n /** Removes `value`. Returns `true` if found. */\n delete(value: T): boolean {\n const index = this._items.findIndex((item) => Object.is(item, value));\n if (index === -1) return false;\n this._items.splice(index, 1);\n return true;\n }\n\n /** Removes all items. Uses splice to trigger proxy notification. */\n clear(): void {\n this._items.splice(0, this._items.length);\n }\n\n /** Returns an iterator over the values (same as `values()`, matching Set API). */\n keys(): IterableIterator<T> {\n return this._items[Symbol.iterator]();\n }\n\n /** Returns an iterator over the values. */\n values(): IterableIterator<T> {\n return this._items[Symbol.iterator]();\n }\n\n /** Returns an iterator over [value, value] pairs, matching the native Set API. */\n entries(): IterableIterator<[T, T]> {\n return this._items.map((v) => [v, v] as [T, T])[Symbol.iterator]();\n }\n\n /** Calls `callback` for each item, matching the native `Set.forEach` signature. */\n forEach(callback: (value: T, key: T, set: ReactiveSet<T>) => void): void {\n for (const v of this._items) {\n callback(v, v, this);\n }\n }\n\n /** Enables `for...of` iteration over values. */\n [Symbol.iterator](): IterableIterator<T> {\n return this.values();\n }\n}\n\n// ── Factory functions ─────────────────────────────────────────────────────────\n\n/**\n * Creates a reactive Map-like collection backed by a plain array.\n * Wrap the parent object with `store()` for full reactivity.\n *\n * @param initial - Optional iterable of `[key, value]` pairs.\n */\nexport function reactiveMap<K, V>(\n initial?: Iterable<[K, V]>,\n): ReactiveMap<K, V> {\n return new ReactiveMap(initial);\n}\n\n/**\n * Creates a reactive Set-like collection backed by a plain array.\n * Wrap the parent object with `store()` for full reactivity.\n *\n * @param initial - Optional iterable of values.\n */\nexport function reactiveSet<T>(initial?: Iterable<T>): ReactiveSet<T> {\n return new ReactiveSet(initial);\n}\n","import {createProxy, isChanged} from 'proxy-compare';\nimport {useCallback, useRef, useSyncExternalStore} from 'react';\nimport {subscribe as coreSubscribe, getInternal} from './core';\nimport {snapshot} from './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":"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"}
@@ -0,0 +1,215 @@
1
+ //#region src/utils.d.ts
2
+ /**
3
+ * Symbol that class instances can use to opt-in to deep proxying.
4
+ * Classes with `static [PROXYABLE] = true` will be wrapped by the store proxy
5
+ * just like plain objects, enabling nested reactivity.
6
+ */
7
+ declare const PROXYABLE: unique symbol;
8
+ /**
9
+ * Shallow-equal comparison for objects and arrays.
10
+ * Useful as a custom `isEqual` for `useStore` selectors that return objects/arrays.
11
+ *
12
+ * - Primitives compared with `Object.is`.
13
+ * - Arrays: length + element-wise `Object.is`.
14
+ * - Objects: key count + value-wise `Object.is`.
15
+ */
16
+ declare function shallowEqual<T>(a: T, b: T): boolean;
17
+ //#endregion
18
+ //#region src/collections.d.ts
19
+ /**
20
+ * A Map-like class backed by a plain array so `store()` can proxy mutations.
21
+ *
22
+ * Native `Map` uses internal slots that ES6 Proxy can't intercept, so mutations
23
+ * like `.set()` would be invisible to the store. `ReactiveMap` solves this by
24
+ * storing entries in a plain array (`_entries`) that the proxy can track.
25
+ *
26
+ * Usage:
27
+ * ```ts
28
+ * const myStore = store({ users: reactiveMap<string, User>() });
29
+ * myStore.users.set('id1', { name: 'Alice' }); // reactive
30
+ * ```
31
+ */
32
+ declare class ReactiveMap<K, V> {
33
+ static [PROXYABLE]: boolean;
34
+ /** @internal Backing storage — proxied by store(). */
35
+ _entries: [K, V][];
36
+ /** Deduplicates initial entries by key (last value wins, matching native `Map`). */
37
+ constructor(initial?: Iterable<[K, V]>);
38
+ /** Returns the number of entries. */
39
+ get size(): number;
40
+ /** Returns the value for `key`, or `undefined`. O(n) linear scan. */
41
+ get(key: K): V | undefined;
42
+ /** Returns `true` if `key` exists. O(n) linear scan. */
43
+ has(key: K): boolean;
44
+ /** Sets `key` to `value`. Updates in-place if key exists, appends otherwise. */
45
+ set(key: K, value: V): this;
46
+ /** Removes the entry for `key`. Returns `true` if found. */
47
+ delete(key: K): boolean;
48
+ /** Removes all entries. Uses splice to trigger proxy notification. */
49
+ clear(): void;
50
+ /** Returns an iterator over the keys. */
51
+ keys(): IterableIterator<K>;
52
+ /** Returns an iterator over the values. */
53
+ values(): IterableIterator<V>;
54
+ /** Returns an iterator over [key, value] pairs. */
55
+ entries(): IterableIterator<[K, V]>;
56
+ /** Calls `callback` for each entry, matching the native `Map.forEach` signature. */
57
+ forEach(callback: (value: V, key: K, map: ReactiveMap<K, V>) => void): void;
58
+ /** Enables `for...of` iteration over [key, value] pairs. */
59
+ [Symbol.iterator](): IterableIterator<[K, V]>;
60
+ }
61
+ /**
62
+ * A Set-like class backed by a plain array so `store()` can proxy mutations.
63
+ *
64
+ * Native `Set` uses internal slots that ES6 Proxy can't intercept, so mutations
65
+ * like `.add()` would be invisible to the store. `ReactiveSet` solves this by
66
+ * storing items in a plain array (`_items`) that the proxy can track.
67
+ *
68
+ * Usage:
69
+ * ```ts
70
+ * const myStore = store({ tags: reactiveSet<string>(['urgent']) });
71
+ * myStore.tags.add('bug'); // reactive
72
+ * ```
73
+ */
74
+ declare class ReactiveSet<T> {
75
+ static [PROXYABLE]: boolean;
76
+ /** @internal Backing storage — proxied by store(). */
77
+ _items: T[];
78
+ /** Deduplicates initial values using `Object.is` comparison. */
79
+ constructor(initial?: Iterable<T>);
80
+ /** Returns the number of unique items. */
81
+ get size(): number;
82
+ /** Returns `true` if `value` exists. O(n) linear scan. */
83
+ has(value: T): boolean;
84
+ /** Adds `value` if not already present (no-op for duplicates). */
85
+ add(value: T): this;
86
+ /** Removes `value`. Returns `true` if found. */
87
+ delete(value: T): boolean;
88
+ /** Removes all items. Uses splice to trigger proxy notification. */
89
+ clear(): void;
90
+ /** Returns an iterator over the values (same as `values()`, matching Set API). */
91
+ keys(): IterableIterator<T>;
92
+ /** Returns an iterator over the values. */
93
+ values(): IterableIterator<T>;
94
+ /** Returns an iterator over [value, value] pairs, matching the native Set API. */
95
+ entries(): IterableIterator<[T, T]>;
96
+ /** Calls `callback` for each item, matching the native `Set.forEach` signature. */
97
+ forEach(callback: (value: T, key: T, set: ReactiveSet<T>) => void): void;
98
+ /** Enables `for...of` iteration over values. */
99
+ [Symbol.iterator](): IterableIterator<T>;
100
+ }
101
+ /**
102
+ * Creates a reactive Map-like collection backed by a plain array.
103
+ * Wrap the parent object with `store()` for full reactivity.
104
+ *
105
+ * @param initial - Optional iterable of `[key, value]` pairs.
106
+ */
107
+ declare function reactiveMap<K, V>(initial?: Iterable<[K, V]>): ReactiveMap<K, V>;
108
+ /**
109
+ * Creates a reactive Set-like collection backed by a plain array.
110
+ * Wrap the parent object with `store()` for full reactivity.
111
+ *
112
+ * @param initial - Optional iterable of values.
113
+ */
114
+ declare function reactiveSet<T>(initial?: Iterable<T>): ReactiveSet<T>;
115
+ //#endregion
116
+ //#region src/types.d.ts
117
+ /**
118
+ * Primitive types that should not be proxied or snapshot-cloned.
119
+ * Used by `Snapshot<T>` to identify leaf types that pass through unchanged.
120
+ */
121
+ type Primitive = string | number | boolean | null | undefined | symbol | bigint;
122
+ /**
123
+ * Function type shorthand.
124
+ * Functions are treated as snapshot leaves -- they pass through unchanged
125
+ * because freezing or cloning them would break callable references.
126
+ */
127
+ type AnyFunction = (...args: unknown[]) => unknown;
128
+ /**
129
+ * Types that `snapshot()` returns as-is (no deep clone or freeze).
130
+ * These are either already immutable-ish (Date, RegExp), use internal slots
131
+ * that proxies can't intercept (Map, Set, WeakMap, WeakSet), or can't be
132
+ * meaningfully frozen (functions, Promises, Errors).
133
+ */
134
+ type SnapshotLeaf = Primitive | AnyFunction | Date | RegExp | Error | Map<unknown, unknown> | Set<unknown> | WeakMap<object, unknown> | WeakSet<object> | Promise<unknown>;
135
+ /**
136
+ * Recursively converts an object type to a deeply readonly version.
137
+ * Leaf types (primitives, Date, Map, etc.) pass through unchanged.
138
+ */
139
+ type Snapshot<T> = T extends SnapshotLeaf ? T : T extends Array<infer U> ? ReadonlyArray<Snapshot<U>> : T extends object ? { readonly [K in keyof T]: Snapshot<T[K]> } : T;
140
+ //#endregion
141
+ //#region src/core.d.ts
142
+ /**
143
+ * Wraps a class instance in a reactive proxy.
144
+ *
145
+ * - Mutations (property writes, array push/splice, etc.) are intercepted and
146
+ * batched into a single notification per microtask.
147
+ * - Class getters are automatically memoized — they only recompute when a
148
+ * dependency they read changes.
149
+ * - Methods are automatically bound so `this` mutations go through the proxy.
150
+ *
151
+ * @param instance - A class instance (or plain object) to make reactive.
152
+ * @returns The same object wrapped in a reactive Proxy.
153
+ */
154
+ declare function store<T extends object>(instance: T): T;
155
+ /**
156
+ * Subscribe to store changes. The callback fires once per batched mutation
157
+ * (coalesced via `queueMicrotask`), not once per individual property write.
158
+ *
159
+ * @param proxy - A reactive proxy created by `store()`.
160
+ * @param callback - Invoked after each batched mutation.
161
+ * @returns An unsubscribe function. Call it to stop receiving notifications.
162
+ */
163
+ declare function subscribe(proxy: object, callback: () => void): () => void;
164
+ /**
165
+ * Returns the current version number of a store proxy.
166
+ *
167
+ * Versions are monotonically increasing and bump on any mutation in the
168
+ * store's subtree (child mutations propagate up to the root). Useful for
169
+ * debugging, custom cache invalidation, or testing whether a store has changed.
170
+ */
171
+ declare function getVersion(proxy: object): number;
172
+ //#endregion
173
+ //#region src/snapshot.d.ts
174
+ /**
175
+ * Creates an immutable, deeply-frozen snapshot of the store proxy's current state.
176
+ *
177
+ * **Structural sharing:** unchanged sub-trees reuse the previous snapshot's
178
+ * object reference, so `===` comparison can cheaply detect changes.
179
+ *
180
+ * **Version-cached:** calling `snapshot()` multiple times without intervening
181
+ * mutations returns the identical snapshot object (O(1) cache hit).
182
+ *
183
+ * **Getters:** class getters are automatically memoized — they compute once
184
+ * per snapshot and their results are stable across snapshots when dependencies
185
+ * haven't changed (cross-snapshot memoization).
186
+ *
187
+ * @param proxyStore - A reactive proxy created by `store()`.
188
+ * @returns A deeply frozen plain-JS object (Snapshot<T>).
189
+ */
190
+ declare function snapshot<T extends object>(proxyStore: T): Snapshot<T>;
191
+ //#endregion
192
+ //#region src/useStore.d.ts
193
+ /**
194
+ * Subscribe to a store proxy with an explicit selector.
195
+ *
196
+ * Re-renders only when the selected value changes (compared via `Object.is`
197
+ * by default, or a custom `isEqual`).
198
+ *
199
+ * @param proxyStore - A reactive proxy created by `store()`.
200
+ * @param selector - Picks data from the immutable snapshot.
201
+ * @param isEqual - Optional custom equality function (default: `Object.is`).
202
+ */
203
+ declare function useStore<T extends object, S>(proxyStore: T, selector: (snap: Snapshot<T>) => S, isEqual?: (a: S, b: S) => boolean): S;
204
+ /**
205
+ * Subscribe to a store proxy **without** a selector (auto-tracked mode).
206
+ *
207
+ * Returns a `proxy-compare` tracking proxy over the immutable snapshot.
208
+ * The component only re-renders when a property it actually read changes.
209
+ *
210
+ * @param proxyStore - A reactive proxy created by `store()`.
211
+ */
212
+ declare function useStore<T extends object>(proxyStore: T): Snapshot<T>;
213
+ //#endregion
214
+ export { type ReactiveMap, type ReactiveSet, type Snapshot, getVersion, reactiveMap, reactiveSet, shallowEqual, snapshot, store, subscribe, useStore };
215
+ //# sourceMappingURL=index.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/utils.ts","../src/collections.ts","../src/types.ts","../src/core.ts","../src/snapshot.ts","../src/useStore.ts"],"mappings":"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"}