@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
TypeScript
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 { }