@oxog/state 1.0.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.
@@ -0,0 +1,1061 @@
1
+ /**
2
+ * Deep partial type for nested optional properties.
3
+ *
4
+ * @typeParam T - The type to make partially deep
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * type User = {
9
+ * name: string;
10
+ * profile: { age: number; city: string; };
11
+ * };
12
+ *
13
+ * const partial: DeepPartial<User> = {
14
+ * name: 'John',
15
+ * profile: { age: 30 } // city is optional
16
+ * };
17
+ * ```
18
+ */
19
+ type DeepPartial<T> = T extends object ? {
20
+ [P in keyof T]?: DeepPartial<T[P]>;
21
+ } : T;
22
+ /**
23
+ * Action function that receives state and optional arguments, returning a partial state update.
24
+ *
25
+ * @typeParam TState - The store state type
26
+ * @typeParam TArgs - The action argument types tuple
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * type CounterAction = Action<{ count: number }, [number: number]>;
31
+ *
32
+ * const incrementBy: CounterAction = (state, amount) => ({
33
+ * count: state.count + amount
34
+ * });
35
+ * ```
36
+ */
37
+ type Action<TState, TArgs extends unknown[] = []> = (state: TState, ...args: TArgs) => Partial<TState> | Promise<Partial<TState>>;
38
+ /**
39
+ * Collection of actions indexed by name.
40
+ *
41
+ * @typeParam TState - The store state type
42
+ *
43
+ * @example
44
+ * ```typescript
45
+ * const actions: Actions<{ count: number }> = {
46
+ * increment: (state) => ({ count: state.count + 1 }),
47
+ * decrement: (state) => ({ count: state.count - 1 })
48
+ * };
49
+ * ```
50
+ */
51
+ type Actions<TState> = Record<string, Action<TState>>;
52
+ /**
53
+ * Selector function to extract a slice of state.
54
+ *
55
+ * @typeParam TState - The store state type
56
+ * @typeParam TSelected - The selected value type
57
+ *
58
+ * @example
59
+ * ```typescript
60
+ * const selectCount: Selector<{ count: number; name: string }, number> =
61
+ * (state) => state.count;
62
+ * ```
63
+ */
64
+ type Selector<TState, TSelected> = (state: TState) => TSelected;
65
+ /**
66
+ * Equality function for comparing two values.
67
+ *
68
+ * @typeParam T - The type to compare
69
+ *
70
+ * @example
71
+ * ```typescript
72
+ * const shallowEquality: EqualityFn<{ a: number }> = (a, b) =>
73
+ * a.a === b.a;
74
+ * ```
75
+ */
76
+ type EqualityFn<T> = (a: T, b: T) => boolean;
77
+ /**
78
+ * Listener function called when state changes.
79
+ *
80
+ * @typeParam TState - The store state type
81
+ *
82
+ * @example
83
+ * ```typescript
84
+ * const listener: Listener<{ count: number }> = (state, prevState) => {
85
+ * console.log(`Count changed from ${prevState.count} to ${state.count}`);
86
+ * };
87
+ * ```
88
+ */
89
+ type Listener<TState> = (state: TState, prevState: TState) => void;
90
+ /**
91
+ * Storage interface for persisting state.
92
+ *
93
+ * @example
94
+ * ```typescript
95
+ * const sessionStorage: StorageLike = {
96
+ * getItem: (key) => sessionStorage.getItem(key),
97
+ * setItem: (key, value) => sessionStorage.setItem(key, value),
98
+ * removeItem: (key) => sessionStorage.removeItem(key)
99
+ * };
100
+ * ```
101
+ */
102
+ interface StorageLike$1 {
103
+ /** Get an item from storage */
104
+ getItem(key: string): string | null;
105
+ /** Set an item in storage */
106
+ setItem(key: string, value: string): void;
107
+ /** Remove an item from storage */
108
+ removeItem(key: string): void;
109
+ }
110
+ /**
111
+ * Store configuration options.
112
+ *
113
+ * @typeParam TState - The store state type
114
+ *
115
+ * @example
116
+ * ```typescript
117
+ * const options: StoreOptions<{ count: number }> = {
118
+ * name: 'Counter',
119
+ * devtools: true
120
+ * };
121
+ * ```
122
+ */
123
+ interface StoreOptions<TState> {
124
+ /** Initial state */
125
+ initialState: TState;
126
+ /** Store name for debugging */
127
+ name?: string;
128
+ /** Enable/disable devtools (default: true in development) */
129
+ devtools?: boolean;
130
+ }
131
+ /**
132
+ * Plugin interface for extending store functionality.
133
+ *
134
+ * @typeParam TState - The store state type
135
+ *
136
+ * @example
137
+ * ```typescript
138
+ * const loggerPlugin: Plugin<{ count: number }> = {
139
+ * name: 'logger',
140
+ * version: '1.0.0',
141
+ * install(store) {
142
+ * store.subscribe((state) => console.log('State:', state));
143
+ * }
144
+ * };
145
+ * ```
146
+ */
147
+ interface Plugin<TState = unknown> {
148
+ /** Unique plugin identifier (kebab-case) */
149
+ name: string;
150
+ /** Semantic version (e.g., "1.0.0") */
151
+ version: string;
152
+ /** Other plugins this plugin depends on */
153
+ dependencies?: string[];
154
+ /**
155
+ * Called when plugin is registered.
156
+ *
157
+ * @param store - The store instance
158
+ * @param options - Plugin-specific options
159
+ */
160
+ install: (store: Store<TState>, options?: unknown) => void;
161
+ /**
162
+ * Called after all plugins are installed.
163
+ *
164
+ * @param store - The store instance
165
+ */
166
+ onInit?: (store: Store<TState>) => void | Promise<void>;
167
+ /**
168
+ * Called when plugin is unregistered.
169
+ */
170
+ onDestroy?: () => void | Promise<void>;
171
+ /**
172
+ * Called on state change.
173
+ *
174
+ * @param state - New state
175
+ * @param prevState - Previous state
176
+ */
177
+ onStateChange?: (state: TState, prevState: TState) => void;
178
+ /**
179
+ * Called on error in store.
180
+ *
181
+ * @param error - The error that occurred
182
+ */
183
+ onError?: (error: Error) => void;
184
+ }
185
+ /**
186
+ * Store instance with state management methods.
187
+ *
188
+ * @typeParam TState - The store state type
189
+ *
190
+ * @example
191
+ * ```typescript
192
+ * const store: Store<{ count: number }> = createStore({ count: 0 });
193
+ * const state = store.getState(); // { count: 0 }
194
+ * store.setState({ count: 1 });
195
+ * ```
196
+ */
197
+ interface Store<TState> {
198
+ /** Get current state snapshot */
199
+ getState(): TState;
200
+ /**
201
+ * Update state with partial object or function.
202
+ *
203
+ * @param partial - Partial state or updater function
204
+ *
205
+ * @example
206
+ * ```typescript
207
+ * store.setState({ count: 10 });
208
+ * store.setState((state) => ({ count: state.count + 1 }));
209
+ * ```
210
+ */
211
+ setState(partial: Partial<TState> | ((state: TState) => Partial<TState>)): void;
212
+ /**
213
+ * Deep merge state.
214
+ *
215
+ * @param partial - Partial state to merge
216
+ *
217
+ * @example
218
+ * ```typescript
219
+ * store.merge({ user: { name: 'John' } });
220
+ * ```
221
+ */
222
+ merge(partial: DeepPartial<TState>): void;
223
+ /** Reset to initial state */
224
+ reset(): void;
225
+ /**
226
+ * Subscribe to state changes.
227
+ *
228
+ * @param listener - Function called on state changes
229
+ * @returns Unsubscribe function
230
+ *
231
+ * @example
232
+ * ```typescript
233
+ * const unsubscribe = store.subscribe((state) => console.log(state));
234
+ * unsubscribe();
235
+ * ```
236
+ */
237
+ subscribe(listener: Listener<TState>): () => void;
238
+ /**
239
+ * Subscribe to state changes with selector.
240
+ *
241
+ * @param selector - Function to extract state slice
242
+ * @param listener - Function called when selected value changes
243
+ * @param equalityFn - Optional custom equality function
244
+ * @returns Unsubscribe function
245
+ *
246
+ * @example
247
+ * ```typescript
248
+ * const unsubscribe = store.subscribe(
249
+ * (state) => state.count,
250
+ * (count) => console.log('Count:', count)
251
+ * );
252
+ * ```
253
+ */
254
+ subscribe<TSelected>(selector: Selector<TState, TSelected>, listener: Listener<TSelected>, equalityFn?: EqualityFn<TSelected>): () => void;
255
+ /**
256
+ * Register a plugin.
257
+ *
258
+ * @param plugin - The plugin to register
259
+ * @param options - Plugin-specific options
260
+ * @returns The store instance for chaining
261
+ *
262
+ * @example
263
+ * ```typescript
264
+ * store.use(persist({ key: 'app' }));
265
+ * ```
266
+ */
267
+ use<TPlugin extends Plugin<TState>>(plugin: TPlugin, options?: unknown): this;
268
+ /** Destroy store and cleanup all resources */
269
+ destroy(): void;
270
+ }
271
+ /**
272
+ * Store builder interface for fluent API.
273
+ *
274
+ * @typeParam TState - The store state type
275
+ *
276
+ * @example
277
+ * ```typescript
278
+ * createStore({ count: 0 })
279
+ * .action('increment', (s) => ({ count: s.count + 1 }))
280
+ * .action('decrement', (s) => ({ count: s.count - 1 }));
281
+ * ```
282
+ */
283
+ interface StoreBuilder<TState> extends Store<TState> {
284
+ /**
285
+ * Add an action to the store.
286
+ *
287
+ * @param name - Action name
288
+ * @param fn - Action function
289
+ * @returns The builder for chaining
290
+ */
291
+ action<K extends string>(name: K, fn: Action<TState & Record<K, Action<TState>>>): this;
292
+ }
293
+ /**
294
+ * Error codes for store errors.
295
+ */
296
+ declare enum StoreErrorCode {
297
+ /** Store was destroyed and cannot be used */
298
+ STORE_DESTROYED = "STORE_DESTROYED",
299
+ /** Plugin with same name already registered */
300
+ PLUGIN_EXISTS = "PLUGIN_EXISTS",
301
+ /** Required plugin dependency not found */
302
+ PLUGIN_DEPENDENCY_MISSING = "PLUGIN_DEPENDENCY_MISSING",
303
+ /** Invalid state update argument */
304
+ INVALID_STATE_UPDATE = "INVALID_STATE_UPDATE",
305
+ /** Action threw an error */
306
+ ACTION_ERROR = "ACTION_ERROR"
307
+ }
308
+ /**
309
+ * Store error class.
310
+ */
311
+ declare class StoreError extends Error {
312
+ code: StoreErrorCode;
313
+ constructor(code: StoreErrorCode, message: string);
314
+ }
315
+
316
+ /**
317
+ * Create a new reactive store.
318
+ *
319
+ * Supports three action definition styles:
320
+ * - **Inline**: Actions defined within state object (functions starting with $)
321
+ * - **Separate**: Actions passed as second argument
322
+ * - **Fluent**: Actions added via `.action()` method
323
+ *
324
+ * @typeParam TState - The type of the store state
325
+ * @param initialState - Initial state object, may include inline actions
326
+ * @param actions - Optional separate actions object
327
+ * @returns A new Store instance
328
+ *
329
+ * @example
330
+ * ```typescript
331
+ * // Style A: Inline actions (prefix with $)
332
+ * const store = createStore({
333
+ * count: 0,
334
+ * $increment: (state) => ({ count: state.count + 1 }),
335
+ * });
336
+ *
337
+ * // Style B: Separate actions
338
+ * const store = createStore(
339
+ * { count: 0 },
340
+ * { increment: (state) => ({ count: state.count + 1 }) }
341
+ * );
342
+ *
343
+ * // Style C: Fluent builder
344
+ * const store = createStore({ count: 0 })
345
+ * .action('increment', (state) => ({ count: state.count + 1 }));
346
+ * ```
347
+ */
348
+ declare function createStore<TState>(initialState: TState, actions?: Actions<TState>): Store<TState>;
349
+ /**
350
+ * Batch multiple state updates into a single notification.
351
+ *
352
+ * @param fn - Function containing state updates
353
+ * @returns The return value of fn
354
+ *
355
+ * @example
356
+ * ```typescript
357
+ * import { batch } from '@oxog/state';
358
+ *
359
+ * // Without batch - 3 re-renders
360
+ * store.setState({ a: 1 });
361
+ * store.setState({ b: 2 });
362
+ * store.setState({ c: 3 });
363
+ *
364
+ * // With batch - 1 re-render
365
+ * batch(() => {
366
+ * store.setState({ a: 1 });
367
+ * store.setState({ b: 2 });
368
+ * store.setState({ c: 3 });
369
+ * });
370
+ * ```
371
+ */
372
+ declare function batch<T>(fn: () => T): T;
373
+
374
+ /**
375
+ * React hook for subscribing to store state changes.
376
+ *
377
+ * Uses useSyncExternalStore for optimal performance and SSR compatibility.
378
+ *
379
+ * @typeParam TState - The store state type
380
+ * @typeParam TSelected - The selected state type
381
+ * @param store - The store instance
382
+ * @param selector - Optional selector to extract a slice of state
383
+ * @param equalityFn - Optional custom equality function
384
+ * @returns The selected state slice
385
+ *
386
+ * @example
387
+ * ```typescript
388
+ * import { createStore, useStore } from '@oxog/state';
389
+ *
390
+ * const store = createStore({
391
+ * count: 0,
392
+ * name: 'John',
393
+ * increment: (state) => ({ count: state.count + 1 }),
394
+ * });
395
+ *
396
+ * function Counter() {
397
+ * // Select entire state
398
+ * const state = useStore(store);
399
+ *
400
+ * // Select with selector
401
+ * const count = useStore(store, (state) => state.count);
402
+ *
403
+ * // Select with custom equality check
404
+ * const user = useStore(
405
+ * store,
406
+ * (state) => state.user,
407
+ * (a, b) => a?.id === b?.id
408
+ * );
409
+ *
410
+ * // Select action
411
+ * const increment = useStore(store, (state) => state.increment);
412
+ *
413
+ * return (
414
+ * <button onClick={increment}>
415
+ * Count: {count}
416
+ * </button>
417
+ * );
418
+ * }
419
+ * ```
420
+ */
421
+ declare function useStore<TState, TSelected = TState>(store: Store<TState>, selector?: Selector<TState, TSelected>, equalityFn?: EqualityFn<TSelected>): TSelected;
422
+ /**
423
+ * React hook for creating and using a store.
424
+ *
425
+ * Creates a store on first render and destroys it on unmount.
426
+ *
427
+ * @typeParam TState - The store state type
428
+ * @param initialState - The initial state
429
+ * @returns The store instance
430
+ *
431
+ * @example
432
+ * ```typescript
433
+ * import { useCreateStore } from '@oxog/state';
434
+ *
435
+ * function Component() {
436
+ * const store = useCreateStore({ count: 0 });
437
+ * const count = useStore(store, (s) => s.count);
438
+ *
439
+ * return <div>{count}</div>;
440
+ * }
441
+ * ```
442
+ */
443
+ declare function useCreateStore<TState>(initialState: TState): Store<TState>;
444
+ /**
445
+ * React hook for getting a store action.
446
+ *
447
+ * Convenience hook for selecting action functions from a store.
448
+ *
449
+ * @typeParam TState - The store state type
450
+ * @typeParam TAction - The action type
451
+ * @param store - The store instance
452
+ * @param actionName - The name of the action
453
+ * @returns The action function
454
+ *
455
+ * @example
456
+ * ```typescript
457
+ * import { createStore, useAction } from '@oxog/state';
458
+ *
459
+ * const store = createStore({
460
+ * count: 0,
461
+ * increment: (state) => ({ count: state.count + 1 }),
462
+ * decrement: (state) => ({ count: state.count - 1 }),
463
+ * });
464
+ *
465
+ * function Counter() {
466
+ * const increment = useAction(store, 'increment');
467
+ * const decrement = useAction(store, 'decrement');
468
+ * const count = useStore(store, (s) => s.count);
469
+ *
470
+ * return (
471
+ * <>
472
+ * <button onClick={decrement}>-</button>
473
+ * <span>{count}</span>
474
+ * <button onClick={increment}>+</button>
475
+ * </>
476
+ * );
477
+ * }
478
+ * ```
479
+ */
480
+ declare function useAction<TState, TAction extends (...args: any[]) => any>(store: Store<TState>, actionName: string): TAction;
481
+
482
+ /**
483
+ * Plugin-specific types and interfaces.
484
+ */
485
+
486
+ /**
487
+ * Persist plugin options.
488
+ */
489
+ interface PersistOptions<TState> {
490
+ /** Storage key */
491
+ key: string;
492
+ /** Storage implementation (defaults to localStorage) */
493
+ storage?: StorageLike;
494
+ /** List of state keys to persist (whitelist) */
495
+ whitelist?: Array<keyof TState>;
496
+ /** List of state keys to exclude (blacklist) */
497
+ blacklist?: Array<keyof TState>;
498
+ }
499
+ /**
500
+ * Storage interface for persistence.
501
+ */
502
+ interface StorageLike {
503
+ getItem(key: string): string | null;
504
+ setItem(key: string, value: string): void;
505
+ removeItem(key: string): void;
506
+ }
507
+ /**
508
+ * Devtools plugin options.
509
+ */
510
+ interface DevtoolsOptions {
511
+ /** Store name for DevTools */
512
+ name?: string;
513
+ /** Enable/disable DevTools */
514
+ enabled?: boolean;
515
+ /** Maximum number of states to keep in history */
516
+ maxAge?: number;
517
+ }
518
+ /**
519
+ * History plugin options.
520
+ */
521
+ interface HistoryOptions<TState> {
522
+ /** Maximum number of past states to keep */
523
+ limit?: number;
524
+ /** Keys to track for history (empty array tracks all) */
525
+ keys?: Array<keyof TState>;
526
+ }
527
+ /**
528
+ * Sync plugin options.
529
+ */
530
+ interface SyncOptions {
531
+ /** Channel name for BroadcastChannel */
532
+ channel?: string;
533
+ }
534
+ /**
535
+ * Selector plugin options.
536
+ */
537
+ interface SelectorOptions<TState> {
538
+ /** Map of computed selectors */
539
+ selectors: {
540
+ [K in keyof TState]?: (state: TState) => TState[K];
541
+ };
542
+ }
543
+ /**
544
+ * History-enabled store interface.
545
+ */
546
+ interface HistoryStore<TState> extends Store<TState> {
547
+ undo(): void;
548
+ redo(): void;
549
+ clearHistory(): void;
550
+ canUndo(): boolean;
551
+ canRedo(): boolean;
552
+ }
553
+
554
+ /**
555
+ * Persist plugin - Save and restore state from storage.
556
+ *
557
+ * Automatically persists state to localStorage, sessionStorage, or any
558
+ * storage implementation. State is restored on store creation.
559
+ *
560
+ * @example
561
+ * ```typescript
562
+ * import { createStore, persist } from '@oxog/state';
563
+ *
564
+ * const store = createStore({ count: 0, user: null })
565
+ * .use(persist({
566
+ * key: 'my-app',
567
+ * storage: localStorage,
568
+ * whitelist: ['count'] // Only persist count
569
+ * }));
570
+ * ```
571
+ */
572
+
573
+ /**
574
+ * SessionStorage implementation.
575
+ */
576
+ declare const sessionStorage: StorageLike;
577
+ /**
578
+ * Create a persist plugin.
579
+ *
580
+ * @param options - Plugin options
581
+ * @returns A persist plugin
582
+ *
583
+ * @example
584
+ * ```typescript
585
+ * import { persist, sessionStorage } from '@oxog/state';
586
+ *
587
+ * // Using localStorage (default)
588
+ * const store = createStore({ count: 0 })
589
+ * .use(persist({ key: 'counter' }));
590
+ *
591
+ * // Using sessionStorage
592
+ * const store = createStore({ count: 0 })
593
+ * .use(persist({ key: 'counter', storage: sessionStorage }));
594
+ *
595
+ * // With whitelist
596
+ * const store = createStore({ count: 0, temp: '' })
597
+ * .use(persist({ key: 'app', whitelist: ['count'] }));
598
+ *
599
+ * // With blacklist
600
+ * const store = createStore({ count: 0, temp: '' })
601
+ * .use(persist({ key: 'app', blacklist: ['temp'] }));
602
+ * ```
603
+ */
604
+ declare function persist<TState>(options: PersistOptions<TState>): Plugin<TState>;
605
+ /**
606
+ * Create a custom storage from a storage object.
607
+ *
608
+ * @param storage - Any object with getItem, setItem, removeItem
609
+ * @returns A StorageLike interface
610
+ *
611
+ * @example
612
+ * ```typescript
613
+ * import { createStorage } from '@oxog/state';
614
+ *
615
+ * const AsyncStorage = createStorage({
616
+ * getItem: async (key) => await AsyncStorage.getItem(key),
617
+ * setItem: async (key, value) => await AsyncStorage.setItem(key, value),
618
+ * removeItem: async (key) => await AsyncStorage.removeItem(key),
619
+ * });
620
+ * ```
621
+ */
622
+ declare function createStorage(storage: StorageLike): StorageLike;
623
+
624
+ /**
625
+ * Devtools plugin - Redux DevTools integration.
626
+ *
627
+ * Connects to Redux DevTools extension for debugging state changes.
628
+ *
629
+ * @example
630
+ * ```typescript
631
+ * import { createStore, devtools } from '@oxog/state';
632
+ *
633
+ * const store = createStore({ count: 0 })
634
+ * .use(devtools({ name: 'Counter' }));
635
+ * ```
636
+ */
637
+
638
+ /**
639
+ * Create a DevTools plugin.
640
+ *
641
+ * @param options - Plugin options
642
+ * @returns A DevTools plugin
643
+ *
644
+ * @example
645
+ * ```typescript
646
+ * import { devtools } from '@oxog/state';
647
+ *
648
+ * // Basic usage
649
+ * const store = createStore({ count: 0 })
650
+ * .use(devtools({ name: 'My Store' }));
651
+ *
652
+ * // Disabled in production
653
+ * const store = createStore({ count: 0 })
654
+ * .use(devtools({
655
+ * name: 'My Store',
656
+ * enabled: process.env.NODE_ENV === 'development'
657
+ * }));
658
+ * ```
659
+ */
660
+ declare function devtools<TState>(options?: DevtoolsOptions): Plugin<TState>;
661
+
662
+ /**
663
+ * History plugin - Undo/redo functionality.
664
+ *
665
+ * Tracks state changes and provides undo/redo methods.
666
+ *
667
+ * @example
668
+ * ```typescript
669
+ * import { createStore, history } from '@oxog/state';
670
+ *
671
+ * const store = createStore({ count: 0 })
672
+ * .use(history({ limit: 100 }));
673
+ *
674
+ * // Now store has undo() and redo() methods
675
+ * store.setState({ count: 1 });
676
+ * store.setState({ count: 2 });
677
+ * store.undo(); // { count: 1 }
678
+ * store.redo(); // { count: 2 }
679
+ * ```
680
+ */
681
+
682
+ /**
683
+ * Create a history plugin.
684
+ *
685
+ * @param options - Plugin options
686
+ * @returns A history plugin
687
+ *
688
+ * @example
689
+ * ```typescript
690
+ * import { history } from '@oxog/state';
691
+ *
692
+ * // Default options
693
+ * const store = createStore({ count: 0 })
694
+ * .use(history());
695
+ *
696
+ * // Custom limit
697
+ * const store = createStore({ count: 0 })
698
+ * .use(history({ limit: 50 }));
699
+ *
700
+ * // Track specific keys only
701
+ * const store = createStore({ count: 0, temp: '' })
702
+ * .use(history({ keys: ['count'] }));
703
+ * ```
704
+ */
705
+ declare function history<TState>(options?: HistoryOptions<TState>): Plugin<TState>;
706
+ /**
707
+ * Check if a store has history capabilities.
708
+ *
709
+ * @param store - The store to check
710
+ * @returns true if store supports undo/redo
711
+ *
712
+ * @example
713
+ * ```typescript
714
+ * import { hasHistory } from '@oxog/state';
715
+ *
716
+ * if (hasHistory(store)) {
717
+ * store.undo();
718
+ * store.redo();
719
+ * }
720
+ * ```
721
+ */
722
+ declare function hasHistory<TState>(store: Store<TState>): store is HistoryStore<TState>;
723
+
724
+ /**
725
+ * Sync plugin - Cross-tab state synchronization.
726
+ *
727
+ * Synchronizes state across browser tabs using BroadcastChannel API.
728
+ *
729
+ * @example
730
+ * ```typescript
731
+ * import { createStore, sync } from '@oxog/state';
732
+ *
733
+ * const store = createStore({ count: 0 })
734
+ * .use(sync({ channel: 'my-app-state' }));
735
+ *
736
+ * // State changes will sync across all tabs
737
+ * ```
738
+ */
739
+
740
+ /**
741
+ * Create a sync plugin.
742
+ *
743
+ * @param options - Plugin options
744
+ * @returns A sync plugin
745
+ *
746
+ * @example
747
+ * ```typescript
748
+ * import { sync } from '@oxog/state';
749
+ *
750
+ * // Default channel name
751
+ * const store = createStore({ count: 0 })
752
+ * .use(sync());
753
+ *
754
+ * // Custom channel name
755
+ * const store = createStore({ count: 0 })
756
+ * .use(sync({ channel: 'my-app' }));
757
+ * ```
758
+ */
759
+ declare function sync<TState>(options?: SyncOptions): Plugin<TState>;
760
+ /**
761
+ * Manually trigger a sync broadcast.
762
+ *
763
+ * @param store - The store to sync
764
+ * @param channel - The channel to broadcast on
765
+ *
766
+ * @example
767
+ * ```typescript
768
+ * import { createStore, sync, triggerSync } from '@oxog/state';
769
+ *
770
+ * const store = createStore({ count: 0 })
771
+ * .use(sync({ channel: 'my-app' }));
772
+ *
773
+ * // Manually trigger sync
774
+ * triggerSync(store, 'my-app');
775
+ * ```
776
+ */
777
+ declare function triggerSync<TState>(store: Store<TState>, channel?: string): void;
778
+
779
+ /**
780
+ * Immer plugin - Immutable updates with mutable syntax.
781
+ *
782
+ * Uses Proxy to enable writing immutable state updates with mutable syntax.
783
+ *
784
+ * @example
785
+ * ```typescript
786
+ * import { createStore, immer } from '@oxog/state';
787
+ *
788
+ * const store = createStore({
789
+ * users: [{ name: 'John', age: 30 }]
790
+ * }).use(immer());
791
+ *
792
+ * // Now you can write mutable-style updates
793
+ * store.setState((draft) => {
794
+ * draft.users[0].age = 31; // Mutate draft directly
795
+ * });
796
+ * ```
797
+ */
798
+
799
+ /**
800
+ * Produce a new state by applying mutations to a draft.
801
+ *
802
+ * @param base - The base state
803
+ * @param recipe - The mutation function
804
+ * @returns The new state
805
+ *
806
+ * @example
807
+ * ```typescript
808
+ * import { produce } from '@oxog/state';
809
+ *
810
+ * const state = { users: [{ name: 'John', age: 30 }] };
811
+ * const newState = produce(state, (draft) => {
812
+ * draft.users[0].age = 31;
813
+ * });
814
+ * ```
815
+ */
816
+ declare function produce<T>(base: T, recipe: (draft: T) => void): T;
817
+ /**
818
+ * Create an immer plugin.
819
+ *
820
+ * @returns An immer plugin
821
+ *
822
+ * @example
823
+ * ```typescript
824
+ * import { createStore, immer } from '@oxog/state';
825
+ *
826
+ * const store = createStore({
827
+ * items: [{ id: 1, name: 'Item 1' }]
828
+ * }).use(immer());
829
+ *
830
+ * // Now setState can accept a mutable recipe function
831
+ * store.setState((draft) => {
832
+ * draft.items[0].name = 'Updated Item';
833
+ * draft.items.push({ id: 2, name: 'Item 2' });
834
+ * });
835
+ * ```
836
+ */
837
+ declare function immer<TState>(): Plugin<TState>;
838
+
839
+ /**
840
+ * Selector plugin - Computed/derived values.
841
+ *
842
+ * Define computed values that automatically update when dependencies change.
843
+ *
844
+ * @example
845
+ * ```typescript
846
+ * import { createStore, selector } from '@oxog/state';
847
+ *
848
+ * const store = createStore({
849
+ * items: [],
850
+ * filter: 'all',
851
+ * })
852
+ * .use(selector({
853
+ * // Computed: filtered items
854
+ * filteredItems: (state) => {
855
+ * if (state.filter === 'all') return state.items;
856
+ * return state.items.filter((item: any) => item.status === state.filter);
857
+ * },
858
+ * // Computed: item count
859
+ * itemCount: (state) => state.items.length,
860
+ * }));
861
+ *
862
+ * // Access computed values
863
+ * const state = store.getState();
864
+ * console.log(state.filteredItems); // Computed value
865
+ * ```
866
+ */
867
+
868
+ /**
869
+ * Create a selector plugin for computed values.
870
+ *
871
+ * @param options - Plugin options with selectors
872
+ * @returns A selector plugin
873
+ *
874
+ * @example
875
+ * ```typescript
876
+ * import { selector } from '@oxog/state';
877
+ *
878
+ * const store = createStore({
879
+ * items: [{ price: 10 }, { price: 20 }],
880
+ * taxRate: 0.1,
881
+ * })
882
+ * .use(selector({
883
+ * // Computed total
884
+ * total: (state) =>
885
+ * state.items.reduce((sum: number, item: any) => sum + item.price, 0),
886
+ *
887
+ * // Computed total with tax
888
+ * totalWithTax: (state) => {
889
+ * const total = state.items.reduce((sum: number, item: any) => sum + item.price, 0);
890
+ * return total * (1 + state.taxRate);
891
+ * },
892
+ * }));
893
+ * ```
894
+ */
895
+ declare function selector<TState>(options: SelectorOptions<TState>): Plugin<TState>;
896
+
897
+ /**
898
+ * Deep clone a value, creating copies of nested objects and arrays.
899
+ *
900
+ * Handles:
901
+ * - Primitives (returned as-is)
902
+ * - null and undefined (returned as-is)
903
+ * - Date objects
904
+ * - Arrays
905
+ * - Plain objects
906
+ * - Circular references
907
+ * - Other objects (returned as-is, not cloned)
908
+ *
909
+ * @typeParam T - The type to clone
910
+ * @param value - The value to clone
911
+ * @param seen - Internal map for tracking circular references
912
+ * @returns A deep clone of the value
913
+ *
914
+ * @example
915
+ * ```typescript
916
+ * const original = { a: 1, b: { c: 2 } };
917
+ * const cloned = deepClone(original);
918
+ * cloned.b.c = 3;
919
+ * console.log(original.b.c); // 2 (unchanged)
920
+ * ```
921
+ */
922
+ declare function deepClone<T>(value: T, seen?: WeakMap<object, unknown>): T;
923
+
924
+ /**
925
+ * Deep equality check for two values.
926
+ *
927
+ * Recursively compares objects and arrays.
928
+ * Uses Object.is for primitive comparison.
929
+ *
930
+ * @param a - First value
931
+ * @param b - Second value
932
+ * @returns true if values are deeply equal
933
+ *
934
+ * @example
935
+ * ```typescript
936
+ * deepEqual(1, 1); // true
937
+ * deepEqual({ a: { b: 1 } }, { a: { b: 1 } }); // true
938
+ * deepEqual({ a: { b: 1 } }, { a: { b: 2 } }); // false
939
+ * deepEqual([1, 2], [1, 2]); // true
940
+ * deepEqual([1, 2], [1, 2, 3]); // false
941
+ * ```
942
+ */
943
+ declare function deepEqual(a: unknown, b: unknown): boolean;
944
+
945
+ /**
946
+ * Shallow equality check for two values.
947
+ *
948
+ * Uses Object.is for comparison, which handles NaN correctly
949
+ * and distinguishes between +0 and -0.
950
+ *
951
+ * @param a - First value
952
+ * @param b - Second value
953
+ * @returns true if values are shallowly equal
954
+ *
955
+ * @example
956
+ * ```typescript
957
+ * shallowEqual(1, 1); // true
958
+ * shallowEqual({ a: 1 }, { a: 1 }); // true
959
+ * shallowEqual({ a: 1 }, { a: 2 }); // false
960
+ * shallowEqual(NaN, NaN); // true
961
+ * ```
962
+ */
963
+ declare function shallowEqual(a: unknown, b: unknown): boolean;
964
+
965
+ /**
966
+ * Deep merge a partial object into a target object.
967
+ *
968
+ * Creates a new object with nested objects merged recursively.
969
+ * Arrays are replaced, not merged.
970
+ *
971
+ * @typeParam T - The target type
972
+ * @param target - The target object
973
+ * @param source - The partial source to merge
974
+ * @returns A new merged object
975
+ *
976
+ * @example
977
+ * ```typescript
978
+ * const target = { a: 1, b: { c: 2, d: 3 } };
979
+ * const source = { b: { c: 10 }, e: 4 };
980
+ * const merged = deepMerge(target, source);
981
+ * // { a: 1, b: { c: 10, d: 3 }, e: 4 }
982
+ * ```
983
+ */
984
+
985
+ declare function deepMerge<T>(target: T, source: Partial<T> | DeepPartial<T>): T;
986
+
987
+ /**
988
+ * Type guard to check if a value is a function.
989
+ *
990
+ * @param value - The value to check
991
+ * @returns true if the value is a function
992
+ *
993
+ * @example
994
+ * ```typescript
995
+ * const value: unknown = () => {};
996
+ * if (isFunction(value)) {
997
+ * value(); // TypeScript knows this is a function
998
+ * }
999
+ * ```
1000
+ */
1001
+ declare function isFunction(value: unknown): value is (...args: any[]) => any;
1002
+
1003
+ /**
1004
+ * Pick specified properties from an object.
1005
+ *
1006
+ * Creates a new object with only the specified keys.
1007
+ *
1008
+ * @typeParam T - The object type
1009
+ * @typeParam K - The keys to pick
1010
+ * @param obj - The source object
1011
+ * @param keys - The keys to pick
1012
+ * @returns A new object with only the picked keys
1013
+ *
1014
+ * @example
1015
+ * ```typescript
1016
+ * const user = { name: 'John', age: 30, city: 'NYC' };
1017
+ * const picked = pick(user, ['name', 'age']);
1018
+ * // { name: 'John', age: 30 }
1019
+ * ```
1020
+ */
1021
+ declare function pick<T extends object, K extends keyof T>(obj: T, keys: readonly K[]): Pick<T, K>;
1022
+
1023
+ /**
1024
+ * Omit specified properties from an object.
1025
+ *
1026
+ * Creates a new object without the specified keys.
1027
+ *
1028
+ * @typeParam T - The object type
1029
+ * @typeParam K - The keys to omit
1030
+ * @param obj - The source object
1031
+ * @param keys - The keys to omit
1032
+ * @returns A new object without the omitted keys
1033
+ *
1034
+ * @example
1035
+ * ```typescript
1036
+ * const user = { name: 'John', age: 30, city: 'NYC' };
1037
+ * const omitted = omit(user, ['age', 'city']);
1038
+ * // { name: 'John' }
1039
+ * ```
1040
+ */
1041
+ declare function omit<T extends object, K extends keyof T>(obj: T, keys: readonly K[]): Omit<T, K>;
1042
+
1043
+ /**
1044
+ * Identity function that returns its input.
1045
+ *
1046
+ * Useful as a default selector when no transformation is needed.
1047
+ *
1048
+ * @typeParam T - The value type
1049
+ * @param value - The value to return
1050
+ * @returns The same value
1051
+ *
1052
+ * @example
1053
+ * ```typescript
1054
+ * const selector = identity;
1055
+ * selector(42); // 42
1056
+ * selector('hello'); // 'hello'
1057
+ * ```
1058
+ */
1059
+ declare function identity<T>(value: T): T;
1060
+
1061
+ export { type Action, type Actions, type DeepPartial, type DevtoolsOptions, type EqualityFn, type HistoryOptions, type HistoryStore, type Listener, type PersistOptions, type Plugin, type Selector, type SelectorOptions, type StorageLike$1 as StorageLike, type Store, type StoreBuilder, StoreError, StoreError as StoreErrorClass, StoreErrorCode, type StoreOptions, type SyncOptions, batch, createStorage, createStore, deepClone, deepEqual, deepMerge, devtools, hasHistory, history, identity, immer, isFunction, omit, persist, pick, produce, selector, sessionStorage, shallowEqual, sync, triggerSync, useAction, useCreateStore, useStore };