stroid 0.1.1 → 0.1.3

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 (112) hide show
  1. package/CHANGELOG.md +235 -119
  2. package/README.md +104 -431
  3. package/dist/async.d.ts +42 -9
  4. package/dist/async.js +26 -26
  5. package/dist/async.js.map +1 -1
  6. package/dist/cache.d.ts +12 -0
  7. package/dist/computed.d.ts +46 -7
  8. package/dist/computed.js +11 -11
  9. package/dist/computed.js.map +1 -1
  10. package/dist/core.d.ts +5 -15
  11. package/dist/core.js +14 -15
  12. package/dist/core.js.map +1 -1
  13. package/dist/devtools.d.ts +30 -5
  14. package/dist/devtools.js +1 -1
  15. package/dist/devtools.js.map +1 -1
  16. package/dist/feature.d.ts +92 -14
  17. package/dist/feature.js +1 -1
  18. package/dist/feature.js.map +1 -1
  19. package/dist/helpers.d.ts +37 -3
  20. package/dist/helpers.js +14 -15
  21. package/dist/helpers.js.map +1 -1
  22. package/dist/index-internal.d.ts +44 -0
  23. package/dist/index.d.cts +170 -33
  24. package/dist/index.d.ts +170 -33
  25. package/dist/index.js +24 -23
  26. package/dist/index.js.map +1 -1
  27. package/dist/install.d.ts +6 -4
  28. package/dist/install.js +1 -1
  29. package/dist/install.js.map +1 -1
  30. package/dist/options.d.ts +295 -0
  31. package/dist/persist.d.ts +1 -1
  32. package/dist/persist.js +1 -1
  33. package/dist/persist.js.map +1 -1
  34. package/dist/react/index.d.ts +70 -0
  35. package/dist/react/index.js +38 -0
  36. package/dist/react/index.js.map +1 -0
  37. package/dist/registry.d.ts +117 -0
  38. package/dist/runtime-admin.d.ts +4 -2
  39. package/dist/runtime-admin.js +1 -1
  40. package/dist/runtime-admin.js.map +1 -1
  41. package/dist/runtime-tools.d.ts +66 -9
  42. package/dist/runtime-tools.js +2 -2
  43. package/dist/runtime-tools.js.map +1 -1
  44. package/dist/selectors.d.ts +4 -2
  45. package/dist/selectors.js +1 -1
  46. package/dist/selectors.js.map +1 -1
  47. package/dist/server.d.ts +30 -2
  48. package/dist/server.js +11 -10
  49. package/dist/server.js.map +1 -1
  50. package/dist/store-registry.d.ts +79 -0
  51. package/dist/sync.d.ts +1 -1
  52. package/dist/sync.js +1 -1
  53. package/dist/sync.js.map +1 -1
  54. package/dist/testing.d.ts +16 -4
  55. package/dist/testing.js +14 -15
  56. package/dist/testing.js.map +1 -1
  57. package/dist/tsdoc-metadata.json +11 -0
  58. package/dist/types.d.ts +65 -0
  59. package/dist/utility.d.ts +15 -0
  60. package/package.json +29 -11
  61. package/dist/_tsup-dts-rollup.d.cts +0 -2411
  62. package/dist/_tsup-dts-rollup.d.ts +0 -2411
  63. package/dist/async.cjs +0 -34
  64. package/dist/async.cjs.map +0 -1
  65. package/dist/async.d.cts +0 -9
  66. package/dist/computed.cjs +0 -13
  67. package/dist/computed.cjs.map +0 -1
  68. package/dist/computed.d.cts +0 -7
  69. package/dist/core.cjs +0 -24
  70. package/dist/core.cjs.map +0 -1
  71. package/dist/core.d.cts +0 -15
  72. package/dist/devtools.cjs +0 -2
  73. package/dist/devtools.cjs.map +0 -1
  74. package/dist/devtools.d.cts +0 -5
  75. package/dist/feature.cjs +0 -2
  76. package/dist/feature.cjs.map +0 -1
  77. package/dist/feature.d.cts +0 -14
  78. package/dist/helpers.cjs +0 -24
  79. package/dist/helpers.cjs.map +0 -1
  80. package/dist/helpers.d.cts +0 -3
  81. package/dist/index.cjs +0 -35
  82. package/dist/index.cjs.map +0 -1
  83. package/dist/install.cjs +0 -2
  84. package/dist/install.cjs.map +0 -1
  85. package/dist/install.d.cts +0 -4
  86. package/dist/persist.cjs +0 -2
  87. package/dist/persist.cjs.map +0 -1
  88. package/dist/persist.d.cts +0 -1
  89. package/dist/react.cjs +0 -36
  90. package/dist/react.cjs.map +0 -1
  91. package/dist/react.d.cts +0 -7
  92. package/dist/react.d.ts +0 -7
  93. package/dist/react.js +0 -36
  94. package/dist/react.js.map +0 -1
  95. package/dist/runtime-admin.cjs +0 -2
  96. package/dist/runtime-admin.cjs.map +0 -1
  97. package/dist/runtime-admin.d.cts +0 -2
  98. package/dist/runtime-tools.cjs +0 -4
  99. package/dist/runtime-tools.cjs.map +0 -1
  100. package/dist/runtime-tools.d.cts +0 -9
  101. package/dist/selectors.cjs +0 -2
  102. package/dist/selectors.cjs.map +0 -1
  103. package/dist/selectors.d.cts +0 -2
  104. package/dist/server.cjs +0 -12
  105. package/dist/server.cjs.map +0 -1
  106. package/dist/server.d.cts +0 -2
  107. package/dist/sync.cjs +0 -2
  108. package/dist/sync.cjs.map +0 -1
  109. package/dist/sync.d.cts +0 -1
  110. package/dist/testing.cjs +0 -24
  111. package/dist/testing.cjs.map +0 -1
  112. package/dist/testing.d.cts +0 -4
