@flurryx/store 0.7.1 → 0.7.3
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.cjs +67 -30
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -3
- package/dist/index.d.ts +7 -3
- package/dist/index.js +68 -31
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -381,13 +381,36 @@ var DynamicStore = class extends BaseStore {
|
|
|
381
381
|
}
|
|
382
382
|
};
|
|
383
383
|
|
|
384
|
+
// src/mirror-key.ts
|
|
385
|
+
function mirrorKey(source, sourceKey, target, targetKeyOrOptions, options) {
|
|
386
|
+
const resolvedTargetKey = typeof targetKeyOrOptions === "string" ? targetKeyOrOptions : sourceKey;
|
|
387
|
+
const resolvedOptions = typeof targetKeyOrOptions === "object" ? targetKeyOrOptions : options;
|
|
388
|
+
const cleanup = source.onUpdate(sourceKey, (state) => {
|
|
389
|
+
target.update(
|
|
390
|
+
resolvedTargetKey,
|
|
391
|
+
state
|
|
392
|
+
);
|
|
393
|
+
});
|
|
394
|
+
if (resolvedOptions?.destroyRef) {
|
|
395
|
+
resolvedOptions.destroyRef.onDestroy(cleanup);
|
|
396
|
+
}
|
|
397
|
+
return cleanup;
|
|
398
|
+
}
|
|
399
|
+
|
|
384
400
|
// src/resource.ts
|
|
385
401
|
function resource() {
|
|
386
402
|
return {};
|
|
387
403
|
}
|
|
388
404
|
|
|
389
405
|
// src/store-builder.ts
|
|
390
|
-
function
|
|
406
|
+
function wireMirrors(store, mirrors) {
|
|
407
|
+
for (const def of mirrors) {
|
|
408
|
+
const sourceStore = (0, import_core4.inject)(def.sourceToken);
|
|
409
|
+
mirrorKey(sourceStore, def.sourceKey, store, def.targetKey);
|
|
410
|
+
}
|
|
411
|
+
return store;
|
|
412
|
+
}
|
|
413
|
+
function createBuilder(accum, mirrors = []) {
|
|
391
414
|
return {
|
|
392
415
|
resource(key) {
|
|
393
416
|
return {
|
|
@@ -396,19 +419,27 @@ function createBuilder(accum) {
|
|
|
396
419
|
...accum,
|
|
397
420
|
[key]: resource()
|
|
398
421
|
};
|
|
399
|
-
return createBuilder(nextAccum);
|
|
422
|
+
return createBuilder(nextAccum, mirrors);
|
|
400
423
|
}
|
|
401
424
|
};
|
|
402
425
|
},
|
|
426
|
+
mirror(source, sourceKey, targetKey) {
|
|
427
|
+
const def = {
|
|
428
|
+
sourceToken: source,
|
|
429
|
+
sourceKey,
|
|
430
|
+
targetKey: targetKey ?? sourceKey
|
|
431
|
+
};
|
|
432
|
+
return createBuilder(accum, [...mirrors, def]);
|
|
433
|
+
},
|
|
403
434
|
build() {
|
|
404
435
|
return new import_core4.InjectionToken("FlurryxStore", {
|
|
405
436
|
providedIn: "root",
|
|
406
|
-
factory: () => new DynamicStore(accum)
|
|
437
|
+
factory: () => wireMirrors(new DynamicStore(accum), mirrors)
|
|
407
438
|
});
|
|
408
439
|
}
|
|
409
440
|
};
|
|
410
441
|
}
|
|
411
|
-
function createConstrainedBuilder(_enumObj, accum) {
|
|
442
|
+
function createConstrainedBuilder(_enumObj, accum, mirrors = []) {
|
|
412
443
|
return {
|
|
413
444
|
resource(key) {
|
|
414
445
|
return {
|
|
@@ -417,14 +448,43 @@ function createConstrainedBuilder(_enumObj, accum) {
|
|
|
417
448
|
...accum,
|
|
418
449
|
[key]: resource()
|
|
419
450
|
};
|
|
420
|
-
return createConstrainedBuilder(_enumObj, nextAccum);
|
|
451
|
+
return createConstrainedBuilder(_enumObj, nextAccum, mirrors);
|
|
421
452
|
}
|
|
422
453
|
};
|
|
423
454
|
},
|
|
455
|
+
mirror(source, sourceKey, targetKey) {
|
|
456
|
+
const def = {
|
|
457
|
+
sourceToken: source,
|
|
458
|
+
sourceKey,
|
|
459
|
+
targetKey: targetKey ?? sourceKey
|
|
460
|
+
};
|
|
461
|
+
return createConstrainedBuilder(_enumObj, accum, [...mirrors, def]);
|
|
462
|
+
},
|
|
424
463
|
build() {
|
|
425
464
|
return new import_core4.InjectionToken("FlurryxStore", {
|
|
426
465
|
providedIn: "root",
|
|
427
|
-
factory: () => new DynamicStore(accum)
|
|
466
|
+
factory: () => wireMirrors(new DynamicStore(accum), mirrors)
|
|
467
|
+
});
|
|
468
|
+
}
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
function createInterfaceBuilder(mirrors = []) {
|
|
472
|
+
return {
|
|
473
|
+
mirror(source, sourceKey, targetKey) {
|
|
474
|
+
const def = {
|
|
475
|
+
sourceToken: source,
|
|
476
|
+
sourceKey,
|
|
477
|
+
targetKey: targetKey ?? sourceKey
|
|
478
|
+
};
|
|
479
|
+
return createInterfaceBuilder([...mirrors, def]);
|
|
480
|
+
},
|
|
481
|
+
build() {
|
|
482
|
+
return new import_core4.InjectionToken("FlurryxStore", {
|
|
483
|
+
providedIn: "root",
|
|
484
|
+
factory: () => wireMirrors(
|
|
485
|
+
new LazyStore(),
|
|
486
|
+
mirrors
|
|
487
|
+
)
|
|
428
488
|
});
|
|
429
489
|
}
|
|
430
490
|
};
|
|
@@ -433,35 +493,12 @@ var Store = {
|
|
|
433
493
|
...createBuilder({}),
|
|
434
494
|
for(enumObj) {
|
|
435
495
|
if (arguments.length === 0) {
|
|
436
|
-
return
|
|
437
|
-
build() {
|
|
438
|
-
return new import_core4.InjectionToken("FlurryxStore", {
|
|
439
|
-
providedIn: "root",
|
|
440
|
-
factory: () => new LazyStore()
|
|
441
|
-
});
|
|
442
|
-
}
|
|
443
|
-
};
|
|
496
|
+
return createInterfaceBuilder();
|
|
444
497
|
}
|
|
445
498
|
return createConstrainedBuilder(enumObj, {});
|
|
446
499
|
}
|
|
447
500
|
};
|
|
448
501
|
|
|
449
|
-
// src/mirror-key.ts
|
|
450
|
-
function mirrorKey(source, sourceKey, target, targetKeyOrOptions, options) {
|
|
451
|
-
const resolvedTargetKey = typeof targetKeyOrOptions === "string" ? targetKeyOrOptions : sourceKey;
|
|
452
|
-
const resolvedOptions = typeof targetKeyOrOptions === "object" ? targetKeyOrOptions : options;
|
|
453
|
-
const cleanup = source.onUpdate(sourceKey, (state) => {
|
|
454
|
-
target.update(
|
|
455
|
-
resolvedTargetKey,
|
|
456
|
-
state
|
|
457
|
-
);
|
|
458
|
-
});
|
|
459
|
-
if (resolvedOptions?.destroyRef) {
|
|
460
|
-
resolvedOptions.destroyRef.onDestroy(cleanup);
|
|
461
|
-
}
|
|
462
|
-
return cleanup;
|
|
463
|
-
}
|
|
464
|
-
|
|
465
502
|
// src/collect-keyed.ts
|
|
466
503
|
var import_core5 = require("@flurryx/core");
|
|
467
504
|
function collectKeyed(source, sourceKey, target, targetKeyOrOptions, options) {
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/base-store.ts","../src/lazy-store.ts","../src/store-builder.ts","../src/dynamic-store.ts","../src/resource.ts","../src/mirror-key.ts","../src/collect-keyed.ts"],"sourcesContent":["export { BaseStore } from \"./base-store\";\nexport { LazyStore } from \"./lazy-store\";\nexport { Store } from \"./store-builder\";\nexport { mirrorKey } from \"./mirror-key\";\nexport { collectKeyed } from \"./collect-keyed\";\nexport type { MirrorOptions } from \"./mirror-key\";\nexport type { CollectKeyedOptions } from \"./collect-keyed\";\nexport type { IStore, ConfigToData } from \"./types\";\n","import { signal, WritableSignal } from \"@angular/core\";\nimport {\n ResourceState,\n isAnyKeyLoading,\n isKeyedResourceData,\n createKeyedResourceData,\n type KeyedResourceKey,\n} from \"@flurryx/core\";\nimport type { IStore } from \"./types\";\n\ntype UpdateHooksMap = Map<\n unknown,\n Array<\n (\n nextState: ResourceState<unknown>,\n previousState: ResourceState<unknown>\n ) => void\n >\n>;\n\nconst updateHooksMap = new WeakMap<object, UpdateHooksMap>();\n\nexport abstract class BaseStore<\n TEnum extends Record<string, string | number>,\n TData extends { [K in keyof TEnum]: ResourceState<unknown> }\n> implements IStore<TData>\n{\n private readonly signalsState = new Map<\n keyof TEnum,\n WritableSignal<TData[keyof TEnum]>\n >();\n\n protected constructor(protected readonly storeEnum: TEnum) {\n this.initializeState();\n updateHooksMap.set(this, new Map());\n }\n\n get<K extends keyof TData>(key: K): WritableSignal<TData[K]> {\n return this.signalsState.get(key.toString()) as WritableSignal<TData[K]>;\n }\n\n onUpdate<K extends keyof TData>(\n key: K,\n callback: (state: TData[K], previousState: TData[K]) => void\n ): () => void {\n const hooks = updateHooksMap.get(this)!;\n if (!hooks.has(key)) {\n hooks.set(key, []);\n }\n hooks\n .get(key)!\n .push(\n callback as (\n nextState: ResourceState<unknown>,\n previousState: ResourceState<unknown>\n ) => void\n );\n\n return () => {\n const hooksMap = hooks.get(key);\n if (!hooksMap) {\n return;\n }\n const index = hooksMap.indexOf(\n callback as (\n nextState: ResourceState<unknown>,\n previousState: ResourceState<unknown>\n ) => void\n );\n if (index > -1) {\n hooksMap.splice(index, 1);\n }\n };\n }\n\n update<K extends keyof TData>(key: K, newState: Partial<TData[K]>): void {\n const currentState = this.signalsState.get(key.toString());\n if (!currentState) {\n return;\n }\n\n const previousState = currentState() as TData[K];\n currentState.update((state) => ({\n ...state,\n ...newState,\n }));\n\n const updatedState = currentState() as TData[K];\n this.notifyUpdateHooks(key, updatedState, previousState);\n }\n\n clearAll(): void {\n Object.keys(this.storeEnum).forEach((key) => {\n this.clear(key as keyof TData);\n });\n }\n\n clear<K extends keyof TData>(key: K): void {\n const currentState = this.signalsState.get(key.toString());\n if (!currentState) {\n return;\n }\n\n const previousState = currentState() as TData[K];\n const _typedKey = key as keyof TEnum;\n currentState.set({\n data: undefined,\n isLoading: false,\n status: undefined,\n errors: undefined,\n } as TData[typeof _typedKey]);\n\n const nextState = currentState() as TData[K];\n this.notifyUpdateHooks(key, nextState, previousState);\n }\n\n startLoading<K extends keyof TData>(key: K): void {\n const currentState = this.signalsState.get(key.toString());\n if (!currentState) {\n return;\n }\n\n const _typedKey = key as keyof TEnum;\n currentState.update(\n (state) =>\n ({\n ...state,\n status: undefined,\n isLoading: true,\n errors: undefined,\n } as TData[typeof _typedKey])\n );\n }\n\n stopLoading<K extends keyof TData>(key: K): void {\n const currentState = this.signalsState.get(key.toString());\n if (!currentState) {\n return;\n }\n\n const _typedKey = key as keyof TEnum;\n currentState.update(\n (state) =>\n ({\n ...state,\n isLoading: false,\n status: undefined,\n errors: undefined,\n } as TData[typeof _typedKey])\n );\n }\n\n updateKeyedOne<K extends keyof TData>(\n key: K,\n resourceKey: KeyedResourceKey,\n entity: unknown\n ): void {\n const currentState = this.signalsState.get(key.toString());\n if (!currentState) {\n return;\n }\n\n const state = currentState();\n const data = isKeyedResourceData(state.data)\n ? state.data\n : createKeyedResourceData();\n\n const nextErrors = { ...data.errors };\n delete nextErrors[resourceKey];\n\n const nextData = {\n ...data,\n entities: {\n ...data.entities,\n [resourceKey]: entity,\n },\n isLoading: {\n ...data.isLoading,\n [resourceKey]: false,\n },\n status: {\n ...data.status,\n [resourceKey]: \"Success\" as const,\n },\n errors: nextErrors,\n };\n\n this.update(key, {\n data: nextData as unknown,\n isLoading: isAnyKeyLoading(nextData.isLoading),\n status: undefined,\n errors: undefined,\n } as Partial<TData[K]>);\n }\n\n clearKeyedOne<K extends keyof TData>(\n key: K,\n resourceKey: KeyedResourceKey\n ): void {\n const currentState = this.signalsState.get(key.toString());\n if (!currentState) {\n return;\n }\n\n const previousState = currentState() as TData[K];\n const state = previousState as ResourceState<unknown>;\n if (!isKeyedResourceData(state.data)) {\n return;\n }\n\n const data = state.data;\n\n const nextEntities = { ...data.entities };\n delete nextEntities[resourceKey];\n\n const nextIsLoading = { ...data.isLoading };\n delete nextIsLoading[resourceKey];\n\n const nextStatus = { ...data.status };\n delete nextStatus[resourceKey];\n\n const nextErrors = { ...data.errors };\n delete nextErrors[resourceKey];\n\n const nextData = {\n ...data,\n entities: nextEntities,\n isLoading: nextIsLoading,\n status: nextStatus,\n errors: nextErrors,\n };\n\n const _typedKey = key as keyof TEnum;\n currentState.update(\n (prev) =>\n ({\n ...prev,\n data: nextData as unknown,\n status: undefined,\n isLoading: isAnyKeyLoading(nextIsLoading),\n errors: undefined,\n } as TData[typeof _typedKey])\n );\n\n const updatedState = currentState() as TData[K];\n this.notifyUpdateHooks(key, updatedState, previousState);\n }\n\n startKeyedLoading<K extends keyof TData>(\n key: K,\n resourceKey: KeyedResourceKey\n ): void {\n const currentState = this.signalsState.get(key.toString());\n if (!currentState) {\n return;\n }\n\n const _typedKey = key as keyof TEnum;\n const state = currentState();\n if (!isKeyedResourceData(state.data)) {\n this.startLoading(key);\n return;\n }\n\n const previousState = state as TData[K];\n const data = state.data;\n\n const nextIsLoading = {\n ...data.isLoading,\n [resourceKey]: true,\n } as typeof data.isLoading;\n\n const nextStatus: typeof data.status = {\n ...data.status,\n };\n delete nextStatus[resourceKey];\n\n const nextErrors: typeof data.errors = {\n ...data.errors,\n };\n delete nextErrors[resourceKey];\n\n const nextData = {\n ...data,\n isLoading: nextIsLoading,\n status: nextStatus,\n errors: nextErrors,\n };\n\n currentState.update(\n (previous) =>\n ({\n ...previous,\n data: nextData,\n status: undefined,\n isLoading: isAnyKeyLoading(nextIsLoading),\n errors: undefined,\n } as TData[typeof _typedKey])\n );\n\n const updatedState = currentState() as TData[K];\n this.notifyUpdateHooks(key, updatedState, previousState);\n }\n\n private notifyUpdateHooks<K extends keyof TData>(\n key: K,\n nextState: TData[K],\n previousState: TData[K]\n ): void {\n const hooks = updateHooksMap.get(this);\n const keyHooks = hooks?.get(key);\n if (!keyHooks) {\n return;\n }\n\n keyHooks.forEach((hook) =>\n hook(\n nextState as ResourceState<unknown>,\n previousState as ResourceState<unknown>\n )\n );\n }\n\n private initializeState(): void {\n Object.keys(this.storeEnum).forEach((key) => {\n const _typedKey = key as keyof TEnum;\n const initialState: ResourceState<unknown> = {\n data: undefined,\n isLoading: false,\n status: undefined,\n errors: undefined,\n };\n this.signalsState.set(\n _typedKey,\n signal<TData[typeof _typedKey]>(initialState as TData[typeof _typedKey])\n );\n });\n }\n}\n","import { signal, WritableSignal } from '@angular/core';\nimport type { ResourceState } from '@flurryx/core';\nimport type { IStore } from './types';\n\ntype UpdateCallback = (\n nextState: ResourceState<unknown>,\n previousState: ResourceState<unknown>\n) => void;\n\nfunction createDefaultState<T>(): ResourceState<T> {\n return {\n data: undefined,\n isLoading: false,\n status: undefined,\n errors: undefined,\n };\n}\n\n/**\n * Lazy store that creates signals on first access.\n * Used by the `Store.for<Config>().build()` API where keys are\n * known only at the type level (no runtime enum).\n */\nexport class LazyStore<\n TData extends Record<string, ResourceState<unknown>>,\n> implements IStore<TData>\n{\n private readonly signals = new Map<string, WritableSignal<ResourceState<unknown>>>();\n private readonly hooks = new Map<string, UpdateCallback[]>();\n\n private getOrCreate<K extends keyof TData & string>(\n key: K\n ): WritableSignal<TData[K]> {\n let sig = this.signals.get(key);\n if (!sig) {\n sig = signal<ResourceState<unknown>>(createDefaultState());\n this.signals.set(key, sig);\n }\n return sig as WritableSignal<TData[K]>;\n }\n\n get<K extends keyof TData & string>(key: K): WritableSignal<TData[K]> {\n return this.getOrCreate(key);\n }\n\n update<K extends keyof TData & string>(\n key: K,\n newState: Partial<TData[K]>\n ): void {\n const sig = this.getOrCreate(key);\n const previousState = sig();\n sig.update((state) => ({ ...state, ...newState }));\n const nextState = sig();\n this.notifyHooks(key, nextState, previousState);\n }\n\n clear<K extends keyof TData & string>(key: K): void {\n const sig = this.getOrCreate(key);\n const previousState = sig();\n sig.set(createDefaultState() as TData[K]);\n const nextState = sig();\n this.notifyHooks(key, nextState, previousState);\n }\n\n clearAll(): void {\n for (const key of this.signals.keys()) {\n this.clear(key as keyof TData & string);\n }\n }\n\n startLoading<K extends keyof TData & string>(key: K): void {\n const sig = this.getOrCreate(key);\n sig.update(\n (state) =>\n ({\n ...state,\n status: undefined,\n isLoading: true,\n errors: undefined,\n }) as TData[K]\n );\n }\n\n stopLoading<K extends keyof TData & string>(key: K): void {\n const sig = this.getOrCreate(key);\n sig.update(\n (state) =>\n ({\n ...state,\n isLoading: false,\n status: undefined,\n errors: undefined,\n }) as TData[K]\n );\n }\n\n onUpdate<K extends keyof TData & string>(\n key: K,\n callback: (state: TData[K], previousState: TData[K]) => void\n ): () => void {\n if (!this.hooks.has(key)) {\n this.hooks.set(key, []);\n }\n const typedCallback = callback as UpdateCallback;\n this.hooks.get(key)!.push(typedCallback);\n\n return () => {\n const keyHooks = this.hooks.get(key);\n if (!keyHooks) {\n return;\n }\n const index = keyHooks.indexOf(typedCallback);\n if (index > -1) {\n keyHooks.splice(index, 1);\n }\n };\n }\n\n private notifyHooks<K extends keyof TData & string>(\n key: K,\n nextState: TData[K],\n previousState: TData[K]\n ): void {\n const keyHooks = this.hooks.get(key);\n if (!keyHooks) {\n return;\n }\n keyHooks.forEach((hook) =>\n hook(\n nextState as ResourceState<unknown>,\n previousState as ResourceState<unknown>\n )\n );\n }\n}\n","import { InjectionToken } from \"@angular/core\";\nimport { BaseStore } from \"./base-store\";\nimport { DynamicStore } from \"./dynamic-store\";\nimport { LazyStore } from \"./lazy-store\";\nimport { resource } from \"./resource\";\nimport type {\n StoreConfig,\n ResourceDef,\n InferEnum,\n InferData,\n ConfigToData,\n IStore,\n} from \"./types\";\n\n// ---------------------------------------------------------------------------\n// Unconstrained builder (existing API)\n// ---------------------------------------------------------------------------\n\n/**\n * Intermediate builder step after .resource('key') — awaits .as<T>().\n */\ninterface AsStep<TAccum extends StoreConfig, TKey extends string> {\n as<T>(): StoreBuilder<TAccum & Record<TKey, ResourceDef<T>>>;\n}\n\n/**\n * Fluent builder for creating stores.\n * Accumulates resource definitions then produces an InjectionToken on .build().\n */\ninterface StoreBuilder<TAccum extends StoreConfig> {\n resource<TKey extends string>(key: TKey): AsStep<TAccum, TKey>;\n build(): InjectionToken<BaseStore<InferEnum<TAccum>, InferData<TAccum>>>;\n}\n\nfunction createBuilder<TAccum extends StoreConfig>(\n accum: TAccum\n): StoreBuilder<TAccum> {\n return {\n resource<TKey extends string>(key: TKey): AsStep<TAccum, TKey> {\n return {\n as<T>(): StoreBuilder<TAccum & Record<TKey, ResourceDef<T>>> {\n const nextAccum = {\n ...accum,\n [key]: resource<T>(),\n } as TAccum & Record<TKey, ResourceDef<T>>;\n return createBuilder(nextAccum);\n },\n };\n },\n build() {\n return new InjectionToken<\n BaseStore<InferEnum<TAccum>, InferData<TAccum>>\n >(\"FlurryxStore\", {\n providedIn: \"root\",\n factory: () => new DynamicStore(accum),\n });\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// Constrained builder (.for(enum) API)\n// ---------------------------------------------------------------------------\n\n/** Keys from the enum that have NOT yet been defined. */\ntype Remaining<\n TEnum extends Record<string, string>,\n TAccum extends StoreConfig\n> = Exclude<keyof TEnum & string, keyof TAccum>;\n\n/** Intermediate .as<T>() step for the constrained builder. */\ninterface ConstrainedAsStep<\n TEnum extends Record<string, string>,\n TAccum extends StoreConfig,\n TKey extends string\n> {\n as<T>(): ConstrainedBuilder<TEnum, TAccum & Record<TKey, ResourceDef<T>>>;\n}\n\n/**\n * Constrained builder — only allows keys from the enum that haven't been\n * defined yet. `.build()` is only available when all keys are accounted for.\n */\ntype ConstrainedBuilder<\n TEnum extends Record<string, string>,\n TAccum extends StoreConfig\n> = [Remaining<TEnum, TAccum>] extends [never]\n ? {\n build(): InjectionToken<BaseStore<InferEnum<TAccum>, InferData<TAccum>>>;\n }\n : {\n resource<TKey extends Remaining<TEnum, TAccum>>(\n key: TKey\n ): ConstrainedAsStep<TEnum, TAccum, TKey>;\n };\n\nfunction createConstrainedBuilder<\n TEnum extends Record<string, string>,\n TAccum extends StoreConfig\n>(_enumObj: TEnum, accum: TAccum): ConstrainedBuilder<TEnum, TAccum> {\n return {\n resource<TKey extends string>(\n key: TKey\n ): ConstrainedAsStep<TEnum, TAccum, TKey> {\n return {\n as<T>(): ConstrainedBuilder<\n TEnum,\n TAccum & Record<TKey, ResourceDef<T>>\n > {\n const nextAccum = {\n ...accum,\n [key]: resource<T>(),\n } as TAccum & Record<TKey, ResourceDef<T>>;\n return createConstrainedBuilder(_enumObj, nextAccum);\n },\n };\n },\n build() {\n return new InjectionToken<\n BaseStore<InferEnum<TAccum>, InferData<TAccum>>\n >(\"FlurryxStore\", {\n providedIn: \"root\",\n factory: () => new DynamicStore(accum),\n });\n },\n } as ConstrainedBuilder<TEnum, TAccum>;\n}\n\n// ---------------------------------------------------------------------------\n// Public entry point\n// ---------------------------------------------------------------------------\n\ninterface StoreEntry {\n /**\n * Define a named resource slot.\n * Chain .as<T>() to assign its type, then continue with more .resource() calls\n * or call .build() when done.\n */\n resource<TKey extends string>(\n key: TKey\n ): {\n as<T>(): StoreBuilder<Record<TKey, ResourceDef<T>>>;\n };\n\n /**\n * Interface-based builder: pass a config interface as a generic.\n * No runtime argument needed — keys and types are inferred from the interface.\n *\n * @example\n * interface ChatStoreConfig {\n * SESSIONS: ChatSession[];\n * MESSAGES: ChatMessage[];\n * }\n * const ChatStore = Store.for<ChatStoreConfig>().build();\n */\n for<TConfig extends Record<string, unknown>>(): {\n build(): InjectionToken<IStore<ConfigToData<TConfig>>>;\n };\n\n /**\n * Bind the builder to an enum object for compile-time key validation.\n *\n * @example\n * const Enum = { A: 'A', B: 'B' } as const;\n * const MyStore = Store.for(Enum)\n * .resource('A').as<string>()\n * .resource('B').as<number>()\n * .build();\n */\n for<TEnum extends Record<string, string>>(\n enumObj: TEnum\n ): ConstrainedBuilder<TEnum, Record<string, never>>;\n}\n\n/**\n * Fluent store builder entry point.\n *\n * @example\n * // Unconstrained\n * export const CustomersStore = Store\n * .resource('customers').as<Customer[]>()\n * .resource('customerDetails').as<Customer>()\n * .build();\n *\n * @example\n * // Constrained with enum\n * const Enum = { SESSIONS: 'SESSIONS', MESSAGES: 'MESSAGES' } as const;\n * export const ChatStore = Store.for(Enum)\n * .resource('SESSIONS').as<Session[]>()\n * .resource('MESSAGES').as<Message[]>()\n * .build();\n */\nexport const Store: StoreEntry = {\n ...createBuilder({} as StoreConfig),\n for(enumObj?: Record<string, string>) {\n if (arguments.length === 0) {\n return {\n build() {\n return new InjectionToken(\"FlurryxStore\", {\n providedIn: \"root\",\n factory: () => new LazyStore(),\n });\n },\n };\n }\n return createConstrainedBuilder(enumObj!, {} as Record<string, never>);\n },\n};\n","import { BaseStore } from './base-store';\nimport type { StoreConfig, InferEnum, InferData } from './types';\n\n/**\n * Internal concrete subclass of BaseStore.\n * Auto-generates an identity enum from config keys.\n * NOT publicly exported — consumers interact via BaseStore interface.\n */\nexport class DynamicStore<\n TConfig extends StoreConfig,\n> extends BaseStore<InferEnum<TConfig>, InferData<TConfig>> {\n constructor(config: TConfig) {\n const identityEnum = Object.keys(config).reduce(\n (acc, key) => ({ ...acc, [key]: key }),\n {} as InferEnum<TConfig>\n );\n super(identityEnum);\n }\n}\n","import type { ResourceDef } from './types';\n\n/**\n * Creates a phantom-typed resource definition marker.\n * Zero runtime cost — returns an empty object that only carries type info.\n *\n * @example\n * const config = {\n * customers: resource<Customer[]>(),\n * customerDetails: resource<Customer>(),\n * };\n */\nexport function resource<T>(): ResourceDef<T> {\n return {} as ResourceDef<T>;\n}\n","import type { ResourceState } from \"@flurryx/core\";\nimport type { IStore } from \"./types\";\n\nexport interface MirrorOptions {\n destroyRef?: { onDestroy: (fn: () => void) => void };\n}\n\n/**\n * Mirrors a resource key from a source store to a target store.\n * When the source key updates, the target key is updated with the same state.\n *\n * @param source - The store to mirror from\n * @param sourceKey - The key to watch on the source store\n * @param target - The store to mirror to\n * @param targetKeyOrOptions - Either the target key name or options (defaults source key)\n * @param options - Mirror options when a target key is provided\n * @returns Cleanup function to stop mirroring\n */\nexport function mirrorKey<\n TSource extends Record<string, ResourceState<unknown>>,\n TTarget extends Record<string, ResourceState<unknown>>\n>(\n source: IStore<TSource>,\n sourceKey: keyof TSource & string,\n target: IStore<TTarget>,\n targetKeyOrOptions?: (keyof TTarget & string) | MirrorOptions,\n options?: MirrorOptions\n): () => void {\n const resolvedTargetKey = (\n typeof targetKeyOrOptions === \"string\" ? targetKeyOrOptions : sourceKey\n ) as keyof TTarget & string;\n\n const resolvedOptions =\n typeof targetKeyOrOptions === \"object\" ? targetKeyOrOptions : options;\n\n const cleanup = source.onUpdate(sourceKey, (state) => {\n target.update(\n resolvedTargetKey,\n state as unknown as Partial<TTarget[keyof TTarget & string]>\n );\n });\n\n if (resolvedOptions?.destroyRef) {\n resolvedOptions.destroyRef.onDestroy(cleanup);\n }\n\n return cleanup;\n}\n","import type {\n ResourceState,\n KeyedResourceKey,\n KeyedResourceData,\n} from '@flurryx/core';\nimport { createKeyedResourceData, isAnyKeyLoading } from '@flurryx/core';\nimport type { IStore } from './types';\n\nexport interface CollectKeyedOptions<TEntity> {\n extractId: (data: TEntity | undefined) => KeyedResourceKey | undefined;\n destroyRef?: { onDestroy: (fn: () => void) => void };\n}\n\n/**\n * Accumulates single-entity resource fetches into a keyed cache on a target store.\n *\n * On each source update:\n * - If status is 'Success' and extractId returns a valid key, merges the entity\n * into the target's keyed resource data.\n * - If the source data is cleared and a previous entity existed, removes it from\n * the target's keyed data.\n *\n * @param source - The store containing the single-entity resource\n * @param sourceKey - The key to watch on the source store\n * @param target - The store to accumulate entities into\n * @param targetKeyOrOptions - Either the target key name or options (defaults source key)\n * @param options - Collect options when a target key is provided\n * @returns Cleanup function to stop collecting\n */\nexport function collectKeyed<\n TSource extends Record<string, ResourceState<unknown>>,\n TTarget extends Record<string, ResourceState<unknown>>,\n TEntity = unknown,\n>(\n source: IStore<TSource>,\n sourceKey: keyof TSource & string,\n target: IStore<TTarget>,\n targetKeyOrOptions?: (keyof TTarget & string) | CollectKeyedOptions<TEntity>,\n options?: CollectKeyedOptions<TEntity>,\n): () => void {\n const resolvedTargetKey = (\n typeof targetKeyOrOptions === 'string'\n ? targetKeyOrOptions\n : sourceKey\n ) as keyof TTarget & string;\n\n const resolvedOptions = (\n typeof targetKeyOrOptions === 'object' ? targetKeyOrOptions : options\n ) as CollectKeyedOptions<TEntity>;\n\n // Initialize target with empty keyed resource data\n target.update(resolvedTargetKey, {\n data: createKeyedResourceData(),\n } as Partial<TTarget[keyof TTarget & string]>);\n\n let previousId: KeyedResourceKey | undefined;\n\n const cleanup = source.onUpdate(sourceKey, (state) => {\n const resourceState = state as ResourceState<TEntity>;\n const currentId = resolvedOptions.extractId(resourceState.data);\n const currentTarget = target.get(resolvedTargetKey)();\n const currentKeyed = (currentTarget as ResourceState<unknown>).data as\n KeyedResourceData<KeyedResourceKey, TEntity> | undefined;\n\n if (!currentKeyed) {\n return;\n }\n\n if (resourceState.status === 'Success' && currentId !== undefined) {\n const newEntities = { ...currentKeyed.entities, [currentId]: resourceState.data };\n const newIsLoading = { ...currentKeyed.isLoading, [currentId]: false };\n const newStatus = { ...currentKeyed.status, [currentId]: resourceState.status };\n const newErrors = { ...currentKeyed.errors };\n delete newErrors[currentId];\n\n const updatedKeyed: KeyedResourceData<KeyedResourceKey, TEntity> = {\n entities: newEntities,\n isLoading: newIsLoading,\n status: newStatus,\n errors: newErrors,\n };\n\n target.update(resolvedTargetKey, {\n data: updatedKeyed,\n isLoading: isAnyKeyLoading(newIsLoading),\n status: 'Success',\n } as Partial<TTarget[keyof TTarget & string]>);\n\n previousId = currentId;\n } else if (resourceState.status === 'Error' && currentId !== undefined) {\n const newIsLoading = { ...currentKeyed.isLoading, [currentId]: false };\n const newStatus = { ...currentKeyed.status, [currentId]: resourceState.status };\n const newErrors = { ...currentKeyed.errors, [currentId]: resourceState.errors };\n\n const updatedKeyed: KeyedResourceData<KeyedResourceKey, TEntity> = {\n entities: { ...currentKeyed.entities },\n isLoading: newIsLoading,\n status: newStatus,\n errors: newErrors,\n };\n\n target.update(resolvedTargetKey, {\n data: updatedKeyed,\n isLoading: isAnyKeyLoading(newIsLoading),\n } as Partial<TTarget[keyof TTarget & string]>);\n\n previousId = currentId;\n } else if (resourceState.data === undefined && previousId !== undefined) {\n // Source cleared — remove previous entity from cache\n const { [previousId]: _removed, ...remainingEntities } = currentKeyed.entities;\n const { [previousId]: _removedLoading, ...remainingLoading } = currentKeyed.isLoading;\n const { [previousId]: _removedStatus, ...remainingStatus } = currentKeyed.status;\n const { [previousId]: _removedErrors, ...remainingErrors } = currentKeyed.errors;\n\n const updatedKeyed: KeyedResourceData<KeyedResourceKey, TEntity> = {\n entities: remainingEntities,\n isLoading: remainingLoading,\n status: remainingStatus,\n errors: remainingErrors,\n };\n\n target.update(resolvedTargetKey, {\n data: updatedKeyed,\n isLoading: isAnyKeyLoading(remainingLoading),\n } as Partial<TTarget[keyof TTarget & string]>);\n\n previousId = undefined;\n } else if (resourceState.isLoading && currentId !== undefined) {\n const newIsLoading = { ...currentKeyed.isLoading, [currentId]: true };\n\n const updatedKeyed: KeyedResourceData<KeyedResourceKey, TEntity> = {\n entities: { ...currentKeyed.entities },\n isLoading: newIsLoading,\n status: { ...currentKeyed.status },\n errors: { ...currentKeyed.errors },\n };\n\n target.update(resolvedTargetKey, {\n data: updatedKeyed,\n isLoading: true,\n } as Partial<TTarget[keyof TTarget & string]>);\n\n previousId = currentId;\n }\n });\n\n if (resolvedOptions?.destroyRef) {\n resolvedOptions.destroyRef.onDestroy(cleanup);\n }\n\n return cleanup;\n}\n"],"mappings":"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","names":["import_core","import_core","import_core","import_core"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/base-store.ts","../src/lazy-store.ts","../src/store-builder.ts","../src/dynamic-store.ts","../src/mirror-key.ts","../src/resource.ts","../src/collect-keyed.ts"],"sourcesContent":["export { BaseStore } from \"./base-store\";\nexport { LazyStore } from \"./lazy-store\";\nexport { Store } from \"./store-builder\";\nexport { mirrorKey } from \"./mirror-key\";\nexport { collectKeyed } from \"./collect-keyed\";\nexport type { MirrorOptions } from \"./mirror-key\";\nexport type { CollectKeyedOptions } from \"./collect-keyed\";\nexport type { IStore, ConfigToData } from \"./types\";\n","import { signal, WritableSignal } from \"@angular/core\";\nimport {\n ResourceState,\n isAnyKeyLoading,\n isKeyedResourceData,\n createKeyedResourceData,\n type KeyedResourceKey,\n} from \"@flurryx/core\";\nimport type { IStore } from \"./types\";\n\ntype UpdateHooksMap = Map<\n unknown,\n Array<\n (\n nextState: ResourceState<unknown>,\n previousState: ResourceState<unknown>\n ) => void\n >\n>;\n\nconst updateHooksMap = new WeakMap<object, UpdateHooksMap>();\n\nexport abstract class BaseStore<\n TEnum extends Record<string, string | number>,\n TData extends { [K in keyof TEnum]: ResourceState<unknown> }\n> implements IStore<TData>\n{\n private readonly signalsState = new Map<\n keyof TEnum,\n WritableSignal<TData[keyof TEnum]>\n >();\n\n protected constructor(protected readonly storeEnum: TEnum) {\n this.initializeState();\n updateHooksMap.set(this, new Map());\n }\n\n get<K extends keyof TData>(key: K): WritableSignal<TData[K]> {\n return this.signalsState.get(key.toString()) as WritableSignal<TData[K]>;\n }\n\n onUpdate<K extends keyof TData>(\n key: K,\n callback: (state: TData[K], previousState: TData[K]) => void\n ): () => void {\n const hooks = updateHooksMap.get(this)!;\n if (!hooks.has(key)) {\n hooks.set(key, []);\n }\n hooks\n .get(key)!\n .push(\n callback as (\n nextState: ResourceState<unknown>,\n previousState: ResourceState<unknown>\n ) => void\n );\n\n return () => {\n const hooksMap = hooks.get(key);\n if (!hooksMap) {\n return;\n }\n const index = hooksMap.indexOf(\n callback as (\n nextState: ResourceState<unknown>,\n previousState: ResourceState<unknown>\n ) => void\n );\n if (index > -1) {\n hooksMap.splice(index, 1);\n }\n };\n }\n\n update<K extends keyof TData>(key: K, newState: Partial<TData[K]>): void {\n const currentState = this.signalsState.get(key.toString());\n if (!currentState) {\n return;\n }\n\n const previousState = currentState() as TData[K];\n currentState.update((state) => ({\n ...state,\n ...newState,\n }));\n\n const updatedState = currentState() as TData[K];\n this.notifyUpdateHooks(key, updatedState, previousState);\n }\n\n clearAll(): void {\n Object.keys(this.storeEnum).forEach((key) => {\n this.clear(key as keyof TData);\n });\n }\n\n clear<K extends keyof TData>(key: K): void {\n const currentState = this.signalsState.get(key.toString());\n if (!currentState) {\n return;\n }\n\n const previousState = currentState() as TData[K];\n const _typedKey = key as keyof TEnum;\n currentState.set({\n data: undefined,\n isLoading: false,\n status: undefined,\n errors: undefined,\n } as TData[typeof _typedKey]);\n\n const nextState = currentState() as TData[K];\n this.notifyUpdateHooks(key, nextState, previousState);\n }\n\n startLoading<K extends keyof TData>(key: K): void {\n const currentState = this.signalsState.get(key.toString());\n if (!currentState) {\n return;\n }\n\n const _typedKey = key as keyof TEnum;\n currentState.update(\n (state) =>\n ({\n ...state,\n status: undefined,\n isLoading: true,\n errors: undefined,\n } as TData[typeof _typedKey])\n );\n }\n\n stopLoading<K extends keyof TData>(key: K): void {\n const currentState = this.signalsState.get(key.toString());\n if (!currentState) {\n return;\n }\n\n const _typedKey = key as keyof TEnum;\n currentState.update(\n (state) =>\n ({\n ...state,\n isLoading: false,\n status: undefined,\n errors: undefined,\n } as TData[typeof _typedKey])\n );\n }\n\n updateKeyedOne<K extends keyof TData>(\n key: K,\n resourceKey: KeyedResourceKey,\n entity: unknown\n ): void {\n const currentState = this.signalsState.get(key.toString());\n if (!currentState) {\n return;\n }\n\n const state = currentState();\n const data = isKeyedResourceData(state.data)\n ? state.data\n : createKeyedResourceData();\n\n const nextErrors = { ...data.errors };\n delete nextErrors[resourceKey];\n\n const nextData = {\n ...data,\n entities: {\n ...data.entities,\n [resourceKey]: entity,\n },\n isLoading: {\n ...data.isLoading,\n [resourceKey]: false,\n },\n status: {\n ...data.status,\n [resourceKey]: \"Success\" as const,\n },\n errors: nextErrors,\n };\n\n this.update(key, {\n data: nextData as unknown,\n isLoading: isAnyKeyLoading(nextData.isLoading),\n status: undefined,\n errors: undefined,\n } as Partial<TData[K]>);\n }\n\n clearKeyedOne<K extends keyof TData>(\n key: K,\n resourceKey: KeyedResourceKey\n ): void {\n const currentState = this.signalsState.get(key.toString());\n if (!currentState) {\n return;\n }\n\n const previousState = currentState() as TData[K];\n const state = previousState as ResourceState<unknown>;\n if (!isKeyedResourceData(state.data)) {\n return;\n }\n\n const data = state.data;\n\n const nextEntities = { ...data.entities };\n delete nextEntities[resourceKey];\n\n const nextIsLoading = { ...data.isLoading };\n delete nextIsLoading[resourceKey];\n\n const nextStatus = { ...data.status };\n delete nextStatus[resourceKey];\n\n const nextErrors = { ...data.errors };\n delete nextErrors[resourceKey];\n\n const nextData = {\n ...data,\n entities: nextEntities,\n isLoading: nextIsLoading,\n status: nextStatus,\n errors: nextErrors,\n };\n\n const _typedKey = key as keyof TEnum;\n currentState.update(\n (prev) =>\n ({\n ...prev,\n data: nextData as unknown,\n status: undefined,\n isLoading: isAnyKeyLoading(nextIsLoading),\n errors: undefined,\n } as TData[typeof _typedKey])\n );\n\n const updatedState = currentState() as TData[K];\n this.notifyUpdateHooks(key, updatedState, previousState);\n }\n\n startKeyedLoading<K extends keyof TData>(\n key: K,\n resourceKey: KeyedResourceKey\n ): void {\n const currentState = this.signalsState.get(key.toString());\n if (!currentState) {\n return;\n }\n\n const _typedKey = key as keyof TEnum;\n const state = currentState();\n if (!isKeyedResourceData(state.data)) {\n this.startLoading(key);\n return;\n }\n\n const previousState = state as TData[K];\n const data = state.data;\n\n const nextIsLoading = {\n ...data.isLoading,\n [resourceKey]: true,\n } as typeof data.isLoading;\n\n const nextStatus: typeof data.status = {\n ...data.status,\n };\n delete nextStatus[resourceKey];\n\n const nextErrors: typeof data.errors = {\n ...data.errors,\n };\n delete nextErrors[resourceKey];\n\n const nextData = {\n ...data,\n isLoading: nextIsLoading,\n status: nextStatus,\n errors: nextErrors,\n };\n\n currentState.update(\n (previous) =>\n ({\n ...previous,\n data: nextData,\n status: undefined,\n isLoading: isAnyKeyLoading(nextIsLoading),\n errors: undefined,\n } as TData[typeof _typedKey])\n );\n\n const updatedState = currentState() as TData[K];\n this.notifyUpdateHooks(key, updatedState, previousState);\n }\n\n private notifyUpdateHooks<K extends keyof TData>(\n key: K,\n nextState: TData[K],\n previousState: TData[K]\n ): void {\n const hooks = updateHooksMap.get(this);\n const keyHooks = hooks?.get(key);\n if (!keyHooks) {\n return;\n }\n\n keyHooks.forEach((hook) =>\n hook(\n nextState as ResourceState<unknown>,\n previousState as ResourceState<unknown>\n )\n );\n }\n\n private initializeState(): void {\n Object.keys(this.storeEnum).forEach((key) => {\n const _typedKey = key as keyof TEnum;\n const initialState: ResourceState<unknown> = {\n data: undefined,\n isLoading: false,\n status: undefined,\n errors: undefined,\n };\n this.signalsState.set(\n _typedKey,\n signal<TData[typeof _typedKey]>(initialState as TData[typeof _typedKey])\n );\n });\n }\n}\n","import { signal, WritableSignal } from '@angular/core';\nimport type { ResourceState } from '@flurryx/core';\nimport type { IStore } from './types';\n\ntype UpdateCallback = (\n nextState: ResourceState<unknown>,\n previousState: ResourceState<unknown>\n) => void;\n\nfunction createDefaultState<T>(): ResourceState<T> {\n return {\n data: undefined,\n isLoading: false,\n status: undefined,\n errors: undefined,\n };\n}\n\n/**\n * Lazy store that creates signals on first access.\n * Used by the `Store.for<Config>().build()` API where keys are\n * known only at the type level (no runtime enum).\n */\nexport class LazyStore<\n TData extends Record<string, ResourceState<unknown>>,\n> implements IStore<TData>\n{\n private readonly signals = new Map<string, WritableSignal<ResourceState<unknown>>>();\n private readonly hooks = new Map<string, UpdateCallback[]>();\n\n private getOrCreate<K extends keyof TData & string>(\n key: K\n ): WritableSignal<TData[K]> {\n let sig = this.signals.get(key);\n if (!sig) {\n sig = signal<ResourceState<unknown>>(createDefaultState());\n this.signals.set(key, sig);\n }\n return sig as WritableSignal<TData[K]>;\n }\n\n get<K extends keyof TData & string>(key: K): WritableSignal<TData[K]> {\n return this.getOrCreate(key);\n }\n\n update<K extends keyof TData & string>(\n key: K,\n newState: Partial<TData[K]>\n ): void {\n const sig = this.getOrCreate(key);\n const previousState = sig();\n sig.update((state) => ({ ...state, ...newState }));\n const nextState = sig();\n this.notifyHooks(key, nextState, previousState);\n }\n\n clear<K extends keyof TData & string>(key: K): void {\n const sig = this.getOrCreate(key);\n const previousState = sig();\n sig.set(createDefaultState() as TData[K]);\n const nextState = sig();\n this.notifyHooks(key, nextState, previousState);\n }\n\n clearAll(): void {\n for (const key of this.signals.keys()) {\n this.clear(key as keyof TData & string);\n }\n }\n\n startLoading<K extends keyof TData & string>(key: K): void {\n const sig = this.getOrCreate(key);\n sig.update(\n (state) =>\n ({\n ...state,\n status: undefined,\n isLoading: true,\n errors: undefined,\n }) as TData[K]\n );\n }\n\n stopLoading<K extends keyof TData & string>(key: K): void {\n const sig = this.getOrCreate(key);\n sig.update(\n (state) =>\n ({\n ...state,\n isLoading: false,\n status: undefined,\n errors: undefined,\n }) as TData[K]\n );\n }\n\n onUpdate<K extends keyof TData & string>(\n key: K,\n callback: (state: TData[K], previousState: TData[K]) => void\n ): () => void {\n if (!this.hooks.has(key)) {\n this.hooks.set(key, []);\n }\n const typedCallback = callback as UpdateCallback;\n this.hooks.get(key)!.push(typedCallback);\n\n return () => {\n const keyHooks = this.hooks.get(key);\n if (!keyHooks) {\n return;\n }\n const index = keyHooks.indexOf(typedCallback);\n if (index > -1) {\n keyHooks.splice(index, 1);\n }\n };\n }\n\n private notifyHooks<K extends keyof TData & string>(\n key: K,\n nextState: TData[K],\n previousState: TData[K]\n ): void {\n const keyHooks = this.hooks.get(key);\n if (!keyHooks) {\n return;\n }\n keyHooks.forEach((hook) =>\n hook(\n nextState as ResourceState<unknown>,\n previousState as ResourceState<unknown>\n )\n );\n }\n}\n","import { InjectionToken, inject } from \"@angular/core\";\nimport { BaseStore } from \"./base-store\";\nimport { DynamicStore } from \"./dynamic-store\";\nimport { LazyStore } from \"./lazy-store\";\nimport { mirrorKey } from \"./mirror-key\";\nimport { resource } from \"./resource\";\nimport type { ResourceState } from \"@flurryx/core\";\nimport type {\n StoreConfig,\n ResourceDef,\n InferEnum,\n InferData,\n ConfigToData,\n IStore,\n} from \"./types\";\n\n// ---------------------------------------------------------------------------\n// Mirror definition — accumulated by builders, wired up in build() factory\n// ---------------------------------------------------------------------------\n\ninterface MirrorDef {\n readonly sourceToken: InjectionToken<\n IStore<Record<string, ResourceState<unknown>>>\n >;\n readonly sourceKey: string;\n readonly targetKey: string;\n}\n\nfunction wireMirrors<\n TStore extends IStore<Record<string, ResourceState<unknown>>>\n>(store: TStore, mirrors: readonly MirrorDef[]): TStore {\n for (const def of mirrors) {\n const sourceStore = inject(def.sourceToken);\n mirrorKey(sourceStore, def.sourceKey, store, def.targetKey);\n }\n return store;\n}\n\n// ---------------------------------------------------------------------------\n// Unconstrained builder (existing API)\n// ---------------------------------------------------------------------------\n\n/**\n * Intermediate builder step after .resource('key') — awaits .as<T>().\n */\ninterface AsStep<TAccum extends StoreConfig, TKey extends string> {\n as<T>(): StoreBuilder<TAccum & Record<TKey, ResourceDef<T>>>;\n}\n\n/**\n * Fluent builder for creating stores.\n * Accumulates resource definitions then produces an InjectionToken on .build().\n */\ninterface StoreBuilder<TAccum extends StoreConfig> {\n resource<TKey extends string>(key: TKey): AsStep<TAccum, TKey>;\n mirror<TSourceData extends Record<string, ResourceState<unknown>>>(\n source: InjectionToken<IStore<TSourceData>>,\n sourceKey: keyof TSourceData & string,\n targetKey?: keyof TAccum & string\n ): StoreBuilder<TAccum>;\n build(): InjectionToken<BaseStore<InferEnum<TAccum>, InferData<TAccum>>>;\n}\n\nfunction createBuilder<TAccum extends StoreConfig>(\n accum: TAccum,\n mirrors: readonly MirrorDef[] = []\n): StoreBuilder<TAccum> {\n return {\n resource<TKey extends string>(key: TKey): AsStep<TAccum, TKey> {\n return {\n as<T>(): StoreBuilder<TAccum & Record<TKey, ResourceDef<T>>> {\n const nextAccum = {\n ...accum,\n [key]: resource<T>(),\n } as TAccum & Record<TKey, ResourceDef<T>>;\n return createBuilder(nextAccum, mirrors);\n },\n };\n },\n mirror(source, sourceKey, targetKey?) {\n const def: MirrorDef = {\n sourceToken: source as InjectionToken<\n IStore<Record<string, ResourceState<unknown>>>\n >,\n sourceKey,\n targetKey: (targetKey ?? sourceKey) as string,\n };\n return createBuilder(accum, [...mirrors, def]);\n },\n build() {\n return new InjectionToken<\n BaseStore<InferEnum<TAccum>, InferData<TAccum>>\n >(\"FlurryxStore\", {\n providedIn: \"root\",\n factory: () =>\n wireMirrors(new DynamicStore(accum), mirrors) as BaseStore<\n InferEnum<TAccum>,\n InferData<TAccum>\n >,\n });\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// Constrained builder (.for(enum) API)\n// ---------------------------------------------------------------------------\n\n/** Keys from the enum that have NOT yet been defined. */\ntype Remaining<\n TEnum extends Record<string, string>,\n TAccum extends StoreConfig\n> = Exclude<keyof TEnum & string, keyof TAccum>;\n\n/** Intermediate .as<T>() step for the constrained builder. */\ninterface ConstrainedAsStep<\n TEnum extends Record<string, string>,\n TAccum extends StoreConfig,\n TKey extends string\n> {\n as<T>(): ConstrainedBuilder<TEnum, TAccum & Record<TKey, ResourceDef<T>>>;\n}\n\n/**\n * Constrained builder — only allows keys from the enum that haven't been\n * defined yet. `.build()` is only available when all keys are accounted for.\n */\ntype ConstrainedBuilder<\n TEnum extends Record<string, string>,\n TAccum extends StoreConfig\n> = [Remaining<TEnum, TAccum>] extends [never]\n ? {\n mirror<TSourceData extends Record<string, ResourceState<unknown>>>(\n source: InjectionToken<IStore<TSourceData>>,\n sourceKey: keyof TSourceData & string,\n targetKey?: keyof TAccum & string\n ): ConstrainedBuilder<TEnum, TAccum>;\n build(): InjectionToken<BaseStore<InferEnum<TAccum>, InferData<TAccum>>>;\n }\n : {\n resource<TKey extends Remaining<TEnum, TAccum>>(\n key: TKey\n ): ConstrainedAsStep<TEnum, TAccum, TKey>;\n };\n\nfunction createConstrainedBuilder<\n TEnum extends Record<string, string>,\n TAccum extends StoreConfig\n>(\n _enumObj: TEnum,\n accum: TAccum,\n mirrors: readonly MirrorDef[] = []\n): ConstrainedBuilder<TEnum, TAccum> {\n return {\n resource<TKey extends string>(\n key: TKey\n ): ConstrainedAsStep<TEnum, TAccum, TKey> {\n return {\n as<T>(): ConstrainedBuilder<\n TEnum,\n TAccum & Record<TKey, ResourceDef<T>>\n > {\n const nextAccum = {\n ...accum,\n [key]: resource<T>(),\n } as TAccum & Record<TKey, ResourceDef<T>>;\n return createConstrainedBuilder(_enumObj, nextAccum, mirrors);\n },\n };\n },\n mirror(\n source: InjectionToken<IStore<Record<string, ResourceState<unknown>>>>,\n sourceKey: string,\n targetKey?: string\n ) {\n const def: MirrorDef = {\n sourceToken: source,\n sourceKey,\n targetKey: targetKey ?? sourceKey,\n };\n return createConstrainedBuilder(_enumObj, accum, [...mirrors, def]);\n },\n build() {\n return new InjectionToken<\n BaseStore<InferEnum<TAccum>, InferData<TAccum>>\n >(\"FlurryxStore\", {\n providedIn: \"root\",\n factory: () =>\n wireMirrors(new DynamicStore(accum), mirrors) as BaseStore<\n InferEnum<TAccum>,\n InferData<TAccum>\n >,\n });\n },\n } as ConstrainedBuilder<TEnum, TAccum>;\n}\n\n// ---------------------------------------------------------------------------\n// Interface-based builder (Store.for<Config>() API)\n// ---------------------------------------------------------------------------\n\ninterface InterfaceBuilder<TConfig extends Record<string, unknown>> {\n mirror<TSourceData extends Record<string, ResourceState<unknown>>>(\n source: InjectionToken<IStore<TSourceData>>,\n sourceKey: keyof TSourceData & string,\n targetKey?: keyof TConfig & string\n ): InterfaceBuilder<TConfig>;\n build(): InjectionToken<IStore<ConfigToData<TConfig>>>;\n}\n\nfunction createInterfaceBuilder<TConfig extends Record<string, unknown>>(\n mirrors: readonly MirrorDef[] = []\n): InterfaceBuilder<TConfig> {\n return {\n mirror(source, sourceKey, targetKey?) {\n const def: MirrorDef = {\n sourceToken: source as InjectionToken<\n IStore<Record<string, ResourceState<unknown>>>\n >,\n sourceKey,\n targetKey: (targetKey ?? sourceKey) as string,\n };\n return createInterfaceBuilder<TConfig>([...mirrors, def]);\n },\n build() {\n return new InjectionToken(\"FlurryxStore\", {\n providedIn: \"root\",\n factory: () =>\n wireMirrors(\n new LazyStore() as IStore<Record<string, ResourceState<unknown>>>,\n mirrors\n ) as unknown as IStore<ConfigToData<TConfig>>,\n });\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// Public entry point\n// ---------------------------------------------------------------------------\n\ninterface StoreEntry {\n /**\n * Define a named resource slot.\n * Chain .as<T>() to assign its type, then continue with more .resource() calls\n * or call .build() when done.\n */\n resource<TKey extends string>(\n key: TKey\n ): {\n as<T>(): StoreBuilder<Record<TKey, ResourceDef<T>>>;\n };\n\n /**\n * Interface-based builder: pass a config interface as a generic.\n * No runtime argument needed — keys and types are inferred from the interface.\n *\n * @example\n * interface ChatStoreConfig {\n * SESSIONS: ChatSession[];\n * MESSAGES: ChatMessage[];\n * }\n * const ChatStore = Store.for<ChatStoreConfig>().build();\n */\n for<TConfig extends Record<string, unknown>>(): InterfaceBuilder<TConfig>;\n\n /**\n * Bind the builder to an enum object for compile-time key validation.\n *\n * @example\n * const Enum = { A: 'A', B: 'B' } as const;\n * const MyStore = Store.for(Enum)\n * .resource('A').as<string>()\n * .resource('B').as<number>()\n * .build();\n */\n for<TEnum extends Record<string, string>>(\n enumObj: TEnum\n ): ConstrainedBuilder<TEnum, Record<string, never>>;\n}\n\n/**\n * Fluent store builder entry point.\n *\n * @example\n * // Unconstrained\n * export const CustomersStore = Store\n * .resource('customers').as<Customer[]>()\n * .resource('customerDetails').as<Customer>()\n * .build();\n *\n * @example\n * // Constrained with enum\n * const Enum = { SESSIONS: 'SESSIONS', MESSAGES: 'MESSAGES' } as const;\n * export const ChatStore = Store.for(Enum)\n * .resource('SESSIONS').as<Session[]>()\n * .resource('MESSAGES').as<Message[]>()\n * .build();\n */\nexport const Store: StoreEntry = {\n ...createBuilder({} as StoreConfig),\n for(enumObj?: Record<string, string>) {\n if (arguments.length === 0) {\n return createInterfaceBuilder();\n }\n return createConstrainedBuilder(enumObj!, {} as Record<string, never>);\n },\n};\n","import { BaseStore } from './base-store';\nimport type { StoreConfig, InferEnum, InferData } from './types';\n\n/**\n * Internal concrete subclass of BaseStore.\n * Auto-generates an identity enum from config keys.\n * NOT publicly exported — consumers interact via BaseStore interface.\n */\nexport class DynamicStore<\n TConfig extends StoreConfig,\n> extends BaseStore<InferEnum<TConfig>, InferData<TConfig>> {\n constructor(config: TConfig) {\n const identityEnum = Object.keys(config).reduce(\n (acc, key) => ({ ...acc, [key]: key }),\n {} as InferEnum<TConfig>\n );\n super(identityEnum);\n }\n}\n","import type { ResourceState } from \"@flurryx/core\";\nimport type { IStore } from \"./types\";\n\nexport interface MirrorOptions {\n destroyRef?: { onDestroy: (fn: () => void) => void };\n}\n\n/**\n * Mirrors a resource key from a source store to a target store.\n * When the source key updates, the target key is updated with the same state.\n *\n * @param source - The store to mirror from\n * @param sourceKey - The key to watch on the source store\n * @param target - The store to mirror to\n * @param targetKeyOrOptions - Either the target key name or options (defaults source key)\n * @param options - Mirror options when a target key is provided\n * @returns Cleanup function to stop mirroring\n */\nexport function mirrorKey<\n TSource extends Record<string, ResourceState<unknown>>,\n TTarget extends Record<string, ResourceState<unknown>>\n>(\n source: IStore<TSource>,\n sourceKey: keyof TSource & string,\n target: IStore<TTarget>,\n targetKeyOrOptions?: (keyof TTarget & string) | MirrorOptions,\n options?: MirrorOptions\n): () => void {\n const resolvedTargetKey = (\n typeof targetKeyOrOptions === \"string\" ? targetKeyOrOptions : sourceKey\n ) as keyof TTarget & string;\n\n const resolvedOptions =\n typeof targetKeyOrOptions === \"object\" ? targetKeyOrOptions : options;\n\n const cleanup = source.onUpdate(sourceKey, (state) => {\n target.update(\n resolvedTargetKey,\n state as unknown as Partial<TTarget[keyof TTarget & string]>\n );\n });\n\n if (resolvedOptions?.destroyRef) {\n resolvedOptions.destroyRef.onDestroy(cleanup);\n }\n\n return cleanup;\n}\n","import type { ResourceDef } from './types';\n\n/**\n * Creates a phantom-typed resource definition marker.\n * Zero runtime cost — returns an empty object that only carries type info.\n *\n * @example\n * const config = {\n * customers: resource<Customer[]>(),\n * customerDetails: resource<Customer>(),\n * };\n */\nexport function resource<T>(): ResourceDef<T> {\n return {} as ResourceDef<T>;\n}\n","import type {\n ResourceState,\n KeyedResourceKey,\n KeyedResourceData,\n} from '@flurryx/core';\nimport { createKeyedResourceData, isAnyKeyLoading } from '@flurryx/core';\nimport type { IStore } from './types';\n\nexport interface CollectKeyedOptions<TEntity> {\n extractId: (data: TEntity | undefined) => KeyedResourceKey | undefined;\n destroyRef?: { onDestroy: (fn: () => void) => void };\n}\n\n/**\n * Accumulates single-entity resource fetches into a keyed cache on a target store.\n *\n * On each source update:\n * - If status is 'Success' and extractId returns a valid key, merges the entity\n * into the target's keyed resource data.\n * - If the source data is cleared and a previous entity existed, removes it from\n * the target's keyed data.\n *\n * @param source - The store containing the single-entity resource\n * @param sourceKey - The key to watch on the source store\n * @param target - The store to accumulate entities into\n * @param targetKeyOrOptions - Either the target key name or options (defaults source key)\n * @param options - Collect options when a target key is provided\n * @returns Cleanup function to stop collecting\n */\nexport function collectKeyed<\n TSource extends Record<string, ResourceState<unknown>>,\n TTarget extends Record<string, ResourceState<unknown>>,\n TEntity = unknown,\n>(\n source: IStore<TSource>,\n sourceKey: keyof TSource & string,\n target: IStore<TTarget>,\n targetKeyOrOptions?: (keyof TTarget & string) | CollectKeyedOptions<TEntity>,\n options?: CollectKeyedOptions<TEntity>,\n): () => void {\n const resolvedTargetKey = (\n typeof targetKeyOrOptions === 'string'\n ? targetKeyOrOptions\n : sourceKey\n ) as keyof TTarget & string;\n\n const resolvedOptions = (\n typeof targetKeyOrOptions === 'object' ? targetKeyOrOptions : options\n ) as CollectKeyedOptions<TEntity>;\n\n // Initialize target with empty keyed resource data\n target.update(resolvedTargetKey, {\n data: createKeyedResourceData(),\n } as Partial<TTarget[keyof TTarget & string]>);\n\n let previousId: KeyedResourceKey | undefined;\n\n const cleanup = source.onUpdate(sourceKey, (state) => {\n const resourceState = state as ResourceState<TEntity>;\n const currentId = resolvedOptions.extractId(resourceState.data);\n const currentTarget = target.get(resolvedTargetKey)();\n const currentKeyed = (currentTarget as ResourceState<unknown>).data as\n KeyedResourceData<KeyedResourceKey, TEntity> | undefined;\n\n if (!currentKeyed) {\n return;\n }\n\n if (resourceState.status === 'Success' && currentId !== undefined) {\n const newEntities = { ...currentKeyed.entities, [currentId]: resourceState.data };\n const newIsLoading = { ...currentKeyed.isLoading, [currentId]: false };\n const newStatus = { ...currentKeyed.status, [currentId]: resourceState.status };\n const newErrors = { ...currentKeyed.errors };\n delete newErrors[currentId];\n\n const updatedKeyed: KeyedResourceData<KeyedResourceKey, TEntity> = {\n entities: newEntities,\n isLoading: newIsLoading,\n status: newStatus,\n errors: newErrors,\n };\n\n target.update(resolvedTargetKey, {\n data: updatedKeyed,\n isLoading: isAnyKeyLoading(newIsLoading),\n status: 'Success',\n } as Partial<TTarget[keyof TTarget & string]>);\n\n previousId = currentId;\n } else if (resourceState.status === 'Error' && currentId !== undefined) {\n const newIsLoading = { ...currentKeyed.isLoading, [currentId]: false };\n const newStatus = { ...currentKeyed.status, [currentId]: resourceState.status };\n const newErrors = { ...currentKeyed.errors, [currentId]: resourceState.errors };\n\n const updatedKeyed: KeyedResourceData<KeyedResourceKey, TEntity> = {\n entities: { ...currentKeyed.entities },\n isLoading: newIsLoading,\n status: newStatus,\n errors: newErrors,\n };\n\n target.update(resolvedTargetKey, {\n data: updatedKeyed,\n isLoading: isAnyKeyLoading(newIsLoading),\n } as Partial<TTarget[keyof TTarget & string]>);\n\n previousId = currentId;\n } else if (resourceState.data === undefined && previousId !== undefined) {\n // Source cleared — remove previous entity from cache\n const { [previousId]: _removed, ...remainingEntities } = currentKeyed.entities;\n const { [previousId]: _removedLoading, ...remainingLoading } = currentKeyed.isLoading;\n const { [previousId]: _removedStatus, ...remainingStatus } = currentKeyed.status;\n const { [previousId]: _removedErrors, ...remainingErrors } = currentKeyed.errors;\n\n const updatedKeyed: KeyedResourceData<KeyedResourceKey, TEntity> = {\n entities: remainingEntities,\n isLoading: remainingLoading,\n status: remainingStatus,\n errors: remainingErrors,\n };\n\n target.update(resolvedTargetKey, {\n data: updatedKeyed,\n isLoading: isAnyKeyLoading(remainingLoading),\n } as Partial<TTarget[keyof TTarget & string]>);\n\n previousId = undefined;\n } else if (resourceState.isLoading && currentId !== undefined) {\n const newIsLoading = { ...currentKeyed.isLoading, [currentId]: true };\n\n const updatedKeyed: KeyedResourceData<KeyedResourceKey, TEntity> = {\n entities: { ...currentKeyed.entities },\n isLoading: newIsLoading,\n status: { ...currentKeyed.status },\n errors: { ...currentKeyed.errors },\n };\n\n target.update(resolvedTargetKey, {\n data: updatedKeyed,\n isLoading: true,\n } as Partial<TTarget[keyof TTarget & string]>);\n\n previousId = currentId;\n }\n });\n\n if (resolvedOptions?.destroyRef) {\n resolvedOptions.destroyRef.onDestroy(cleanup);\n }\n\n return cleanup;\n}\n"],"mappings":"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","names":["import_core","import_core","import_core","import_core"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -98,6 +98,7 @@ interface AsStep<TAccum extends StoreConfig, TKey extends string> {
|
|
|
98
98
|
*/
|
|
99
99
|
interface StoreBuilder<TAccum extends StoreConfig> {
|
|
100
100
|
resource<TKey extends string>(key: TKey): AsStep<TAccum, TKey>;
|
|
101
|
+
mirror<TSourceData extends Record<string, ResourceState<unknown>>>(source: InjectionToken<IStore<TSourceData>>, sourceKey: keyof TSourceData & string, targetKey?: keyof TAccum & string): StoreBuilder<TAccum>;
|
|
101
102
|
build(): InjectionToken<BaseStore<InferEnum<TAccum>, InferData<TAccum>>>;
|
|
102
103
|
}
|
|
103
104
|
/** Keys from the enum that have NOT yet been defined. */
|
|
@@ -111,10 +112,15 @@ interface ConstrainedAsStep<TEnum extends Record<string, string>, TAccum extends
|
|
|
111
112
|
* defined yet. `.build()` is only available when all keys are accounted for.
|
|
112
113
|
*/
|
|
113
114
|
type ConstrainedBuilder<TEnum extends Record<string, string>, TAccum extends StoreConfig> = [Remaining<TEnum, TAccum>] extends [never] ? {
|
|
115
|
+
mirror<TSourceData extends Record<string, ResourceState<unknown>>>(source: InjectionToken<IStore<TSourceData>>, sourceKey: keyof TSourceData & string, targetKey?: keyof TAccum & string): ConstrainedBuilder<TEnum, TAccum>;
|
|
114
116
|
build(): InjectionToken<BaseStore<InferEnum<TAccum>, InferData<TAccum>>>;
|
|
115
117
|
} : {
|
|
116
118
|
resource<TKey extends Remaining<TEnum, TAccum>>(key: TKey): ConstrainedAsStep<TEnum, TAccum, TKey>;
|
|
117
119
|
};
|
|
120
|
+
interface InterfaceBuilder<TConfig extends Record<string, unknown>> {
|
|
121
|
+
mirror<TSourceData extends Record<string, ResourceState<unknown>>>(source: InjectionToken<IStore<TSourceData>>, sourceKey: keyof TSourceData & string, targetKey?: keyof TConfig & string): InterfaceBuilder<TConfig>;
|
|
122
|
+
build(): InjectionToken<IStore<ConfigToData<TConfig>>>;
|
|
123
|
+
}
|
|
118
124
|
interface StoreEntry {
|
|
119
125
|
/**
|
|
120
126
|
* Define a named resource slot.
|
|
@@ -135,9 +141,7 @@ interface StoreEntry {
|
|
|
135
141
|
* }
|
|
136
142
|
* const ChatStore = Store.for<ChatStoreConfig>().build();
|
|
137
143
|
*/
|
|
138
|
-
for<TConfig extends Record<string, unknown>>():
|
|
139
|
-
build(): InjectionToken<IStore<ConfigToData<TConfig>>>;
|
|
140
|
-
};
|
|
144
|
+
for<TConfig extends Record<string, unknown>>(): InterfaceBuilder<TConfig>;
|
|
141
145
|
/**
|
|
142
146
|
* Bind the builder to an enum object for compile-time key validation.
|
|
143
147
|
*
|
package/dist/index.d.ts
CHANGED
|
@@ -98,6 +98,7 @@ interface AsStep<TAccum extends StoreConfig, TKey extends string> {
|
|
|
98
98
|
*/
|
|
99
99
|
interface StoreBuilder<TAccum extends StoreConfig> {
|
|
100
100
|
resource<TKey extends string>(key: TKey): AsStep<TAccum, TKey>;
|
|
101
|
+
mirror<TSourceData extends Record<string, ResourceState<unknown>>>(source: InjectionToken<IStore<TSourceData>>, sourceKey: keyof TSourceData & string, targetKey?: keyof TAccum & string): StoreBuilder<TAccum>;
|
|
101
102
|
build(): InjectionToken<BaseStore<InferEnum<TAccum>, InferData<TAccum>>>;
|
|
102
103
|
}
|
|
103
104
|
/** Keys from the enum that have NOT yet been defined. */
|
|
@@ -111,10 +112,15 @@ interface ConstrainedAsStep<TEnum extends Record<string, string>, TAccum extends
|
|
|
111
112
|
* defined yet. `.build()` is only available when all keys are accounted for.
|
|
112
113
|
*/
|
|
113
114
|
type ConstrainedBuilder<TEnum extends Record<string, string>, TAccum extends StoreConfig> = [Remaining<TEnum, TAccum>] extends [never] ? {
|
|
115
|
+
mirror<TSourceData extends Record<string, ResourceState<unknown>>>(source: InjectionToken<IStore<TSourceData>>, sourceKey: keyof TSourceData & string, targetKey?: keyof TAccum & string): ConstrainedBuilder<TEnum, TAccum>;
|
|
114
116
|
build(): InjectionToken<BaseStore<InferEnum<TAccum>, InferData<TAccum>>>;
|
|
115
117
|
} : {
|
|
116
118
|
resource<TKey extends Remaining<TEnum, TAccum>>(key: TKey): ConstrainedAsStep<TEnum, TAccum, TKey>;
|
|
117
119
|
};
|
|
120
|
+
interface InterfaceBuilder<TConfig extends Record<string, unknown>> {
|
|
121
|
+
mirror<TSourceData extends Record<string, ResourceState<unknown>>>(source: InjectionToken<IStore<TSourceData>>, sourceKey: keyof TSourceData & string, targetKey?: keyof TConfig & string): InterfaceBuilder<TConfig>;
|
|
122
|
+
build(): InjectionToken<IStore<ConfigToData<TConfig>>>;
|
|
123
|
+
}
|
|
118
124
|
interface StoreEntry {
|
|
119
125
|
/**
|
|
120
126
|
* Define a named resource slot.
|
|
@@ -135,9 +141,7 @@ interface StoreEntry {
|
|
|
135
141
|
* }
|
|
136
142
|
* const ChatStore = Store.for<ChatStoreConfig>().build();
|
|
137
143
|
*/
|
|
138
|
-
for<TConfig extends Record<string, unknown>>():
|
|
139
|
-
build(): InjectionToken<IStore<ConfigToData<TConfig>>>;
|
|
140
|
-
};
|
|
144
|
+
for<TConfig extends Record<string, unknown>>(): InterfaceBuilder<TConfig>;
|
|
141
145
|
/**
|
|
142
146
|
* Bind the builder to an enum object for compile-time key validation.
|
|
143
147
|
*
|
package/dist/index.js
CHANGED
|
@@ -342,7 +342,7 @@ var LazyStore = class {
|
|
|
342
342
|
};
|
|
343
343
|
|
|
344
344
|
// src/store-builder.ts
|
|
345
|
-
import { InjectionToken } from "@angular/core";
|
|
345
|
+
import { InjectionToken, inject } from "@angular/core";
|
|
346
346
|
|
|
347
347
|
// src/dynamic-store.ts
|
|
348
348
|
var DynamicStore = class extends BaseStore {
|
|
@@ -355,13 +355,36 @@ var DynamicStore = class extends BaseStore {
|
|
|
355
355
|
}
|
|
356
356
|
};
|
|
357
357
|
|
|
358
|
+
// src/mirror-key.ts
|
|
359
|
+
function mirrorKey(source, sourceKey, target, targetKeyOrOptions, options) {
|
|
360
|
+
const resolvedTargetKey = typeof targetKeyOrOptions === "string" ? targetKeyOrOptions : sourceKey;
|
|
361
|
+
const resolvedOptions = typeof targetKeyOrOptions === "object" ? targetKeyOrOptions : options;
|
|
362
|
+
const cleanup = source.onUpdate(sourceKey, (state) => {
|
|
363
|
+
target.update(
|
|
364
|
+
resolvedTargetKey,
|
|
365
|
+
state
|
|
366
|
+
);
|
|
367
|
+
});
|
|
368
|
+
if (resolvedOptions?.destroyRef) {
|
|
369
|
+
resolvedOptions.destroyRef.onDestroy(cleanup);
|
|
370
|
+
}
|
|
371
|
+
return cleanup;
|
|
372
|
+
}
|
|
373
|
+
|
|
358
374
|
// src/resource.ts
|
|
359
375
|
function resource() {
|
|
360
376
|
return {};
|
|
361
377
|
}
|
|
362
378
|
|
|
363
379
|
// src/store-builder.ts
|
|
364
|
-
function
|
|
380
|
+
function wireMirrors(store, mirrors) {
|
|
381
|
+
for (const def of mirrors) {
|
|
382
|
+
const sourceStore = inject(def.sourceToken);
|
|
383
|
+
mirrorKey(sourceStore, def.sourceKey, store, def.targetKey);
|
|
384
|
+
}
|
|
385
|
+
return store;
|
|
386
|
+
}
|
|
387
|
+
function createBuilder(accum, mirrors = []) {
|
|
365
388
|
return {
|
|
366
389
|
resource(key) {
|
|
367
390
|
return {
|
|
@@ -370,19 +393,27 @@ function createBuilder(accum) {
|
|
|
370
393
|
...accum,
|
|
371
394
|
[key]: resource()
|
|
372
395
|
};
|
|
373
|
-
return createBuilder(nextAccum);
|
|
396
|
+
return createBuilder(nextAccum, mirrors);
|
|
374
397
|
}
|
|
375
398
|
};
|
|
376
399
|
},
|
|
400
|
+
mirror(source, sourceKey, targetKey) {
|
|
401
|
+
const def = {
|
|
402
|
+
sourceToken: source,
|
|
403
|
+
sourceKey,
|
|
404
|
+
targetKey: targetKey ?? sourceKey
|
|
405
|
+
};
|
|
406
|
+
return createBuilder(accum, [...mirrors, def]);
|
|
407
|
+
},
|
|
377
408
|
build() {
|
|
378
409
|
return new InjectionToken("FlurryxStore", {
|
|
379
410
|
providedIn: "root",
|
|
380
|
-
factory: () => new DynamicStore(accum)
|
|
411
|
+
factory: () => wireMirrors(new DynamicStore(accum), mirrors)
|
|
381
412
|
});
|
|
382
413
|
}
|
|
383
414
|
};
|
|
384
415
|
}
|
|
385
|
-
function createConstrainedBuilder(_enumObj, accum) {
|
|
416
|
+
function createConstrainedBuilder(_enumObj, accum, mirrors = []) {
|
|
386
417
|
return {
|
|
387
418
|
resource(key) {
|
|
388
419
|
return {
|
|
@@ -391,14 +422,43 @@ function createConstrainedBuilder(_enumObj, accum) {
|
|
|
391
422
|
...accum,
|
|
392
423
|
[key]: resource()
|
|
393
424
|
};
|
|
394
|
-
return createConstrainedBuilder(_enumObj, nextAccum);
|
|
425
|
+
return createConstrainedBuilder(_enumObj, nextAccum, mirrors);
|
|
395
426
|
}
|
|
396
427
|
};
|
|
397
428
|
},
|
|
429
|
+
mirror(source, sourceKey, targetKey) {
|
|
430
|
+
const def = {
|
|
431
|
+
sourceToken: source,
|
|
432
|
+
sourceKey,
|
|
433
|
+
targetKey: targetKey ?? sourceKey
|
|
434
|
+
};
|
|
435
|
+
return createConstrainedBuilder(_enumObj, accum, [...mirrors, def]);
|
|
436
|
+
},
|
|
398
437
|
build() {
|
|
399
438
|
return new InjectionToken("FlurryxStore", {
|
|
400
439
|
providedIn: "root",
|
|
401
|
-
factory: () => new DynamicStore(accum)
|
|
440
|
+
factory: () => wireMirrors(new DynamicStore(accum), mirrors)
|
|
441
|
+
});
|
|
442
|
+
}
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
function createInterfaceBuilder(mirrors = []) {
|
|
446
|
+
return {
|
|
447
|
+
mirror(source, sourceKey, targetKey) {
|
|
448
|
+
const def = {
|
|
449
|
+
sourceToken: source,
|
|
450
|
+
sourceKey,
|
|
451
|
+
targetKey: targetKey ?? sourceKey
|
|
452
|
+
};
|
|
453
|
+
return createInterfaceBuilder([...mirrors, def]);
|
|
454
|
+
},
|
|
455
|
+
build() {
|
|
456
|
+
return new InjectionToken("FlurryxStore", {
|
|
457
|
+
providedIn: "root",
|
|
458
|
+
factory: () => wireMirrors(
|
|
459
|
+
new LazyStore(),
|
|
460
|
+
mirrors
|
|
461
|
+
)
|
|
402
462
|
});
|
|
403
463
|
}
|
|
404
464
|
};
|
|
@@ -407,35 +467,12 @@ var Store = {
|
|
|
407
467
|
...createBuilder({}),
|
|
408
468
|
for(enumObj) {
|
|
409
469
|
if (arguments.length === 0) {
|
|
410
|
-
return
|
|
411
|
-
build() {
|
|
412
|
-
return new InjectionToken("FlurryxStore", {
|
|
413
|
-
providedIn: "root",
|
|
414
|
-
factory: () => new LazyStore()
|
|
415
|
-
});
|
|
416
|
-
}
|
|
417
|
-
};
|
|
470
|
+
return createInterfaceBuilder();
|
|
418
471
|
}
|
|
419
472
|
return createConstrainedBuilder(enumObj, {});
|
|
420
473
|
}
|
|
421
474
|
};
|
|
422
475
|
|
|
423
|
-
// src/mirror-key.ts
|
|
424
|
-
function mirrorKey(source, sourceKey, target, targetKeyOrOptions, options) {
|
|
425
|
-
const resolvedTargetKey = typeof targetKeyOrOptions === "string" ? targetKeyOrOptions : sourceKey;
|
|
426
|
-
const resolvedOptions = typeof targetKeyOrOptions === "object" ? targetKeyOrOptions : options;
|
|
427
|
-
const cleanup = source.onUpdate(sourceKey, (state) => {
|
|
428
|
-
target.update(
|
|
429
|
-
resolvedTargetKey,
|
|
430
|
-
state
|
|
431
|
-
);
|
|
432
|
-
});
|
|
433
|
-
if (resolvedOptions?.destroyRef) {
|
|
434
|
-
resolvedOptions.destroyRef.onDestroy(cleanup);
|
|
435
|
-
}
|
|
436
|
-
return cleanup;
|
|
437
|
-
}
|
|
438
|
-
|
|
439
476
|
// src/collect-keyed.ts
|
|
440
477
|
import { createKeyedResourceData as createKeyedResourceData2, isAnyKeyLoading as isAnyKeyLoading2 } from "@flurryx/core";
|
|
441
478
|
function collectKeyed(source, sourceKey, target, targetKeyOrOptions, options) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/base-store.ts","../src/lazy-store.ts","../src/store-builder.ts","../src/dynamic-store.ts","../src/resource.ts","../src/mirror-key.ts","../src/collect-keyed.ts"],"sourcesContent":["import { signal, WritableSignal } from \"@angular/core\";\nimport {\n ResourceState,\n isAnyKeyLoading,\n isKeyedResourceData,\n createKeyedResourceData,\n type KeyedResourceKey,\n} from \"@flurryx/core\";\nimport type { IStore } from \"./types\";\n\ntype UpdateHooksMap = Map<\n unknown,\n Array<\n (\n nextState: ResourceState<unknown>,\n previousState: ResourceState<unknown>\n ) => void\n >\n>;\n\nconst updateHooksMap = new WeakMap<object, UpdateHooksMap>();\n\nexport abstract class BaseStore<\n TEnum extends Record<string, string | number>,\n TData extends { [K in keyof TEnum]: ResourceState<unknown> }\n> implements IStore<TData>\n{\n private readonly signalsState = new Map<\n keyof TEnum,\n WritableSignal<TData[keyof TEnum]>\n >();\n\n protected constructor(protected readonly storeEnum: TEnum) {\n this.initializeState();\n updateHooksMap.set(this, new Map());\n }\n\n get<K extends keyof TData>(key: K): WritableSignal<TData[K]> {\n return this.signalsState.get(key.toString()) as WritableSignal<TData[K]>;\n }\n\n onUpdate<K extends keyof TData>(\n key: K,\n callback: (state: TData[K], previousState: TData[K]) => void\n ): () => void {\n const hooks = updateHooksMap.get(this)!;\n if (!hooks.has(key)) {\n hooks.set(key, []);\n }\n hooks\n .get(key)!\n .push(\n callback as (\n nextState: ResourceState<unknown>,\n previousState: ResourceState<unknown>\n ) => void\n );\n\n return () => {\n const hooksMap = hooks.get(key);\n if (!hooksMap) {\n return;\n }\n const index = hooksMap.indexOf(\n callback as (\n nextState: ResourceState<unknown>,\n previousState: ResourceState<unknown>\n ) => void\n );\n if (index > -1) {\n hooksMap.splice(index, 1);\n }\n };\n }\n\n update<K extends keyof TData>(key: K, newState: Partial<TData[K]>): void {\n const currentState = this.signalsState.get(key.toString());\n if (!currentState) {\n return;\n }\n\n const previousState = currentState() as TData[K];\n currentState.update((state) => ({\n ...state,\n ...newState,\n }));\n\n const updatedState = currentState() as TData[K];\n this.notifyUpdateHooks(key, updatedState, previousState);\n }\n\n clearAll(): void {\n Object.keys(this.storeEnum).forEach((key) => {\n this.clear(key as keyof TData);\n });\n }\n\n clear<K extends keyof TData>(key: K): void {\n const currentState = this.signalsState.get(key.toString());\n if (!currentState) {\n return;\n }\n\n const previousState = currentState() as TData[K];\n const _typedKey = key as keyof TEnum;\n currentState.set({\n data: undefined,\n isLoading: false,\n status: undefined,\n errors: undefined,\n } as TData[typeof _typedKey]);\n\n const nextState = currentState() as TData[K];\n this.notifyUpdateHooks(key, nextState, previousState);\n }\n\n startLoading<K extends keyof TData>(key: K): void {\n const currentState = this.signalsState.get(key.toString());\n if (!currentState) {\n return;\n }\n\n const _typedKey = key as keyof TEnum;\n currentState.update(\n (state) =>\n ({\n ...state,\n status: undefined,\n isLoading: true,\n errors: undefined,\n } as TData[typeof _typedKey])\n );\n }\n\n stopLoading<K extends keyof TData>(key: K): void {\n const currentState = this.signalsState.get(key.toString());\n if (!currentState) {\n return;\n }\n\n const _typedKey = key as keyof TEnum;\n currentState.update(\n (state) =>\n ({\n ...state,\n isLoading: false,\n status: undefined,\n errors: undefined,\n } as TData[typeof _typedKey])\n );\n }\n\n updateKeyedOne<K extends keyof TData>(\n key: K,\n resourceKey: KeyedResourceKey,\n entity: unknown\n ): void {\n const currentState = this.signalsState.get(key.toString());\n if (!currentState) {\n return;\n }\n\n const state = currentState();\n const data = isKeyedResourceData(state.data)\n ? state.data\n : createKeyedResourceData();\n\n const nextErrors = { ...data.errors };\n delete nextErrors[resourceKey];\n\n const nextData = {\n ...data,\n entities: {\n ...data.entities,\n [resourceKey]: entity,\n },\n isLoading: {\n ...data.isLoading,\n [resourceKey]: false,\n },\n status: {\n ...data.status,\n [resourceKey]: \"Success\" as const,\n },\n errors: nextErrors,\n };\n\n this.update(key, {\n data: nextData as unknown,\n isLoading: isAnyKeyLoading(nextData.isLoading),\n status: undefined,\n errors: undefined,\n } as Partial<TData[K]>);\n }\n\n clearKeyedOne<K extends keyof TData>(\n key: K,\n resourceKey: KeyedResourceKey\n ): void {\n const currentState = this.signalsState.get(key.toString());\n if (!currentState) {\n return;\n }\n\n const previousState = currentState() as TData[K];\n const state = previousState as ResourceState<unknown>;\n if (!isKeyedResourceData(state.data)) {\n return;\n }\n\n const data = state.data;\n\n const nextEntities = { ...data.entities };\n delete nextEntities[resourceKey];\n\n const nextIsLoading = { ...data.isLoading };\n delete nextIsLoading[resourceKey];\n\n const nextStatus = { ...data.status };\n delete nextStatus[resourceKey];\n\n const nextErrors = { ...data.errors };\n delete nextErrors[resourceKey];\n\n const nextData = {\n ...data,\n entities: nextEntities,\n isLoading: nextIsLoading,\n status: nextStatus,\n errors: nextErrors,\n };\n\n const _typedKey = key as keyof TEnum;\n currentState.update(\n (prev) =>\n ({\n ...prev,\n data: nextData as unknown,\n status: undefined,\n isLoading: isAnyKeyLoading(nextIsLoading),\n errors: undefined,\n } as TData[typeof _typedKey])\n );\n\n const updatedState = currentState() as TData[K];\n this.notifyUpdateHooks(key, updatedState, previousState);\n }\n\n startKeyedLoading<K extends keyof TData>(\n key: K,\n resourceKey: KeyedResourceKey\n ): void {\n const currentState = this.signalsState.get(key.toString());\n if (!currentState) {\n return;\n }\n\n const _typedKey = key as keyof TEnum;\n const state = currentState();\n if (!isKeyedResourceData(state.data)) {\n this.startLoading(key);\n return;\n }\n\n const previousState = state as TData[K];\n const data = state.data;\n\n const nextIsLoading = {\n ...data.isLoading,\n [resourceKey]: true,\n } as typeof data.isLoading;\n\n const nextStatus: typeof data.status = {\n ...data.status,\n };\n delete nextStatus[resourceKey];\n\n const nextErrors: typeof data.errors = {\n ...data.errors,\n };\n delete nextErrors[resourceKey];\n\n const nextData = {\n ...data,\n isLoading: nextIsLoading,\n status: nextStatus,\n errors: nextErrors,\n };\n\n currentState.update(\n (previous) =>\n ({\n ...previous,\n data: nextData,\n status: undefined,\n isLoading: isAnyKeyLoading(nextIsLoading),\n errors: undefined,\n } as TData[typeof _typedKey])\n );\n\n const updatedState = currentState() as TData[K];\n this.notifyUpdateHooks(key, updatedState, previousState);\n }\n\n private notifyUpdateHooks<K extends keyof TData>(\n key: K,\n nextState: TData[K],\n previousState: TData[K]\n ): void {\n const hooks = updateHooksMap.get(this);\n const keyHooks = hooks?.get(key);\n if (!keyHooks) {\n return;\n }\n\n keyHooks.forEach((hook) =>\n hook(\n nextState as ResourceState<unknown>,\n previousState as ResourceState<unknown>\n )\n );\n }\n\n private initializeState(): void {\n Object.keys(this.storeEnum).forEach((key) => {\n const _typedKey = key as keyof TEnum;\n const initialState: ResourceState<unknown> = {\n data: undefined,\n isLoading: false,\n status: undefined,\n errors: undefined,\n };\n this.signalsState.set(\n _typedKey,\n signal<TData[typeof _typedKey]>(initialState as TData[typeof _typedKey])\n );\n });\n }\n}\n","import { signal, WritableSignal } from '@angular/core';\nimport type { ResourceState } from '@flurryx/core';\nimport type { IStore } from './types';\n\ntype UpdateCallback = (\n nextState: ResourceState<unknown>,\n previousState: ResourceState<unknown>\n) => void;\n\nfunction createDefaultState<T>(): ResourceState<T> {\n return {\n data: undefined,\n isLoading: false,\n status: undefined,\n errors: undefined,\n };\n}\n\n/**\n * Lazy store that creates signals on first access.\n * Used by the `Store.for<Config>().build()` API where keys are\n * known only at the type level (no runtime enum).\n */\nexport class LazyStore<\n TData extends Record<string, ResourceState<unknown>>,\n> implements IStore<TData>\n{\n private readonly signals = new Map<string, WritableSignal<ResourceState<unknown>>>();\n private readonly hooks = new Map<string, UpdateCallback[]>();\n\n private getOrCreate<K extends keyof TData & string>(\n key: K\n ): WritableSignal<TData[K]> {\n let sig = this.signals.get(key);\n if (!sig) {\n sig = signal<ResourceState<unknown>>(createDefaultState());\n this.signals.set(key, sig);\n }\n return sig as WritableSignal<TData[K]>;\n }\n\n get<K extends keyof TData & string>(key: K): WritableSignal<TData[K]> {\n return this.getOrCreate(key);\n }\n\n update<K extends keyof TData & string>(\n key: K,\n newState: Partial<TData[K]>\n ): void {\n const sig = this.getOrCreate(key);\n const previousState = sig();\n sig.update((state) => ({ ...state, ...newState }));\n const nextState = sig();\n this.notifyHooks(key, nextState, previousState);\n }\n\n clear<K extends keyof TData & string>(key: K): void {\n const sig = this.getOrCreate(key);\n const previousState = sig();\n sig.set(createDefaultState() as TData[K]);\n const nextState = sig();\n this.notifyHooks(key, nextState, previousState);\n }\n\n clearAll(): void {\n for (const key of this.signals.keys()) {\n this.clear(key as keyof TData & string);\n }\n }\n\n startLoading<K extends keyof TData & string>(key: K): void {\n const sig = this.getOrCreate(key);\n sig.update(\n (state) =>\n ({\n ...state,\n status: undefined,\n isLoading: true,\n errors: undefined,\n }) as TData[K]\n );\n }\n\n stopLoading<K extends keyof TData & string>(key: K): void {\n const sig = this.getOrCreate(key);\n sig.update(\n (state) =>\n ({\n ...state,\n isLoading: false,\n status: undefined,\n errors: undefined,\n }) as TData[K]\n );\n }\n\n onUpdate<K extends keyof TData & string>(\n key: K,\n callback: (state: TData[K], previousState: TData[K]) => void\n ): () => void {\n if (!this.hooks.has(key)) {\n this.hooks.set(key, []);\n }\n const typedCallback = callback as UpdateCallback;\n this.hooks.get(key)!.push(typedCallback);\n\n return () => {\n const keyHooks = this.hooks.get(key);\n if (!keyHooks) {\n return;\n }\n const index = keyHooks.indexOf(typedCallback);\n if (index > -1) {\n keyHooks.splice(index, 1);\n }\n };\n }\n\n private notifyHooks<K extends keyof TData & string>(\n key: K,\n nextState: TData[K],\n previousState: TData[K]\n ): void {\n const keyHooks = this.hooks.get(key);\n if (!keyHooks) {\n return;\n }\n keyHooks.forEach((hook) =>\n hook(\n nextState as ResourceState<unknown>,\n previousState as ResourceState<unknown>\n )\n );\n }\n}\n","import { InjectionToken } from \"@angular/core\";\nimport { BaseStore } from \"./base-store\";\nimport { DynamicStore } from \"./dynamic-store\";\nimport { LazyStore } from \"./lazy-store\";\nimport { resource } from \"./resource\";\nimport type {\n StoreConfig,\n ResourceDef,\n InferEnum,\n InferData,\n ConfigToData,\n IStore,\n} from \"./types\";\n\n// ---------------------------------------------------------------------------\n// Unconstrained builder (existing API)\n// ---------------------------------------------------------------------------\n\n/**\n * Intermediate builder step after .resource('key') — awaits .as<T>().\n */\ninterface AsStep<TAccum extends StoreConfig, TKey extends string> {\n as<T>(): StoreBuilder<TAccum & Record<TKey, ResourceDef<T>>>;\n}\n\n/**\n * Fluent builder for creating stores.\n * Accumulates resource definitions then produces an InjectionToken on .build().\n */\ninterface StoreBuilder<TAccum extends StoreConfig> {\n resource<TKey extends string>(key: TKey): AsStep<TAccum, TKey>;\n build(): InjectionToken<BaseStore<InferEnum<TAccum>, InferData<TAccum>>>;\n}\n\nfunction createBuilder<TAccum extends StoreConfig>(\n accum: TAccum\n): StoreBuilder<TAccum> {\n return {\n resource<TKey extends string>(key: TKey): AsStep<TAccum, TKey> {\n return {\n as<T>(): StoreBuilder<TAccum & Record<TKey, ResourceDef<T>>> {\n const nextAccum = {\n ...accum,\n [key]: resource<T>(),\n } as TAccum & Record<TKey, ResourceDef<T>>;\n return createBuilder(nextAccum);\n },\n };\n },\n build() {\n return new InjectionToken<\n BaseStore<InferEnum<TAccum>, InferData<TAccum>>\n >(\"FlurryxStore\", {\n providedIn: \"root\",\n factory: () => new DynamicStore(accum),\n });\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// Constrained builder (.for(enum) API)\n// ---------------------------------------------------------------------------\n\n/** Keys from the enum that have NOT yet been defined. */\ntype Remaining<\n TEnum extends Record<string, string>,\n TAccum extends StoreConfig\n> = Exclude<keyof TEnum & string, keyof TAccum>;\n\n/** Intermediate .as<T>() step for the constrained builder. */\ninterface ConstrainedAsStep<\n TEnum extends Record<string, string>,\n TAccum extends StoreConfig,\n TKey extends string\n> {\n as<T>(): ConstrainedBuilder<TEnum, TAccum & Record<TKey, ResourceDef<T>>>;\n}\n\n/**\n * Constrained builder — only allows keys from the enum that haven't been\n * defined yet. `.build()` is only available when all keys are accounted for.\n */\ntype ConstrainedBuilder<\n TEnum extends Record<string, string>,\n TAccum extends StoreConfig\n> = [Remaining<TEnum, TAccum>] extends [never]\n ? {\n build(): InjectionToken<BaseStore<InferEnum<TAccum>, InferData<TAccum>>>;\n }\n : {\n resource<TKey extends Remaining<TEnum, TAccum>>(\n key: TKey\n ): ConstrainedAsStep<TEnum, TAccum, TKey>;\n };\n\nfunction createConstrainedBuilder<\n TEnum extends Record<string, string>,\n TAccum extends StoreConfig\n>(_enumObj: TEnum, accum: TAccum): ConstrainedBuilder<TEnum, TAccum> {\n return {\n resource<TKey extends string>(\n key: TKey\n ): ConstrainedAsStep<TEnum, TAccum, TKey> {\n return {\n as<T>(): ConstrainedBuilder<\n TEnum,\n TAccum & Record<TKey, ResourceDef<T>>\n > {\n const nextAccum = {\n ...accum,\n [key]: resource<T>(),\n } as TAccum & Record<TKey, ResourceDef<T>>;\n return createConstrainedBuilder(_enumObj, nextAccum);\n },\n };\n },\n build() {\n return new InjectionToken<\n BaseStore<InferEnum<TAccum>, InferData<TAccum>>\n >(\"FlurryxStore\", {\n providedIn: \"root\",\n factory: () => new DynamicStore(accum),\n });\n },\n } as ConstrainedBuilder<TEnum, TAccum>;\n}\n\n// ---------------------------------------------------------------------------\n// Public entry point\n// ---------------------------------------------------------------------------\n\ninterface StoreEntry {\n /**\n * Define a named resource slot.\n * Chain .as<T>() to assign its type, then continue with more .resource() calls\n * or call .build() when done.\n */\n resource<TKey extends string>(\n key: TKey\n ): {\n as<T>(): StoreBuilder<Record<TKey, ResourceDef<T>>>;\n };\n\n /**\n * Interface-based builder: pass a config interface as a generic.\n * No runtime argument needed — keys and types are inferred from the interface.\n *\n * @example\n * interface ChatStoreConfig {\n * SESSIONS: ChatSession[];\n * MESSAGES: ChatMessage[];\n * }\n * const ChatStore = Store.for<ChatStoreConfig>().build();\n */\n for<TConfig extends Record<string, unknown>>(): {\n build(): InjectionToken<IStore<ConfigToData<TConfig>>>;\n };\n\n /**\n * Bind the builder to an enum object for compile-time key validation.\n *\n * @example\n * const Enum = { A: 'A', B: 'B' } as const;\n * const MyStore = Store.for(Enum)\n * .resource('A').as<string>()\n * .resource('B').as<number>()\n * .build();\n */\n for<TEnum extends Record<string, string>>(\n enumObj: TEnum\n ): ConstrainedBuilder<TEnum, Record<string, never>>;\n}\n\n/**\n * Fluent store builder entry point.\n *\n * @example\n * // Unconstrained\n * export const CustomersStore = Store\n * .resource('customers').as<Customer[]>()\n * .resource('customerDetails').as<Customer>()\n * .build();\n *\n * @example\n * // Constrained with enum\n * const Enum = { SESSIONS: 'SESSIONS', MESSAGES: 'MESSAGES' } as const;\n * export const ChatStore = Store.for(Enum)\n * .resource('SESSIONS').as<Session[]>()\n * .resource('MESSAGES').as<Message[]>()\n * .build();\n */\nexport const Store: StoreEntry = {\n ...createBuilder({} as StoreConfig),\n for(enumObj?: Record<string, string>) {\n if (arguments.length === 0) {\n return {\n build() {\n return new InjectionToken(\"FlurryxStore\", {\n providedIn: \"root\",\n factory: () => new LazyStore(),\n });\n },\n };\n }\n return createConstrainedBuilder(enumObj!, {} as Record<string, never>);\n },\n};\n","import { BaseStore } from './base-store';\nimport type { StoreConfig, InferEnum, InferData } from './types';\n\n/**\n * Internal concrete subclass of BaseStore.\n * Auto-generates an identity enum from config keys.\n * NOT publicly exported — consumers interact via BaseStore interface.\n */\nexport class DynamicStore<\n TConfig extends StoreConfig,\n> extends BaseStore<InferEnum<TConfig>, InferData<TConfig>> {\n constructor(config: TConfig) {\n const identityEnum = Object.keys(config).reduce(\n (acc, key) => ({ ...acc, [key]: key }),\n {} as InferEnum<TConfig>\n );\n super(identityEnum);\n }\n}\n","import type { ResourceDef } from './types';\n\n/**\n * Creates a phantom-typed resource definition marker.\n * Zero runtime cost — returns an empty object that only carries type info.\n *\n * @example\n * const config = {\n * customers: resource<Customer[]>(),\n * customerDetails: resource<Customer>(),\n * };\n */\nexport function resource<T>(): ResourceDef<T> {\n return {} as ResourceDef<T>;\n}\n","import type { ResourceState } from \"@flurryx/core\";\nimport type { IStore } from \"./types\";\n\nexport interface MirrorOptions {\n destroyRef?: { onDestroy: (fn: () => void) => void };\n}\n\n/**\n * Mirrors a resource key from a source store to a target store.\n * When the source key updates, the target key is updated with the same state.\n *\n * @param source - The store to mirror from\n * @param sourceKey - The key to watch on the source store\n * @param target - The store to mirror to\n * @param targetKeyOrOptions - Either the target key name or options (defaults source key)\n * @param options - Mirror options when a target key is provided\n * @returns Cleanup function to stop mirroring\n */\nexport function mirrorKey<\n TSource extends Record<string, ResourceState<unknown>>,\n TTarget extends Record<string, ResourceState<unknown>>\n>(\n source: IStore<TSource>,\n sourceKey: keyof TSource & string,\n target: IStore<TTarget>,\n targetKeyOrOptions?: (keyof TTarget & string) | MirrorOptions,\n options?: MirrorOptions\n): () => void {\n const resolvedTargetKey = (\n typeof targetKeyOrOptions === \"string\" ? targetKeyOrOptions : sourceKey\n ) as keyof TTarget & string;\n\n const resolvedOptions =\n typeof targetKeyOrOptions === \"object\" ? targetKeyOrOptions : options;\n\n const cleanup = source.onUpdate(sourceKey, (state) => {\n target.update(\n resolvedTargetKey,\n state as unknown as Partial<TTarget[keyof TTarget & string]>\n );\n });\n\n if (resolvedOptions?.destroyRef) {\n resolvedOptions.destroyRef.onDestroy(cleanup);\n }\n\n return cleanup;\n}\n","import type {\n ResourceState,\n KeyedResourceKey,\n KeyedResourceData,\n} from '@flurryx/core';\nimport { createKeyedResourceData, isAnyKeyLoading } from '@flurryx/core';\nimport type { IStore } from './types';\n\nexport interface CollectKeyedOptions<TEntity> {\n extractId: (data: TEntity | undefined) => KeyedResourceKey | undefined;\n destroyRef?: { onDestroy: (fn: () => void) => void };\n}\n\n/**\n * Accumulates single-entity resource fetches into a keyed cache on a target store.\n *\n * On each source update:\n * - If status is 'Success' and extractId returns a valid key, merges the entity\n * into the target's keyed resource data.\n * - If the source data is cleared and a previous entity existed, removes it from\n * the target's keyed data.\n *\n * @param source - The store containing the single-entity resource\n * @param sourceKey - The key to watch on the source store\n * @param target - The store to accumulate entities into\n * @param targetKeyOrOptions - Either the target key name or options (defaults source key)\n * @param options - Collect options when a target key is provided\n * @returns Cleanup function to stop collecting\n */\nexport function collectKeyed<\n TSource extends Record<string, ResourceState<unknown>>,\n TTarget extends Record<string, ResourceState<unknown>>,\n TEntity = unknown,\n>(\n source: IStore<TSource>,\n sourceKey: keyof TSource & string,\n target: IStore<TTarget>,\n targetKeyOrOptions?: (keyof TTarget & string) | CollectKeyedOptions<TEntity>,\n options?: CollectKeyedOptions<TEntity>,\n): () => void {\n const resolvedTargetKey = (\n typeof targetKeyOrOptions === 'string'\n ? targetKeyOrOptions\n : sourceKey\n ) as keyof TTarget & string;\n\n const resolvedOptions = (\n typeof targetKeyOrOptions === 'object' ? targetKeyOrOptions : options\n ) as CollectKeyedOptions<TEntity>;\n\n // Initialize target with empty keyed resource data\n target.update(resolvedTargetKey, {\n data: createKeyedResourceData(),\n } as Partial<TTarget[keyof TTarget & string]>);\n\n let previousId: KeyedResourceKey | undefined;\n\n const cleanup = source.onUpdate(sourceKey, (state) => {\n const resourceState = state as ResourceState<TEntity>;\n const currentId = resolvedOptions.extractId(resourceState.data);\n const currentTarget = target.get(resolvedTargetKey)();\n const currentKeyed = (currentTarget as ResourceState<unknown>).data as\n KeyedResourceData<KeyedResourceKey, TEntity> | undefined;\n\n if (!currentKeyed) {\n return;\n }\n\n if (resourceState.status === 'Success' && currentId !== undefined) {\n const newEntities = { ...currentKeyed.entities, [currentId]: resourceState.data };\n const newIsLoading = { ...currentKeyed.isLoading, [currentId]: false };\n const newStatus = { ...currentKeyed.status, [currentId]: resourceState.status };\n const newErrors = { ...currentKeyed.errors };\n delete newErrors[currentId];\n\n const updatedKeyed: KeyedResourceData<KeyedResourceKey, TEntity> = {\n entities: newEntities,\n isLoading: newIsLoading,\n status: newStatus,\n errors: newErrors,\n };\n\n target.update(resolvedTargetKey, {\n data: updatedKeyed,\n isLoading: isAnyKeyLoading(newIsLoading),\n status: 'Success',\n } as Partial<TTarget[keyof TTarget & string]>);\n\n previousId = currentId;\n } else if (resourceState.status === 'Error' && currentId !== undefined) {\n const newIsLoading = { ...currentKeyed.isLoading, [currentId]: false };\n const newStatus = { ...currentKeyed.status, [currentId]: resourceState.status };\n const newErrors = { ...currentKeyed.errors, [currentId]: resourceState.errors };\n\n const updatedKeyed: KeyedResourceData<KeyedResourceKey, TEntity> = {\n entities: { ...currentKeyed.entities },\n isLoading: newIsLoading,\n status: newStatus,\n errors: newErrors,\n };\n\n target.update(resolvedTargetKey, {\n data: updatedKeyed,\n isLoading: isAnyKeyLoading(newIsLoading),\n } as Partial<TTarget[keyof TTarget & string]>);\n\n previousId = currentId;\n } else if (resourceState.data === undefined && previousId !== undefined) {\n // Source cleared — remove previous entity from cache\n const { [previousId]: _removed, ...remainingEntities } = currentKeyed.entities;\n const { [previousId]: _removedLoading, ...remainingLoading } = currentKeyed.isLoading;\n const { [previousId]: _removedStatus, ...remainingStatus } = currentKeyed.status;\n const { [previousId]: _removedErrors, ...remainingErrors } = currentKeyed.errors;\n\n const updatedKeyed: KeyedResourceData<KeyedResourceKey, TEntity> = {\n entities: remainingEntities,\n isLoading: remainingLoading,\n status: remainingStatus,\n errors: remainingErrors,\n };\n\n target.update(resolvedTargetKey, {\n data: updatedKeyed,\n isLoading: isAnyKeyLoading(remainingLoading),\n } as Partial<TTarget[keyof TTarget & string]>);\n\n previousId = undefined;\n } else if (resourceState.isLoading && currentId !== undefined) {\n const newIsLoading = { ...currentKeyed.isLoading, [currentId]: true };\n\n const updatedKeyed: KeyedResourceData<KeyedResourceKey, TEntity> = {\n entities: { ...currentKeyed.entities },\n isLoading: newIsLoading,\n status: { ...currentKeyed.status },\n errors: { ...currentKeyed.errors },\n };\n\n target.update(resolvedTargetKey, {\n data: updatedKeyed,\n isLoading: true,\n } as Partial<TTarget[keyof TTarget & string]>);\n\n previousId = currentId;\n }\n });\n\n if (resolvedOptions?.destroyRef) {\n resolvedOptions.destroyRef.onDestroy(cleanup);\n }\n\n return cleanup;\n}\n"],"mappings":"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","names":["signal","createKeyedResourceData","isAnyKeyLoading"]}
|
|
1
|
+
{"version":3,"sources":["../src/base-store.ts","../src/lazy-store.ts","../src/store-builder.ts","../src/dynamic-store.ts","../src/mirror-key.ts","../src/resource.ts","../src/collect-keyed.ts"],"sourcesContent":["import { signal, WritableSignal } from \"@angular/core\";\nimport {\n ResourceState,\n isAnyKeyLoading,\n isKeyedResourceData,\n createKeyedResourceData,\n type KeyedResourceKey,\n} from \"@flurryx/core\";\nimport type { IStore } from \"./types\";\n\ntype UpdateHooksMap = Map<\n unknown,\n Array<\n (\n nextState: ResourceState<unknown>,\n previousState: ResourceState<unknown>\n ) => void\n >\n>;\n\nconst updateHooksMap = new WeakMap<object, UpdateHooksMap>();\n\nexport abstract class BaseStore<\n TEnum extends Record<string, string | number>,\n TData extends { [K in keyof TEnum]: ResourceState<unknown> }\n> implements IStore<TData>\n{\n private readonly signalsState = new Map<\n keyof TEnum,\n WritableSignal<TData[keyof TEnum]>\n >();\n\n protected constructor(protected readonly storeEnum: TEnum) {\n this.initializeState();\n updateHooksMap.set(this, new Map());\n }\n\n get<K extends keyof TData>(key: K): WritableSignal<TData[K]> {\n return this.signalsState.get(key.toString()) as WritableSignal<TData[K]>;\n }\n\n onUpdate<K extends keyof TData>(\n key: K,\n callback: (state: TData[K], previousState: TData[K]) => void\n ): () => void {\n const hooks = updateHooksMap.get(this)!;\n if (!hooks.has(key)) {\n hooks.set(key, []);\n }\n hooks\n .get(key)!\n .push(\n callback as (\n nextState: ResourceState<unknown>,\n previousState: ResourceState<unknown>\n ) => void\n );\n\n return () => {\n const hooksMap = hooks.get(key);\n if (!hooksMap) {\n return;\n }\n const index = hooksMap.indexOf(\n callback as (\n nextState: ResourceState<unknown>,\n previousState: ResourceState<unknown>\n ) => void\n );\n if (index > -1) {\n hooksMap.splice(index, 1);\n }\n };\n }\n\n update<K extends keyof TData>(key: K, newState: Partial<TData[K]>): void {\n const currentState = this.signalsState.get(key.toString());\n if (!currentState) {\n return;\n }\n\n const previousState = currentState() as TData[K];\n currentState.update((state) => ({\n ...state,\n ...newState,\n }));\n\n const updatedState = currentState() as TData[K];\n this.notifyUpdateHooks(key, updatedState, previousState);\n }\n\n clearAll(): void {\n Object.keys(this.storeEnum).forEach((key) => {\n this.clear(key as keyof TData);\n });\n }\n\n clear<K extends keyof TData>(key: K): void {\n const currentState = this.signalsState.get(key.toString());\n if (!currentState) {\n return;\n }\n\n const previousState = currentState() as TData[K];\n const _typedKey = key as keyof TEnum;\n currentState.set({\n data: undefined,\n isLoading: false,\n status: undefined,\n errors: undefined,\n } as TData[typeof _typedKey]);\n\n const nextState = currentState() as TData[K];\n this.notifyUpdateHooks(key, nextState, previousState);\n }\n\n startLoading<K extends keyof TData>(key: K): void {\n const currentState = this.signalsState.get(key.toString());\n if (!currentState) {\n return;\n }\n\n const _typedKey = key as keyof TEnum;\n currentState.update(\n (state) =>\n ({\n ...state,\n status: undefined,\n isLoading: true,\n errors: undefined,\n } as TData[typeof _typedKey])\n );\n }\n\n stopLoading<K extends keyof TData>(key: K): void {\n const currentState = this.signalsState.get(key.toString());\n if (!currentState) {\n return;\n }\n\n const _typedKey = key as keyof TEnum;\n currentState.update(\n (state) =>\n ({\n ...state,\n isLoading: false,\n status: undefined,\n errors: undefined,\n } as TData[typeof _typedKey])\n );\n }\n\n updateKeyedOne<K extends keyof TData>(\n key: K,\n resourceKey: KeyedResourceKey,\n entity: unknown\n ): void {\n const currentState = this.signalsState.get(key.toString());\n if (!currentState) {\n return;\n }\n\n const state = currentState();\n const data = isKeyedResourceData(state.data)\n ? state.data\n : createKeyedResourceData();\n\n const nextErrors = { ...data.errors };\n delete nextErrors[resourceKey];\n\n const nextData = {\n ...data,\n entities: {\n ...data.entities,\n [resourceKey]: entity,\n },\n isLoading: {\n ...data.isLoading,\n [resourceKey]: false,\n },\n status: {\n ...data.status,\n [resourceKey]: \"Success\" as const,\n },\n errors: nextErrors,\n };\n\n this.update(key, {\n data: nextData as unknown,\n isLoading: isAnyKeyLoading(nextData.isLoading),\n status: undefined,\n errors: undefined,\n } as Partial<TData[K]>);\n }\n\n clearKeyedOne<K extends keyof TData>(\n key: K,\n resourceKey: KeyedResourceKey\n ): void {\n const currentState = this.signalsState.get(key.toString());\n if (!currentState) {\n return;\n }\n\n const previousState = currentState() as TData[K];\n const state = previousState as ResourceState<unknown>;\n if (!isKeyedResourceData(state.data)) {\n return;\n }\n\n const data = state.data;\n\n const nextEntities = { ...data.entities };\n delete nextEntities[resourceKey];\n\n const nextIsLoading = { ...data.isLoading };\n delete nextIsLoading[resourceKey];\n\n const nextStatus = { ...data.status };\n delete nextStatus[resourceKey];\n\n const nextErrors = { ...data.errors };\n delete nextErrors[resourceKey];\n\n const nextData = {\n ...data,\n entities: nextEntities,\n isLoading: nextIsLoading,\n status: nextStatus,\n errors: nextErrors,\n };\n\n const _typedKey = key as keyof TEnum;\n currentState.update(\n (prev) =>\n ({\n ...prev,\n data: nextData as unknown,\n status: undefined,\n isLoading: isAnyKeyLoading(nextIsLoading),\n errors: undefined,\n } as TData[typeof _typedKey])\n );\n\n const updatedState = currentState() as TData[K];\n this.notifyUpdateHooks(key, updatedState, previousState);\n }\n\n startKeyedLoading<K extends keyof TData>(\n key: K,\n resourceKey: KeyedResourceKey\n ): void {\n const currentState = this.signalsState.get(key.toString());\n if (!currentState) {\n return;\n }\n\n const _typedKey = key as keyof TEnum;\n const state = currentState();\n if (!isKeyedResourceData(state.data)) {\n this.startLoading(key);\n return;\n }\n\n const previousState = state as TData[K];\n const data = state.data;\n\n const nextIsLoading = {\n ...data.isLoading,\n [resourceKey]: true,\n } as typeof data.isLoading;\n\n const nextStatus: typeof data.status = {\n ...data.status,\n };\n delete nextStatus[resourceKey];\n\n const nextErrors: typeof data.errors = {\n ...data.errors,\n };\n delete nextErrors[resourceKey];\n\n const nextData = {\n ...data,\n isLoading: nextIsLoading,\n status: nextStatus,\n errors: nextErrors,\n };\n\n currentState.update(\n (previous) =>\n ({\n ...previous,\n data: nextData,\n status: undefined,\n isLoading: isAnyKeyLoading(nextIsLoading),\n errors: undefined,\n } as TData[typeof _typedKey])\n );\n\n const updatedState = currentState() as TData[K];\n this.notifyUpdateHooks(key, updatedState, previousState);\n }\n\n private notifyUpdateHooks<K extends keyof TData>(\n key: K,\n nextState: TData[K],\n previousState: TData[K]\n ): void {\n const hooks = updateHooksMap.get(this);\n const keyHooks = hooks?.get(key);\n if (!keyHooks) {\n return;\n }\n\n keyHooks.forEach((hook) =>\n hook(\n nextState as ResourceState<unknown>,\n previousState as ResourceState<unknown>\n )\n );\n }\n\n private initializeState(): void {\n Object.keys(this.storeEnum).forEach((key) => {\n const _typedKey = key as keyof TEnum;\n const initialState: ResourceState<unknown> = {\n data: undefined,\n isLoading: false,\n status: undefined,\n errors: undefined,\n };\n this.signalsState.set(\n _typedKey,\n signal<TData[typeof _typedKey]>(initialState as TData[typeof _typedKey])\n );\n });\n }\n}\n","import { signal, WritableSignal } from '@angular/core';\nimport type { ResourceState } from '@flurryx/core';\nimport type { IStore } from './types';\n\ntype UpdateCallback = (\n nextState: ResourceState<unknown>,\n previousState: ResourceState<unknown>\n) => void;\n\nfunction createDefaultState<T>(): ResourceState<T> {\n return {\n data: undefined,\n isLoading: false,\n status: undefined,\n errors: undefined,\n };\n}\n\n/**\n * Lazy store that creates signals on first access.\n * Used by the `Store.for<Config>().build()` API where keys are\n * known only at the type level (no runtime enum).\n */\nexport class LazyStore<\n TData extends Record<string, ResourceState<unknown>>,\n> implements IStore<TData>\n{\n private readonly signals = new Map<string, WritableSignal<ResourceState<unknown>>>();\n private readonly hooks = new Map<string, UpdateCallback[]>();\n\n private getOrCreate<K extends keyof TData & string>(\n key: K\n ): WritableSignal<TData[K]> {\n let sig = this.signals.get(key);\n if (!sig) {\n sig = signal<ResourceState<unknown>>(createDefaultState());\n this.signals.set(key, sig);\n }\n return sig as WritableSignal<TData[K]>;\n }\n\n get<K extends keyof TData & string>(key: K): WritableSignal<TData[K]> {\n return this.getOrCreate(key);\n }\n\n update<K extends keyof TData & string>(\n key: K,\n newState: Partial<TData[K]>\n ): void {\n const sig = this.getOrCreate(key);\n const previousState = sig();\n sig.update((state) => ({ ...state, ...newState }));\n const nextState = sig();\n this.notifyHooks(key, nextState, previousState);\n }\n\n clear<K extends keyof TData & string>(key: K): void {\n const sig = this.getOrCreate(key);\n const previousState = sig();\n sig.set(createDefaultState() as TData[K]);\n const nextState = sig();\n this.notifyHooks(key, nextState, previousState);\n }\n\n clearAll(): void {\n for (const key of this.signals.keys()) {\n this.clear(key as keyof TData & string);\n }\n }\n\n startLoading<K extends keyof TData & string>(key: K): void {\n const sig = this.getOrCreate(key);\n sig.update(\n (state) =>\n ({\n ...state,\n status: undefined,\n isLoading: true,\n errors: undefined,\n }) as TData[K]\n );\n }\n\n stopLoading<K extends keyof TData & string>(key: K): void {\n const sig = this.getOrCreate(key);\n sig.update(\n (state) =>\n ({\n ...state,\n isLoading: false,\n status: undefined,\n errors: undefined,\n }) as TData[K]\n );\n }\n\n onUpdate<K extends keyof TData & string>(\n key: K,\n callback: (state: TData[K], previousState: TData[K]) => void\n ): () => void {\n if (!this.hooks.has(key)) {\n this.hooks.set(key, []);\n }\n const typedCallback = callback as UpdateCallback;\n this.hooks.get(key)!.push(typedCallback);\n\n return () => {\n const keyHooks = this.hooks.get(key);\n if (!keyHooks) {\n return;\n }\n const index = keyHooks.indexOf(typedCallback);\n if (index > -1) {\n keyHooks.splice(index, 1);\n }\n };\n }\n\n private notifyHooks<K extends keyof TData & string>(\n key: K,\n nextState: TData[K],\n previousState: TData[K]\n ): void {\n const keyHooks = this.hooks.get(key);\n if (!keyHooks) {\n return;\n }\n keyHooks.forEach((hook) =>\n hook(\n nextState as ResourceState<unknown>,\n previousState as ResourceState<unknown>\n )\n );\n }\n}\n","import { InjectionToken, inject } from \"@angular/core\";\nimport { BaseStore } from \"./base-store\";\nimport { DynamicStore } from \"./dynamic-store\";\nimport { LazyStore } from \"./lazy-store\";\nimport { mirrorKey } from \"./mirror-key\";\nimport { resource } from \"./resource\";\nimport type { ResourceState } from \"@flurryx/core\";\nimport type {\n StoreConfig,\n ResourceDef,\n InferEnum,\n InferData,\n ConfigToData,\n IStore,\n} from \"./types\";\n\n// ---------------------------------------------------------------------------\n// Mirror definition — accumulated by builders, wired up in build() factory\n// ---------------------------------------------------------------------------\n\ninterface MirrorDef {\n readonly sourceToken: InjectionToken<\n IStore<Record<string, ResourceState<unknown>>>\n >;\n readonly sourceKey: string;\n readonly targetKey: string;\n}\n\nfunction wireMirrors<\n TStore extends IStore<Record<string, ResourceState<unknown>>>\n>(store: TStore, mirrors: readonly MirrorDef[]): TStore {\n for (const def of mirrors) {\n const sourceStore = inject(def.sourceToken);\n mirrorKey(sourceStore, def.sourceKey, store, def.targetKey);\n }\n return store;\n}\n\n// ---------------------------------------------------------------------------\n// Unconstrained builder (existing API)\n// ---------------------------------------------------------------------------\n\n/**\n * Intermediate builder step after .resource('key') — awaits .as<T>().\n */\ninterface AsStep<TAccum extends StoreConfig, TKey extends string> {\n as<T>(): StoreBuilder<TAccum & Record<TKey, ResourceDef<T>>>;\n}\n\n/**\n * Fluent builder for creating stores.\n * Accumulates resource definitions then produces an InjectionToken on .build().\n */\ninterface StoreBuilder<TAccum extends StoreConfig> {\n resource<TKey extends string>(key: TKey): AsStep<TAccum, TKey>;\n mirror<TSourceData extends Record<string, ResourceState<unknown>>>(\n source: InjectionToken<IStore<TSourceData>>,\n sourceKey: keyof TSourceData & string,\n targetKey?: keyof TAccum & string\n ): StoreBuilder<TAccum>;\n build(): InjectionToken<BaseStore<InferEnum<TAccum>, InferData<TAccum>>>;\n}\n\nfunction createBuilder<TAccum extends StoreConfig>(\n accum: TAccum,\n mirrors: readonly MirrorDef[] = []\n): StoreBuilder<TAccum> {\n return {\n resource<TKey extends string>(key: TKey): AsStep<TAccum, TKey> {\n return {\n as<T>(): StoreBuilder<TAccum & Record<TKey, ResourceDef<T>>> {\n const nextAccum = {\n ...accum,\n [key]: resource<T>(),\n } as TAccum & Record<TKey, ResourceDef<T>>;\n return createBuilder(nextAccum, mirrors);\n },\n };\n },\n mirror(source, sourceKey, targetKey?) {\n const def: MirrorDef = {\n sourceToken: source as InjectionToken<\n IStore<Record<string, ResourceState<unknown>>>\n >,\n sourceKey,\n targetKey: (targetKey ?? sourceKey) as string,\n };\n return createBuilder(accum, [...mirrors, def]);\n },\n build() {\n return new InjectionToken<\n BaseStore<InferEnum<TAccum>, InferData<TAccum>>\n >(\"FlurryxStore\", {\n providedIn: \"root\",\n factory: () =>\n wireMirrors(new DynamicStore(accum), mirrors) as BaseStore<\n InferEnum<TAccum>,\n InferData<TAccum>\n >,\n });\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// Constrained builder (.for(enum) API)\n// ---------------------------------------------------------------------------\n\n/** Keys from the enum that have NOT yet been defined. */\ntype Remaining<\n TEnum extends Record<string, string>,\n TAccum extends StoreConfig\n> = Exclude<keyof TEnum & string, keyof TAccum>;\n\n/** Intermediate .as<T>() step for the constrained builder. */\ninterface ConstrainedAsStep<\n TEnum extends Record<string, string>,\n TAccum extends StoreConfig,\n TKey extends string\n> {\n as<T>(): ConstrainedBuilder<TEnum, TAccum & Record<TKey, ResourceDef<T>>>;\n}\n\n/**\n * Constrained builder — only allows keys from the enum that haven't been\n * defined yet. `.build()` is only available when all keys are accounted for.\n */\ntype ConstrainedBuilder<\n TEnum extends Record<string, string>,\n TAccum extends StoreConfig\n> = [Remaining<TEnum, TAccum>] extends [never]\n ? {\n mirror<TSourceData extends Record<string, ResourceState<unknown>>>(\n source: InjectionToken<IStore<TSourceData>>,\n sourceKey: keyof TSourceData & string,\n targetKey?: keyof TAccum & string\n ): ConstrainedBuilder<TEnum, TAccum>;\n build(): InjectionToken<BaseStore<InferEnum<TAccum>, InferData<TAccum>>>;\n }\n : {\n resource<TKey extends Remaining<TEnum, TAccum>>(\n key: TKey\n ): ConstrainedAsStep<TEnum, TAccum, TKey>;\n };\n\nfunction createConstrainedBuilder<\n TEnum extends Record<string, string>,\n TAccum extends StoreConfig\n>(\n _enumObj: TEnum,\n accum: TAccum,\n mirrors: readonly MirrorDef[] = []\n): ConstrainedBuilder<TEnum, TAccum> {\n return {\n resource<TKey extends string>(\n key: TKey\n ): ConstrainedAsStep<TEnum, TAccum, TKey> {\n return {\n as<T>(): ConstrainedBuilder<\n TEnum,\n TAccum & Record<TKey, ResourceDef<T>>\n > {\n const nextAccum = {\n ...accum,\n [key]: resource<T>(),\n } as TAccum & Record<TKey, ResourceDef<T>>;\n return createConstrainedBuilder(_enumObj, nextAccum, mirrors);\n },\n };\n },\n mirror(\n source: InjectionToken<IStore<Record<string, ResourceState<unknown>>>>,\n sourceKey: string,\n targetKey?: string\n ) {\n const def: MirrorDef = {\n sourceToken: source,\n sourceKey,\n targetKey: targetKey ?? sourceKey,\n };\n return createConstrainedBuilder(_enumObj, accum, [...mirrors, def]);\n },\n build() {\n return new InjectionToken<\n BaseStore<InferEnum<TAccum>, InferData<TAccum>>\n >(\"FlurryxStore\", {\n providedIn: \"root\",\n factory: () =>\n wireMirrors(new DynamicStore(accum), mirrors) as BaseStore<\n InferEnum<TAccum>,\n InferData<TAccum>\n >,\n });\n },\n } as ConstrainedBuilder<TEnum, TAccum>;\n}\n\n// ---------------------------------------------------------------------------\n// Interface-based builder (Store.for<Config>() API)\n// ---------------------------------------------------------------------------\n\ninterface InterfaceBuilder<TConfig extends Record<string, unknown>> {\n mirror<TSourceData extends Record<string, ResourceState<unknown>>>(\n source: InjectionToken<IStore<TSourceData>>,\n sourceKey: keyof TSourceData & string,\n targetKey?: keyof TConfig & string\n ): InterfaceBuilder<TConfig>;\n build(): InjectionToken<IStore<ConfigToData<TConfig>>>;\n}\n\nfunction createInterfaceBuilder<TConfig extends Record<string, unknown>>(\n mirrors: readonly MirrorDef[] = []\n): InterfaceBuilder<TConfig> {\n return {\n mirror(source, sourceKey, targetKey?) {\n const def: MirrorDef = {\n sourceToken: source as InjectionToken<\n IStore<Record<string, ResourceState<unknown>>>\n >,\n sourceKey,\n targetKey: (targetKey ?? sourceKey) as string,\n };\n return createInterfaceBuilder<TConfig>([...mirrors, def]);\n },\n build() {\n return new InjectionToken(\"FlurryxStore\", {\n providedIn: \"root\",\n factory: () =>\n wireMirrors(\n new LazyStore() as IStore<Record<string, ResourceState<unknown>>>,\n mirrors\n ) as unknown as IStore<ConfigToData<TConfig>>,\n });\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// Public entry point\n// ---------------------------------------------------------------------------\n\ninterface StoreEntry {\n /**\n * Define a named resource slot.\n * Chain .as<T>() to assign its type, then continue with more .resource() calls\n * or call .build() when done.\n */\n resource<TKey extends string>(\n key: TKey\n ): {\n as<T>(): StoreBuilder<Record<TKey, ResourceDef<T>>>;\n };\n\n /**\n * Interface-based builder: pass a config interface as a generic.\n * No runtime argument needed — keys and types are inferred from the interface.\n *\n * @example\n * interface ChatStoreConfig {\n * SESSIONS: ChatSession[];\n * MESSAGES: ChatMessage[];\n * }\n * const ChatStore = Store.for<ChatStoreConfig>().build();\n */\n for<TConfig extends Record<string, unknown>>(): InterfaceBuilder<TConfig>;\n\n /**\n * Bind the builder to an enum object for compile-time key validation.\n *\n * @example\n * const Enum = { A: 'A', B: 'B' } as const;\n * const MyStore = Store.for(Enum)\n * .resource('A').as<string>()\n * .resource('B').as<number>()\n * .build();\n */\n for<TEnum extends Record<string, string>>(\n enumObj: TEnum\n ): ConstrainedBuilder<TEnum, Record<string, never>>;\n}\n\n/**\n * Fluent store builder entry point.\n *\n * @example\n * // Unconstrained\n * export const CustomersStore = Store\n * .resource('customers').as<Customer[]>()\n * .resource('customerDetails').as<Customer>()\n * .build();\n *\n * @example\n * // Constrained with enum\n * const Enum = { SESSIONS: 'SESSIONS', MESSAGES: 'MESSAGES' } as const;\n * export const ChatStore = Store.for(Enum)\n * .resource('SESSIONS').as<Session[]>()\n * .resource('MESSAGES').as<Message[]>()\n * .build();\n */\nexport const Store: StoreEntry = {\n ...createBuilder({} as StoreConfig),\n for(enumObj?: Record<string, string>) {\n if (arguments.length === 0) {\n return createInterfaceBuilder();\n }\n return createConstrainedBuilder(enumObj!, {} as Record<string, never>);\n },\n};\n","import { BaseStore } from './base-store';\nimport type { StoreConfig, InferEnum, InferData } from './types';\n\n/**\n * Internal concrete subclass of BaseStore.\n * Auto-generates an identity enum from config keys.\n * NOT publicly exported — consumers interact via BaseStore interface.\n */\nexport class DynamicStore<\n TConfig extends StoreConfig,\n> extends BaseStore<InferEnum<TConfig>, InferData<TConfig>> {\n constructor(config: TConfig) {\n const identityEnum = Object.keys(config).reduce(\n (acc, key) => ({ ...acc, [key]: key }),\n {} as InferEnum<TConfig>\n );\n super(identityEnum);\n }\n}\n","import type { ResourceState } from \"@flurryx/core\";\nimport type { IStore } from \"./types\";\n\nexport interface MirrorOptions {\n destroyRef?: { onDestroy: (fn: () => void) => void };\n}\n\n/**\n * Mirrors a resource key from a source store to a target store.\n * When the source key updates, the target key is updated with the same state.\n *\n * @param source - The store to mirror from\n * @param sourceKey - The key to watch on the source store\n * @param target - The store to mirror to\n * @param targetKeyOrOptions - Either the target key name or options (defaults source key)\n * @param options - Mirror options when a target key is provided\n * @returns Cleanup function to stop mirroring\n */\nexport function mirrorKey<\n TSource extends Record<string, ResourceState<unknown>>,\n TTarget extends Record<string, ResourceState<unknown>>\n>(\n source: IStore<TSource>,\n sourceKey: keyof TSource & string,\n target: IStore<TTarget>,\n targetKeyOrOptions?: (keyof TTarget & string) | MirrorOptions,\n options?: MirrorOptions\n): () => void {\n const resolvedTargetKey = (\n typeof targetKeyOrOptions === \"string\" ? targetKeyOrOptions : sourceKey\n ) as keyof TTarget & string;\n\n const resolvedOptions =\n typeof targetKeyOrOptions === \"object\" ? targetKeyOrOptions : options;\n\n const cleanup = source.onUpdate(sourceKey, (state) => {\n target.update(\n resolvedTargetKey,\n state as unknown as Partial<TTarget[keyof TTarget & string]>\n );\n });\n\n if (resolvedOptions?.destroyRef) {\n resolvedOptions.destroyRef.onDestroy(cleanup);\n }\n\n return cleanup;\n}\n","import type { ResourceDef } from './types';\n\n/**\n * Creates a phantom-typed resource definition marker.\n * Zero runtime cost — returns an empty object that only carries type info.\n *\n * @example\n * const config = {\n * customers: resource<Customer[]>(),\n * customerDetails: resource<Customer>(),\n * };\n */\nexport function resource<T>(): ResourceDef<T> {\n return {} as ResourceDef<T>;\n}\n","import type {\n ResourceState,\n KeyedResourceKey,\n KeyedResourceData,\n} from '@flurryx/core';\nimport { createKeyedResourceData, isAnyKeyLoading } from '@flurryx/core';\nimport type { IStore } from './types';\n\nexport interface CollectKeyedOptions<TEntity> {\n extractId: (data: TEntity | undefined) => KeyedResourceKey | undefined;\n destroyRef?: { onDestroy: (fn: () => void) => void };\n}\n\n/**\n * Accumulates single-entity resource fetches into a keyed cache on a target store.\n *\n * On each source update:\n * - If status is 'Success' and extractId returns a valid key, merges the entity\n * into the target's keyed resource data.\n * - If the source data is cleared and a previous entity existed, removes it from\n * the target's keyed data.\n *\n * @param source - The store containing the single-entity resource\n * @param sourceKey - The key to watch on the source store\n * @param target - The store to accumulate entities into\n * @param targetKeyOrOptions - Either the target key name or options (defaults source key)\n * @param options - Collect options when a target key is provided\n * @returns Cleanup function to stop collecting\n */\nexport function collectKeyed<\n TSource extends Record<string, ResourceState<unknown>>,\n TTarget extends Record<string, ResourceState<unknown>>,\n TEntity = unknown,\n>(\n source: IStore<TSource>,\n sourceKey: keyof TSource & string,\n target: IStore<TTarget>,\n targetKeyOrOptions?: (keyof TTarget & string) | CollectKeyedOptions<TEntity>,\n options?: CollectKeyedOptions<TEntity>,\n): () => void {\n const resolvedTargetKey = (\n typeof targetKeyOrOptions === 'string'\n ? targetKeyOrOptions\n : sourceKey\n ) as keyof TTarget & string;\n\n const resolvedOptions = (\n typeof targetKeyOrOptions === 'object' ? targetKeyOrOptions : options\n ) as CollectKeyedOptions<TEntity>;\n\n // Initialize target with empty keyed resource data\n target.update(resolvedTargetKey, {\n data: createKeyedResourceData(),\n } as Partial<TTarget[keyof TTarget & string]>);\n\n let previousId: KeyedResourceKey | undefined;\n\n const cleanup = source.onUpdate(sourceKey, (state) => {\n const resourceState = state as ResourceState<TEntity>;\n const currentId = resolvedOptions.extractId(resourceState.data);\n const currentTarget = target.get(resolvedTargetKey)();\n const currentKeyed = (currentTarget as ResourceState<unknown>).data as\n KeyedResourceData<KeyedResourceKey, TEntity> | undefined;\n\n if (!currentKeyed) {\n return;\n }\n\n if (resourceState.status === 'Success' && currentId !== undefined) {\n const newEntities = { ...currentKeyed.entities, [currentId]: resourceState.data };\n const newIsLoading = { ...currentKeyed.isLoading, [currentId]: false };\n const newStatus = { ...currentKeyed.status, [currentId]: resourceState.status };\n const newErrors = { ...currentKeyed.errors };\n delete newErrors[currentId];\n\n const updatedKeyed: KeyedResourceData<KeyedResourceKey, TEntity> = {\n entities: newEntities,\n isLoading: newIsLoading,\n status: newStatus,\n errors: newErrors,\n };\n\n target.update(resolvedTargetKey, {\n data: updatedKeyed,\n isLoading: isAnyKeyLoading(newIsLoading),\n status: 'Success',\n } as Partial<TTarget[keyof TTarget & string]>);\n\n previousId = currentId;\n } else if (resourceState.status === 'Error' && currentId !== undefined) {\n const newIsLoading = { ...currentKeyed.isLoading, [currentId]: false };\n const newStatus = { ...currentKeyed.status, [currentId]: resourceState.status };\n const newErrors = { ...currentKeyed.errors, [currentId]: resourceState.errors };\n\n const updatedKeyed: KeyedResourceData<KeyedResourceKey, TEntity> = {\n entities: { ...currentKeyed.entities },\n isLoading: newIsLoading,\n status: newStatus,\n errors: newErrors,\n };\n\n target.update(resolvedTargetKey, {\n data: updatedKeyed,\n isLoading: isAnyKeyLoading(newIsLoading),\n } as Partial<TTarget[keyof TTarget & string]>);\n\n previousId = currentId;\n } else if (resourceState.data === undefined && previousId !== undefined) {\n // Source cleared — remove previous entity from cache\n const { [previousId]: _removed, ...remainingEntities } = currentKeyed.entities;\n const { [previousId]: _removedLoading, ...remainingLoading } = currentKeyed.isLoading;\n const { [previousId]: _removedStatus, ...remainingStatus } = currentKeyed.status;\n const { [previousId]: _removedErrors, ...remainingErrors } = currentKeyed.errors;\n\n const updatedKeyed: KeyedResourceData<KeyedResourceKey, TEntity> = {\n entities: remainingEntities,\n isLoading: remainingLoading,\n status: remainingStatus,\n errors: remainingErrors,\n };\n\n target.update(resolvedTargetKey, {\n data: updatedKeyed,\n isLoading: isAnyKeyLoading(remainingLoading),\n } as Partial<TTarget[keyof TTarget & string]>);\n\n previousId = undefined;\n } else if (resourceState.isLoading && currentId !== undefined) {\n const newIsLoading = { ...currentKeyed.isLoading, [currentId]: true };\n\n const updatedKeyed: KeyedResourceData<KeyedResourceKey, TEntity> = {\n entities: { ...currentKeyed.entities },\n isLoading: newIsLoading,\n status: { ...currentKeyed.status },\n errors: { ...currentKeyed.errors },\n };\n\n target.update(resolvedTargetKey, {\n data: updatedKeyed,\n isLoading: true,\n } as Partial<TTarget[keyof TTarget & string]>);\n\n previousId = currentId;\n }\n });\n\n if (resolvedOptions?.destroyRef) {\n resolvedOptions.destroyRef.onDestroy(cleanup);\n }\n\n return cleanup;\n}\n"],"mappings":";AAAA,SAAS,cAA8B;AACvC;AAAA,EAEE;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AAaP,IAAM,iBAAiB,oBAAI,QAAgC;AAEpD,IAAe,YAAf,MAIP;AAAA,EAMY,YAA+B,WAAkB;AAAlB;AACvC,SAAK,gBAAgB;AACrB,mBAAe,IAAI,MAAM,oBAAI,IAAI,CAAC;AAAA,EACpC;AAAA,EARiB,eAAe,oBAAI,IAGlC;AAAA,EAOF,IAA2B,KAAkC;AAC3D,WAAO,KAAK,aAAa,IAAI,IAAI,SAAS,CAAC;AAAA,EAC7C;AAAA,EAEA,SACE,KACA,UACY;AACZ,UAAM,QAAQ,eAAe,IAAI,IAAI;AACrC,QAAI,CAAC,MAAM,IAAI,GAAG,GAAG;AACnB,YAAM,IAAI,KAAK,CAAC,CAAC;AAAA,IACnB;AACA,UACG,IAAI,GAAG,EACP;AAAA,MACC;AAAA,IAIF;AAEF,WAAO,MAAM;AACX,YAAM,WAAW,MAAM,IAAI,GAAG;AAC9B,UAAI,CAAC,UAAU;AACb;AAAA,MACF;AACA,YAAM,QAAQ,SAAS;AAAA,QACrB;AAAA,MAIF;AACA,UAAI,QAAQ,IAAI;AACd,iBAAS,OAAO,OAAO,CAAC;AAAA,MAC1B;AAAA,IACF;AAAA,EACF;AAAA,EAEA,OAA8B,KAAQ,UAAmC;AACvE,UAAM,eAAe,KAAK,aAAa,IAAI,IAAI,SAAS,CAAC;AACzD,QAAI,CAAC,cAAc;AACjB;AAAA,IACF;AAEA,UAAM,gBAAgB,aAAa;AACnC,iBAAa,OAAO,CAAC,WAAW;AAAA,MAC9B,GAAG;AAAA,MACH,GAAG;AAAA,IACL,EAAE;AAEF,UAAM,eAAe,aAAa;AAClC,SAAK,kBAAkB,KAAK,cAAc,aAAa;AAAA,EACzD;AAAA,EAEA,WAAiB;AACf,WAAO,KAAK,KAAK,SAAS,EAAE,QAAQ,CAAC,QAAQ;AAC3C,WAAK,MAAM,GAAkB;AAAA,IAC/B,CAAC;AAAA,EACH;AAAA,EAEA,MAA6B,KAAc;AACzC,UAAM,eAAe,KAAK,aAAa,IAAI,IAAI,SAAS,CAAC;AACzD,QAAI,CAAC,cAAc;AACjB;AAAA,IACF;AAEA,UAAM,gBAAgB,aAAa;AACnC,UAAM,YAAY;AAClB,iBAAa,IAAI;AAAA,MACf,MAAM;AAAA,MACN,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV,CAA4B;AAE5B,UAAM,YAAY,aAAa;AAC/B,SAAK,kBAAkB,KAAK,WAAW,aAAa;AAAA,EACtD;AAAA,EAEA,aAAoC,KAAc;AAChD,UAAM,eAAe,KAAK,aAAa,IAAI,IAAI,SAAS,CAAC;AACzD,QAAI,CAAC,cAAc;AACjB;AAAA,IACF;AAEA,UAAM,YAAY;AAClB,iBAAa;AAAA,MACX,CAAC,WACE;AAAA,QACC,GAAG;AAAA,QACH,QAAQ;AAAA,QACR,WAAW;AAAA,QACX,QAAQ;AAAA,MACV;AAAA,IACJ;AAAA,EACF;AAAA,EAEA,YAAmC,KAAc;AAC/C,UAAM,eAAe,KAAK,aAAa,IAAI,IAAI,SAAS,CAAC;AACzD,QAAI,CAAC,cAAc;AACjB;AAAA,IACF;AAEA,UAAM,YAAY;AAClB,iBAAa;AAAA,MACX,CAAC,WACE;AAAA,QACC,GAAG;AAAA,QACH,WAAW;AAAA,QACX,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV;AAAA,IACJ;AAAA,EACF;AAAA,EAEA,eACE,KACA,aACA,QACM;AACN,UAAM,eAAe,KAAK,aAAa,IAAI,IAAI,SAAS,CAAC;AACzD,QAAI,CAAC,cAAc;AACjB;AAAA,IACF;AAEA,UAAM,QAAQ,aAAa;AAC3B,UAAM,OAAO,oBAAoB,MAAM,IAAI,IACvC,MAAM,OACN,wBAAwB;AAE5B,UAAM,aAAa,EAAE,GAAG,KAAK,OAAO;AACpC,WAAO,WAAW,WAAW;AAE7B,UAAM,WAAW;AAAA,MACf,GAAG;AAAA,MACH,UAAU;AAAA,QACR,GAAG,KAAK;AAAA,QACR,CAAC,WAAW,GAAG;AAAA,MACjB;AAAA,MACA,WAAW;AAAA,QACT,GAAG,KAAK;AAAA,QACR,CAAC,WAAW,GAAG;AAAA,MACjB;AAAA,MACA,QAAQ;AAAA,QACN,GAAG,KAAK;AAAA,QACR,CAAC,WAAW,GAAG;AAAA,MACjB;AAAA,MACA,QAAQ;AAAA,IACV;AAEA,SAAK,OAAO,KAAK;AAAA,MACf,MAAM;AAAA,MACN,WAAW,gBAAgB,SAAS,SAAS;AAAA,MAC7C,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV,CAAsB;AAAA,EACxB;AAAA,EAEA,cACE,KACA,aACM;AACN,UAAM,eAAe,KAAK,aAAa,IAAI,IAAI,SAAS,CAAC;AACzD,QAAI,CAAC,cAAc;AACjB;AAAA,IACF;AAEA,UAAM,gBAAgB,aAAa;AACnC,UAAM,QAAQ;AACd,QAAI,CAAC,oBAAoB,MAAM,IAAI,GAAG;AACpC;AAAA,IACF;AAEA,UAAM,OAAO,MAAM;AAEnB,UAAM,eAAe,EAAE,GAAG,KAAK,SAAS;AACxC,WAAO,aAAa,WAAW;AAE/B,UAAM,gBAAgB,EAAE,GAAG,KAAK,UAAU;AAC1C,WAAO,cAAc,WAAW;AAEhC,UAAM,aAAa,EAAE,GAAG,KAAK,OAAO;AACpC,WAAO,WAAW,WAAW;AAE7B,UAAM,aAAa,EAAE,GAAG,KAAK,OAAO;AACpC,WAAO,WAAW,WAAW;AAE7B,UAAM,WAAW;AAAA,MACf,GAAG;AAAA,MACH,UAAU;AAAA,MACV,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV;AAEA,UAAM,YAAY;AAClB,iBAAa;AAAA,MACX,CAAC,UACE;AAAA,QACC,GAAG;AAAA,QACH,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,WAAW,gBAAgB,aAAa;AAAA,QACxC,QAAQ;AAAA,MACV;AAAA,IACJ;AAEA,UAAM,eAAe,aAAa;AAClC,SAAK,kBAAkB,KAAK,cAAc,aAAa;AAAA,EACzD;AAAA,EAEA,kBACE,KACA,aACM;AACN,UAAM,eAAe,KAAK,aAAa,IAAI,IAAI,SAAS,CAAC;AACzD,QAAI,CAAC,cAAc;AACjB;AAAA,IACF;AAEA,UAAM,YAAY;AAClB,UAAM,QAAQ,aAAa;AAC3B,QAAI,CAAC,oBAAoB,MAAM,IAAI,GAAG;AACpC,WAAK,aAAa,GAAG;AACrB;AAAA,IACF;AAEA,UAAM,gBAAgB;AACtB,UAAM,OAAO,MAAM;AAEnB,UAAM,gBAAgB;AAAA,MACpB,GAAG,KAAK;AAAA,MACR,CAAC,WAAW,GAAG;AAAA,IACjB;AAEA,UAAM,aAAiC;AAAA,MACrC,GAAG,KAAK;AAAA,IACV;AACA,WAAO,WAAW,WAAW;AAE7B,UAAM,aAAiC;AAAA,MACrC,GAAG,KAAK;AAAA,IACV;AACA,WAAO,WAAW,WAAW;AAE7B,UAAM,WAAW;AAAA,MACf,GAAG;AAAA,MACH,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV;AAEA,iBAAa;AAAA,MACX,CAAC,cACE;AAAA,QACC,GAAG;AAAA,QACH,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,WAAW,gBAAgB,aAAa;AAAA,QACxC,QAAQ;AAAA,MACV;AAAA,IACJ;AAEA,UAAM,eAAe,aAAa;AAClC,SAAK,kBAAkB,KAAK,cAAc,aAAa;AAAA,EACzD;AAAA,EAEQ,kBACN,KACA,WACA,eACM;AACN,UAAM,QAAQ,eAAe,IAAI,IAAI;AACrC,UAAM,WAAW,OAAO,IAAI,GAAG;AAC/B,QAAI,CAAC,UAAU;AACb;AAAA,IACF;AAEA,aAAS;AAAA,MAAQ,CAAC,SAChB;AAAA,QACE;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,kBAAwB;AAC9B,WAAO,KAAK,KAAK,SAAS,EAAE,QAAQ,CAAC,QAAQ;AAC3C,YAAM,YAAY;AAClB,YAAM,eAAuC;AAAA,QAC3C,MAAM;AAAA,QACN,WAAW;AAAA,QACX,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV;AACA,WAAK,aAAa;AAAA,QAChB;AAAA,QACA,OAAgC,YAAuC;AAAA,MACzE;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;AClVA,SAAS,UAAAA,eAA8B;AASvC,SAAS,qBAA0C;AACjD,SAAO;AAAA,IACL,MAAM;AAAA,IACN,WAAW;AAAA,IACX,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV;AACF;AAOO,IAAM,YAAN,MAGP;AAAA,EACmB,UAAU,oBAAI,IAAoD;AAAA,EAClE,QAAQ,oBAAI,IAA8B;AAAA,EAEnD,YACN,KAC0B;AAC1B,QAAI,MAAM,KAAK,QAAQ,IAAI,GAAG;AAC9B,QAAI,CAAC,KAAK;AACR,YAAMA,QAA+B,mBAAmB,CAAC;AACzD,WAAK,QAAQ,IAAI,KAAK,GAAG;AAAA,IAC3B;AACA,WAAO;AAAA,EACT;AAAA,EAEA,IAAoC,KAAkC;AACpE,WAAO,KAAK,YAAY,GAAG;AAAA,EAC7B;AAAA,EAEA,OACE,KACA,UACM;AACN,UAAM,MAAM,KAAK,YAAY,GAAG;AAChC,UAAM,gBAAgB,IAAI;AAC1B,QAAI,OAAO,CAAC,WAAW,EAAE,GAAG,OAAO,GAAG,SAAS,EAAE;AACjD,UAAM,YAAY,IAAI;AACtB,SAAK,YAAY,KAAK,WAAW,aAAa;AAAA,EAChD;AAAA,EAEA,MAAsC,KAAc;AAClD,UAAM,MAAM,KAAK,YAAY,GAAG;AAChC,UAAM,gBAAgB,IAAI;AAC1B,QAAI,IAAI,mBAAmB,CAAa;AACxC,UAAM,YAAY,IAAI;AACtB,SAAK,YAAY,KAAK,WAAW,aAAa;AAAA,EAChD;AAAA,EAEA,WAAiB;AACf,eAAW,OAAO,KAAK,QAAQ,KAAK,GAAG;AACrC,WAAK,MAAM,GAA2B;AAAA,IACxC;AAAA,EACF;AAAA,EAEA,aAA6C,KAAc;AACzD,UAAM,MAAM,KAAK,YAAY,GAAG;AAChC,QAAI;AAAA,MACF,CAAC,WACE;AAAA,QACC,GAAG;AAAA,QACH,QAAQ;AAAA,QACR,WAAW;AAAA,QACX,QAAQ;AAAA,MACV;AAAA,IACJ;AAAA,EACF;AAAA,EAEA,YAA4C,KAAc;AACxD,UAAM,MAAM,KAAK,YAAY,GAAG;AAChC,QAAI;AAAA,MACF,CAAC,WACE;AAAA,QACC,GAAG;AAAA,QACH,WAAW;AAAA,QACX,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV;AAAA,IACJ;AAAA,EACF;AAAA,EAEA,SACE,KACA,UACY;AACZ,QAAI,CAAC,KAAK,MAAM,IAAI,GAAG,GAAG;AACxB,WAAK,MAAM,IAAI,KAAK,CAAC,CAAC;AAAA,IACxB;AACA,UAAM,gBAAgB;AACtB,SAAK,MAAM,IAAI,GAAG,EAAG,KAAK,aAAa;AAEvC,WAAO,MAAM;AACX,YAAM,WAAW,KAAK,MAAM,IAAI,GAAG;AACnC,UAAI,CAAC,UAAU;AACb;AAAA,MACF;AACA,YAAM,QAAQ,SAAS,QAAQ,aAAa;AAC5C,UAAI,QAAQ,IAAI;AACd,iBAAS,OAAO,OAAO,CAAC;AAAA,MAC1B;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,YACN,KACA,WACA,eACM;AACN,UAAM,WAAW,KAAK,MAAM,IAAI,GAAG;AACnC,QAAI,CAAC,UAAU;AACb;AAAA,IACF;AACA,aAAS;AAAA,MAAQ,CAAC,SAChB;AAAA,QACE;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;ACtIA,SAAS,gBAAgB,cAAc;;;ACQhC,IAAM,eAAN,cAEG,UAAkD;AAAA,EAC1D,YAAY,QAAiB;AAC3B,UAAM,eAAe,OAAO,KAAK,MAAM,EAAE;AAAA,MACvC,CAAC,KAAK,SAAS,EAAE,GAAG,KAAK,CAAC,GAAG,GAAG,IAAI;AAAA,MACpC,CAAC;AAAA,IACH;AACA,UAAM,YAAY;AAAA,EACpB;AACF;;;ACAO,SAAS,UAId,QACA,WACA,QACA,oBACA,SACY;AACZ,QAAM,oBACJ,OAAO,uBAAuB,WAAW,qBAAqB;AAGhE,QAAM,kBACJ,OAAO,uBAAuB,WAAW,qBAAqB;AAEhE,QAAM,UAAU,OAAO,SAAS,WAAW,CAAC,UAAU;AACpD,WAAO;AAAA,MACL;AAAA,MACA;AAAA,IACF;AAAA,EACF,CAAC;AAED,MAAI,iBAAiB,YAAY;AAC/B,oBAAgB,WAAW,UAAU,OAAO;AAAA,EAC9C;AAEA,SAAO;AACT;;;ACnCO,SAAS,WAA8B;AAC5C,SAAO,CAAC;AACV;;;AHcA,SAAS,YAEP,OAAe,SAAuC;AACtD,aAAW,OAAO,SAAS;AACzB,UAAM,cAAc,OAAO,IAAI,WAAW;AAC1C,cAAU,aAAa,IAAI,WAAW,OAAO,IAAI,SAAS;AAAA,EAC5D;AACA,SAAO;AACT;AA2BA,SAAS,cACP,OACA,UAAgC,CAAC,GACX;AACtB,SAAO;AAAA,IACL,SAA8B,KAAiC;AAC7D,aAAO;AAAA,QACL,KAA6D;AAC3D,gBAAM,YAAY;AAAA,YAChB,GAAG;AAAA,YACH,CAAC,GAAG,GAAG,SAAY;AAAA,UACrB;AACA,iBAAO,cAAc,WAAW,OAAO;AAAA,QACzC;AAAA,MACF;AAAA,IACF;AAAA,IACA,OAAO,QAAQ,WAAW,WAAY;AACpC,YAAM,MAAiB;AAAA,QACrB,aAAa;AAAA,QAGb;AAAA,QACA,WAAY,aAAa;AAAA,MAC3B;AACA,aAAO,cAAc,OAAO,CAAC,GAAG,SAAS,GAAG,CAAC;AAAA,IAC/C;AAAA,IACA,QAAQ;AACN,aAAO,IAAI,eAET,gBAAgB;AAAA,QAChB,YAAY;AAAA,QACZ,SAAS,MACP,YAAY,IAAI,aAAa,KAAK,GAAG,OAAO;AAAA,MAIhD,CAAC;AAAA,IACH;AAAA,EACF;AACF;AA2CA,SAAS,yBAIP,UACA,OACA,UAAgC,CAAC,GACE;AACnC,SAAO;AAAA,IACL,SACE,KACwC;AACxC,aAAO;AAAA,QACL,KAGE;AACA,gBAAM,YAAY;AAAA,YAChB,GAAG;AAAA,YACH,CAAC,GAAG,GAAG,SAAY;AAAA,UACrB;AACA,iBAAO,yBAAyB,UAAU,WAAW,OAAO;AAAA,QAC9D;AAAA,MACF;AAAA,IACF;AAAA,IACA,OACE,QACA,WACA,WACA;AACA,YAAM,MAAiB;AAAA,QACrB,aAAa;AAAA,QACb;AAAA,QACA,WAAW,aAAa;AAAA,MAC1B;AACA,aAAO,yBAAyB,UAAU,OAAO,CAAC,GAAG,SAAS,GAAG,CAAC;AAAA,IACpE;AAAA,IACA,QAAQ;AACN,aAAO,IAAI,eAET,gBAAgB;AAAA,QAChB,YAAY;AAAA,QACZ,SAAS,MACP,YAAY,IAAI,aAAa,KAAK,GAAG,OAAO;AAAA,MAIhD,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAeA,SAAS,uBACP,UAAgC,CAAC,GACN;AAC3B,SAAO;AAAA,IACL,OAAO,QAAQ,WAAW,WAAY;AACpC,YAAM,MAAiB;AAAA,QACrB,aAAa;AAAA,QAGb;AAAA,QACA,WAAY,aAAa;AAAA,MAC3B;AACA,aAAO,uBAAgC,CAAC,GAAG,SAAS,GAAG,CAAC;AAAA,IAC1D;AAAA,IACA,QAAQ;AACN,aAAO,IAAI,eAAe,gBAAgB;AAAA,QACxC,YAAY;AAAA,QACZ,SAAS,MACP;AAAA,UACE,IAAI,UAAU;AAAA,UACd;AAAA,QACF;AAAA,MACJ,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAgEO,IAAM,QAAoB;AAAA,EAC/B,GAAG,cAAc,CAAC,CAAgB;AAAA,EAClC,IAAI,SAAkC;AACpC,QAAI,UAAU,WAAW,GAAG;AAC1B,aAAO,uBAAuB;AAAA,IAChC;AACA,WAAO,yBAAyB,SAAU,CAAC,CAA0B;AAAA,EACvE;AACF;;;AI9SA,SAAS,2BAAAC,0BAAyB,mBAAAC,wBAAuB;AAwBlD,SAAS,aAKd,QACA,WACA,QACA,oBACA,SACY;AACZ,QAAM,oBACJ,OAAO,uBAAuB,WAC1B,qBACA;AAGN,QAAM,kBACJ,OAAO,uBAAuB,WAAW,qBAAqB;AAIhE,SAAO,OAAO,mBAAmB;AAAA,IAC/B,MAAMD,yBAAwB;AAAA,EAChC,CAA6C;AAE7C,MAAI;AAEJ,QAAM,UAAU,OAAO,SAAS,WAAW,CAAC,UAAU;AACpD,UAAM,gBAAgB;AACtB,UAAM,YAAY,gBAAgB,UAAU,cAAc,IAAI;AAC9D,UAAM,gBAAgB,OAAO,IAAI,iBAAiB,EAAE;AACpD,UAAM,eAAgB,cAAyC;AAG/D,QAAI,CAAC,cAAc;AACjB;AAAA,IACF;AAEA,QAAI,cAAc,WAAW,aAAa,cAAc,QAAW;AACjE,YAAM,cAAc,EAAE,GAAG,aAAa,UAAU,CAAC,SAAS,GAAG,cAAc,KAAK;AAChF,YAAM,eAAe,EAAE,GAAG,aAAa,WAAW,CAAC,SAAS,GAAG,MAAM;AACrE,YAAM,YAAY,EAAE,GAAG,aAAa,QAAQ,CAAC,SAAS,GAAG,cAAc,OAAO;AAC9E,YAAM,YAAY,EAAE,GAAG,aAAa,OAAO;AAC3C,aAAO,UAAU,SAAS;AAE1B,YAAM,eAA6D;AAAA,QACjE,UAAU;AAAA,QACV,WAAW;AAAA,QACX,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV;AAEA,aAAO,OAAO,mBAAmB;AAAA,QAC/B,MAAM;AAAA,QACN,WAAWC,iBAAgB,YAAY;AAAA,QACvC,QAAQ;AAAA,MACV,CAA6C;AAE7C,mBAAa;AAAA,IACf,WAAW,cAAc,WAAW,WAAW,cAAc,QAAW;AACtE,YAAM,eAAe,EAAE,GAAG,aAAa,WAAW,CAAC,SAAS,GAAG,MAAM;AACrE,YAAM,YAAY,EAAE,GAAG,aAAa,QAAQ,CAAC,SAAS,GAAG,cAAc,OAAO;AAC9E,YAAM,YAAY,EAAE,GAAG,aAAa,QAAQ,CAAC,SAAS,GAAG,cAAc,OAAO;AAE9E,YAAM,eAA6D;AAAA,QACjE,UAAU,EAAE,GAAG,aAAa,SAAS;AAAA,QACrC,WAAW;AAAA,QACX,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV;AAEA,aAAO,OAAO,mBAAmB;AAAA,QAC/B,MAAM;AAAA,QACN,WAAWA,iBAAgB,YAAY;AAAA,MACzC,CAA6C;AAE7C,mBAAa;AAAA,IACf,WAAW,cAAc,SAAS,UAAa,eAAe,QAAW;AAEvE,YAAM,EAAE,CAAC,UAAU,GAAG,UAAU,GAAG,kBAAkB,IAAI,aAAa;AACtE,YAAM,EAAE,CAAC,UAAU,GAAG,iBAAiB,GAAG,iBAAiB,IAAI,aAAa;AAC5E,YAAM,EAAE,CAAC,UAAU,GAAG,gBAAgB,GAAG,gBAAgB,IAAI,aAAa;AAC1E,YAAM,EAAE,CAAC,UAAU,GAAG,gBAAgB,GAAG,gBAAgB,IAAI,aAAa;AAE1E,YAAM,eAA6D;AAAA,QACjE,UAAU;AAAA,QACV,WAAW;AAAA,QACX,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV;AAEA,aAAO,OAAO,mBAAmB;AAAA,QAC/B,MAAM;AAAA,QACN,WAAWA,iBAAgB,gBAAgB;AAAA,MAC7C,CAA6C;AAE7C,mBAAa;AAAA,IACf,WAAW,cAAc,aAAa,cAAc,QAAW;AAC7D,YAAM,eAAe,EAAE,GAAG,aAAa,WAAW,CAAC,SAAS,GAAG,KAAK;AAEpE,YAAM,eAA6D;AAAA,QACjE,UAAU,EAAE,GAAG,aAAa,SAAS;AAAA,QACrC,WAAW;AAAA,QACX,QAAQ,EAAE,GAAG,aAAa,OAAO;AAAA,QACjC,QAAQ,EAAE,GAAG,aAAa,OAAO;AAAA,MACnC;AAEA,aAAO,OAAO,mBAAmB;AAAA,QAC/B,MAAM;AAAA,QACN,WAAW;AAAA,MACb,CAA6C;AAE7C,mBAAa;AAAA,IACf;AAAA,EACF,CAAC;AAED,MAAI,iBAAiB,YAAY;AAC/B,oBAAgB,WAAW,UAAU,OAAO;AAAA,EAC9C;AAEA,SAAO;AACT;","names":["signal","createKeyedResourceData","isAnyKeyLoading"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flurryx/store",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.3",
|
|
4
4
|
"description": "Signal-first reactive store for Angular",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
},
|
|
29
29
|
"sideEffects": false,
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@flurryx/core": "0.7.
|
|
31
|
+
"@flurryx/core": "0.7.3"
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|
|
34
34
|
"@angular/core": ">=17.0.0"
|