add sink mutations
This commit is contained in:
parent
73973a9588
commit
0e03628502
@ -12,7 +12,7 @@ type SubMutations = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function buildMutations(
|
function buildMutations(
|
||||||
mutations :Dictionary<Mutation> = {},
|
mutations :Dictionary<Mutation|([Mutation,boolean|undefined])> = {},
|
||||||
subduxes = {}
|
subduxes = {}
|
||||||
) {
|
) {
|
||||||
// we have to differentiate the subduxes with '*' than those
|
// we have to differentiate the subduxes with '*' than those
|
||||||
@ -49,15 +49,26 @@ function buildMutations(
|
|||||||
|
|
||||||
nonGlobby.forEach(([slice, {mutations = {}, reducer = {}}]:any[]) => {
|
nonGlobby.forEach(([slice, {mutations = {}, reducer = {}}]:any[]) => {
|
||||||
Object.entries(mutations).forEach(([type, mutation]) => {
|
Object.entries(mutations).forEach(([type, mutation]) => {
|
||||||
const localized = (payload = null, action :Action) =>
|
const localized = (payload = null, action :Action) => {
|
||||||
u.updateIn(slice)((mutation as Mutation)(payload, action));
|
console.log(slice);
|
||||||
|
|
||||||
|
return u.updateIn(slice)((mutation as Mutation)(payload, action));
|
||||||
|
}
|
||||||
|
|
||||||
mergedMutations[type].push(localized);
|
mergedMutations[type].push(localized);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
Object.entries(mutations).forEach(([type, mutation]) => {
|
Object.entries(mutations).forEach(([type, mutation]) => {
|
||||||
mergedMutations[type].push(mutation);
|
if ( Array.isArray(mutation) ) {
|
||||||
|
if( mutation[1] ) {
|
||||||
|
mergedMutations[type] = [
|
||||||
|
mutation[0]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
else mergedMutations[type].push( mutation[0] );
|
||||||
|
}
|
||||||
|
else mergedMutations[type].push(mutation);
|
||||||
});
|
});
|
||||||
|
|
||||||
return fp.mapValues(composeMutations)(mergedMutations);
|
return fp.mapValues(composeMutations)(mergedMutations);
|
||||||
|
39
src/sink.test.ts
Normal file
39
src/sink.test.ts
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import Updux from './updux';
|
||||||
|
|
||||||
|
const foo = new Updux<number>({
|
||||||
|
initial: 0,
|
||||||
|
mutations: {
|
||||||
|
doIt: () => (state: number) => {
|
||||||
|
console.log(state);
|
||||||
|
return state + 1;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const bar = new Updux<{foo: number}>({
|
||||||
|
subduxes: {foo},
|
||||||
|
mutations: {
|
||||||
|
doIt: () => (state: any) => state,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
bar.addMutation(
|
||||||
|
foo.actions.doIt,
|
||||||
|
() => (state: any) => ({...state, bar: 'yay'}),
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
|
||||||
|
test('initial', () => {
|
||||||
|
expect(bar.initial).toEqual({foo: 0});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('foo alone', () => {
|
||||||
|
expect(foo.reducer(undefined, foo.actions.doIt())).toEqual(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('sink mutations', () => {
|
||||||
|
expect(bar.reducer(undefined, bar.actions.doIt())).toEqual({
|
||||||
|
foo: 0,
|
||||||
|
bar: 'yay',
|
||||||
|
});
|
||||||
|
});
|
96
src/updux.ts
96
src/updux.ts
@ -42,12 +42,12 @@ export type Dux<S> = Pick<
|
|||||||
>;
|
>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* `Updux` is a way to minimize and simplify the boilerplate associated with the
|
* `Updux` is a way to minimize and simplify the boilerplate associated with the
|
||||||
* creation of a `Redux` store. It takes a shorthand configuration
|
* creation of a `Redux` store. It takes a shorthand configuration
|
||||||
* object, and generates the appropriate reducer, actions, middleware, etc.
|
* object, and generates the appropriate reducer, actions, middleware, etc.
|
||||||
* In true `Redux`-like fashion, upduxes can be made of sub-upduxes (`subduxes` for short) for different slices of the root state.
|
* In true `Redux`-like fashion, upduxes can be made of sub-upduxes (`subduxes` for short) for different slices of the root state.
|
||||||
* @typeparam S Store's state type. Defaults to `any`.
|
* @typeparam S Store's state type. Defaults to `any`.
|
||||||
*/
|
*/
|
||||||
export class Updux<S = any> {
|
export class Updux<S = any> {
|
||||||
subduxes: Dictionary<Updux>;
|
subduxes: Dictionary<Updux>;
|
||||||
|
|
||||||
@ -60,41 +60,41 @@ export class Updux<S = any> {
|
|||||||
*/
|
*/
|
||||||
initial: S;
|
initial: S;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function that can be provided to alter all local mutations of the updux
|
* Function that can be provided to alter all local mutations of the updux
|
||||||
* (the mutations of subduxes are left untouched).
|
* (the mutations of subduxes are left untouched).
|
||||||
*
|
*
|
||||||
* Can be used, for example, for Immer integration:
|
* Can be used, for example, for Immer integration:
|
||||||
*
|
*
|
||||||
* ```
|
* ```
|
||||||
* import Updux from 'updux';
|
* import Updux from 'updux';
|
||||||
* import { produce } from 'Immer';
|
* import { produce } from 'Immer';
|
||||||
*
|
*
|
||||||
* const updux = new Updux({
|
* const updux = new Updux({
|
||||||
* initial: { counter: 0 },
|
* initial: { counter: 0 },
|
||||||
* groomMutations: mutation => (...args) => produce( mutation(...args) ),
|
* groomMutations: mutation => (...args) => produce( mutation(...args) ),
|
||||||
* mutations: {
|
* mutations: {
|
||||||
* add: (inc=1) => draft => draft.counter += inc
|
* add: (inc=1) => draft => draft.counter += inc
|
||||||
* }
|
* }
|
||||||
* });
|
* });
|
||||||
*
|
*
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* Or perhaps for debugging:
|
* Or perhaps for debugging:
|
||||||
*
|
*
|
||||||
* ```
|
* ```
|
||||||
* import Updux from 'updux';
|
* import Updux from 'updux';
|
||||||
*
|
*
|
||||||
* const updux = new Updux({
|
* const updux = new Updux({
|
||||||
* initial: { counter: 0 },
|
* initial: { counter: 0 },
|
||||||
* groomMutations: mutation => (...args) => state => {
|
* groomMutations: mutation => (...args) => state => {
|
||||||
* console.log( "got action ", args[1] );
|
* console.log( "got action ", args[1] );
|
||||||
* return mutation(...args)(state);
|
* return mutation(...args)(state);
|
||||||
* }
|
* }
|
||||||
* });
|
* });
|
||||||
*
|
*
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
groomMutations: (mutation: Mutation<S>) => Mutation<S>;
|
groomMutations: (mutation: Mutation<S>) => Mutation<S>;
|
||||||
|
|
||||||
@observable private localEffects: Dictionary<
|
@observable private localEffects: Dictionary<
|
||||||
@ -103,7 +103,9 @@ export class Updux<S = any> {
|
|||||||
|
|
||||||
@observable private localActions: Dictionary<ActionCreator>;
|
@observable private localActions: Dictionary<ActionCreator>;
|
||||||
|
|
||||||
@observable private localMutations: Dictionary<Mutation<S>>;
|
@observable private localMutations: Dictionary<
|
||||||
|
Mutation<S> | [Mutation<S>, boolean | undefined]
|
||||||
|
>;
|
||||||
|
|
||||||
constructor(config: UpduxConfig = {}) {
|
constructor(config: UpduxConfig = {}) {
|
||||||
this.groomMutations = config.groomMutations || ((x: Mutation<S>) => x);
|
this.groomMutations = config.groomMutations || ((x: Mutation<S>) => x);
|
||||||
@ -245,6 +247,8 @@ export class Updux<S = any> {
|
|||||||
* Adds a mutation and its associated action to the updux.
|
* Adds a mutation and its associated action to the updux.
|
||||||
* If a local mutation was already associated to the action,
|
* If a local mutation was already associated to the action,
|
||||||
* it will be replaced by the new one.
|
* it will be replaced by the new one.
|
||||||
|
* @param isSink
|
||||||
|
* If `true`, disables the subduxes mutations for this action.
|
||||||
* @example
|
* @example
|
||||||
* ```
|
* ```
|
||||||
* updux.addMutation( add, inc => state => state + inc );
|
* updux.addMutation( add, inc => state => state + inc );
|
||||||
@ -253,11 +257,13 @@ export class Updux<S = any> {
|
|||||||
addMutation<A extends ActionCreator>(
|
addMutation<A extends ActionCreator>(
|
||||||
creator: A,
|
creator: A,
|
||||||
mutation: Mutation<S, A extends (...args: any[]) => infer R ? R : never>,
|
mutation: Mutation<S, A extends (...args: any[]) => infer R ? R : never>,
|
||||||
|
isSink?: boolean,
|
||||||
) {
|
) {
|
||||||
this.localActions[creator.type] = creator;
|
this.localActions[creator.type] = creator;
|
||||||
this.localMutations[creator.type] = this.groomMutations(
|
this.localMutations[creator.type] = [
|
||||||
mutation as any,
|
this.groomMutations(mutation as any) as Mutation<S>,
|
||||||
) as Mutation<S>;
|
isSink,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user