UNPKG

redux-dux

Version:

``` npm i --save redux-dux ```

220 lines (176 loc) 6.89 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.update = undefined; exports.combine = combine; exports.dux = dux; exports.bindSelectors = bindSelectors; exports.createStore = createStore; var _redux = require('redux'); var redux = _interopRequireWildcard(_redux); var _lodash = require('lodash.snakecase'); var _lodash2 = _interopRequireDefault(_lodash); var _lodash3 = require('lodash.set'); var _lodash4 = _interopRequireDefault(_lodash3); var _lodash5 = require('lodash.reduce'); var _lodash6 = _interopRequireDefault(_lodash5); var _lodash7 = require('lodash.map'); var _lodash8 = _interopRequireDefault(_lodash7); var _lodash9 = require('lodash.get'); var _lodash10 = _interopRequireDefault(_lodash9); var _lodash11 = require('lodash.assign'); var _lodash12 = _interopRequireDefault(_lodash11); var _updateJs = require('update-js'); var _updateJs2 = _interopRequireDefault(_updateJs); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } /** * @module dux */ var store = void 0; var reducers = []; var combinedReducer = function combinedReducer(s) { return s; }; function duxReducer() { return combinedReducer.apply(undefined, arguments); } /** * Combines an array of reducers into one. * If reducer doesn't modify the state it should return its first * argument. In the case nothing is passed, the resulting * reducer will be an identity function. * @param {Function[]} [reducers] - Reducers to combine into one. */ function combine() { for (var _len = arguments.length, reducers = Array(_len), _key = 0; _key < _len; _key++) { reducers[_key] = arguments[_key]; } return function (state, action) { for (var i = 0; i < reducers.length; i += 1) { var newState = reducers[i](state, action); if (newState && newState !== state) { return newState; } } return state; }; } function sdbm(str) { var hash = 0; for (var i = 0; i < str.length; i++) { hash = str.charCodeAt(i) + (hash << 6) + (hash << 16) - hash; } hash = hash >>> 0; return hash.toString(16); } function hashKeys(o) { return sdbm((0, _lodash6.default)(o, function (acc, __, key) { return acc + key; }, '')); } var createReducerCreator = function createReducerCreator(nameToActionType, sliceKey) { return function (reduceFn, key) { var actionType = nameToActionType(key); return function (state, _ref) { var type = _ref.type, args = _ref.args; if (type !== actionType) return state; var slice = reduceFn.apply(undefined, [(0, _lodash10.default)(state, sliceKey)].concat(_toConsumableArray(args))); if (slice instanceof Function) { slice = slice(state); } return update(state, sliceKey, slice); }; }; }; // TODO(ET): deep-freeze slice in dev mode /** * Creates a Redux module. * @param {Object} options - set of key-value pairs, where key is an action * creator name and value is a reducer function. * The reducer function receives a slice of the state, corresponding * to the module, and arguments passed to the action creator: (slice, ...args). * The reducer function can return either a new slice or a function which * receives the whole state and returns a new slice. * */ function dux(options, selectors) { var hash = hashKeys(options); var nameToActionType = function nameToActionType(key) { return hash + '/' + (0, _lodash2.default)(key).toUpperCase(); }; var createReducer = createReducerCreator(nameToActionType, hash); var createAction = function createAction(key) { return function () { for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { args[_key2] = arguments[_key2]; } return store.dispatch({ type: nameToActionType(key), args: args }); }; }; var createSelector = function createSelector(fn) { return function (state) { return fn((0, _lodash10.default)(state, hash)); }; }; var self = (0, _lodash6.default)(options, function (acc, val, key) { return (0, _lodash4.default)(acc, key, createAction(key)); }, {}); self.selectors = (0, _lodash6.default)(selectors, function (acc, val, key) { var selector = createSelector(val); return (0, _lodash4.default)(acc, key, selector); }, {}); self.extend = function (duck, selectors) { var __ = duck.selectors, actions = _objectWithoutProperties(duck, ['selectors']); (0, _lodash12.default)(this, actions); (0, _lodash12.default)(this.selectors, selectors); return this; }; reducers.push(combine.apply(undefined, _toConsumableArray((0, _lodash8.default)(options, createReducer)))); combinedReducer = combine.apply(undefined, reducers); return self; } function bindSelectors() { for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { args[_key3] = arguments[_key3]; } var selectorsArr = args.slice(0, args.length - 1); var cb = args[args.length - 1]; return function (state) { var sliceGetters = selectorsArr.map(function (selectors) { return Object.defineProperties({}, (0, _lodash6.default)(selectors, function (acc, selector, name) { return (0, _lodash4.default)(acc, name, { get: function get() { return selector(state); } }); }, {})); }); return cb.apply(undefined, _toConsumableArray(sliceGetters)); }; } /** * Creates Redux store. * See [createStore.md](https://github.com/reduxjs/redux/blob/master/docs/api/createStore.md). */ function createStore(reducer, preloadedState, enhancers) { if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') { enhancers = preloadedState; preloadedState = undefined; } // TODO: what if createStore is called multiple times? reducers.push(reducer); combinedReducer = combine.apply(undefined, reducers); return store = redux.createStore(duxReducer, preloadedState, enhancers); } /** * Object immutability helper. * See [update-js](https://github.com/akuzko/update-js). */ var update = exports.update = _updateJs2.default;