-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathindex.js
111 lines (99 loc) · 3.48 KB
/
index.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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
import { runSaga, stdChannel } from 'redux-saga';
/**
* Normalize the map
* normalizeMap([1, 2, 3]) => [ { key: 1, val: 1 }, { key: 2, val: 2 }, { key: 3, val: 3 } ]
* normalizeMap({a: 1, b: 2, c: 3}) => [ { key: 'a', val: 1 }, { key: 'b', val: 2 }, { key: 'c', val: 3 } ]
* @param {Array|Object} map
* @return {Object}
*/
function normalizeMap(map) {
return Array.isArray(map)
? map.map(key => ({ key, val: key }))
: Object.keys(map).map(key => ({ key, val: map[key] }));
}
/**
* Reduce the code which written in Vue.js for dispatch the action
* @param {Object|Array} actions # Object's item can be a function which accept `dispatch` function as the first param, it can accept anthor params. You can dispatch action and do any other things in this function. specially, You need to pass anthor params from the mapped function.
* @return {Object}
*/
export function mapSagaActions(actions) {
const res = {};
normalizeMap(actions).forEach(({ key, val }) => {
res[key] = function mappedSagaAction(...args) {
// get saga dispatch function from store
const { sagaDispatch } = this.$store;
return typeof val === 'function'
? val.apply(this, [sagaDispatch].concat(args))
: sagaDispatch.apply(this.$store, [val].concat(args));
};
});
return res;
}
const channel = stdChannel();
/**
* Sync saga dispatch
*
* @param {string} type
* @param {any} payload
*/
export const sagaDispatch = (type, payload) => channel.put({ type, payload });
/**
* Async saga dispatch
*
* @param {string} type action
* @param {any} payload action
* @param {(action: Action) => boolean | string} resolver resolver for finish action
* @returns {Promise}
*/
export const sagaDispatchResolve = async ({ type, payload, resolver } = {}) =>
new Promise(resolve => {
if (resolver) {
const isFn = typeof resolver === 'function';
const isString = typeof resolver === 'string';
// eslint-disable-next-line no-nested-ternary
const matcher = isFn ? resolver : isString ? action => action.type === resolver : () => true;
channel.take(resolve, matcher);
sagaDispatch(type, payload);
}
});
/**
* Add saga after creating root store
*
* @param {Generator} saga array of saga functions
* @param {Store} store Vuex store
* @param args other parameters acceptable by rudux-saga runSaga function
*/
export const addSaga = (saga, store, args) => {
runSaga(
{
channel,
dispatch: output => store.commit(output),
getState: () => store.state,
...args
},
saga
);
};
/**
* Main plugin function
*
* @param {Array} sagas array of saga functions
* @param {Boolean} isProxingFromVuex flag of proxing mutation from vuex to saga.
* @param args other parameters acceptable by rudux-saga runSaga function
* @return {Function}
*/
export function VuexSaga({ sagas = [], isProxingFromVuex = true, ...args } = {}) {
return store => {
const { commit } = store;
sagas.forEach(saga => addSaga(saga, store, args));
// eslint-disable-next-line no-param-reassign
store.sagaDispatch = sagaDispatch;
if (isProxingFromVuex) {
// eslint-disable-next-line no-param-reassign
store.commit = (type, payload) => {
channel.put({ type, payload });
return commit(type, payload);
};
}
};
}