stroid 0.1.3 โ†’ 0.1.4

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 (133) hide show
  1. package/CHANGELOG.md +312 -265
  2. package/README.md +1017 -115
  3. package/dist/async.d.ts +1 -1
  4. package/dist/async.js +1 -33
  5. package/dist/chunk-645IESIU.js +2 -0
  6. package/dist/chunk-6ELWGQ4Q.js +2 -0
  7. package/dist/chunk-BW32TJGE.js +13 -0
  8. package/dist/chunk-FOQKGHPS.js +26 -0
  9. package/dist/chunk-KQCSFGHJ.js +2 -0
  10. package/dist/chunk-M2NJVI36.js +2 -0
  11. package/dist/chunk-PVATWAY4.js +2 -0
  12. package/dist/chunk-X3JR32JD.js +2 -0
  13. package/dist/chunk-YU5GMPCC.js +2 -0
  14. package/dist/computed-types.d.ts +42 -0
  15. package/dist/computed-types.js +2 -0
  16. package/dist/computed.d.ts +9 -2
  17. package/dist/computed.js +1 -12
  18. package/dist/core.js +1 -22
  19. package/dist/devtools.d.ts +1 -1
  20. package/dist/devtools.js +1 -1
  21. package/dist/feature.js +1 -1
  22. package/dist/helpers.js +1 -22
  23. package/dist/index-internal.d.ts +1 -1
  24. package/dist/index.d.cts +3 -1
  25. package/dist/index.d.ts +3 -1
  26. package/dist/index.js +1 -35
  27. package/dist/install.js +1 -1
  28. package/dist/options.d.ts +1 -1
  29. package/dist/persist.js +1 -1
  30. package/dist/psr.d.ts +48 -0
  31. package/dist/psr.js +2 -0
  32. package/dist/react/index.d.ts +3 -1
  33. package/dist/react/index.js +5 -36
  34. package/dist/registry.d.ts +1 -0
  35. package/dist/runtime-admin.js +1 -1
  36. package/dist/runtime-patch.d.ts +29 -0
  37. package/dist/runtime-tools.d.ts +6 -1
  38. package/dist/runtime-tools.js +1 -3
  39. package/dist/selectors.js +1 -1
  40. package/dist/server.d.ts +4 -1
  41. package/dist/server.js +1 -12
  42. package/dist/store-registry.d.ts +8 -0
  43. package/dist/sync.js +1 -1
  44. package/dist/testing.js +1 -22
  45. package/dist/types/adapters/options.d.ts +335 -0
  46. package/dist/types/async/cache.d.ts +40 -0
  47. package/dist/types/async/clone.d.ts +10 -0
  48. package/dist/types/async/errors.d.ts +3 -0
  49. package/dist/types/async/fetch.d.ts +37 -0
  50. package/dist/types/async/inflight.d.ts +30 -0
  51. package/dist/types/async/rate.d.ts +5 -0
  52. package/dist/types/async/registry.d.ts +117 -0
  53. package/dist/types/async/request.d.ts +11 -0
  54. package/dist/types/async/retry.d.ts +10 -0
  55. package/dist/types/async.d.ts +10 -0
  56. package/dist/types/computed/computed-graph.d.ts +33 -0
  57. package/dist/types/computed/index.d.ts +21 -0
  58. package/dist/types/computed/types.d.ts +40 -0
  59. package/dist/types/config.d.ts +10 -0
  60. package/dist/types/core/index.d.ts +11 -0
  61. package/dist/types/core/lifecycle-hooks.d.ts +16 -0
  62. package/dist/types/core/runtime-patch.d.ts +67 -0
  63. package/dist/types/core/store-admin-impl.d.ts +9 -0
  64. package/dist/types/core/store-admin.d.ts +9 -0
  65. package/dist/types/core/store-core.d.ts +13 -0
  66. package/dist/types/core/store-create.d.ts +16 -0
  67. package/dist/types/core/store-hydrate-impl.d.ts +35 -0
  68. package/dist/types/core/store-hydrate.d.ts +9 -0
  69. package/dist/types/core/store-lifecycle/hooks.d.ts +20 -0
  70. package/dist/types/core/store-lifecycle/identity.d.ts +23 -0
  71. package/dist/types/core/store-lifecycle/registry.d.ts +54 -0
  72. package/dist/types/core/store-lifecycle/types.d.ts +67 -0
  73. package/dist/types/core/store-lifecycle/validation.d.ts +53 -0
  74. package/dist/types/core/store-name.d.ts +28 -0
  75. package/dist/types/core/store-notify.d.ts +13 -0
  76. package/dist/types/core/store-read.d.ts +18 -0
  77. package/dist/types/core/store-registry.d.ts +115 -0
  78. package/dist/types/core/store-replace-impl.d.ts +11 -0
  79. package/dist/types/core/store-replace.d.ts +9 -0
  80. package/dist/types/core/store-set-impl.d.ts +13 -0
  81. package/dist/types/core/store-set.d.ts +9 -0
  82. package/dist/types/core/store-shared/core.d.ts +13 -0
  83. package/dist/types/core/store-shared/notify.d.ts +12 -0
  84. package/dist/types/core/store-transaction.d.ts +28 -0
  85. package/dist/types/core/store-write-shared.d.ts +25 -0
  86. package/dist/types/core/store-write.d.ts +13 -0
  87. package/dist/types/features/feature-registry.d.ts +91 -0
  88. package/dist/types/features/lifecycle.d.ts +40 -0
  89. package/dist/types/index.d.ts +17 -0
  90. package/dist/types/integrations/query.d.ts +8 -0
  91. package/dist/types/internals/computed-order.d.ts +3 -0
  92. package/dist/types/internals/config.d.ts +116 -0
  93. package/dist/types/internals/diagnostics.d.ts +21 -0
  94. package/dist/types/internals/reporting.d.ts +9 -0
  95. package/dist/types/internals/store-admin.d.ts +7 -0
  96. package/dist/types/internals/store-ops.d.ts +13 -0
  97. package/dist/types/internals/test-reset.d.ts +2 -0
  98. package/dist/types/internals/write-context.d.ts +20 -0
  99. package/dist/types/notification/delivery.d.ts +3 -0
  100. package/dist/types/notification/index.d.ts +10 -0
  101. package/dist/types/notification/metrics.d.ts +12 -0
  102. package/dist/types/notification/priority.d.ts +9 -0
  103. package/dist/types/notification/scheduler.d.ts +11 -0
  104. package/dist/types/notification/snapshot.d.ts +8 -0
  105. package/dist/types/runtime-admin/index.d.ts +2 -0
  106. package/dist/types/runtime-tools/index.d.ts +63 -0
  107. package/dist/types/store.d.ts +16 -0
  108. package/dist/types/types/utility.d.ts +17 -0
  109. package/dist/types/utils/clone.d.ts +4 -0
  110. package/dist/types/utils/devfreeze.d.ts +2 -0
  111. package/dist/types/utils/hash.d.ts +8 -0
  112. package/dist/types/utils/path.d.ts +5 -0
  113. package/dist/types/utils/validation.d.ts +14 -0
  114. package/dist/types/utils.d.ts +13 -0
  115. package/dist/types.d.ts +2 -2
  116. package/package.json +31 -20
  117. package/dist/async.js.map +0 -1
  118. package/dist/computed.js.map +0 -1
  119. package/dist/core.js.map +0 -1
  120. package/dist/devtools.js.map +0 -1
  121. package/dist/feature.js.map +0 -1
  122. package/dist/helpers.js.map +0 -1
  123. package/dist/index.js.map +0 -1
  124. package/dist/install.js.map +0 -1
  125. package/dist/persist.js.map +0 -1
  126. package/dist/react/index.js.map +0 -1
  127. package/dist/runtime-admin.js.map +0 -1
  128. package/dist/runtime-tools.js.map +0 -1
  129. package/dist/selectors.js.map +0 -1
  130. package/dist/server.js.map +0 -1
  131. package/dist/sync.js.map +0 -1
  132. package/dist/testing.js.map +0 -1
  133. package/dist/tsdoc-metadata.json +0 -11
