UNPKG

ngx-statewise

Version:

A lightweight and intuitive state management for Angular. Simpler than NgRx, more structured than DIY.

786 lines (749 loc) 33.5 kB
import * as i0 from '@angular/core'; import { Injectable, inject, signal, runInInjectionContext, provideEnvironmentInitializer, EnvironmentInjector, makeEnvironmentProviders, provideAppInitializer } from '@angular/core'; import { isObservable, firstValueFrom } from 'rxjs'; /** * Represents an empty payload for actions without data. * * @returns `undefined` */ const emptyPayload = () => undefined; /** * Creates a typed identity function for payloads. * * Useful to define payload handlers with a specific type. * * @template T - The expected payload type. * @returns A function that returns the same payload it receives. */ function payload() { return (p) => p; } /** * Converts a camelCase or PascalCase string to SCREAMING_SNAKE_CASE. * * @param str - The input string. * @returns The same string converted to SCREAMING_SNAKE_CASE. * * @example * toScreamingSnakeCase('loadFailure') // 'LOAD_FAILURE' * toScreamingSnakeCase('UserLogin') // 'USER_LOGIN' */ function toScreamingSnakeCase(str) { return str.replace(/([a-z])([A-Z])/g, '$1_$2').toUpperCase(); } function ofType(action) { if (typeof action === 'function') { return action.type; } return action.type; } class ActionCreatorFactory { static defineActionCreator(type, payloadFn) { let fn; if (payloadFn === emptyPayload) { fn = () => this.createAction(type); } else { fn = (payload) => this.createAction(type, payloadFn(payload)); } fn.type = type; return fn; } static createAction(type, payload) { return payload === undefined ? { type } : { type, payload }; } } class ActionGroupHandler { static handle(config) { const { source, events } = config; const result = {}; for (const key in events) { const type = `${source.toUpperCase()}_${toScreamingSnakeCase(key)}`; result[key] = ActionCreatorFactory.defineActionCreator(type, events[key]); } return result; } } class SingleActionHandler { static handle(source, payload) { return { action: ActionCreatorFactory.defineActionCreator(`${source}_ACTION`, payload), }; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: SingleActionHandler, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: SingleActionHandler, providedIn: 'root' }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: SingleActionHandler, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }] }); class ActionService { static defineActionsGroup(config) { return ActionGroupHandler.handle(config); } static defineSingleAction(source, payload) { return SingleActionHandler.handle(source, payload); } } /** * Defines a group of related actions with a common source * * This function provides a convenient way to define action groups without * directly injecting the ActionService * * @param config - Object containing source prefix and events map * @returns An object with action creators for each event */ function defineActionsGroup(config) { return ActionService.defineActionsGroup(config); } /** * Defines a single action with a source prefix * * This function provides a convenient way to define a single action without * directly injecting the ActionService * * @param source - Source prefix for the action type * @param payload - Payload handler function * @returns An object with an action creator */ function defineSingleAction(source, payload) { return ActionService.defineSingleAction(source, payload); } class EffectRelationRegistery { actionRelations = new Map(); register(parent, child) { if (!this.actionRelations.has(parent)) { this.actionRelations.set(parent, new Set()); } this.actionRelations.get(parent)?.add(child); } getAllRelated(action, visited = new Set()) { if (visited.has(action)) return visited; visited.add(action); const children = this.actionRelations.get(action) || new Set(); for (const child of children) { this.getAllRelated(child, visited); } return visited; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: EffectRelationRegistery, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: EffectRelationRegistery, providedIn: 'root' }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: EffectRelationRegistery, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }] }); class PendingEffectRegistry { pending = new Map(); effectRelationRegistery = inject(EffectRelationRegistery); register(actionType, promise) { const list = this.pending.get(actionType) || []; this.pending.set(actionType, [...list, promise]); promise.finally(() => { const current = this.pending.get(actionType) || []; this.pending.set(actionType, current.filter((p) => p !== promise)); }); return promise; } get(actionType) { return this.pending.get(actionType) || []; } async waitFor(actionType) { const allRelatedTypes = this.effectRelationRegistery.getAllRelated(actionType); const allPromisesToWait = []; for (const type of allRelatedTypes) { const promises = this.pending.get(type) || []; allPromisesToWait.push(...promises); } await Promise.all(allPromisesToWait); } async waitForAll() { const all = Array.from(this.pending.values()).flat(); await Promise.all(all); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: PendingEffectRegistry, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: PendingEffectRegistry, providedIn: 'root' }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: PendingEffectRegistry, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }] }); class EffectResultResolver { async resolve(result) { if (result === undefined || result === null) { return [undefined]; } if (result instanceof Promise) { const awaited = await result; if (isObservable(awaited)) { const resolvedObs = await firstValueFrom(awaited); return Array.isArray(resolvedObs) ? resolvedObs : [resolvedObs]; } return Array.isArray(awaited) ? awaited.flat() : [awaited]; } if (isObservable(result)) { const resolved = await firstValueFrom(result); return Array.isArray(resolved) ? resolved : [resolved]; } if (Array.isArray(result)) { return result; } return [result]; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: EffectResultResolver, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: EffectResultResolver, providedIn: 'root' }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: EffectResultResolver, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }] }); class GlobalUpdatorsRegistry { _updatorRegistry = new Map(); constructor() { } registerUpdator(actionType, updator) { if (this._updatorRegistry.has(actionType)) { return; } this._updatorRegistry.set(actionType, updator); } registerFullUpdator(updator) { Object.keys(updator.updators).forEach((actionType) => { this.registerUpdator(actionType, updator); }); } getUpdator(actionType) { return this._updatorRegistry.get(actionType); } getRegisteredActionTypes() { return Array.from(this._updatorRegistry.keys()); } hasUpdator(actionType) { return this._updatorRegistry.has(actionType); } unregisterUpdator(actionType) { return this._updatorRegistry.delete(actionType); } clearUpdators() { this._updatorRegistry.clear(); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: GlobalUpdatorsRegistry, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: GlobalUpdatorsRegistry, providedIn: 'root' }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: GlobalUpdatorsRegistry, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }], ctorParameters: () => [] }); class ActionContextRegistery { contextMap = new Map(); set(actionType, context) { this.contextMap.set(actionType, context); } get(actionType) { return this.contextMap.get(actionType); } clear(actionType) { this.contextMap.delete(actionType); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: ActionContextRegistery, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: ActionContextRegistery, providedIn: 'root' }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: ActionContextRegistery, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }] }); class LocalUpdatorRegistry { localRegistries = new WeakMap(); register(manager, updator) { if (!this.localRegistries.has(manager)) { this.localRegistries.set(manager, new Set()); } const localRegistry = this.localRegistries.get(manager); localRegistry.add(updator); } get(manager, actionType) { const localRegistry = this.localRegistries.get(manager); if (!localRegistry) return undefined; for (const updator of localRegistry) { if (updator.updators[actionType]) { return updator; } } return undefined; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: LocalUpdatorRegistry, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: LocalUpdatorRegistry, providedIn: 'root' }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: LocalUpdatorRegistry, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }] }); /** * Updates the given state based on the action and the corresponding `updator`. * * This function looks up the `Updator` function associated with the action type * from the provided `updators` registry and applies it to update the state. * If no handler is found for the action type, a warning is logged. * * @template S - The type of the state to be updated. * @param state - The current state to be updated. * @param action - The action that triggered the state update. * @param updators - A registry of action types to their respective `Updator` functions. */ function update(state, action, updators) { const handler = updators[action.type]; if (handler) { handler(state, action.payload); } else { console.warn(`No handler for action type: ${action.type}`); } } class ActionEffectRegistry { _effects = new Map(); register(actionType, effect) { const list = this._effects.get(actionType) || []; this._effects.set(actionType, [...list, effect]); } get(actionType) { return this._effects.get(actionType) || []; } has(actionType) { return !!this._effects.get(actionType)?.length; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: ActionEffectRegistry, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: ActionEffectRegistry, providedIn: 'root' }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: ActionEffectRegistry, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }] }); class ActionHistoryService { _latest = signal(null); _history = signal([]); latest() { return this._latest.asReadonly(); } history() { return this._history.asReadonly(); } record(action) { this._latest.set(action); this._history.update((list) => [...list, action]); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: ActionHistoryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: ActionHistoryService, providedIn: 'root' }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: ActionHistoryService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }] }); class ActionEffectHandlerr { registry = inject(ActionEffectRegistry); handle(action) { const effects = this.registry.get(action.type); for (const effect of effects) { effect(action); } } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: ActionEffectHandlerr, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: ActionEffectHandlerr, providedIn: 'root' }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: ActionEffectHandlerr, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }] }); class ActionDispatcherService { actionHistory = inject(ActionHistoryService); actionEffectHandler = inject(ActionEffectHandlerr); globalEffectRegistery = inject(ActionEffectRegistry); pendingEffectRegistry = inject(PendingEffectRegistry); emit(action) { if (!this.globalEffectRegistery.has(action.type)) { this.pendingEffectRegistry.register(action.type, Promise.resolve()); } this.actionHistory.record(action); this.actionEffectHandler.handle(action); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: ActionDispatcherService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: ActionDispatcherService, providedIn: 'root' }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: ActionDispatcherService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }] }); class CoordinatorService { pendingEffectRegistry = inject(PendingEffectRegistry); actionDispatcher = inject(ActionDispatcherService); dispatch(action, updator) { update(updator.state, action, updator.updators); this.actionDispatcher.emit(action); } dispatchAsync(action, updator) { this.dispatch(action, updator); return this.pendingEffectRegistry.waitFor(action.type); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: CoordinatorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: CoordinatorService, providedIn: 'root' }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: CoordinatorService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }] }); class UpdatorResolver { globalUpdatorsRegistry = inject(GlobalUpdatorsRegistry); localUpdatorsRegistry = inject(LocalUpdatorRegistry); actionContext = inject(ActionContextRegistery); resolveUpdator(actionType, contextOrUpdator) { this.setContext(actionType, contextOrUpdator); const explicit = this.asUpdator(contextOrUpdator); if (explicit) { this.localUpdatorsRegistry.register(explicit, explicit); return explicit; } const local = this.asLocal(contextOrUpdator, actionType); if (local) { return local; } return this.globalUpdatorsRegistry.getUpdator(actionType); } setContext(type, context) { if (context) this.actionContext.set(type, context); } asUpdator(updator) { return updator && 'state' in updator && 'updators' in updator ? updator : null; } asLocal(context, type) { return context && !this.asUpdator(context) ? this.localUpdatorsRegistry.get(context, type) ?? null : null; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: UpdatorResolver, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: UpdatorResolver, providedIn: 'root' }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: UpdatorResolver, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }] }); class DispatchHandler { coordinator = inject(CoordinatorService); actionDispatcher = inject(ActionDispatcherService); updatorResolver = inject(UpdatorResolver); handle(action, contextOrUpdator) { const updator = this.updatorResolver.resolveUpdator(action.type, contextOrUpdator); if (updator) { this.coordinator.dispatch(action, updator); } else { this.actionDispatcher.emit(action); } } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: DispatchHandler, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: DispatchHandler, providedIn: 'root' }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: DispatchHandler, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }] }); class EffectResultHandler { actionDispatcher = inject(ActionDispatcherService); pendingEffectRegistry = inject(PendingEffectRegistry); actionContextRegistry = inject(ActionContextRegistery); effectRelationRegistry = inject(EffectRelationRegistery); globalUpdatorsRegistry = inject(GlobalUpdatorsRegistry); localUpdatorRegistry = inject(LocalUpdatorRegistry); dispatch = inject(DispatchHandler); async handle(results, parentActionType) { const subActionPromises = []; const context = this.actionContextRegistry.get(parentActionType); for (const result of results.flat().filter((a) => !!a)) { this.effectRelationRegistry.register(parentActionType, result.type); let used = this.tryUseLocalUpdator(result, context); if (!used) { used = this.tryUseGlobalUpdator(result); } if (!used) { this.actionDispatcher.emit(result); } this.collectPendingPromises(result, subActionPromises); } this.actionContextRegistry.clear(parentActionType); return subActionPromises; } tryUseLocalUpdator(action, context) { if (!context) return false; const local = this.localUpdatorRegistry.get(context, action.type); if (local) { this.dispatch.handle(action, context); return true; } return false; } tryUseGlobalUpdator(action) { const globalUpdator = this.globalUpdatorsRegistry.getUpdator(action.type); if (globalUpdator) { this.dispatch.handle(action, globalUpdator); return true; } return false; } collectPendingPromises(action, subActionPromises) { const pending = this.pendingEffectRegistry.get(action.type); if (pending.length) { subActionPromises.push(pending[0]); } } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: EffectResultHandler, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: EffectResultHandler, providedIn: 'root' }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: EffectResultHandler, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }] }); class EffectPromiseService { effectResultResolver = inject(EffectResultResolver); effectResultHandler = inject(EffectResultHandler); createPromise(handler, action, actionType) { return (async () => { try { const rawResult = handler(action.payload); const results = await this.effectResultResolver.resolve(rawResult); const subActionPromises = await this.effectResultHandler.handle(results, actionType); if (subActionPromises.length > 0) { await Promise.all(subActionPromises); } } catch (error) { console.error(`Effect for ${actionType} failed:`, error); } })(); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: EffectPromiseService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: EffectPromiseService, providedIn: 'root' }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: EffectPromiseService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }] }); class EffectRegistrationService { globalEffectRegistry = inject(ActionEffectRegistry); pendingEffectRegistry = inject(PendingEffectRegistry); effectPromiseService = inject(EffectPromiseService); registerEffect(actionCreator, handler) { const actionType = ofType(actionCreator); this.globalEffectRegistry.register(actionType, async (action) => { const effectPromise = this.effectPromiseService.createPromise(handler, action, actionType); this.pendingEffectRegistry.register(actionType, effectPromise); return effectPromise; }); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: EffectRegistrationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: EffectRegistrationService, providedIn: 'root' }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: EffectRegistrationService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }] }); let rootInjector = null; function setRootInjector(injector) { rootInjector = injector; } function getRootInjector() { if (!rootInjector) { throw new Error('[StateManager] EnvironmentInjector not initialized. Ensure that provideStateManager() is included in the providers of bootstrapApplication.'); } return rootInjector; } async function withInjectionContext(fn) { return runInInjectionContext(getRootInjector(), fn); } /** * Internal implementation of createEffect, handling both payload and no-payload cases. */ function createEffect(action, handler) { withInjectionContext(() => { const effectRegistrationService = inject(EffectRegistrationService); effectRegistrationService.registerEffect(action, handler); }); } /** * Waits for all currently pending effects to resolve. * * This function ensures that all side effects triggered by actions are completed * before continuing with the execution flow. * * @returns A promise that resolves when all pending effects are completed. */ function waitForAllEffects() { return withInjectionContext(() => { const pendingEffect = inject(PendingEffectRegistry); return pendingEffect.waitForAll(); }); } /** * Waits for pending effects associated with a specific action type to resolve. * * Useful for scenarios where you need to wait for effects triggered by a particular * action before proceeding. * * @param actionType - The action type whose effects should be waited for. * @returns A promise that resolves when all pending effects for the specified action type are completed. */ function waitForEffect(actionType) { return withInjectionContext(() => { const pendingEffect = inject(PendingEffectRegistry); return pendingEffect.waitFor(actionType); }); } class DispatchService { dispatchHandler = inject(DispatchHandler); dispatch(action, contextOrUpdator) { this.dispatchHandler.handle(action, contextOrUpdator); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: DispatchService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: DispatchService, providedIn: 'root' }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: DispatchService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }] }); function dispatch(action, contextOrUpdator) { withInjectionContext(() => { const dispatchService = inject(DispatchService); dispatchService.dispatch(action, contextOrUpdator); }); } class DispatchAsyncHandler { coordinator = inject(CoordinatorService); actionDispatcher = inject(ActionDispatcherService); pendingEffect = inject(PendingEffectRegistry); actionContext = inject(ActionContextRegistery); updatorResolver = inject(UpdatorResolver); handle(action, contextOrUpdator) { const updator = this.updatorResolver.resolveUpdator(action.type, contextOrUpdator); if (updator) { return this.execWithCleanup(this.coordinator.dispatchAsync(action, updator), action.type); } this.actionDispatcher.emit(action); return this.execWithCleanup(this.pendingEffect.waitFor(action.type), action.type); } async execWithCleanup(promise, type) { try { return await promise; } finally { this.actionContext.clear(type); } } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: DispatchAsyncHandler, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: DispatchAsyncHandler, providedIn: 'root' }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: DispatchAsyncHandler, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }] }); class DispatchAsyncService { dispatchAsynHandler = inject(DispatchAsyncHandler); dispatchAsync(action, contextOrUpdator) { return this.dispatchAsynHandler.handle(action, contextOrUpdator); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: DispatchAsyncService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: DispatchAsyncService, providedIn: 'root' }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: DispatchAsyncService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }] }); function dispatchAsync(action, contextOrUpdator) { return withInjectionContext(() => { const dispatchAsyncService = inject(DispatchAsyncService); return dispatchAsyncService.dispatchAsync(action, contextOrUpdator); }); } class UpdatorRegistrationService { localRegistry = inject(LocalUpdatorRegistry); registerLocalUpdator(manager, updator) { this.localRegistry.register(manager, updator); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: UpdatorRegistrationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: UpdatorRegistrationService, providedIn: 'root' }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.2", ngImport: i0, type: UpdatorRegistrationService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }] }); /** * Registers a local updater for a given manager context. * * This function should be used within an Angular injection context (e.g. during component initialization). * * @template S - The state type handled by the updater. * @param {object} manager - The local context object (e.g., a component or a service) to associate the updater with. * @param {IUpdator<S>} updator - The updater instance defining actions and their update logic for the given state. */ function registerLocalUpdator(manager, updator) { withInjectionContext(() => { const updatorRegistrationService = inject(UpdatorRegistrationService); updatorRegistrationService.registerLocalUpdator(manager, updator); }); } function provideStatewise() { return provideEnvironmentInitializer(() => { const injector = inject(EnvironmentInjector); setRootInjector(injector); }); } /** * Registers and instantiates a list of effect classes at application startup. * * @param effectClasses - Array of effect class types to initialize. * @returns EnvironmentProviders to include in your application bootstrap. */ function provideEffects(effectClasses) { return makeEnvironmentProviders([ ...effectClasses.map((effectClass) => ({ provide: effectClass, useClass: effectClass, })), provideEnvironmentInitializer(() => { effectClasses.forEach((effectClass) => inject(effectClass)); }), ]); } /** * Registers an array of updators globally at application startup. * * This function provides a way to register state updators during the Angular * application initialization phase, making them available throughout the application * without needing to register them with each dispatch call. * * @param updators - An array of Updator class to be registered globally. * @returns Angular EnvironmentProviders to be included in your application bootstrap. * */ function provideUpdators(updatorClasses) { return makeEnvironmentProviders([ ...updatorClasses, // ensure classes are registered as providers provideAppInitializer(() => { const registry = inject(GlobalUpdatorsRegistry); updatorClasses.forEach((cls) => { const instance = inject(cls); registry.registerFullUpdator(instance); }); }), ]); } /* * Public API Surface of ngx-statewise */ /** * Generated bundle index. Do not edit. */ export { createEffect, defineActionsGroup, defineSingleAction, dispatch, dispatchAsync, emptyPayload, ofType, payload, provideEffects, provideStatewise, provideUpdators, registerLocalUpdator, waitForAllEffects, waitForEffect }; //# sourceMappingURL=ngx-statewise.mjs.map