add subdux actions
This commit is contained in:
parent
d304fc0fcc
commit
5e39c2b162
21
src/Updux.ts
21
src/Updux.ts
@ -1,3 +1,4 @@
|
||||
import * as R from 'remeda';
|
||||
import {
|
||||
createStore as reduxCreateStore,
|
||||
applyMiddleware,
|
||||
@ -5,7 +6,8 @@ import {
|
||||
Action,
|
||||
} from 'redux';
|
||||
import { configureStore, Reducer, createAction } from '@reduxjs/toolkit';
|
||||
import { withPayload } from './actions';
|
||||
import { withPayload } from './actions.js';
|
||||
import { AggregateActions, Dux, UnionToIntersection } from './types.js';
|
||||
|
||||
type ActionCreator = ReturnType<typeof createAction>;
|
||||
|
||||
@ -20,6 +22,7 @@ type Mutation<A extends ActionCreator = ActionCreator, S = any> = (
|
||||
export default class Updux<
|
||||
T_LocalState = Record<any, any>,
|
||||
T_LocalActions = {},
|
||||
SUBDUXES extends Record<string, Dux> = {},
|
||||
> {
|
||||
#localInitial: T_LocalState;
|
||||
#localActions: T_LocalActions;
|
||||
@ -27,16 +30,28 @@ export default class Updux<
|
||||
string,
|
||||
Mutation<ActionCreator, AggregateState<T_LocalState>>
|
||||
> = {};
|
||||
#subduxes: SUBDUXES;
|
||||
|
||||
#actions: Record<string, ActionCreator>;
|
||||
|
||||
constructor(
|
||||
config: Partial<{
|
||||
initial: T_LocalState;
|
||||
actions: T_LocalActions;
|
||||
subduxes: SUBDUXES;
|
||||
}>,
|
||||
) {
|
||||
// TODO check that we can't alter the initial after the fact
|
||||
this.#localInitial = config.initial ?? ({} as T_LocalState);
|
||||
this.#localActions = config.actions ?? ({} as T_LocalActions);
|
||||
this.#subduxes = config.subduxes ?? ({} as SUBDUXES);
|
||||
}
|
||||
|
||||
get actions(): AggregateActions<T_LocalActions, SUBDUXES> {
|
||||
return R.mergeAll([
|
||||
this.#localActions,
|
||||
...Object.values(this.#subduxes).map(R.pathOr(['actions'], {})),
|
||||
]) as any;
|
||||
}
|
||||
|
||||
// TODO memoize?
|
||||
@ -44,10 +59,6 @@ export default class Updux<
|
||||
return this.#localInitial;
|
||||
}
|
||||
|
||||
get actions() {
|
||||
return this.#localActions;
|
||||
}
|
||||
|
||||
createStore(
|
||||
options: Partial<{
|
||||
initial: T_LocalState;
|
||||
|
@ -34,23 +34,6 @@ test('Updux config accepts actions', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('subduxes actions', () => {
|
||||
const foo = new Updux({
|
||||
actions: {
|
||||
foo: null,
|
||||
},
|
||||
subduxes: {
|
||||
beta: {
|
||||
actions: {
|
||||
bar: null,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(foo.actions).toHaveProperty('foo');
|
||||
expect(foo.actions).toHaveProperty('bar');
|
||||
});
|
||||
|
||||
test('throw if double action', () => {
|
||||
expect(
|
||||
|
27
src/actions.test.ts
Normal file
27
src/actions.test.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import Updux, { createAction } from './index.js';
|
||||
|
||||
test('subduxes actions', () => {
|
||||
const bar = createAction<number>('bar');
|
||||
const baz = createAction('baz');
|
||||
|
||||
const foo = new Updux({
|
||||
actions: {
|
||||
bar,
|
||||
},
|
||||
subduxes: {
|
||||
beta: {
|
||||
actions: {
|
||||
baz,
|
||||
},
|
||||
},
|
||||
// to check if we can deal with empty actions
|
||||
gamma: {},
|
||||
},
|
||||
});
|
||||
|
||||
expect(foo.actions).toHaveProperty('bar');
|
||||
expect(foo.actions).toHaveProperty('baz');
|
||||
|
||||
expect(foo.actions.bar(2)).toHaveProperty('type', 'bar');
|
||||
expect(foo.actions.baz()).toHaveProperty('type', 'baz');
|
||||
});
|
@ -1,5 +1,7 @@
|
||||
import { createAction } from '@reduxjs/toolkit';
|
||||
|
||||
export { createAction } from '@reduxjs/toolkit';
|
||||
|
||||
export const withPayload =
|
||||
<P>() =>
|
||||
(payload: P) => ({ payload });
|
||||
(payload: P) => ({ payload });
|
||||
|
@ -1,5 +1,5 @@
|
||||
import Updux from './Updux';
|
||||
import Updux from './Updux.js';
|
||||
|
||||
export { withPayload, createAction } from './actions';
|
||||
export { withPayload, createAction } from './actions.js';
|
||||
|
||||
export default Updux;
|
||||
|
21
src/types.ts
Normal file
21
src/types.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import { Action, ActionCreator } from 'redux';
|
||||
|
||||
export type Dux<
|
||||
STATE = any,
|
||||
ACTIONS extends Record<string, ActionCreator<string>> = {},
|
||||
> = Partial<{
|
||||
initial: STATE;
|
||||
actions: ACTIONS;
|
||||
}>;
|
||||
|
||||
type ActionsOf<DUX> = DUX extends { actions: infer A } ? A : {};
|
||||
|
||||
export type AggregateActions<A, S> = UnionToIntersection<
|
||||
ActionsOf<S[keyof S]> | A
|
||||
>;
|
||||
|
||||
export type UnionToIntersection<U> = (
|
||||
U extends any ? (k: U) => void : never
|
||||
) extends (k: infer I) => void
|
||||
? I
|
||||
: never;
|
Loading…
Reference in New Issue
Block a user