@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 +218 -0
- package/LICENSE +21 -0
- package/README.md +33 -6
- package/fesm2022/reforgium-statum.mjs +137 -656
- package/package.json +17 -6
- package/types/reforgium-statum.d.ts +44 -310
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
|
-
###
|
|
157
|
+
### storageStrategy
|
|
155
158
|
|
|
156
|
-
`
|
|
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 {
|
|
186
|
+
import { storageStrategy } from '@reforgium/statum';
|
|
184
187
|
|
|
185
188
|
type User = { id: number; name: string };
|
|
186
189
|
|
|
187
|
-
const storage =
|
|
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`
|
|
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 |
|