@reforgium/statum 3.0.1 → 3.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,218 @@
1
+ ## [3.1.1]: 2026-04-04
2
+
3
+ ### Refactor:
4
+ - Moved `Serializer` core into `@reforgium/internal`; `statum` now keeps serializer presets and public wrappers while reusing the shared codec engine underneath.
5
+ - Moved low-level storage implementations and `storageStrategy(...)` into `@reforgium/internal`; `statum` cache exports now act as compatibility wrappers over the shared foundation layer.
6
+
7
+ ### Fix:
8
+ - Package build and workspace resolution were aligned with hidden `@reforgium/internal` usage.
9
+ - `PagedQueryStore` transport generic ordering was corrected for package build stability.
10
+
11
+ ### Docs:
12
+ - `README` now reflects `storageStrategy(...)` naming and clarifies that serializer/storage core are shared through `@reforgium/internal`.
13
+
14
+ ---
15
+
16
+ ## [3.1.0]: 2026-04-01
17
+
18
+ ### Feat:
19
+ - `ResourceStore`: added `observe` option on per-call config; set `observe: 'response'` to pass the full `HttpResponse<T>` to `parseResponse` instead of just the body
20
+ - `ResourceStore`: added request-body pass-through for `FormData`, `Blob`, and `ArrayBuffer`
21
+ - `ResourceStore`: added optional retry jitter (`+-25%`) on top of constant/exponential backoff
22
+
23
+ ### Refactor:
24
+ - `PagedQueryStore`: removed `@deprecated` annotations from direct state setters (`page`, `pageSize`, `filters`, `query`, `totalElements`); setters remain available for low-level integration scenarios
25
+
26
+ ### Fix:
27
+ - `ResourceStore`: aligned query generics with actual transport behavior; query args now support booleans and arrays without reusing payload constraints
28
+ - `ResourceStore`: GET cache lookups now refresh LRU order, while `cache-only` misses no longer create empty cache entries
29
+ - `ResourceStore`: abort and abortAll now cancel underlying `HttpClient` requests via `AbortController` and correctly recognize browser `AbortError`
30
+ - `ResourceStore`: request state promotion and loading cleanup were stabilized for abort and retry flows, including non-promoted entries
31
+ - `PagedQueryStore`: `presetQuery.page` is now optional and defaults to `0`
32
+ - `PagedQueryStore`: `parseRequest` typing now accepts concrete filter dictionaries without conflicting with `AnyDict` call sites
33
+ - `Serializer`: deep object serialization now skips circular references instead of throwing
34
+
35
+ ### Test:
36
+ - `ResourceStore`: added `observe` coverage for cache-first hit, HTTP error propagation, and PUT/PATCH/DELETE methods
37
+ - `ResourceStore`: added coverage for retry backoff/jitter, payload pass-through, abort edge cases, forced eviction, and hot-key LRU behavior
38
+ - `DictStore`, `DictLocalStore`, and `EntityStore`: added regression coverage for uncovered edge scenarios
39
+ - `Serializer`: added regression coverage for direct and indirect circular references plus repeated shared-object serialization
40
+
41
+ ### Docs:
42
+ - `README`: documented `observe: 'response'` behavior and clarified direct setter usage in `PagedQueryStore`
43
+
44
+ ### Chore:
45
+ - package assets now include `CHANGELOG.md` and `LICENSE`
46
+
47
+ ---
48
+
49
+ ## [3.0.1]: 2026-03-31
50
+
51
+ ### Feat:
52
+ - `ResourceStore`: added `observe` option on per-call config - set `observe: 'response'` to pass the full `HttpResponse<T>` to `parseResponse` instead of just the body; useful for reading response headers or status codes
53
+
54
+ ### Refactor:
55
+ - `PagedQueryStore`: removed `@deprecated` annotations from direct state setters (`page`, `pageSize`, `filters`, `query`, `totalElements`); setters remain available for low-level integration scenarios (e.g., external data-grid source contracts)
56
+
57
+ ### Test:
58
+ - `ResourceStore`: added `observe` coverage for cache-first hit, HTTP error propagation, and PUT/PATCH/DELETE methods
59
+
60
+ ---
61
+
62
+ ## [3.0.0]: 2026-03-17
63
+
64
+ ### Feat:
65
+ - `PagedQueryStore`: added first-class sorting state and methods (`setSort`, `updateSort`, `updateSorts`) with standard repeated query serialization (`sort=a,asc&sort=b,desc`)
66
+ - `PagedQueryStore`: added reactive metadata signals (`pageState`, `pageSizeState`, `totalElementsState`, `filtersState`, `queryState`, `sortState`, `routeParamsState`)
67
+ - `PagedQueryStore`: added reactive `error` signal
68
+ - `PagedQueryStore`: added configurable request concurrency (`latest-wins` by default, optional `parallel`)
69
+ - `PagedQueryStore`: added `baseUrl` config option and `defaultBaseUrl` provider default for routing requests through a shared API prefix
70
+ - `PagedQueryStore`: added `disableCacheLimit` config flag to disable LRU eviction and keep all loaded pages in memory
71
+ - `PagedQueryStoreProviderConfig`: added `defaultDisableCacheLimit` global default
72
+ - `DictStore`: added cache freshness controls (`ttlMs`, `revalidate`) and provider defaults (`defaultTtlMs`, `defaultRevalidate`)
73
+ - `DictStore`: added `clearCache()`
74
+ - `Serializer`: added per-field array query serialization override via `mapFields.<key>.concatType`
75
+
76
+ ### Refactor:
77
+ - `PagedQueryStore`: route params are now exposed only via `routeParamsState`; direct `routeParams` getter was removed
78
+ - `PagedQueryStore`: direct `sort` / `routeParams` mutation setters were removed; remaining direct state setters are now deprecated
79
+ - `ResourceStore`: GET setup path no longer uses the extra local rethrow branch while preserving dedupe/cache behavior
80
+
81
+ ### Fix:
82
+ - `PagedQueryStore`: `latest-wins` request bursts now keep `loading` stable until the newest request finishes
83
+ - `PagedQueryStore`: stale async `parseResponse` results are now ignored after a newer request starts, transport is reinitialized, or the store is destroyed
84
+ - `PagedQueryStore.updateConfig(...)` / `copy(...)`: transport is now reinitialized so updated request settings apply immediately
85
+ - `ResourceStore`: query arrays are now serialized as comma-separated values (`a=1,2,3`) instead of collapsing to a single last value
86
+ - `PagedQueryStore`: cache limit resolution is now consistent across constructor/config apply/`updateConfig`, including cache-size updates at runtime
87
+ - `ResourceStore`: empty-string routes are now treated as valid and `baseUrl + ''` no longer produces a trailing slash
88
+ - `DictStore`: stale local cache can now stay visible while background refresh runs, with timestamped storage metadata
89
+ - `LruCache`: limit setter ordering/typing was normalized to keep runtime behavior predictable
90
+ - `Serializer`: query parse/build now respects per-field array concat modes
91
+
92
+ ### Test:
93
+ - added expanded `PagedQueryStore` regression coverage for sorting, cache limits, concurrency, config updates, and source-mode integration
94
+ - added `ResourceStore` regression coverage for query-array serialization and empty-string routes
95
+ - added `DictStore` regression coverage for TTL/revalidate/clear-cache flows
96
+ - added perf/stress suites and report benchmarks for main stores
97
+ - stabilized test setup / Vitest library configuration for the v3 suite
98
+
99
+ ### Docs:
100
+ - `README`: updated positioning, API stability policy, behavioral guarantees, recipes, and `PagedQueryStore` / `data-grid` integration guidance
101
+ - `MIGRATION.md`: added v3 stability note and expanded migration guidance
102
+ - `PERF.md`: added checked-in benchmark/report baseline for main stores
103
+
104
+ ---
105
+
106
+ ## [3.0.0-rc.1]: 2026-02-18
107
+
108
+ ### Feat:
109
+ - `PagedQueryStore`: normalized public API to object-style contracts (`fetch`, `refetchWith`, `updatePage`, `updatePageSize`, `updateByOffset`, `setRouteParams`, `updateConfig`, `copy`)
110
+ - `PagedQueryStore`: `fetch({ filters, query, routeParams })` performs clean first-page request with cache reset
111
+ - `ResourceStore`: added reusable option presets via `RESOURCE_PROFILES` and `createResourceProfile(...)`
112
+ - `Statum`: added `provideStatum(...)` provider helper for DI configuration
113
+
114
+ ### Refactor:
115
+ - `PagedQueryStore`: removed built-in sorting state/transport mapping from store internals (sorting stays at consumer side)
116
+ - `PagedQueryStore`: removed legacy APIs `updateFilters(...)`, `updateQuery(...)`, `setRoute(...)`
117
+ - `DictStore`: migrated internal helper calls to new `PagedQueryStore.fetch(...)` contract
118
+
119
+ ### Fix:
120
+ - `ResourceStore`: `abort(...)` / `abortAll(...)` now clear dedupe inflight references immediately
121
+ - `Serializer` tests: aligned `multi` query-array expectation with current query builder behavior
122
+
123
+ ### Docs:
124
+ - `README`: updated `PagedQueryStore` v3 API and cache behavior matrix
125
+ - `MIGRATION.md`: added v3 old-to-new mapping with concrete replacement examples
126
+
127
+ ---
128
+
129
+ ## [2.1.0]: 2026-02-14
130
+
131
+ ### Feat:
132
+ - `EntityStore`: added normalized entity store (`byId` + `ids`) with `setAll`, `upsert`, `remove`, `patch`, and computed `items`
133
+ - `ResourceStore`: added unified retry policy (`attempts`, `delayMs`, `backoff`, `shouldRetry`) on store and per-call levels
134
+ - `ResourceStore`: added trace hook (`onTrace`) for cache/request lifecycle (`cache-hit/miss/fallback/write`, `request-start/success/error/retry`, `abort`)
135
+ - `Serializer`: added presets export (`serializer.presets`) for quicker setup of common mapping configurations
136
+ - `Stores`: added `resource.scheduler` public test coverage and scheduler stability improvements
137
+ - `Stores`: added integration tests for composed flows (`ResourceStore` + `PaginatedDataStore` + `EntityStore`)
138
+ - `Stores`: added perf/stress test suite for main stores
139
+
140
+ ### Fix:
141
+ - `ResourceStore + KeyedScheduler`: stabilized cancel/reject behavior for abort/debounce scenarios in tests
142
+ - `EntityStore`: fixed generic type narrowing an edge case (`TS2677`) by removing invalid predicate narrowing in `removeMany`
143
+ - `ResourceStore`: expanded models/exports and aligned runtime behavior for retry + tracing hooks
144
+ - `PaginatedDataStore`: refined config/cache behavior and updated tests around cache/refresh flows
145
+ - `DictStore`: refined store behavior and updated coverage for edge scenarios
146
+ - `CacheStrategy` + storages (`local/session/lru`): safety and behavior fixes with updated tests
147
+ - `Serializer`: parsing/normalization fixes and stronger test coverage for edge cases
148
+
149
+ ### Docs:
150
+ - `README`: added composition patterns and updated usage examples for `EntityStore` and `ResourceStore` retry/trace
151
+
152
+ ---
153
+
154
+ ## [2.0.1]: 2026-02-06
155
+
156
+ ### Fix:
157
+ - `ResourceStore`: stable request keys now include payload; use `responseType` in HttpClient requests; avoid unhandled rejections
158
+ - `PaginatedDataStore`: initialize LRU cache size from resolved config; keep cache limit in sync after config changes; clarify `setRouteParams` reset behavior
159
+ - `DictStore`: debounce respects configured `debounceTime`; local filter handles non-string values safely
160
+ - `DictLocalStore`: respects global default `maxOptionsSize`
161
+ - `Serializer`: honor `mapString.parse` without precedence bugs; deep object deserialize; nullable handling preserves falsy values
162
+
163
+ ### Chore:
164
+ - `LruCache`: added `entries()` helper
165
+ - `README`: updated defaults and fixed broken formatting/encoding
166
+
167
+ ---
168
+
169
+ ## [2.0.0]: 2026-01-22
170
+
171
+ ### Feat:
172
+ - `PaginatedDataStore`: added route params update method
173
+ - `DictStore`: added debounce for search
174
+
175
+ ### Fix:
176
+ - `ResourceStore`: improved internal key uniqueness
177
+ - `ResourceStore`: fixed `loading` handling for concurrent requests
178
+ - `LocalStorage`/`SessionStorage`: prefix-based safety for clear operations
179
+
180
+ ---
181
+
182
+ ## [1.0.2]: 2026-01-09
183
+
184
+ ### Chore:
185
+ - improved docs
186
+
187
+ ---
188
+
189
+ ## [1.0.1]: 2026-01-09
190
+
191
+ ### Fix:
192
+ - `DictStore`: fixed search effect handling
193
+ - `PaginatedDataStore`: reordered filter caching
194
+
195
+ ### Feat:
196
+ - `PaginatedDataStore`: made `parseResponse` async
197
+
198
+ ---
199
+
200
+ ## [1.0.0]: 2025-12-24
201
+
202
+ ### Feat:
203
+ - base data grid functionality
204
+ - virtual scrolling for large datasets
205
+ - single-column sorting
206
+ - pagination and infinite scroll
207
+ - customizable cell and header templates
208
+ - pin rows to top and bottom
209
+ - sticky columns left and right
210
+ - text alignment configuration per column
211
+ - min/max column widths
212
+ - single and multiple row selection
213
+ - index column support
214
+ - empty/loading state customization
215
+ - flexible data typing system
216
+
217
+
218
+
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 rtommievich
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  **Signals-first query and data stores for Angular (18+).**
7
7
 