package/CHANGELOG.md CHANGED
@@ -1,163 +1,279 @@
1
1
  # Changelog
2
2
 
3
- All notable changes to this project will be documented in this file.
3
+ All notable changes to this project are documented in this file.
4
+ Format: [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
5
+ Versioning: [Semantic Versioning](https://semver.org/).
6
+
7
+ ---
8
+ <details open>
9
+ <summary><strong>Unreleased</strong></summary>
10
+
11
+ - No unreleased changes yet.
12
+
13
+ </details>
14
+
15
+ ---
16
+
17
+ <details open>
18
+ <summary><strong>v0.1.3 — 2026-03-22</strong></summary>
19
+
20
+ - Fixed async rate limiting so `fetchStore(..., { cacheKey })` is throttled per `cacheSlot` instead of incorrectly sharing one counter across the whole store name.
21
+ - Fixed `createSelector` dependency tracking for object-valued reads so cached selector results no longer go stale when object references change without primitive leaf access.
22
+ - Fixed `setStoreBatch` teardown so a later commit-phase feature error does not discard notifications that were already queued by earlier successful commits.
23
+ - Fixed persist unload listeners so deleting and recreating a persisted store no longer accumulates stale `pagehide` / `beforeunload` flush handlers.
24
+ - Fixed sync-applied remote state so feature write hooks still run, allowing `persist` and other write-driven features to observe synced updates.
25
+ - Fixed `clearAllStores()` under `assertRuntime: true` so a successful clear logs normally instead of throwing from the success path.
26
+ - Fixed sync checksum handling so incoming sync payloads are now verified before remote state is accepted.
27
+ - Fixed async request defaults so bodyless `GET` / `HEAD` / `DELETE` requests no longer send `Content-Type: application/json`.
28
+ - Fixed `createComputed(..., { autoDispose: true })` so computed stores are removed after their last dependency is deleted.
29
+ - Fixed `resetStore()` for falsy initial values (`false`, `0`, `""`, `null`) so registered stores no longer report `not-found` during reset.
30
+ - Replaced the default registry scope's `import.meta.url`-based identifier with a stable bundler-safe string to avoid webpack / Next.js resolution failures.
31
+ - Hardened SSR write-context isolation by routing `runWithWriteContext(...)` through the server AsyncLocalStorage runner instead of relying only on a module-level fallback context.
32
+ - Hardened inline notification delivery to snapshot the subscriber list per flush instead of reusing a shared registry buffer.
33
+ - Tightened React hook type coverage for ambient `StoreStateMap` usage, including `useStore`, `useStoreField`, `useStoreStatic`, `useSelector`, `useFormStore`, `useAsyncStore`, and `useAsyncStoreSuspense`.
34
+ - Clarified React selector recreation warnings and docs so they describe selector churn and cache reuse accurately instead of implying repeated re-subscriptions.
35
+ - Upgraded the transitive `flatted` resolution to `3.4.2` via `npm overrides` to address the Dependabot alert in the eslint / flat-cache toolchain path.
36
+
37
+ </details>
38
+
39
+ ---
40
+
41
+
42
+ <details>
43
+ <summary><strong>v0.1.2 — 2026-03-19</strong></summary>
44
+ > **Note:** This release contains breaking changes to the `stroid/core` export surface and hydration defaults to improve bundle size and security.
45
+
46
+ - `hydrateStores` now requires an explicit trust argument at the TypeScript level (compile-time enforcement).
47
+ - Default snapshot mode changed to `"shallow"` (was `"deep"`). Override per-store with `snapshot: "deep"` or globally with `configureStroid({ defaultSnapshotMode: "deep" })`.
48
+
49
+ ### Migration
50
+
51
+ - If you use `stroid/core` for batching, reset, or hydration — move those imports to `stroid`.
52
+ - If you call `hydrateStores` without a trust argument — add `{ allowTrusted: true }` as the third argument.
53
+ - If your app relies on deep-clone snapshot semantics — add `snapshot: "deep"` to affected stores or set `configureStroid({ defaultSnapshotMode: "deep" })`.
54
+
55
+ ### Performance
56
+
57
+ - Hot-path proxy avoidance: `deliverFlush` now captures direct registry references once and reuses them during the flush loop.
58
+ - `Array.from` elimination: replaced per-flush subscriber array allocations with a registry-level reusable buffer.
59
+ - `buildFlushPlan` collapse: reduced passes, preserved `pendingBuffer` semantics, and removed the terminal `orderedNames.slice()` allocation.
60
+
61
+ ### Added
62
+
63
+ - `allowTrusted` hydration flag (aliasing `allowHydration`; `allowUntrusted` deprecated).
64
+ - `allowTrustedHydration` config alias.
65
+ - `sync.loopGuard` option to suppress immediate rebroadcasts after an incoming sync update.
66
+ - `registerMutatorProduce` helper for safely registering Immer (or other mutator engines).
67
+ - `selectorCloneFrozen` config flag to control frozen-state cloning in `createSelector` (dev performance toggle).
68
+ - `createStoreForRequest` now exposes the request `registry` for `RegistryScope` or advanced SSR usage.
69
+ - `stroid/server` now re-exports the `StoreRegistry` type for SSR typing.
70
+ - Store metrics now include reset timing (`resetCount`, `totalResetMs`, `lastResetMs`).
71
+ - API Extractor configuration and `docs:api` script for generating typed API reports.
72
+ - `IStoreCore` shared interface and `store-core` adapter for layer boundaries.
73
+ - ESLint layer guards for async-cache and store-notify imports.
74
+ - Optional TypeScript layer configs (`tsconfig.layers.json`) for build-time dependency checks.
75
+ - `sync.insecure` option to explicitly allow unauthenticated sync in production.
76
+ - `onValidationError` hook for hydrate trust validation failures.
77
+ - `acknowledgeLooseTypes` config flag to silence the loose-type dev warning.
78
+ - `pathCacheSize` config to tune per-store path validation cache limits.
79
+ - `HydrateSnapshotFor<Map>` helper type for stricter hydration typing.
80
+ - Internal lifecycle hook hub for decoupled cross-layer events.
81
+ - Lazy store lifecycle helpers: `isLazyStore`, `isLazyPending`, `isStoreMaterialized`.
82
+ - `autoCorrelationIds` config and `fetchStore` correlation/trace context propagation.
83
+ - `getStoreHealth()` unified observability helper for per-store and global metrics.
84
+ - `findColdStores()` to surface cold/stale/write-only stores.
85
+ - Root exports for `getMetrics` and `getAsyncMetrics` for discoverability.
86
+ - Reserved `stroid/vue` and `stroid/svelte` entry points (adapter placeholders, not implemented).
87
+ - `onStoreLifecycle` registry hook for single-listener lifecycle events (devtools-oriented).
88
+
89
+ ### Changed
90
+
91
+ - `createStoreForRequest` now hydrates with `{ allowTrusted: true }`.
92
+ - `getStore` now respects `snapshot` mode (`deep`/`shallow`/`ref`) for both whole-store and path reads.
93
+ - `setStore` TypeScript overloads consolidated to reduce IntelliSense noise.
94
+ - Lazy store typings now require `lazy: true` when initial data is a function.
95
+ - Sync loop guard is enabled by default (opt out with `sync: { loopGuard: false }`).
96
+ - Unauthenticated sync is blocked in production unless `authToken`, `verify`, or `insecure` is provided.
97
+ - `hydrateStores` throws in dev when `trust.validate` throws; routes via `onError` in production.
98
+ - `hydrateStores` returns structured `failed` entries with `blocked` reasons.
99
+ - `mutatorProduce: "immer"` now uses `registerMutatorProduce`.
100
+ - `useStore` warns once in dev when store names are untyped.
101
+ - `useStore` broad-subscription warnings now surface outside dev (once per store).
102
+ - `snapshot: "shallow"` now dev-freezes the top-level snapshot.
103
+ - Notification pipeline split into `notification/*` modules.
104
+ - Async cache cleanup hooks now register through lifecycle hooks.
105
+ - `resetStore` reports `lazy-uninitialized` when called before materialization.
106
+ - `setStoreBatch` throws in production SSR on the global registry (requires request scope).
107
+ - Store metadata now tracks read counts and last-read timestamps.
108
+ - Middleware contexts include optional `correlationId`/`traceContext`.
109
+ - React hooks live exclusively under `stroid/react`.
110
+ - `deepClone` throws on non-cloneable values.
111
+ - `endTransaction` now executes all pending commit callbacks, capturing the first error while allowing remaining commits to run.
112
+
113
+ ### Fixed
114
+
115
+ - Helper store typings align with stricter `createStore` overloads.
116
+ - `replaceStore` now participates in `setStoreBatch` transactions.
117
+ - Removed dead `runInline` logic from the chunked notify queue.
118
+ - Selector reads in request scope no longer leak through the default registry.
119
+ - React hooks now resolve the active request registry when `RegistryScope` is omitted during SSR hydration.
120
+ - Chunked flush now snapshots subscribers per task to avoid mid-flush corruption.
121
+ - `injectTransactionRunner` ignores unsafe reinjection attempts.
122
+ - `endTransaction` surfaces commit-phase errors.
123
+ - Persist writes re-check the latest sequence before `setItem`.
124
+ - `fetchStore` sets an error state when `transform` returns a Promise.
125
+ - Async rate limiting is enforced per store (not per cache slot).
126
+ - `hydrateStores` recomputes affected computed stores after hydration.
127
+ - User `onError` callbacks are now isolated from core operations if they throw.
128
+
129
+ ### Docs
130
+
131
+ - Hydration examples now reference `allowTrusted` language.
132
+ - Sync options documentation now includes `loopGuard`.
133
+ - README now documents `registerMutatorProduce`, `sync.insecure`, and `onValidationError`.
134
+ - React SSR docs now mention `stores.registry` and the automatic request-registry fallback.
135
+
136
+ </details>
137
+
138
+ ---
139
+
140
+ <details>
141
+ <summary><strong>0.1.1 — 2026-03-15</strong></summary>
4
142
 
5
- ## 0.1.1 - 2026-03-15
6
143
  ### Breaking
144
+
7
145
  - `stroid/core` now exports only `createStore`, `setStore`, `getStore`, and `deleteStore` (minimal primitives).
8
146
 
9
147
  ### Migration
10
- - If you relied on `stroid/core` for batching, reset, hydration, or other core APIs, import them from `stroid` instead.
11
148
 
149
+ - If you used `stroid/core` for batching, reset, or hydration — import those from `stroid` instead.
12
150
 
13
151
  ### Added
14
- - Public feature installer entrypoints and a features option bag for custom feature registration.
152
+
153
+ - Public feature installer entrypoints and a `features` option bag for custom feature registration.
15
154
  - Optional structural sharing via `configureStroid({ mutatorProduce })` (supports a global Immer shim).
16
155
  - `strictAsyncUsageErrors` to throw on async usage errors when enabled.
17
156
 
18
157
  ### Changed
158
+
19
159
  - SSR request APIs are now fully typed; `snapshotStrategy` drives the default snapshot mode.
20
160
  - Config is registry-scoped to avoid cross-request bleed in SSR.
21
- - Transaction snapshot caching is scoped to the active batch to reduce repeated cloning.
22
- - Internal layering tightened without runtime behavior changes; added a guard against restricted lifecycle imports.
161
+ - Transaction snapshot caching scoped to the active batch.
162
+ - Internal layering tightened; added guard against restricted lifecycle imports.
23
163
 
24
164
  ### Fixed
165
+
25
166
  - Chunked flush delivery no longer mixes snapshots within a single notification.
26
167
  - Persist sequencing avoids stale writes when debounce timers overlap.
27
168
  - Notification queues and batch depth are registry-scoped for SSR safety.
28
- - DTS build now succeeds with a type-safe internal cast for SSR options merges.
169
+ - DTS build succeeds with a type-safe internal cast for SSR options merges.
29
170
  - `useStore` missing-store warning moved to render time for immediate feedback.
30
- - Sync warns when authentication is missing or sign is configured without verify.
171
+ - Sync warns when authentication is missing or `sign` is configured without `verify`.
31
172
 
32
- ### Docs
33
- - Standardized file header JSDoc and polished README guidance.
173
+ </details>
34
174
 
35
- ### Testing
36
- - Expanded regression coverage across SSR, features, persist, and sync; coverage thresholds now pass.
175
+ ---
176
+
177
+ <details>
178
+ <summary><strong>0.1.0 — 2026-03-14</strong></summary>
37
179
 
38
- ## 0.1.0 - 2026-03-14
39
180
  ### Added
40
- - `configureStroid({ strictMissingFeatures: true })` option to hard-fail when a feature is requested without its side-effect registration import.
41
- - `configureStroid({ allowUntrustedHydration: true })` to opt in to hydrateStores on untrusted snapshots.
42
- - `configureStroid({ mutatorProduce })` to plug in a structural-sharing mutator engine (e.g. Immer).
43
- - `getSubscriberCount`, `getAsyncInflightCount`, and `getPersistQueueDepth` observability helpers in `runtime-tools`.
44
- - `configureStroid({ assertRuntime: true })` option to throw on warnings/errors for test-time assertions.
181
+
182
+ - `configureStroid({ strictMissingFeatures: true })` to hard-fail when a feature is used without its side-effect import.
183
+ - `configureStroid({ allowUntrustedHydration: true })` to opt in to `hydrateStores` on untrusted snapshots.
184
+ - `configureStroid({ mutatorProduce })` to plug in a structural-sharing mutator engine.
185
+ - `getSubscriberCount`, `getAsyncInflightCount`, `getPersistQueueDepth` observability helpers.
186
+ - `configureStroid({ assertRuntime: true })` to throw on warnings/errors.
45
187
  - `createComputed(...)` for reactive derived stores.
46
- - `getComputedGraph()` and `getComputedDeps()` diagnostics in `runtime-tools`.
188
+ - `getComputedGraph()` and `getComputedDeps()` diagnostics.
47
189
  - `configureStroid({ strictMutatorReturns: true })` to forbid mutator return values.
48
- - `useStore`/`useSelector` now warn once when a store is missing (including SSR renders).
49
- - `StrictStoreMap` opt-in type mode for compile-time enforcement of known store names.
190
+ - `StrictStoreMap` opt-in type mode.
50
191
 
51
- ### Changed
52
- - Runtime now always surfaces missing feature registrations via warnings (even in production), and can throw when `strictMissingFeatures` is enabled.
53
- - Default `Path<T>` inference depth increased to 10; use `PathDepth<T, N>` for deeper paths.
54
- - Removed `mergeStore` and `chain` from the public API; use `setStore(name, partial)` and mutator updates instead.
55
- - `setStoreBatch` is now transactional: batched writes are staged and only committed if the batch completes successfully. `createStore`, `deleteStore`, and `hydrateStores` are disallowed inside a batch.
56
- - `setStoreBatch` now warns and no-ops when called with a non-function instead of throwing synchronously.
57
- - `resetStore` and `deleteStore` now accept `StoreKey`/`StoreDefinition` handles in addition to string names.
58
- - `useStore` overloads now return non-nullable values when called with `StoreKey`/`StoreDefinition` handles.
59
- - Persist internals split into `features/persist/*` (crypto/load/save/watch/types) to keep responsibilities isolated.
60
- - `fetchStore` now warns in dev when it auto-creates a missing store (to surface typos early).
61
- - `fetchStore` now refuses to overwrite non-async store shapes unless a `stateAdapter` is provided.
62
- - `fetchStore` now hard-fails when the per-store inflight slot limit is exceeded (throws instead of returning `null`).
63
- - Selector cache logic in React hooks is shared between `useStore` and `useSelector` to avoid duplicate implementations and ensure consistent selector identity checks.
64
- - Feature hook context creation now avoids full object spread copies on every write/delete to reduce overhead.
65
- - Path validation cache is capped per-store (no global cache thrash); per-store cache entries are cleared on store invalidation/reset.
66
- - Feature runtimes now initialize on registration/bind, removing redundant per-write initialization checks.
67
- - `useAsyncStoreSuspense` now triggers/awaits async fetches and reuses inflight promises for React Suspense integration.
68
- - Mutator-based `setStore` now honors non-undefined return values to replace draft updates.
69
- - Mutator-based `setStore` now warns in dev when a mutator returns a value, since return values replace the entire store.
70
- - `hydrateStores` now requires explicit trust via the third argument or `configureStroid({ allowUntrustedHydration: true })` (breaking for implicit hydration).
71
- - Persist now supports async crypto hooks (`encryptAsync`/`decryptAsync`) and `checksum: "sha256"` for stronger integrity checks.
72
- - `sanitize` now rejects non-serializable host objects (WeakRef/EventTarget/streams) earlier instead of letting clone fallbacks fail later.
192
+ ### Breaking Changes
193
+
194
+ - Removed `mergeStore` and `chain` from the public API.
195
+ - `setStoreBatch` is now transactional (staged writes, atomic commit, rollback on error).
196
+ - `createStore`, `deleteStore`, `hydrateStores` are disallowed inside a batch.
197
+ - `hydrateStores` requires explicit trust via third argument or config.
73
198
 
74
199
  ### Fixed
75
- - `deleteStore` no longer emits an intermediate null notification before deletion, preventing double-render transitions.
76
- - Async fetch 60s timeout now clears on completion to avoid late error handling after a successful request.
77
- - Async rate limiter metadata now clears on store deletion to prevent leakage across request scopes.
78
- - Subscriber storage uses `Set` consistently across `subscribeStore` and `subscribeWithSelector`, preventing type mismatches.
200
+
201
+ - `deleteStore` no longer emits an intermediate null notification.
202
+ - Async fetch 60s timeout now clears on completion.
79
203
  - `clearAllStores` now removes stores created during delete hooks.
80
- - SSR registry isolation now uses AsyncLocalStorage-backed registries to prevent concurrent request scope leakage.
81
- - Registry bindings no longer go stale after scope rebinds; registry exports proxy to the active scope (SSR safe).
82
- - Store names now reject `__proto__`, `constructor`, and `prototype`, and `hydrateStores` skips invalid names to prevent registry pollution.
83
- - Persist now validates encrypt/decrypt round-trips and disables persistence when crypto hooks are misconfigured.
84
- - `setStore` returns typed `WriteResult` objects without casting.
85
- - `subscribeWithSelector` now uses store snapshots so selectors never receive mutable live references.
86
- - `deepClone` fallback now preserves Dates consistently (no JSON stringify fallback).
87
- - `hashState` now handles circular structures and uses a stronger 53-bit hash for non-string inputs while preserving legacy checksums for strings.
88
- - Chunked notification delivery now defers remaining subscribers if the store updates mid-flush, avoiding mixed snapshots in a single delivery.
89
- - Chunked notification delivery now includes subscribers added mid-flush in the same notification cycle.
90
- - `_hardResetAllStoresForTest` is no longer exported from the main package entry; it remains in `stroid/testing`.
91
- - Async rate limiter now initializes per-slot windows and prunes stale metadata to avoid unbounded growth.
92
- - Computed cleanup registrations are now scoped to the active registry, preventing cross-request leaks in SSR.
93
- - Store delete hooks now iterate the registered feature set (including third-party features).
94
- - Computed creation logs now use the configured `logSink` instead of raw `console.log`.
95
- - Async fetch usage errors now route through the configured `logSink.critical` in production.
96
- - `useAsyncStoreSuspense` no longer allocates a new default options object each render, stabilizing memoization.
204
+ - SSR registry isolation uses `AsyncLocalStorage`-backed registries.
205
+ - Store names reject `__proto__`, `constructor`, `prototype`.
97
206
 
98
- ### Docs
99
- - `subscribeWithSelector` now documents `prev` semantics for batched writes.
100
-
101
- ### Testing
102
- - `patch0/test` completed the `P0` stabilization pass for core state safety and production failure handling.
103
- - Core testing now covers immutable reads/snapshots/history, guarded validator and lifecycle failures, delete/persist races, reset persistence, sanitize rejection for hostile payloads, SSR async fail-fast behavior, hydration replacement semantics, and stale sync messages after delete.
104
- - `patch1/testing` extends the stabilization pass across selector correctness, dotted-key path handling, retry/caching guardrails, environment defaults, and sync payload consistency.
105
- - Patch1 testing now covers re-entrant notify delivery, selector subscription false positives, dependency-aware selector memoization, escaped dotted keys and dotted entity IDs, bounded retry/cache behavior, production fallback env resolution, and canonical sync payloads under redaction.
106
- - `remain` continues the draft-issue hardening pass across persist initialization ordering, pollution-safe sanitization, deep-clone fallback safety, request-scope contract enforcement, promise retry semantics, synchronous batch guarantees, and fallback entity ID uniqueness.
107
- - Testing now also covers persisted init load precedence, forbidden prototype keys, forced `deepClone` fallback behavior, request-scope unknown-store failures, promise-input retry bypass, async batch rejection, and fixed-clock fallback entity inserts.
108
- - `debugging/bug` closes the remaining pre-push runtime gaps across React inline selector stability, async stale-request ordering, middleware veto semantics, clone fallback safety, and deep-freeze resilience.
109
- - Testing now also includes mounted React hook runtime coverage for `useStore()` inline selectors, alongside the branch’s new regressions for stale async ordering, middleware vetoes, exact selector fallback matching, and cycle-safe deep freeze.
110
- - CI test scripts now run directory-based Node tests and type tests build dist before type-checking package declarations.
111
- - React Suspense coverage added for `useAsyncStoreSuspense`, including stable memoization under rerender.
112
- - SSR carrier test now asserts the global store remains unpolluted after concurrent requests.
207
+ </details>
113
208
 
114
- ### Changed
115
- - `v0.0.5` is now the active development branch. `main` stays locked on the released `0.0.4` line until the next release is cut.
116
- - Release artifacts remain release-managed on this branch: `dist/` may be absent here or still reflect the last released `0.0.4` build while current source/docs continue to move forward.
209
+ ---
210
+
211
+ <details>
212
+ <summary><strong>0.0.4 — 2026-03-06</strong></summary>
117
213
 
118
- ## 0.0.4 - 2026-03-06
119
214
  ### Added
215
+
120
216
  - Persistence recovery hooks: `persist.onMigrationFail` and `persist.onStorageCleared`.
121
- - Sync hardening options and behaviors: `sync.maxPayloadBytes` plus snapshot requests for reconnecting tabs.
217
+ - Sync hardening: `sync.maxPayloadBytes` and snapshot requests for reconnecting tabs.
218
+
122
219
  ### Changed
123
- - Docs: converted the repo docs into the chapter-based handbook, then aligned README and API chapters with the real package surface so examples now use `setStore(name, path, value)`, `getStore(name, path)`, `useStore(name, path)`, `subscribeWithSelector(name, selector, equalityFn, listener)`, and `useFormStore(name, field)`.
124
- - Packaging: rebuilt `dist` from the current `src`, and fixed the `stroid/react` build entry so the published subpath exports `useAsyncStore` and `useFormStore` consistently with the root package and docs.
220
+
221
+ - Docs: converted repo docs into chapter-based handbook; aligned README and API chapters with real package surface.
222
+ - Packaging: rebuilt `dist` from current `src`; fixed `stroid/react` build entry.
223
+
125
224
  ### Fixed
126
- - `hydrateStores` now rejects invalid schema payloads without leaving broken store shells behind.
225
+
226
+ - `hydrateStores` rejects invalid schema payloads without leaving broken store shells.
127
227
  - Middleware throws no longer poison later notifications.
128
- - Critical persistence failures in production now surface through `onError`.
129
- - Async lifecycle cleanup is hardened: inflight metadata clears on store deletion, lifecycle-owned requests abort on delete, and internal cleanup registrations are removed correctly.
130
- - Persisted version/schema mismatches can recover through `onMigrationFail`, and cleared storage keys can be detected through `onStorageCleared`.
131
- - Sync now reports unavailable `BroadcastChannel` transport, rejects oversized payloads safely, orders conflicts with monotonic clocks, and requests fresh snapshots on reconnect/focus/online.
228
+ - Async lifecycle cleanup hardened (inflight metadata clears on store deletion).
229
+
230
+ </details>
231
+
232
+ ---
233
+
234
+ <details>
235
+ <summary><strong>0.0.3 — 2026-03-04</strong></summary>
132
236
 
133
- ## 0.0.3 - 2026-03-04
134
237
  ### Fixed
135
- - Persistence now catches `localStorage.setItem` / driver `setItem` errors (e.g., `QuotaExceededError`) and routes them to `onError` instead of letting them bubble and crash. State updates still apply while persistence failures surface to the app.
136
- - Async fetch metadata (inflight, cache, registry) now cleans up when a store is deleted, avoiding stale entries and refetch surprises.
137
- - `enableRevalidateOnFocus` now removes its focus/online listeners when the store is deleted, preventing event-listener leaks.
138
- - React `useSelector` now memoizes selected values with shallow equality, preventing endless re-renders when selectors return new array/object references for unchanged data.
139
- - Store schemas are now enforced on write (`setStore`), blocking invalid shapes at runtime instead of silently accepting them.
140
- - `createStore` no longer overwrites an existing store name; it warns and keeps the original state.
141
- - `setStore` path updates now respect existing structure: array paths no longer auto-create missing indices and array shapes are preserved instead of converting to objects.
142
- - Docs: README updated with the pre-v1 bundle-size promise so the published package README matches the repo.
143
-
144
- ## 0.0.2 - 2026-03-03
238
+
239
+ - Persistence catches `localStorage.setItem` errors (e.g., `QuotaExceededError`) and routes to `onError`.
240
+ - Async fetch metadata cleans up when a store is deleted.
241
+ - `enableRevalidateOnFocus` removes focus/online listeners when the store is deleted.
242
+ - `useSelector` memoizes with shallow equality, preventing endless re-renders.
243
+ - Store schemas now enforced on write (`setStore`).
244
+ - `createStore` no longer overwrites an existing store name.
245
+ - `setStore` path updates preserve array shapes instead of converting to objects.
246
+
247
+ </details>
248
+
249
+ ---
250
+
251
+ <details>
252
+ <summary><strong>0.0.2 — 2026-03-03</strong></summary>
253
+
145
254
  ### Added
146
- - SSR helpers: `createStoreForRequest` and `hydrateStores` for request-scoped stores and snapshot hydration.
147
- - Store helpers: `createEntityStore`, `createListStore`, and `createCounterStore` for common patterns.
148
- - Observability: `getHistory`/`clearHistory` (with `historyLimit`) and `getMetrics` for notify timing.
149
- - Sync tuning: optional `channel` and `conflictResolver`; warnings when BroadcastChannel is unavailable.
150
- - Branding & DX: new logo/favicons, Next.js docs site with theme switcher, compact prev/next pager, robots.txt + sitemap + OG/Twitter metadata for SEO.
151
- ### Changed
152
- - Docs now reflect actual APIs (persist driver/serialize/encrypt; top-level version/migrations; DevTools boolean + historyLimit).
255
+
256
+ - SSR helpers: `createStoreForRequest` and `hydrateStores`.
257
+ - Store helpers: `createEntityStore`, `createListStore`, `createCounterStore`.
258
+ - Observability: `getHistory`, `clearHistory`, `getMetrics`.
259
+ - Sync tuning: optional `channel` and `conflictResolver`.
260
+
153
261
  ### Fixed
154
- - Hydration safety around theme toggles to prevent client/server mismatch warnings.
155
-
156
- ## 0.0.1
157
- - Initial release: tsup-minified ESM bundles with subpath outputs; shared chunk noted; CJS omitted.
158
- - Packaging: `sideEffects: false`, subpath exports (`./react`, `./async`, `./testing`), React peer dependency `>=18`.
159
- - DX: `useStore` selector overload with dev warning on broad subscriptions; hooks split into core/async/form modules; usage docs with quick start, gotchas, limitations.
160
- - Async: focus/online revalidation helper; dev warning when no AbortSignal is provided.
161
- - Safety: path/type guard warnings dev-only; persist key collision warning; circular-friendly `produceClone` error message; Map/Set/Date warnings.
162
- - Utils: CRC table lazy init.
163
- - Docs: testing subpath guidance, LWW clock-skew note, semver policy.
262
+
263
+ - Hydration safety around theme toggles.
264
+
265
+ </details>
266
+
267
+ ---
268
+
269
+ <details>
270
+ <summary><strong>0.0.1 Initial Release</strong></summary>
271
+
272
+ - tsup-minified ESM bundles with subpath outputs.
273
+ - `useStore` selector overload with dev warning on broad subscriptions.
274
+ - Hooks split into core/async/form modules.
275
+ - Async focus/online revalidation helper.
276
+ - Safety: path/type guard warnings, persist key collision warning.
277
+ - CRC table lazy init.
278
+
279
+ </details>