UNPKG

3 kBPlain TextView Raw
1import {
2 Action,
3 ModelEffects,
4 ModelEffectsCreator,
5 Models,
6 NamedModel,
7 RematchBag,
8 RematchDispatcher,
9 RematchStore,
10} from './types'
11import { validateModelEffect, validateModelReducer } from './validate'
12
13/**
14 * Builds a dispatcher for given model name and action name. The dispatched
15 * action will have a type `modelName/actionName`.
16 * Additionally, adds the isEffect property to the created dispatcher.
17 * isEffect helps to differentiate effects dispatchers from reducer dispatchers.
18 */
19const createActionDispatcher = <
20 TModels extends Models<TModels>,
21 TExtraModels extends Models<TModels>
22>(
23 rematch: RematchStore<TModels, TExtraModels>,
24 modelName: string,
25 actionName: string,
26 isEffect: boolean
27): RematchDispatcher<boolean> => {
28 return Object.assign(
29 (payload?: any, meta?: any): Action => {
30 const action: Action = { type: `${modelName}/${actionName}` }
31
32 if (typeof payload !== 'undefined') {
33 action.payload = payload
34 }
35
36 if (typeof meta !== 'undefined') {
37 action.meta = meta
38 }
39
40 return rematch.dispatch(action)
41 },
42 {
43 isEffect,
44 }
45 )
46}
47
48/**
49 * Creates a dispatcher object for a model - it contains a mapping from all
50 * reducers to functions which dispatch their corresponding actions.
51 */
52export const createReducerDispatcher = <
53 TModels extends Models<TModels>,
54 TExtraModels extends Models<TModels>,
55 TModel extends NamedModel<TModels>
56>(
57 rematch: RematchStore<TModels, TExtraModels>,
58 model: TModel
59): void => {
60 const modelDispatcher = rematch.dispatch[model.name]
61
62 // map reducer names to dispatch actions
63 const modelReducersKeys = Object.keys(model.reducers)
64 modelReducersKeys.forEach((reducerName) => {
65 validateModelReducer(model.name, model.reducers, reducerName)
66
67 modelDispatcher[reducerName] = createActionDispatcher(
68 rematch,
69 model.name,
70 reducerName,
71 false
72 )
73 })
74}
75
76/**
77 * Creates effects dispatcher for a model - it contains a mapping from all
78 * effects *names* to functions which dispatch their corresponding actions.
79 */
80export const createEffectDispatcher = <
81 TModels extends Models<TModels>,
82 TExtraModels extends Models<TModels>,
83 TModel extends NamedModel<TModels>
84>(
85 rematch: RematchStore<TModels, TExtraModels>,
86 bag: RematchBag<TModels, TExtraModels>,
87 model: TModel
88): void => {
89 const modelDispatcher = rematch.dispatch[model.name]
90 let effects: ModelEffects<TModels> = {}
91
92 // 'effects' might be actually a function creating effects
93 if (model.effects) {
94 effects =
95 typeof model.effects === 'function'
96 ? (model.effects as ModelEffectsCreator<TModels>)(rematch.dispatch)
97 : model.effects
98 }
99
100 // map effects names to dispatch actions
101 const effectKeys = Object.keys(effects)
102 effectKeys.forEach((effectName) => {
103 validateModelEffect(model.name, effects, effectName)
104
105 bag.effects[`${model.name}/${effectName}`] =
106 effects[effectName].bind(modelDispatcher)
107
108 modelDispatcher[effectName] = createActionDispatcher(
109 rematch,
110 model.name,
111 effectName,
112 true
113 )
114 })
115}