package/README.md CHANGED
@@ -1,188 +1,1090 @@
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/bundlephobia/minzip/stroid?color=1D9E75&label=minzipped&style=flat-square" alt="bundle size" />
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" />
15
+ <img src="https://img.shields.io/snyk/vulnerabilities/github/Himesh-Bhattarai/stroid?style=flat-square" alt="vulnerabilities" />
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 />
8
20
 
21
+ # ๐ŸŸฃ Stroid - State Engine for TypeScript and React
9
22
  **Named-store state engine for TypeScript and React.**
10
23
 
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.
24
+ 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 core logic.
25
+ <br />
26
+ [**Get Started**](#30-second-quickstart) | [**Why Stroid**](#why-stroid) | [**API Reference**](#full-api-reference) | [**PSR**](#psr---write-governance) | [**DevTools**](#devtools) | [**Examples**](#real-world-examples)
27
+
28
+ </div>
29
+
30
+ ---
31
+ > [!IMPORTANT]
32
+ > ## ๐Ÿง  What Is Stroid?
33
+ >
34
+ > A structured state management system focused on predictability, SSR safety, and debugging clarity.
35
+ >
36
+ > - Core store runtime (`createStore`, `setStore`, `getStore`)
37
+ > - React hooks (`useStore`, `useSelector`)
38
+ > - Async fetch/cache/revalidate
39
+ > - Optional features
40
+ > - SSR request isolation
41
+ > - Native PSR contract
42
+ ---
43
+
44
+ <a id="30-second-quickstart"></a>
45
+ ## โšก 30-Second Quickstart
46
+
47
+ ---
48
+
49
+ >[!NOTE]
50
+ >```bash
51
+ >npm install stroid
52
+ >```
53
+ ---
54
+
55
+ >[!NOTE]
56
+ >```ts
57
+ >import { createStore, setStore, getStore, configureStroid } from "stroid";
58
+ >import { installPersist } from "stroid/persist";
59
+ >import { installSync } from "stroid/sync";
60
+ >
61
+ >configureStroid({
62
+ > asyncAutoCreate: false,
63
+ > defaultSnapshotMode: "deep",
64
+ >});
65
+ >
66
+ >installPersist();
67
+ >installSync();
68
+ >//create store
69
+ >createStore("auth", { user: null, token: null });
70
+ >//create store with persist
71
+ >createStore("settings", { theme: "dark" }, { persist: true });
72
+ >//create store with sync and persist.
73
+ >createStore("session", { active: true }, { persist: true, sync: true });
74
+ >
75
+ >setStore("auth", "user", { id: "u1", name: "Asha" });
76
+ >const auth = getStore("auth");
77
+ >
78
+ >```
79
+ ---
80
+
81
+ ### Stroid PSR
82
+
83
+ Stroid ships a native PSR contract in `stroid/psr`.
84
+ It exposes committed snapshots, patch application APIs, and runtime graph/timing data used for governance flows.
85
+
86
+ ---
87
+
88
+ ## ๐Ÿ—บ๏ธ Ecosystem Map
89
+
90
+ Stroid is organized into focused sub-packages. Import only what you need.
91
+
92
+ ```
93
+ stroid <- core public runtime
94
+ |- stroid/react <- React hooks
95
+ |- stroid/core <- minimal core surface
96
+ |- stroid/psr <- native PSR contract
97
+ |- stroid/async <- fetch/cache/revalidate
98
+ |- stroid/selectors <- selector helpers
99
+ |- stroid/computed <- computed stores
100
+ |- stroid/persist <- installPersist()
101
+ |- stroid/sync <- installSync()
102
+ |- stroid/devtools <- installDevtools(), history API
103
+ |- stroid/server <- SSR request-scoped registry
104
+ |- stroid/helpers <- entity/list/counter helpers
105
+ |- stroid/testing <- test helpers
106
+ |- stroid/runtime-tools <- observability APIs
107
+ |- stroid/runtime-admin <- clear helpers
108
+ |- stroid/feature <- feature plugin API
109
+ |- stroid/install <- installAllFeatures()
110
+ ```
111
+
112
+ ---
113
+
114
+ <a id="why-stroid"></a>
115
+ ## ๐Ÿค” Why Stroid?
116
+
117
+ ### Honest comparison
118
+
119
+ | Feature | **Stroid** | Redux Toolkit | Zustand | Jotai | Valtio |
120
+ |---|:---:|:---:|:---:|:---:|:---:|
121
+ | Write without reducers | โœ… | โŒ | โœ… | โœ… | โœ… |
122
+ | Named global stores | โœ… | โœ… | โš ๏ธ manual | โŒ | โŒ |
123
+ | Write governance (PSR) | โœ… | โŒ | โŒ | โŒ | โŒ |
124
+ | Built-in DevTools extension | โœ… | โœ… | โš ๏ธ limited | โŒ | โŒ |
125
+ | Computed / derived state | โœ… | โœ… | โš ๏ธ manual | โœ… | โœ… |
126
+ | Async data built-in | โœ… | โœ… RTK Query | โŒ | โš ๏ธ | โŒ |
127
+ | SSR / request isolation | โœ… | โš ๏ธ | โš ๏ธ | โœ… | โš ๏ธ |
128
+ | Atomic rollback guarantee | โœ… | โŒ | โŒ | โŒ | โŒ |
129
+ | Race resistance proof | โœ… | โŒ | โŒ | โŒ | โŒ |
130
+ | Determinism replay | โœ… | โŒ | โŒ | โŒ | โŒ |
131
+ | Ring-buffer event timeline | โœ… | โŒ | โŒ | โŒ | โŒ |
132
+ | Bundle size (core import closure) | 77.6kb raw / 25.1kb gzip | ~11kb | ~1kb | ~3kb | ~3kb |
133
+ | TypeScript-first | โœ… | โœ… | โœ… | โœ… | โœ… |
134
+
135
+ NOTE: BUNDLE SIZE: 25.1 gzip include whole "Stroid". Stroid is treeshakable so, stroid size will determine by your import.
136
+
137
+ > โš ๏ธ = possible with extra setup ยท โŒ = not supported natively
138
+
139
+ Stroid exposes governance-oriented write flows through `stroid/psr`, including committed snapshot reads, patch application APIs, runtime graph inspection, and timing contracts.
140
+ Benchmark report: [docs/STROID/BENCHMARK.md](./docs/STROID/BENCHMARK.md).
141
+
142
+ Stroid is a fit when you need these together:
143
+ - Named global stores with direct writes
144
+ - Optional feature installs instead of mandatory side effects
145
+ - Strict hydration trust gate (`hydrateStores(..., ..., { allowTrusted: true })`)
146
+ - Request-scoped SSR runtime (`createStoreForRequest`) with server guards
147
+ - PSR-style patch application and runtime graph inspection (`stroid/psr`)
148
+
149
+ If you only need ultra-minimal local state, `stroid/core` exists for a smaller surface.
150
+
151
+ ---
152
+
153
+ <a id="full-api-reference"></a>
154
+ ## ๐Ÿ“š Full API Reference
155
+
156
+ All examples use real APIs from this repository's current source.
157
+
158
+ ## โš™๏ธ Core - `stroid`
159
+
160
+ ### `createStore`
161
+
162
+ ```ts
163
+ import { createStore } from "stroid";
164
+
165
+ createStore("cart", {
166
+ items: [],
167
+ total: 0,
168
+ });
169
+ ```
170
+
171
+ Creates a named store and registers its initial state.
172
+
173
+ ---
174
+
175
+ ### `setStore`
176
+
177
+ ```ts
178
+ import { setStore } from "stroid";
179
+
180
+ setStore("cart", "total", 499);
181
+ setStore("cart", { currency: "NPR" });
182
+ setStore("cart", (draft: any) => {
183
+ draft.items.push({ id: "pizza", qty: 1 });
184
+ });
185
+ ```
186
+ Updates existing store state by path, partial object merge, or mutator function.
187
+
188
+ ---
189
+
190
+ ### `getStore`
191
+
192
+ ```ts
193
+ import { getStore } from "stroid";
194
+
195
+ const cart = getStore("cart");
196
+ const total = getStore("cart", "total");
197
+ ```
198
+ Reads current store state, optionally at a nested path.
199
+
200
+ ---
201
+
202
+ ### `hasStore`
203
+
204
+ ```ts
205
+ import { hasStore, createStore } from "stroid";
206
+
207
+ if (!hasStore("cart")) {
208
+ createStore("cart", { items: [], total: 0 });
209
+ }
210
+ ```
211
+ Checks whether a store is already registered.
212
+
213
+ ---
214
+
215
+ ### `resetStore`
216
+
217
+ ```ts
218
+ import { resetStore } from "stroid";
219
+
220
+ resetStore("cart");
221
+ ```
222
+ Resets a store back to its original initial state.
223
+
224
+ ---
225
+
226
+ ### `deleteStore`
227
+
228
+ ```ts
229
+ import { deleteStore } from "stroid";
230
+
231
+ deleteStore("cart");
232
+ ```
233
+ Removes a store and its runtime metadata/subscriptions.
234
+
235
+ ---
236
+
237
+ ### `setStoreBatch`
238
+
239
+ ```ts
240
+ import { setStoreBatch, setStore } from "stroid";
241
+
242
+ setStoreBatch(() => {
243
+ setStore("checkout", "coupon", "SAVE20");
244
+ setStore("checkout", "deliveryType", "priority");
245
+ setStore("checkout", "tip", 50);
246
+ });
247
+ ```
248
+ `setStoreBatch` accepts only synchronous callbacks.
249
+ Runs multiple synchronous writes in one transaction-style batch.
250
+
251
+ ---
252
+
253
+ ### `hydrateStores`
254
+
255
+ ```ts
256
+ import { hydrateStores } from "stroid";
257
+
258
+ hydrateStores(
259
+ {
260
+ cart: { items: [{ id: "pizza", qty: 1 }], total: 499 },
261
+ profile: { name: "Asha" },
262
+ },
263
+ {},
264
+ { allowTrusted: true }
265
+ );
266
+ ```
267
+ Hydrates many stores from a trusted snapshot payload.
268
+
269
+ ---
270
+
271
+ ### `configureStroid`
272
+
273
+ ```ts
274
+ import { configureStroid } from "stroid";
275
+
276
+ configureStroid({
277
+ asyncAutoCreate: false,
278
+ strictMutatorReturns: true,
279
+ defaultSnapshotMode: "deep",
280
+ });
281
+ ```
282
+ Sets global runtime behavior such as async and snapshot defaults.
283
+
284
+ ---
285
+
286
+ ## โš›๏ธ React Hooks - `stroid/react`
287
+
288
+ ### `useStore`
289
+
290
+ ```tsx
291
+ import { useStore } from "stroid/react";
292
+
293
+ function CartPanel() {
294
+ const cart = useStore("cart");
295
+ return <div>{cart ? `${cart.items.length} items` : "Cart empty"}</div>;
296
+ }
297
+ ```
298
+ Subscribes React components to a store value (full store, path, or selector form).
299
+
300
+ ---
301
+
302
+ ### `useSelector`
303
+
304
+ ```tsx
305
+ import { useSelector } from "stroid/react";
306
+
307
+ function CartTotal() {
308
+ const total = useSelector("cart", (s: any) => s?.total ?? 0);
309
+ return <strong>Rs. {total}</strong>;
310
+ }
311
+ ```
312
+ Subscribes to a derived slice and re-renders only when selected output changes.
313
+
314
+ ---
315
+
316
+ ### `useStoreField`
317
+
318
+ ```tsx
319
+ import { useStoreField } from "stroid/react";
320
+
321
+ function DeliveryTypeChip() {
322
+ const deliveryType = useStoreField("checkout", "deliveryType");
323
+ return <span>{deliveryType ?? "standard"}</span>;
324
+ }
325
+ ```
326
+ Subscribes directly to one field/path inside a store.
327
+
328
+ ---
329
+
330
+ ### `useStoreStatic`
331
+
332
+ ```tsx
333
+ import { useStoreStatic } from "stroid/react";
334
+
335
+ function DebugPanel() {
336
+ const snapshot = useStoreStatic("cart");
337
+ return <pre>{JSON.stringify(snapshot, null, 2)}</pre>;
338
+ }
339
+ ```
340
+ Reads a snapshot once without live subscription updates.
341
+
342
+ ---
343
+
344
+ ### `useAsyncStore`
345
+
346
+ ```tsx
347
+ import { useEffect } from "react";
348
+ import { useAsyncStore } from "stroid/react";
349
+ import { fetchStore } from "stroid/async";
350
+
351
+ function Menu() {
352
+ useEffect(() => {
353
+ void fetchStore("menu", "https://api.example.com/menu");
354
+ }, []);
355
+
356
+ const { loading, error, data } = useAsyncStore("menu");
357
+
358
+ if (loading) return <p>Loading menu...</p>;
359
+ if (error) return <p>Failed to load menu</p>;
360
+ return <MenuList items={data ?? []} />;
361
+ }
362
+ ```
363
+ Reads async store shape (`data/loading/error/status`) from an existing store.
364
+
365
+ ---
366
+
367
+ ### `useAsyncStoreSuspense`
368
+
369
+ ```tsx
370
+ import { useAsyncStoreSuspense } from "stroid/react";
371
+
372
+ function MenuSuspense() {
373
+ const menu = useAsyncStoreSuspense<Array<{ id: string; name: string }>>(
374
+ "menu",
375
+ "https://api.example.com/menu"
376
+ );
377
+
378
+ return <MenuList items={menu} />;
379
+ }
380
+ ```
381
+ Integrates async store reads with React Suspense by throwing pending work.
382
+
383
+ ---
384
+
385
+ ### `useFormStore`
386
+
387
+ ```tsx
388
+ import { createStore } from "stroid";
389
+ import { useFormStore } from "stroid/react";
390
+
391
+ createStore("loginForm", { email: "", password: "" });
392
+
393
+ function LoginForm() {
394
+ const email = useFormStore("loginForm", "email");
395
+ const password = useFormStore("loginForm", "password");
396
+
397
+ return (
398
+ <form>
399
+ <input value={email.value ?? ""} onChange={email.onChange} />
400
+ <input value={password.value ?? ""} onChange={password.onChange} type="password" />
401
+ <button disabled={!email.value || !password.value}>Sign in</button>
402
+ </form>
403
+ );
404
+ }
405
+ ```
406
+ Binds a store field to form-style `value` and `onChange` helpers.
407
+
408
+ ---
409
+
410
+ ### `RegistryScope`
411
+
412
+ ```tsx
413
+ import { RegistryScope } from "stroid/react";
414
+
415
+ function App({ registry }: { registry: any }) {
416
+ return (
417
+ <RegistryScope value={registry}>
418
+ <CartPanel />
419
+ <ProfilePanel />
420
+ </RegistryScope>
421
+ );
422
+ }
423
+ ```
424
+ Scopes a React subtree to a specific store registry context.
425
+
426
+ ---
427
+
428
+ ## ๐›ฒSe Selectors & Computed
429
+
430
+ ### `createSelector` - `stroid/selectors`
431
+
432
+ ```ts
433
+ import { createSelector } from "stroid/selectors";
434
+
435
+ const selectItemCount = createSelector("cart", (s: any) => s?.items?.length ?? 0);
436
+ const count = selectItemCount();
437
+ ```
438
+ Builds a memoized selector function for derived store reads.
439
+
440
+ ---
441
+
442
+ ### `subscribeWithSelector` - `stroid/selectors`
443
+
444
+ ```ts
445
+ import { subscribeWithSelector } from "stroid/selectors";
446
+
447
+ const stop = subscribeWithSelector(
448
+ "cart",
449
+ (s: any) => s?.total,
450
+ Object.is,
451
+ (next, prev) => {
452
+ if (typeof prev === "number" && next > prev) {
453
+ // run side effect
454
+ }
455
+ }
456
+ );
457
+
458
+ stop();
459
+ ```
460
+ Runs a listener only when the selected value changes by equality check.
461
+
462
+ ---
463
+
464
+ ### `createComputed` - `stroid/computed`
465
+
466
+ ```ts
467
+ import { createComputed } from "stroid/computed";
468
+ import { getStore } from "stroid";
469
+
470
+ createComputed("deliveryFee", ["cart"], (cart: any) => (cart?.total ?? 0) > 1000 ? 0 : 60);
471
+
472
+ const fee = getStore("deliveryFee");
473
+ ```
474
+ Creates a computed store derived from one or more dependency stores.
475
+
476
+ ---
477
+
478
+ ### `invalidateComputed` / `deleteComputed` / `isComputedStore`
479
+
480
+ ```ts
481
+ import { invalidateComputed, deleteComputed, isComputedStore } from "stroid/computed";
482
+
483
+ invalidateComputed("deliveryFee");
484
+ deleteComputed("deliveryFee");
485
+ isComputedStore("deliveryFee");
486
+ ```
487
+ Invalidates, removes, or checks computed-store registrations.
488
+
489
+ ---
490
+
491
+ ## โฑ๏ธ Async - `stroid/async`
492
+
493
+ ```ts
494
+ import { fetchStore, refetchStore, enableRevalidateOnFocus } from "stroid/async";
495
+
496
+ await fetchStore("menu", "https://api.example.com/menu");
497
+ await refetchStore("menu");
498
+ const stopFocusRevalidate = enableRevalidateOnFocus("menu");
499
+
500
+ stopFocusRevalidate();
501
+ ```
502
+ Fetches/refetches remote data into stores with cache, dedupe, retries, and focus revalidation.
503
+
504
+ ---
505
+
506
+ ## PSR - Write Governance
507
+
508
+ ```ts
509
+ import { applyStorePatch, applyStorePatchesAtomic } from "stroid/psr";
510
+
511
+ applyStorePatch({
512
+ id: "cart-total-set",
513
+ store: "cart",
514
+ path: ["total"],
515
+ op: "set",
516
+ value: 549,
517
+ meta: { timestamp: Date.now(), source: "setStore" },
518
+ });
519
+
520
+ applyStorePatchesAtomic([
521
+ {
522
+ id: "wallet-set",
523
+ store: "wallet",
524
+ path: ["balance"],
525
+ op: "set",
526
+ value: 900,
527
+ meta: { timestamp: Date.now(), source: "setStore" },
528
+ },
529
+ {
530
+ id: "order-set",
531
+ store: "order",
532
+ path: ["status"],
533
+ op: "set",
534
+ value: "paid",
535
+ meta: { timestamp: Date.now(), source: "setStore" },
536
+ },
537
+ ]);
538
+ ```
539
+ Applies patch-based governed writes with atomic multi-patch support.
540
+
541
+ ---
542
+
543
+ ## ๐Ÿ›ก๏ธ Features - `stroid/feature`
544
+
545
+ ### Install - Opt-In Capabilities
546
+
547
+ ```ts
548
+ import { installPersist } from "stroid/persist";
549
+ import { installSync } from "stroid/sync";
550
+ import { installDevtools } from "stroid/devtools";
551
+
552
+ installPersist();
553
+ installSync();
554
+ installDevtools();
555
+ ```
556
+ Installs optional persist/sync/devtools features explicitly at app entry.
557
+
558
+ ---
559
+
560
+ ## ๐ŸŒ SSR - `stroid/server`
561
+
562
+ ```ts
563
+ import { createStoreForRequest } from "stroid/server";
564
+
565
+ const requestScope = createStoreForRequest((api) => {
566
+ api.create("session", { userId: "u-1" });
567
+ api.create("cart", { items: [], total: 0 });
568
+ });
569
+
570
+ const html = requestScope.hydrate(() => renderToString(<App />));
571
+ const snapshot = requestScope.snapshot();
572
+ ```
573
+ Creates per-request store scopes for SSR-safe hydrate/snapshot flows.
574
+
575
+ ---
576
+
577
+ ## ๐Ÿ”ข Helpers - `stroid/helpers`
578
+
579
+ ```ts
580
+ import { createEntityStore, createListStore, createCounterStore } from "stroid/helpers";
581
+
582
+ const users = createEntityStore<{ id?: string; name: string }>("users");
583
+ users.upsert({ id: "u1", name: "Asha" });
584
+ users.remove("u1");
585
+
586
+ const tasks = createListStore("tasks", [] as string[]);
587
+ tasks.push("pick up order");
588
+ tasks.removeAt(0);
589
+ tasks.clear();
590
+
591
+ const retries = createCounterStore("retries", 0);
592
+ retries.inc();
593
+ retries.dec();
594
+ retries.set(5);
595
+ const retryValue = retries.get();
596
+ ```
597
+ Provides ready-made entity, list, and counter store helpers.
598
+
599
+ ---
600
+
601
+ ## ๐Ÿงช Testing - `stroid/testing`
602
+
603
+ ```ts
604
+ import {
605
+ createMockStore,
606
+ resetAllStoresForTest,
607
+ withMockedTime,
608
+ benchmarkStoreSet,
609
+ } from "stroid/testing";
610
+
611
+ const mockOrder = createMockStore("order", { status: "draft" });
612
+ mockOrder.set({ status: "confirmed" });
613
+
614
+ withMockedTime(1700000000000, () => {
615
+ // Date.now() is fixed in this callback
616
+ });
617
+
618
+ const result = benchmarkStoreSet({ name: "cart" } as any, 300);
619
+ const avgMs = result.avgMs;
620
+
621
+ resetAllStoresForTest();
622
+ ```
623
+ Provides test helpers for mock stores, time control, reset, and micro-benchmarks.
624
+
625
+ ---
626
+
627
+ ## ๐Ÿ“ˆ Runtime Observability - `stroid/runtime-tools`
628
+
629
+ ```ts
630
+ import {
631
+ listStores,
632
+ getStoreMeta,
633
+ getMetrics,
634
+ getSubscriberCount,
635
+ getStoreHealth,
636
+ findColdStores,
637
+ getComputedGraph,
638
+ getComputedDeps,
639
+ getPersistQueueDepth,
640
+ } from "stroid/runtime-tools";
641
+
642
+ const stores = listStores();
643
+ const meta = getStoreMeta("cart");
644
+ const metrics = getMetrics("cart");
645
+ const subscribers = getSubscriberCount("cart");
646
+ const health = getStoreHealth();
647
+ const cold = findColdStores();
648
+ const graph = getComputedGraph();
649
+ const deps = getComputedDeps("deliveryFee");
650
+ const persistDepth = getPersistQueueDepth("cart");
651
+ ```
652
+ Exposes runtime diagnostics for stores, metrics, health, and computed graph state.
653
+
654
+ ---
655
+
656
+ ## ๐Ÿ”ง Runtime Admin - `stroid/runtime-admin`
657
+
658
+ ```ts
659
+ import { clearAllStores, clearStores } from "stroid/runtime-admin";
660
+
661
+ clearStores("cart*");
662
+ clearAllStores();
663
+ ```
664
+ Clears stores in bulk by pattern or globally.
665
+
666
+ ---
667
+
668
+ ## ๐ŸŒ‰ DevTools Bridge - `stroid/devtools`
12
669
 
13
670
  ```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)
671
+ import { installDevtools, getHistory, clearHistory } from "stroid/devtools";
672
+
673
+ installDevtools();
674
+
675
+ const cartHistory = getHistory("cart");
676
+ // Array<HistoryEntry> where entry has: ts, action, prev, next, diff
677
+
678
+ clearHistory("cart");
679
+ ```
680
+ Connects to devtools runtime and exposes local history read/clear APIs.
681
+
682
+ ---
683
+
684
+ ## ๐Ÿ”Œ Feature Plugin API - `stroid/feature`
685
+
686
+ ```ts
687
+ import {
688
+ registerStoreFeature,
689
+ hasRegisteredStoreFeature,
690
+ getRegisteredFeatureNames,
691
+ } from "stroid/feature";
692
+
693
+ registerStoreFeature("auditFeature", () => ({
694
+ onStoreCreate(ctx) {
695
+ // fires when a store is created
696
+ },
697
+ onStoreWrite(ctx) {
698
+ // fires on store write
699
+ },
700
+ }));
701
+
702
+ const hasAudit = hasRegisteredStoreFeature("auditFeature");
703
+ const featureNames = getRegisteredFeatureNames();
704
+ ```
705
+ Registers custom feature runtimes with lifecycle hooks.
706
+
707
+ ---
708
+
709
+ <a id="psr---write-governance"></a>
710
+ ## ๐Ÿ›ก๏ธ PSR - Write Governance - `stroid/psr`
711
+
712
+ PSR (`stroid/psr`) is the public contract for:
713
+ - Committed snapshots
714
+ - Post-commit subscriptions
715
+ - Serializable patch application
716
+ - Runtime graph and timing contract inspection
717
+
718
+ ### PSR API
719
+
720
+ ```ts
721
+ import {
722
+ getStoreSnapshot,
723
+ getStoreSnapshotNoTrack,
724
+ subscribeStore,
725
+ applyStorePatch,
726
+ applyStorePatchesAtomic,
727
+ getRuntimeGraph,
728
+ getComputedDescriptor,
729
+ evaluateComputed,
730
+ getTimingContract,
731
+ } from "stroid/psr";
732
+
733
+ const committed = getStoreSnapshot("cart");
734
+ const committedNoTrack = getStoreSnapshotNoTrack("cart");
735
+
736
+ const unsubscribe = subscribeStore("cart", (next) => {
737
+ // handle committed updates
738
+ });
739
+
740
+ const graph = getRuntimeGraph();
741
+ const checkoutNode = graph.nodes.find(
742
+ (n) => n.storeId === "checkoutTotal" && (n.type === "computed" || n.type === "async-boundary")
743
+ );
744
+
745
+ if (checkoutNode) {
746
+ const descriptor = getComputedDescriptor(checkoutNode.id);
747
+ const preview = evaluateComputed(checkoutNode.id, {
748
+ cart: { items: [{ id: "pizza", qty: 2 }], total: 998 },
749
+ });
750
+ }
751
+
752
+ const timing = getTimingContract("cart");
17
753
  ```
754
+ Exposes committed snapshots, subscriptions, patch APIs, runtime graph, and timing contract.
755
+ ---
756
+
757
+ <a id="devtools"></a>
758
+ ## ๐Ÿ”ฌ DevTools - `stroid/devtools`
759
+
760
+ `stroid/devtools` integrates with the Redux DevTools browser extension and also keeps in-memory history per store.
761
+
762
+ What you get from code:
763
+ - `installDevtools()` to enable the devtools feature runtime
764
+ - `getHistory(name, limit?)` to read recorded store history
765
+ - `clearHistory(name?)` to clear one store or all stores
766
+
767
+ Setup:
768
+ 1. Install Redux DevTools extension in your browser.
769
+ 2. Call `installDevtools()` once in app entry.
770
+ 3. Open browser DevTools and inspect the connected `stroid` session.
18
771
 
19
772
  ---
20
773
 
21
- ## Install
774
+ <a id="real-world-examples"></a>
775
+ ## ๐Ÿ• Real-World Examples
776
+
777
+ ### Food delivery cart (full flow)
778
+
779
+ ```tsx
780
+ // app/entry.ts
781
+ import { configureStroid } from "stroid";
782
+ import { installPersist } from "stroid/persist";
783
+ import { installDevtools } from "stroid/devtools";
784
+
785
+ configureStroid({ asyncAutoCreate: false });
786
+ installPersist();
787
+ installDevtools();
788
+
789
+ // stores/cart.ts
790
+ import { createStore, setStoreBatch, setStore } from "stroid";
22
791
 
23
- ```bash
24
- npm install stroid
792
+ createStore("cart", { items: [], total: 0 });
793
+ createStore("checkout", { coupon: null, deliveryType: "standard", tip: 0 });
794
+
795
+ // components/CartPanel.tsx
796
+ import { useSelector, useStoreField } from "stroid/react";
797
+
798
+ function CartPanel() {
799
+ const total = useSelector("cart", (s: any) => s?.total ?? 0);
800
+ const deliveryType = useStoreField("checkout", "deliveryType");
801
+
802
+ function applyPromo() {
803
+ setStoreBatch(() => {
804
+ setStore("checkout", "coupon", "SAVE20");
805
+ setStore("checkout", "deliveryType", "priority");
806
+ setStore("checkout", "tip", 50);
807
+ });
808
+ }
809
+
810
+ return (
811
+ <div>
812
+ <p>Total: Rs. {total}</p>
813
+ <p>Delivery: {deliveryType}</p>
814
+ <button onClick={applyPromo}>Apply promo</button>
815
+ </div>
816
+ );
817
+ }
25
818
  ```
26
819
 
27
- **Requirements:** Node `>=18`. React `>=18` (only if using `stroid/react`).
820
+ ### Atomic payment (wallet + order status)
821
+
822
+ ```ts
823
+ import { getStore } from "stroid";
824
+ import { applyStorePatchesAtomic } from "stroid/psr";
825
+
826
+ function confirmPayment(amount: number) {
827
+ const wallet = getStore("wallet") as { balance: number } | null;
828
+ const nextBalance = (wallet?.balance ?? 0) - amount;
28
829
 
29
- **ESM-only:** Stroid ships ESM only. If your toolchain requires CJS, use a bundler with ESM support (Vite, webpack 5, esbuild).
830
+ applyStorePatchesAtomic([
831
+ {
832
+ id: "pay-wallet",
833
+ store: "wallet",
834
+ path: ["balance"],
835
+ op: "set",
836
+ value: nextBalance,
837
+ meta: { timestamp: Date.now(), source: "setStore" },
838
+ },
839
+ {
840
+ id: "pay-order",
841
+ store: "order",
842
+ path: ["status"],
843
+ op: "set",
844
+ value: "paid",
845
+ meta: { timestamp: Date.now(), source: "setStore" },
846
+ },
847
+ ]);
848
+ }
849
+ ```
850
+ Applies related wallet/order updates atomically so both succeed or fail together.
30
851
 
31
852
  ---
853
+ ### Menu with Suspense
854
+
855
+ ```tsx
856
+ import { Suspense } from "react";
857
+ import { useAsyncStoreSuspense } from "stroid/react";
858
+
859
+ function MenuList() {
860
+ const menu = useAsyncStoreSuspense<Array<{ id: string; name: string }>>(
861
+ "menu",
862
+ "https://api.example.com/menu"
863
+ );
32
864
 
33
- ## Layer Map
865
+ return <ul>{menu.map((item) => <li key={item.id}>{item.name}</li>)}</ul>;
866
+ }
34
867
 
868
+ export function MenuPage() {
869
+ return (
870
+ <Suspense fallback={<p>Loading menu...</p>}>
871
+ <MenuList />
872
+ </Suspense>
873
+ );
874
+ }
35
875
  ```
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
- โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
876
+ Loads menu data through Suspense-friendly async store access.
877
+
878
+ ---
879
+
880
+ ## ๐Ÿงฑ Layer Map
881
+
882
+ ```
883
+ +---------------------------------------------------------+
884
+ | your app |
885
+ +---------------------------------------------------------+
886
+ | useStore useSelector useAsyncStore useFormStore | stroid/react
887
+ +---------------------------------------------------------+
888
+ | createStore setStore getStore setStoreBatch | stroid
889
+ | createComputed createSelector createEntityStore |
890
+ +--------------+--------------+---------------------------+
891
+ | stroid/persist | stroid/sync | stroid/async |
892
+ | installPersist | installSync | fetch + cache + retry |
893
+ +--------------+--------------+---------------------------+
894
+ | stroid/server createStoreForRequest | SSR
895
+ +---------------------------------------------------------+
896
+ | stroid/devtools stroid/testing stroid/runtime-tools |
897
+ +---------------------------------------------------------+
51
898
  ```
52
899
 
53
900
  Each row is independent. Use only what you need.
54
901
 
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`.
902
+ `stroid/core` exports only `createStore`, `setStore`, `getStore`, `hasStore`, `resetStore`, and `deleteStore`.
903
+ Import from `stroid` for batching/hydration/computed plus runtime metrics and config.
56
904
 
57
- ## What Each Import Contains
905
+ ## ๐Ÿ“ฆ What Each Import Contains
58
906
 
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.
907
+ - `stroid`: Core public runtime (`createStore`, `createStoreStrict`, `setStore`, `setStoreBatch`, `getStore`, `deleteStore`, `resetStore`, `hasStore`, `hydrateStores`), plus `configureStroid`, computed helpers, and health/metric helpers.
908
+ - `stroid/psr`: PSR contract (`getStoreSnapshot`, `getStoreSnapshotNoTrack`, `subscribeStore`, `applyStorePatch`, `applyStorePatchesAtomic`, runtime graph/timing helpers).
909
+ - `stroid/core`: Minimal CRUD runtime (`createStore`, `setStore`, `getStore`, `hasStore`, `resetStore`, `deleteStore`).
910
+ - `stroid/react`: React hooks (`useStore`, `useSelector`, `useStoreField`, `useStoreStatic`, `useAsyncStore`, `useFormStore`, `useAsyncStoreSuspense`) and `RegistryScope`.
911
+ - `stroid/async`: Async APIs (`fetchStore`, `refetchStore`, `enableRevalidateOnFocus`, `getAsyncMetrics`).
63
912
  - `stroid/selectors`: `createSelector`, `subscribeWithSelector`.
64
913
  - `stroid/computed`: `createComputed`, `invalidateComputed`, `deleteComputed`, `isComputedStore`.
65
- - `stroid/persist`: Side-effect registration for persistence (localStorage/sessionStorage). Not tree-shakeable.
66
- - `stroid/sync`: Side-effect registration for BroadcastChannel sync. Not tree-shakeable.
67
- - `stroid/devtools`: Side-effect registration for Redux DevTools bridge. Not tree-shakeable.
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).
914
+ - `stroid/persist`: `installPersist`.
915
+ - `stroid/sync`: `installSync`.
916
+ - `stroid/devtools`: `installDevtools`, `getHistory`, `clearHistory`.
917
+ - `stroid/server`: `createStoreForRequest`.
918
+ - `stroid/helpers`: `createEntityStore`, `createListStore`, `createCounterStore`.
919
+ - `stroid/testing`: `createMockStore`, `resetAllStoresForTest`, `withMockedTime`, `benchmarkStoreSet`.
920
+ - `stroid/runtime-tools`: Store/runtime observability APIs.
921
+ - `stroid/runtime-admin`: `clearAllStores`, `clearStores`.
922
+ - `stroid/feature`: Feature registration APIs.
923
+ - `stroid/install`: `installPersist`, `installSync`, `installDevtools`, `installAllFeatures`.
73
924
 
