redux-logic
Version:
Redux middleware for organizing all your business logic. Intercept actions and perform async processing.
309 lines (266 loc) • 9.09 kB
TypeScript
/*
* *** MIT LICENSE ***
* -------------------------------------------------------------------------
* This code may be modified and distributed under the MIT license.
* See the LICENSE file for details.
* -------------------------------------------------------------------------
*
* @summary Definitions for redux-logic
*
* @author Alvis HT Tang <alvis@hilbert.space>
* @license MIT
* @copyright Copyright (c) 2018 - All Rights Reserved.
* -------------------------------------------------------------------------
*/
import { Observable, Subject } from 'rxjs';
import { Middleware } from 'redux';
import { ArgumentAction, Action, ActionBasis, StandardAction } from './action';
import { Object, Override } from './utilities';
//
// LOGIC
//
/* * * * * *
| State is the type of the state stored in redux |
| Payload is the type of the payload of the handled action |
| Meta is the type of the meta object of the handled action |
| Dependency is the type of depObj excluding getState/action |
| Context is the type of the ctx object |
| Type is the type of the handled action |
* * * * * */
export type Logic<
State extends object = {},
Payload extends Object = undefined,
Meta extends Object = undefined,
Dependency extends object = {},
Context extends Object = undefined,
Type extends string = string
> = Override<
CreateLogic.Config<
State,
Action<Type, Payload, Meta>,
Dependency,
Context,
Type
>,
{
name: string;
type: string;
cancelType: string;
}
>;
/* ----- createLogic ----- */
export declare const createLogic: CreateLogic;
export interface CreateLogic {
// full createLogic declaration
<
State extends object,
Payload extends Object = undefined,
Meta extends Object = undefined,
Dependency extends object = {},
Context extends Object = undefined,
Type extends string = string,
Action extends StandardAction<Type, Payload, Meta> = StandardAction<Type, Payload, Meta>,
>(
config: CreateLogic.Config<
State,
Action,
Dependency,
Context,
Type
>
): Logic<State, Payload, Meta, Dependency, Context, Type>;
// createLogic wihout context
<
State extends object,
Payload extends Object = undefined,
Meta extends Object = undefined,
Dependency extends object = {},
Type extends string = string,
Action extends StandardAction<Type, Payload, Meta> = StandardAction<Type, Payload, Meta>,
>(
config: CreateLogic.Config<
State,
Action,
Dependency,
undefined,
Type
>
): Logic<State, Payload, Meta, Dependency, undefined, Type>;
// createLogic wihout payload and meta
<
State extends object,
Dependency extends object = {},
Context extends Object = undefined,
Type extends string = string,
Action extends StandardAction<Type> = StandardAction<Type>
>(
config: CreateLogic.Config<State, Action, Dependency, Context, Type>
): Logic<State, undefined, undefined, Dependency, Context, Type>;
// createLogic with State and Type only
<State extends object, Type extends string = string, Action extends StandardAction<Type> = StandardAction<Type>>(
config: CreateLogic.Config<State, Action, {}, undefined, Type>
): Logic<State, undefined, undefined, {}, undefined, Type>;
// createLogic with State, Dependency and Type only
<
State extends object,
Dependency extends object = {},
Type extends string = string,
Action extends StandardAction<Type> = StandardAction<Type>
>(
config: CreateLogic.Config<State, Action, Dependency, undefined, Type>
): Logic<State, undefined, undefined, Dependency, undefined, Type>;
}
export namespace CreateLogic {
export type Config<
State extends object,
Action extends StandardAction,
Dependency extends object,
Context extends Object,
Type extends string
> = Config.Base<State, Action, Type> &
(
| Config.Validate<State, Action, Dependency, Context>
| Config.Transform<State, Action, Dependency, Context>) &
(Config.Process<State, Action, Dependency, Context>);
export namespace Config {
/* ----- common ----- */
export type DepObj<State, Action, Dependency> = Dependency & {
getState(): State;
action: Action;
action$: Observable<Action>;
};
export type ActionCreatorType<Action extends StandardAction> = {
(payload: PayloadExtractor<Action>): Action;
toString(): string;
}
export type PrimitiveType<Type extends string | symbol, InputPayload> =
| Type
| RegExp
| Function;
export type TypeMatcher<
Type extends string | symbol,
Payload extends Object
> = PrimitiveType<Type, Payload> | PrimitiveType<Type, Payload>[];
export type Pass<Action extends ActionBasis, Context extends Object> = (
action: ArgumentAction &
(Context extends undefined
? {}
: (Context extends undefined ? { ctx?: Context } : { ctx: Context })),
options?: {
useDispatch: boolean | 'auto';
}
) => void;
export interface Base<
State extends object,
Action extends StandardAction,
Type extends string
> {
name?: string | Function;
type: TypeMatcher<Type, PayloadExtractor<Action>> | ActionCreatorType<Action>;
cancelType?: TypeMatcher<string, PayloadExtractor<Action>>;
latest?: boolean;
debounce?: number;
throttle?: number;
warnTimeout?: number;
}
// ---------------------------------------- //
/* ----- validate ----- */
interface Validate<
State,
Action extends ActionBasis,
Dependency extends object,
Context extends Object
> {
validate?: Validate.Hook<State, Action, Dependency, Context>;
}
export namespace Validate {
export type Hook<
State,
Action extends ActionBasis,
Dependency extends object,
Context extends Object = undefined
> = (
depObj: DepObj<State, Action, Dependency>,
allow: Pass<Action, Context>,
reject: Pass<Action, Context>
) => void;
}
// ---------------------------------------- //
/* ----- transform ----- */
interface Transform<
State,
Action extends ActionBasis,
Dependency extends object,
Context extends Object
> {
transform?: Transform.Hook<State, Action, Dependency, Context>;
}
export namespace Transform {
export type Hook<
State,
Action extends ActionBasis,
Dependency extends object,
Context extends Object = undefined
> = (
depObj: DepObj<State, Action, Dependency>,
next: Pass<Action, Context>,
reject?: Pass<Action, Context>
) => void;
}
// ---------------------------------------- //
/* ----- process ----- */
type ActionCreator<
InputPayload extends Object
> = InputPayload extends undefined
? (payload?: InputPayload) => StandardAction<string, any>
: (InputPayload extends Error
? (error?: Error) => Action<string, any>
: (payload?: InputPayload) => Action<string, any>);
type PayloadExtractor<
Action extends StandardAction
> = Action extends StandardAction<infer Type, infer Payload>
? Payload
: undefined;
export interface Process<
State extends object,
Action extends StandardAction<string>,
Dependency extends object,
Context extends Object = undefined
> {
processOptions?: Process.Options<Action>;
process?: Process.Hook<State, Action, Dependency, Context>;
}
export namespace Process {
export interface Options<Action extends StandardAction> {
dispatchReturn?: boolean;
dispatchMultiple?: boolean;
successType?: string | ActionCreator<PayloadExtractor<Action>>;
failType?: string | ActionCreator<Error>;
}
export type DepObj<
State extends object,
Action extends StandardAction,
Dependency extends object,
Context extends Object = undefined
> = Config.DepObj<State, Action, Dependency> & {
cancelled$: Subject<void>;
ctx: Context;
};
export type Hook<
State extends object,
Action extends StandardAction,
Dependency extends object,
Context extends Object = undefined
> = ((
depObj: Process.DepObj<State, Action, Dependency, Context>,
dispatch: <T extends ArgumentAction>(action: T) => T,
done: () => void
) => void);
}
// ---------------------------------------- //
}
}
// ---------------------------------------- //
/* ----- configureLogic ----- */
export function configureLogic(options: { warnTimeout?: number }): void;
// ---------------------------------------- //