stroid 0.1.4-beta.0 → 0.1.5

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 (73) hide show
  1. package/CHANGELOG.md +427 -288
  2. package/README.md +1125 -118
  3. package/dist/async-internal.d.ts +30 -0
  4. package/dist/async.d.ts +7 -12
  5. package/dist/async.js +1 -33
  6. package/dist/chunk-4C666HHU.js +2 -0
  7. package/dist/chunk-4D6OA3DD.js +2 -0
  8. package/dist/chunk-6IBJ7CIK.js +14 -0
  9. package/dist/chunk-BWNLQKTY.js +2 -0
  10. package/dist/chunk-E33L4MII.js +2 -0
  11. package/dist/chunk-FSNVSMAV.js +2 -0
  12. package/dist/chunk-GZQGU64H.js +2 -0
  13. package/dist/chunk-LWUT37FW.js +13 -0
  14. package/dist/chunk-NFT6AZXY.js +2 -0
  15. package/dist/chunk-PHE2BCFG.js +2 -0
  16. package/dist/chunk-SF6EP56S.js +2 -0
  17. package/dist/chunk-WE3ZR6OG.js +2 -0
  18. package/dist/chunk-WXJ3IREA.js +2 -0
  19. package/dist/chunk-X2MKRN7O.js +14 -0
  20. package/dist/chunk-Y54SMROI.js +2 -0
  21. package/dist/chunk-YU5GMPCC.js +2 -0
  22. package/dist/computed.d.ts +6 -5
  23. package/dist/computed.js +1 -12
  24. package/dist/core-internal.d.ts +23 -0
  25. package/dist/core.d.ts +3 -2
  26. package/dist/core.js +1 -22
  27. package/dist/devtools-internal.d.ts +26 -0
  28. package/dist/devtools.d.ts +4 -25
  29. package/dist/devtools.js +1 -1
  30. package/dist/feature.d.ts +9 -2
  31. package/dist/feature.js +1 -1
  32. package/dist/fetch-4RH6MPY3.js +2 -0
  33. package/dist/graph-D28.d.ts +20 -0
  34. package/dist/helpers.d.ts +2 -1
  35. package/dist/helpers.js +1 -22
  36. package/dist/index-internal.d.ts +19 -19
  37. package/dist/index.d.cts +40 -22
  38. package/dist/index.d.ts +40 -22
  39. package/dist/index.js +1 -35
  40. package/dist/install.d.ts +16 -4
  41. package/dist/install.js +1 -1
  42. package/dist/metrics.d.ts +13 -0
  43. package/dist/persist.d.ts +3 -1
  44. package/dist/persist.js +1 -1
  45. package/dist/psr.d.ts +20 -11
  46. package/dist/psr.js +1 -18
  47. package/dist/query.d.ts +17 -0
  48. package/dist/query.js +2 -0
  49. package/dist/react/index.d.ts +10 -3
  50. package/dist/react/index.js +5 -36
  51. package/dist/registry.d.ts +23 -14
  52. package/dist/runtime-admin.js +1 -1
  53. package/dist/runtime-tools.d.ts +38 -65
  54. package/dist/runtime-tools.js +1 -3
  55. package/dist/selectors.d.ts +1 -1
  56. package/dist/selectors.js +1 -1
  57. package/dist/server/portable.d.ts +27 -0
  58. package/dist/server/portable.js +2 -0
  59. package/dist/server.d.ts +9 -19
  60. package/dist/server.js +1 -12
  61. package/dist/shared.d.ts +36 -0
  62. package/dist/store-registry.d.ts +5 -1
  63. package/dist/sync.d.ts +10 -1
  64. package/dist/sync.js +1 -1
  65. package/dist/testing.d.ts +1 -0
  66. package/dist/testing.js +1 -22
  67. package/dist/tsdoc-metadata.json +1 -1
  68. package/dist/types-internal-2.d.ts +168 -0
  69. package/dist/{computed-types.d.ts → types-internal-3.d.ts} +1 -1
  70. package/dist/{options.d.ts → types-internal.d.ts} +26 -10
  71. package/dist/types.d.ts +12 -2
  72. package/package.json +111 -44
  73. package/dist/computed-types.js +0 -2
package/README.md CHANGED
@@ -1,190 +1,1197 @@
1
- # Stroid
1
+ <div align="center">
2
2
 
