ngx-statewise
Version:
A lightweight and intuitive state management for Angular. Simpler than NgRx, more structured than DIY.
266 lines (251 loc) • 10.2 kB
TypeScript
import { Observable } from 'rxjs';
import * as i0 from '@angular/core';
import { Type, EnvironmentProviders } from '@angular/core';
/**
* Represents an action with no payload.
*
* @returns `undefined` — used as a placeholder for actions without data.
*/
type EmptyPayloadFn = () => undefined;
/**
* Function that receives and returns a typed payload.
*
* @template T - The payload type.
* @param payload - The input data.
* @returns The same payload.
*/
type ValuePayloadFn<T> = (payload: T) => T;
/**
* Defines a payload function based on the payload type:
* - If `T` is `undefined`, resolves to `EmptyPayloadFn`.
* - Otherwise, resolves to `ValuePayloadFn<T>`.
*
* @template T - Payload type.
*/
type SingleAction<T> = T extends undefined ? EmptyPayloadFn : ValuePayloadFn<T>;
/**
* Base structure for all actions.
*
* @property type - The action type string.
* @property payload - Optional data attached to the action.
*/
type Action = {
type: string;
payload?: any;
};
/**
* Converts a CamelCase or PascalCase string to snake_case.
*
* @template S - Input string type.
*
* @example
* type A = CamelToSnakeCase<'loadFailure'> // 'load_failure'
* type B = CamelToSnakeCase<'UserLogin'> // 'user_login'
*/
type CamelToSnakeCase<S extends string> = S extends `${infer Head}${infer Tail}` ? Tail extends Uncapitalize<Tail> ? `${Lowercase<Head>}${CamelToSnakeCase<Tail>}` : `${Lowercase<Head>}_${CamelToSnakeCase<Tail>}` : S;
/**
* Represents an empty payload for actions without data.
*
* @returns `undefined`
*/
declare const emptyPayload: EmptyPayloadFn;
/**
* 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.
*/
declare function payload<T>(): ValuePayloadFn<T>;
/**
* Extracts the action type string from an action creator or object.
*
* @param action - Either an action creator (function with `.type`) or an action object.
* @returns The `type` string.
*
* @example
* ofType(someActionCreator) // 'SOME_ACTION'
* ofType({ type: 'MY_ACTION' }) // 'MY_ACTION'
*/
declare function ofType<T extends (...args: any[]) => Action>(action: T): string;
declare function ofType(action: {
type: string;
}): string;
/**
* 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
*/
declare function defineActionsGroup<Source extends string, Events extends Record<string, SingleAction<any>>>(config: {
source: Source;
events: Events;
}): { [K in keyof Events]: Events[K] extends EmptyPayloadFn ? () => {
type: `${Uppercase<Source>}_${Uppercase<CamelToSnakeCase<string & K>>}`;
} : (payload: Parameters<Events[K]>[0]) => {
type: `${Uppercase<Source>}_${Uppercase<CamelToSnakeCase<string & K>>}`;
payload: Parameters<Events[K]>[0];
}; };
/**
* 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
*/
declare function defineSingleAction<Source extends string, ActionPayload>(source: Source, payload: SingleAction<ActionPayload>): {
action: ActionPayload extends undefined ? () => {
type: `${Source}_ACTION`;
} : (payload: ActionPayload) => {
type: `${Source}_ACTION`;
payload: ActionPayload;
};
};
type SWEffects = Promise<Observable<Action> | Action | Action[] | void> | Observable<Action | Action[]> | Action | Action[] | void;
/**
* Registers an effect that listens to a specific action and executes a handler.
*
* @param action - The action creator function.
* @param handler - A function called when the action is dispatched.
* - Receives the payload if the action defines one.
* - Can return an action, array of actions, observable, or promise.
*/
declare function createEffect<T extends (payload: any) => Action>(action: T, handler: (payload: Parameters<T>[0]) => SWEffects): void;
/**
* Registers an effect for an action without payload.
*
* @param action - Action creator with no payload.
* @param handler - Function executed when the action is dispatched.
*/
declare function createEffect(action: () => Action, handler: () => SWEffects): void;
/**
* 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.
*/
declare function waitForAllEffects(): Promise<void>;
/**
* 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.
*/
declare function waitForEffect(actionType: string): Promise<void>;
/**
* Interface representing an updator for state management.
*
* The `IUpdator` holds the current state and a registry of functions
* (updators) that can modify that state based on different action types.
*
* @template S - The type of the state.
*/
interface IUpdator<S> {
/**
* The current state that the updators will modify.
*/
readonly state: S;
/**
* A registry of updators, where each action type is associated with a function
* that modifies the state.
*/
readonly updators: UpdatorGlobalRegistry<S>;
}
/**
* Type representing a function that updates the state based on an action.
*
* @template S - The type of the state.
* @template P - The type of the payload (optional).
*
* @param state - The current state to be updated.
* @param payload - The data to modify the state (optional).
*/
type Updator<S, P = any> = (state: S, payload?: P) => void;
/**
* A registry of updators, where each action type is mapped to an `Updator` function.
*
* The key is the action type (usually a string), and the value is the corresponding
* function that modifies the state when the action is dispatched.
*
* @template S - The type of the state.
*/
interface UpdatorGlobalRegistry<S> {
/**
* Maps action types to their corresponding `Updator` function.
*
* The key is an action type, and the value is an `Updator` that modifies the state.
*/
[actionType: string]: Updator<S>;
}
/**
* 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.
*/
declare function registerLocalUpdator<S>(manager: object, updator: IUpdator<S>): void;
/**
* Dispatches an action with optional updator registration.
*
* This function provides a flexible way to dispatch actions:
* - If only an action is provided, it will be dispatched through the ActionDispatcher
* - If an updator is also provided, it will be registered (if needed) and used to update state
*
* @template T - The action type.
* @template S - The state type (inferred from updator if provided).
* @param action - The action to dispatch.
* @param updator - Optional updator to handle state updates for this action.
*/
declare function dispatch<T extends Action>(action: T, context?: object): void;
declare function dispatch<T extends Action, S>(action: T, updator: IUpdator<S>): void;
/**
* Asynchronously dispatches an action and waits for effects to complete.
*
* Similar to `dispatch`, but returns a Promise that resolves when all associated
* effects are completed. Supports both global and local updators.
*
* @template T - The action type.
* @template S - The state type (inferred from updator if provided).
* @param action - The action to dispatch.
* @param updator - Optional updator to handle state updates for this action.
* @returns A Promise that resolves when all effects for this action are completed.
*/
declare function dispatchAsync<T extends Action>(action: T, context?: object): Promise<void>;
declare function dispatchAsync<T extends Action, S>(action: T, updator: IUpdator<S>): Promise<void>;
declare function provideStatewise(): i0.EnvironmentProviders;
/**
* 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.
*/
declare function provideEffects(effectClasses: Type<any>[]): EnvironmentProviders;
/**
* 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.
*
*/
declare function provideUpdators(updatorClasses: Type<IUpdator<any>>[]): EnvironmentProviders;
export { createEffect, defineActionsGroup, defineSingleAction, dispatch, dispatchAsync, emptyPayload, ofType, payload, provideEffects, provideStatewise, provideUpdators, registerLocalUpdator, waitForAllEffects, waitForEffect };
export type { IUpdator, UpdatorGlobalRegistry as UpdatorRegistry };