@superutils/store 0.1.18 → 0.1.20

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/dist/index.d.ts CHANGED
@@ -1,48 +1,6 @@
1
- import { Subject, BehaviorSubject } from 'rxjs';
2
1
  import { ThrottleOptions, DebounceOptions, sort, SortOptions, DropFirst, search, ValueOrPromise, filter, FindOptions, find, TypedMap } from '@superutils/core';
3
2
  export { TypedMap, objToMap } from '@superutils/core';
4
-
5
- /**
6
- * Literal union of all operations that can be intercepted by a validator.
7
- */
8
- type Store_ValidateAction = 'clear' | 'delete' | 'set' | 'setAll' | 'write';
9
- /**
10
- * Function signature for an operation-specific validation hook.
11
- *
12
- * **Behavior:**
13
- * - Invoked immediately before the store's internal state is updated.
14
- * - If validation fails (throw error), the write operation is aborted and error is propagated to the caller.
15
- *
16
- * @param params - The specific payload for the action:
17
- * - `clear`: `[]`
18
- * - `delete`: `[keys: Key[]]`
19
- * - `set`: `[key: Key, value: Value]`
20
- * - `setAll`: `[data: Map<Key, Value>, replace: boolean]`
21
- * - 'write': `[data: Map<Key, Value>]`
22
- * @param action - The literal name of the action being performed.
23
- *
24
- * @template Key - The type of keys in the store.
25
- * @template Value - The type of values in the store.
26
- * @template CacheDisabled - Whether caching is disabled.
27
- */
28
- type Store_ValidateFn<Key, Value, CacheDisabled extends boolean, Action extends keyof IStore<Key, Value> & Store_ValidateAction> = (this: IStore<Key, Value, CacheDisabled>, params: 'clear' extends Action ? [] : 'delete' extends Action ? [keys: Key[]] : 'set' extends Action ? [key: Key, value: Value] : 'setAll' extends Action ? [data?: Map<Key, Value>, replace?: boolean] : 'write' extends Action ? [data: Map<Key, Value>] : [], action: Action) => void | undefined | boolean;
29
- /**
30
- * A configuration object containing optional validation hooks for specific store operations.
31
- *
32
- * This structure allows for granular control over write operations, enabling you
33
- * to define custom logic to intercept and prevent invalid state updates.
34
- *
35
- * @template Key - The type of keys in the store.
36
- * @template Value - The type of values in the store.
37
- * @template CacheDisabled - Whether caching is disabled for the store.
38
- */
39
- type Store_Validate<Key, Value, CacheDisabled extends boolean> = {
40
- clear?: Store_ValidateFn<Key, Value, CacheDisabled, 'clear'>;
41
- delete?: Store_ValidateFn<Key, Value, CacheDisabled, 'delete'>;
42
- set?: Store_ValidateFn<Key, Value, CacheDisabled, 'set'>;
43
- setAll?: Store_ValidateFn<Key, Value, CacheDisabled, 'setAll'>;
44
- write?: Store_ValidateFn<Key, Value, CacheDisabled, 'write'>;
45
- };
3
+ import { Subject, BehaviorSubject } from 'rxjs';
46
4
 
47
5
  /**
48
6
  * Represents the minimal subset of the `Storage` interface required for persistence.
@@ -85,34 +43,6 @@ declare enum Store_OnErrorType {
85
43
  /** Occurs when the attempt to save data to the underlying storage (e.g., `localStorage.setItem`) fails. */
86
44
  write = "write"
87
45
  }
88
- /**
89
- * Configuration options for initializing a {@link Store} or {@link ObjectStore}.
90
- *
91
- * These options define the behavior of caching, persistence, error handling, and validation.
92
- */
93
- type Store_Options<Key, Value, CacheDisabled extends boolean = false> = {
94
- /**
95
- * An optional `Map` used to seed the storage if no persistent data is found for the instance.
96
- *
97
- * **Data Precedence:**
98
- * Persistent data associated with the instance's specific `name` takes priority. This value is
99
- * only utilized if the storage entry for that `name` does not exist (e.g., first-time use).
100
- *
101
- * **Initialization Behavior:**
102
- * - If provided and non-empty, the instance initializes immediately during construction.
103
- * - Otherwise, initialization is lazy, occurring upon an explicit `init()` call or the first read/write operation.
104
- *
105
- * **Type Inference:**
106
- * When provided, it enables automatic inference of the `Key` and `Value` generic types.
107
- * If omitted, these default to `unknown` and `object` respectively, unless explicitly defined.
108
- *
109
- * Default: `undefined`
110
- */
111
- initialValue?: Map<Key, Value>;
112
- } & Pick<Partial<IStore<Key, Value, CacheDisabled>>, 'cacheDisabled' | 'onChange' | 'onError' | 'parse' | 'spaces' | 'storage' | 'stringify' | 'validate'> & (CacheDisabled extends false ? Pick<Partial<IStore<Key, Value, CacheDisabled>>, 'delay' | 'delayOptions'> : {
113
- delay?: never;
114
- delayOptions?: never;
115
- });
116
46
  /**
117
47
  * Function signature for custom data deserialization.
118
48
  *
@@ -171,6 +101,36 @@ type Store_Stringify<Data, ThisArg> = (this: ThisArg, data: Data) => string | un
171
101
  */
172
102
  type Store_ToJSON<K, V> = (replacer?: null | ((key: K, value: V) => unknown), spacing?: string | number, data?: Map<K, V>) => string;
173
103
 
