@flurryx/store 0.6.0 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -311,7 +311,33 @@ function createBuilder(accum) {
311
311
  }
312
312
  };
313
313
  }
314
- var Store = createBuilder({});
314
+ function createConstrainedBuilder(_enumObj, accum) {
315
+ return {
316
+ resource(key) {
317
+ return {
318
+ as() {
319
+ const nextAccum = {
320
+ ...accum,
321
+ [key]: resource()
322
+ };
323
+ return createConstrainedBuilder(_enumObj, nextAccum);
324
+ }
325
+ };
326
+ },
327
+ build() {
328
+ return new import_core3.InjectionToken("FlurryxStore", {
329
+ providedIn: "root",
330
+ factory: () => new DynamicStore(accum)
331
+ });
332
+ }
333
+ };
334
+ }
335
+ var Store = {
336
+ ...createBuilder({}),
337
+ for(enumObj) {
338
+ return createConstrainedBuilder(enumObj, {});
339
+ }
340
+ };
315
341
  // Annotate the CommonJS export names for ESM import in node:
316
342
  0 && (module.exports = {
317
343
  BaseStore,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/base-store.ts","../src/store-builder.ts","../src/dynamic-store.ts","../src/resource.ts"],"sourcesContent":["export { BaseStore } from './base-store';\nexport { Store } from './store-builder';\n","import { signal, WritableSignal } from '@angular/core';\nimport {\n ResourceState,\n isAnyKeyLoading,\n isKeyedResourceData,\n createKeyedResourceData,\n type KeyedResourceKey,\n} from '@flurryx/core';\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> {\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]>(\n initialState as TData[typeof _typedKey]\n )\n );\n });\n }\n}\n","import { InjectionToken } from '@angular/core';\nimport { BaseStore } from './base-store';\nimport { DynamicStore } from './dynamic-store';\nimport { resource } from './resource';\nimport type {\n StoreConfig,\n ResourceDef,\n InferEnum,\n InferData,\n} from './types';\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 * Fluent store builder entry point.\n *\n * @example\n * export const CustomersStore = Store\n * .resource('customers').as<Customer[]>()\n * .resource('customerDetails').as<Customer>()\n * .build();\n */\nexport const Store = createBuilder({} as StoreConfig);\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"],"mappings":"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","names":["import_core","import_core"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/base-store.ts","../src/store-builder.ts","../src/dynamic-store.ts","../src/resource.ts"],"sourcesContent":["export { BaseStore } from './base-store';\nexport { Store } from './store-builder';\n","import { signal, WritableSignal } from '@angular/core';\nimport {\n ResourceState,\n isAnyKeyLoading,\n isKeyedResourceData,\n createKeyedResourceData,\n type KeyedResourceKey,\n} from '@flurryx/core';\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> {\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]>(\n initialState as TData[typeof _typedKey]\n )\n );\n });\n }\n}\n","import { InjectionToken } from \"@angular/core\";\nimport { BaseStore } from \"./base-store\";\nimport { DynamicStore } from \"./dynamic-store\";\nimport { resource } from \"./resource\";\nimport type { StoreConfig, ResourceDef, InferEnum, InferData } 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 * 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<TEnum extends Record<string, string>>(\n enumObj: TEnum\n ): ConstrainedBuilder<TEnum, Record<string, never>> {\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"],"mappings":"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","names":["import_core","import_core"]}
package/dist/index.d.cts CHANGED
@@ -62,15 +62,60 @@ interface StoreBuilder<TAccum extends StoreConfig> {
62
62
  resource<TKey extends string>(key: TKey): AsStep<TAccum, TKey>;
63
63
  build(): InjectionToken<BaseStore<InferEnum<TAccum>, InferData<TAccum>>>;
64
64
  }
