Merge branch 'upreducerWrapper' into return-to-ts
This commit is contained in:
commit
541790425a
49
src/Updux.ts
49
src/Updux.ts
@ -11,7 +11,14 @@ import { action } from './actions';
|
|||||||
import { buildUpreducer } from './buildUpreducer';
|
import { buildUpreducer } from './buildUpreducer';
|
||||||
import { buildMiddleware, augmentMiddlewareApi } from './buildMiddleware';
|
import { buildMiddleware, augmentMiddlewareApi } from './buildMiddleware';
|
||||||
|
|
||||||
import { AggregateDuxActions, AggregateDuxState, Dict } from './types';
|
import {
|
||||||
|
AggregateDuxActions,
|
||||||
|
AggregateDuxState,
|
||||||
|
Dict,
|
||||||
|
ItemsOf,
|
||||||
|
Reducer,
|
||||||
|
Upreducer,
|
||||||
|
} from './types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configuration object typically passed to the constructor of the class Updux.
|
* Configuration object typically passed to the constructor of the class Updux.
|
||||||
@ -70,6 +77,28 @@ export interface UpduxConfig<
|
|||||||
* reaction for the mapped dux.
|
* reaction for the mapped dux.
|
||||||
*/
|
*/
|
||||||
mappedReaction?: Function | boolean;
|
mappedReaction?: Function | boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapping function for the upreducer to provides full customization.
|
||||||
|
* @example
|
||||||
|
* // if an action has the 'dontDoIt' meta flag, don't do anything
|
||||||
|
* const dux = new Updux({
|
||||||
|
* ...,
|
||||||
|
* upreducerWrapper: (upreducer) => action => {
|
||||||
|
* if( action?.meta?.dontDoIt ) return state => state;
|
||||||
|
* return upreducer(action);
|
||||||
|
* }
|
||||||
|
* })
|
||||||
|
*/
|
||||||
|
upreducerWrapper?: (
|
||||||
|
upreducer: Upreducer<
|
||||||
|
AggregateDuxState<TState, TSubduxes>,
|
||||||
|
ItemsOf<AggregateDuxActions<TActions, TSubduxes>>
|
||||||
|
>
|
||||||
|
) => Upreducer<
|
||||||
|
AggregateDuxState<TState, TSubduxes>,
|
||||||
|
ItemsOf<AggregateDuxActions<TActions, TSubduxes>>
|
||||||
|
>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Updux<
|
export class Updux<
|
||||||
@ -90,6 +119,7 @@ export class Updux<
|
|||||||
#reactions = [];
|
#reactions = [];
|
||||||
#mappedSelectors = undefined;
|
#mappedSelectors = undefined;
|
||||||
#mappedReaction = undefined;
|
#mappedReaction = undefined;
|
||||||
|
#upreducerWrapper = undefined;
|
||||||
|
|
||||||
constructor(config: UpduxConfig<TState, TActions, TSelectors, TSubduxes>) {
|
constructor(config: UpduxConfig<TState, TActions, TSelectors, TSubduxes>) {
|
||||||
this.#initial = config.initial ?? {};
|
this.#initial = config.initial ?? {};
|
||||||
@ -130,6 +160,8 @@ export class Updux<
|
|||||||
this.#reactions = config.reactions ?? [];
|
this.#reactions = config.reactions ?? [];
|
||||||
|
|
||||||
this.#mappedReaction = config.mappedReaction;
|
this.#mappedReaction = config.mappedReaction;
|
||||||
|
|
||||||
|
this.#upreducerWrapper = config.upreducerWrapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
#memoInitial = moize(buildInitial);
|
#memoInitial = moize(buildInitial);
|
||||||
@ -171,15 +203,22 @@ export class Updux<
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
get upreducer() {
|
get upreducer(): Upreducer<
|
||||||
|
AggregateDuxState<TState, TSubduxes>,
|
||||||
|
ItemsOf<AggregateDuxActions<TActions, TSubduxes>>
|
||||||
|
> {
|
||||||
return this.#memoUpreducer(
|
return this.#memoUpreducer(
|
||||||
this.initial,
|
this.initial,
|
||||||
this.#mutations,
|
this.#mutations,
|
||||||
this.#subduxes
|
this.#subduxes,
|
||||||
|
this.#upreducerWrapper
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
get reducer() {
|
get reducer(): Reducer<
|
||||||
|
AggregateDuxState<TState, TSubduxes>,
|
||||||
|
ItemsOf<AggregateDuxActions<TActions, TSubduxes>>
|
||||||
|
> {
|
||||||
return (state, action) => this.upreducer(action)(state);
|
return (state, action) => this.upreducer(action)(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -340,7 +379,7 @@ export class Updux<
|
|||||||
selectors: Record<string, Function>;
|
selectors: Record<string, Function>;
|
||||||
actions: AggregateDuxActions<TActions, TSubduxes>;
|
actions: AggregateDuxActions<TActions, TSubduxes>;
|
||||||
} = reduxCreateStore(
|
} = reduxCreateStore(
|
||||||
this.reducer,
|
this.reducer as any,
|
||||||
initial ?? this.initial,
|
initial ?? this.initial,
|
||||||
enhancer
|
enhancer
|
||||||
) as any;
|
) as any;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
export type Action<T extends string = string, TPayload = unknown> = {
|
export type Action<T extends string = string, TPayload = any> = {
|
||||||
type: T;
|
type: T;
|
||||||
meta?: Record<string, unknown>;
|
meta?: Record<string, unknown>;
|
||||||
} & {
|
} & {
|
||||||
|
@ -1,13 +1,18 @@
|
|||||||
import u from 'updeep';
|
import u from 'updeep';
|
||||||
import { mapValues } from 'lodash';
|
import { mapValues } from 'lodash';
|
||||||
|
|
||||||
export function buildUpreducer(initial, mutations, subduxes = {}) {
|
export function buildUpreducer(
|
||||||
|
initial,
|
||||||
|
mutations,
|
||||||
|
subduxes = {},
|
||||||
|
wrapper = undefined
|
||||||
|
) {
|
||||||
const subReducers =
|
const subReducers =
|
||||||
Object.keys(subduxes).length > 0
|
Object.keys(subduxes).length > 0
|
||||||
? mapValues(subduxes, ({ upreducer }) => upreducer)
|
? mapValues(subduxes, ({ upreducer }) => upreducer)
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
return (action) => (state) => {
|
const upreducer = (action) => (state) => {
|
||||||
if (!action?.type)
|
if (!action?.type)
|
||||||
throw new Error('upreducer called with a bad action');
|
throw new Error('upreducer called with a bad action');
|
||||||
|
|
||||||
@ -35,4 +40,6 @@ export function buildUpreducer(initial, mutations, subduxes = {}) {
|
|||||||
|
|
||||||
return a(action.payload, action)(newState);
|
return a(action.payload, action)(newState);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
return wrapper ? wrapper(upreducer) : upreducer;
|
||||||
}
|
}
|
||||||
|
13
src/types.ts
13
src/types.ts
@ -1,5 +1,16 @@
|
|||||||
|
import { Action } from './actions';
|
||||||
|
|
||||||
export type Dict<T> = Record<string, T>;
|
export type Dict<T> = Record<string, T>;
|
||||||
|
|
||||||
|
export type Upreducer<TState = any, TAction = Action> = (
|
||||||
|
action: Action
|
||||||
|
) => (state: TState) => TState;
|
||||||
|
|
||||||
|
export type Reducer<TState = any, TAction = Action> = (
|
||||||
|
state: TState | undefined,
|
||||||
|
action: Action
|
||||||
|
) => TState;
|
||||||
|
|
||||||
export type UnionToIntersection<U> = (
|
export type UnionToIntersection<U> = (
|
||||||
U extends any ? (k: U) => void : never
|
U extends any ? (k: U) => void : never
|
||||||
) extends (k: infer I) => void
|
) extends (k: infer I) => void
|
||||||
@ -31,7 +42,7 @@ export type AggregateDuxState<TState, TSubduxes> = TState &
|
|||||||
|
|
||||||
type DuxActionsSubduxes<C> = C extends object ? ActionsOf<C[keyof C]> : unknown;
|
type DuxActionsSubduxes<C> = C extends object ? ActionsOf<C[keyof C]> : unknown;
|
||||||
|
|
||||||
type ItemsOf<C> = C extends object ? C[keyof C] : unknown;
|
export type ItemsOf<C> = C extends object ? C[keyof C] : unknown;
|
||||||
|
|
||||||
export type AggregateDuxActions<TActions, TSubduxes> = TActions &
|
export type AggregateDuxActions<TActions, TSubduxes> = TActions &
|
||||||
UnionToIntersection<ActionsOf<ItemsOf<TSubduxes>>>;
|
UnionToIntersection<ActionsOf<ItemsOf<TSubduxes>>>;
|
||||||
|
Loading…
Reference in New Issue
Block a user