74
925
  ---
75
926
 
76
- ## Quick API Reference
927
+ ## ๐Ÿงพ Quick API Reference
77
928
 
78
929
  | API | Purpose |
79
930
  |-----|---------|
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. |
931
+ | `createStore(name, state, options?)` | Define a store. Returns `StoreDefinition` or `undefined`. |
932
+ | `createStoreStrict(name, state, options?)` | Define a store; throws if creation fails. |
933
+ | `setStore(name, update)` | Merge object update into object store state. |
934
+ | `setStore(name, path, value)` | Write by path. |
935
+ | `setStore(name, draft => { ... })` | Mutator-style update. |
936
+ | `getStore(name, path?)` | Read current state (or nested path). |
937
+ | `deleteStore(name)` | Remove a store from registry. |
938
+ | `resetStore(name)` | Restore initial state. |
939
+ | `hasStore(name)` | Check if store exists. |
940
+ | `setStoreBatch(fn)` | Group synchronous writes into one transaction. |
941
+ | `hydrateStores(snapshot, options?, trust)` | Hydrate trusted snapshot into runtime. |
942
+ | `configureStroid(config)` | Configure global/runtime behavior. |
943
+ | `useStore(name, selectorOrPath?)` | React subscription hook. |
944
+ | `useSelector(name, fn, equality?)` | Fine-grained React selector hook. |
945
+ | `fetchStore(name, input, options?)` | Fetch remote data into store. |
946
+ | `createComputed(name, deps, fn)` | Define computed store. |
947
+ | `createStoreForRequest(fn)` | Build SSR request-scoped store runtime. |
97
948
 