65
+ /** Keys from the enum that have NOT yet been defined. */
66
+ type Remaining<TEnum extends Record<string, string>, TAccum extends StoreConfig> = Exclude<keyof TEnum & string, keyof TAccum>;
67
+ /** Intermediate .as<T>() step for the constrained builder. */
68
+ interface ConstrainedAsStep<TEnum extends Record<string, string>, TAccum extends StoreConfig, TKey extends string> {
69
+ as<T>(): ConstrainedBuilder<TEnum, TAccum & Record<TKey, ResourceDef<T>>>;
70
+ }
71
+ /**
72
+ * Constrained builder — only allows keys from the enum that haven't been
73
+ * defined yet. `.build()` is only available when all keys are accounted for.
74
+ */
75
+ type ConstrainedBuilder<TEnum extends Record<string, string>, TAccum extends StoreConfig> = [Remaining<TEnum, TAccum>] extends [never] ? {
76
+ build(): InjectionToken<BaseStore<InferEnum<TAccum>, InferData<TAccum>>>;
77
+ } : {
78
+ resource<TKey extends Remaining<TEnum, TAccum>>(key: TKey): ConstrainedAsStep<TEnum, TAccum, TKey>;
79
+ };
80
+ interface StoreEntry {
81
+ /**
82
+ * Define a named resource slot.
83
+ * Chain .as<T>() to assign its type, then continue with more .resource() calls
84
+ * or call .build() when done.
85
+ */
86
+ resource<TKey extends string>(key: TKey): {
87
+ as<T>(): StoreBuilder<Record<TKey, ResourceDef<T>>>;
88
+ };
89
+ /**
90
+ * Bind the builder to an enum object for compile-time key validation.
91
+ *
92
+ * @example
93
+ * const Enum = { A: 'A', B: 'B' } as const;
94
+ * const MyStore = Store.for(Enum)
95
+ * .resource('A').as<string>()
96
+ * .resource('B').as<number>()
97
+ * .build();
98
+ */
99
+ for<TEnum extends Record<string, string>>(enumObj: TEnum): ConstrainedBuilder<TEnum, Record<string, never>>;
100
+ }
65
101
  /**
66
102
  * Fluent store builder entry point.
67
103
  *
68
104
  * @example
105
+ * // Unconstrained
69
106
  * export const CustomersStore = Store
70
107
  * .resource('customers').as<Customer[]>()
71
108
  * .resource('customerDetails').as<Customer>()
72
109
  * .build();
110
+ *
111
+ * @example
112
+ * // Constrained with enum
113
+ * const Enum = { SESSIONS: 'SESSIONS', MESSAGES: 'MESSAGES' } as const;
114
+ * export const ChatStore = Store.for(Enum)
115
+ * .resource('SESSIONS').as<Session[]>()
116
+ * .resource('MESSAGES').as<Message[]>()
117
+ * .build();
73
118
  */
74
- declare const Store: StoreBuilder<StoreConfig>;
119
+ declare const Store: StoreEntry;
75
120
 
76
121
  export { BaseStore, Store };
package/dist/index.d.ts CHANGED
@@ -62,15 +62,60 @@ interface StoreBuilder<TAccum extends StoreConfig> {
62
62
  resource<TKey extends string>(key: TKey): AsStep<TAccum, TKey>;
63
63
  build(): InjectionToken<BaseStore<InferEnum<TAccum>, InferData<TAccum>>>;
64
64
  }
65
+ /** Keys from the enum that have NOT yet been defined. */
66
+ type Remaining<TEnum extends Record<string, string>, TAccum extends StoreConfig> = Exclude<keyof TEnum & string, keyof TAccum>;
67
+ /** Intermediate .as<T>() step for the constrained builder. */
68
+ interface ConstrainedAsStep<TEnum extends Record<string, string>, TAccum extends StoreConfig, TKey extends string> {
69
+ as<T>(): ConstrainedBuilder<TEnum, TAccum & Record<TKey, ResourceDef<T>>>;
70
+ }
71
+ /**
72
+ * Constrained builder — only allows keys from the enum that haven't been
73
+ * defined yet. `.build()` is only available when all keys are accounted for.
74
+ */
75
+ type ConstrainedBuilder<TEnum extends Record<string, string>, TAccum extends StoreConfig> = [Remaining<TEnum, TAccum>] extends [never] ? {
76
+ build(): InjectionToken<BaseStore<InferEnum<TAccum>, InferData<TAccum>>>;
77
+ } : {
78
+ resource<TKey extends Remaining<TEnum, TAccum>>(key: TKey): ConstrainedAsStep<TEnum, TAccum, TKey>;
79
+ };
80
+ interface StoreEntry {
81
+ /**
82
+ * Define a named resource slot.
83
+ * Chain .as<T>() to assign its type, then continue with more .resource() calls
84
+ * or call .build() when done.
85
+ */
86
+ resource<TKey extends string>(key: TKey): {
87
+ as<T>(): StoreBuilder<Record<TKey, ResourceDef<T>>>;
88
+ };
89
+ /**
90
+ * Bind the builder to an enum object for compile-time key validation.
91
+ *
92
+ * @example
93
+ * const Enum = { A: 'A', B: 'B' } as const;
94
+ * const MyStore = Store.for(Enum)
95
+ * .resource('A').as<string>()
96
+ * .resource('B').as<number>()
97
+ * .build();
98
+ */
99
+ for<TEnum extends Record<string, string>>(enumObj: TEnum): ConstrainedBuilder<TEnum, Record<string, never>>;
100
+ }
65
101
  /**
66
102
  * Fluent store builder entry point.
67
103
  *
68
104
  * @example
105
+ * // Unconstrained
69
106
  * export const CustomersStore = Store
70
107
  * .resource('customers').as<Customer[]>()
71
108
  * .resource('customerDetails').as<Customer>()
72
109
  * .build();
110
+ *
111
+ * @example
112
+ * // Constrained with enum
113
+ * const Enum = { SESSIONS: 'SESSIONS', MESSAGES: 'MESSAGES' } as const;
114
+ * export const ChatStore = Store.for(Enum)
115
+ * .resource('SESSIONS').as<Session[]>()
116
+ * .resource('MESSAGES').as<Message[]>()
117
+ * .build();
73
118
  */
