|
| 1 | +# CLAUDE.md — @codebelt/classy-store |
| 2 | + |
| 3 | +Context for Claude Code sessions in this monorepo. |
| 4 | + |
| 5 | +## What This Library Is |
| 6 | + |
| 7 | +`@codebelt/classy-store` is a class-based reactive state management library (~2.3 KB gzipped) for React, Vue, Svelte, Solid, and Angular. You define state as a plain TypeScript class, wrap it with `createClassyStore()`, and get a reactive proxy back. Class getters become automatically memoized computed values. ES6 Proxy intercepts mutations, batches them via `queueMicrotask`, and notifies framework-specific bindings via immutable snapshots with structural sharing. |
| 8 | + |
| 9 | +## Monorepo Layout |
| 10 | + |
| 11 | +``` |
| 12 | +packages/classy-store/src/ |
| 13 | +├── core/core.ts # Layer 1: Write Proxy — createClassyStore(), subscribe(), getVersion() |
| 14 | +├── snapshot/snapshot.ts # Layer 2: Immutable snapshots — snapshot(), structural sharing |
| 15 | +├── types.ts # Snapshot<T>, StoreInternal, DepEntry, ComputedEntry |
| 16 | +├── index.ts # Main barrel: createClassyStore, snapshot, subscribe, getVersion, shallowEqual, reactiveMap, reactiveSet |
| 17 | +├── collections/collections.ts # ReactiveMap and ReactiveSet (array-backed Map/Set emulation) |
| 18 | +├── frameworks/ |
| 19 | +│ ├── react/react.ts # Layer 3 (React): useStore(), useLocalStore() via useSyncExternalStore |
| 20 | +│ ├── vue/vue.ts # Vue: useStore() → ShallowRef<Snapshot<T>> (onUnmounted cleanup) |
| 21 | +│ ├── svelte/svelte.ts # Svelte: toSvelteStore() → ClassyReadable<Snapshot<T>> |
| 22 | +│ ├── solid/solid.ts # Solid: useStore() → () => Snapshot<T> signal (onCleanup) |
| 23 | +│ └── angular/angular.ts # Angular: injectStore() → Signal<Snapshot<T>> (DestroyRef) |
| 24 | +└── utils/ |
| 25 | + ├── index.ts # Utils barrel: persist, devtools, subscribeKey, withHistory |
| 26 | + ├── persist/persist.ts # persist() — storage, transforms, versioning, cross-tab sync, TTL |
| 27 | + ├── devtools/devtools.ts # devtools() — Redux DevTools integration, time-travel |
| 28 | + ├── history/history.ts # withHistory() — undo/redo via snapshot stack, pause/resume |
| 29 | + ├── subscribe-key/subscribe-key.ts # subscribeKey() — single-property subscription |
| 30 | + ├── equality/equality.ts # shallowEqual |
| 31 | + └── internal/internal.ts # isPlainObject, canProxy, findGetterDescriptor, PROXYABLE |
| 32 | +
|
| 33 | +website/ # Docusaurus documentation site |
| 34 | +website/docs/ # .md source for all doc pages |
| 35 | +website/static/ # Served verbatim at site root (llms.txt, llms-full.txt, etc.) |
| 36 | +
|
| 37 | +examples/ # Framework demo examples |
| 38 | +``` |
| 39 | + |
| 40 | +## Key Technical Facts |
| 41 | + |
| 42 | +- **Batching:** mutations are coalesced via `queueMicrotask`. Multiple synchronous writes (including array `push` which triggers multiple SET traps) produce a single subscriber notification. |
| 43 | +- **Internal state:** stored in a `WeakMap<proxy, StoreInternal>` — never on the user's object. Allows GC when a store is dereferenced. |
| 44 | +- **Non-proxyable types:** `Date`, `RegExp`, native `Map`, and native `Set` are treated as opaque values (internal slots can't be intercepted by Proxy). Use `reactiveMap()` and `reactiveSet()` for Map/Set semantics. Replace Date instances entirely to trigger updates. |
| 45 | +- **`persist()` exclusions:** getters (detected by walking the prototype chain with `Object.getOwnPropertyDescriptor`) and methods (`typeof value === 'function'`) are automatically excluded from persistence. Only own data properties are saved. |
| 46 | +- **Computed memoization:** two layers — the write proxy caches getter results keyed on dependency versions/values; the snapshot layer adds cross-snapshot caching using structural sharing reference equality. |
| 47 | +- **Structural sharing:** unchanged sub-trees reuse the previous frozen snapshot reference. This makes `Object.is` comparisons in selectors efficient without `shallowEqual`. |
| 48 | +- **Version numbers:** monotonically increasing integers stored per proxy node. Child mutations propagate version bumps up to the root. The snapshot cache is keyed on version — a cache hit is O(1). |
| 49 | + |
| 50 | +## Package Export Entry Points |
| 51 | + |
| 52 | +| Import path | Contents | |
| 53 | +|---|---| |
| 54 | +| `@codebelt/classy-store` | `createClassyStore`, `snapshot`, `subscribe`, `getVersion`, `shallowEqual`, `reactiveMap`, `reactiveSet`, `Snapshot` type | |
| 55 | +| `@codebelt/classy-store/react` | `useStore`, `useLocalStore` | |
| 56 | +| `@codebelt/classy-store/vue` | `useStore` (ShallowRef) | |
| 57 | +| `@codebelt/classy-store/svelte` | `toSvelteStore` (ClassyReadable) | |
| 58 | +| `@codebelt/classy-store/solid` | `useStore` (signal getter) | |
| 59 | +| `@codebelt/classy-store/angular` | `injectStore` (Signal) | |
| 60 | +| `@codebelt/classy-store/utils` | `persist`, `devtools`, `subscribeKey`, `withHistory` | |
| 61 | + |
| 62 | +## Build & Test Commands |
| 63 | + |
| 64 | +Run from the repo root: |
| 65 | + |
| 66 | +```bash |
| 67 | +bun install # Install all workspace dependencies |
| 68 | + |
| 69 | +bun run build # Build all packages (tsdown, outputs to packages/classy-store/dist/) |
| 70 | +bun run test # Run all tests (Bun test runner, uses happy-dom for React hook tests) |
| 71 | + |
| 72 | +bun run docs:dev # Start Docusaurus dev server at http://localhost:3000/classy-store/ |
| 73 | +bun run docs:build # Build docs site to website/build/ |
| 74 | +``` |
| 75 | + |
| 76 | +Run from `packages/classy-store/`: |
| 77 | + |
| 78 | +```bash |
| 79 | +bun run dev # Build in watch mode |
| 80 | +bun test # Run tests for this package only |
| 81 | +bun run typecheck # TypeScript type check without emit |
| 82 | +``` |
| 83 | + |
| 84 | +## LLM Documentation Files |
| 85 | + |
| 86 | +- `website/static/llms.txt` — navigation index (served at `/classy-store/llms.txt`) |
| 87 | +- `website/static/llms-full.txt` — all docs concatenated (served at `/classy-store/llms-full.txt`) |
| 88 | + |
| 89 | +These follow the [llms.txt standard](https://llmstxt.org/). |
0 commit comments