diff --git a/src/Updux.ts b/src/Updux.ts index 7aad5e3..9fd7513 100644 --- a/src/Updux.ts +++ b/src/Updux.ts @@ -8,6 +8,7 @@ import { import { configureStore, Reducer, createAction } from '@reduxjs/toolkit'; import { withPayload } from './actions.js'; import { AggregateActions, Dux, UnionToIntersection } from './types.js'; +import { buildActions } from './buildActions.js'; type ActionCreator = ReturnType; @@ -32,7 +33,9 @@ export default class Updux< > = {}; #subduxes: SUBDUXES; - #actions: Record; + #name: string; + + #actions: AggregateActions; constructor( config: Partial<{ @@ -45,13 +48,12 @@ export default class Updux< this.#localInitial = config.initial ?? ({} as T_LocalState); this.#localActions = config.actions ?? ({} as T_LocalActions); this.#subduxes = config.subduxes ?? ({} as SUBDUXES); + + this.#actions = buildActions(this.#localActions, this.#subduxes); } - get actions(): AggregateActions { - return R.mergeAll([ - this.#localActions, - ...Object.values(this.#subduxes).map(R.pathOr(['actions'], {})), - ]) as any; + get actions() { + return this.#actions; } // TODO memoize? diff --git a/src/actions.test.todo b/src/actions.test.todo index 174cfa2..e17edf4 100644 --- a/src/actions.test.todo +++ b/src/actions.test.todo @@ -7,24 +7,6 @@ import { Updux } from './Updux.js'; -test('throw if double action', () => { - expect( - () => - new Updux({ - actions: { - foo: action('foo'), - }, - subduxes: { - beta: { - actions: { - foo: action('foo'), - }, - }, - }, - }), - ).toThrow(/action 'foo' already defined/); -}); - test('action definition shortcut', () => { const foo = new Updux({ actions: { diff --git a/src/actions.test.ts b/src/actions.test.ts index 99fdeb9..c39b8be 100644 --- a/src/actions.test.ts +++ b/src/actions.test.ts @@ -64,3 +64,39 @@ test('Updux config accepts actions', () => { }, }); }); + +test('throw if double action', () => { + expect( + () => + new Updux({ + actions: { + foo: createAction('foo'), + }, + subduxes: { + beta: { + actions: { + foo: createAction('foo'), + }, + }, + }, + }), + ).toThrow(/action 'foo' defined both locally and in subdux 'beta'/); + + expect( + () => + new Updux({ + subduxes: { + gamma: { + actions: { + foo: createAction('foo'), + }, + }, + beta: { + actions: { + foo: createAction('foo'), + }, + }, + }, + }), + ).toThrow(/action 'foo' defined both in subduxes 'gamma' and 'beta'/); +}); diff --git a/src/actions.ts b/src/actions.ts index 9bd5453..f8d7dcf 100644 --- a/src/actions.ts +++ b/src/actions.ts @@ -3,7 +3,7 @@ import { createAction } from '@reduxjs/toolkit'; export { createAction } from '@reduxjs/toolkit'; interface WithPayload { - ():

(input: P) => { payload: P }; +

(): (input: P) => { payload: P }; (prepare: (...args: A) => P): (...input: A) => { payload: P; }; @@ -11,5 +11,5 @@ interface WithPayload { export const withPayload: WithPayload = ((prepare) => (...input) => ({ - payload: prepare ? prepare(...input) : input, + payload: prepare ? prepare(...input) : input[0], })) as any; diff --git a/src/buildActions.ts b/src/buildActions.ts new file mode 100644 index 0000000..21f0cef --- /dev/null +++ b/src/buildActions.ts @@ -0,0 +1,33 @@ +import * as R from 'remeda'; + +export function buildActions(localActions, subduxes) { + let actions: Record = {}; + + for (const slice in subduxes) { + const subdux = subduxes[slice].actions; + + if (!subdux) continue; + + for (const a in subdux) { + if (actions[a]) { + throw new Error( + `action '${a}' defined both in subduxes '${actions[a]}' and '${slice}'`, + ); + } + actions[a] = slice; + } + } + + for (const a in localActions) { + if (actions[a]) { + throw new Error( + `action '${a}' defined both locally and in subdux '${actions[a]}'`, + ); + } + } + + return R.mergeAll([ + localActions, + ...Object.values(subduxes).map(R.pathOr(['actions'], {})), + ]) as any; +}