UNPKG

@simplux/core

Version:

The core package of simplux. Contains everything to manage your application state in a simple way.

624 lines (565 loc) 20.2 kB
import { Action } from 'redux'; import type { AnyAction } from 'redux'; import { Reducer } from 'redux'; import { Store } from 'redux'; /** * @public */ export declare type _AtomicObject = Promise<unknown> | Date | RegExp | Boolean | Number | String; /** * Create a new effect. An effect is any function that has side effects. * The main purpose of this function is to allow simple mocking of the * effect. * * @param effect - the effect to create * * @returns a function that calls the provided effect and can be mocked * * @public */ export declare function createEffect<TEffectFunction extends (...args: any[]) => any>(effect: TEffectFunction): SimpluxEffect<TEffectFunction>; /** * Create new effects. An effect is any function that has side effects. * The main purpose of this function is to allow simple mocking of the * effect. * * @param effects - the effects to create * * @returns functions that call the provided effects and can be mocked * * @public */ export declare function createEffects<TEffectDefinitions extends SimpluxEffectDefinitions>(effects: TEffectDefinitions): SimpluxEffects<TEffectDefinitions>; /** * Create new mutations for the module. A mutation is a function * that takes the module state and optionally additional parameters * and updates the state. * * @param simpluxModule - the module to create mutations for * @param mutationDefinitions - the mutations to create * * @returns an object that contains a function for each provided * mutation which when called will execute the mutation on the module * * @public */ export declare function createMutations<TState, TMutations extends MutationDefinitions<TState>>(simpluxModule: SimpluxModuleMarker<TState>, mutationDefinitions: TMutations): SimpluxMutations<TState, TMutations>; /** * Create new selectors for the module. A selector is a function * that takes the module state and optionally additional parameters * and returns some selected value. * * The selector must be a pure function. Its result is memoized * for the latest state and parameters. * * @param simpluxModule - the module to create selectors for * @param selectorDefinitions - the selectors to create * * @returns an object that contains a function for each provided * selector * * @public */ export declare function createSelectors<TState, TSelectorDefinitions extends SelectorDefinitions<TState>>(simpluxModule: SimpluxModuleMarker<TState>, selectorDefinitions: TSelectorDefinitions): SimpluxSelectors<TState, TSelectorDefinitions>; /** * Create a new simplux module. * * A module has a unique name (provided via the `config` parameter) * and a type of state it contains (the initial state is provided via * the `config` parameter). * * The returned module contains functions for basic interaction with * the module as well as any other functions that are provided by the * extension packages you have loaded. * * To learn more, have a look at the [getting started recipe](https://github.com/MrWolfZ/simplux/tree/master/recipes/basics/getting-started). * * @param config - the configuration values for the module * * @returns the created module * * @public */ export declare function createSimpluxModule<TState>(config: SimpluxModuleConfig<TState>): SimpluxModule<TState>; /** * Create a new simplux module. * * A module has a unique name and a type of state it contains. * * The returned module contains functions for basic interaction with * the module as well as any other functions that are provided by the * extension packages you have loaded. * * To learn more, have a look at the [getting started recipe](https://github.com/MrWolfZ/simplux/tree/master/recipes/basics/getting-started). * * @param name - the unique name of the module * @param initialState - the initial state of the module * * @returns the created module * * @public */ export declare function createSimpluxModule<TState>(name: string, initialState: TState): SimpluxModule<TState>; /** * Helper type to create a function type with the same signature as a given function * * @public */ export declare type FunctionSignature<TFunction extends (...args: any[]) => any> = _NonFunctionProperties<TFunction> extends never ? TFunction : TFunction extends (...args: infer TArgs) => infer TReturn ? (...args: TArgs) => TReturn : never; /** * Returns the root reducer that manages all simplux state. * This reducer should be combined with all the other reducers * your application has. * * To learn more, have a look at the [getting started recipe](https://github.com/MrWolfZ/simplux/tree/master/recipes/basics/getting-started). * * @returns the simplux root reducer * * @public */ export declare function getSimpluxReducer(): Reducer; /** * @public */ export declare type _IfEquals<X, Y, A = X, B = never> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2 ? A : B; /** * A type that recursively converts another type to be immutable, i.e. * all properties and arrays become readonly. * * @public */ export declare type Immutable<T> = T extends _AtomicObject ? T : _IsImmutable<T> extends true ? T : T extends ReadonlyMap<infer K, infer V> ? ReadonlyMap<Immutable<K>, Immutable<V>> : T extends ReadonlySet<infer V> ? ReadonlySet<Immutable<V>> : T extends object ? { readonly [K in keyof T]: Immutable<T[K]>; } : T; /** * @public */ export declare type _IsAtomicObject<T> = T extends _AtomicObject ? true : false; /** * @public */ export declare type _IsImmutable<T> = _IsAtomicObject<T> extends true ? true : _IsImmutableArray<T> extends true ? true : _IsImmutableObject<T> extends true ? true : false; /** * @public */ export declare type _IsImmutableArray<T> = T extends unknown[] ? false : T extends readonly (infer U)[] ? { [K in keyof T]: _IsImmutable<U>; }[number] extends true ? true : false : false; /** * @public */ export declare type _IsImmutableObject<T> = T extends object ? Exclude<keyof T, _ReadonlyKeys<T>> extends false ? { [K in keyof T]: _IsImmutable<T[K]> extends true ? true : false; }[keyof T] extends true ? true : false : false : false; /** * @public */ export declare type _IsMutable<T> = T extends _AtomicObject ? true : T extends _MutableArray<T> ? true : T extends object ? Exclude<keyof T, _WritableKeys<T>> extends never ? { [K in keyof T]: _IsMutable<T[K]> extends true ? true : false; }[keyof T] extends true ? true : false : false : true; /** * A type that recursively converts another type to be mutable, i.e. * all readonly modifiers are removed from properties and arrays. * * @public */ export declare type Mutable<T> = T extends _AtomicObject ? T : _IsMutable<T> extends true ? T : T extends readonly (infer U)[] ? Mutable<U>[] : T extends ReadonlyMap<infer K, infer V> ? Map<Mutable<K>, Mutable<V>> : T extends ReadonlySet<infer V> ? Set<Mutable<V>> : T extends object ? { -readonly [K in keyof T]: Mutable<T[K]>; } : T; /** * @public */ export declare type _MutableArray<T> = T extends readonly (infer U)[] ? Mutable<U>[] : never; /** * A function to turn into a mutation. * * @public */ export declare type MutationDefinition<TState> = (state: TState, ...args: any) => TState | void; /** * The functions to turn into mutations. * * @public */ export declare interface MutationDefinitions<TState> { [name: string]: MutationDefinition<TState>; } /** * @public */ export declare type _NonFunctionProperties<TFunction extends Function> = Exclude<keyof TFunction, keyof Function>; /** * @public */ export declare type _ReadonlyKeys<T> = { [P in keyof T]-?: _IfEquals<{ [Q in P]: T[P]; }, { -readonly [Q in P]: T[P]; }, never, P>; }[keyof T]; /** * A simplux mutation is a function that updates a module's state. * {@link SimpluxMutation} * * @public */ export declare type ResolvedMutation<TState, TMutation extends MutationDefinition<TState>> = TMutation extends (state: TState, ...args: infer TArgs) => TState | void ? SimpluxMutation<TState, TArgs> : never; /** * A simplux selector is a function that projects a module's state to some value. * {@link SimpluxSelector} * * @public */ export declare type ResolvedSelector<TState, TSelectorDefinition extends SelectorDefinition<TState, ReturnType<TSelectorDefinition>>> = TSelectorDefinition extends (state: Immutable<TState>, ...args: infer TArgs) => infer TReturn ? SimpluxSelector<TState, TArgs, TReturn> : never; /** * This type exists to get the concrete type of the handler, i.e. to return * a handler with the correct number or parameters * * @public */ export declare type ResolvedStateChangeHandler<TState, THandler> = THandler extends (state: Immutable<TState>) => void ? (state: Immutable<TState>) => void : StateChangeHandler<TState>; /** * A function to turn into a selector. * * @public */ export declare type SelectorDefinition<TState, TReturn> = (state: Immutable<TState>, ...args: any) => TReturn; /** * The functions to turn into selectors. * * @public */ export declare interface SelectorDefinitions<TState> { [name: string]: SelectorDefinition<TState, any>; } /** * Set the redux store that simplux should use. It is required to call * this function before any created simplux module can be used. * * The second parameter must be a function that maps from the redux store's * root state to the simplux root state. * * If this function is called again with a new store, simplux will safely * switch over to the new store. However, no state is transferred and * therefore all modules are reset to their initial state. This is primarily * useful in server-side rendering scenarios. * * To learn more, have a look at the [getting started recipe](https://github.com/MrWolfZ/simplux/tree/master/recipes/basics/getting-started). * * @param storeToUse - the redux store that simplux should use * @param simpluxStateGetter - a mapper function from the redux root state * to the simplux root state * * @returns a cleanup function that when called disconnects simplux from the * redux store (but it does not remove any of the simplux state from the store) * * @public */ export declare function setReduxStoreForSimplux<TState>(storeToUse: Store<TState>, simpluxStateGetter: (rootState: TState) => any): () => void; /** * Helper symbol used for identifying simplux effect objects. * * @public */ export declare const SIMPLUX_EFFECT = "[SIMPLUX_EFFECT]"; /** * Helper symbol used for identifying simplux module objects. * * @public */ export declare const SIMPLUX_MODULE = "[SIMPLUX_MODULE]"; /** * Helper symbol used for identifying simplux mutation objects. * * @public */ export declare const SIMPLUX_MUTATION = "[SIMPLUX_MUTATION]"; /** * Helper symbol used for identifying simplux selector objects. * * @public */ export declare const SIMPLUX_SELECTOR = "[SIMPLUX_SELECTOR]"; /** * A function with side-effects that can be easily mocked for testing. * * @public */ export declare type SimpluxEffect<TFunction extends (...args: any[]) => any> = FunctionSignature<TFunction> & SimpluxEffectMarker<TFunction> & SimpluxEffectMetadata; /** * The functions to turn into effects. * * @public */ export declare interface SimpluxEffectDefinitions { readonly [name: string]: (...args: any[]) => any; } /** * Interface for efficiently identifying simplux effect objects at compile time. * * @public */ export declare interface SimpluxEffectMarker<TFunction extends (...args: any[]) => any> { /** * A symbol that allows efficient compile-time and run-time identification * of simplux effect objects. * * This property will have an `undefined` value at runtime. * * @public */ readonly [SIMPLUX_EFFECT]: TFunction; } /** * @public */ export declare interface SimpluxEffectMetadata { /** * The name of this effect. */ readonly effectName: string; } /** * A collection of functions with side-effects that can be easily mocked for testing. * * @public */ export declare type SimpluxEffects<TEffectDefinitions extends SimpluxEffectDefinitions> = { [effectName in keyof TEffectDefinitions]: SimpluxEffect<TEffectDefinitions[effectName]>; }; /** * A simplux module that contains some state and allows controlled modification * and observation of the state. * * @public */ export declare interface SimpluxModule<TState> extends SimpluxModuleMarker<TState> { /** * A selector for getting the current module state. * * @returns the module state */ readonly state: SimpluxSelector<TState, [], Immutable<TState>>; /** * Replace the whole module state. * * @param state - the state to set for the module */ readonly setState: (state: Immutable<TState>) => void; /** * Register a handler to be called whenever the module's state * changes. The handler will be called immediately with the module's * current state when subscribing (can be changed by providing custom * options). * * @param handler - the function to call whenever the module's state changes * * @returns a subscription that can be unsubscribed from to remove the handler */ readonly subscribeToStateChanges: SubscribeToStateChanges<TState>; } /** * Configuration object for creating simplux modules. * * @public */ export declare interface SimpluxModuleConfig<TState> { readonly name: string; readonly initialState: TState; } /** * Interface for efficiently identifying simplux module objects at compile time. * * @public */ export declare interface SimpluxModuleMarker<TState> { /** * A symbol that allows efficient compile-time and run-time identification * of simplux module objects. * * This property will have an `undefined` value at runtime. * * @public */ readonly [SIMPLUX_MODULE]: TState; } /** * A simplux mutation is a function that updates a module's state. * * @public */ export declare interface SimpluxMutation<TState, TArgs extends any[]> extends SimpluxMutationMarker<TState, TArgs> { (...args: TArgs): TState; /** * The name of this mutation. */ readonly mutationName: string; /** * When a mutation is called directly it updates the module's state. * Sometimes (e.g. for testing) it is useful to call the mutation * with a given state. In this case no changes are made to the module. * * @param state - the state to use when executing the mutation * @param args - the arguments for the mutation * * @returns the updated state */ readonly withState: (state: TState, ...args: TArgs) => TState; /** * When a mutation is called directly it updates the module's state by * dispatching a redux action to the store. Sometimes it is useful to * instead handle the action yourself instead of having simplux dispatch * it automatically. This function returns the redux action instead of * dispatching it. * * @param args - the arguments for the mutation * * @returns a redux action object */ readonly asAction: (...args: TArgs) => { type: string; args: TArgs; }; } /** * Interface for efficiently identifying simplux mutation objects at compile time. * * @public */ export declare interface SimpluxMutationMarker<TState, TArgs extends any[]> { /** * A symbol that allows efficient compile-time and run-time identification * of simplux mutation objects. * * This property will have an `undefined` value at runtime. * * @public */ readonly [SIMPLUX_MUTATION]: [TState, TArgs]; } /** * A collection of simplux mutations. * * @public */ export declare type SimpluxMutations<TState, TMutations extends MutationDefinitions<TState>> = { readonly [name in keyof TMutations]: ResolvedMutation<TState, TMutations[name]>; }; /** * A simplux selector is a function that projects a module's state to some value. * * @public */ export declare interface SimpluxSelector<TState, TArgs extends any[], TReturn> extends SimpluxSelectorMarker<TState, TArgs, TReturn> { (...args: TArgs): TReturn; /** * The name of this selector. */ readonly selectorName: string; /** * By default a selector is evaluated with the module's latest state. * This function evaluates the selector with the given state instead. * * @param state - the state to use when evaluating the selector * @param args - the arguments for the selector * * @returns the selected value */ readonly withState: (state: Immutable<TState>, ...args: TArgs) => TReturn; } /** * Interface for efficiently identifying simplux selector objects at compile time. * * @public */ export declare interface SimpluxSelectorMarker<TState, TArgs extends any[], TReturn> { /** * A symbol that allows efficient compile-time and run-time identification * of simplux selector objects. * * This property will have an `undefined` value at runtime. * * @public */ readonly [SIMPLUX_SELECTOR]: [TState, TArgs, TReturn]; } /** * A collection of simplux selectors. * * @public */ export declare type SimpluxSelectors<TState, TSelectorDefinitions extends SelectorDefinitions<TState>> = { readonly [name in keyof TSelectorDefinitions]: ResolvedSelector<TState, TSelectorDefinitions[name]>; }; /** * A function that can be registered in a module to be notified of * module state changes. * * @param state - the current state of the module * @param previousState - the previous state of the module * * @public */ export declare type StateChangeHandler<TState> = (state: Immutable<TState>, previousState: Immutable<TState>) => void; /** * Configuration object for registering state change handlers. * * @public */ export declare interface StateChangeHandlerOptions { /** * By default a state change handler will be called with the module's * current state immediately after being registered. Setting this * property to true will skip that invocation and will only call the * handler as soon as the state changes. * * @defaultValue `false` */ readonly shouldSkipInitialInvocation?: boolean; } /** * A subscription for a state change handler. * * @public */ export declare interface StateChangeSubscription<TState, THandler extends StateChangeHandler<TState>> extends Subscription { /** * The handler function. Useful for testing. */ readonly handler: ResolvedStateChangeHandler<TState, THandler>; } /** * Subscribe to state changes. * * @param handler - the handler function to be called whenever the state changes * @param options - configuration for the subscription * * @returns a subscription that can be used to unsubscribe from state changes * * @public */ export declare type SubscribeToStateChanges<TState> = <THandler extends StateChangeHandler<TState>>(handler: THandler, options?: StateChangeHandlerOptions) => StateChangeSubscription<TState, THandler>; /** * An object that can be used to unsubscribe from a subscription (e.g. for a * state change handler). * * @public */ export declare interface Subscription { /** * Unsubscribe from the subscription. */ readonly unsubscribe: () => void; } /** * @public */ export declare type _WritableKeys<T> = { [P in keyof T]-?: _IfEquals<{ [Q in P]: T[P]; }, { -readonly [Q in P]: T[P]; }, P>; }[keyof T]; export { }