@coherent.js/state 1.0.0-beta.5 → 1.0.0-beta.6
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/package.json +2 -2
- package/types/index.d.ts +364 -39
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coherent.js/state",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.6",
|
|
4
4
|
"description": "Reactive state management for Coherent.js applications",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"access": "public"
|
|
30
30
|
},
|
|
31
31
|
"peerDependencies": {
|
|
32
|
-
"@coherent.js/core": "1.0.0-beta.
|
|
32
|
+
"@coherent.js/core": "1.0.0-beta.6"
|
|
33
33
|
},
|
|
34
34
|
"types": "./types/index.d.ts",
|
|
35
35
|
"files": [
|
package/types/index.d.ts
CHANGED
|
@@ -3,138 +3,463 @@
|
|
|
3
3
|
* @module @coherent.js/state
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
import type { CoherentNode, ComponentState } from '@coherent.js/core';
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
// ============================================================================
|
|
9
|
+
// Core Store Types
|
|
10
|
+
// ============================================================================
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Typed state store with subscribe and update capabilities
|
|
14
|
+
* @template T - The shape of the state object
|
|
15
|
+
*/
|
|
16
|
+
export interface Store<T extends Record<string, unknown> = Record<string, unknown>> {
|
|
17
|
+
/**
|
|
18
|
+
* Get the current state
|
|
19
|
+
*/
|
|
20
|
+
getState(): T;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Update state with partial object or updater function
|
|
24
|
+
*/
|
|
25
|
+
setState(partial: Partial<T> | ((state: T) => Partial<T>)): void;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Subscribe to state changes
|
|
29
|
+
* @returns Unsubscribe function
|
|
30
|
+
*/
|
|
31
|
+
subscribe(listener: (state: T, prevState: T) => void): () => void;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Destroy the store and clean up subscriptions
|
|
35
|
+
*/
|
|
36
|
+
destroy(): void;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Store creation options
|
|
41
|
+
* @template T - The shape of the state object
|
|
42
|
+
*/
|
|
43
|
+
export interface StoreOptions<T extends Record<string, unknown> = Record<string, unknown>> {
|
|
44
|
+
/** Initial state */
|
|
45
|
+
initialState: T;
|
|
46
|
+
/** Persistence configuration */
|
|
47
|
+
persist?: {
|
|
48
|
+
/** Storage key */
|
|
49
|
+
key: string;
|
|
50
|
+
/** Storage adapter (localStorage, sessionStorage, or custom) */
|
|
51
|
+
storage?: Storage;
|
|
52
|
+
/** Custom serialization */
|
|
53
|
+
serialize?: (state: T) => string;
|
|
54
|
+
/** Custom deserialization */
|
|
55
|
+
deserialize?: (value: string) => T;
|
|
56
|
+
/** Debounce persistence writes (ms) */
|
|
57
|
+
debounce?: number;
|
|
58
|
+
};
|
|
59
|
+
/** Enable devtools integration */
|
|
60
|
+
devtools?: boolean;
|
|
61
|
+
/** Store name for debugging */
|
|
62
|
+
name?: string;
|
|
63
|
+
/** Middleware functions */
|
|
64
|
+
middleware?: Array<StoreMiddleware<T>>;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Store middleware function
|
|
69
|
+
*/
|
|
70
|
+
export type StoreMiddleware<T> = (
|
|
71
|
+
state: T,
|
|
72
|
+
action: string,
|
|
73
|
+
payload?: unknown
|
|
74
|
+
) => T | void;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Create a typed state store
|
|
78
|
+
*/
|
|
79
|
+
export function createStore<T extends Record<string, unknown>>(
|
|
80
|
+
options: StoreOptions<T>
|
|
81
|
+
): Store<T>;
|
|
82
|
+
|
|
83
|
+
// ============================================================================
|
|
84
|
+
// Selector Types
|
|
85
|
+
// ============================================================================
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Create a derived selector from store state
|
|
89
|
+
* @template T - Store state type
|
|
90
|
+
* @template R - Return type of selector
|
|
91
|
+
*/
|
|
92
|
+
export function createSelector<T extends Record<string, unknown>, R>(
|
|
93
|
+
store: Store<T>,
|
|
94
|
+
selector: (state: T) => R
|
|
95
|
+
): () => R;
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Create a memoized selector with dependencies
|
|
99
|
+
*/
|
|
100
|
+
export function createMemoizedSelector<T extends Record<string, unknown>, D extends unknown[], R>(
|
|
101
|
+
store: Store<T>,
|
|
102
|
+
dependencies: (...args: D) => unknown[],
|
|
103
|
+
selector: (state: T, ...deps: D) => R
|
|
104
|
+
): (...args: D) => R;
|
|
105
|
+
|
|
106
|
+
// ============================================================================
|
|
107
|
+
// Action Types
|
|
108
|
+
// ============================================================================
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Action type helper for type-safe actions
|
|
112
|
+
* @template T - Store state type
|
|
113
|
+
* @template P - Payload type (void for no payload)
|
|
114
|
+
*/
|
|
115
|
+
export type Action<T, P = void> = P extends void
|
|
116
|
+
? () => Partial<T>
|
|
117
|
+
: (payload: P) => Partial<T>;
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Create typed action creators
|
|
121
|
+
*/
|
|
122
|
+
export function createActions<
|
|
123
|
+
T extends Record<string, unknown>,
|
|
124
|
+
A extends Record<string, Action<T, unknown>>
|
|
125
|
+
>(
|
|
126
|
+
store: Store<T>,
|
|
127
|
+
actions: A
|
|
128
|
+
): {
|
|
129
|
+
[K in keyof A]: A[K] extends Action<T, infer P>
|
|
130
|
+
? P extends void
|
|
131
|
+
? () => void
|
|
132
|
+
: (payload: P) => void
|
|
133
|
+
: never;
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
// ============================================================================
|
|
137
|
+
// Reactive State Types
|
|
138
|
+
// ============================================================================
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Observer callback type
|
|
142
|
+
*/
|
|
143
|
+
export interface Observer<T = unknown> {
|
|
9
144
|
(value: T, oldValue: T): void;
|
|
10
145
|
}
|
|
11
146
|
|
|
12
|
-
|
|
147
|
+
/**
|
|
148
|
+
* Observable value wrapper
|
|
149
|
+
*/
|
|
150
|
+
export class Observable<T = unknown> {
|
|
13
151
|
constructor(initialValue: T);
|
|
152
|
+
|
|
153
|
+
/** Get current value */
|
|
14
154
|
get(): T;
|
|
155
|
+
|
|
156
|
+
/** Set new value */
|
|
15
157
|
set(value: T): void;
|
|
158
|
+
|
|
159
|
+
/** Subscribe to changes */
|
|
16
160
|
subscribe(observer: Observer<T>): () => void;
|
|
161
|
+
|
|
162
|
+
/** Unsubscribe observer */
|
|
17
163
|
unsubscribe(observer: Observer<T>): void;
|
|
164
|
+
|
|
165
|
+
/** Notify all observers */
|
|
18
166
|
notify(): void;
|
|
19
167
|
}
|
|
20
168
|
|
|
21
|
-
|
|
169
|
+
/**
|
|
170
|
+
* Reactive state options
|
|
171
|
+
*/
|
|
172
|
+
export interface ReactiveStateOptions<T = unknown> {
|
|
173
|
+
/** Initial state value */
|
|
22
174
|
initialValue: T;
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
175
|
+
/** Computed properties */
|
|
176
|
+
computed?: Record<string, (state: T) => unknown>;
|
|
177
|
+
/** Property watchers */
|
|
178
|
+
watchers?: Record<string, Observer<unknown>>;
|
|
179
|
+
/** Middleware functions */
|
|
180
|
+
middleware?: Array<(state: T, action: string, payload?: unknown) => T | void>;
|
|
26
181
|
}
|
|
27
182
|
|
|
28
|
-
|
|
183
|
+
/**
|
|
184
|
+
* Reactive state class with computed properties and watchers
|
|
185
|
+
*/
|
|
186
|
+
export class ReactiveState<T extends Record<string, unknown> = Record<string, unknown>> {
|
|
29
187
|
constructor(options: ReactiveStateOptions<T>);
|
|
188
|
+
|
|
189
|
+
/** Get a property value */
|
|
30
190
|
get<K extends keyof T>(key: K): T[K];
|
|
191
|
+
|
|
192
|
+
/** Set a property value */
|
|
31
193
|
set<K extends keyof T>(key: K, value: T[K]): void;
|
|
194
|
+
|
|
195
|
+
/** Update multiple properties */
|
|
32
196
|
update(partial: Partial<T>): void;
|
|
197
|
+
|
|
198
|
+
/** Subscribe to all changes */
|
|
33
199
|
subscribe(observer: Observer<T>): () => void;
|
|
200
|
+
|
|
201
|
+
/** Watch a specific property */
|
|
34
202
|
watch<K extends keyof T>(key: K, observer: Observer<T[K]>): () => void;
|
|
203
|
+
|
|
204
|
+
/** Get full state */
|
|
35
205
|
getState(): T;
|
|
206
|
+
|
|
207
|
+
/** Reset to initial state */
|
|
36
208
|
reset(): void;
|
|
37
209
|
}
|
|
38
210
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
211
|
+
/**
|
|
212
|
+
* Create a reactive state instance
|
|
213
|
+
*/
|
|
214
|
+
export function createReactiveState<T extends Record<string, unknown> = Record<string, unknown>>(
|
|
215
|
+
options: ReactiveStateOptions<T>
|
|
216
|
+
): ReactiveState<T>;
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Create a simple observable value
|
|
220
|
+
*/
|
|
221
|
+
export function observable<T = unknown>(initialValue: T): Observable<T>;
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Create a computed observable
|
|
225
|
+
*/
|
|
226
|
+
export function computed<T = unknown>(
|
|
227
|
+
fn: () => T,
|
|
228
|
+
dependencies: Observable<unknown>[]
|
|
229
|
+
): Observable<T>;
|
|
42
230
|
|
|
231
|
+
/**
|
|
232
|
+
* State utility functions
|
|
233
|
+
*/
|
|
43
234
|
export const stateUtils: {
|
|
235
|
+
/** Batch multiple state updates */
|
|
44
236
|
batch<T>(fn: () => T): T;
|
|
237
|
+
/** Run updates in a transaction */
|
|
45
238
|
transaction<T>(fn: () => T): T;
|
|
239
|
+
/** Freeze state (make immutable) */
|
|
46
240
|
freeze<T>(state: T): Readonly<T>;
|
|
241
|
+
/** Deep clone state */
|
|
47
242
|
clone<T>(state: T): T;
|
|
48
243
|
};
|
|
49
244
|
|
|
50
|
-
//
|
|
245
|
+
// ============================================================================
|
|
246
|
+
// SSR-Compatible State Manager
|
|
247
|
+
// ============================================================================
|
|
51
248
|
|
|
52
|
-
|
|
249
|
+
/**
|
|
250
|
+
* State manager options
|
|
251
|
+
*/
|
|
252
|
+
export interface StateManagerOptions<T = unknown> {
|
|
253
|
+
/** Initial state */
|
|
53
254
|
initialState?: T;
|
|
255
|
+
/** Enable persistence */
|
|
54
256
|
persist?: boolean;
|
|
257
|
+
/** Persistence key */
|
|
55
258
|
key?: string;
|
|
259
|
+
/** Middleware functions */
|
|
56
260
|
middleware?: Array<(state: T, action: string) => T | void>;
|
|
57
261
|
}
|
|
58
262
|
|
|
59
|
-
|
|
263
|
+
/**
|
|
264
|
+
* Simple state interface
|
|
265
|
+
*/
|
|
266
|
+
export interface State<T = unknown> {
|
|
267
|
+
/** Get current state */
|
|
60
268
|
get(): T;
|
|
269
|
+
/** Set new state */
|
|
61
270
|
set(value: T): void;
|
|
271
|
+
/** Update with partial */
|
|
62
272
|
update(partial: Partial<T>): void;
|
|
273
|
+
/** Subscribe to changes */
|
|
63
274
|
subscribe(listener: (state: T) => void): () => void;
|
|
275
|
+
/** Reset to initial state */
|
|
64
276
|
reset(): void;
|
|
65
277
|
}
|
|
66
278
|
|
|
67
|
-
|
|
279
|
+
/**
|
|
280
|
+
* Create a simple state container
|
|
281
|
+
*/
|
|
282
|
+
export function createState<T = unknown>(
|
|
283
|
+
initialState: T,
|
|
284
|
+
options?: StateManagerOptions<T>
|
|
285
|
+
): State<T>;
|
|
68
286
|
|
|
287
|
+
/**
|
|
288
|
+
* Global state manager for SSR
|
|
289
|
+
*/
|
|
69
290
|
export const globalStateManager: {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
291
|
+
/** Get state by key */
|
|
292
|
+
getState<T = unknown>(key: string): T | undefined;
|
|
293
|
+
/** Set state by key */
|
|
294
|
+
setState<T = unknown>(key: string, value: T): void;
|
|
295
|
+
/** Subscribe to state key */
|
|
296
|
+
subscribe<T = unknown>(key: string, listener: (state: T) => void): () => void;
|
|
297
|
+
/** Clear state (optionally by key) */
|
|
73
298
|
clear(key?: string): void;
|
|
74
299
|
};
|
|
75
300
|
|
|
76
|
-
//
|
|
301
|
+
// ============================================================================
|
|
302
|
+
// Context API
|
|
303
|
+
// ============================================================================
|
|
77
304
|
|
|
78
|
-
|
|
305
|
+
/**
|
|
306
|
+
* Context value wrapper
|
|
307
|
+
*/
|
|
308
|
+
export interface ContextValue<T = unknown> {
|
|
79
309
|
value: T;
|
|
80
310
|
subscribers: Set<(value: T) => void>;
|
|
81
311
|
}
|
|
82
312
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
export function
|
|
313
|
+
/**
|
|
314
|
+
* Provide a context value
|
|
315
|
+
*/
|
|
316
|
+
export function provideContext<T = unknown>(key: string, value: T): void;
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Create a context provider
|
|
320
|
+
*/
|
|
321
|
+
export function createContextProvider<T = unknown>(
|
|
322
|
+
key: string,
|
|
323
|
+
value: T
|
|
324
|
+
): { key: string; value: T };
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Use/consume a context value
|
|
328
|
+
*/
|
|
329
|
+
export function useContext<T = unknown>(key: string, defaultValue?: T): T;
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Restore context from saved state
|
|
333
|
+
*/
|
|
334
|
+
export function restoreContext(contexts: Record<string, unknown>): void;
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Clear all context stacks
|
|
338
|
+
*/
|
|
87
339
|
export function clearAllContexts(): void;
|
|
88
340
|
|
|
89
|
-
//
|
|
341
|
+
// ============================================================================
|
|
342
|
+
// Persistent State
|
|
343
|
+
// ============================================================================
|
|
90
344
|
|
|
345
|
+
/**
|
|
346
|
+
* Persistence adapter interface
|
|
347
|
+
*/
|
|
91
348
|
export interface PersistenceAdapter {
|
|
349
|
+
/** Get item from storage */
|
|
92
350
|
getItem(key: string): Promise<string | null> | string | null;
|
|
351
|
+
/** Set item in storage */
|
|
93
352
|
setItem(key: string, value: string): Promise<void> | void;
|
|
353
|
+
/** Remove item from storage */
|
|
94
354
|
removeItem(key: string): Promise<void> | void;
|
|
95
355
|
}
|
|
96
356
|
|
|
97
|
-
|
|
357
|
+
/**
|
|
358
|
+
* Persistent state options
|
|
359
|
+
*/
|
|
360
|
+
export interface PersistentStateOptions<T = unknown> extends StateManagerOptions<T> {
|
|
361
|
+
/** Required: storage key */
|
|
98
362
|
key: string;
|
|
363
|
+
/** Storage adapter */
|
|
99
364
|
storage?: PersistenceAdapter;
|
|
365
|
+
/** Custom serialization */
|
|
100
366
|
serialize?: (state: T) => string;
|
|
367
|
+
/** Custom deserialization */
|
|
101
368
|
deserialize?: (data: string) => T;
|
|
369
|
+
/** Debounce writes (ms) */
|
|
102
370
|
debounce?: number;
|
|
103
371
|
}
|
|
104
372
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
export function
|
|
373
|
+
/**
|
|
374
|
+
* Create a persistent state
|
|
375
|
+
*/
|
|
376
|
+
export function createPersistentState<T = unknown>(
|
|
377
|
+
options: PersistentStateOptions<T>
|
|
378
|
+
): State<T>;
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* Wrap state with localStorage persistence
|
|
382
|
+
*/
|
|
383
|
+
export function withLocalStorage<T = unknown>(state: State<T>, key: string): State<T>;
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* Wrap state with sessionStorage persistence
|
|
387
|
+
*/
|
|
388
|
+
export function withSessionStorage<T = unknown>(state: State<T>, key: string): State<T>;
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Wrap state with IndexedDB persistence
|
|
392
|
+
*/
|
|
393
|
+
export function withIndexedDB<T = unknown>(
|
|
394
|
+
state: State<T>,
|
|
395
|
+
key: string,
|
|
396
|
+
dbName?: string
|
|
397
|
+
): Promise<State<T>>;
|
|
109
398
|
|
|
110
|
-
//
|
|
399
|
+
// ============================================================================
|
|
400
|
+
// Validated State
|
|
401
|
+
// ============================================================================
|
|
111
402
|
|
|
112
|
-
|
|
403
|
+
/**
|
|
404
|
+
* Validation rule function
|
|
405
|
+
*/
|
|
406
|
+
export interface ValidationRule<T = unknown> {
|
|
113
407
|
(value: T): boolean | string;
|
|
114
408
|
}
|
|
115
409
|
|
|
116
|
-
|
|
117
|
-
|
|
410
|
+
/**
|
|
411
|
+
* Validated state options
|
|
412
|
+
*/
|
|
413
|
+
export interface ValidatedStateOptions<T extends Record<string, unknown> = Record<string, unknown>>
|
|
414
|
+
extends StateManagerOptions<T> {
|
|
415
|
+
/** Validation rules by property */
|
|
416
|
+
validators: { [K in keyof T]?: ValidationRule<T[K]>[] };
|
|
417
|
+
/** Validate on every change */
|
|
118
418
|
validateOnChange?: boolean;
|
|
419
|
+
/** Throw on validation failure */
|
|
119
420
|
strict?: boolean;
|
|
120
421
|
}
|
|
121
422
|
|
|
122
|
-
|
|
123
|
-
|
|
423
|
+
/**
|
|
424
|
+
* Validated state interface
|
|
425
|
+
*/
|
|
426
|
+
export interface ValidatedState<T extends Record<string, unknown> = Record<string, unknown>>
|
|
427
|
+
extends State<T> {
|
|
428
|
+
/** Validate current state */
|
|
429
|
+
validate(): { valid: boolean; errors: { [K in keyof T]?: string[] } };
|
|
430
|
+
/** Check if state is valid */
|
|
124
431
|
isValid(): boolean;
|
|
125
|
-
|
|
432
|
+
/** Get validation errors */
|
|
433
|
+
getErrors(): { [K in keyof T]?: string[] };
|
|
126
434
|
}
|
|
127
435
|
|
|
128
|
-
|
|
436
|
+
/**
|
|
437
|
+
* Create a validated state
|
|
438
|
+
*/
|
|
439
|
+
export function createValidatedState<T extends Record<string, unknown> = Record<string, unknown>>(
|
|
440
|
+
options: ValidatedStateOptions<T>
|
|
441
|
+
): ValidatedState<T>;
|
|
129
442
|
|
|
443
|
+
/**
|
|
444
|
+
* Built-in validators
|
|
445
|
+
*/
|
|
130
446
|
export const validators: {
|
|
447
|
+
/** Required value */
|
|
131
448
|
required(message?: string): ValidationRule;
|
|
449
|
+
/** Minimum length */
|
|
132
450
|
minLength(length: number, message?: string): ValidationRule;
|
|
451
|
+
/** Maximum length */
|
|
133
452
|
maxLength(length: number, message?: string): ValidationRule;
|
|
453
|
+
/** Minimum value */
|
|
134
454
|
min(value: number, message?: string): ValidationRule;
|
|
455
|
+
/** Maximum value */
|
|
135
456
|
max(value: number, message?: string): ValidationRule;
|
|
457
|
+
/** Pattern matching */
|
|
136
458
|
pattern(regex: RegExp, message?: string): ValidationRule;
|
|
459
|
+
/** Email format */
|
|
137
460
|
email(message?: string): ValidationRule;
|
|
461
|
+
/** URL format */
|
|
138
462
|
url(message?: string): ValidationRule;
|
|
139
|
-
|
|
463
|
+
/** Custom validator */
|
|
464
|
+
custom(fn: (value: unknown) => boolean | string): ValidationRule;
|
|
140
465
|
};
|