98
949
  ---
99
950
 
100
- ## Module Import Map
951
+ ## ๐Ÿงญ Module Import Map
101
952
 
102
953
  ```ts
103
954
  // Core
104
- import { createStore, setStore, getStore, hasStore,
105
- deleteStore, resetStore, setStoreBatch, hydrateStores } from "stroid"
955
+ import {
956
+ createStore,
957
+ createStoreStrict,
958
+ setStore,
959
+ getStore,
960
+ hasStore,
961
+ deleteStore,
962
+ resetStore,
963
+ setStoreBatch,
964
+ hydrateStores,
965
+ configureStroid,
966
+ } from "stroid";
967
+
968
+ // Native PSR contract
969
+ import {
970
+ getStoreSnapshot,
971
+ getStoreSnapshotNoTrack,
972
+ subscribeStore,
973
+ applyStorePatch,
974
+ applyStorePatchesAtomic,
975
+ getRuntimeGraph,
976
+ getComputedDescriptor,
977
+ evaluateComputed,
978
+ getTimingContract,
979
+ } from "stroid/psr";
106
980
 
107
981
  // Minimal core (bundle-size-sensitive)
108
- import { createStore, setStore, getStore, hasStore,
109
- resetStore, deleteStore } from "stroid/core"
982
+ import { createStore, setStore, getStore, hasStore, resetStore, deleteStore } from "stroid/core";
110
983
 
111
984
  // React
112
- import { useStore, useSelector, useStoreField, useStoreStatic,
113
- useAsyncStore, useFormStore, useAsyncStoreSuspense,
114
- RegistryScope } from "stroid/react"
985
+ import {
986
+ useStore,
987
+ useSelector,
988
+ useStoreField,
989
+ useStoreStatic,
990
+ useAsyncStore,
991
+ useFormStore,
992
+ useAsyncStoreSuspense,
993
+ RegistryScope,
994
+ } from "stroid/react";
115
995
 
116
996
  // Async
117
- import { fetchStore, refetchStore, enableRevalidateOnFocus } from "stroid/async"
997
+ import { fetchStore, refetchStore, enableRevalidateOnFocus } from "stroid/async";
118
998
 
119
999
  // Selectors & Computed
120
- import { createSelector, subscribeWithSelector } from "stroid/selectors"
121
- import { createComputed, invalidateComputed,
122
- deleteComputed, isComputedStore } from "stroid/computed"
1000
+ import { createSelector, subscribeWithSelector } from "stroid/selectors";
1001
+ import { createComputed, invalidateComputed, deleteComputed, isComputedStore } from "stroid/computed";
123
1002
 
124
- // Features (side-effect imports โ€” register once at app entry)
125
- import "stroid/persist"
126
- import "stroid/sync"
127
- import "stroid/devtools"
1003
+ // Features (explicit install - call once at app entry)
1004
+ import { installPersist } from "stroid/persist";
1005
+ import { installSync } from "stroid/sync";
1006
+ import { installDevtools, getHistory, clearHistory } from "stroid/devtools";
128
1007
 
129
- // Note: stroid/persist and stroid/sync are side-effect entrypoints only.
130
- // All types live on the main "stroid" entry.
1008
+ installPersist();
1009
+ installSync();
1010
+ installDevtools();
131
1011
 
132
1012
  // Server / SSR
133
- import { createStoreForRequest } from "stroid/server"
1013
+ import { createStoreForRequest } from "stroid/server";
134
1014
 
135
1015
  // Helpers & Testing
136
- import { createEntityStore, createListStore, createCounterStore } from "stroid/helpers"
137
- import { createMockStore, resetAllStoresForTest,
138
- withMockedTime, benchmarkStoreSet } from "stroid/testing"
139
-
140
- // Runtime Observability
141
- import { listStores, getStoreMeta, getMetrics,
142
- getSubscriberCount, getStoreHealth, findColdStores,
143
- getComputedGraph, getComputedDeps,
144
- getPersistQueueDepth } from "stroid/runtime-tools"
145
- import { clearAllStores, clearStores } from "stroid/runtime-admin"
146
-
147
- // Devtools API (after `import "stroid/devtools"`)
148
- import { getHistory, clearHistory } from "stroid/devtools"
1016
+ import { createEntityStore, createListStore, createCounterStore } from "stroid/helpers";
1017
+ import { createMockStore, resetAllStoresForTest, withMockedTime, benchmarkStoreSet } from "stroid/testing";
149
1018
 
150
- // Config
151
- import { configureStroid, resetConfig,
152
- registerMutatorProduce } from "stroid"
1019
+ // Runtime Observability + Admin
1020
+ import {
1021
+ listStores,
1022
+ getStoreMeta,
1023
+ getMetrics,
1024
+ getSubscriberCount,
1025
+ getStoreHealth,
1026
+ findColdStores,
1027
+ getComputedGraph,
1028
+ getComputedDeps,
1029
+ getPersistQueueDepth,
1030
+ } from "stroid/runtime-tools";
1031
+ import { clearAllStores, clearStores } from "stroid/runtime-admin";
153
1032
 
154
1033
  // Feature plugin API
155
- import { registerStoreFeature,
156
- hasRegisteredStoreFeature,
157
- getRegisteredFeatureNames } from "stroid/feature"
1034
+ import { registerStoreFeature, hasRegisteredStoreFeature, getRegisteredFeatureNames } from "stroid/feature";
1035
+
1036
+ // Optional all-in-one installer
1037
+ import { installAllFeatures } from "stroid/install";
158
1038
  ```
