94 lines
2.7 KiB
TypeScript
94 lines
2.7 KiB
TypeScript
import { Action, ActionCreator, createAction } from '@reduxjs/toolkit';
|
|
import { BaseActionCreator } from '@reduxjs/toolkit/dist/createAction.js';
|
|
import * as R from 'remeda';
|
|
import { Dux } from './types.js';
|
|
import { Mutation } from './Updux.js';
|
|
import u from '@yanick/updeep-remeda';
|
|
|
|
export type MutationCase = {
|
|
matcher: (action: Action) => boolean;
|
|
mutation: Mutation;
|
|
terminal: boolean;
|
|
};
|
|
|
|
export function buildReducer(
|
|
initialState: any,
|
|
mutations: MutationCase[] = [],
|
|
defaultMutation?: Omit<MutationCase, 'matcher'>,
|
|
subduxes: Record<string, Dux> = {},
|
|
) {
|
|
const subReducers = R.mapValues(subduxes, R.prop('reducer'));
|
|
|
|
// TODO matcherMutation
|
|
// TODO defaultMutation
|
|
//
|
|
const reducer = (state = initialState, action: Action) => {
|
|
const orig = state;
|
|
if (!action?.type)
|
|
throw new Error('upreducer called with a bad action');
|
|
|
|
let terminal = false;
|
|
let didSomething = false;
|
|
|
|
mutations
|
|
.filter(({ matcher }) => matcher(action))
|
|
.forEach(({ mutation, terminal: t }) => {
|
|
if (t) terminal = true;
|
|
didSomething = true;
|
|
//
|
|
// TODO wrap mutations in immer
|
|
state = mutation((action as any).payload, action)(state);
|
|
});
|
|
|
|
if (!didSomething && defaultMutation) {
|
|
if (defaultMutation.terminal) terminal = true;
|
|
|
|
state = defaultMutation.mutation(
|
|
(action as any).payload,
|
|
action,
|
|
)(state);
|
|
}
|
|
|
|
if (!terminal && Object.keys(subduxes).length > 0) {
|
|
// subduxes
|
|
state = u.update(
|
|
state,
|
|
R.mapValues(subReducers, (reducer, slice) =>
|
|
(reducer as any)(state[slice], action),
|
|
),
|
|
);
|
|
}
|
|
|
|
return state;
|
|
};
|
|
|
|
return reducer;
|
|
|
|
/*
|
|
if (subReducers) {
|
|
if (subduxes['*']) {
|
|
newState = u.updateIn(
|
|
'*',
|
|
subduxes['*'].upreducer(action),
|
|
newState,
|
|
);
|
|
} else {
|
|
const update = mapValues(subReducers, (upReducer) =>
|
|
upReducer(action),
|
|
);
|
|
|
|
newState = u(update, newState);
|
|
}
|
|
}
|
|
|
|
const a = mutations[action.type] || mutations['+'];
|
|
|
|
if (!a) return newState;
|
|
|
|
return a(action.payload, action)(newState);
|
|
};
|
|
|
|
return wrapper ? wrapper(upreducer) : upreducer;
|
|
*/
|
|
}
|