@flurryx/store 0.7.6 → 0.8.1

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,6 +1,10 @@
1
1
  import { Signal, InjectionToken } from '@angular/core';
2
2
  import { ResourceState, KeyedResourceKey } from '@flurryx/core';
3
3
 
4
+ type StoreDataShape<TData> = {
5
+ [K in keyof TData]: ResourceState<unknown>;
6
+ };
7
+ type StoreKey<TData> = keyof TData & string;
4
8
  /**
5
9
  * Phantom-typed marker for a store resource slot.
6
10
  * Carries type information at compile time with zero runtime cost.
@@ -31,23 +35,23 @@ type InferData<TConfig extends StoreConfig> = {
31
35
  * Maps a plain config interface to ResourceState-wrapped data.
32
36
  * e.g. { SESSIONS: ChatSession[] } -> { SESSIONS: ResourceState<ChatSession[]> }
33
37
  */
34
- type ConfigToData<TConfig extends Record<string, unknown>> = {
38
+ type ConfigToData<TConfig extends object> = {
35
39
  [K in keyof TConfig & string]: ResourceState<TConfig[K]>;
36
40
  };
37
41
  /**
38
42
  * Shared store interface implemented by both BaseStore and LazyStore.
39
43
  */
40
- interface IStore<TData extends Record<string, ResourceState<unknown>>> {
41
- get<K extends keyof TData & string>(key: K): Signal<TData[K]>;
42
- update<K extends keyof TData & string>(key: K, newState: Partial<TData[K]>): void;
43
- clear<K extends keyof TData & string>(key: K): void;
44
+ interface IStore<TData extends StoreDataShape<TData>> {
45
+ get<K extends StoreKey<TData>>(key: K): Signal<TData[K]>;
46
+ update<K extends StoreKey<TData>>(key: K, newState: Partial<TData[K]>): void;
47
+ clear<K extends StoreKey<TData>>(key: K): void;
44
48
  clearAll(): void;
45
- startLoading<K extends keyof TData & string>(key: K): void;
46
- stopLoading<K extends keyof TData & string>(key: K): void;
47
- updateKeyedOne<K extends keyof TData & string>(key: K, resourceKey: KeyedResourceKey, entity: unknown): void;
48
- clearKeyedOne<K extends keyof TData & string>(key: K, resourceKey: KeyedResourceKey): void;
49
- startKeyedLoading<K extends keyof TData & string>(key: K, resourceKey: KeyedResourceKey): void;
50
- onUpdate<K extends keyof TData & string>(key: K, callback: (state: TData[K], previousState: TData[K]) => void): () => void;
49
+ startLoading<K extends StoreKey<TData>>(key: K): void;
50
+ stopLoading<K extends StoreKey<TData>>(key: K): void;
51
+ updateKeyedOne<K extends StoreKey<TData>>(key: K, resourceKey: KeyedResourceKey, entity: unknown): void;
52
+ clearKeyedOne<K extends StoreKey<TData>>(key: K, resourceKey: KeyedResourceKey): void;
53
+ startKeyedLoading<K extends StoreKey<TData>>(key: K, resourceKey: KeyedResourceKey): void;
54
+ onUpdate<K extends StoreKey<TData>>(key: K, callback: (state: TData[K], previousState: TData[K]) => void): () => void;
51
55
  }
52
56
 
53
57
  declare abstract class BaseStore<TEnum extends Record<string, string | number>, TData extends {
@@ -75,20 +79,21 @@ declare abstract class BaseStore<TEnum extends Record<string, string | number>,
75
79
  * Used by the `Store.for<Config>().build()` API where keys are
76
80
  * known only at the type level (no runtime enum).
77
81
  */
78
- declare class LazyStore<TData extends Record<string, ResourceState<unknown>>> implements IStore<TData> {
82
+ declare class LazyStore<TData extends StoreDataShape<TData>> implements IStore<TData> {
79
83
  private readonly signals;
80
84
  private readonly hooks;
85
+ constructor();
81
86
  private getOrCreate;
82
- get<K extends keyof TData & string>(key: K): Signal<TData[K]>;
83
- update<K extends keyof TData & string>(key: K, newState: Partial<TData[K]>): void;
84
- clear<K extends keyof TData & string>(key: K): void;
87
+ get<K extends StoreKey<TData>>(key: K): Signal<TData[K]>;
88
+ update<K extends StoreKey<TData>>(key: K, newState: Partial<TData[K]>): void;
89
+ clear<K extends StoreKey<TData>>(key: K): void;
85
90
  clearAll(): void;
86
- startLoading<K extends keyof TData & string>(key: K): void;
87
- stopLoading<K extends keyof TData & string>(key: K): void;
88
- updateKeyedOne<K extends keyof TData & string>(key: K, resourceKey: KeyedResourceKey, entity: unknown): void;
89
- clearKeyedOne<K extends keyof TData & string>(key: K, resourceKey: KeyedResourceKey): void;
90
- startKeyedLoading<K extends keyof TData & string>(key: K, resourceKey: KeyedResourceKey): void;
91
- onUpdate<K extends keyof TData & string>(key: K, callback: (state: TData[K], previousState: TData[K]) => void): () => void;
91
+ startLoading<K extends StoreKey<TData>>(key: K): void;
92
+ stopLoading<K extends StoreKey<TData>>(key: K): void;
93
+ updateKeyedOne<K extends StoreKey<TData>>(key: K, resourceKey: KeyedResourceKey, entity: unknown): void;
94
+ clearKeyedOne<K extends StoreKey<TData>>(key: K, resourceKey: KeyedResourceKey): void;
95
+ startKeyedLoading<K extends StoreKey<TData>>(key: K, resourceKey: KeyedResourceKey): void;
96
+ onUpdate<K extends StoreKey<TData>>(key: K, callback: (state: TData[K], previousState: TData[K]) => void): () => void;
92
97
  private notifyHooks;
93
98
  }
94
99
 
@@ -104,10 +109,11 @@ interface AsStep<TAccum extends StoreConfig, TKey extends string> {
104
109
  */
105
110
  interface StoreBuilder<TAccum extends StoreConfig> {
106
111
  resource<TKey extends string>(key: TKey): AsStep<TAccum, TKey>;
107
- mirror<TSourceData extends Record<string, ResourceState<unknown>>>(source: InjectionToken<IStore<TSourceData>>, sourceKey: keyof TSourceData & string, targetKey?: keyof TAccum & string): StoreBuilder<TAccum>;
108
- mirrorKeyed<TSourceData extends Record<string, ResourceState<unknown>>, TEntity>(source: InjectionToken<IStore<TSourceData>>, sourceKey: keyof TSourceData & string, options: {
112
+ mirror<TSourceData extends StoreDataShape<TSourceData>>(source: InjectionToken<IStore<TSourceData>>, sourceKey: StoreKey<TSourceData>, targetKey?: StoreKey<TAccum>): StoreBuilder<TAccum>;
113
+ mirrorSelf(sourceKey: StoreKey<TAccum>, targetKey: StoreKey<TAccum>): StoreBuilder<TAccum>;
114
+ mirrorKeyed<TSourceData extends StoreDataShape<TSourceData>, TEntity>(source: InjectionToken<IStore<TSourceData>>, sourceKey: StoreKey<TSourceData>, options: {
109
115
  extractId: (data: TEntity | undefined) => KeyedResourceKey | undefined;
110
- }, targetKey?: keyof TAccum & string): StoreBuilder<TAccum>;
116
+ }, targetKey?: StoreKey<TAccum>): StoreBuilder<TAccum>;
111
117
  build(): InjectionToken<BaseStore<InferEnum<TAccum>, InferData<TAccum>>>;
112
118
  }
113
119
  /** Keys from the enum that have NOT yet been defined. */
@@ -121,19 +127,21 @@ interface ConstrainedAsStep<TEnum extends Record<string, string>, TAccum extends
121
127
  * defined yet. `.build()` is only available when all keys are accounted for.
122
128
  */
123
129
  type ConstrainedBuilder<TEnum extends Record<string, string>, TAccum extends StoreConfig> = [Remaining<TEnum, TAccum>] extends [never] ? {
124
- mirror<TSourceData extends Record<string, ResourceState<unknown>>>(source: InjectionToken<IStore<TSourceData>>, sourceKey: keyof TSourceData & string, targetKey?: keyof TAccum & string): ConstrainedBuilder<TEnum, TAccum>;
125
- mirrorKeyed<TSourceData extends Record<string, ResourceState<unknown>>, TEntity>(source: InjectionToken<IStore<TSourceData>>, sourceKey: keyof TSourceData & string, options: {
130
+ mirror<TSourceData extends StoreDataShape<TSourceData>>(source: InjectionToken<IStore<TSourceData>>, sourceKey: StoreKey<TSourceData>, targetKey?: StoreKey<TAccum>): ConstrainedBuilder<TEnum, TAccum>;
131
+ mirrorSelf(sourceKey: StoreKey<TAccum>, targetKey: StoreKey<TAccum>): ConstrainedBuilder<TEnum, TAccum>;
132
+ mirrorKeyed<TSourceData extends StoreDataShape<TSourceData>, TEntity>(source: InjectionToken<IStore<TSourceData>>, sourceKey: StoreKey<TSourceData>, options: {
126
133
  extractId: (data: TEntity | undefined) => KeyedResourceKey | undefined;
127
- }, targetKey?: keyof TAccum & string): ConstrainedBuilder<TEnum, TAccum>;
134
+ }, targetKey?: StoreKey<TAccum>): ConstrainedBuilder<TEnum, TAccum>;
128
135
  build(): InjectionToken<BaseStore<InferEnum<TAccum>, InferData<TAccum>>>;
129
136
  } : {
130
137
  resource<TKey extends Remaining<TEnum, TAccum>>(key: TKey): ConstrainedAsStep<TEnum, TAccum, TKey>;
131
138
  };
132
- interface InterfaceBuilder<TConfig extends Record<string, unknown>> {
133
- mirror<TSourceData extends Record<string, ResourceState<unknown>>>(source: InjectionToken<IStore<TSourceData>>, sourceKey: keyof TSourceData & string, targetKey?: keyof TConfig & string): InterfaceBuilder<TConfig>;
134
- mirrorKeyed<TSourceData extends Record<string, ResourceState<unknown>>, TEntity>(source: InjectionToken<IStore<TSourceData>>, sourceKey: keyof TSourceData & string, options: {
139
+ interface InterfaceBuilder<TConfig extends object> {
140
+ mirror<TSourceData extends StoreDataShape<TSourceData>>(source: InjectionToken<IStore<TSourceData>>, sourceKey: StoreKey<TSourceData>, targetKey?: StoreKey<ConfigToData<TConfig>>): InterfaceBuilder<TConfig>;
141
+ mirrorSelf(sourceKey: StoreKey<ConfigToData<TConfig>>, targetKey: StoreKey<ConfigToData<TConfig>>): InterfaceBuilder<TConfig>;
142
+ mirrorKeyed<TSourceData extends StoreDataShape<TSourceData>, TEntity>(source: InjectionToken<IStore<TSourceData>>, sourceKey: StoreKey<TSourceData>, options: {
135
143
  extractId: (data: TEntity | undefined) => KeyedResourceKey | undefined;
136
- }, targetKey?: keyof TConfig & string): InterfaceBuilder<TConfig>;
144
+ }, targetKey?: StoreKey<ConfigToData<TConfig>>): InterfaceBuilder<TConfig>;
137
145
  build(): InjectionToken<IStore<ConfigToData<TConfig>>>;
138
146
  }
139
147
  interface StoreEntry {
@@ -156,7 +164,7 @@ interface StoreEntry {
156
164
  * }
157
165
  * const ChatStore = Store.for<ChatStoreConfig>().build();
158
166
  */
159
- for<TConfig extends Record<string, unknown>>(): InterfaceBuilder<TConfig>;
167
+ for<TConfig extends object>(): InterfaceBuilder<TConfig>;
160
168
  /**
161
169
  * Bind the builder to an enum object for compile-time key validation.
162
170
  *
@@ -167,7 +175,7 @@ interface StoreEntry {
167
175
  * .resource('B').as<number>()
168
176
  * .build();
169
177
  */
170
- for<TEnum extends Record<string, string>>(enumObj: TEnum): ConstrainedBuilder<TEnum, Record<string, never>>;
178
+ for<TEnum extends Record<string, string>>(enumObj: TEnum): ConstrainedBuilder<TEnum, Record<never, never>>;
171
179
  }
172
180
  /**
173
181
  * Fluent store builder entry point.
@@ -189,6 +197,8 @@ interface StoreEntry {
189
197
  */
190
198
  declare const Store: StoreEntry;
191
199
 
200
+ declare function clearAllStores(): void;
201
+
192
202
  interface MirrorOptions {
193
203
  destroyRef?: {
194
204
  onDestroy: (fn: () => void) => void;
@@ -205,7 +215,7 @@ interface MirrorOptions {
205
215
  * @param options - Mirror options when a target key is provided
206
216
  * @returns Cleanup function to stop mirroring
207
217
  */
208
- declare function mirrorKey<TSource extends Record<string, ResourceState<unknown>>, TTarget extends Record<string, ResourceState<unknown>>>(source: IStore<TSource>, sourceKey: keyof TSource & string, target: IStore<TTarget>, targetKeyOrOptions?: (keyof TTarget & string) | MirrorOptions, options?: MirrorOptions): () => void;
218
+ 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;
209
219
 
210
220
  interface CollectKeyedOptions<TEntity> {
211
221
  extractId: (data: TEntity | undefined) => KeyedResourceKey | undefined;
@@ -229,6 +239,6 @@ interface CollectKeyedOptions<TEntity> {
229
239
  * @param options - Collect options when a target key is provided
230
240
  * @returns Cleanup function to stop collecting
231
241
  */
232
- declare function collectKeyed<TSource extends Record<string, ResourceState<unknown>>, TTarget extends Record<string, ResourceState<unknown>>, TEntity = unknown>(source: IStore<TSource>, sourceKey: keyof TSource & string, target: IStore<TTarget>, targetKeyOrOptions?: (keyof TTarget & string) | CollectKeyedOptions<TEntity>, options?: CollectKeyedOptions<TEntity>): () => void;
242
+ declare function collectKeyed<TSource extends StoreDataShape<TSource>, TTarget extends StoreDataShape<TTarget>, TEntity = unknown>(source: IStore<TSource>, sourceKey: StoreKey<TSource>, target: IStore<TTarget>, targetKeyOrOptions?: StoreKey<TTarget> | CollectKeyedOptions<TEntity>, options?: CollectKeyedOptions<TEntity>): () => void;
233
243
 
234
- export { BaseStore, type CollectKeyedOptions, type ConfigToData, type IStore, LazyStore, type MirrorOptions, Store, collectKeyed, mirrorKey };
244
+ export { BaseStore, type CollectKeyedOptions, type ConfigToData, type IStore, LazyStore, type MirrorOptions, Store, clearAllStores, collectKeyed, mirrorKey };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,10 @@
1
1
  import { Signal, InjectionToken } from '@angular/core';
2
2
  import { ResourceState, KeyedResourceKey } from '@flurryx/core';
3
3
 
4
+ type StoreDataShape<TData> = {
5
+ [K in keyof TData]: ResourceState<unknown>;
6
+ };
7
+ type StoreKey<TData> = keyof TData & string;
4
8
  /**
5
9
  * Phantom-typed marker for a store resource slot.
6
10
  * Carries type information at compile time with zero runtime cost.
@@ -31,23 +35,23 @@ type InferData<TConfig extends StoreConfig> = {
31
35
  * Maps a plain config interface to ResourceState-wrapped data.
32
36
  * e.g. { SESSIONS: ChatSession[] } -> { SESSIONS: ResourceState<ChatSession[]> }
33
37
  */
34
- type ConfigToData<TConfig extends Record<string, unknown>> = {
38
+ type ConfigToData<TConfig extends object> = {
35
39
  [K in keyof TConfig & string]: ResourceState<TConfig[K]>;
36
40
  };
37
41
  /**
38
42
  * Shared store interface implemented by both BaseStore and LazyStore.
39
43
  */
40
- interface IStore<TData extends Record<string, ResourceState<unknown>>> {
41
- get<K extends keyof TData & string>(key: K): Signal<TData[K]>;
42
- update<K extends keyof TData & string>(key: K, newState: Partial<TData[K]>): void;
43
- clear<K extends keyof TData & string>(key: K): void;
44
+ interface IStore<TData extends StoreDataShape<TData>> {
45
+ get<K extends StoreKey<TData>>(key: K): Signal<TData[K]>;
46
+ update<K extends StoreKey<TData>>(key: K, newState: Partial<TData[K]>): void;
47
+ clear<K extends StoreKey<TData>>(key: K): void;
44
48
  clearAll(): void;
45
- startLoading<K extends keyof TData & string>(key: K): void;
46
- stopLoading<K extends keyof TData & string>(key: K): void;
47
- updateKeyedOne<K extends keyof TData & string>(key: K, resourceKey: KeyedResourceKey, entity: unknown): void;
48
- clearKeyedOne<K extends keyof TData & string>(key: K, resourceKey: KeyedResourceKey): void;
49
- startKeyedLoading<K extends keyof TData & string>(key: K, resourceKey: KeyedResourceKey): void;
50
- onUpdate<K extends keyof TData & string>(key: K, callback: (state: TData[K], previousState: TData[K]) => void): () => void;
49
+ startLoading<K extends StoreKey<TData>>(key: K): void;
50
+ stopLoading<K extends StoreKey<TData>>(key: K): void;
51
+ updateKeyedOne<K extends StoreKey<TData>>(key: K, resourceKey: KeyedResourceKey, entity: unknown): void;
52
+ clearKeyedOne<K extends StoreKey<TData>>(key: K, resourceKey: KeyedResourceKey): void;
53
+ startKeyedLoading<K extends StoreKey<TData>>(key: K, resourceKey: KeyedResourceKey): void;
54
+ onUpdate<K extends StoreKey<TData>>(key: K, callback: (state: TData[K], previousState: TData[K]) => void): () => void;
51
55
  }
52
56
 
53
57
  declare abstract class BaseStore<TEnum extends Record<string, string | number>, TData extends {
@@ -75,20 +79,21 @@ declare abstract class BaseStore<TEnum extends Record<string, string | number>,
75
79
  * Used by the `Store.for<Config>().build()` API where keys are
76
80
  * known only at the type level (no runtime enum).
77
81
  */
78
- declare class LazyStore<TData extends Record<string, ResourceState<unknown>>> implements IStore<TData> {
82
+ declare class LazyStore<TData extends StoreDataShape<TData>> implements IStore<TData> {
79
83
  private readonly signals;
80
84
  private readonly hooks;
85
+ constructor();
81
86
  private getOrCreate;
82
- get<K extends keyof TData & string>(key: K): Signal<TData[K]>;
83
- update<K extends keyof TData & string>(key: K, newState: Partial<TData[K]>): void;
84
- clear<K extends keyof TData & string>(key: K): void;
87
+ get<K extends StoreKey<TData>>(key: K): Signal<TData[K]>;
88
+ update<K extends StoreKey<TData>>(key: K, newState: Partial<TData[K]>): void;
89
+ clear<K extends StoreKey<TData>>(key: K): void;
85
90
  clearAll(): void;
86
- startLoading<K extends keyof TData & string>(key: K): void;
87
- stopLoading<K extends keyof TData & string>(key: K): void;
88
- updateKeyedOne<K extends keyof TData & string>(key: K, resourceKey: KeyedResourceKey, entity: unknown): void;
89
- clearKeyedOne<K extends keyof TData & string>(key: K, resourceKey: KeyedResourceKey): void;
90
- startKeyedLoading<K extends keyof TData & string>(key: K, resourceKey: KeyedResourceKey): void;
91
- onUpdate<K extends keyof TData & string>(key: K, callback: (state: TData[K], previousState: TData[K]) => void): () => void;
91
+ startLoading<K extends StoreKey<TData>>(key: K): void;
92
+ stopLoading<K extends StoreKey<TData>>(key: K): void;
93
+ updateKeyedOne<K extends StoreKey<TData>>(key: K, resourceKey: KeyedResourceKey, entity: unknown): void;
94
+ clearKeyedOne<K extends StoreKey<TData>>(key: K, resourceKey: KeyedResourceKey): void;
95
+ startKeyedLoading<K extends StoreKey<TData>>(key: K, resourceKey: KeyedResourceKey): void;
96
+ onUpdate<K extends StoreKey<TData>>(key: K, callback: (state: TData[K], previousState: TData[K]) => void): () => void;
92
97
  private notifyHooks;
93
98
  }
94
99
 
@@ -104,10 +109,11 @@ interface AsStep<TAccum extends StoreConfig, TKey extends string> {
104
109
  */
105
110
  interface StoreBuilder<TAccum extends StoreConfig> {
106
111
  resource<TKey extends string>(key: TKey): AsStep<TAccum, TKey>;
107
- mirror<TSourceData extends Record<string, ResourceState<unknown>>>(source: InjectionToken<IStore<TSourceData>>, sourceKey: keyof TSourceData & string, targetKey?: keyof TAccum & string): StoreBuilder<TAccum>;
108
- mirrorKeyed<TSourceData extends Record<string, ResourceState<unknown>>, TEntity>(source: InjectionToken<IStore<TSourceData>>, sourceKey: keyof TSourceData & string, options: {
112
+ mirror<TSourceData extends StoreDataShape<TSourceData>>(source: InjectionToken<IStore<TSourceData>>, sourceKey: StoreKey<TSourceData>, targetKey?: StoreKey<TAccum>): StoreBuilder<TAccum>;
113
+ mirrorSelf(sourceKey: StoreKey<TAccum>, targetKey: StoreKey<TAccum>): StoreBuilder<TAccum>;
114
+ mirrorKeyed<TSourceData extends StoreDataShape<TSourceData>, TEntity>(source: InjectionToken<IStore<TSourceData>>, sourceKey: StoreKey<TSourceData>, options: {
109
115
  extractId: (data: TEntity | undefined) => KeyedResourceKey | undefined;
110
- }, targetKey?: keyof TAccum & string): StoreBuilder<TAccum>;
116
+ }, targetKey?: StoreKey<TAccum>): StoreBuilder<TAccum>;
111
117
  build(): InjectionToken<BaseStore<InferEnum<TAccum>, InferData<TAccum>>>;
112
118
  }
113
119
  /** Keys from the enum that have NOT yet been defined. */
@@ -121,19 +127,21 @@ interface ConstrainedAsStep<TEnum extends Record<string, string>, TAccum extends
121
127
  * defined yet. `.build()` is only available when all keys are accounted for.
122
128
  */
123
129
  type ConstrainedBuilder<TEnum extends Record<string, string>, TAccum extends StoreConfig> = [Remaining<TEnum, TAccum>] extends [never] ? {
124
- mirror<TSourceData extends Record<string, ResourceState<unknown>>>(source: InjectionToken<IStore<TSourceData>>, sourceKey: keyof TSourceData & string, targetKey?: keyof TAccum & string): ConstrainedBuilder<TEnum, TAccum>;
125
- mirrorKeyed<TSourceData extends Record<string, ResourceState<unknown>>, TEntity>(source: InjectionToken<IStore<TSourceData>>, sourceKey: keyof TSourceData & string, options: {
130
+ mirror<TSourceData extends StoreDataShape<TSourceData>>(source: InjectionToken<IStore<TSourceData>>, sourceKey: StoreKey<TSourceData>, targetKey?: StoreKey<TAccum>): ConstrainedBuilder<TEnum, TAccum>;
131
+ mirrorSelf(sourceKey: StoreKey<TAccum>, targetKey: StoreKey<TAccum>): ConstrainedBuilder<TEnum, TAccum>;
132
+ mirrorKeyed<TSourceData extends StoreDataShape<TSourceData>, TEntity>(source: InjectionToken<IStore<TSourceData>>, sourceKey: StoreKey<TSourceData>, options: {
126
133
  extractId: (data: TEntity | undefined) => KeyedResourceKey | undefined;
127
- }, targetKey?: keyof TAccum & string): ConstrainedBuilder<TEnum, TAccum>;
134
+ }, targetKey?: StoreKey<TAccum>): ConstrainedBuilder<TEnum, TAccum>;
128
135
  build(): InjectionToken<BaseStore<InferEnum<TAccum>, InferData<TAccum>>>;
129
136
  } : {
130
137
  resource<TKey extends Remaining<TEnum, TAccum>>(key: TKey): ConstrainedAsStep<TEnum, TAccum, TKey>;
131
138
  };
132
- interface InterfaceBuilder<TConfig extends Record<string, unknown>> {
133
- mirror<TSourceData extends Record<string, ResourceState<unknown>>>(source: InjectionToken<IStore<TSourceData>>, sourceKey: keyof TSourceData & string, targetKey?: keyof TConfig & string): InterfaceBuilder<TConfig>;
134
- mirrorKeyed<TSourceData extends Record<string, ResourceState<unknown>>, TEntity>(source: InjectionToken<IStore<TSourceData>>, sourceKey: keyof TSourceData & string, options: {
139
+ interface InterfaceBuilder<TConfig extends object> {
140
+ mirror<TSourceData extends StoreDataShape<TSourceData>>(source: InjectionToken<IStore<TSourceData>>, sourceKey: StoreKey<TSourceData>, targetKey?: StoreKey<ConfigToData<TConfig>>): InterfaceBuilder<TConfig>;
141
+ mirrorSelf(sourceKey: StoreKey<ConfigToData<TConfig>>, targetKey: StoreKey<ConfigToData<TConfig>>): InterfaceBuilder<TConfig>;
142
+ mirrorKeyed<TSourceData extends StoreDataShape<TSourceData>, TEntity>(source: InjectionToken<IStore<TSourceData>>, sourceKey: StoreKey<TSourceData>, options: {
135
143
  extractId: (data: TEntity | undefined) => KeyedResourceKey | undefined;
136
- }, targetKey?: keyof TConfig & string): InterfaceBuilder<TConfig>;
144
+ }, targetKey?: StoreKey<ConfigToData<TConfig>>): InterfaceBuilder<TConfig>;
137
145
  build(): InjectionToken<IStore<ConfigToData<TConfig>>>;
138
146
  }
139
147
  interface StoreEntry {
@@ -156,7 +164,7 @@ interface StoreEntry {
156
164
  * }
157
165
  * const ChatStore = Store.for<ChatStoreConfig>().build();
158
166
  */
159
- for<TConfig extends Record<string, unknown>>(): InterfaceBuilder<TConfig>;
167
+ for<TConfig extends object>(): InterfaceBuilder<TConfig>;
160
168
  /**
161
169
  * Bind the builder to an enum object for compile-time key validation.
162
170
  *
@@ -167,7 +175,7 @@ interface StoreEntry {
167
175
  * .resource('B').as<number>()
168
176
  * .build();
169
177
  */
170
- for<TEnum extends Record<string, string>>(enumObj: TEnum): ConstrainedBuilder<TEnum, Record<string, never>>;
178
+ for<TEnum extends Record<string, string>>(enumObj: TEnum): ConstrainedBuilder<TEnum, Record<never, never>>;
171
179
  }
172
180
  /**
173
181
  * Fluent store builder entry point.
@@ -189,6 +197,8 @@ interface StoreEntry {
189
197
  */
190
198
  declare const Store: StoreEntry;
191
199
 
200
+ declare function clearAllStores(): void;
201
+
192
202
  interface MirrorOptions {
193
203
  destroyRef?: {
194
204
  onDestroy: (fn: () => void) => void;
@@ -205,7 +215,7 @@ interface MirrorOptions {
205
215
  * @param options - Mirror options when a target key is provided
206
216
  * @returns Cleanup function to stop mirroring
207
217
  */
208
- declare function mirrorKey<TSource extends Record<string, ResourceState<unknown>>, TTarget extends Record<string, ResourceState<unknown>>>(source: IStore<TSource>, sourceKey: keyof TSource & string, target: IStore<TTarget>, targetKeyOrOptions?: (keyof TTarget & string) | MirrorOptions, options?: MirrorOptions): () => void;
218
+ 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;
209
219
 
210
220
  interface CollectKeyedOptions<TEntity> {
211
221
  extractId: (data: TEntity | undefined) => KeyedResourceKey | undefined;
@@ -229,6 +239,6 @@ interface CollectKeyedOptions<TEntity> {
229
239
  * @param options - Collect options when a target key is provided
230
240
  * @returns Cleanup function to stop collecting
231
241
  */
232
- declare function collectKeyed<TSource extends Record<string, ResourceState<unknown>>, TTarget extends Record<string, ResourceState<unknown>>, TEntity = unknown>(source: IStore<TSource>, sourceKey: keyof TSource & string, target: IStore<TTarget>, targetKeyOrOptions?: (keyof TTarget & string) | CollectKeyedOptions<TEntity>, options?: CollectKeyedOptions<TEntity>): () => void;
242
+ declare function collectKeyed<TSource extends StoreDataShape<TSource>, TTarget extends StoreDataShape<TTarget>, TEntity = unknown>(source: IStore<TSource>, sourceKey: StoreKey<TSource>, target: IStore<TTarget>, targetKeyOrOptions?: StoreKey<TTarget> | CollectKeyedOptions<TEntity>, options?: CollectKeyedOptions<TEntity>): () => void;
233
243
 
234
- export { BaseStore, type CollectKeyedOptions, type ConfigToData, type IStore, LazyStore, type MirrorOptions, Store, collectKeyed, mirrorKey };
244
+ export { BaseStore, type CollectKeyedOptions, type ConfigToData, type IStore, LazyStore, type MirrorOptions, Store, clearAllStores, collectKeyed, mirrorKey };
package/dist/index.js CHANGED
@@ -5,12 +5,26 @@ import {
5
5
  isKeyedResourceData,
6
6
  createKeyedResourceData
7
7
  } from "@flurryx/core";
8
+
9
+ // src/store-registry.ts
10
+ var trackedStores = /* @__PURE__ */ new Set();
11
+ function trackStore(store) {
12
+ trackedStores.add(store);
13
+ }
14
+ function clearAllStores() {
15
+ for (const store of [...trackedStores]) {
16
+ store.clearAll();
17
+ }
18
+ }
19
+
20
+ // src/base-store.ts
8
21
  var updateHooksMap = /* @__PURE__ */ new WeakMap();
9
22
  var BaseStore = class {
10
23
  constructor(storeEnum) {
11
24
  this.storeEnum = storeEnum;
12
25
  this.initializeState();
13
26
  updateHooksMap.set(this, /* @__PURE__ */ new Map());
27
+ trackStore(this);
14
28
  }
15
29
  signalsState = /* @__PURE__ */ new Map();
16
30
  get(key) {
@@ -263,6 +277,9 @@ function createDefaultState() {
263
277
  var LazyStore = class {
264
278
  signals = /* @__PURE__ */ new Map();
265
279
  hooks = /* @__PURE__ */ new Map();
280
+ constructor() {
281
+ trackStore(this);
282
+ }
266
283
  getOrCreate(key) {
267
284
  let sig = this.signals.get(key);
268
285
  if (!sig) {
@@ -575,7 +592,22 @@ function wireMirrorKeyed(store, defs) {
575
592
  }
576
593
  return store;
577
594
  }
578
- function createBuilder(accum, mirrors = [], mirrorKeyedDefs = []) {
595
+ var MIRROR_SELF_SAME_KEY_ERROR = "mirrorSelf source and target keys must be different";
596
+ function wireSelfMirrors(store, defs) {
597
+ for (const def of defs) {
598
+ if (def.sourceKey === def.targetKey) {
599
+ throw new Error(MIRROR_SELF_SAME_KEY_ERROR);
600
+ }
601
+ mirrorKey(
602
+ store,
603
+ def.sourceKey,
604
+ store,
605
+ def.targetKey
606
+ );
607
+ }
608
+ return store;
609
+ }
610
+ function createBuilder(accum, mirrors = [], mirrorKeyedDefs = [], selfMirrors = []) {
579
611
  return {
580
612
  resource(key) {
581
613
  return {
@@ -584,7 +616,12 @@ function createBuilder(accum, mirrors = [], mirrorKeyedDefs = []) {
584
616
  ...accum,
585
617
  [key]: resource()
586
618
  };
587
- return createBuilder(nextAccum, mirrors, mirrorKeyedDefs);
619
+ return createBuilder(
620
+ nextAccum,
621
+ mirrors,
622
+ mirrorKeyedDefs,
623
+ selfMirrors
624
+ );
588
625
  }
589
626
  };
590
627
  },
@@ -594,7 +631,22 @@ function createBuilder(accum, mirrors = [], mirrorKeyedDefs = []) {
594
631
  sourceKey,
595
632
  targetKey: targetKey ?? sourceKey
596
633
  };
597
- return createBuilder(accum, [...mirrors, def], mirrorKeyedDefs);
634
+ return createBuilder(
635
+ accum,
636
+ [...mirrors, def],
637
+ mirrorKeyedDefs,
638
+ selfMirrors
639
+ );
640
+ },
641
+ mirrorSelf(sourceKey, targetKey) {
642
+ const def = {
643
+ sourceKey,
644
+ targetKey
645
+ };
646
+ return createBuilder(accum, mirrors, mirrorKeyedDefs, [
647
+ ...selfMirrors,
648
+ def
649
+ ]);
598
650
  },
599
651
  mirrorKeyed(source, sourceKey, options, targetKey) {
600
652
  const def = {
@@ -603,7 +655,12 @@ function createBuilder(accum, mirrors = [], mirrorKeyedDefs = []) {
603
655
  targetKey: targetKey ?? sourceKey,
604
656
  extractId: options.extractId
605
657
  };
606
- return createBuilder(accum, mirrors, [...mirrorKeyedDefs, def]);
658
+ return createBuilder(
659
+ accum,
660
+ mirrors,
661
+ [...mirrorKeyedDefs, def],
662
+ selfMirrors
663
+ );
607
664
  },
608
665
  build() {
609
666
  return new InjectionToken("FlurryxStore", {
@@ -612,13 +669,14 @@ function createBuilder(accum, mirrors = [], mirrorKeyedDefs = []) {
612
669
  const store = new DynamicStore(accum);
613
670
  wireMirrors(store, mirrors);
614
671
  wireMirrorKeyed(store, mirrorKeyedDefs);
672
+ wireSelfMirrors(store, selfMirrors);
615
673
  return store;
616
674
  }
617
675
  });
618
676
  }
619
677
  };
620
678
  }
621
- function createConstrainedBuilder(_enumObj, accum, mirrors = [], mirrorKeyedDefs = []) {
679
+ function createConstrainedBuilder(_enumObj, accum, mirrors = [], mirrorKeyedDefs = [], selfMirrors = []) {
622
680
  return {
623
681
  resource(key) {
624
682
  return {
@@ -631,7 +689,8 @@ function createConstrainedBuilder(_enumObj, accum, mirrors = [], mirrorKeyedDefs
631
689
  _enumObj,
632
690
  nextAccum,
633
691
  mirrors,
634
- mirrorKeyedDefs
692
+ mirrorKeyedDefs,
693
+ selfMirrors
635
694
  );
636
695
  }
637
696
  };
@@ -646,7 +705,21 @@ function createConstrainedBuilder(_enumObj, accum, mirrors = [], mirrorKeyedDefs
646
705
  _enumObj,
647
706
  accum,
648
707
  [...mirrors, def],
649
- mirrorKeyedDefs
708
+ mirrorKeyedDefs,
709
+ selfMirrors
710
+ );
711
+ },
712
+ mirrorSelf(sourceKey, targetKey) {
713
+ const def = {
714
+ sourceKey,
715
+ targetKey
716
+ };
717
+ return createConstrainedBuilder(
718
+ _enumObj,
719
+ accum,
720
+ mirrors,
721
+ mirrorKeyedDefs,
722
+ [...selfMirrors, def]
650
723
  );
651
724
  },
652
725
  mirrorKeyed(source, sourceKey, options, targetKey) {
@@ -656,10 +729,13 @@ function createConstrainedBuilder(_enumObj, accum, mirrors = [], mirrorKeyedDefs
656
729
  targetKey: targetKey ?? sourceKey,
657
730
  extractId: options.extractId
658
731
  };
659
- return createConstrainedBuilder(_enumObj, accum, mirrors, [
660
- ...mirrorKeyedDefs,
661
- def
662
- ]);
732
+ return createConstrainedBuilder(
733
+ _enumObj,
734
+ accum,
735
+ mirrors,
736
+ [...mirrorKeyedDefs, def],
737
+ selfMirrors
738
+ );
663
739
  },
664
740
  build() {
665
741
  return new InjectionToken("FlurryxStore", {
@@ -668,13 +744,14 @@ function createConstrainedBuilder(_enumObj, accum, mirrors = [], mirrorKeyedDefs
668
744
  const store = new DynamicStore(accum);
669
745
  wireMirrors(store, mirrors);
670
746
  wireMirrorKeyed(store, mirrorKeyedDefs);
747
+ wireSelfMirrors(store, selfMirrors);
671
748
  return store;
672
749
  }
673
750
  });
674
751
  }
675
752
  };
676
753
  }
677
- function createInterfaceBuilder(mirrors = [], mirrorKeyedDefs = []) {
754
+ function createInterfaceBuilder(mirrors = [], mirrorKeyedDefs = [], selfMirrors = []) {
678
755
  return {
679
756
  mirror(source, sourceKey, targetKey) {
680
757
  const def = {
@@ -684,9 +761,20 @@ function createInterfaceBuilder(mirrors = [], mirrorKeyedDefs = []) {
684
761
  };
685
762
  return createInterfaceBuilder(
686
763
  [...mirrors, def],
687
- mirrorKeyedDefs
764
+ mirrorKeyedDefs,
765
+ selfMirrors
688
766
  );
689
767
  },
768
+ mirrorSelf(sourceKey, targetKey) {
769
+ const def = {
770
+ sourceKey,
771
+ targetKey
772
+ };
773
+ return createInterfaceBuilder(mirrors, mirrorKeyedDefs, [
774
+ ...selfMirrors,
775
+ def
776
+ ]);
777
+ },
690
778
  mirrorKeyed(source, sourceKey, options, targetKey) {
691
779
  const def = {
692
780
  sourceToken: source,
@@ -694,10 +782,11 @@ function createInterfaceBuilder(mirrors = [], mirrorKeyedDefs = []) {
694
782
  targetKey: targetKey ?? sourceKey,
695
783
  extractId: options.extractId
696
784
  };
697
- return createInterfaceBuilder(mirrors, [
698
- ...mirrorKeyedDefs,
699
- def
700
- ]);
785
+ return createInterfaceBuilder(
786
+ mirrors,
787
+ [...mirrorKeyedDefs, def],
788
+ selfMirrors
789
+ );
701
790
  },
702
791
  build() {
703
792
  return new InjectionToken("FlurryxStore", {
@@ -706,6 +795,7 @@ function createInterfaceBuilder(mirrors = [], mirrorKeyedDefs = []) {
706
795
  const store = new LazyStore();
707
796
  wireMirrors(store, mirrors);
708
797
  wireMirrorKeyed(store, mirrorKeyedDefs);
798
+ wireSelfMirrors(store, selfMirrors);
709
799
  return store;
710
800
  }
711
801
  });
@@ -714,17 +804,19 @@ function createInterfaceBuilder(mirrors = [], mirrorKeyedDefs = []) {
714
804
  }
715
805
  var Store = {
716
806
  ...createBuilder({}),
717
- for(enumObj) {
718
- if (arguments.length === 0) {
719
- return createInterfaceBuilder();
720
- }
721
- return createConstrainedBuilder(enumObj, {});
722
- }
807
+ for: createStoreFor
723
808
  };
809
+ function createStoreFor(enumObj) {
810
+ if (arguments.length === 0) {
811
+ return createInterfaceBuilder();
812
+ }
813
+ return createConstrainedBuilder(enumObj, {});
814
+ }
724
815
  export {
725
816
  BaseStore,
726
817
  LazyStore,
727
818
  Store,
819
+ clearAllStores,
728
820
  collectKeyed,
729
821
  mirrorKey
730
822
  };