defaultMutation
This commit is contained in:
parent
2e03a51e15
commit
76ccd0d14a
20
src/Updux.ts
20
src/Updux.ts
@ -15,7 +15,7 @@ import {
|
|||||||
import { AggregateActions, Dux } from './types.js';
|
import { AggregateActions, Dux } from './types.js';
|
||||||
import { buildActions } from './buildActions.js';
|
import { buildActions } from './buildActions.js';
|
||||||
import { buildInitial, AggregateState } from './initial.js';
|
import { buildInitial, AggregateState } from './initial.js';
|
||||||
import { buildReducer } from './reducer.js';
|
import { buildReducer, MutationCase } from './reducer.js';
|
||||||
|
|
||||||
type MyActionCreator = { type: string } & ((...args: any) => any);
|
type MyActionCreator = { type: string } & ((...args: any) => any);
|
||||||
|
|
||||||
@ -61,6 +61,7 @@ export default class Updux<
|
|||||||
#localInitial: T_LocalState;
|
#localInitial: T_LocalState;
|
||||||
#localActions: T_LocalActions;
|
#localActions: T_LocalActions;
|
||||||
#localMutations: MutationCase[] = [];
|
#localMutations: MutationCase[] = [];
|
||||||
|
#defaultMutation: Omit<MutationCase, 'matcher'>;
|
||||||
#subduxes: T_Subduxes;
|
#subduxes: T_Subduxes;
|
||||||
|
|
||||||
#name: string;
|
#name: string;
|
||||||
@ -111,12 +112,17 @@ export default class Updux<
|
|||||||
|
|
||||||
// TODO memoize this sucker
|
// TODO memoize this sucker
|
||||||
get reducer() {
|
get reducer() {
|
||||||
return buildReducer(this.initial, this.#localMutations) as any as (
|
return buildReducer(
|
||||||
|
this.initial,
|
||||||
|
this.#localMutations,
|
||||||
|
this.#defaultMutation,
|
||||||
|
) as any as (
|
||||||
state: undefined | typeof this.initial,
|
state: undefined | typeof this.initial,
|
||||||
action: Action,
|
action: Action,
|
||||||
) => typeof this.initial;
|
) => typeof this.initial;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO be smarter with the guard?
|
||||||
addMutation<A extends Action<any>>(
|
addMutation<A extends Action<any>>(
|
||||||
matcher: (action: A) => boolean,
|
matcher: (action: A) => boolean,
|
||||||
mutation: Mutation<A, AggregateState<T_LocalState, T_Subduxes>>,
|
mutation: Mutation<A, AggregateState<T_LocalState, T_Subduxes>>,
|
||||||
@ -142,4 +148,14 @@ export default class Updux<
|
|||||||
mutation,
|
mutation,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addDefaultMutation(
|
||||||
|
mutation: Mutation<
|
||||||
|
Action<any>,
|
||||||
|
AggregateState<T_LocalState, T_Subduxes>
|
||||||
|
>,
|
||||||
|
terminal = false,
|
||||||
|
) {
|
||||||
|
this.#defaultMutation = { mutation, terminal };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,3 +37,19 @@ test('catch-all mutation', () => {
|
|||||||
|
|
||||||
expect(dux.reducer(undefined, { type: 'foo' })).toEqual('got it');
|
expect(dux.reducer(undefined, { type: 'foo' })).toEqual('got it');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('default mutation', () => {
|
||||||
|
const dux = new Updux({
|
||||||
|
initial: '',
|
||||||
|
actions: {
|
||||||
|
foo: 0,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
dux.addMutation(dux.actions.foo, () => () => 'got it');
|
||||||
|
|
||||||
|
dux.addDefaultMutation((_payload, action) => () => action.type);
|
||||||
|
|
||||||
|
expect(dux.reducer(undefined, { type: 'foo' })).toEqual('got it');
|
||||||
|
expect(dux.reducer(undefined, { type: 'bar' })).toEqual('bar');
|
||||||
|
});
|
||||||
|
@ -13,6 +13,7 @@ export type MutationCase = {
|
|||||||
export function buildReducer(
|
export function buildReducer(
|
||||||
initialState: any,
|
initialState: any,
|
||||||
mutations: MutationCase[] = [],
|
mutations: MutationCase[] = [],
|
||||||
|
defaultMutation?: Omit<MutationCase, 'matcher'>,
|
||||||
subduxes: Record<string, Dux> = {},
|
subduxes: Record<string, Dux> = {},
|
||||||
) {
|
) {
|
||||||
// const subReducers =
|
// const subReducers =
|
||||||
@ -32,12 +33,20 @@ export function buildReducer(
|
|||||||
.filter(({ matcher }) => matcher(action))
|
.filter(({ matcher }) => matcher(action))
|
||||||
.forEach(({ mutation, terminal: t }) => {
|
.forEach(({ mutation, terminal: t }) => {
|
||||||
if (t) terminal = true;
|
if (t) terminal = true;
|
||||||
|
didSomething = true;
|
||||||
//
|
//
|
||||||
// TODO wrap mutations in immer
|
// TODO wrap mutations in immer
|
||||||
state = mutation((action as any).payload, action)(state);
|
state = mutation((action as any).payload, action)(state);
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO defaultMutation
|
if (!didSomething && defaultMutation) {
|
||||||
|
if (defaultMutation.terminal) terminal = true;
|
||||||
|
|
||||||
|
state = defaultMutation.mutation(
|
||||||
|
(action as any).payload,
|
||||||
|
action,
|
||||||
|
)(state);
|
||||||
|
}
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user