74
- declare const Store: StoreBuilder<StoreConfig>;
119
+ declare const Store: StoreEntry;
75
120
 
76
121
  export { BaseStore, Store };
package/dist/index.js CHANGED
@@ -288,7 +288,33 @@ function createBuilder(accum) {
288
288
  }
289
289
  };
290
290
  }
291
- var Store = createBuilder({});
291
+ function createConstrainedBuilder(_enumObj, accum) {
292
+ return {
293
+ resource(key) {
294
+ return {
295
+ as() {
296
+ const nextAccum = {
297
+ ...accum,
298
+ [key]: resource()
299
+ };
300
+ return createConstrainedBuilder(_enumObj, nextAccum);
301
+ }
302
+ };
303
+ },
304
+ build() {
305
+ return new InjectionToken("FlurryxStore", {
306
+ providedIn: "root",
307
+ factory: () => new DynamicStore(accum)
308
+ });
309
+ }
310
+ };
311
+ }
312
+ var Store = {
313
+ ...createBuilder({}),
314
+ for(enumObj) {
315
+ return createConstrainedBuilder(enumObj, {});
316
+ }
317
+ };
292
318
  export {
293
319
  BaseStore,
294
320
  Store
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/base-store.ts","../src/store-builder.ts","../src/dynamic-store.ts","../src/resource.ts"],"sourcesContent":["import { signal, WritableSignal } from '@angular/core';\nimport {\n ResourceState,\n isAnyKeyLoading,\n isKeyedResourceData,\n createKeyedResourceData,\n type KeyedResourceKey,\n} from '@flurryx/core';\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> {\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]>(\n initialState as TData[typeof _typedKey]\n )\n );\n });\n }\n}\n","import { InjectionToken } from '@angular/core';\nimport { BaseStore } from './base-store';\nimport { DynamicStore } from './dynamic-store';\nimport { resource } from './resource';\nimport type {\n StoreConfig,\n ResourceDef,\n InferEnum,\n InferData,\n} from './types';\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 * Fluent store builder entry point.\n *\n * @example\n * export const CustomersStore = Store\n * .resource('customers').as<Customer[]>()\n * .resource('customerDetails').as<Customer>()\n * .build();\n */\nexport const Store = createBuilder({} as StoreConfig);\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"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/base-store.ts","../src/store-builder.ts","../src/dynamic-store.ts","../src/resource.ts"],"sourcesContent":["import { signal, WritableSignal } from '@angular/core';\nimport {\n ResourceState,\n isAnyKeyLoading,\n isKeyedResourceData,\n createKeyedResourceData,\n type KeyedResourceKey,\n} from '@flurryx/core';\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> {\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]>(\n initialState as TData[typeof _typedKey]\n )\n );\n });\n }\n}\n","import { InjectionToken } from \"@angular/core\";\nimport { BaseStore } from \"./base-store\";\nimport { DynamicStore } from \"./dynamic-store\";\nimport { resource } from \"./resource\";\nimport type { StoreConfig, ResourceDef, InferEnum, InferData } 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 * 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<TEnum extends Record<string, string>>(\n enumObj: TEnum\n ): ConstrainedBuilder<TEnum, Record<string, never>> {\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"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flurryx/store",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
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.6.0"
31
+ "@flurryx/core": "0.6.1"
32
32
  },
33
33
  "peerDependencies": {
34
34
  "@angular/core": ">=17.0.0"