@reforgium/statum 2.0.1 → 2.1.0
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/README.md
CHANGED
|
@@ -12,14 +12,16 @@ Designed for **application state**, not abstract reducers.
|
|
|
12
12
|
|
|
13
13
|
---
|
|
14
14
|
|
|
15
|
-
## Features
|
|
16
|
-
|
|
17
|
-
- Signals-first API (`signal()` everywhere)
|
|
18
|
-
- API-driven stores (resource / paginated / dictionaries)
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
15
|
+
## Features
|
|
16
|
+
|
|
17
|
+
- Signals-first API (`signal()` everywhere)
|
|
18
|
+
- API-driven stores (resource / paginated / dictionaries)
|
|
19
|
+
- Normalized entity store (`EntityStore`)
|
|
20
|
+
- Built-in cache strategies (TTL, prefix grouping)
|
|
21
|
+
- Deterministic request lifecycle: loading / error / data
|
|
22
|
+
- Optional transport-level: dedupe, debounce/throttle, abort
|
|
23
|
+
- Unified retry and trace hooks in `ResourceStore`
|
|
24
|
+
- Explicit serialization / deserialization boundary
|
|
23
25
|
|
|
24
26
|
---
|
|
25
27
|
|
|
@@ -67,7 +69,7 @@ interface StorageInterface<T> {
|
|
|
67
69
|
}
|
|
68
70
|
```
|
|
69
71
|
|
|
70
|
-
Example:
|
|
72
|
+
Example:
|
|
71
73
|
|
|
72
74
|
```ts
|
|
73
75
|
import { cacheStrategy } from '@reforgium/statum';
|
|
@@ -128,15 +130,56 @@ const userStore = new ResourceStore<User>(
|
|
|
128
130
|
{ baseUrl: '/api', ttlMs: 60_000 }
|
|
129
131
|
);
|
|
130
132
|
|
|
131
|
-
const user = await userStore.get(
|
|
132
|
-
{ params: { id: '42' }, query: {} },
|
|
133
|
-
{ dedupe: true }
|
|
134
|
-
);
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
133
|
+
const user = await userStore.get(
|
|
134
|
+
{ params: { id: '42' }, query: {} },
|
|
135
|
+
{ dedupe: true }
|
|
136
|
+
);
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Retry + trace example:
|
|
140
|
+
|
|
141
|
+
```ts
|
|
142
|
+
import { ResourceStore } from '@reforgium/statum';
|
|
143
|
+
|
|
144
|
+
const store = new ResourceStore<{ id: number; name: string }>(
|
|
145
|
+
{ GET: '/users/:id' },
|
|
146
|
+
{
|
|
147
|
+
baseUrl: '/api',
|
|
148
|
+
retry: { attempts: 2, delayMs: 150, backoff: 'exponential' },
|
|
149
|
+
onTrace: (event) => console.debug('[resource-trace]', event),
|
|
150
|
+
}
|
|
151
|
+
);
|
|
152
|
+
|
|
153
|
+
await store.get(
|
|
154
|
+
{ params: { id: '42' } },
|
|
155
|
+
{ retry: { attempts: 1 } } // per-call override
|
|
156
|
+
);
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## EntityStore
|
|
162
|
+
|
|
163
|
+
Normalized entities store (`byId` + `ids`) for fast updates and stable list composition.
|
|
164
|
+
|
|
165
|
+
Example:
|
|
166
|
+
|
|
167
|
+
```ts
|
|
168
|
+
import { EntityStore } from '@reforgium/statum';
|
|
169
|
+
|
|
170
|
+
type User = { id: number; name: string };
|
|
171
|
+
|
|
172
|
+
const entities = new EntityStore<User, 'id'>({ idKey: 'id' });
|
|
173
|
+
|
|
174
|
+
entities.setAll([{ id: 1, name: 'Neo' }]);
|
|
175
|
+
entities.upsertOne({ id: 2, name: 'Trinity' });
|
|
176
|
+
entities.patchOne(2, { name: 'Trin' });
|
|
177
|
+
entities.removeOne(1);
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## PaginatedDataStore
|
|
140
183
|
|
|
141
184
|
Lightweight store for server-side pagination with sorting, filtering, and page cache.
|
|
142
185
|
|
|
@@ -259,12 +302,34 @@ const dict = new DictStore<Country>('api/dictionaries/countries', 'countries', {
|
|
|
259
302
|
});
|
|
260
303
|
|
|
261
304
|
dict.search(''); // initial fill
|
|
262
|
-
dict.search('kir'); // local search over cache
|
|
263
|
-
```
|
|
264
|
-
|
|
265
|
-
---
|
|
266
|
-
|
|
267
|
-
##
|
|
305
|
+
dict.search('kir'); // local search over cache
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
---
|
|
309
|
+
|
|
310
|
+
## Composition Patterns
|
|
311
|
+
|
|
312
|
+
### PaginatedDataStore + EntityStore
|
|
313
|
+
|
|
314
|
+
```ts
|
|
315
|
+
import { effect } from '@angular/core';
|
|
316
|
+
import { EntityStore, PaginatedDataStore } from '@reforgium/statum';
|
|
317
|
+
|
|
318
|
+
type User = { id: number; name: string };
|
|
319
|
+
|
|
320
|
+
const pages = new PaginatedDataStore<User, { search?: string }>('/api/users');
|
|
321
|
+
const entities = new EntityStore<User, 'id'>({ idKey: 'id' });
|
|
322
|
+
|
|
323
|
+
effect(() => {
|
|
324
|
+
entities.upsertMany(pages.items());
|
|
325
|
+
});
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
This keeps page-loading logic in `PaginatedDataStore` and normalized lookup/update logic in `EntityStore`.
|
|
329
|
+
|
|
330
|
+
---
|
|
331
|
+
|
|
332
|
+
## Serializer
|
|
268
333
|
|
|
269
334
|
### Serializer
|
|
270
335
|
|