159
1039
 
160
1040
  ---
161
1041
 
162
- ## Docs
1042
+ ## ๐Ÿงท Native PSR Contract
1043
+
1044
+ `stroid/psr` is the supported public surface for native PSR-style integration.
1045
+
1046
+ - Committed reads: `getStoreSnapshot()` and `getStoreSnapshotNoTrack()`
1047
+ - Committed-final observation: `subscribeStore()`
1048
+ - Serializable writes: `applyStorePatch()` and `applyStorePatchesAtomic()` with `set`, `merge`, `delete`, and `insert`
1049
+ - Runtime inspection: `getRuntimeGraph()`, `getComputedDescriptor()`, `evaluateComputed()`, and `getTimingContract()`
1050
+
1051
+ See [Native PSR Contract](./docs/STROID_PSR/INDEX.md) for full details.
1052
+
1053
+ ---
1054
+
1055
+ ## ๐Ÿ“˜ Docs
163
1056
 
164
1057
  Full documentation in [`/docs`](./docs/):
165
1058
 
166
- - [Architecture](./docs/architecture/ARCHITECTURE.md) โ€” layers, data flow, registry model
167
- - [Core Concepts](./docs/core-concepts/STORES.md) โ€” store lifecycle, options, write modes
168
- - [React Layer](./docs/guides/REACT.md) โ€” hooks, selectors, SSR
169
- - [Async Layer](./docs/guides/ASYNC.md) โ€” `fetchStore`, caching, revalidation
170
- - [Persistence](./docs/guides/PERSIST.md) โ€” `localStorage`, encryption, migrations
171
- - [Cross-tab Sync](./docs/guides/SYNC.md) โ€” `BroadcastChannel`, conflict resolution
172
- - [Computed Stores](./docs/guides/COMPUTED.md) โ€” reactive derived values
173
- - [Server & SSR](./docs/guides/SERVER.md) โ€” request-scoped stores, hydration
174
- - [Testing](./docs/guides/TESTING.md) โ€” mock stores, resets, benchmarks
175
- - [Devtools](./docs/guides/DEVTOOLS.md) โ€” history, redaction
176
- - [Runtime Tools](./docs/guides/RUNTIME_TOOLS.md) โ€” observability, health checks
177
- - [Full API Reference](./docs/api/API_REFERENCE.md)
1059
+ - [Architecture](./docs/STROID_ARCHITECTURE/AECHITECTURE.md) - layers, data flow, registry model
1060
+ - [Core Concepts](./docs/STROID_CORE/INDEX.md) - store lifecycle, options, write modes
1061
+ - [React Layer](./docs/STROID_REACT/INDEX.md) - hooks, selectors, SSR
1062
+ - [Async Layer](./docs/STROID_ASYNC/INDEX.md) - `fetchStore`, caching, revalidation
1063
+ - [Persistence](./docs/STROID_PERSIST/INDEX.md) - persist options, encryption, migrations
1064
+ - [Cross-tab Sync](./docs/STROID_SYNC/INDEX.md) - BroadcastChannel sync behavior
1065
+ - [Computed Stores](./docs/STROID_COMPUTED/INDEX.md) - reactive derived values
1066
+ - [Native PSR Contract](./docs/STROID_PSR/INDEX.md) - patch coverage, timing/governance, graph identity
1067
+ - [Server & SSR](./docs/STROID_SERVER/INDEX.md) - request-scoped stores, hydration
1068
+ - [Testing](./docs/STROID_TESTING/INDEX.md) - mock stores, resets, benchmarks
1069
+ - [Runtime Tools](./docs/STROID_RUNTIME_TOOLS/INDEX.md) - observability, health checks
1070
+ - [TypeScript Guide](./docs/STROID_TYPESCRIPT/INDEX.md)
1071
+ - [Full API Reference](./docs/api/stroid.api.md)
178
1072
  - [Project Status](./STATUS.MD)
179
1073
  - [Contributing](./CONTRIBUTING.md)
180
1074
 
181
1075
  ---
182
1076
 
183
- ## Changelog & License
1077
+ ## ๐Ÿ“ Changelog & License
184
1078
 
185
1079
  - [CHANGELOG](./CHANGELOG.md)
186
1080
  - [MIT License](./LICENSE)
187
1081
  - [Issues](https://github.com/Himesh-Bhattarai/stroid/issues)
188
1082
 
1083
+
1084
+ <div align="center">
1085
+
1086
+ **Made with care for developers who think about state seriously.**
1087
+
1088
+ [โญ 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)
1089
+
1090
+ </div>