104
+ /** Store properties accepted in {@link Store_Options} */
105
+ type Store_OptionKeys = 'cacheDisabled' | 'name' | 'onChange' | 'onError' | 'parse' | 'spaces' | 'storage' | 'stringify' | 'validate';
106
+ /**
107
+ * Configuration options for initializing {@link IStore} instances.
108
+ *
109
+ * These options define the behavior of caching, persistence, error handling, and validation.
110
+ */
111
+ type Store_Options<Key = unknown, Value = unknown, CacheDisabled extends boolean = false> = {
112
+ /**
113
+ * An optional `Map` used to seed the storage if no persistent data is found for the instance.
114
+ *
115
+ * **Data Precedence:**
116
+ * Persistent data associated with the instance's specific `name` takes priority. This value is
117
+ * only utilized if the storage entry for that `name` does not exist (e.g., first-time use).
118
+ *
119
+ * **Initialization Behavior:**
120
+ * - If provided and non-empty, the instance initializes immediately during construction.
121
+ * - Otherwise, initialization is lazy, occurring upon an explicit `init()` call or the first read/write operation.
122
+ *
123
+ * **Type Inference:**
124
+ * When provided, it enables automatic inference of the `Key` and `Value` generic types.
125
+ * If omitted, these default to `unknown` and `object` respectively, unless explicitly defined.
126
+ *
127
+ * Default: `undefined`
128
+ */
129
+ initialValue?: Map<Key, Value>;
130
+ } & Partial<Pick<IStore<Key, Value, CacheDisabled>, Store_OptionKeys> & (CacheDisabled extends false ? Pick<IStore<Key, Value, CacheDisabled>, 'delay' | 'delayOptions'> : {
131
+ delay?: never;
132
+ delayOptions?: never;
133
+ })>;
174
134
  /**
175
135
  * Represents a generic, reactive, and persistent Map-like data store.
176
136
  *
@@ -186,9 +146,9 @@ type Store_ToJSON<K, V> = (replacer?: null | ((key: K, value: V) => unknown), sp
186
146
  * @template CacheDisabled - A boolean flag; if `true`, the store operates without an in-memory cache,
187
147
  * reading and writing directly to the underlying storage on every operation.
188
148
  */
