@flurryx/store 0.8.3 → 0.8.4

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.cts CHANGED
@@ -1,9 +1,15 @@
1
1
  import { Signal, InjectionToken } from '@angular/core';
2
2
  import { ResourceState, KeyedResourceKey } from '@flurryx/core';
3
3
 
4
+ /**
5
+ * Constraint type ensuring every key in a store data map holds a {@link ResourceState}.
6
+ */
4
7
  type StoreDataShape<TData> = {
5
8
  [K in keyof TData]: ResourceState<unknown>;
6
9
  };
10
+ /**
11
+ * Extracts the string-typed keys from a store data map.
12
+ */
7
13
  type StoreKey<TData> = keyof TData & string;
8
14
  /**
9
15
  * Phantom-typed marker for a store resource slot.
@@ -40,35 +46,124 @@ type ConfigToData<TConfig extends object> = {
40
46
  };
41
47
  /**
42
48
  * Shared store interface implemented by both BaseStore and LazyStore.
49
+ *
50
+ * All store instances expose these methods regardless of how they were created
51
+ * (interface-based, fluent, or enum-constrained builder).
43
52
  */
44
53
  interface IStore<TData extends StoreDataShape<TData>> {
54
+ /** Returns a read-only `Signal` for the given slot. */
45
55
  get<K extends StoreKey<TData>>(key: K): Signal<TData[K]>;
56
+ /** Merges a partial state into the given slot (immutable spread). */
46
57
  update<K extends StoreKey<TData>>(key: K, newState: Partial<TData[K]>): void;
58
+ /** Resets a slot to its initial idle state (`{ data: undefined, isLoading: false, … }`). */
47
59
  clear<K extends StoreKey<TData>>(key: K): void;
60
+ /** Resets every slot in this store. */
48
61
  clearAll(): void;
62
+ /** Marks a slot as loading: sets `isLoading: true` and clears `status`/`errors`. */
49
63
  startLoading<K extends StoreKey<TData>>(key: K): void;
64
+ /** Marks a slot as no longer loading: sets `isLoading: false`. */
50
65
  stopLoading<K extends StoreKey<TData>>(key: K): void;
66
+ /** Merges a single entity into a keyed slot and sets its status to `'Success'`. */
51
67
  updateKeyedOne<K extends StoreKey<TData>>(key: K, resourceKey: KeyedResourceKey, entity: unknown): void;
68
+ /** Removes a single entity (and its loading/status/errors) from a keyed slot. */
52
69
  clearKeyedOne<K extends StoreKey<TData>>(key: K, resourceKey: KeyedResourceKey): void;
70
+ /** Marks a single entity within a keyed slot as loading. */
53
71
  startKeyedLoading<K extends StoreKey<TData>>(key: K, resourceKey: KeyedResourceKey): void;
72
+ /**
73
+ * Registers a callback invoked whenever the given slot is updated.
74
+ * @returns A cleanup function that removes the listener.
75
+ */
54
76
  onUpdate<K extends StoreKey<TData>>(key: K, callback: (state: TData[K], previousState: TData[K]) => void): () => void;
55
77
  }
56
78
 
