1 | 'use strict';
|
2 |
|
3 | Object.defineProperty(exports, '__esModule', { value: true });
|
4 |
|
5 | var Redux = require('redux');
|
6 |
|
7 | function _interopNamespace(e) {
|
8 | if (e && e.__esModule) return e;
|
9 | var n = Object.create(null);
|
10 | if (e) {
|
11 | Object.keys(e).forEach(function (k) {
|
12 | if (k !== 'default') {
|
13 | var d = Object.getOwnPropertyDescriptor(e, k);
|
14 | Object.defineProperty(n, k, d.get ? d : {
|
15 | enumerable: true,
|
16 | get: function () { return e[k]; }
|
17 | });
|
18 | }
|
19 | });
|
20 | }
|
21 | n["default"] = e;
|
22 | return n;
|
23 | }
|
24 |
|
25 | var Redux__namespace = _interopNamespace(Redux);
|
26 |
|
27 | function _extends() {
|
28 | _extends = Object.assign || function (target) {
|
29 | for (var i = 1; i < arguments.length; i++) {
|
30 | var source = arguments[i];
|
31 |
|
32 | for (var key in source) {
|
33 | if (Object.prototype.hasOwnProperty.call(source, key)) {
|
34 | target[key] = source[key];
|
35 | }
|
36 | }
|
37 | }
|
38 |
|
39 | return target;
|
40 | };
|
41 |
|
42 | return _extends.apply(this, arguments);
|
43 | }
|
44 |
|
45 | function createReduxStore(bag) {
|
46 | var _bag$reduxConfig;
|
47 |
|
48 | bag.models.forEach(function (model) {
|
49 | return createModelReducer(bag, model);
|
50 | });
|
51 | var rootReducer = createRootReducer(bag);
|
52 | var middlewares = Redux__namespace.applyMiddleware.apply(Redux__namespace, bag.reduxConfig.middlewares);
|
53 | var enhancers = bag.reduxConfig.devtoolComposer ? (_bag$reduxConfig = bag.reduxConfig).devtoolComposer.apply(_bag$reduxConfig, bag.reduxConfig.enhancers.concat([middlewares])) : composeEnhancersWithDevtools(bag.reduxConfig.devtoolOptions).apply(void 0, bag.reduxConfig.enhancers.concat([middlewares]));
|
54 | var createStore = bag.reduxConfig.createStore || Redux__namespace.createStore;
|
55 | var bagInitialState = bag.reduxConfig.initialState;
|
56 | var initialState = bagInitialState === undefined ? {} : bagInitialState;
|
57 | return createStore(rootReducer, initialState, enhancers);
|
58 | }
|
59 | function createModelReducer(bag, model) {
|
60 | var modelReducers = {};
|
61 | var modelReducerKeys = Object.keys(model.reducers);
|
62 | modelReducerKeys.forEach(function (reducerKey) {
|
63 | var actionName = isAlreadyActionName(reducerKey) ? reducerKey : model.name + "/" + reducerKey;
|
64 | modelReducers[actionName] = model.reducers[reducerKey];
|
65 | });
|
66 |
|
67 | var combinedReducer = function combinedReducer(state, action) {
|
68 | if (state === void 0) {
|
69 | state = model.state;
|
70 | }
|
71 |
|
72 | if (action.type in modelReducers) {
|
73 | return modelReducers[action.type](state, action.payload, action.meta);
|
74 | }
|
75 |
|
76 | return state;
|
77 | };
|
78 |
|
79 | var modelBaseReducer = model.baseReducer;
|
80 | var reducer = !modelBaseReducer ? combinedReducer : function (state, action) {
|
81 | if (state === void 0) {
|
82 | state = model.state;
|
83 | }
|
84 |
|
85 | return combinedReducer(modelBaseReducer(state, action), action);
|
86 | };
|
87 | bag.forEachPlugin('onReducer', function (onReducer) {
|
88 | reducer = onReducer(reducer, model.name, bag) || reducer;
|
89 | });
|
90 | bag.reduxConfig.reducers[model.name] = reducer;
|
91 | }
|
92 | function createRootReducer(bag) {
|
93 | var rootReducers = bag.reduxConfig.rootReducers;
|
94 | var mergedReducers = mergeReducers(bag.reduxConfig);
|
95 | var rootReducer = mergedReducers;
|
96 |
|
97 | if (rootReducers && Object.keys(rootReducers).length) {
|
98 | rootReducer = function rootReducer(state, action) {
|
99 | var actionRootReducer = rootReducers[action.type];
|
100 |
|
101 | if (actionRootReducer) {
|
102 | return mergedReducers(actionRootReducer(state, action), action);
|
103 | }
|
104 |
|
105 | return mergedReducers(state, action);
|
106 | };
|
107 | }
|
108 |
|
109 | bag.forEachPlugin('onRootReducer', function (onRootReducer) {
|
110 | rootReducer = onRootReducer(rootReducer, bag) || rootReducer;
|
111 | });
|
112 | return rootReducer;
|
113 | }
|
114 |
|
115 | function mergeReducers(reduxConfig) {
|
116 | var combineReducers = reduxConfig.combineReducers || Redux__namespace.combineReducers;
|
117 |
|
118 | if (!Object.keys(reduxConfig.reducers).length) {
|
119 | return function (state) {
|
120 | return state;
|
121 | };
|
122 | }
|
123 |
|
124 | return combineReducers(reduxConfig.reducers);
|
125 | }
|
126 |
|
127 | function composeEnhancersWithDevtools(devtoolOptions) {
|
128 | if (devtoolOptions === void 0) {
|
129 | devtoolOptions = {};
|
130 | }
|
131 |
|
132 | return !devtoolOptions.disabled && typeof window === 'object' && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__(devtoolOptions) : Redux__namespace.compose;
|
133 | }
|
134 |
|
135 | function isAlreadyActionName(reducerKey) {
|
136 | return reducerKey.indexOf('/') > -1;
|
137 | }
|
138 |
|
139 | var isObject = function isObject(obj) {
|
140 | return typeof obj === 'object' && obj !== null && !Array.isArray(obj);
|
141 | };
|
142 | var ifDefinedIsFunction = function ifDefinedIsFunction(func) {
|
143 | return !func || typeof func === 'function';
|
144 | };
|
145 |
|
146 | var validate = function validate(runValidations) {
|
147 | {
|
148 | var validations = runValidations();
|
149 | var errors = [];
|
150 | validations.forEach(function (validation) {
|
151 | var isInvalid = validation[0];
|
152 | var errorMessage = validation[1];
|
153 |
|
154 | if (isInvalid) {
|
155 | errors.push(errorMessage);
|
156 | }
|
157 | });
|
158 |
|
159 | if (errors.length > 0) {
|
160 | throw new Error(errors.join(', '));
|
161 | }
|
162 | }
|
163 | };
|
164 |
|
165 | var validateConfig = function validateConfig(config) {
|
166 | validate(function () {
|
167 | return [[!Array.isArray(config.plugins), 'init config.plugins must be an array'], [!isObject(config.models), 'init config.models must be an object'], [!isObject(config.redux.reducers), 'init config.redux.reducers must be an object'], [!Array.isArray(config.redux.middlewares), 'init config.redux.middlewares must be an array'], [!Array.isArray(config.redux.enhancers), 'init config.redux.enhancers must be an array of functions'], [!ifDefinedIsFunction(config.redux.combineReducers), 'init config.redux.combineReducers must be a function'], [!ifDefinedIsFunction(config.redux.createStore), 'init config.redux.createStore must be a function']];
|
168 | });
|
169 | };
|
170 | var validateModel = function validateModel(model) {
|
171 | validate(function () {
|
172 | return [[!model, 'model config is required'], [typeof model.name !== 'string', 'model "name" [string] is required'], [model.state === undefined && model.baseReducer === undefined, 'model "state" is required'], [!ifDefinedIsFunction(model.baseReducer), 'model "baseReducer" must be a function']];
|
173 | });
|
174 | };
|
175 | var validatePlugin = function validatePlugin(plugin) {
|
176 | validate(function () {
|
177 | return [[!ifDefinedIsFunction(plugin.onStoreCreated), 'Plugin onStoreCreated must be a function'], [!ifDefinedIsFunction(plugin.onModel), 'Plugin onModel must be a function'], [!ifDefinedIsFunction(plugin.onReducer), 'Plugin onReducer must be a function'], [!ifDefinedIsFunction(plugin.onRootReducer), 'Plugin onRootReducer must be a function'], [!ifDefinedIsFunction(plugin.createMiddleware), 'Plugin createMiddleware must be a function']];
|
178 | });
|
179 | };
|
180 | var validateModelReducer = function validateModelReducer(modelName, reducers, reducerName) {
|
181 | validate(function () {
|
182 | return [[!!reducerName.match(/\/.+\//), "Invalid reducer name (" + modelName + "/" + reducerName + ")"], [typeof reducers[reducerName] !== 'function', "Invalid reducer (" + modelName + "/" + reducerName + "). Must be a function"]];
|
183 | });
|
184 | };
|
185 | var validateModelEffect = function validateModelEffect(modelName, effects, effectName) {
|
186 | validate(function () {
|
187 | return [[!!effectName.match(/\//), "Invalid effect name (" + modelName + "/" + effectName + ")"], [typeof effects[effectName] !== 'function', "Invalid effect (" + modelName + "/" + effectName + "). Must be a function"]];
|
188 | });
|
189 | };
|
190 |
|
191 | var createActionDispatcher = function createActionDispatcher(rematch, modelName, actionName, isEffect) {
|
192 | return Object.assign(function (payload, meta) {
|
193 | var action = {
|
194 | type: modelName + "/" + actionName
|
195 | };
|
196 |
|
197 | if (typeof payload !== 'undefined') {
|
198 | action.payload = payload;
|
199 | }
|
200 |
|
201 | if (typeof meta !== 'undefined') {
|
202 | action.meta = meta;
|
203 | }
|
204 |
|
205 | return rematch.dispatch(action);
|
206 | }, {
|
207 | isEffect: isEffect
|
208 | });
|
209 | };
|
210 |
|
211 | var createReducerDispatcher = function createReducerDispatcher(rematch, model) {
|
212 | var modelDispatcher = rematch.dispatch[model.name];
|
213 | var modelReducersKeys = Object.keys(model.reducers);
|
214 | modelReducersKeys.forEach(function (reducerName) {
|
215 | validateModelReducer(model.name, model.reducers, reducerName);
|
216 | modelDispatcher[reducerName] = createActionDispatcher(rematch, model.name, reducerName, false);
|
217 | });
|
218 | };
|
219 | var createEffectDispatcher = function createEffectDispatcher(rematch, bag, model) {
|
220 | var modelDispatcher = rematch.dispatch[model.name];
|
221 | var effects = {};
|
222 |
|
223 | if (model.effects) {
|
224 | effects = typeof model.effects === 'function' ? model.effects(rematch.dispatch) : model.effects;
|
225 | }
|
226 |
|
227 | var effectKeys = Object.keys(effects);
|
228 | effectKeys.forEach(function (effectName) {
|
229 | validateModelEffect(model.name, effects, effectName);
|
230 | bag.effects[model.name + "/" + effectName] = effects[effectName].bind(modelDispatcher);
|
231 | modelDispatcher[effectName] = createActionDispatcher(rematch, model.name, effectName, true);
|
232 | });
|
233 | };
|
234 |
|
235 | function createRematchBag(config) {
|
236 | return {
|
237 | models: createNamedModels(config.models),
|
238 | reduxConfig: config.redux,
|
239 | forEachPlugin: function forEachPlugin(method, fn) {
|
240 | config.plugins.forEach(function (plugin) {
|
241 | if (plugin[method]) {
|
242 | fn(plugin[method]);
|
243 | }
|
244 | });
|
245 | },
|
246 | effects: {}
|
247 | };
|
248 | }
|
249 |
|
250 | function createNamedModels(models) {
|
251 | return Object.keys(models).map(function (modelName) {
|
252 | var model = createNamedModel(modelName, models[modelName]);
|
253 | validateModel(model);
|
254 | return model;
|
255 | });
|
256 | }
|
257 |
|
258 | function createNamedModel(name, model) {
|
259 | return _extends({
|
260 | name: name,
|
261 | reducers: {}
|
262 | }, model);
|
263 | }
|
264 |
|
265 | function createRematchStore(config) {
|
266 | var bag = createRematchBag(config);
|
267 | bag.reduxConfig.middlewares.push(createEffectsMiddleware(bag));
|
268 | bag.forEachPlugin('createMiddleware', function (createMiddleware) {
|
269 | bag.reduxConfig.middlewares.push(createMiddleware(bag));
|
270 | });
|
271 | var reduxStore = createReduxStore(bag);
|
272 |
|
273 | var rematchStore = _extends({}, reduxStore, {
|
274 | name: config.name,
|
275 | addModel: function addModel(model) {
|
276 | validateModel(model);
|
277 | createModelReducer(bag, model);
|
278 | prepareModel(rematchStore, model);
|
279 | enhanceModel(rematchStore, bag, model);
|
280 | reduxStore.replaceReducer(createRootReducer(bag));
|
281 | reduxStore.dispatch({
|
282 | type: '@@redux/REPLACE'
|
283 | });
|
284 | }
|
285 | });
|
286 |
|
287 | addExposed(rematchStore, config.plugins);
|
288 | bag.models.forEach(function (model) {
|
289 | return prepareModel(rematchStore, model);
|
290 | });
|
291 | bag.models.forEach(function (model) {
|
292 | return enhanceModel(rematchStore, bag, model);
|
293 | });
|
294 | bag.forEachPlugin('onStoreCreated', function (onStoreCreated) {
|
295 | rematchStore = onStoreCreated(rematchStore, bag) || rematchStore;
|
296 | });
|
297 | return rematchStore;
|
298 | }
|
299 |
|
300 | function createEffectsMiddleware(bag) {
|
301 | return function (store) {
|
302 | return function (next) {
|
303 | return function (action) {
|
304 | if (action.type in bag.effects) {
|
305 | next(action);
|
306 | return bag.effects[action.type](action.payload, store.getState(), action.meta);
|
307 | }
|
308 |
|
309 | return next(action);
|
310 | };
|
311 | };
|
312 | };
|
313 | }
|
314 |
|
315 | function prepareModel(rematchStore, model) {
|
316 | var modelDispatcher = {};
|
317 | rematchStore.dispatch["" + model.name] = modelDispatcher;
|
318 | createReducerDispatcher(rematchStore, model);
|
319 | }
|
320 |
|
321 | function enhanceModel(rematchStore, bag, model) {
|
322 | createEffectDispatcher(rematchStore, bag, model);
|
323 | bag.forEachPlugin('onModel', function (onModel) {
|
324 | onModel(model, rematchStore);
|
325 | });
|
326 | }
|
327 |
|
328 | function addExposed(store, plugins) {
|
329 | plugins.forEach(function (plugin) {
|
330 | if (!plugin.exposed) return;
|
331 | var pluginKeys = Object.keys(plugin.exposed);
|
332 | pluginKeys.forEach(function (key) {
|
333 | if (!plugin.exposed) return;
|
334 | var exposedItem = plugin.exposed[key];
|
335 | var isExposedFunction = typeof exposedItem === 'function';
|
336 | store[key] = isExposedFunction ? function () {
|
337 | for (var _len = arguments.length, params = new Array(_len), _key = 0; _key < _len; _key++) {
|
338 | params[_key] = arguments[_key];
|
339 | }
|
340 |
|
341 | return exposedItem.apply(void 0, [store].concat(params));
|
342 | } : Object.create(plugin.exposed[key]);
|
343 | });
|
344 | });
|
345 | }
|
346 |
|
347 | var count = 0;
|
348 | function createConfig(initConfig) {
|
349 | var _initConfig$name, _initConfig$redux$dev, _initConfig$redux;
|
350 |
|
351 | var storeName = (_initConfig$name = initConfig.name) != null ? _initConfig$name : "Rematch Store " + count;
|
352 | count += 1;
|
353 | var config = {
|
354 | name: storeName,
|
355 | models: initConfig.models || {},
|
356 | plugins: initConfig.plugins || [],
|
357 | redux: _extends({
|
358 | reducers: {},
|
359 | rootReducers: {},
|
360 | enhancers: [],
|
361 | middlewares: []
|
362 | }, initConfig.redux, {
|
363 | devtoolOptions: _extends({
|
364 | name: storeName
|
365 | }, (_initConfig$redux$dev = (_initConfig$redux = initConfig.redux) == null ? void 0 : _initConfig$redux.devtoolOptions) != null ? _initConfig$redux$dev : {})
|
366 | })
|
367 | };
|
368 | validateConfig(config);
|
369 | config.plugins.forEach(function (plugin) {
|
370 | if (plugin.config) {
|
371 | config.models = merge(config.models, plugin.config.models);
|
372 |
|
373 | if (plugin.config.redux) {
|
374 | config.redux.initialState = merge(config.redux.initialState, plugin.config.redux.initialState);
|
375 | config.redux.reducers = merge(config.redux.reducers, plugin.config.redux.reducers);
|
376 | config.redux.rootReducers = merge(config.redux.rootReducers, plugin.config.redux.reducers);
|
377 | config.redux.enhancers = [].concat(config.redux.enhancers, plugin.config.redux.enhancers || []);
|
378 | config.redux.middlewares = [].concat(config.redux.middlewares, plugin.config.redux.middlewares || []);
|
379 | config.redux.combineReducers = config.redux.combineReducers || plugin.config.redux.combineReducers;
|
380 | config.redux.createStore = config.redux.createStore || plugin.config.redux.createStore;
|
381 | }
|
382 | }
|
383 |
|
384 | validatePlugin(plugin);
|
385 | });
|
386 | return config;
|
387 | }
|
388 |
|
389 | function merge(original, extra) {
|
390 | return extra ? _extends({}, extra, original) : original;
|
391 | }
|
392 |
|
393 | var init = function init(initConfig) {
|
394 | var config = createConfig(initConfig || {});
|
395 | return createRematchStore(config);
|
396 | };
|
397 | var createModel = function createModel() {
|
398 | return function (mo) {
|
399 | return mo;
|
400 | };
|
401 | };
|
402 | var index = {
|
403 | init: init,
|
404 | createModel: createModel
|
405 | };
|
406 |
|
407 | exports.createModel = createModel;
|
408 | exports["default"] = index;
|
409 | exports.init = init;
|
410 |
|