@rematch/core
Version:
A Redux Framework
411 lines (354 loc) • 14.2 kB
JavaScript
Object.defineProperty(exports, '__esModule', { value: true });
var Redux = require('redux');
function _interopNamespace(e) {
if (e && e.__esModule) return e;
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n["default"] = e;
return n;
}
var Redux__namespace = /*#__PURE__*/_interopNamespace(Redux);
function _extends() {
_extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
return _extends.apply(this, arguments);
}
function createReduxStore(bag) {
var _bag$reduxConfig;
bag.models.forEach(function (model) {
return createModelReducer(bag, model);
});
var rootReducer = createRootReducer(bag);
var middlewares = Redux__namespace.applyMiddleware.apply(Redux__namespace, bag.reduxConfig.middlewares);
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]));
var createStore = bag.reduxConfig.createStore || Redux__namespace.createStore;
var bagInitialState = bag.reduxConfig.initialState;
var initialState = bagInitialState === undefined ? {} : bagInitialState;
return createStore(rootReducer, initialState, enhancers);
}
function createModelReducer(bag, model) {
var modelReducers = {};
var modelReducerKeys = Object.keys(model.reducers);
modelReducerKeys.forEach(function (reducerKey) {
var actionName = isAlreadyActionName(reducerKey) ? reducerKey : model.name + "/" + reducerKey;
modelReducers[actionName] = model.reducers[reducerKey];
});
var combinedReducer = function combinedReducer(state, action) {
if (state === void 0) {
state = model.state;
}
if (action.type in modelReducers) {
return modelReducers[action.type](state, action.payload, action.meta);
}
return state;
};
var modelBaseReducer = model.baseReducer;
var reducer = !modelBaseReducer ? combinedReducer : function (state, action) {
if (state === void 0) {
state = model.state;
}
return combinedReducer(modelBaseReducer(state, action), action);
};
bag.forEachPlugin('onReducer', function (onReducer) {
reducer = onReducer(reducer, model.name, bag) || reducer;
});
bag.reduxConfig.reducers[model.name] = reducer;
}
function createRootReducer(bag) {
var rootReducers = bag.reduxConfig.rootReducers;
var mergedReducers = mergeReducers(bag.reduxConfig);
var rootReducer = mergedReducers;
if (rootReducers && Object.keys(rootReducers).length) {
rootReducer = function rootReducer(state, action) {
var actionRootReducer = rootReducers[action.type];
if (actionRootReducer) {
return mergedReducers(actionRootReducer(state, action), action);
}
return mergedReducers(state, action);
};
}
bag.forEachPlugin('onRootReducer', function (onRootReducer) {
rootReducer = onRootReducer(rootReducer, bag) || rootReducer;
});
return rootReducer;
}
function mergeReducers(reduxConfig) {
var combineReducers = reduxConfig.combineReducers || Redux__namespace.combineReducers;
if (!Object.keys(reduxConfig.reducers).length) {
return function (state) {
return state;
};
}
return combineReducers(reduxConfig.reducers);
}
function composeEnhancersWithDevtools(devtoolOptions) {
if (devtoolOptions === void 0) {
devtoolOptions = {};
}
return !devtoolOptions.disabled && typeof window === 'object' && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__(devtoolOptions) : Redux__namespace.compose;
}
function isAlreadyActionName(reducerKey) {
return reducerKey.indexOf('/') > -1;
}
var isObject = function isObject(obj) {
return typeof obj === 'object' && obj !== null && !Array.isArray(obj);
};
var ifDefinedIsFunction = function ifDefinedIsFunction(func) {
return !func || typeof func === 'function';
};
var validate = function validate(runValidations) {
{
var validations = runValidations();
var errors = [];
validations.forEach(function (validation) {
var isInvalid = validation[0];
var errorMessage = validation[1];
if (isInvalid) {
errors.push(errorMessage);
}
});
if (errors.length > 0) {
throw new Error(errors.join(', '));
}
}
};
var validateConfig = function validateConfig(config) {
validate(function () {
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']];
});
};
var validateModel = function validateModel(model) {
validate(function () {
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']];
});
};
var validatePlugin = function validatePlugin(plugin) {
validate(function () {
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']];
});
};
var validateModelReducer = function validateModelReducer(modelName, reducers, reducerName) {
validate(function () {
return [[!!reducerName.match(/\/.+\//), "Invalid reducer name (" + modelName + "/" + reducerName + ")"], [typeof reducers[reducerName] !== 'function', "Invalid reducer (" + modelName + "/" + reducerName + "). Must be a function"]];
});
};
var validateModelEffect = function validateModelEffect(modelName, effects, effectName) {
validate(function () {
return [[!!effectName.match(/\//), "Invalid effect name (" + modelName + "/" + effectName + ")"], [typeof effects[effectName] !== 'function', "Invalid effect (" + modelName + "/" + effectName + "). Must be a function"]];
});
};
var createActionDispatcher = function createActionDispatcher(rematch, modelName, actionName, isEffect) {
return Object.assign(function (payload, meta) {
var action = {
type: modelName + "/" + actionName
};
if (typeof payload !== 'undefined') {
action.payload = payload;
}
if (typeof meta !== 'undefined') {
action.meta = meta;
}
return rematch.dispatch(action);
}, {
isEffect: isEffect
});
};
var createReducerDispatcher = function createReducerDispatcher(rematch, model) {
var modelDispatcher = rematch.dispatch[model.name];
var modelReducersKeys = Object.keys(model.reducers);
modelReducersKeys.forEach(function (reducerName) {
validateModelReducer(model.name, model.reducers, reducerName);
modelDispatcher[reducerName] = createActionDispatcher(rematch, model.name, reducerName, false);
});
};
var createEffectDispatcher = function createEffectDispatcher(rematch, bag, model) {
var modelDispatcher = rematch.dispatch[model.name];
var effects = {};
if (model.effects) {
effects = typeof model.effects === 'function' ? model.effects(rematch.dispatch) : model.effects;
}
var effectKeys = Object.keys(effects);
effectKeys.forEach(function (effectName) {
validateModelEffect(model.name, effects, effectName);
bag.effects[model.name + "/" + effectName] = effects[effectName].bind(modelDispatcher);
modelDispatcher[effectName] = createActionDispatcher(rematch, model.name, effectName, true);
});
};
function createRematchBag(config) {
return {
models: createNamedModels(config.models),
reduxConfig: config.redux,
forEachPlugin: function forEachPlugin(method, fn) {
config.plugins.forEach(function (plugin) {
if (plugin[method]) {
fn(plugin[method]);
}
});
},
effects: {}
};
}
function createNamedModels(models) {
return Object.keys(models).map(function (modelName) {
var model = createNamedModel(modelName, models[modelName]);
validateModel(model);
return model;
});
}
function createNamedModel(name, model) {
return _extends({
name: name,
reducers: {}
}, model);
}
function createRematchStore(config) {
var bag = createRematchBag(config);
bag.reduxConfig.middlewares.push(createEffectsMiddleware(bag));
bag.forEachPlugin('createMiddleware', function (createMiddleware) {
bag.reduxConfig.middlewares.push(createMiddleware(bag));
});
var reduxStore = createReduxStore(bag);
var rematchStore = _extends({}, reduxStore, {
name: config.name,
addModel: function addModel(model) {
validateModel(model);
createModelReducer(bag, model);
prepareModel(rematchStore, model);
enhanceModel(rematchStore, bag, model);
reduxStore.replaceReducer(createRootReducer(bag));
reduxStore.dispatch({
type: '@@redux/REPLACE'
});
}
});
addExposed(rematchStore, config.plugins);
bag.models.forEach(function (model) {
return prepareModel(rematchStore, model);
});
bag.models.forEach(function (model) {
return enhanceModel(rematchStore, bag, model);
});
bag.forEachPlugin('onStoreCreated', function (onStoreCreated) {
rematchStore = onStoreCreated(rematchStore, bag) || rematchStore;
});
return rematchStore;
}
function createEffectsMiddleware(bag) {
return function (store) {
return function (next) {
return function (action) {
if (action.type in bag.effects) {
next(action);
return bag.effects[action.type](action.payload, store.getState(), action.meta);
}
return next(action);
};
};
};
}
function prepareModel(rematchStore, model) {
var modelDispatcher = {};
rematchStore.dispatch["" + model.name] = modelDispatcher;
createReducerDispatcher(rematchStore, model);
}
function enhanceModel(rematchStore, bag, model) {
createEffectDispatcher(rematchStore, bag, model);
bag.forEachPlugin('onModel', function (onModel) {
onModel(model, rematchStore);
});
}
function addExposed(store, plugins) {
plugins.forEach(function (plugin) {
if (!plugin.exposed) return;
var pluginKeys = Object.keys(plugin.exposed);
pluginKeys.forEach(function (key) {
if (!plugin.exposed) return;
var exposedItem = plugin.exposed[key];
var isExposedFunction = typeof exposedItem === 'function';
store[key] = isExposedFunction ? function () {
for (var _len = arguments.length, params = new Array(_len), _key = 0; _key < _len; _key++) {
params[_key] = arguments[_key];
}
return exposedItem.apply(void 0, [store].concat(params));
} : Object.create(plugin.exposed[key]);
});
});
}
var count = 0;
function createConfig(initConfig) {
var _initConfig$name, _initConfig$redux$dev, _initConfig$redux;
var storeName = (_initConfig$name = initConfig.name) != null ? _initConfig$name : "Rematch Store " + count;
count += 1;
var config = {
name: storeName,
models: initConfig.models || {},
plugins: initConfig.plugins || [],
redux: _extends({
reducers: {},
rootReducers: {},
enhancers: [],
middlewares: []
}, initConfig.redux, {
devtoolOptions: _extends({
name: storeName
}, (_initConfig$redux$dev = (_initConfig$redux = initConfig.redux) == null ? void 0 : _initConfig$redux.devtoolOptions) != null ? _initConfig$redux$dev : {})
})
};
validateConfig(config);
config.plugins.forEach(function (plugin) {
if (plugin.config) {
config.models = merge(config.models, plugin.config.models);
if (plugin.config.redux) {
config.redux.initialState = merge(config.redux.initialState, plugin.config.redux.initialState);
config.redux.reducers = merge(config.redux.reducers, plugin.config.redux.reducers);
config.redux.rootReducers = merge(config.redux.rootReducers, plugin.config.redux.reducers);
config.redux.enhancers = [].concat(config.redux.enhancers, plugin.config.redux.enhancers || []);
config.redux.middlewares = [].concat(config.redux.middlewares, plugin.config.redux.middlewares || []);
config.redux.combineReducers = config.redux.combineReducers || plugin.config.redux.combineReducers;
config.redux.createStore = config.redux.createStore || plugin.config.redux.createStore;
}
}
validatePlugin(plugin);
});
return config;
}
function merge(original, extra) {
return extra ? _extends({}, extra, original) : original;
}
var init = function init(initConfig) {
var config = createConfig(initConfig || {});
return createRematchStore(config);
};
var createModel = function createModel() {
return function (mo) {
return mo;
};
};
var index = {
init: init,
createModel: createModel
};
exports.createModel = createModel;
exports["default"] = index;
exports.init = init;
//# sourceMappingURL=core.cjs.development.js.map
;