-
Notifications
You must be signed in to change notification settings - Fork 0
/
createResolveReducer.js
70 lines (61 loc) 路 2.2 KB
/
createResolveReducer.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
// @ts-check
/** @typedef {import('redux').AnyAction} AnyAction */
/** @typedef {import('redux').Reducer} Reducer */
/** @typedef {import('mutant-json').MutantOptions} MutantOptions */
const mutantJson = require('mutant-json');
const tap = require('mutant-json/tap');
const isAlias = require('./isAlias');
const isReducer = require('./isReducer');
const parseAliasReducer = (reducer) => Array.isArray(reducer) ? reducer : [reducer];
/**
* @typedef {Object} CuserStoreResolveReducerOptions
* @prop {Record<string, Reducer>} [aliases={}]
* @prop {Number} [maxRecursion=10]
*/
/**
*
* @param {Reducer} rootReducer
* @param {CuserStoreResolveReducerOptions & MutantOptions} [opts]
*/
const createResolveReducer = (rootReducer, opts) => {
const {
aliases = {},
maxRecursion = 10,
...restOptions
} = { ...opts };
const createRecursiveResolveReducer = (rootReducer, recursion = []) => {
/**
*
* @param {any} state
* @param {AnyAction} action
*/
const resolveReducer = (state, action) => {
return mutantJson(rootReducer(state, action), (mutate, value, pointer) => {
let alias, reducerState, reducerAction = action, reducer = value;
if (isAlias(reducer)) {
[alias, reducerState, reducerAction = action] = parseAliasReducer(reducer);
if (!aliases[alias]) {
throw new Error(`CuserStore: resolve-reducer missing reducer ${alias}`);
}
reducer = aliases[alias];
}
if (isReducer(reducer)) {
if (recursion.filter((red) => red === reducer).length > maxRecursion) {
throw new Error(`CuserStore: resolve-reducer max recursion "${maxRecursion}" reached "${pointer}" for "${alias || reducer.toString()}"`);
}
reducer = createRecursiveResolveReducer(reducer, recursion.concat(reducer));
mutate({
value: reducer(reducerState ||聽tap(state, pointer), reducerAction)
});
}
}, {
test: ([_, value]) => isAlias(value) ||聽isReducer(value),
promises: false,
...restOptions
});
}
return resolveReducer;
}
return createRecursiveResolveReducer(rootReducer);
}
module.exports = createResolveReducer;