UNPKG

genji-core

Version:

The core lightweight library for genji, based on redux and redux-saga.

332 lines (274 loc) 9.82 kB
"use strict"; var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard"); var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.create = create; var _getIterator2 = _interopRequireDefault(require("@babel/runtime/core-js/get-iterator")); var _keys = _interopRequireDefault(require("@babel/runtime/core-js/object/keys")); var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread")); var _invariant = _interopRequireDefault(require("invariant")); var _checkModel = _interopRequireDefault(require("./checkModel")); var _prefixNamespace = _interopRequireDefault(require("./prefixNamespace")); var _Plugin = _interopRequireWildcard(require("./Plugin")); var _createStore = _interopRequireDefault(require("./createStore")); var _getAction = _interopRequireDefault(require("./getAction")); var _getMutation = _interopRequireDefault(require("./getMutation")); var _createAsyncMiddleware = _interopRequireDefault(require("./createAsyncMiddleware")); var _createImmerReducer = _interopRequireWildcard(require("./createImmerReducer")); var _subscription = require("./subscription"); var _utils = require("./utils"); // Internal model to update global state when do unmodel var genjiModel = { namespace: '@@genji', state: 0, mutations: { UPDATE: function UPDATE(state) { state += 1; } } }; /** * Create dva-core instance. * * @param hooksAndOpts * @param createOpts */ function create() { var hooksAndOpts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var createOpts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var initialReducer = createOpts.initialReducer, _createOpts$setupApp = createOpts.setupApp, setupApp = _createOpts$setupApp === void 0 ? _utils.noop : _createOpts$setupApp; var plugin = new _Plugin.default(); plugin.use((0, _Plugin.filterHooks)(hooksAndOpts)); var app = { _models: [(0, _prefixNamespace.default)((0, _objectSpread2.default)({}, genjiModel))], _store: null, _plugin: plugin, use: plugin.use.bind(plugin), model: model, start: start }; return app; /** * Register model before app is started. * * @param m {Object} model to register */ function model(m) { if (process.env.NODE_ENV !== 'production') { (0, _checkModel.default)(m, app._models); } var prefixedModel = (0, _prefixNamespace.default)((0, _objectSpread2.default)({}, m)); app._models.push(prefixedModel); return prefixedModel; } /** * Inject model after app is started. * * @param createReducer * @param onError * @param unlisteners * @param m */ function injectModel(createReducer, actions, onError, unlisteners, m) { m = model(m); var store = app._store; var onMutation = plugin.get('onMutation'); store.asyncReducers[m.namespace] = { mutations: (0, _getMutation.default)(m.mutations, onMutation, m), state: m.state }; store.replaceReducer(createReducer(store.asyncReducers)); if (m.actions) { actions[m.namespace] = app._getAction(m.actions, m, onError, plugin.get('onAction')); store.runAction(actions); } if (m.subscriptions) { unlisteners[m.namespace] = (0, _subscription.run)(m.subscriptions, m, app, onError); } } /** * Unregister model. * * @param createReducer * @param reducers * @param unlisteners * @param namespace * * Unexpected key warn problem: * https://github.com/reactjs/redux/issues/1636 */ function unmodel(createReducer, reducers, actions, unlisteners, namespace) { var store = app._store; // Delete reducers delete store.asyncReducers[namespace]; delete reducers[namespace]; delete actions[namespace]; store.replaceReducer(createReducer()); store.dispatch({ type: '@@genji/UPDATE' }); //reload actions store.runAction(actions); // Unlisten subscrioptions (0, _subscription.unlisten)(unlisteners, namespace); // Delete model from app._models app._models = app._models.filter(function (model) { return model.namespace !== namespace; }); } /** * Start the app. * * @returns void */ function start() { // Global error handler var onError = function onError(err, extension) { if (err) { if (typeof err === 'string') err = new Error(err); err.preventDefault = function () { err._dontReject = true; }; plugin.apply('onError', function (err) { throw new Error(err.stack || err); })(err, app._store.dispatch, extension); } }; var extraModels = plugin.get('extraModels'); extraModels.forEach(function (model) { app.model(model); }); var asyncMiddleware = (0, _createAsyncMiddleware.default)(); app._getAction = _getAction.default.bind(null); var actions = {}; var onMutation = plugin.get('onMutation'); var reducers = {}; var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = (0, _getIterator2.default)(app._models), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var m = _step.value; reducers[m.namespace] = { mutations: (0, _getMutation.default)(m.mutations, onMutation, m), state: m.state }; actions[m.namespace] = app._getAction(m.actions, m, onError, plugin.get('onAction')); } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return != null) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } var extraReducers = (0, _objectSpread2.default)({}, initialReducer, plugin.get('extraReducers')); (0, _invariant.default)((0, _keys.default)(extraReducers).every(function (key) { return !(key in reducers); }), "[app.start] extraReducers is conflict with other reducers, reducers list: ".concat((0, _keys.default)(reducers).join(', '))); // Create store var store = app._store = (0, _createStore.default)({ // eslint-disable-line reducers: createReducer(), initialState: hooksAndOpts.initialState || {}, plugin: plugin, createOpts: createOpts, asyncMiddleware: asyncMiddleware }); // Extend store store.runAction = asyncMiddleware.run; store.asyncReducers = {}; // Execute listeners when state is changed var listeners = plugin.get('onStateChange'); var _iteratorNormalCompletion2 = true; var _didIteratorError2 = false; var _iteratorError2 = undefined; try { var _loop = function _loop() { var listener = _step2.value; store.subscribe(function () { listener(store.getState()); }); }; for (var _iterator2 = (0, _getIterator2.default)(listeners), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { _loop(); } // Run sagas } catch (err) { _didIteratorError2 = true; _iteratorError2 = err; } finally { try { if (!_iteratorNormalCompletion2 && _iterator2.return != null) { _iterator2.return(); } } finally { if (_didIteratorError2) { throw _iteratorError2; } } } asyncMiddleware.run(actions); // Setup app setupApp(app); // Run subscriptions var unlisteners = {}; var _iteratorNormalCompletion3 = true; var _didIteratorError3 = false; var _iteratorError3 = undefined; try { for (var _iterator3 = (0, _getIterator2.default)(this._models), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { var _model = _step3.value; if (_model.subscriptions) { unlisteners[_model.namespace] = (0, _subscription.run)(_model.subscriptions, _model, app, onError); } } // Setup app.model and app.unmodel } catch (err) { _didIteratorError3 = true; _iteratorError3 = err; } finally { try { if (!_iteratorNormalCompletion3 && _iterator3.return != null) { _iterator3.return(); } } finally { if (_didIteratorError3) { throw _iteratorError3; } } } app.model = injectModel.bind(app, createReducer, actions, onError, unlisteners); app.unmodel = unmodel.bind(app, createReducer, reducers, actions, unlisteners); /** * Create global reducer for redux. * * @returns {Object} */ function createReducer() { var normalReducers; if ((0, _keys.default)(extraReducers).length != 0) { normalReducers = (0, _createImmerReducer.combineReducers)(extraReducers); } else { normalReducers = function normalReducers(state, action) { return state; }; } var mutations = (0, _createImmerReducer.default)(reducers); var asyncMutations; if (app._store) { asyncMutations = (0, _createImmerReducer.default)(app._store.asyncReducers); } else { asyncMutations = function asyncMutations(state, action) { return state; }; } return function (state, action) { state = normalReducers(state, action); state = mutations(state, action); state = asyncMutations(state, action); return state; }; } } }