3
- [![npm](https://img.shields.io/npm/v/stroid)](https://npmjs.com/package/stroid)
4
- [![bundle size](https://img.shields.io/bundlephobia/minzip/stroid)](https://bundlephobia.com/package/stroid)
5
- [![types](https://img.shields.io/npm/types/stroid)](https://npmjs.com/package/stroid)
6
- [![license](https://img.shields.io/npm/l/stroid)](./LICENSE)
7
- [![CI](https://img.shields.io/github/actions/workflow/status/Himesh-Bhattarai/stroid/ci.yml)](https://github.com/Himesh-Bhattarai/stroid/actions)
3
+ <img src="https://img.shields.io/npm/v/stroid?color=7F77DD&label=stroid&style=flat-square" alt="npm version" />
4
+ <img src="https://img.shields.io/badge/tree--shakeable-subpaths-0F766E?style=flat-square" alt="tree-shakeable via subpaths" />
5
+ <img src="https://img.shields.io/npm/types/stroid?color=4A90E2&style=flat-square" alt="types" />
6
+ <img src="https://img.shields.io/npm/l/stroid?color=3B8BD4&style=flat-square" alt="license" />
7
+ <img src="https://img.shields.io/github/actions/workflow/status/Himesh-Bhattarai/stroid/ci.yml?color=639922&label=tests&style=flat-square" alt="tests" />
8
+ <img src="https://img.shields.io/npm/dm/stroid?color=2E7D32&label=downloads&style=flat-square" alt="npm downloads" />
9
+ <img src="https://img.shields.io/node/v/stroid?color=455A64&style=flat-square" alt="node version" />
10
+ <img src="https://img.shields.io/codecov/c/github/Himesh-Bhattarai/stroid?style=flat-square&label=coverage" alt="coverage" />
11
+ <img src="https://img.shields.io/github/last-commit/Himesh-Bhattarai/stroid?style=flat-square&label=last%20commit" alt="last commit" />
12
+ <img src="https://img.shields.io/github/stars/Himesh-Bhattarai/stroid?style=flat-square&label=stars" alt="stars" />
13
+ <img src="https://img.shields.io/github/contributors/Himesh-Bhattarai/stroid?style=flat-square" alt="contributors" />
14
+ <img src="https://img.shields.io/github/issues/Himesh-Bhattarai/stroid?style=flat-square" alt="issues" />
8
15
 
16
+ <!-- <a href="https://your-demo-link.com">
17
+ <img src="https://img.shields.io/badge/demo-live-ff69b4?style=flat-square" alt="live demo" />
18
+ </a> -->
19
+ <br /><br />
20
+
21
+ **Stroid is the only state management library with a theoretical correctness argument, a matching implementation, and a certified benchmark suite proving it holds under production-grade concurrent SSR conditions.**
22
+ <br /><br />
23
+
24
+ # 🟣 Stroid - State Engine for TypeScript and React
9
25
  **Named-store state engine for TypeScript and React.**
10
26
 
11
- Every store has a name. Write to it from anywhere hooks, utilities, server, tests. Optional layers add persistence, sync, async fetch, SSR isolation, and devtools without coupling to your core logic.
27
+ Every store has a name. Write to it from anywhere: hooks, utilities, server, tests. Optional layers add persistence, sync, async fetch, SSR isolation, post-hydration consistency controls, and devtools without coupling to core logic.
28
+ <br />
29
+ [**Get Started**](#30-second-quickstart) | [**Why Stroid**](#why-stroid) | [**API Reference**](#full-api-reference) | [**PSR**](#psr---write-governance) | [**DevTools**](#devtools) | [**Examples**](#real-world-examples)
30
+ <br /><br />
31
+
32
+ **Certified benchmark suite (latest rerun: `2026-04-02`)**
33
+ <br />
34
+ `0` SSR correctness violations across `2 x 1,024` burst requests, `8,192` sustained requests, and `256` concurrent React streaming SSR requests, plus `0` detached leaks in warm-container/provider-model runs and `0` React concurrency invariant violations under `useTransition` and `useDeferredValue`.
35
+ <br />
36
+ [**Benchmark Report**](./docs/STROID/BENCHMARK.md) | Run: `npm run benchmark:guarantees`
37
+
38
+ </div>
39
+
40
+ ---
41
+ > [!IMPORTANT]
42
+ > ## 🧠 What Is Stroid?
43
+ >
44
+ > A structured state management system focused on predictability, SSR safety, and debugging clarity.
45
+ >
46
+ > - Core store runtime (`createStore`, `setStore`, `getStore`)
47
+ > - React hooks (`useStore`, `useSelector`)
48
+ > - Async fetch/cache/revalidate
49
+ > - Optional features
50
+ > - SSR request isolation
51
+ > - Native PSR contract
52
+ ---
53
+
54
+ <a id="30-second-quickstart"></a>
55
+ ## ⚡ 30-Second Quickstart
56
+
57
+ ---
58
+
59
+ >[!NOTE]
60
+ >```bash
61
+ >npm install stroid
62
+ >```
63
+ ---
64
+
65
+ >[!NOTE]
66
+ >```ts
67
+ >import { createStore, setStore, getStore, configureStroid } from "stroid";
68
+ >import { installPersist } from "stroid/persist";
69
+ >import { installSync } from "stroid/sync";
70
+ >
71
+ >configureStroid({
72
+ > asyncAutoCreate: false,
73
+ > defaultSnapshotMode: "deep",
74
+ >});
75
+ >
76
+ >installPersist();
77
+ >installSync();
78
+ >//create store
79
+ >createStore("auth", { user: null, token: null });
80
+ >//create store with persist
81
+ >createStore("settings", { theme: "dark" }, { persist: true });
82
+ >//create store with sync and persist.
83
+ >createStore("session", { active: true }, { persist: true, sync: true });
84
+ >
85
+ >setStore("auth", "user", { id: "u1", name: "Asha" });
86
+ >const auth = getStore("auth");
87
+ >
88
+ >```
89
+ ---
90
+
91
+ ## Operational Notes
92
+
93
+ - Store names are runtime-validated. Avoid spaces and reserved keys like `__proto__`, `constructor`, and `prototype`.
94
+ - `useStore("name")` without a path or selector subscribes to the full store. Prefer `useSelector(...)` or path reads in hot React components.
95
+ - Hook string names are only strongly typed after `StoreStateMap` augmentation. Without it, `useStore("name")` reads are intentionally loose and typically resolve to `unknown`.
96
+ - Selector-heavy dev flows that read frozen state deep-clone by default for safe dependency tracking. If that overhead matters more than the extra safety, tune `selectorCloneFrozen`.
97
+ - `fetchStore(name, promise, ...)` accepts a direct Promise, but direct Promise inputs cannot use retries or replayable `refetchStore()` semantics. Use a URL string or factory when you need retry/backoff behavior.
98
+ - `asyncAutoCreate` is a development convenience, not a production safety feature. Leave it off in production to avoid typo-created phantom stores.
99
+ - `stroid/sync` uses same-origin `BroadcastChannel` transport. Stroid requests a fresh snapshot on startup, focus, and reconnect, but listener registration can still race under load, `policy: "insecure"` is an explicit opt-out, and open channels may reduce BFCache restores.
100
+ - `stroid/persist` relies on browser storage. `checksum: "hash"` is non-cryptographic, and Safari/WebKit can evict script-writable storage after roughly 7 days of inactivity, so persisted auth, carts, and drafts should have a server-backed recovery path.
101
+ - `hydrateStores(snapshot, options, trust, consistency?)` can add a bounded post-hydration consistency window. Stroid can defer early client writes, emit structured drift events, and reconcile per store with `server_wins`, `client_wins`, `merge`, or `invalidate_and_refetch`.
102
+ - React hooks are built on `useSyncExternalStore`; local concurrency certification now covers no-tearing invariants under `useTransition` and `useDeferredValue`.
103
+ - `stroid/server` is Node-only today because it depends on `node:async_hooks`. Edge runtimes and Workers need a different adapter.
104
+ - `stroid/server/portable` is the explicit request-scope boundary for serverless hand-offs, worker-style runtimes, and Server Actions. It does not rely on implicit async context; use the bound scope API it returns.
105
+ - Local provider-model certification now covers warm AWS Lambda-style Node handlers, Vercel render-to-action hand-off, and Cloudflare Workers-style explicit scopes, but you should still validate against your deployed provider before claiming production certification.
106
+ - Next.js Server Actions are a separate execution boundary. They do not inherit the original request carrier automatically; capture state on render and resume it with `stroid/server/portable`. The render-to-action hand-off is covered by `benchmark:next-server-actions` and [examples/next-app-router-server-actions.ts](./examples/next-app-router-server-actions.ts).
107
+ - Stroid can only guarantee request isolation for state written through Stroid APIs. Third-party singleton stores remain outside that guarantee.
108
+
109
+ ---
110
+
111
+ ### Stroid PSR
112
+
113
+ Stroid ships a native PSR contract in `stroid/psr`.
114
+ It exposes committed snapshots, patch application APIs, and runtime graph/timing data used for governance flows.
115
+
116
+ ---
117
+
118
+ ## 🗺️ Ecosystem Map
119
+
120
+ Stroid is organized into focused sub-packages. Import only what you need.
121
+
122
+ ```
123
+ stroid <- core public runtime
124
+ |- stroid/react <- React hooks
125
+ |- stroid/core <- minimal core surface
126
+ |- stroid/psr <- native PSR contract
127
+ |- stroid/async <- fetch/cache/revalidate
128
+ |- stroid/query <- reactQueryKey(), swrKey()
129
+ |- stroid/selectors <- selector helpers
130
+ |- stroid/computed <- computed stores
131
+ |- stroid/persist <- installPersist()
132
+ |- stroid/sync <- installSync()
133
+ |- stroid/devtools <- installDevtools(), history API
134
+ |- stroid/server <- SSR request-scoped registry
135
+ |- stroid/server/portable <- explicit request-scope bridge for serverless / workers / server actions
136
+ |- stroid/helpers <- entity/list/counter helpers
137
+ |- stroid/testing <- test helpers
138
+ |- stroid/runtime-tools <- observability APIs
139
+ |- stroid/runtime-admin <- clear helpers
140
+ |- stroid/feature <- feature plugin API
141
+ |- stroid/install <- installAllFeatures()
142
+ ```
143
+
144
+ Import note:
145
+ - Prefer subpath imports and avoid defaulting to the full `stroid` root import unless you need its broader compatibility surface.
146
+
147
+ ---
148
+
149
+ <a id="why-stroid"></a>
150
+ ## 🤔 Why Stroid?
151
+
152
+ ### Honest comparison
153
+
154
+ | Feature | **Stroid** | Redux Toolkit | Zustand | Jotai | Valtio |
155
+ |---|:---:|:---:|:---:|:---:|:---:|
156
+ | Write without reducers | ✅ | ❌ | ✅ | ✅ | ✅ |
157
+ | Named global stores | ✅ | ✅ | ⚠️ manual | ❌ | ❌ |
158
+ | Write governance (PSR) | ✅ | ❌ | ❌ | ❌ | ❌ |
159
+ | Built-in DevTools extension | ✅ | ✅ | ⚠️ limited | ❌ | ❌ |
160
+ | Computed / derived state | ✅ | ✅ | ⚠️ manual | ✅ | ✅ |
161
+ | Async data built-in | ✅ | ✅ RTK Query | ❌ | ⚠️ | ❌ |
162
+ | SSR / request isolation | ✅ | ⚠️ | ⚠️ | ✅ | ⚠️ |
163
+ | Atomic rollback guarantee | ✅ | ❌ | ❌ | ❌ | ❌ |
164
+ | Race resistance proof | ✅ | ❌ | ❌ | ❌ | ❌ |
165
+ | Determinism replay | ✅ | ❌ | ❌ | ❌ | ❌ |
166
+ | Ring-buffer event timeline | ✅ | ❌ | ❌ | ❌ | ❌ |
167
+ | TypeScript-first | ✅ | ✅ | ✅ | ✅ | ✅ |
168
+
169
+ > ⚠️ = possible with extra setup · ❌ = not supported natively
170
+
171
+ Stroid exposes governance-oriented write flows through `stroid/psr`, including committed snapshot reads, patch application APIs, runtime graph inspection, and timing contracts.
172
+ Benchmark report: [docs/STROID/BENCHMARK.md](./docs/STROID/BENCHMARK.md).
173
+ Benchmark script layout is categorized by domain under `scripts/core`, `scripts/ssr`, `scripts/hydration`, `scripts/react`, `scripts/guarantees`, and `scripts/comparison`.
174
+
175
+ Stroid is a fit when you need these together:
176
+ - Named global stores with direct writes
177
+ - Optional feature installs instead of mandatory side effects
178
+ - Strict hydration trust gate (`hydrateStores(..., ..., { allowTrusted: true })`)
179
+ - Governed post-hydration drift handling with per-store consistency policies
180
+ - Request-scoped SSR runtime (`createStoreForRequest`) with server guards
181
+ - PSR-style patch application and runtime graph inspection (`stroid/psr`)
182
+
183
+ If you only need ultra-minimal local state, `stroid/core` exists for a smaller surface.
184
+
185
+ ---
186
+
187
+ <a id="full-api-reference"></a>
188
+ ## 📚 Full API Reference
189
+
190
+ All examples use real APIs from this repository's current source.
191
+
192
+ ## ⚙️ Core - `stroid`
193
+
194
+ ### `createStore`
195
+
196
+ ```ts
197
+ import { createStore } from "stroid";
198
+
199
+ createStore("cart", {
200
+ items: [],
201
+ total: 0,
202
+ });
203
+ ```
204
+
205
+ Creates a named store and registers its initial state.
206
+
207
+ ---
208
+
209
+ ### `setStore`
210
+
211
+ ```ts
212
+ import { setStore } from "stroid";
213
+
214
+ setStore("cart", "total", 499);
215
+ setStore("cart", { currency: "NPR" });
216
+ setStore("cart", (draft: any) => {
217
+ draft.items.push({ id: "pizza", qty: 1 });
218
+ });
219
+ ```
220
+ Updates existing store state by path, partial object merge, or mutator function.
221
+ The public root API intentionally does not export `replaceStore`; explicit full-store replacement is kept on the internal runtime/PSR side to reduce accidental overwrite mistakes.
222
+
223
+ ---
224
+
225
+ ### `getStore`
226
+
227
+ ```ts
228
+ import { getStore } from "stroid";
229
+
230
+ const cart = getStore("cart");
231
+ const total = getStore("cart", "total");
232
+ ```
233
+ Reads current store state, optionally at a nested path.
234
+
235
+ ---
236
+
237
+ ### `hasStore`
12
238
 
13
239
  ```ts
14
- createStore("user", { name: "Ava", role: "admin" }) // define once
15
- setStore("user", "name", "Kai") // write from anywhere
16
- const name = useStore("user", s => s.name) // React hook (stroid/react)
240
+ import { hasStore, createStore } from "stroid";
241
+
242
+ if (!hasStore("cart")) {
243
+ createStore("cart", { items: [], total: 0 });
244
+ }
17
245
  ```
246
+ Checks whether a store is already registered.
18
247
 
19
248
  ---
20
249
 
21
- ## Install
250
+ ### `resetStore`
22
251
 
23
- ```bash
24
- npm install stroid
252
+ ```ts
253
+ import { resetStore } from "stroid";
254
+
255
+ resetStore("cart");
25
256
  ```
257
+ Resets a store back to its original initial state.
26
258
 
27
- **Requirements:** Node `>=18`. React `>=18` (only if using `stroid/react`).
259
+ Reset clone behavior is configurable:
28
260
 
29
- **ESM-only:** Stroid ships ESM only. If your toolchain requires CJS, use a bundler with ESM support (Vite, webpack 5, esbuild).
261
+ - Per store: `createStore("cart", initial, { resetClone: "deep" | "shallow" | "none" })`
262
+ - Global default: `configureStroid({ resetCloneMode: "deep" | "shallow" | "none" })`
30
263
 
31
264
  ---
32
265
 
33
- ## Layer Map
266
+ ### `deleteStore`
34
267
 
268
+ ```ts
269
+ import { deleteStore } from "stroid";
270
+
271
+ deleteStore("cart");
35
272
  ```
36
- ┌─────────────────────────────────────────────────────────┐
37
- │ your app │
38
- ├─────────────────────────────────────────────────────────┤
39
- │ useStore useSelector useAsyncStore useFormStore │ stroid/react
40
- ├─────────────────────────────────────────────────────────┤
41
- │ createStore setStore getStore setStoreBatch │ stroid ← core
42
- │ createComputed createSelector createEntityStore │
43
- ├──────────────┬──────────────┬───────────────────────────┤
44
- │ stroid/persist│ stroid/sync │ stroid/async │ opt-in features
45
- localStorage │ BroadcastCh │ fetch + cache + retry │
46
- ├──────────────┴──────────────┴───────────────────────────┤
47
- stroid/server createStoreForRequest (AsyncLocalStorage)│ SSR
48
- ├─────────────────────────────────────────────────────────┤
49
- │ stroid/devtools stroid/testing stroid/runtime-tools │ tooling
50
- └─────────────────────────────────────────────────────────┘
273
+ Removes a store and its runtime metadata/subscriptions.
274
+
275
+ ---
276
+
277
+ ### `setStoreBatch`
278
+
279
+ ```ts
280
+ import { setStoreBatch, setStore } from "stroid";
281
+
282
+ setStoreBatch(() => {
283
+ setStore("checkout", "coupon", "SAVE20");
284
+ setStore("checkout", "deliveryType", "priority");
285
+ setStore("checkout", "tip", 50);
286
+ });
287
+ ```
288
+ `setStoreBatch` accepts only synchronous callbacks.
289
+ Runs multiple synchronous writes in one transaction-style batch.
290
+
291
+ ---
292
+
293
+ ### `hydrateStores`
294
+
295
+ ```ts
296
+ import { hydrateStores } from "stroid";
297
+
298
+ const hydration = hydrateStores(
299
+ {
300
+ cart: { items: [{ id: "pizza", qty: 1 }], total: 499 },
301
+ profile: { name: "Asha" },
302
+ },
303
+ {},
304
+ { allowTrusted: true },
305
+ {
306
+ contract: {
307
+ snapshotVersion: 3,
308
+ timestamp: Date.now(),
309
+ stores: {
310
+ cart: { authority: "server-authoritative" },
311
+ profile: { authority: "client-authoritative" },
312
+ },
313
+ },
314
+ bootWindow: {
315
+ mode: "manual",
316
+ fallbackMs: 3000,
317
+ },
318
+ policyMap: {
319
+ cart: "server_wins",
320
+ profile: "client_wins",
321
+ },
322
+ }
323
+ );
324
+
325
+ hydration.bootWindow?.close();
326
+ ```
327
+ Hydrates many stores from a trusted snapshot payload. The optional fourth argument adds post-hydration drift controls, write deferral during the boot window, and structured drift diagnostics. Manual mode returns `hydration.bootWindow`, so your app can close the gate when its critical hydration boundary is ready.
328
+
329
+ Recommended rollout defaults:
330
+ - use `bootWindow: { mode: "manual", fallbackMs: 3000 }` when you need certification-grade control
331
+ - keep `bootWindowMs` or `bootWindow: { mode: "timer", ms: ... }` only as a compatibility fallback when you cannot close manually yet
332
+ - keep auth/session stores `server_wins`
333
+ - keep drafts/forms `client_wins`
334
+ - use `merge` for filters or preference bags and `invalidate_and_refetch` for replayable async caches
335
+
336
+ The full adoption guide, policy defaults, and runtime-tools workflow live in [Post-Hydration Consistency](./docs/STROID_SERVER/POST_HYDRATION_CONSISTENCY.md).
337
+
338
+ ---
339
+
340
+ ### `configureStroid`
341
+
342
+ ```ts
343
+ import { configureStroid } from "stroid";
344
+
345
+ configureStroid({
346
+ asyncAutoCreate: false,
347
+ strictMutatorReturns: true,
348
+ defaultSnapshotMode: "deep",
349
+ });
350
+ ```
351
+ Sets global runtime behavior such as async and snapshot defaults.
352
+
353
+ ---
354
+ >[!TIP]
355
+ >
356
+ >Stroid is NOT for:
357
+ >- small apps
358
+ >- simple UI state
359
+ >- beginners learning React
360
+ >
361
+ >Stroid is for:
362
+ >- complex apps
363
+ >- SSR-heavy systems
364
+ >- multi-source async data
365
+ >- teams that need debugging + guarantees
366
+ > *If Still want to learn, then:
367
+ > - **Beginners:** If you are building a personal portfolio or a small app, you likely only need `createStore`, `getStore`, and the basic React hooks like `useStore`. I don't want you to read whole README.
368
+ > - **Intermediate:** We recommend reading the full README to understand features like batching, persistence,SSR Isolation,Sync,and async fetching. Don't take overhead about PSR FOR NOW, THINK THAT NOT EXIST AT ALL. UNTIL, I MAKE PROPER EXPLANATION VIDEO.
369
+ > - **Advanced:** Explore the `/docs` directory for deep dives into architecture, SSR isolation, and the PSR contract, DevTools.
370
+ ---
371
+ ## ⚛️ React Hooks - `stroid/react`
372
+
373
+ ### `useStore`
374
+
375
+ ```tsx
376
+ import { useStore } from "stroid/react";
377
+
378
+ function CartPanel() {
379
+ const cart = useStore("cart");
380
+ return <div>{cart ? `${cart.items.length} items` : "Cart empty"}</div>;
381
+ }
382
+ ```
383
+ Subscribes React components to a store value (full store, path, or selector form).
384
+
385
+ ---
386
+
387
+ ### `useSelector`
388
+
389
+ ```tsx
390
+ import { useSelector } from "stroid/react";
391
+
392
+ function CartTotal() {
393
+ const total = useSelector("cart", (s: any) => s?.total ?? 0);
394
+ return <strong>Rs. {total}</strong>;
395
+ }
396
+ ```
397
+ Subscribes to a derived slice and re-renders only when selected output changes.
398
+
399
+ ---
400
+
401
+ ### `useStoreField`
402
+
403
+ ```tsx
404
+ import { useStoreField } from "stroid/react";
405
+
406
+ function DeliveryTypeChip() {
407
+ const deliveryType = useStoreField("checkout", "deliveryType");
408
+ return <span>{deliveryType ?? "standard"}</span>;
409
+ }
410
+ ```
411
+ Subscribes directly to one field/path inside a store.
412
+
413
+ ---
414
+
415
+ ### `useStoreStatic`
416
+
417
+ ```tsx
418
+ import { useStoreStatic } from "stroid/react";
419
+
420
+ function DebugPanel() {
421
+ const snapshot = useStoreStatic("cart");
422
+ return <pre>{JSON.stringify(snapshot, null, 2)}</pre>;
423
+ }
424
+ ```
425
+ Reads a snapshot once without live subscription updates.
426
+
427
+ ---
428
+
429
+ ### `useAsyncStore`
430
+
431
+ ```tsx
432
+ import { useEffect } from "react";
433
+ import { useAsyncStore } from "stroid/react";
434
+ import { fetchStore } from "stroid/async";
435
+
436
+ function Menu() {
437
+ useEffect(() => {
438
+ void fetchStore("menu", "https://api.example.com/menu", { autoCreate: true });
439
+ }, []);
440
+
441
+ const { loading, error, data } = useAsyncStore("menu");
442
+
443
+ if (loading) return <p>Loading menu...</p>;
444
+ if (error) return <p>Failed to load menu</p>;
445
+ return <MenuList items={data ?? []} />;
446
+ }
447
+ ```
448
+ Reads async store shape (`data/loading/error/status`) from an existing store.
449
+
450
+ ---
451
+
452
+ ### `useAsyncStoreSuspense`
453
+
454
+ ```tsx
455
+ import { useAsyncStoreSuspense } from "stroid/react";
456
+
457
+ function MenuSuspense() {
458
+ const menu = useAsyncStoreSuspense<Array<{ id: string; name: string }>>(
459
+ "menu",
460
+ "https://api.example.com/menu",
461
+ { autoCreate: true }
462
+ );
463
+
464
+ return <MenuList items={menu} />;
465
+ }
466
+ ```
467
+ Integrates async store reads with React Suspense by throwing pending work.
468
+
469
+ ---
470
+
471
+ ### `useFormStore`
472
+
473
+ ```tsx
474
+ import { createStore } from "stroid";
475
+ import { useFormStore } from "stroid/react";
476
+
477
+ createStore("loginForm", { email: "", password: "" });
478
+
479
+ function LoginForm() {
480
+ const email = useFormStore("loginForm", "email");
481
+ const password = useFormStore("loginForm", "password");
482
+
483
+ return (
484
+ <form>
485
+ <input value={email.value ?? ""} onChange={email.onChange} />
486
+ <input value={password.value ?? ""} onChange={password.onChange} type="password" />
487
+ <button disabled={!email.value || !password.value}>Sign in</button>
488
+ </form>
489
+ );
490
+ }
491
+ ```
492
+ Binds a store field to form-style `value` and `onChange` helpers.
493
+
494
+ ---
495
+
496
+ ### `RegistryScope`
497
+
498
+ ```tsx
499
+ import { RegistryScope } from "stroid/react";
500
+
501
+ function App({ registry }: { registry: any }) {
502
+ return (
503
+ <RegistryScope value={registry}>
504
+ <CartPanel />
505
+ <ProfilePanel />
506
+ </RegistryScope>
507
+ );
508
+ }
509
+ ```
510
+ Scopes a React subtree to a specific store registry context.
511
+
512
+ ---
513
+
514
+ ## 𛲝Se Selectors & Computed
515
+
516
+ ### `createSelector` - `stroid/selectors`
517
+
518
+ ```ts
519
+ import { createSelector } from "stroid/selectors";
520
+
521
+ const selectItemCount = createSelector("cart", (s: any) => s?.items?.length ?? 0);
522
+ const count = selectItemCount();
523
+ ```
524
+ Builds a memoized selector function for derived store reads.
525
+
526
+ ---
527
+
528
+ ### `subscribeWithSelector` - `stroid/selectors`
529
+
530
+ ```ts
531
+ import { subscribeWithSelector } from "stroid/selectors";
532
+
533
+ const stop = subscribeWithSelector(
534
+ "cart",
535
+ (s: any) => s?.total,
536
+ Object.is,
537
+ (next, prev) => {
538
+ if (typeof prev === "number" && next > prev) {
539
+ // run side effect
540
+ }
541
+ }
542
+ );
543
+
544
+ stop();
545
+ ```
546
+ Runs a listener only when the selected value changes by equality check.
547
+
548
+ ---
549
+
550
+ ### `createComputed` - `stroid/computed`
551
+
552
+ ```ts
553
+ import { createComputed } from "stroid/computed";
554
+ import { getStore } from "stroid";
555
+
556
+ createComputed("deliveryFee", ["cart"], (cart: any) => (cart?.total ?? 0) > 1000 ? 0 : 60);
557
+
558
+ const fee = getStore("deliveryFee");
559
+ ```
560
+ Creates a computed store derived from one or more dependency stores.
561
+
562
+ ---
563
+
564
+ ### `invalidateComputed` / `deleteComputed` / `isComputedStore`
565
+
566
+ ```ts
567
+ import { invalidateComputed, deleteComputed, isComputedStore } from "stroid/computed";
568
+
569
+ invalidateComputed("deliveryFee");
570
+ deleteComputed("deliveryFee");
571
+ isComputedStore("deliveryFee");
572
+ ```
573
+ Invalidates, removes, or checks computed-store registrations.
574
+
575
+ ---
576
+
577
+ ## ⏱️ Async - `stroid/async`
578
+
579
+ ```ts
580
+ import { fetchStore, refetchStore, enableRevalidateOnFocus } from "stroid/async";
581
+
582
+ await fetchStore("menu", "https://api.example.com/menu");
583
+ await refetchStore("menu");
584
+ const stopFocusRevalidate = enableRevalidateOnFocus("menu");
585
+
586
+ stopFocusRevalidate();
587
+ ```
588
+ Fetches/refetches remote data into stores with cache, dedupe, retries, and focus revalidation.
589
+
590
+ ---
591
+
592
+ ## PSR - Write Governance
593
+
594
+ ```ts
595
+ import { applyStorePatch, applyStorePatchesAtomic } from "stroid/psr";
596
+
597
+ applyStorePatch({
598
+ id: "cart-total-set",
599
+ store: "cart",
600
+ path: ["total"],
601
+ op: "set",
602
+ value: 549,
603
+ meta: { timestamp: Date.now(), source: "setStore" },
604
+ });
605
+
606
+ applyStorePatchesAtomic([
607
+ {
608
+ id: "wallet-set",
609
+ store: "wallet",
610
+ path: ["balance"],
611
+ op: "set",
612
+ value: 900,
613
+ meta: { timestamp: Date.now(), source: "setStore" },
614
+ },
615
+ {
616
+ id: "order-set",
617
+ store: "order",
618
+ path: ["status"],
619
+ op: "set",
620
+ value: "paid",
621
+ meta: { timestamp: Date.now(), source: "setStore" },
622
+ },
623
+ ]);
624
+ ```
625
+ Applies patch-based governed writes with atomic multi-patch support.
626
+
627
+ ---
628
+
629
+ ## 🛡️ Features - `stroid/feature`
630
+
631
+ ### Install - Opt-In Capabilities
632
+
633
+ ```ts
634
+ import { installPersist } from "stroid/persist";
635
+ import { installSync } from "stroid/sync";
636
+ import { installDevtools } from "stroid/devtools";
637
+
638
+ installPersist();
639
+ installSync();
640
+ installDevtools();
641
+ ```
642
+ Installs optional persist/sync/devtools features explicitly at app entry.
643
+
644
+ ---
645
+
646
+ ## 🌐 SSR - `stroid/server`
647
+
648
+ ```ts
649
+ import { createStoreForRequest } from "stroid/server";
650
+
651
+ const requestScope = createStoreForRequest((api) => {
652
+ api.create("session", { userId: "u-1" });
653
+ api.create("cart", { items: [], total: 0 });
654
+ });
655
+
656
+ const html = requestScope.hydrate(() => renderToString(<App />));
657
+ const snapshot = requestScope.snapshot();
658
+ ```
659
+ Creates per-request store scopes for SSR-safe hydrate/snapshot flows.
660
+
661
+ ---
662
+
663
+ ## 🔢 Helpers - `stroid/helpers`
664
+
665
+ ```ts
666
+ import { createEntityStore, createListStore, createCounterStore } from "stroid/helpers";
667
+
668
+ const users = createEntityStore<{ id?: string; name: string }>("users");
669
+ users.upsert({ id: "u1", name: "Asha" });
670
+ users.remove("u1");
671
+
672
+ const tasks = createListStore("tasks", [] as string[]);
673
+ tasks.push("pick up order");
674
+ tasks.removeAt(0);
675
+ tasks.clear();
676
+
677
+ const retries = createCounterStore("retries", 0);
678
+ retries.inc();
679
+ retries.dec();
680
+ retries.set(5);
681
+ const retryValue = retries.get();
682
+ ```
683
+ Provides ready-made entity, list, and counter store helpers.
684
+
685
+ ---
686
+
687
+ ## 🧪 Testing - `stroid/testing`
688
+
689
+ ```ts
690
+ import { store } from "stroid";
691
+ import {
692
+ createMockStore,
693
+ resetAllStoresForTest,
694
+ withMockedTime,
695
+ benchmarkStoreSet,
696
+ } from "stroid/testing";
697
+
698
+ const mockOrder = createMockStore("order", { status: "draft" });
699
+ mockOrder.set({ status: "confirmed" });
700
+
701
+ withMockedTime(1700000000000, () => {
702
+ // Date.now() is fixed in this callback
703
+ });
704
+
705
+ const result = benchmarkStoreSet(store("cart"), 300);
706
+ const avgMs = result.avgMs;
707
+
708
+ resetAllStoresForTest();
709
+ ```
710
+ Provides test helpers for mock stores, time control, reset, and micro-benchmarks.
711
+
712
+ ---
713
+
714
+ ## 📈 Runtime Observability - `stroid/runtime-tools`
715
+
716
+ ```ts
717
+ import {
718
+ listStores,
719
+ getStoreMeta,
720
+ getMetrics,
721
+ getSubscriberCount,
722
+ getStoreHealth,
723
+ findColdStores,
724
+ getComputedGraph,
725
+ getComputedDeps,
726
+ getPersistQueueDepth,
727
+ } from "stroid/runtime-tools";
728
+
729
+ const stores = listStores();
730
+ const meta = getStoreMeta("cart");
731
+ const metrics = getMetrics("cart");
732
+ const subscribers = getSubscriberCount("cart");
733
+ const health = getStoreHealth();
734
+ const cold = findColdStores();
735
+ const graph = getComputedGraph();
736
+ const deps = getComputedDeps("deliveryFee");
737
+ const persistDepth = getPersistQueueDepth("cart");
738
+ ```
739
+ Exposes runtime diagnostics for stores, metrics, health, and computed graph state.
740
+ Import only the functions you need. The internal helpers are grouped more narrowly now, but the published multi-entry build still shares runtime chunks, so the biggest remaining wins are still deeper than this surface split.
741
+
742
+ ---
743
+
744
+ ## 🗝️ Query Keys - `stroid/query`
745
+
746
+ ```ts
747
+ import { reactQueryKey, swrKey } from "stroid/query";
748
+
749
+ const tanstackKey = reactQueryKey("cart");
750
+ const swrCacheKey = swrKey("cart", "summary");
751
+ ```
752
+ Use `stroid/query` when you only need stable cache keys for TanStack Query or SWR.
753
+ The root `queryIntegrations` namespace still exists for compatibility, but `stroid/query` is the leaner path.
754
+
755
+ ---
756
+
757
+ ## 🔧 Runtime Admin - `stroid/runtime-admin`
758
+
759
+ ```ts
760
+ import { clearAllStores, clearStores } from "stroid/runtime-admin";
761
+
762
+ clearStores("cart*");
763
+ clearAllStores();
764
+ ```
765
+ Clears stores in bulk by pattern or globally.
766
+
767
+ ---
768
+
769
+ ## 🌉 DevTools Bridge - `stroid/devtools`
770
+
771
+ ```ts
772
+ import { installDevtools, getHistory, clearHistory } from "stroid/devtools";
773
+
774
+ installDevtools();
775
+
776
+ const cartHistory = getHistory("cart");
777
+ // Array<HistoryEntry> where entry has: ts, action, prev, next, diff
778
+
779
+ clearHistory("cart");
780
+ ```
781
+ Connects to devtools runtime and exposes local history read/clear APIs.
782
+
783
+ ---
784
+
785
+ ## 🔌 Feature Plugin API - `stroid/feature`
786
+
787
+ ```ts
788
+ import {
789
+ registerStoreFeature,
790
+ hasRegisteredStoreFeature,
791
+ getRegisteredFeatureNames,
792
+ } from "stroid/feature";
793
+
794
+ registerStoreFeature("auditFeature", () => ({
795
+ onStoreCreate(ctx) {
796
+ // fires when a store is created
797
+ },
798
+ onStoreWrite(ctx) {
799
+ // fires on store write
800
+ },
801
+ }));
802
+
803
+ const hasAudit = hasRegisteredStoreFeature("auditFeature");
804
+ const featureNames = getRegisteredFeatureNames();
805
+ ```
806
+ Registers custom feature runtimes with lifecycle hooks.
807
+
808
+ ---
809
+
810
+ <a id="psr---write-governance"></a>
811
+ ## 🛡️ PSR - Write Governance - `stroid/psr`
812
+
813
+ PSR (`stroid/psr`) is the public contract for:
814
+ - Committed snapshots
815
+ - Post-commit subscriptions
816
+ - Serializable patch application
817
+ - Runtime graph and timing contract inspection
818
+
819
+ ### PSR API
820
+
821
+ ```ts
822
+ import {
823
+ getStoreSnapshot,
824
+ getStoreSnapshotNoTrack,
825
+ subscribeStore,
826
+ applyStorePatch,
827
+ applyStorePatchesAtomic,
828
+ getRuntimeGraph,
829
+ getComputedDescriptor,
830
+ evaluateComputed,
831
+ getTimingContract,
832
+ } from "stroid/psr";
833
+
834
+ const committed = getStoreSnapshot("cart");
835
+ const committedNoTrack = getStoreSnapshotNoTrack("cart");
836
+
837
+ const unsubscribe = subscribeStore("cart", (next) => {
838
+ // handle committed updates
839
+ });
840
+
841
+ const graph = getRuntimeGraph();
842
+ const checkoutNode = graph.nodes.find(
843
+ (n) => n.storeId === "checkoutTotal" && (n.type === "computed" || n.type === "async-boundary")
844
+ );
845
+
846
+ if (checkoutNode) {
847
+ const descriptor = getComputedDescriptor(checkoutNode.id);
848
+ const preview = evaluateComputed(checkoutNode.id, {
849
+ cart: { items: [{ id: "pizza", qty: 2 }], total: 998 },
850
+ });
851
+ }
852
+
853
+ const timing = getTimingContract("cart");
854
+ ```
855
+ Exposes committed snapshots, subscriptions, patch APIs, runtime graph, and timing contract.
856
+ ---
857
+
858
+ <a id="devtools"></a>
859
+ ## 🔬 DevTools - `stroid/devtools`
860
+
861
+ `stroid/devtools` integrates with the Redux DevTools browser extension and also keeps in-memory history per store.
862
+
863
+ What you get from code:
864
+ - `installDevtools()` to enable the devtools feature runtime
865
+ - `getHistory(name, limit?)` to read recorded store history
866
+ - `clearHistory(name?)` to clear one store or all stores
867
+
868
+ Setup:
869
+ 1. Install Redux DevTools extension in your browser.
870
+ 2. Call `installDevtools()` once in app entry.
871
+ 3. Open browser DevTools and inspect the connected `stroid` session.
872
+
873
+ ---
874
+
875
+ <a id="real-world-examples"></a>
876
+ ## 🍕 Real-World Examples
877
+
878
+ ### Food delivery cart (full flow)
879
+
880
+ ```tsx
881
+ // app/entry.ts
882
+ import { configureStroid } from "stroid";
883
+ import { installPersist } from "stroid/persist";
884
+ import { installDevtools } from "stroid/devtools";
885
+
886
+ configureStroid({ asyncAutoCreate: false });
887
+ installPersist();
888
+ installDevtools();
889
+
890
+ // stores/cart.ts
891
+ import { createStore, setStoreBatch, setStore } from "stroid";
892
+
893
+ createStore("cart", { items: [], total: 0 });
894
+ createStore("checkout", { coupon: null, deliveryType: "standard", tip: 0 });
895
+
896
+ // components/CartPanel.tsx
897
+ import { useSelector, useStoreField } from "stroid/react";
898
+
899
+ function CartPanel() {
900
+ const total = useSelector("cart", (s: any) => s?.total ?? 0);
901
+ const deliveryType = useStoreField("checkout", "deliveryType");
902
+
903
+ function applyPromo() {
904
+ setStoreBatch(() => {
905
+ setStore("checkout", "coupon", "SAVE20");
906
+ setStore("checkout", "deliveryType", "priority");
907
+ setStore("checkout", "tip", 50);
908
+ });
909
+ }
910
+
911
+ return (
912
+ <div>
913
+ <p>Total: Rs. {total}</p>
914
+ <p>Delivery: {deliveryType}</p>
915
+ <button onClick={applyPromo}>Apply promo</button>
916
+ </div>
917
+ );
918
+ }
919
+ ```
920
+
921
+ ### Atomic payment (wallet + order status)
922
+
923
+ ```ts
924
+ import { getStore } from "stroid";
925
+ import { applyStorePatchesAtomic } from "stroid/psr";
926
+
927
+ function confirmPayment(amount: number) {
928
+ const wallet = getStore("wallet") as { balance: number } | null;
929
+ const nextBalance = (wallet?.balance ?? 0) - amount;
930
+
931
+ applyStorePatchesAtomic([
932
+ {
933
+ id: "pay-wallet",
934
+ store: "wallet",
935
+ path: ["balance"],
936
+ op: "set",
937
+ value: nextBalance,
938
+ meta: { timestamp: Date.now(), source: "setStore" },
939
+ },
940
+ {
941
+ id: "pay-order",
942
+ store: "order",
943
+ path: ["status"],
944
+ op: "set",
945
+ value: "paid",
946
+ meta: { timestamp: Date.now(), source: "setStore" },
947
+ },
948
+ ]);
949
+ }
950
+ ```
951
+ Applies related wallet/order updates atomically so both succeed or fail together.
952
+
953
+ ---
954
+ ### Menu with Suspense
955
+
956
+ ```tsx
957
+ import { Suspense } from "react";
958
+ import { useAsyncStoreSuspense } from "stroid/react";
959
+
960
+ function MenuList() {
961
+ const menu = useAsyncStoreSuspense<Array<{ id: string; name: string }>>(
962
+ "menu",
963
+ "https://api.example.com/menu",
964
+ { autoCreate: true }
965
+ );
966
+
967
+ return <ul>{menu.map((item) => <li key={item.id}>{item.name}</li>)}</ul>;
968
+ }
969
+
970
+ export function MenuPage() {
971
+ return (
972
+ <Suspense fallback={<p>Loading menu...</p>}>
973
+ <MenuList />
974
+ </Suspense>
975
+ );
976
+ }
977
+ ```
978
+ Loads menu data through Suspense-friendly async store access.
979
+
980
+ ---
981
+
982
+ ## 🧱 Layer Map
983
+
984
+ ```
985
+ +---------------------------------------------------------+
986
+ | your app |
987
+ +---------------------------------------------------------+
988
+ | useStore useSelector useAsyncStore useFormStore | stroid/react
989
+ +---------------------------------------------------------+
990
+ | createStore setStore getStore setStoreBatch | stroid
991
+ | createComputed createSelector createEntityStore |
992
+ +--------------+--------------+---------------------------+
993
+ | stroid/persist | stroid/sync | stroid/async |
994
+ | installPersist | installSync | fetch + cache + retry |
995
+ +--------------+--------------+---------------------------+
996
+ | stroid/server createStoreForRequest | SSR
997
+ +---------------------------------------------------------+
998
+ | stroid/devtools stroid/testing stroid/runtime-tools |
999
+ +---------------------------------------------------------+
51
1000
  ```
52
1001
 
53
1002
  Each row is independent. Use only what you need.
54
1003
 
55
- `stroid/core` exports only `createStore`, `setStore`, `getStore`, `hasStore`, `resetStore`, and `deleteStore`. Import from `stroid` for the full runtime (batching, hydration, computed). React hooks live in `stroid/react`.
1004
+ `stroid/core` exports only `createStore`, `setStore`, `getStore`, `hasStore`, `resetStore`, and `deleteStore`.
1005
+ Import from `stroid` for batching/hydration/computed plus runtime metrics and config.
56
1006
 
57
- ## What Each Import Contains
1007
+ ## 📦 What Each Import Contains
58
1008
 
59
- - `stroid`: Full runtime (batching, hydration, computed, async metrics, runtime tools). No React hooks.
60
- - `stroid/core`: Minimal CRUD only (`createStore`, `setStore`, `getStore`, `hasStore`, `resetStore`, `deleteStore`).
61
- - `stroid/react`: React hooks (`useStore`, `useSelector`, `useAsyncStore`, `useFormStore`, `useAsyncStoreSuspense`) + `RegistryScope`.
62
- - `stroid/async`: `fetchStore`, cache, retry, revalidate helpers.
1009
+ - `stroid`: Core public runtime (`createStore`, `createStoreStrict`, `setStore`, `setStoreBatch`, `getStore`, `deleteStore`, `resetStore`, `hasStore`, `hydrateStores`), plus `configureStroid`, computed helpers, and health/metric helpers.
1010
+ - `stroid/psr`: PSR contract (`getStoreSnapshot`, `getStoreSnapshotNoTrack`, `subscribeStore`, `applyStorePatch`, `applyStorePatchesAtomic`, runtime graph/timing helpers).
1011
+ - `stroid/core`: Minimal CRUD runtime (`createStore`, `setStore`, `getStore`, `hasStore`, `resetStore`, `deleteStore`).
1012
+ - `stroid/react`: React hooks (`useStore`, `useSelector`, `useStoreField`, `useStoreStatic`, `useAsyncStore`, `useFormStore`, `useAsyncStoreSuspense`) and `RegistryScope`.
1013
+ - `stroid/async`: Async APIs (`fetchStore`, `refetchStore`, `enableRevalidateOnFocus`, `getAsyncMetrics`).
1014
+ - `stroid/query`: cache-key helpers (`reactQueryKey`, `swrKey`) without the fetcher helpers.
63
1015
  - `stroid/selectors`: `createSelector`, `subscribeWithSelector`.
64
1016
  - `stroid/computed`: `createComputed`, `invalidateComputed`, `deleteComputed`, `isComputedStore`.
65
- - `stroid/persist`: Explicit persistence installer (`installPersist`) and related types. Side-effect free.
66
- - `stroid/sync`: Explicit sync installer (`installSync`) and related types. Side-effect free.
67
- - `stroid/devtools`: Explicit devtools installer (`installDevtools`) plus history helpers. Side-effect free.
68
- - `stroid/server`: SSR registry helpers (`createStoreForRequest`).
69
- - `stroid/helpers`: Entity/list/counter store helpers.
70
- - `stroid/runtime-tools`: Observability and diagnostics.
71
- - `stroid/runtime-admin`: Admin utilities (clear/flush).
72
- - `stroid/testing`: Testing utilities (mocks, reset helpers, benchmarks).
1017
+ - `stroid/persist`: `installPersist`.
1018
+ - `stroid/sync`: `installSync`.
1019
+ - `stroid/devtools`: `installDevtools`, `getHistory`, `clearHistory`.
1020
+ - `stroid/server`: `createStoreForRequest`.
1021
+ - `stroid/helpers`: `createEntityStore`, `createListStore`, `createCounterStore`.
1022
+ - `stroid/testing`: `createMockStore`, `resetAllStoresForTest`, `withMockedTime`, `benchmarkStoreSet`.
1023
+ - `stroid/runtime-tools`: Store/runtime observability APIs, including hydration drift reports and counters.
1024
+ - `stroid/runtime-admin`: `clearAllStores`, `clearStores`.
1025
+ - `stroid/feature`: Feature registration APIs.
1026
+ - `stroid/install`: `installPersist`, `installSync`, `installDevtools`, `installAllFeatures`.
73
1027
 
74
1028
  ---
75
1029
 
76
- ## Quick API Reference
1030
+ ## 🧾 Quick API Reference
77
1031
 
78
1032
  | API | Purpose |
79
1033
  |-----|---------|
80
- | `createStore(name, state, options?)` | Define a store. Returns `StoreDefinition \| undefined`. |
81
- | `createStoreStrict(name, state, options?)` | Define a store; throw synchronously on failure. |
82
- | `setStore(name, update)` | Shallow-merge an object update into the store. |
83
- | `setStore(name, path, value)` | Write a value by dot-path or array path. |
84
- | `setStore(name, draft => { })` | Mutate with a function (optional Immer support). |
85
- | `replaceStore(name, value)` | Replace the entire store value. |
86
- | `getStore(name, path?)` | Read a store (or a nested path). |
87
- | `deleteStore(name)` | Remove a store from the registry. |
88
- | `resetStore(name)` | Restore a store to its initial state. |
89
- | `hasStore(name)` | Check if a store exists. |
90
- | `setStoreBatch(fn)` | Atomic multi-store write rolls back all writes on failure. |
91
- | `hydrateStores(snapshot, options?, trust)` | Rehydrate on client from a server snapshot. |
92
- | `useStore(name, selector?)` | React hook — subscribes to a store. |
93
- | `useSelector(name, fn)` | React hook — fine-grained derived value. |
94
- | `fetchStore(name, url, options?)` | Async fetch wired to store state. |
95
- | `createComputed(name, deps, fn)` | Reactive derived store. |
96
- | `createStoreForRequest(fn)` | Per-request SSR registry. |
1034
+ | `createStore(name, state, options?)` | Define a store. Returns `StoreDefinition` or `undefined`. |
1035
+ | `createStoreStrict(name, state, options?)` | Define a store; throws if creation fails. |
1036
+ | `setStore(name, update)` | Merge object update into object store state. |
1037
+ | `setStore(name, path, value)` | Write by path. |
1038
+ | `setStore(name, draft => { ... })` | Mutator-style update. |
1039
+ | `getStore(name, path?)` | Read current state (or nested path). |
1040
+ | `deleteStore(name)` | Remove a store from registry. |
1041
+ | `resetStore(name)` | Restore initial state. |
1042
+ | `hasStore(name)` | Check if store exists. |
1043
+ | `setStoreBatch(fn)` | Group synchronous writes into one transaction. |
1044
+ | `hydrateStores(snapshot, options?, trust, consistency?)` | Hydrate trusted snapshot into runtime, optionally governing post-hydration drift. |
1045
+ | `configureStroid(config)` | Configure global/runtime behavior. |
1046
+ | `useStore(name, selectorOrPath?)` | React subscription hook. |
1047
+ | `useSelector(name, fn, equality?)` | Fine-grained React selector hook. |
1048
+ | `fetchStore(name, input, options?)` | Fetch remote data into store. |
1049
+ | `getAsyncMetrics(name?)` | Read global or per-store async counters. |
1050
+ | `createComputed(name, deps, fn)` | Define computed store. |
1051
+ | `createStoreForRequest(fn)` | Build SSR request-scoped store runtime. |
97
1052
 
98
1053
  ---
99
1054
 
100
- ## Module Import Map
1055
+ ## 🧭 Module Import Map
101
1056
 
102
1057
  ```ts
103
1058
  // Core
104
- import { createStore, setStore, getStore, hasStore,
105
- deleteStore, resetStore, setStoreBatch, hydrateStores } from "stroid"
1059
+ import {
1060
+ createStore,
1061
+ createStoreStrict,
1062
+ setStore,
1063
+ getStore,
1064
+ hasStore,
1065
+ deleteStore,
1066
+ resetStore,
1067
+ setStoreBatch,
1068
+ hydrateStores,
1069
+ configureStroid,
1070
+ } from "stroid";
1071
+
1072
+ // Native PSR contract
1073
+ import {
1074
+ getStoreSnapshot,
1075
+ getStoreSnapshotNoTrack,
1076
+ subscribeStore,
1077
+ applyStorePatch,
1078
+ applyStorePatchesAtomic,
1079
+ getRuntimeGraph,
1080
+ getComputedDescriptor,
1081
+ evaluateComputed,
1082
+ getTimingContract,
1083
+ } from "stroid/psr";
106
1084
 
107
- // Minimal core (bundle-size-sensitive)
108
- import { createStore, setStore, getStore, hasStore,
109
- resetStore, deleteStore } from "stroid/core"
1085
+ // Minimal core (subpath import)
1086
+ import { createStore, setStore, getStore, hasStore, resetStore, deleteStore } from "stroid/core";
110
1087
 
111
1088
  // React
112
- import { useStore, useSelector, useStoreField, useStoreStatic,
113
- useAsyncStore, useFormStore, useAsyncStoreSuspense,
114
- RegistryScope } from "stroid/react"
1089
+ import {
1090
+ useStore,
1091
+ useSelector,
1092
+ useStoreField,
1093
+ useStoreStatic,
1094
+ useAsyncStore,
1095
+ useFormStore,
1096
+ useAsyncStoreSuspense,
1097
+ RegistryScope,
1098
+ } from "stroid/react";
115
1099
 
116
1100
  // Async
117
- import { fetchStore, refetchStore, enableRevalidateOnFocus } from "stroid/async"
1101
+ import { fetchStore, refetchStore, enableRevalidateOnFocus } from "stroid/async";
118
1102
 
119
- // Selectors & Computed
120
- import { createSelector, subscribeWithSelector } from "stroid/selectors"
121
- import { createComputed, invalidateComputed,
122
- deleteComputed, isComputedStore } from "stroid/computed"
1103
+ // Query keys only
1104
+ import { reactQueryKey, swrKey } from "stroid/query";
123
1105
 
124
- // Features (explicit install — call once at app entry)
125
- import { installPersist } from "stroid/persist"
126
- import { installSync } from "stroid/sync"
127
- import { installDevtools } from "stroid/devtools"
1106
+ // Selectors & Computed
1107
+ import { createSelector, subscribeWithSelector } from "stroid/selectors";
1108
+ import { createComputed, invalidateComputed, deleteComputed, isComputedStore } from "stroid/computed";
128
1109
 
129
- installPersist()
130
- installSync()
131
- installDevtools()
1110
+ // Features (explicit install - call once at app entry)
1111
+ import { installPersist } from "stroid/persist";
1112
+ import { installSync } from "stroid/sync";
1113
+ import { installDevtools, getHistory, clearHistory } from "stroid/devtools";
132
1114
 
1115
+ installPersist();
1116
+ installSync();
1117
+ installDevtools();
133
1118
 
134
1119
  // Server / SSR
135
- import { createStoreForRequest } from "stroid/server"
1120
+ import { createStoreForRequest } from "stroid/server";
136
1121
 
137
1122
  // Helpers & Testing
138
- import { createEntityStore, createListStore, createCounterStore } from "stroid/helpers"
139
- import { createMockStore, resetAllStoresForTest,
140
- withMockedTime, benchmarkStoreSet } from "stroid/testing"
141
-
142
- // Runtime Observability
143
- import { listStores, getStoreMeta, getMetrics,
144
- getSubscriberCount, getStoreHealth, findColdStores,
145
- getComputedGraph, getComputedDeps,
146
- getPersistQueueDepth } from "stroid/runtime-tools"
147
- import { clearAllStores, clearStores } from "stroid/runtime-admin"
1123
+ import { createEntityStore, createListStore, createCounterStore } from "stroid/helpers";
1124
+ import { createMockStore, resetAllStoresForTest, withMockedTime, benchmarkStoreSet } from "stroid/testing";
148
1125
 
149
- // Devtools API (after installDevtools())
150
- import { getHistory, clearHistory } from "stroid/devtools"
151
-
152
- // Config
153
- import { configureStroid, resetConfig,
154
- registerMutatorProduce } from "stroid"
1126
+ // Runtime Observability + Admin
1127
+ import {
1128
+ listStores,
1129
+ getStoreMeta,
1130
+ getMetrics,
1131
+ getSubscriberCount,
1132
+ getStoreHealth,
1133
+ findColdStores,
1134
+ getComputedGraph,
1135
+ getComputedDeps,
1136
+ getPersistQueueDepth,
1137
+ } from "stroid/runtime-tools";
1138
+ import { clearAllStores, clearStores } from "stroid/runtime-admin";
155
1139
 
156
1140
  // Feature plugin API
157
- import { registerStoreFeature,
158
- hasRegisteredStoreFeature,
159
- getRegisteredFeatureNames } from "stroid/feature"
1141
+ import { registerStoreFeature, hasRegisteredStoreFeature, getRegisteredFeatureNames } from "stroid/feature";
1142
+
1143
+ // Optional all-in-one installer
1144
+ import { installAllFeatures } from "stroid/install";
160
1145
  ```
161
1146
 
162
1147
  ---
163
1148
 
164
- ## Docs
1149
+ ## 🧷 Native PSR Contract
1150
+
1151
+ `stroid/psr` is the supported public surface for native PSR-style integration.
1152
+
1153
+ - Committed reads: `getStoreSnapshot()` and `getStoreSnapshotNoTrack()`
1154
+ - Committed-final observation: `subscribeStore()`
1155
+ - Serializable writes: `applyStorePatch()` and `applyStorePatchesAtomic()` with `set`, `merge`, `delete`, and `insert`
1156
+ - Runtime inspection: `getRuntimeGraph()`, `getComputedDescriptor()`, `evaluateComputed()`, and `getTimingContract()`
1157
+
1158
+ See [Native PSR Contract](./docs/STROID_PSR/INDEX.md) for full details.
1159
+
1160
+ ---
1161
+
1162
+ ## 📘 Docs
165
1163
 
166
1164
  Full documentation in [`/docs`](./docs/):
167
1165
 
168
- - [Architecture](./docs/architecture/ARCHITECTURE.md) layers, data flow, registry model
169
- - [Core Concepts](./docs/core-concepts/STORES.md) store lifecycle, options, write modes
170
- - [React Layer](./docs/guides/REACT.md) hooks, selectors, SSR
171
- - [Async Layer](./docs/guides/ASYNC.md) `fetchStore`, caching, revalidation
172
- - [Persistence](./docs/guides/PERSIST.md) `localStorage`, encryption, migrations
173
- - [Cross-tab Sync](./docs/guides/SYNC.md) `BroadcastChannel`, conflict resolution
174
- - [Computed Stores](./docs/guides/COMPUTED.md) reactive derived values
175
- - [Server & SSR](./docs/guides/SERVER.md) — request-scoped stores, hydration
176
- - [Testing](./docs/guides/TESTING.md) mock stores, resets, benchmarks
177
- - [Devtools](./docs/guides/DEVTOOLS.md) history, redaction
178
- - [Runtime Tools](./docs/guides/RUNTIME_TOOLS.md) observability, health checks
179
- - [Full API Reference](./docs/api/API_REFERENCE.md)
1166
+ - [Architecture](./docs/STROID_ARCHITECTURE/AECHITECTURE.md) - layers, data flow, registry model
1167
+ - [Core Concepts](./docs/STROID_CORE/INDEX.md) - store lifecycle, options, write modes
1168
+ - [React Layer](./docs/STROID_REACT/INDEX.md) - hooks, selectors, SSR
1169
+ - [Async Layer](./docs/STROID_ASYNC/INDEX.md) - `fetchStore`, caching, revalidation
1170
+ - [Persistence](./docs/STROID_PERSIST/INDEX.md) - persist options, encryption, migrations
1171
+ - [Cross-tab Sync](./docs/STROID_SYNC/INDEX.md) - BroadcastChannel sync behavior
1172
+ - [Computed Stores](./docs/STROID_COMPUTED/INDEX.md) - reactive derived values
1173
+ - [Native PSR Contract](./docs/STROID_PSR/INDEX.md) - patch coverage, timing/governance, graph identity
1174
+ - [Server & SSR](./docs/STROID_SERVER/INDEX.md) - request-scoped stores, hydration
1175
+ - [Testing](./docs/STROID_TESTING/INDEX.md) - mock stores, resets, benchmarks
1176
+ - [Runtime Tools](./docs/STROID_RUNTIME_TOOLS/INDEX.md) - observability, health checks
1177
+ - [TypeScript Guide](./docs/STROID_TYPESCRIPT/INDEX.md)
1178
+ - [Full API Reference](./docs/api/stroid.api.md)
180
1179
  - [Project Status](./STATUS.MD)
181
1180
  - [Contributing](./CONTRIBUTING.md)
182
1181
 
183
1182
  ---
184
1183
 
185
- ## Changelog & License
1184
+ ## 📝 Changelog & License
186
1185
 
187
1186
  - [CHANGELOG](./CHANGELOG.md)
188
1187
  - [MIT License](./LICENSE)
189
1188
  - [Issues](https://github.com/Himesh-Bhattarai/stroid/issues)
190
1189
 
1190
+
1191
+ <div align="center">
1192
+
1193
+ **Made with care for developers who think about state seriously.**
1194
+
1195
+ [⭐ Star on GitHub](https://github.com/Himesh-Bhattarai/stroid) · [🐛 Report a bug](https://github.com/Himesh-Bhattarai/stroid/issues) · [💬 Discussions](https://github.com/Himesh-Bhattarai/stroid/discussions)
1196
+
1197
+ </div>