79
+ /**
80
+ * Abstract base class for flurryx stores.
81
+ *
82
+ * Backed by Angular `signal()` per slot, providing read-only `Signal` access
83
+ * and immutable updates. All writes go through the store's own methods to
84
+ * enforce single-owner encapsulation.
85
+ *
86
+ * Use the {@link Store} builder to create instances — do not subclass directly.
87
+ *
88
+ * @template TEnum - Record mapping slot names to their string/number keys.
89
+ * @template TData - Record mapping slot names to `ResourceState<T>` types.
90
+ */
57
91
  declare abstract class BaseStore<TEnum extends Record<string, string | number>, TData extends {
58
92
  [K in keyof TEnum]: ResourceState<unknown>;
59
93
  }> implements IStore<TData> {
60
94
  protected readonly storeEnum: TEnum;
61
95
  private readonly signalsState;
62
96
  protected constructor(storeEnum: TEnum);
97
+ /**
98
+ * Returns a **read-only** `Signal` for the given store slot.
99
+ *
100
+ * @param key - The slot name to read.
101
+ * @returns A `Signal` wrapping the slot's current {@link ResourceState}.
102
+ */
63
103
  get<K extends keyof TData>(key: K): Signal<TData[K]>;
104
+ /**
105
+ * Registers a callback fired after every `update` or `clear` on the given slot.
106
+ *
107
+ * @param key - The slot to watch.
108
+ * @param callback - Receives the new state and the previous state.
109
+ * @returns A cleanup function that removes the listener when called.
110
+ */
64
111
  onUpdate<K extends keyof TData>(key: K, callback: (state: TData[K], previousState: TData[K]) => void): () => void;
112
+ /**
113
+ * Partially updates a slot by merging `newState` into the current value (immutable spread).
114
+ *
115
+ * @param key - The slot to update.
116
+ * @param newState - Partial state to merge (e.g. `{ data: newData, status: 'Success' }`).
117
+ */
65
118
  update<K extends keyof TData>(key: K, newState: Partial<TData[K]>): void;
119
+ /** Resets every slot in this store to its initial idle state. */
66
120
  clearAll(): void;
121
+ /**
122
+ * Resets a single slot to `{ data: undefined, isLoading: false, status: undefined, errors: undefined }`.
123
+ *
124
+ * @param key - The slot to clear.
125
+ */
67
126
  clear<K extends keyof TData>(key: K): void;
127
+ /**
128
+ * Marks a slot as loading: sets `isLoading: true` and clears `status` and `errors`.
129
+ *
130
+ * @param key - The slot to mark as loading.
131
+ */
68
132
  startLoading<K extends keyof TData>(key: K): void;
133
+ /**
134
+ * Marks a slot as no longer loading: sets `isLoading: false`.
135
+ * Does **not** clear `status` or `errors`.
136
+ *
137
+ * @param key - The slot to stop loading.
138
+ */
69
139
  stopLoading<K extends keyof TData>(key: K): void;
140
+ /**
141
+ * Merges a single entity into a {@link KeyedResourceData} slot.
142
+ * Sets its status to `'Success'` and clears per-key errors.
143
+ * The top-level `isLoading` is recalculated based on remaining loading keys.
144
+ *
145
+ * @param key - The keyed slot name.
146
+ * @param resourceKey - The entity identifier (e.g. `'inv-123'`).
147
+ * @param entity - The entity value to store.
148
+ */
70
149
  updateKeyedOne<K extends keyof TData>(key: K, resourceKey: KeyedResourceKey, entity: unknown): void;
150
+ /**
151
+ * Removes a single entity from a {@link KeyedResourceData} slot,
152
+ * including its loading flag, status, and errors.
153
+ * Recalculates the top-level `isLoading` from the remaining keys.
154
+ *
155
+ * @param key - The keyed slot name.
156
+ * @param resourceKey - The entity identifier to remove.
157
+ */
71
158
  clearKeyedOne<K extends keyof TData>(key: K, resourceKey: KeyedResourceKey): void;
159
+ /**
160
+ * Marks a single entity within a keyed slot as loading.
161
+ * Clears its status and errors. If the slot data is not yet a {@link KeyedResourceData},
162
+ * falls back to `startLoading(key)`.
163
+ *
164
+ * @param key - The keyed slot name.
165
+ * @param resourceKey - The entity identifier to mark as loading.
166
+ */
72
167
  startKeyedLoading<K extends keyof TData>(key: K, resourceKey: KeyedResourceKey): void;
73
168
  private notifyUpdateHooks;
74
169
  private initializeState;
@@ -105,15 +200,42 @@ interface AsStep<TAccum extends StoreConfig, TKey extends string> {
105
200
  }
106
201
  /**
107
202
  * Fluent builder for creating stores.
108
- * Accumulates resource definitions then produces an InjectionToken on .build().
203
+ * Accumulates resource definitions then produces an `InjectionToken` on `.build()`.
109
204
  */
110
205
  interface StoreBuilder<TAccum extends StoreConfig> {
206
+ /** Define a new resource slot. Chain `.as<T>()` to set its type. */
111
207
  resource<TKey extends string>(key: TKey): AsStep<TAccum, TKey>;
208
+ /**
209
+ * Mirror a slot from another store. When the source updates, the target is kept in sync.
210
+ *
211
+ * @param source - The source store's `InjectionToken`.
212
+ * @param sourceKey - The key to watch on the source store.
213
+ * @param targetKey - The key on this store to write to. Defaults to `sourceKey`.
214
+ */
112
215
  mirror<TSourceData extends StoreDataShape<TSourceData>>(source: InjectionToken<IStore<TSourceData>>, sourceKey: StoreKey<TSourceData>, targetKey?: StoreKey<TAccum>): StoreBuilder<TAccum>;
216
+ /**
217
+ * Mirror one slot to another **within the same store**.
218
+ * Source and target keys must be different.
219
+ *
220
+ * @param sourceKey - The slot to read from.
221
+ * @param targetKey - The slot to write to.
222
+ */
113
223
  mirrorSelf(sourceKey: StoreKey<TAccum>, targetKey: StoreKey<TAccum>): StoreBuilder<TAccum>;
224
+ /**
225
+ * Accumulate single-entity fetches from a source store into a `KeyedResourceData` slot.
226
+ *
227
+ * @param source - The source store's `InjectionToken`.
228
+ * @param sourceKey - The single-entity key on the source store.
229
+ * @param options - Must include `extractId` to derive the entity's key from its data.
230
+ * @param targetKey - The keyed slot on this store. Defaults to `sourceKey`.
231
+ */
114
232
  mirrorKeyed<TSourceData extends StoreDataShape<TSourceData>, TEntity>(source: InjectionToken<IStore<TSourceData>>, sourceKey: StoreKey<TSourceData>, options: {
115
233
  extractId: (data: TEntity | undefined) => KeyedResourceKey | undefined;
116
234
  }, targetKey?: StoreKey<TAccum>): StoreBuilder<TAccum>;
235
+ /**
236
+ * Finalize the builder and create an `InjectionToken` (`providedIn: 'root'`).
237
+ * All mirrors are wired up automatically when Angular creates the store.
238
+ */
117
239
  build(): InjectionToken<BaseStore<InferEnum<TAccum>, InferData<TAccum>>>;
118
240
  }
119
241
  /** Keys from the enum that have NOT yet been defined. */
@@ -197,9 +319,31 @@ interface StoreEntry {
197
319
  */
198
320
  declare const Store: StoreEntry;
199
321
 
322
+ /**
323
+ * Clears every store instance tracked by flurryx.
324
+ *
325
+ * Calls `clearAll()` on each registered store, resetting all slots to their
326
+ * initial idle state. Useful for logout, tenant switching, or test cleanup.
327
+ *
328
+ * @example
329
+ * ```ts
330
+ * import { clearAllStores } from 'flurryx';
331
+ *
332
+ * logout() {
333
+ * clearAllStores();
334
+ * }
335
+ * ```
336
+ */
200
337
  declare function clearAllStores(): void;
201
338
 
339
+ /**
340
+ * Options for {@link mirrorKey}.
341
+ */
202
342
  interface MirrorOptions {
343
+ /**
344
+ * Angular `DestroyRef` (or any object with an `onDestroy` method) for
345
+ * automatic cleanup. When provided, the mirror stops when the ref is destroyed.
346
+ */
203
347
  destroyRef?: {
204
348
  onDestroy: (fn: () => void) => void;
205
349
  };
@@ -217,8 +361,21 @@ interface MirrorOptions {
217
361
  */
218
362
  declare function mirrorKey<TSource extends StoreDataShape<TSource>, TTarget extends StoreDataShape<TTarget>>(source: IStore<TSource>, sourceKey: StoreKey<TSource>, target: IStore<TTarget>, targetKeyOrOptions?: StoreKey<TTarget> | MirrorOptions, options?: MirrorOptions): () => void;
219
363
 
364
+ /**
365
+ * Options for {@link collectKeyed}.
366
+ *
367
+ * @template TEntity - The entity type emitted by the source store.
368
+ */
220
369
  interface CollectKeyedOptions<TEntity> {
370
+ /**
371
+ * Extracts the entity identifier from the source data.
372
+ * Return `undefined` to skip accumulation for that emission.
373
+ */
221
374
  extractId: (data: TEntity | undefined) => KeyedResourceKey | undefined;
375
+ /**
376
+ * Angular `DestroyRef` (or any object with an `onDestroy` method) for
377
+ * automatic cleanup. When provided, collection stops when the ref is destroyed.
378
+ */
222
379
  destroyRef?: {
223
380
  onDestroy: (fn: () => void) => void;
224
381
  };
package/dist/index.d.ts CHANGED
@@ -1,9 +1,15 @@
1
1
  import { Signal, InjectionToken } from '@angular/core';
2
2
  import { ResourceState, KeyedResourceKey } from '@flurryx/core';
3
3
 
4
+ /**
5
+ * Constraint type ensuring every key in a store data map holds a {@link ResourceState}.
6
+ */
4
7
  type StoreDataShape<TData> = {
5
8
  [K in keyof TData]: ResourceState<unknown>;
6
9
  };
10
+ /**
11
+ * Extracts the string-typed keys from a store data map.
12
+ */
7
13
  type StoreKey<TData> = keyof TData & string;
8
14
  /**
9
15
  * Phantom-typed marker for a store resource slot.
@@ -40,35 +46,124 @@ type ConfigToData<TConfig extends object> = {
40
46
  };
41
47
  /**
42
48
  * Shared store interface implemented by both BaseStore and LazyStore.
49
+ *
50
+ * All store instances expose these methods regardless of how they were created
51
+ * (interface-based, fluent, or enum-constrained builder).
43
52
  */
44
53
  interface IStore<TData extends StoreDataShape<TData>> {
54
+ /** Returns a read-only `Signal` for the given slot. */
45
55
  get<K extends StoreKey<TData>>(key: K): Signal<TData[K]>;
56
+ /** Merges a partial state into the given slot (immutable spread). */
46
57
  update<K extends StoreKey<TData>>(key: K, newState: Partial<TData[K]>): void;
58
+ /** Resets a slot to its initial idle state (`{ data: undefined, isLoading: false, … }`). */
47
59
  clear<K extends StoreKey<TData>>(key: K): void;
60
+ /** Resets every slot in this store. */
48
61
  clearAll(): void;
62
+ /** Marks a slot as loading: sets `isLoading: true` and clears `status`/`errors`. */
49
63
  startLoading<K extends StoreKey<TData>>(key: K): void;
64
+ /** Marks a slot as no longer loading: sets `isLoading: false`. */
50
65
  stopLoading<K extends StoreKey<TData>>(key: K): void;
66
+ /** Merges a single entity into a keyed slot and sets its status to `'Success'`. */
51
67
  updateKeyedOne<K extends StoreKey<TData>>(key: K, resourceKey: KeyedResourceKey, entity: unknown): void;
68
+ /** Removes a single entity (and its loading/status/errors) from a keyed slot. */
52
69
  clearKeyedOne<K extends StoreKey<TData>>(key: K, resourceKey: KeyedResourceKey): void;
70
+ /** Marks a single entity within a keyed slot as loading. */
53
71
  startKeyedLoading<K extends StoreKey<TData>>(key: K, resourceKey: KeyedResourceKey): void;
72
+ /**
73
+ * Registers a callback invoked whenever the given slot is updated.
74
+ * @returns A cleanup function that removes the listener.
75
+ */
54
76
  onUpdate<K extends StoreKey<TData>>(key: K, callback: (state: TData[K], previousState: TData[K]) => void): () => void;
55
77
  }
56
78
 
79
+ /**
80
+ * Abstract base class for flurryx stores.
81
+ *
82
+ * Backed by Angular `signal()` per slot, providing read-only `Signal` access
83
+ * and immutable updates. All writes go through the store's own methods to
84
+ * enforce single-owner encapsulation.
85
+ *
86
+ * Use the {@link Store} builder to create instances — do not subclass directly.
87
+ *
88
+ * @template TEnum - Record mapping slot names to their string/number keys.
89
+ * @template TData - Record mapping slot names to `ResourceState<T>` types.
90
+ */
57
91
  declare abstract class BaseStore<TEnum extends Record<string, string | number>, TData extends {
58
92
  [K in keyof TEnum]: ResourceState<unknown>;
59
93
  }> implements IStore<TData> {
60
94
  protected readonly storeEnum: TEnum;
61
95
  private readonly signalsState;
62
96
  protected constructor(storeEnum: TEnum);
97
+ /**
98
+ * Returns a **read-only** `Signal` for the given store slot.
99
+ *
100
+ * @param key - The slot name to read.
101
+ * @returns A `Signal` wrapping the slot's current {@link ResourceState}.
102
+ */
63
103
  get<K extends keyof TData>(key: K): Signal<TData[K]>;
104
+ /**
105
+ * Registers a callback fired after every `update` or `clear` on the given slot.
106
+ *
107
+ * @param key - The slot to watch.
108
+ * @param callback - Receives the new state and the previous state.
109
+ * @returns A cleanup function that removes the listener when called.
110
+ */
64
111
  onUpdate<K extends keyof TData>(key: K, callback: (state: TData[K], previousState: TData[K]) => void): () => void;
112
+ /**
113
+ * Partially updates a slot by merging `newState` into the current value (immutable spread).
114
+ *
115
+ * @param key - The slot to update.
116
+ * @param newState - Partial state to merge (e.g. `{ data: newData, status: 'Success' }`).
117
+ */
65
118
  update<K extends keyof TData>(key: K, newState: Partial<TData[K]>): void;
119
+ /** Resets every slot in this store to its initial idle state. */
66
120
  clearAll(): void;
121
+ /**
122
+ * Resets a single slot to `{ data: undefined, isLoading: false, status: undefined, errors: undefined }`.
123
+ *
124
+ * @param key - The slot to clear.
125
+ */
67
126
  clear<K extends keyof TData>(key: K): void;
127
+ /**
128
+ * Marks a slot as loading: sets `isLoading: true` and clears `status` and `errors`.
129
+ *
130
+ * @param key - The slot to mark as loading.
131
+ */
68
132
  startLoading<K extends keyof TData>(key: K): void;
133
+ /**
134
+ * Marks a slot as no longer loading: sets `isLoading: false`.
135
+ * Does **not** clear `status` or `errors`.
136
+ *
137
+ * @param key - The slot to stop loading.
138
+ */
69
139
  stopLoading<K extends keyof TData>(key: K): void;
140
+ /**
141
+ * Merges a single entity into a {@link KeyedResourceData} slot.
142
+ * Sets its status to `'Success'` and clears per-key errors.
143
+ * The top-level `isLoading` is recalculated based on remaining loading keys.
144
+ *
145
+ * @param key - The keyed slot name.
146
+ * @param resourceKey - The entity identifier (e.g. `'inv-123'`).
147
+ * @param entity - The entity value to store.
148
+ */
70
149
  updateKeyedOne<K extends keyof TData>(key: K, resourceKey: KeyedResourceKey, entity: unknown): void;
150
+ /**
151
+ * Removes a single entity from a {@link KeyedResourceData} slot,
152
+ * including its loading flag, status, and errors.
153
+ * Recalculates the top-level `isLoading` from the remaining keys.
154
+ *
155
+ * @param key - The keyed slot name.
156
+ * @param resourceKey - The entity identifier to remove.
157
+ */
71
158
  clearKeyedOne<K extends keyof TData>(key: K, resourceKey: KeyedResourceKey): void;
159
+ /**
160
+ * Marks a single entity within a keyed slot as loading.
161
+ * Clears its status and errors. If the slot data is not yet a {@link KeyedResourceData},
162
+ * falls back to `startLoading(key)`.
163
+ *
164
+ * @param key - The keyed slot name.
165
+ * @param resourceKey - The entity identifier to mark as loading.
166
+ */
72
167
  startKeyedLoading<K extends keyof TData>(key: K, resourceKey: KeyedResourceKey): void;
73
168
  private notifyUpdateHooks;
74
169
  private initializeState;
@@ -105,15 +200,42 @@ interface AsStep<TAccum extends StoreConfig, TKey extends string> {
105
200
  }
106
201
  /**
107
202
  * Fluent builder for creating stores.
108
- * Accumulates resource definitions then produces an InjectionToken on .build().
203
+ * Accumulates resource definitions then produces an `InjectionToken` on `.build()`.
109
204
  */
110
205
  interface StoreBuilder<TAccum extends StoreConfig> {
206
+ /** Define a new resource slot. Chain `.as<T>()` to set its type. */
111
207
  resource<TKey extends string>(key: TKey): AsStep<TAccum, TKey>;
208
+ /**
209
+ * Mirror a slot from another store. When the source updates, the target is kept in sync.
210
+ *
211
+ * @param source - The source store's `InjectionToken`.
212
+ * @param sourceKey - The key to watch on the source store.
213
+ * @param targetKey - The key on this store to write to. Defaults to `sourceKey`.
214
+ */
112
215
  mirror<TSourceData extends StoreDataShape<TSourceData>>(source: InjectionToken<IStore<TSourceData>>, sourceKey: StoreKey<TSourceData>, targetKey?: StoreKey<TAccum>): StoreBuilder<TAccum>;
216
+ /**
217
+ * Mirror one slot to another **within the same store**.
218
+ * Source and target keys must be different.
219
+ *
220
+ * @param sourceKey - The slot to read from.
221
+ * @param targetKey - The slot to write to.
222
+ */
113
223
  mirrorSelf(sourceKey: StoreKey<TAccum>, targetKey: StoreKey<TAccum>): StoreBuilder<TAccum>;
224
+ /**
225
+ * Accumulate single-entity fetches from a source store into a `KeyedResourceData` slot.
226
+ *
227
+ * @param source - The source store's `InjectionToken`.
228
+ * @param sourceKey - The single-entity key on the source store.
229
+ * @param options - Must include `extractId` to derive the entity's key from its data.
230
+ * @param targetKey - The keyed slot on this store. Defaults to `sourceKey`.
231
+ */
114
232
  mirrorKeyed<TSourceData extends StoreDataShape<TSourceData>, TEntity>(source: InjectionToken<IStore<TSourceData>>, sourceKey: StoreKey<TSourceData>, options: {
115
233
  extractId: (data: TEntity | undefined) => KeyedResourceKey | undefined;
116
234
  }, targetKey?: StoreKey<TAccum>): StoreBuilder<TAccum>;
235
+ /**
236
+ * Finalize the builder and create an `InjectionToken` (`providedIn: 'root'`).
237
+ * All mirrors are wired up automatically when Angular creates the store.
238
+ */
117
239
  build(): InjectionToken<BaseStore<InferEnum<TAccum>, InferData<TAccum>>>;
118
240
  }
119
241
  /** Keys from the enum that have NOT yet been defined. */
@@ -197,9 +319,31 @@ interface StoreEntry {
197
319
  */
198
320
  declare const Store: StoreEntry;
199
321
 
322
+ /**
323
+ * Clears every store instance tracked by flurryx.
324
+ *
325
+ * Calls `clearAll()` on each registered store, resetting all slots to their
326
+ * initial idle state. Useful for logout, tenant switching, or test cleanup.
327
+ *
328
+ * @example
329
+ * ```ts
330
+ * import { clearAllStores } from 'flurryx';
331
+ *
332
+ * logout() {
333
+ * clearAllStores();
334
+ * }
335
+ * ```
336
+ */
200
337
  declare function clearAllStores(): void;
201
338
 
339
+ /**
340
+ * Options for {@link mirrorKey}.
341
+ */
202
342
  interface MirrorOptions {
343
+ /**
344
+ * Angular `DestroyRef` (or any object with an `onDestroy` method) for
345
+ * automatic cleanup. When provided, the mirror stops when the ref is destroyed.
346
+ */
203
347
  destroyRef?: {
204
348
  onDestroy: (fn: () => void) => void;
205
349
  };
@@ -217,8 +361,21 @@ interface MirrorOptions {
217
361
  */
218
362
  declare function mirrorKey<TSource extends StoreDataShape<TSource>, TTarget extends StoreDataShape<TTarget>>(source: IStore<TSource>, sourceKey: StoreKey<TSource>, target: IStore<TTarget>, targetKeyOrOptions?: StoreKey<TTarget> | MirrorOptions, options?: MirrorOptions): () => void;
219
363
 
364
+ /**
365
+ * Options for {@link collectKeyed}.
366
+ *
367
+ * @template TEntity - The entity type emitted by the source store.
368
+ */
220
369
  interface CollectKeyedOptions<TEntity> {
370
+ /**
371
+ * Extracts the entity identifier from the source data.
372
+ * Return `undefined` to skip accumulation for that emission.
373
+ */
221
374
  extractId: (data: TEntity | undefined) => KeyedResourceKey | undefined;
375
+ /**
376
+ * Angular `DestroyRef` (or any object with an `onDestroy` method) for
377
+ * automatic cleanup. When provided, collection stops when the ref is destroyed.
378
+ */
222
379
  destroyRef?: {
223
380
  onDestroy: (fn: () => void) => void;
224
381
  };
package/dist/index.js CHANGED
@@ -27,9 +27,22 @@ var BaseStore = class {
27
27
  trackStore(this);
28
28
  }
29
29
  signalsState = /* @__PURE__ */ new Map();
30
+ /**
31
+ * Returns a **read-only** `Signal` for the given store slot.
32
+ *
33
+ * @param key - The slot name to read.
34
+ * @returns A `Signal` wrapping the slot's current {@link ResourceState}.
35
+ */
30
36
  get(key) {
31
37
  return this.signalsState.get(key.toString());
32
38
  }
39
+ /**
40
+ * Registers a callback fired after every `update` or `clear` on the given slot.
41
+ *
42
+ * @param key - The slot to watch.
43
+ * @param callback - Receives the new state and the previous state.
44
+ * @returns A cleanup function that removes the listener when called.
45
+ */
33
46
  onUpdate(key, callback) {
34
47
  const hooks = updateHooksMap.get(this);
35
48
  if (!hooks.has(key)) {
@@ -51,6 +64,12 @@ var BaseStore = class {
51
64
  }
52
65
  };
53
66
  }
67
+ /**
68
+ * Partially updates a slot by merging `newState` into the current value (immutable spread).
69
+ *
70
+ * @param key - The slot to update.
71
+ * @param newState - Partial state to merge (e.g. `{ data: newData, status: 'Success' }`).
72
+ */
54
73
  update(key, newState) {
55
74
  const currentState = this.signalsState.get(key.toString());
56
75
  if (!currentState) {
@@ -64,11 +83,17 @@ var BaseStore = class {
64
83
  const updatedState = currentState();
65
84
  this.notifyUpdateHooks(key, updatedState, previousState);
66
85
  }
86
+ /** Resets every slot in this store to its initial idle state. */
67
87
  clearAll() {
68
88
  Object.keys(this.storeEnum).forEach((key) => {
69
89
  this.clear(key);
70
90
  });
71
91
  }
92
+ /**
93
+ * Resets a single slot to `{ data: undefined, isLoading: false, status: undefined, errors: undefined }`.
94
+ *
95
+ * @param key - The slot to clear.
96
+ */
72
97
  clear(key) {
73
98
  const currentState = this.signalsState.get(key.toString());
74
99
  if (!currentState) {
@@ -85,6 +110,11 @@ var BaseStore = class {
85
110
  const nextState = currentState();
86
111
  this.notifyUpdateHooks(key, nextState, previousState);
87
112
  }
113
+ /**
114
+ * Marks a slot as loading: sets `isLoading: true` and clears `status` and `errors`.
115
+ *
116
+ * @param key - The slot to mark as loading.
117
+ */
88
118
  startLoading(key) {
89
119
  const currentState = this.signalsState.get(key.toString());
90
120
  if (!currentState) {
@@ -100,6 +130,12 @@ var BaseStore = class {
100
130
  })
101
131
  );
102
132
  }
133
+ /**
134
+ * Marks a slot as no longer loading: sets `isLoading: false`.
135
+ * Does **not** clear `status` or `errors`.
136
+ *
137
+ * @param key - The slot to stop loading.
138
+ */
103
139
  stopLoading(key) {
104
140
  const currentState = this.signalsState.get(key.toString());
105
141
  if (!currentState) {
@@ -113,6 +149,15 @@ var BaseStore = class {
113
149
  })
114
150
  );
115
151
  }
152
+ /**
153
+ * Merges a single entity into a {@link KeyedResourceData} slot.
154
+ * Sets its status to `'Success'` and clears per-key errors.
155
+ * The top-level `isLoading` is recalculated based on remaining loading keys.
156
+ *
157
+ * @param key - The keyed slot name.
158
+ * @param resourceKey - The entity identifier (e.g. `'inv-123'`).
159
+ * @param entity - The entity value to store.
160
+ */
116
161
  updateKeyedOne(key, resourceKey, entity) {
117
162
  const currentState = this.signalsState.get(key.toString());
118
163
  if (!currentState) {
@@ -145,6 +190,14 @@ var BaseStore = class {
145
190
  errors: void 0
146
191
  });
147
192
  }
193
+ /**
194
+ * Removes a single entity from a {@link KeyedResourceData} slot,
195
+ * including its loading flag, status, and errors.
196
+ * Recalculates the top-level `isLoading` from the remaining keys.
197
+ *
198
+ * @param key - The keyed slot name.
199
+ * @param resourceKey - The entity identifier to remove.
200
+ */
148
201
  clearKeyedOne(key, resourceKey) {
149
202
  const currentState = this.signalsState.get(key.toString());
150
203
  if (!currentState) {
@@ -184,6 +237,14 @@ var BaseStore = class {
184
237
  const updatedState = currentState();
185
238
  this.notifyUpdateHooks(key, updatedState, previousState);
186
239
  }
240
+ /**
241
+ * Marks a single entity within a keyed slot as loading.
242
+ * Clears its status and errors. If the slot data is not yet a {@link KeyedResourceData},
243
+ * falls back to `startLoading(key)`.
244
+ *
245
+ * @param key - The keyed slot name.
246
+ * @param resourceKey - The entity identifier to mark as loading.
247
+ */
187
248
  startKeyedLoading(key, resourceKey) {
188
249
  const currentState = this.signalsState.get(key.toString());
189
250
  if (!currentState) {
@@ -497,9 +558,15 @@ function collectKeyed(source, sourceKey, target, targetKeyOrOptions, options) {
497
558
  return;
498
559
  }
499
560
  if (resourceState.status === "Success" && currentId !== void 0) {
500
- const newEntities = { ...currentKeyed.entities, [currentId]: resourceState.data };
561
+ const newEntities = {
562
+ ...currentKeyed.entities,
563
+ [currentId]: resourceState.data
564
+ };
501
565
  const newIsLoading = { ...currentKeyed.isLoading, [currentId]: false };
502
- const newStatus = { ...currentKeyed.status, [currentId]: resourceState.status };
566
+ const newStatus = {
567
+ ...currentKeyed.status,
568
+ [currentId]: resourceState.status
569
+ };
503
570
  const newErrors = { ...currentKeyed.errors };
504
571
  delete newErrors[currentId];
505
572
  const updatedKeyed = {
@@ -516,8 +583,14 @@ function collectKeyed(source, sourceKey, target, targetKeyOrOptions, options) {
516
583
  previousId = currentId;
517
584
  } else if (resourceState.status === "Error" && currentId !== void 0) {
518
585
  const newIsLoading = { ...currentKeyed.isLoading, [currentId]: false };
519
- const newStatus = { ...currentKeyed.status, [currentId]: resourceState.status };
520
- const newErrors = { ...currentKeyed.errors, [currentId]: resourceState.errors };
586
+ const newStatus = {
587
+ ...currentKeyed.status,
588
+ [currentId]: resourceState.status
589
+ };
590
+ const newErrors = {
591
+ ...currentKeyed.errors,
592
+ [currentId]: resourceState.errors
593
+ };
521
594
  const updatedKeyed = {
522
595
  entities: { ...currentKeyed.entities },
523
596
  isLoading: newIsLoading,