@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 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 createBuilder(accum) {
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) {
@@ -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 createBuilder(accum) {
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":"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","names":["signal","createKeyedResourceData","isAnyKeyLoading"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flurryx/store",
3
- "version": "0.7.1",
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.1"
31
+ "@flurryx/core": "0.7.3"
32
32
  },
33
33
  "peerDependencies": {
34
34
  "@angular/core": ">=17.0.0"