189
- interface IStore<Key, Value, CacheDisabled extends boolean = false> {
149
+ interface IStore<Key, Value, CD extends boolean = false> {
190
150
  /** Disable in-memory cache and only directly read/write from storage (local storage or JSON fle) */
191
- readonly cacheDisabled: CacheDisabled;
151
+ readonly cacheDisabled: CD;
192
152
  /**
193
153
  * Debounce/throttle delay duration in milliseconds for writing to storage when caching is enabled.
194
154
  *
@@ -220,7 +180,7 @@ interface IStore<Key, Value, CacheDisabled extends boolean = false> {
220
180
  * Note: Execution of this callback is managed by internal subscriptions and will stop
221
181
  * firing once {@link unsubscribe} is called.
222
182
  */
223
- onChange?: (this: IStore<Key, Value, CacheDisabled>, data: Map<Key, Value>) => ValueOrPromise<void | Map<Key, Value>>;
183
+ onChange?: (this: IStore<Key, Value, CD>, data: Map<Key, Value>) => ValueOrPromise<void | Map<Key, Value>>;
224
184
  /**
225
185
  * A global error handler invoked whenever an internal operation fails.
226
186
  *
@@ -232,7 +192,7 @@ interface IStore<Key, Value, CacheDisabled extends boolean = false> {
232
192
  * **Note:** If this handler itself throws an error, the exception is
233
193
  * ignored gracefully to prevent application crashes during storage cycles.
234
194
  */
235
- onError?: (this: IStore<Key, Value, CacheDisabled>, err: unknown, type: Store_OnErrorType) => ValueOrPromise<void>;
195
+ onError?: (this: IStore<Key, Value, CD>, err: unknown, type: Store_OnErrorType) => ValueOrPromise<void>;
236
196
  /**
237
197
  * A callback to customize the deserialization of data read from storage.
238
198
  *
@@ -249,7 +209,7 @@ interface IStore<Key, Value, CacheDisabled extends boolean = false> {
249
209
  * - If this custom `parse` function fails: {@link onError} is triggered with {@link Store_OnErrorType.parse}.
250
210
  * - If the default `JSON.parse` fallback fails: {@link onError} is triggered with {@link Store_OnErrorType.parse_json}.
251
211
  */
252
- parse?: Store_Parse<Map<Key, Value>, IStore<Key, Value, CacheDisabled>>;
212
+ parse?: Store_Parse<Map<Key, Value>, IStore<Key, Value, CD>>;
253
213
  /** Get the number of items */
254
214
  readonly size: number;
255
215
  /** Number of spaces to use when stringifying. Default: `undefined` */
@@ -312,16 +272,15 @@ interface IStore<Key, Value, CacheDisabled extends boolean = false> {
312
272
  * const storage = new Store('users', { stringify })
313
273
  * ```
314
274
  */
315
- stringify?: Store_Stringify<Map<Key, Value>, IStore<Key, Value, CacheDisabled>>;
275
+ stringify?: Store_Stringify<Map<Key, Value>, IStore<Key, Value, CD>>;
316
276
  /**
317
277
  * Indicates type of data parsed as
318
278
  *
319
279
  * Default: 'map'
320
280
  */
321
281
  type: string;
322
- validate?: Store_Validate<Key, Value, CacheDisabled>;
323
282
  /**
324
- * The underlying RxJS Subject that serves as the primary reactive interface for observing data modifications.
283
+ * The underlying RxJS subject that serves as the primary reactive interface for observing data modifications.
325
284
  *
326
285
  * Its implementation type is determined by the caching strategy:
327
286
  * - **BehaviorSubject**: Used when caching is enabled.
@@ -329,15 +288,15 @@ interface IStore<Key, Value, CacheDisabled extends boolean = false> {
329
288
  * - **Subject**: Used when caching is disabled.
330
289
  * It acts as a pure event pipe, emitting updates only at the moment they occur without retaining an in-memory copy.
331
290
  */
332
- readonly subject$: CacheDisabled extends true ? Subject<Map<Key, Value>> : BehaviorSubject<Map<Key, Value>>;
291
+ readonly subject$: CD extends true ? Subject<Map<Key, Value>> : BehaviorSubject<Map<Key, Value>>;
333
292
  /** Clear all items */
334
- readonly clear: () => IStore<Key, Value, CacheDisabled>;
293
+ readonly clear: () => IStore<Key, Value, CD>;
335
294
  /** Delete one or more items by their respective keys */
336
- readonly delete: (key: Key | Key[]) => IStore<Key, Value, CacheDisabled>;
295
+ readonly delete: (key: Key | Key[]) => IStore<Key, Value, CD>;
337
296
  /** Filter items by predicate */
338
297
  readonly filter: <AsArray extends boolean = false>(...args: DropFirst<Parameters<typeof filter<Key, Value, AsArray>>>) => ReturnType<typeof filter<Key, Value, AsArray>>;
339
298
  /** Find an item by predicate or search criteria */
340
- readonly find: <IncludeKey extends boolean = false>(predicateOrOptions: FindOptions<Key, Value, IncludeKey> | Parameters<IStore<Key, Value, CacheDisabled>['filter']>[0]) => ReturnType<typeof find<Key, Value, IncludeKey>>;
299
+ readonly find: <IncludeKey extends boolean = false>(predicateOrOptions: FindOptions<Key, Value, IncludeKey> | Parameters<IStore<Key, Value, CD>['filter']>[0]) => ReturnType<typeof find<Key, Value, IncludeKey>>;
341
300
  /** Get item by key */
342
301
  readonly get: (key: Key) => Value | undefined;
343
302
  /**
@@ -421,7 +380,7 @@ interface IStore<Key, Value, CacheDisabled extends boolean = false> {
421
380
  * store.set('count', (prevCount = 0) => prevCount + 1)
422
381
  * ```
423
382
  */
424
- readonly set: (key: Key, value: Value | ((currentValue?: Value) => Value)) => IStore<Key, Value, CacheDisabled>;
383
+ readonly set: (key: Key, value: Value | ((currentValue?: Value) => Value)) => IStore<Key, Value, CD>;
425
384
  /**
426
385
  * Set multiple entries at once and/or replace the storage entries
427
386
  *
@@ -432,7 +391,7 @@ interface IStore<Key, Value, CacheDisabled extends boolean = false> {
432
391
  *
433
392
  * Default: `false`
434
393
  */
435
- readonly setAll: (data?: Map<Key, Value>, replace?: boolean) => IStore<Key, Value, CacheDisabled>;
394
+ readonly setAll: (data?: Map<Key, Value>, replace?: boolean) => IStore<Key, Value, CD>;
436
395
  /**
437
396
  * Sort items in the storage.
438
397
  *
@@ -473,40 +432,400 @@ interface IStore<Key, Value, CacheDisabled extends boolean = false> {
473
432
  * - If not provided, the current in-memory data is used (if cache is enabled).
474
433
  * @returns `true` if the write was successful, `false` otherwise.
475
434
  */
476
- readonly write: (data?: Map<Key, Value>) => void;
435
+ readonly write: (data?: Map<Key, Value>) => boolean;
477
436
  }
478
437
 
479
- interface IObjectStore<T extends object, CacheDisabled extends boolean = false, ObjectMap extends TypedMap<T> = TypedMap<T>> extends IStore<keyof T, T[keyof T], CacheDisabled> {
438
+ /** Utility to exclude store props & o in context */
439
+ type ContextExcludeProps<Context> = Context extends object ? {
440
+ [K in keyof Context]: K extends keyof IStore<any, any, any> ? never : Context[K];
441
+ } : never;
442
+ /** Extract context return type */
443
+ type ContextReturn<Context> = Context extends (...args: any[]) => infer R ? R : Context extends object ? Context : unknown;
444
+ /** Validate and exclude store properties from context */
445
+ type ContextValidate<Context, Store> = Context extends (...args: unknown[]) => infer R ? (store: Store) => ContextExcludeProps<R> : ContextExcludeProps<Context>;
446
+
447
+ interface IObjectStore<T extends object = object, CacheDisabled extends boolean = false> extends IStore<keyof T, T[keyof T], CacheDisabled> {
480
448
  /**
481
449
  * Default: `object`
482
450
  */
483
451
  type: string;
484
452
  get<Key extends keyof T>(key: Key): T[Key] | undefined;
485
453
  getAll(forceRead?: boolean): TypedMap<T>;
486
- parse?: Store_Parse<ObjectMap, IObjectStore<T, CacheDisabled>>;
454
+ parse?: Store_Parse<TypedMap<T>, IObjectStore<T, CacheDisabled>>;
487
455
  set<Key extends keyof T, Value extends T[Key]>(key: Key, value: Value | ((currentValue?: Value) => Value)): IObjectStore<T, CacheDisabled>;
488
- setAll(data?: ObjectMap, replace?: boolean): IObjectStore<T, CacheDisabled>;
489
- stringify?: Store_Stringify<ObjectMap, IObjectStore<T, CacheDisabled>>;
490
- toObject<O extends object = T>(data?: Map<keyof T, T[keyof T]>): O;
456
+ setAll(data?: T | TypedMap<T>, replace?: boolean): IObjectStore<T, CacheDisabled>;
457
+ stringify?: Store_Stringify<TypedMap<T>, IObjectStore<T, CacheDisabled>>;
458
+ /** Convert data/object to typed map */
459
+ toMap(data?: T): TypedMap<T>;
460
+ toObject<O extends object = T>(data?: Map<keyof T, T[keyof T]> | TypedMap<T>): O;
461
+ }
462
+ /**
463
+ * Configuration options for initializing {@link IStore} instances.
464
+ *
465
+ * These options define the behavior of caching, persistence, error handling, and validation.
466
+ */
467
+ type ObjectStore_Options<T extends object = Record<PropertyKey, unknown>, CacheDisabled extends boolean = false> = {
468
+ /**
469
+ * An optional `Map` used to seed the storage if no persistent data is found for the instance.
470
+ *
471
+ * **Data Precedence:**
472
+ * Persistent data associated with the instance's specific `name` takes priority. This value is
473
+ * only utilized if the storage entry for that `name` does not exist (e.g., first-time use).
474
+ *
475
+ * **Initialization Behavior:**
476
+ * - If provided and non-empty, the instance initializes immediately during construction.
477
+ * - Otherwise, initialization is lazy, occurring upon an explicit `init()` call or the first read/write operation.
478
+ *
479
+ * **Type Inference:**
480
+ * When provided, it enables automatic inference of the `Key` and `Value` generic types.
481
+ * If omitted, these default to `unknown` and `object` respectively, unless explicitly defined.
482
+ *
483
+ * Default: `undefined`
484
+ */
485
+ initialValue?: T;
486
+ } & Partial<Pick<IObjectStore<T, CacheDisabled>, Store_OptionKeys> & (CacheDisabled extends false ? Pick<IObjectStore<T, CacheDisabled>, 'delay' | 'delayOptions'> : {
487
+ delay?: never;
488
+ delayOptions?: never;
489
+ })>;
490
+
491
+ declare module './IStore' {
492
+ interface IStore<Key, Value, CD extends boolean = false> {
493
+ /**
494
+ * A configuration object containing optional validation hooks for specific store operations.
495
+ *
496
+ * This structure allows for granular control over write operations, enabling you
497
+ * to define custom logic to intercept and prevent invalid state updates.
498
+ *
499
+ * **Behavior:**
500
+ * - Invoked immediately before the store's internal state is updated.
501
+ * - If validation fails (throw error), the operation is aborted and the error is propagated to the caller.
502
+ * - The `write` validator is invoked during every persistence cycle, serving as a final check
503
+ * after operation-specific hooks (e.g., `set` or `delete`).
504
+ * - For reference-type values (e.g., Objects, Maps, Arrays), validators can be used to mutate the data
505
+ * (e.g., for normalization) before it is committed.
506
+ * - `thisArg`: all validators are bound to the store instance.
507
+ *
508
+ * @example
509
+ * ```javascript
510
+ * import { createObjectStore } from '@superutils/store'
511
+ *
512
+ * const settingsStore = createObjectStore({
513
+ * name: 'app-settings',
514
+ * initialValue: {
515
+ * theme: 'light',
516
+ * version: '1.0.0',
517
+ * },
518
+ * validate: {
519
+ * set([key, value]) {
520
+ * console.log(this.size) // "this" refers to the store instance
521
+ * if (key !== 'theme' || ['light', 'dark', 'system'].includes(value)) return
522
+ *
523
+ * // throw error to abort operation
524
+ * throw new Error(`Invalid theme: ${value}`)
525
+ * },
526
+ * delete: ([keys]) => {
527
+ * if (!keys.includes('version')) return
528
+ *
529
+ * throw new Error('The "version" key is protected and cannot be deleted')
530
+ * },
531
+ * },
532
+ * })
533
+ *
534
+ * settingsStore.set('theme', 'system')
535
+ * console.log(settingsStore.get('theme')) // 'system'
536
+ * try {
537
+ * settingsStore.set('theme', 'invalid') // throws error
538
+ * } catch (err) {
539
+ * console.error(err.message)
540
+ * }
541
+ * ```
542
+ */
543
+ validate?: Store_Validate<Key, Value, CD>;
544
+ }
491
545
  }
492
546
  /**
493
- * Defines the shape of the context object that can be attached to {@link IObjectStore} instance.
547
+ * A configuration object containing optional validation hooks for specific store operations.
494
548
  *
495
- * A context can be:
496
- * - A plain object containing utility methods or properties.
497
- * - A factory function that receives the {@link IObjectStore} instance and returns an object.
498
- * This is useful for creating methods that need to interact with the store's data
499
- * using the store instance itself.
549
+ * See {@link IStore.validate} or inidivdual actions for more details.
500
550
  *
501
551
  * @template Key - The type of keys in the store.
502
552
  * @template Value - The type of values in the store.
503
- * @template CacheDisabled - Whether caching is disabled for this store.
553
+ * @template CacheDisabled - Whether caching is disabled for the store.
504
554
  */
505
- type ObjectStore_Context<T extends object, CacheDisabled extends boolean = false> = object | ((store: IObjectStore<T, CacheDisabled>) => object);
506
- type ObjectStore_Options<T extends object, CacheDisabled extends boolean, Context extends ObjectStore_Context<T, CacheDisabled>> = Omit<Store_Options<keyof T, T[keyof T], CacheDisabled>, 'initialValue'> & {
507
- context?: Context;
508
- initialValue?: T;
555
+ type Store_Validate<Key, Value, CacheDisabled extends boolean, ThisArg extends IStore<Key, Value, CacheDisabled> = IStore<Key, Value, CacheDisabled>> = {
556
+ /**
557
+ * Validator for the `clear()` operation.
558
+ * Invoked before all entries are removed from the store.
559
+ *
560
+ * **Throw an error to invalidate and abort the operation.**
561
+ *
562
+ * @param actionParams - Empty array for this action.
563
+ * @param action - The literal action name: `'clear'`.
564
+ */
565
+ clear?: (this: ThisArg, actionParams: [], action: 'clear') => void;
566
+ /**
567
+ * Validator for the `delete()` operation.
568
+ * Invoked before one or more entries are removed by their keys.
569
+ *
570
+ * **Throw an error to invalidate and abort the operation.**
571
+ *
572
+ * @param actionParams - Tuple containing the array of keys: `[keys: Key[]]`.
573
+ * @param action - The literal action name: `'delete'`.
574
+ */
575
+ delete?: (this: ThisArg, actionParams: [keys: Key[]], action: 'delete') => void;
576
+ /**
577
+ * Validator for the `set()` operation.
578
+ * Invoked before a single key-value pair is added or updated.
579
+ *
580
+ * **Throw an error to invalidate and abort the operation.**
581
+ *
582
+ * @param actionParams - Tuple containing the key and value: `[key: Key, value: Value]`.
583
+ * @param action - The literal action name: `'set'`.
584
+ */
585
+ set?: (this: ThisArg, actionParams: [key: Key, value: Value], action: 'set') => void;
586
+ /**
587
+ * Validator for the `setAll()` operation.
588
+ * Invoked before merging or replacing the entire dataset.
589
+ *
590
+ * **Throw an error to invalidate and abort the operation.**
591
+ *
592
+ * @param actionParams - Tuple containing the data Map and replace flag:
593
+ * `[data?: Map<Key, Value>, replace?: boolean]`.
594
+ * @param action - The literal action name: `'setAll'`.
595
+ */
596
+ setAll?: (this: ThisArg, actionParams: [data?: Map<Key, Value>, replace?: boolean], action: 'setAll') => void;
597
+ /**
598
+ * Validator for the `write()` operation.
599
+ * Invoked immediately before data is serialized and committed to the underlying storage.
600
+ * This acts as a final gatekeeper for the entire state during persistence.
601
+ *
602
+ * The `write` validator is invoked during every persistence cycle, serving as a final check
603
+ * after operation-specific hooks (like `set` or `delete`).
604
+ *
605
+ * **Throw an error to invalidate and abort the operation.**
606
+ *
607
+ * @param actionParams - Tuple containing the full data Map to be persisted: `[data: Map<Key, Value>]`.
608
+ * @param action - The literal action name: `'write'`.
609
+ */
610
+ write?: (this: ThisArg, actionParams: [data: Map<Key, Value>], action: 'write') => void;
509
611
  };
612
+ /**
613
+ * Literal union of all operations that can be intercepted by a validator.
614
+ */
615
+ type Store_ValidateAction = 'clear' | 'delete' | 'set' | 'setAll' | 'write';
616
+
617
+ /**
618
+ * Creates a {@link IObjectStore} instance initialized from a plain object.
619
+ *
620
+ * This factory method automatically configures `parse` and `stringify` logic to
621
+ * treat the underlying storage as a serialized object, while providing a
622
+ * type-safe Map-like interface for individual properties.
623
+ *
624
+ * This default behavior can be overridden by providing custom `parse` and `stringify` implementations in `options`.
625
+ *
626
+ * @param options (optional) Configuration options for the storage instance. See {@link ObjectStore_Options} for more.
627
+ * @param options.initialValue (optional) An optional object to populate the storage if it's currently empty.
628
+ * @param options.name (optional) locaStorage key (or JSON filename in NodeJS) for persistence storage.
629
+ * @param context - (optional) A plain object or a factory function that returns an object.
630
+ *
631
+ * **Purpose:**
632
+ * Use `context` to encapsulate domain-specific business logic, helper methods, or non-reactive state
633
+ * directly into the store instance.
634
+ *
635
+ * **Behavior:** See {@link createStore}.
636
+ *
637
+ * @template T (optional) The structure of the object being stored. Can auto-infer from `options.initialValue`.
638
+ * @template CacheDisabled - Whether store data caching is disabled.
639
+ * @template Context - The type of the context object or factory function.
640
+ *
641
+ * @returns A new Store instance mapped to the object's keys and values.
642
+ *
643
+ * @example
644
+ * #### Basic property-based access
645
+ *
646
+ * ```javascript
647
+ * import { createObjectStore } from '@superutils/store'
648
+ *
649
+ * const userStore = createObjectStore('user', {
650
+ * initialValue: {
651
+ * age: 99,
652
+ * name: 'Ninety Nine'
653
+ * }
654
+ * })
655
+ *
656
+ * // Keys are strictly inferred from the interface
657
+ * const name = userStore.get('name') // Type: string | undefined
658
+ * console.log(name) // Prints: 'Ninety Nine'
659
+ *
660
+ * // Update properties with type safety
661
+ * userStore.set('age', 100) // Only numbers are accepted for 'age'
662
+ *
663
+ * // Export the underlying data back to a plain object
664
+ * const user = userStore.toObject()
665
+ * console.log(user) // { age: 100, name: 'Ninety Nine' }
666
+ * ```
667
+ *
668
+ * @example
669
+ * #### Usage with context
670
+ *
671
+ * ```javascript
672
+ * import { createObjectStore } from '@superutils/store'
673
+ *
674
+ * const getContext = store => ({
675
+ * isAdmin: () => !!store.get('roles')?.includes('admin'),
676
+ * promoteToAdmin() {
677
+ * if (this.isAdmin()) return
678
+ *
679
+ * // Use functional updates to safely modify the roles array
680
+ * store.set('roles', (prev = []) => [...prev, 'admin'])
681
+ * }
682
+ * }
683
+ * // Functional context allows you to attach business logic directly to the store
684
+ * const userStore = createObjectStore(
685
+ * 'user',
686
+ * {
687
+ * initialValue: {
688
+ * age: 25,
689
+ * name: 'Jane Doe',
690
+ * roles: ['guest']
691
+ * },
692
+ * },
693
+ * getContext
694
+ * )
695
+ *
696
+ * // Logic is encapsulated and easy to invoke
697
+ * userStore.promoteToAdmin()
698
+ * console.log(userStore.get('roles')) // ['guest', 'admin']
699
+ * ```
700
+ *
701
+ */
702
+ declare function createObjectStore<Context extends object | ((store: IObjectStore<T, CacheDisabled>) => object), T extends object = Record<string, unknown>, CacheDisabled extends boolean = false>(options: undefined | null | ObjectStore_Options<T, CacheDisabled>, context: Context & ContextValidate<Context, IObjectStore<T, CacheDisabled>>): IObjectStore<T, CacheDisabled> & ContextReturn<Context>;
703
+ declare function createObjectStore<T extends object = Record<string, unknown>, CacheDisabled extends boolean = false>(options?: ObjectStore_Options<T, CacheDisabled>): IObjectStore<T, CacheDisabled>;
704
+
705
+ /**
706
+ * Store property names that are optional/user-provided and should not be allowed in context.
707
+ *
708
+ * This is used to avoid optional store properties being overriden by context properties
709
+ */
710
+ declare const OPTIONAL_STORE_PROPS: readonly ["delayOptions", "name", "onChange", "onError", "parse", "spaces", "storage", "stringify", "validate"];
711
+ /**
712
+ * Factory function to create a {@link Store} instance with optional business logic augmented into the store instance.
713
+ *
714
+ * This function provides a convenient way to instantiate a store and attach supplemental
715
+ * logic (context) to it. It supports full type inference for both the store's data
716
+ * and the attached context.
717
+ *
718
+ * @param options - (optional) Configuration options for the store.
719
+ * @param context - (optional) A plain object or a factory function that returns an object.
720
+ * If function provided, it is executed only once during instantiation.
721
+ *
722
+ * **Purpose:**
723
+ * Use `context` to encapsulate domain-specific business logic, helper methods, or non-reactive state
724
+ * directly into the store instance.
725
+ *
726
+ * **Behavior:**
727
+ * - **Non-Reactive:** Updates to context properties do **not** trigger `onChange` or RxJS emissions.
728
+ * - **Non-Persistent:** Context data is purely in-memory and is **not** saved to persistent storage.
729
+ * - **Access to Store:** When a factory function is used, it receives the store instance as an argument.
730
+ * - **Notes**:
731
+ * - Built-in store properties are not allowed
732
+ * - Augmented methods' "thisArg" will be the context as per default JavaScript behavior.
733
+ * - Custom class instances are supported as context. Built-in {@link Store} properties take precedence
734
+ * in the event of a naming conflict.
735
+ *
736
+ * @template Key - The type of keys stored in the map.
737
+ * @template Value - The type of values stored in the map.
738
+ * @template CacheDisabled - Whether store data caching is disabled.
739
+ * @template Context - The type of the context object or factory function.
740
+ *
741
+ * @returns A {@link Store} instance with augmented properties (if any).
742
+ *
743
+ * @example
744
+ * #### Basic usage
745
+ * ```javascript
746
+ * import { createStore } from '@superutils/store'
747
+ *
748
+ * const store = createStore({ initialValue: new Map([['count', 0]])})
749
+ * store.set('count', 1)
750
+ * store.set('count', prevCount => prevCount + 1)
751
+ * console.log(store.get('count')) // 2
752
+ * ```
753
+ *
754
+ * @example
755
+ * #### Store augmented with custom business logic
756
+ * ```javascript
757
+ * import { createStore } from '@superutils/store'
758
+ *
759
+ * const store = createStore({ name: 'user-settings'}, {
760
+ * count: 0,
761
+ * log(msg) {
762
+ * console.log(`[${++this.count}] ${msg}`)
763
+ * }
764
+ * })
765
+ *
766
+ * store.log('Settings updated')
767
+ * console.log(store.count)
768
+ * ```
769
+ *
770
+ * @example
771
+ * #### In-memory store
772
+ * ```javascript
773
+ * import fetch from '@superutils/fetch'
774
+ * import { createStore } from '@superutils/store'
775
+ *
776
+ * // Bypass the name property to create an in-memory store
777
+ * const store = createStore()
778
+ *
779
+ * // This will NOT save the data to localStorage
780
+ * store.set('key', 'value')
781
+ * ```
782
+ *
783
+ * @example
784
+ * #### Store with a functional context
785
+ * ```javascript
786
+ * import { createStore } from '@superutils/store'
787
+ *
788
+ * const authStore = createStore(null, store => ({
789
+ * isAuthenticated: () => store.has('token'),
790
+ * logout: () => {
791
+ * store.delete('token')
792
+ * console.log('logged out')
793
+ * }
794
+ * }))
795
+ *
796
+ * if (authStore.isAuthenticated()) {
797
+ * authStore.logout()
798
+ * }
799
+ * ```
800
+ *
801
+ * @example
802
+ * #### Augmenting with a custom class instance
803
+ *
804
+ * ```typescript
805
+ * import { createStore } from '@superutils/store'
806
+ *
807
+ * class MyCustomClass {
808
+ * private _count = 0
809
+ * get count() {
810
+ * return this._count
811
+ * }
812
+ * increment = () => this._count++
813
+ * decrement() {
814
+ * return --this._count
815
+ * }
816
+ * }
817
+ *
818
+ * const store = createStore(null, new MyCustomClass())
819
+ * console.log(
820
+ * store.count, // 0
821
+ * store.increment(),// function
822
+ * store.count, // 1
823
+ * store.decrement(), // undefined
824
+ * )
825
+ *```
826
+ */
827
+ declare function createStore<Context extends object | ((store: IStore<Key, Value, CacheDisabled>) => object), Key, Value, CacheDisabled extends boolean>(options: undefined | null | Store_Options<Key, Value, CacheDisabled>, context: Context & ContextValidate<Context, IStore<Key, Value, CacheDisabled>>): IStore<Key, Value, CacheDisabled> & ContextReturn<Context>;
828
+ declare function createStore<Key, Value, CacheDisabled extends boolean = false>(options?: Store_Options<Key, Value, CacheDisabled>): IStore<Key, Value, CacheDisabled>;
510
829
 
511
830
  /**
512
831
  * RxJS Subject to trigger forced update of cached data from underlying storage of {@link Store} instances.
@@ -584,16 +903,15 @@ declare const forceUpdateCache$: Subject<string | boolean | string[]>;
584
903
  * reference their return types and other method signatures through the interface definition.
585
904
  *
586
905
  * @see {@link forceUpdateCache$} for cache invalidation across instances.
587
- * @see {@link Store.fromObject} for object-oriented storage initialization.
588
906
  *
589
907
  * @example
590
908
  * #### Browser Usage 1: use like a map
591
909
  * ```javascript
592
910
  * import { Store } from '@superutils/store'
593
911
  *
594
- * const userStorage = new Store('users')
595
- * userStorage.set(1, { name: 'Alice', age: 30 })
596
- * const user = userStorage.get(1)
912
+ * const userStore = new Store('users')
913
+ * userStore.set(1, { name: 'Alice', age: 30 })
914
+ * const user = userStore.get(1)
597
915
  * console.log(user) // prints: {name: 'Alice', age: 30}
598
916
  * ```
599
917
  *
@@ -704,7 +1022,7 @@ This extends IStore<Key, Value, CacheDisabled> = IStore<Key, Value, CacheDisable
704
1022
  private subscriptions;
705
1023
  type: This['type'];
706
1024
  validate?: This['validate'];
707
- constructor(name?: This['name'], options?: Store_Options<Key, Value, CacheDisabled>);
1025
+ constructor(name?: This['name'], options?: Store_Options<Key, Value, CacheDisabled> | null);
708
1026
  clear: This['clear'];
709
1027
  delete: This['delete'];
710
1028
  static messages: {
@@ -747,226 +1065,4 @@ This extends IStore<Key, Value, CacheDisabled> = IStore<Key, Value, CacheDisable
747
1065
  write: This['write'];
748
1066
  }
749
1067
 
750
- /**
751
- * Defines the shape of the context object that can be attached to a {@link Store}.
752
- *
753
- * A context can be:
754
- * - A plain object containing utility methods or properties.
755
- * - A factory function that receives the {@link IStore} instance and returns an object.
756
- * This is useful for creating methods that need to interact with the store's data
757
- * using the store instance itself.
758
- *
759
- * @template Key - The type of keys in the store.
760
- * @template Value - The type of values in the store.
761
- * @template CacheDisabled - Whether caching is disabled for this store.
762
- */
763
- type Store_Context<Key, Value, CacheDisabled extends boolean = false> = undefined | object | ((store: IStore<Key, Value, CacheDisabled>) => object);
764
- type Store_ContextReturn<T> = {
765
- context: undefined extends T ? never : T extends (...args: any[]) => infer R ? R : T;
766
- };
767
- type IStoreWithContext<Key, Value, CacheDisabled extends boolean, Context extends Store_Context<Key, Value, CacheDisabled>> = IStore<Key, Value, CacheDisabled> & Store_ContextReturn<Context>;
768
- type IObjectStoreWithContext<T extends object, CacheDisabled extends boolean, Context extends Store_Context<keyof T, T[keyof T], CacheDisabled>> = IObjectStore<T, CacheDisabled> & Store_ContextReturn<Context>;
769
-
770
- /**
771
- * Creates a {@link Store} instance initialized from a plain object.
772
- *
773
- * This factory method automatically configures `parse` and `stringify` logic to
774
- * treat the underlying storage as a serialized object, while providing a
775
- * type-safe Map-like interface for individual properties.
776
- *
777
- * This default behavior can be overridden by providing custom `parse` and `stringify` implementations in `options`.
778
- *
779
- * @param name (optional) The name for the storage (e.g., localStorage key or filename).
780
- * @param options (optional) Configuration options for the storage instance.
781
- * @param options.initialValue (optional) An optional object to populate the storage if it's currently empty.
782
- * @param options.context - (optional) A plain object or a factory function that returns an object.
783
- *
784
- * **Purpose:**
785
- * Use `context` to encapsulate domain-specific business logic, helper methods, or non-reactive state
786
- * directly alongside the store instance.
787
- *
788
- * **Behavior:**
789
- * - **Non-Reactive:** Updates to context properties do **not** trigger `onChange` or RxJS emissions.
790
- * - **Non-Persistent:** Context data is purely in-memory and is **not** saved to persistent storage.
791
- * - **Access to Store:** When a factory function is used, it receives the store instance as an argument.
792
- *
793
- * @template T (optional) The structure of the object being stored. Can auto-infer from `options.initialValue`.
794
- * @template CacheDisabled (optional) Literal type determining whether to disable in-memory caching.
795
- *
796
- * @returns A new Store instance mapped to the object's keys and values.
797
- *
798
- * @example
799
- * #### Basic property-based access
800
- *
801
- * ```typescript
802
- * import { createObjectStore } from '@superutils/store'
803
- *
804
- * const storage = createObjectStore('user-profile', {
805
- * initialValue: {
806
- * age: 99,
807
- * name: 'Ninety Nine'
808
- * }
809
- * })
810
- *
811
- * // Keys are strictly inferred from the interface
812
- * const name = storage.get('name') // Type: string | undefined
813
- * console.log(name) // Prints: 'Ninety Nine'
814
- *
815
- * // Update properties with type safety
816
- * storage.set('age', 100) // Only numbers are accepted for 'age'
817
- *
818
- * // Export the underlying data back to a plain object
819
- * const userObj = storage.toObject<User>()
820
- * console.log(userObj) // { age: 100, name: 'Ninety Nine' }
821
- * ```
822
- *
823
- * @example
824
- * #### Usage with context
825
- *
826
- * ```javascript
827
- * import { createObjectStore } from '@superutils/store'
828
- *
829
- * // Functional context allows you to attach business logic directly to the store
830
- * const userStore = createObjectStore('user-profile', {
831
- * initialValue: {
832
- * age: 25,
833
- * name: 'Jane Doe',
834
- * roles: ['guest']
835
- * },
836
- * context: store => ({
837
- * isAdmin: () => !!store.get('roles')?.includes('admin'),
838
- * promoteToAdmin() {
839
- * if (this.isAdmin()) return
840
- *
841
- * // Use functional updates to safely modify the roles array
842
- * store.set('roles', (prev = []) => [...prev, 'admin'])
843
- * }
844
- * })
845
- * })
846
- *
847
- * // Logic is encapsulated and easy to invoke
848
- * userStore.context.promoteToAdmin()
849
- * console.log(userStore.get('roles')) // ['guest', 'admin']
850
- * ```
851
- *
852
- */
853
- declare function createObjectStore<T extends object = Record<string, unknown>, CacheDisabled extends boolean = false, Context extends ObjectStore_Context<T, CacheDisabled> = ObjectStore_Context<T, CacheDisabled>>(name?: string | null, options?: ObjectStore_Options<T, CacheDisabled, Context>): IObjectStoreWithContext<T, CacheDisabled, Context>;
854
- declare function createObjectStore<T extends object = Record<string, unknown>, CacheDisabled extends boolean = false, Context extends ObjectStore_Context<T, CacheDisabled> = ObjectStore_Context<T, CacheDisabled>>(options: ObjectStore_Options<T, CacheDisabled, Context>): IObjectStoreWithContext<T, CacheDisabled, Context>;
855
- /**
856
- * Create a {@link Store} instance from an object using `options.initialValue`.
857
- */
858
- declare function createObjectStore<T extends object = Record<string, unknown>, Key extends keyof T = keyof T, Value extends T[Key] = T[Key], CacheDisabled extends boolean = false>(...args: ConstructorParameters<typeof Store<Key, Value, CacheDisabled>>): IObjectStore<T, CacheDisabled>;
859
-
860
- /**
861
- * Factory function to create a {@link Store} instance with optional context.
862
- *
863
- * This function provides a convenient way to instantiate a store and attach supplemental
864
- * logic (context) to it. It supports full type inference for both the store's data
865
- * and the attached context.
866
- *
867
- * @param name - The name of the storage (e.g., localStorage key). If null/undefined, the store remains in-memory.
868
- * @param options - Configuration options for the store
869
- * @param options.context - (optional) A plain object or a factory function that returns an object.
870
- *
871
- * **Purpose:**
872
- * Use `context` to encapsulate domain-specific business logic, helper methods, or non-reactive state
873
- * directly alongside the store instance.
874
- *
875
- * **Behavior:**
876
- * - **Non-Reactive:** Updates to context properties do **not** trigger `onChange` or RxJS emissions.
877
- * - **Non-Persistent:** Context data is purely in-memory and is **not** saved to persistent storage.
878
- * - **Access to Store:** When a factory function is used, it receives the store instance as an argument.
879
- *
880
- * @template Context - The type of the context object or factory function.
881
- * @template Key - The type of keys stored in the map.
882
- * @template Value - The type of values stored in the map.
883
- * @template CacheDisabled - Literal type determining whether to disable in-memory caching.
884
- *
885
- * @returns A {@link Store} instance augmented with a `context` property.
886
- *
887
- * @example
888
- * #### Basic store without context
889
- * ```javascript
890
- * import { createStore } from '@superutils/store'
891
- *
892
- * const store = createStore<string, number>()
893
- * store.set('count', 1)
894
- * store.set('count', prevCount => prevCount + 1)
895
- * ```
896
- *
897
- * @example
898
- * #### Store with a static context object
899
- * ```javascript
900
- * import { createStore } from '@superutils/store'
901
- *
902
- * const store = createStore('user-settings', {
903
- * context: {
904
- * count: 0,
905
- * log(msg) {
906
- * console.log(`[${++this.count}] ${msg}`)
907
- * }
908
- * }
909
- * })
910
- *
911
- * store.context.log('Setting updated')
912
- * console.log(store.context.count)
913
- * ```
914
- *
915
- * @example
916
- * #### In-memory store
917
- * ```javascript
918
- * import fetch from '@superutils/fetch'
919
- * import { createStore } from '@superutils/store'
920
- *
921
- * const store = createStore({
922
- * context: store => ({
923
- * async getProducts() {
924
- * const { products } = await fetch.get('https://dummyjson.com/products')
925
- *
926
- * const productsMap = new Map(products.map(p => [p.id, p]))
927
- * store.setAll(productsMap)
928
- *
929
- * return productsMap
930
- * },
931
- * }),
932
- * })
933
- *
934
- * store.context.getProducts().then(() => {
935
- * console.log(store.getAll())
936
- * })
937
- * ```
938
- *
939
- * @example
940
- * #### Store with a functional context (access to store instance)
941
- * ```javascript
942
- * import { createStore } from '@superutils/store'
943
- *
944
- * const authStore = createStore('auth', {
945
- * context: store => ({
946
- * isAuthenticated: () => store.has('token'),
947
- * logout: () => store.delete('token')
948
- * })
949
- * })
950
- *
951
- * if (authStore.context.isAuthenticated()) {
952
- * authStore.context.logout()
953
- * }
954
- * ```
955
- */
956
- declare function createStore<Context extends Store_Context<Key, Value, CacheDisabled>, Key, Value, CacheDisabled extends boolean = false>(name?: ConstructorParameters<typeof Store<Key, Value, CacheDisabled>>[0], options?: Store_Options<Key, Value, CacheDisabled> & {
957
- context?: Context;
958
- }): IStoreWithContext<Key, Value, CacheDisabled, Context>;
959
- declare function createStore<Context extends Store_Context<Key, Value, CacheDisabled>, Key, Value, CacheDisabled extends boolean = false>(options: Store_Options<Key, Value, CacheDisabled> & {
960
- context?: Context;
961
- }): IStoreWithContext<Key, Value, CacheDisabled, Context>;
962
- /**
963
- * Factory method to create a {@link Store} instance.
964
- *
965
- * @param args - Arguments passed directly to the {@link Store} constructor.
966
- * @template Key - The type of keys stored in the map.
967
- * @template Value - The type of values stored in the map.
968
- * @template CacheDisabled - Whether to disable in-memory caching.
969
- */
970
- declare function createStore<Key, Value, CacheDisabled extends boolean = false>(...args: ConstructorParameters<typeof Store<Key, Value, CacheDisabled>>): Store<Key, Value, CacheDisabled>;
971
-
972
- export { type IObjectStore, type IStore, type ObjectStore_Context, type ObjectStore_Options, type StorageCompact, Store, type Store_DelayOptions, Store_OnErrorType, type Store_Options, type Store_Parse, type Store_Search, type Store_Sort, type Store_SortByComparator, type Store_SortByKey, type Store_SortByPropertyName, type Store_SortOptions, type Store_Stringify, type Store_ToJSON, createObjectStore, createStore, Store as default, forceUpdateCache$ };
1068
+ export { type ContextExcludeProps, type ContextReturn, type ContextValidate, type IObjectStore, type IStore, OPTIONAL_STORE_PROPS, type ObjectStore_Options, type StorageCompact, Store, type Store_DelayOptions, Store_OnErrorType, type Store_OptionKeys, type Store_Options, type Store_Parse, type Store_Search, type Store_Sort, type Store_SortByComparator, type Store_SortByKey, type Store_SortByPropertyName, type Store_SortOptions, type Store_Stringify, type Store_ToJSON, type Store_Validate, type Store_ValidateAction, createObjectStore, createStore, Store as default, forceUpdateCache$ };