holy heck the action shortcuts work
This commit is contained in:
parent
1a2b2df9ac
commit
9ac3032a7f
47
src/Updux.ts
47
src/Updux.ts
@ -9,17 +9,46 @@ import {
|
|||||||
configureStore,
|
configureStore,
|
||||||
Reducer,
|
Reducer,
|
||||||
createAction,
|
createAction,
|
||||||
|
ActionCreator,
|
||||||
PrepareAction,
|
PrepareAction,
|
||||||
|
ActionCreatorWithPayload,
|
||||||
|
ActionCreatorWithoutPayload,
|
||||||
|
ActionCreatorWithPreparedPayload,
|
||||||
} from '@reduxjs/toolkit';
|
} from '@reduxjs/toolkit';
|
||||||
import { withPayload } from './actions.js';
|
import { withPayload } from './actions.js';
|
||||||
import { AggregateActions, Dux, UnionToIntersection } from './types.js';
|
import { AggregateActions, Dux, UnionToIntersection } from './types.js';
|
||||||
import { buildActions } from './buildActions.js';
|
import { buildActions } from './buildActions.js';
|
||||||
|
|
||||||
type ActionCreator = ReturnType<typeof createAction>;
|
|
||||||
|
|
||||||
type AggregateState<L> = L;
|
type AggregateState<L> = L;
|
||||||
|
|
||||||
type Mutation<A extends ActionCreator = ActionCreator, S = any> = (
|
type MyActionCreator = { type: string } & ((...args: any) => any);
|
||||||
|
|
||||||
|
type F = null extends any ? 'u' : 'n';
|
||||||
|
|
||||||
|
type ResolveAction<
|
||||||
|
ActionType extends string,
|
||||||
|
ActionArg extends any,
|
||||||
|
> = ActionArg extends MyActionCreator
|
||||||
|
? ActionArg
|
||||||
|
: ActionArg extends (...args: any) => any
|
||||||
|
? ActionCreatorWithPreparedPayload<
|
||||||
|
Parameters<ActionArg>,
|
||||||
|
ReturnType<ActionArg>,
|
||||||
|
ActionType
|
||||||
|
>
|
||||||
|
: ActionCreatorWithoutPayload<ActionType>;
|
||||||
|
|
||||||
|
type ResolveActions<
|
||||||
|
A extends {
|
||||||
|
[key: string]: any;
|
||||||
|
},
|
||||||
|
> = {
|
||||||
|
[ActionType in keyof A]: ActionType extends string
|
||||||
|
? ResolveAction<ActionType, A[ActionType]>
|
||||||
|
: never;
|
||||||
|
};
|
||||||
|
|
||||||
|
type Mutation<A extends ActionCreator<any> = ActionCreator<any>, S = any> = (
|
||||||
state: S,
|
state: S,
|
||||||
payload: ReturnType<A>['payload'],
|
payload: ReturnType<A>['payload'],
|
||||||
action: ReturnType<A>,
|
action: ReturnType<A>,
|
||||||
@ -27,20 +56,22 @@ type Mutation<A extends ActionCreator = ActionCreator, S = any> = (
|
|||||||
|
|
||||||
export default class Updux<
|
export default class Updux<
|
||||||
T_LocalState = Record<any, any>,
|
T_LocalState = Record<any, any>,
|
||||||
T_LocalActions = {},
|
T_LocalActions extends {
|
||||||
|
[actionType: string]: any;
|
||||||
|
} = {},
|
||||||
SUBDUXES extends Record<string, Dux> = {},
|
SUBDUXES extends Record<string, Dux> = {},
|
||||||
> {
|
> {
|
||||||
#localInitial: T_LocalState;
|
#localInitial: T_LocalState;
|
||||||
#localActions: T_LocalActions;
|
#localActions: T_LocalActions;
|
||||||
#localMutations: Record<
|
#localMutations: Record<
|
||||||
string,
|
string,
|
||||||
Mutation<ActionCreator, AggregateState<T_LocalState>>
|
Mutation<ActionCreator<any>, AggregateState<T_LocalState>>
|
||||||
> = {};
|
> = {};
|
||||||
#subduxes: SUBDUXES;
|
#subduxes: SUBDUXES;
|
||||||
|
|
||||||
#name: string;
|
#name: string;
|
||||||
|
|
||||||
#actions: AggregateActions<T_LocalActions, SUBDUXES>;
|
#actions: AggregateActions<ResolveActions<T_LocalActions>, SUBDUXES>;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
config: Partial<{
|
config: Partial<{
|
||||||
@ -81,10 +112,10 @@ export default class Updux<
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO force the actionCreator to be one of the actions?
|
// TODO force the actionCreator to be one of the actions?
|
||||||
mutation<A extends ActionCreator>(
|
mutation<A extends ActionCreator<any>>(
|
||||||
actionCreator: A,
|
actionCreator: A,
|
||||||
mutation: Mutation<A, AggregateState<T_LocalState>>,
|
mutation: Mutation<A, AggregateState<T_LocalState>>,
|
||||||
) {
|
) {
|
||||||
this.#localMutations[actionCreator.type] = mutation;
|
this.#localMutations[(actionCreator as any).type] = mutation;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -101,17 +101,22 @@ test('throw if double action', () => {
|
|||||||
).toThrow(/action 'foo' defined both in subduxes 'gamma' and 'beta'/);
|
).toThrow(/action 'foo' defined both in subduxes 'gamma' and 'beta'/);
|
||||||
});
|
});
|
||||||
|
|
||||||
test.todo('action definition shortcut', () => {
|
test('action definition shortcut', () => {
|
||||||
const foo = new Updux({
|
const foo = new Updux({
|
||||||
actions: {
|
actions: {
|
||||||
foo: undefined,
|
foo: 0,
|
||||||
bar: (x) => ({ x }),
|
bar: (x: number) => ({ x }),
|
||||||
|
baz: createAction('baz', withPayload<boolean>()),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(foo.actions.foo('hello')).toEqual({ type: 'foo', payload: 'hello' });
|
expect(foo.actions.foo()).toEqual({ type: 'foo', payload: undefined });
|
||||||
expect(foo.actions.bar('hello')).toEqual({
|
expect(foo.actions.baz(false)).toEqual({
|
||||||
|
type: 'baz',
|
||||||
|
payload: false,
|
||||||
|
});
|
||||||
|
expect(foo.actions.bar(2)).toEqual({
|
||||||
type: 'bar',
|
type: 'bar',
|
||||||
payload: { x: 'hello' },
|
payload: { x: 2 },
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,6 +1,18 @@
|
|||||||
|
import { createAction } from '@reduxjs/toolkit';
|
||||||
import * as R from 'remeda';
|
import * as R from 'remeda';
|
||||||
|
import { withPayload } from './actions.js';
|
||||||
|
|
||||||
|
function resolveActions(configActions) {
|
||||||
|
return R.mapValues(configActions, (prepare, type: string) => {
|
||||||
|
if (typeof prepare === 'function' && prepare.type) return prepare;
|
||||||
|
|
||||||
|
return createAction(type, withPayload(prepare));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export function buildActions(localActions, subduxes) {
|
export function buildActions(localActions, subduxes) {
|
||||||
|
localActions = resolveActions(localActions);
|
||||||
|
|
||||||
let actions: Record<string, string> = {};
|
let actions: Record<string, string> = {};
|
||||||
|
|
||||||
for (const slice in subduxes) {
|
for (const slice in subduxes) {
|
||||||
|
Loading…
Reference in New Issue
Block a user