8
- `@reforgium/statum` provides **API-oriented stores**, **cache strategies**, and a
8
+ `@reforgium/statum` provides **API-oriented stores**, **cache strategies**, and a
9
9
  **serialization layer** for Angular applications that talk to HTTP backends.
10
10
 
11
11
  Designed for **request orchestration, pagination, dictionaries, and entity state**.
@@ -94,6 +94,9 @@ The safest long-term entry points are:
94
94
  - **Stores** - reusable state containers over HttpClient
95
95
  - **Serializer** - configurable data transformation utility
96
96
 
97
+ Low-level serializer and storage primitives are shared through hidden `@reforgium/internal`.
98
+ `statum` remains the user-facing package; you do not need to install or reason about `@reforgium/internal` directly in normal usage.
99
+
97
100
  ## Behavioral Guarantees
98
101
 
99
102
  The core stores are designed around explicit, testable runtime guarantees.
@@ -151,9 +154,9 @@ Those numbers are machine-specific and should be treated as a local envelope, no
151
154
 
152
155
  ## Cache
153
156
 
154
- ### cacheStrategy
157
+ ### storageStrategy
155
158
 
156
- `cacheStrategy<T>(kind)` is a factory that returns a cache storage implementing `StorageInterface<T>`
159
+ `storageStrategy<T>(kind)` is a factory that returns a cache storage implementing `StorageInterface<T>`
157
160
 
