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( initialStateState: any, mutations: MutationCase[] = [], defaultMutation?: Omit, subduxes: Record = {}, ) { const subReducers = R.mapValues(subduxes, R.prop('reducer')); // TODO matcherMutation // TODO defaultMutation // const reducer = (state = initialStateState, 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; */ }