158
161
  Available strategies:
159
162
 
@@ -180,11 +183,11 @@ interface StorageInterface<T> {
180
183
  Example:
181
184
 
182
185
  ```ts
183
- import { cacheStrategy } from '@reforgium/statum';
186
+ import { storageStrategy } from '@reforgium/statum';
184
187
 
185
188
  type User = { id: number; name: string };
186
189
 
187
- const storage = cacheStrategy<User>('persist');
190
+ const storage = storageStrategy<User>('persist');
188
191
 
189
192
  storage.set('user:1', { id: 1, name: 'John' });
190
193
 
@@ -226,6 +229,28 @@ Transport-level store over HttpClient with cache strategies, deduplication, abor
226
229
  | abort | Abort a specific request |
227
230
  | abortAll | Abort all requests |
228
231
 
232
+ ### observe
233
+
234
+ By default, `parseResponse` (and the resolved Promise value) receive the **response body**.
235
+ Pass `observe: 'response'` to receive the full `HttpResponse` instead — useful for reading response headers or status codes inside `parseResponse`.
236
+
237
+ ```ts
238
+ const result = await store.get(
239
+ { params: { id: '1' }, query: {} },
240
+ {
241
+ observe: 'response',
242
+ parseResponse: (res) => ({
243
+ data: res.body,
244
+ etag: res.headers.get('ETag'),
245
+ }),
246
+ },
247
+ );
248
+ ```
249
+
250
+ `onResponse` (store-level hook) always fires with the full `HttpResponse` regardless of `observe`, and is intended for side-effects only (logging, header extraction).
251
+
252
+ > Cache hits bypass the network entirely. When `observe: 'response'` is used with `strategy: 'cache-first'` or `'cache-only'` and a cached value exists, `parseResponse` is not called — the cached result is returned as-is.
253
+
229
254
  Example:
230
255
 
231
256
  ```ts
@@ -397,7 +422,7 @@ store.updateSort({ sort: 'name', order: 'asc' });
397
422
 
398
423
  `cached()` remains a bounded hot-cache view. It is useful for cache-aware revisit/export/search helpers, but it is not the right datasource for infinity scrolling once cache eviction matters. For `data-grid` infinity mode, prefer passing the whole store as a `GridPagedDataSource` (`[source]="store"`) and let the grid keep its own page buffer.
399
424
 
400
- Direct state mutation setters for `page`, `pageSize`, `filters`, `query`, and `totalElements` still exist for backward compatibility, but they are deprecated in favor of explicit store methods. `sort` and `routeParams` should be changed only through `setSort(...)` and `setRouteParams(...)`.
425
+ `sort` and `routeParams` should be changed only through `setSort(...)` and `setRouteParams(...)`. Direct state mutation setters for `page`, `pageSize`, `filters`, `query`, and `totalElements` are available for low-level integration scenarios (such as external data-grid source contracts) but prefer the explicit store methods for typical use.
401
426
 
402
427
  ### PagedQueryStore + DataGrid source mode
403
428
 
@@ -629,6 +654,8 @@ Use this when list fetching and local item mutations need different lifecycles.
629
654
 
630
655
  Utility for serialization/deserialization between layers (UI -> API, objects -> query string).
631
656
 
657
+ `statum` keeps the user-facing serializer API and presets, while the low-level codec engine is shared from hidden `@reforgium/internal`.
658
+
632
659
  Core API:
633
660
 
634
661
  | Method | Description |