redux-tiles
Version:
Library to create and easily compose redux pieces together in less verbose manner
1,040 lines (963 loc) • 34.3 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(factory((global.ReduxTiles = global.ReduxTiles || {})));
}(this, (function (exports) { 'use strict';
function isArray(arrayToCheck) {
return Array.isArray(arrayToCheck);
}
function isString(stringToCheck) {
return typeof stringToCheck === "string";
}
function isFunction(functionToCheck) {
return typeof functionToCheck === "function";
}
function get(object, path) {
return path.reduce(function (res, key) {
if (!res) {
return undefined;
}
return res[key];
}, object);
}
function mapValues(object, cb) {
return Object.keys(object).reduce(function (hash, key) {
var value = object[key];
hash[key] = cb(value);
return hash;
}, {});
}
function ensureArray(value) {
return isString(value) ? [value] : value;
}
function populateHash(hash, path, value) {
if (isString(path)) {
return populateHash(hash, [path], value);
}
if (path.length === 1) {
hash[path[0]] = value;
return hash;
}
var property = path[0];
if (!hash[property]) {
hash[property] = {};
}
return populateHash(hash[property], path.slice(1), value);
}
function iterate(tiles) {
return isArray(tiles) ? tiles : Object.keys(tiles).reduce(function (arr, key) {
var values = tiles[key];
return arr.concat(values);
}, []);
}
function capitalize(str, i) {
if (i === 0) {
return str;
}
return str[0].toUpperCase() + str.slice(1);
}
function createType(_a) {
var type = _a.type,
path = _a.path;
var list = ensureArray(type).concat(path == null ? [] : path.map(String));
return list.map(capitalize).join("");
}
function createActions(tiles) {
// this storage will keep all promises
// so if the request is already in progress,
// we could still await it
return iterate(tiles).reduce(function (hash, tile) {
populateHash(hash, tile.tileName, tile.action);
return hash;
}, {});
}
/** Detect free variable `global` from Node.js. */
var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;
/** Detect free variable `self`. */
var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
/** Used as a reference to the global object. */
var root = freeGlobal || freeSelf || Function('return this')();
/** Built-in value references. */
var Symbol$1 = root.Symbol;
/** Used for built-in method references. */
var objectProto$1 = Object.prototype;
/** Used to check objects for own properties. */
var hasOwnProperty$1 = objectProto$1.hasOwnProperty;
/**
* Used to resolve the
* [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
* of values.
*/
var nativeObjectToString = objectProto$1.toString;
/** Built-in value references. */
var symToStringTag$1 = Symbol$1 ? Symbol$1.toStringTag : undefined;
/**
* A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
*
* @private
* @param {*} value The value to query.
* @returns {string} Returns the raw `toStringTag`.
*/
function getRawTag(value) {
var isOwn = hasOwnProperty$1.call(value, symToStringTag$1),
tag = value[symToStringTag$1];
try {
value[symToStringTag$1] = undefined;
var unmasked = true;
} catch (e) {}
var result = nativeObjectToString.call(value);
if (unmasked) {
if (isOwn) {
value[symToStringTag$1] = tag;
} else {
delete value[symToStringTag$1];
}
}
return result;
}
/** Used for built-in method references. */
var objectProto$2 = Object.prototype;
/**
* Used to resolve the
* [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
* of values.
*/
var nativeObjectToString$1 = objectProto$2.toString;
/**
* Converts `value` to a string using `Object.prototype.toString`.
*
* @private
* @param {*} value The value to convert.
* @returns {string} Returns the converted string.
*/
function objectToString(value) {
return nativeObjectToString$1.call(value);
}
/** `Object#toString` result references. */
var nullTag = '[object Null]';
var undefinedTag = '[object Undefined]';
/** Built-in value references. */
var symToStringTag = Symbol$1 ? Symbol$1.toStringTag : undefined;
/**
* The base implementation of `getTag` without fallbacks for buggy environments.
*
* @private
* @param {*} value The value to query.
* @returns {string} Returns the `toStringTag`.
*/
function baseGetTag(value) {
if (value == null) {
return value === undefined ? undefinedTag : nullTag;
}
return (symToStringTag && symToStringTag in Object(value))
? getRawTag(value)
: objectToString(value);
}
/**
* Creates a unary function that invokes `func` with its argument transformed.
*
* @private
* @param {Function} func The function to wrap.
* @param {Function} transform The argument transform.
* @returns {Function} Returns the new function.
*/
function overArg(func, transform) {
return function(arg) {
return func(transform(arg));
};
}
/** Built-in value references. */
var getPrototype = overArg(Object.getPrototypeOf, Object);
/**
* Checks if `value` is object-like. A value is object-like if it's not `null`
* and has a `typeof` result of "object".
*
* @static
* @memberOf _
* @since 4.0.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is object-like, else `false`.
* @example
*
* _.isObjectLike({});
* // => true
*
* _.isObjectLike([1, 2, 3]);
* // => true
*
* _.isObjectLike(_.noop);
* // => false
*
* _.isObjectLike(null);
* // => false
*/
function isObjectLike(value) {
return value != null && typeof value == 'object';
}
/** `Object#toString` result references. */
var objectTag = '[object Object]';
/** Used for built-in method references. */
var funcProto = Function.prototype;
var objectProto = Object.prototype;
/** Used to resolve the decompiled source of functions. */
var funcToString = funcProto.toString;
/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;
/** Used to infer the `Object` constructor. */
var objectCtorString = funcToString.call(Object);
/**
* Checks if `value` is a plain object, that is, an object created by the
* `Object` constructor or one with a `[[Prototype]]` of `null`.
*
* @static
* @memberOf _
* @since 0.8.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
* @example
*
* function Foo() {
* this.a = 1;
* }
*
* _.isPlainObject(new Foo);
* // => false
*
* _.isPlainObject([1, 2, 3]);
* // => false
*
* _.isPlainObject({ 'x': 0, 'y': 0 });
* // => true
*
* _.isPlainObject(Object.create(null));
* // => true
*/
function isPlainObject(value) {
if (!isObjectLike(value) || baseGetTag(value) != objectTag) {
return false;
}
var proto = getPrototype(value);
if (proto === null) {
return true;
}
var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor;
return typeof Ctor == 'function' && Ctor instanceof Ctor &&
funcToString.call(Ctor) == objectCtorString;
}
function symbolObservablePonyfill(root) {
var result;
var Symbol = root.Symbol;
if (typeof Symbol === 'function') {
if (Symbol.observable) {
result = Symbol.observable;
} else {
result = Symbol('observable');
Symbol.observable = result;
}
} else {
result = '@@observable';
}
return result;
}
/* global window */
var root$2;
if (typeof self !== 'undefined') {
root$2 = self;
} else if (typeof window !== 'undefined') {
root$2 = window;
} else if (typeof global !== 'undefined') {
root$2 = global;
} else if (typeof module !== 'undefined') {
root$2 = module;
} else {
root$2 = Function('return this')();
}
var result = symbolObservablePonyfill(root$2);
/**
* These are private action types reserved by Redux.
* For any unknown actions, you must return the current state.
* If the current state is undefined, you must return the initial state.
* Do not reference these action types directly in your code.
*/
var ActionTypes = {
INIT: '@@redux/INIT'
};
/**
* Prints a warning in the console if it exists.
*
* @param {String} message The warning message.
* @returns {void}
*/
function warning(message) {
/* eslint-disable no-console */
if (typeof console !== 'undefined' && typeof console.error === 'function') {
console.error(message);
}
/* eslint-enable no-console */
try {
// This error was thrown as a convenience so that if you enable
// "break on all exceptions" in your console,
// it would pause the execution at this line.
throw new Error(message);
/* eslint-disable no-empty */
} catch (e) {}
/* eslint-enable no-empty */
}
function getUndefinedStateErrorMessage(key, action) {
var actionType = action && action.type;
var actionName = actionType && '"' + actionType.toString() + '"' || 'an action';
return 'Given action ' + actionName + ', reducer "' + key + '" returned undefined. ' + 'To ignore an action, you must explicitly return the previous state.';
}
function getUnexpectedStateShapeWarningMessage(inputState, reducers, action, unexpectedKeyCache) {
var reducerKeys = Object.keys(reducers);
var argumentName = action && action.type === ActionTypes.INIT ? 'preloadedState argument passed to createStore' : 'previous state received by the reducer';
if (reducerKeys.length === 0) {
return 'Store does not have a valid reducer. Make sure the argument passed ' + 'to combineReducers is an object whose values are reducers.';
}
if (!isPlainObject(inputState)) {
return 'The ' + argumentName + ' has unexpected type of "' + {}.toString.call(inputState).match(/\s([a-z|A-Z]+)/)[1] + '". Expected argument to be an object with the following ' + ('keys: "' + reducerKeys.join('", "') + '"');
}
var unexpectedKeys = Object.keys(inputState).filter(function (key) {
return !reducers.hasOwnProperty(key) && !unexpectedKeyCache[key];
});
unexpectedKeys.forEach(function (key) {
unexpectedKeyCache[key] = true;
});
if (unexpectedKeys.length > 0) {
return 'Unexpected ' + (unexpectedKeys.length > 1 ? 'keys' : 'key') + ' ' + ('"' + unexpectedKeys.join('", "') + '" found in ' + argumentName + '. ') + 'Expected to find one of the known reducer keys instead: ' + ('"' + reducerKeys.join('", "') + '". Unexpected keys will be ignored.');
}
}
function assertReducerSanity(reducers) {
Object.keys(reducers).forEach(function (key) {
var reducer = reducers[key];
var initialState = reducer(undefined, { type: ActionTypes.INIT });
if (typeof initialState === 'undefined') {
throw new Error('Reducer "' + key + '" returned undefined during initialization. ' + 'If the state passed to the reducer is undefined, you must ' + 'explicitly return the initial state. The initial state may ' + 'not be undefined.');
}
var type = '@@redux/PROBE_UNKNOWN_ACTION_' + Math.random().toString(36).substring(7).split('').join('.');
if (typeof reducer(undefined, { type: type }) === 'undefined') {
throw new Error('Reducer "' + key + '" returned undefined when probed with a random type. ' + ('Don\'t try to handle ' + ActionTypes.INIT + ' or other actions in "redux/*" ') + 'namespace. They are considered private. Instead, you must return the ' + 'current state for any unknown actions, unless it is undefined, ' + 'in which case you must return the initial state, regardless of the ' + 'action type. The initial state may not be undefined.');
}
});
}
/**
* Turns an object whose values are different reducer functions, into a single
* reducer function. It will call every child reducer, and gather their results
* into a single state object, whose keys correspond to the keys of the passed
* reducer functions.
*
* @param {Object} reducers An object whose values correspond to different
* reducer functions that need to be combined into one. One handy way to obtain
* it is to use ES6 `import * as reducers` syntax. The reducers may never return
* undefined for any action. Instead, they should return their initial state
* if the state passed to them was undefined, and the current state for any
* unrecognized action.
*
* @returns {Function} A reducer function that invokes every reducer inside the
* passed object, and builds a state object with the same shape.
*/
function combineReducers(reducers) {
var reducerKeys = Object.keys(reducers);
var finalReducers = {};
for (var i = 0; i < reducerKeys.length; i++) {
var key = reducerKeys[i];
{
if (typeof reducers[key] === 'undefined') {
warning('No reducer provided for key "' + key + '"');
}
}
if (typeof reducers[key] === 'function') {
finalReducers[key] = reducers[key];
}
}
var finalReducerKeys = Object.keys(finalReducers);
{
var unexpectedKeyCache = {};
}
var sanityError;
try {
assertReducerSanity(finalReducers);
} catch (e) {
sanityError = e;
}
return function combination() {
var state = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
var action = arguments[1];
if (sanityError) {
throw sanityError;
}
{
var warningMessage = getUnexpectedStateShapeWarningMessage(state, finalReducers, action, unexpectedKeyCache);
if (warningMessage) {
warning(warningMessage);
}
}
var hasChanged = false;
var nextState = {};
for (var i = 0; i < finalReducerKeys.length; i++) {
var key = finalReducerKeys[i];
var reducer = finalReducers[key];
var previousStateForKey = state[key];
var nextStateForKey = reducer(previousStateForKey, action);
if (typeof nextStateForKey === 'undefined') {
var errorMessage = getUndefinedStateErrorMessage(key, action);
throw new Error(errorMessage);
}
nextState[key] = nextStateForKey;
hasChanged = hasChanged || nextStateForKey !== previousStateForKey;
}
return hasChanged ? nextState : state;
};
}
/**
* Composes single-argument functions from right to left. The rightmost
* function can take multiple arguments as it provides the signature for
* the resulting composite function.
*
* @param {...Function} funcs The functions to compose.
* @returns {Function} A function obtained by composing the argument functions
* from right to left. For example, compose(f, g, h) is identical to doing
* (...args) => f(g(h(...args))).
*/
/*
* This is a dummy function to check if the function name has been altered by minification.
* If the function has been minified and NODE_ENV !== 'production', warn the user.
*/
function isCrushed() {}
if ("development" !== 'production' && typeof isCrushed.name === 'string' && isCrushed.name !== 'isCrushed') {
warning('You are currently using minified code outside of NODE_ENV === \'production\'. ' + 'This means that you are running a slower development build of Redux. ' + 'You can use loose-envify (https://github.com/zertosh/loose-envify) for browserify ' + 'or DefinePlugin for webpack (http://stackoverflow.com/questions/30030031) ' + 'to ensure you have the correct code for your production build.');
}
var DEFAULT_REDUCER = "";
function changeDefaultReducer(newReducer) {
DEFAULT_REDUCER = newReducer;
}
function checkValue(result, defaultValue) {
return result === undefined || result === null ? defaultValue : result;
}
/**
* @overview Deep lookup inside state
* @param {Object} state – current redux state object
* @param {Any} params – argument with which action was dispatched
* @param {Function} nesting – function to create nested data inside store
* @param {String} tileName – string to access module data
* @return {Object} – stored data
*/
function lookup(_a) {
var state = _a.state,
params = _a.params,
nesting = _a.nesting,
tileName = _a.tileName,
selectorFallback = _a.selectorFallback;
var path = [];
var topReducer = DEFAULT_REDUCER;
if (nesting) {
path = nesting(params);
}
var nestedNames = ensureArray(tileName);
var topReducerArray = Boolean(topReducer) ? [topReducer] : [];
return checkValue(get(state, topReducerArray.concat(nestedNames, path)), selectorFallback);
}
/**
* @overview check passed arguments to the Selector function.
* The single purpose is for readability, to throw sane error
* @param {Object} state – redux state
* @param {Any} params – argument with which action was dispatched
* @param {String} tileName – string to access module data
* @param {Function} fn – function to invoke if check was passed
* @return {Any} – result of function invokation
*/
function checkArguments(_a) {
var state = _a.state,
params = _a.params,
tileName = _a.tileName,
fn = _a.fn;
if (!state) {
throw new Error("\n Error in Redux-Tiles Selector \u2013 you have to provide\n state as a first argument!. Error in \"" + createType({
type: tileName
}) + "\" tile.");
}
return fn(state, params);
}
/**
* @overview function to create selectors for modules
* @param {String} tileName – string to access module data
* @param {Function} nesting – function to create nested data inside store
* @return {Object} – object with selectors for all and specific data
*/
function createSelectors(_a) {
var tileName = _a.tileName,
nesting = _a.nesting,
selectorFallback = _a.selectorFallback;
var _getAll = function _getAll(state) {
var topReducerArray = Boolean(DEFAULT_REDUCER) ? [DEFAULT_REDUCER] : [];
return checkValue(get(state, topReducerArray.concat(ensureArray(tileName))));
};
var getSpecific = function getSpecific(state, params) {
return lookup({ state: state, params: params, nesting: nesting, tileName: tileName, selectorFallback: selectorFallback });
};
return {
getAll: function getAll(state) {
return checkArguments({ state: state, tileName: tileName, fn: _getAll });
},
get: function get$$1(state, params) {
return checkArguments({ state: state, params: params, tileName: tileName, fn: getSpecific });
}
};
}
function createNestedReducers(value) {
return combineReducers(Object.keys(value).reduce(function (hash, key) {
var elem = value[key];
hash[key] = isFunction(elem) ? elem : createNestedReducers(elem);
return hash;
}, {}));
}
function createReducers(modules, topReducer) {
if (topReducer === void 0) {
topReducer = DEFAULT_REDUCER;
}
if (topReducer !== DEFAULT_REDUCER) {
changeDefaultReducer(topReducer);
}
var nestedModules = iterate(modules).reduce(function (hash, module) {
populateHash(hash, module.tileName, module.reducer);
return hash;
}, {});
return createNestedReducers(nestedModules);
}
function createSelectors$1(tiles) {
return iterate(tiles).reduce(function (hash, tile) {
var selector = tile.selectors.get;
selector.getAll = tile.selectors.getAll;
populateHash(hash, tile.tileName, selector);
return hash;
}, {});
}
function createEntities(tiles, topReducer) {
return {
actions: createActions(tiles),
reducer: createReducers(tiles, topReducer),
selectors: createSelectors$1(tiles)
};
}
function waitTiles(promisesStorage) {
var promises = Object.keys(promisesStorage).map(function (key) {
return promisesStorage[key];
}).filter(Boolean);
return Promise.all(promises);
}
var __assign = undefined && undefined.__assign || Object.assign || function (t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) {
if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
}
return t;
};
function createMiddleware(paramsToInject) {
if (paramsToInject === void 0) {
paramsToInject = {};
}
var promisesStorage = {};
var middleware = function middleware(_a) {
var dispatch = _a.dispatch,
getState = _a.getState;
return function (next) {
return function (action) {
if (typeof action === "function") {
return action(__assign({ dispatch: dispatch, getState: getState, promisesStorage: promisesStorage }, paramsToInject));
}
return next(action);
};
};
};
return {
middleware: middleware,
waitTiles: waitTiles.bind(null, promisesStorage)
};
}
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
return typeof obj;
} : function (obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
var __assign$2 = undefined && undefined.__assign || Object.assign || function (t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) {
if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
}
return t;
};
var __rest = undefined && undefined.__rest || function (s, e) {
var t = {};
for (var p in s) {
if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p];
}if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0) t[p[i]] = s[p[i]];
}return t;
};
function proccessMiddleware(args) {
if (args.length === 3) {
// let's assume it is redux-thunk with extra argument
return __assign$2({ dispatch: args[0], getState: args[1] }, args[2]);
} else if (args.length === 2) {
// likely it is redux-thunk
return { dispatch: args[0], getState: args[1] };
} else if (args.length === 1 && _typeof(args[0]) === "object") {
// our own middleware
return args[0];
}
// no idea what it is
throw new Error("Redux-Tiles expects own middleware, or redux-thunk");
}
function shouldBeFetched(_a) {
var isPending = _a.isPending,
fetched = _a.fetched,
error = _a.error;
// if it is pending, then we have to wait anyway
if (isPending) {
return false;
}
// in case it was not fetched yet, we have to fetch it for the first time
if (fetched === false) {
return true;
}
// and if error is not null or undefined, we have to re-fetch it again
if (error != null) {
return true;
}
return false;
}
function handleMiddleware(fn) {
return function (fnParams, additionalParams) {
return function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
return fn(proccessMiddleware(args), fnParams, additionalParams);
};
};
}
function asyncAction(_a) {
var START = _a.START,
SUCCESS = _a.SUCCESS,
FAILURE = _a.FAILURE,
fn = _a.fn,
type = _a.type,
caching = _a.caching,
nesting = _a.nesting,
selectors = _a.selectors;
return handleMiddleware(function (_a, params, _b) {
var forceAsync = (_b === void 0 ? {} : _b).forceAsync;
var dispatch = _a.dispatch,
getState = _a.getState,
_c = _a.promisesStorage,
promisesStorage = _c === void 0 ? {} : _c,
middlewares = __rest(_a, ["dispatch", "getState", "promisesStorage"]);
var path = nesting ? nesting(params) : null;
var getIdentificator = createType({ type: type, path: path });
if (caching) {
var activePromise = promisesStorage[getIdentificator];
if (activePromise) {
return activePromise;
}
}
if (caching && !forceAsync) {
var _d = selectors.get(getState(), params),
isPending = _d.isPending,
fetched = _d.fetched,
error = _d.error,
data = _d.data;
var isFetchingNeeded = shouldBeFetched({
isPending: isPending,
fetched: fetched,
error: error
});
if (!isFetchingNeeded) {
return Promise.resolve({ data: data, error: error, isPending: isPending });
}
}
dispatch({
type: START,
payload: { path: path },
isPending: true
});
var promise = fn(__assign$2({ params: params,
dispatch: dispatch,
getState: getState }, middlewares)).then(function (data) {
promisesStorage[getIdentificator] = undefined;
return dispatch({
type: SUCCESS,
payload: { path: path, data: data },
data: data,
isPending: false
});
}).catch(function (error) {
promisesStorage[getIdentificator] = undefined;
return dispatch({
error: error,
type: FAILURE,
payload: { path: path },
isPending: false
});
});
promisesStorage[getIdentificator] = promise;
return promise;
});
}
function createResetAction(_a) {
var type = _a.type;
return handleMiddleware(function (_a) {
var dispatch = _a.dispatch;
return dispatch({ type: type });
});
}
function syncAction(_a) {
var SET = _a.SET,
fn = _a.fn,
nesting = _a.nesting,
selector = _a.selector;
return handleMiddleware(function (_a, params) {
var dispatch = _a.dispatch,
getState = _a.getState,
middlewares = __rest(_a, ["dispatch", "getState"]);
var path = nesting ? nesting(params) : null;
var getData = function getData() {
return selector(getState(), params);
};
var data = fn(__assign$2({ params: params,
dispatch: dispatch,
getState: getState,
getData: getData }, middlewares));
return dispatch({
type: SET,
payload: {
path: path,
data: data
},
data: data
});
});
}
var __assign$3 = undefined && undefined.__assign || Object.assign || function (t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) {
if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
}
return t;
};
/**
* @overview create reducer function from the object
* @param {Any} initialState – initial state of this part of the store
* @param {Object} handlers – object with keys as action types, and
* reduce functions to change store as values
* @return {Function} – function to act as a reducer
*/
function createReducerFromObject(initialState, handlers) {
return function reducer(state, action) {
if (state === void 0) {
state = initialState;
}
var handler = handlers[action.type];
return typeof handler === "function" ? handler(state, action) : state;
};
}
/**
* @overview create reducer from the object, with creating reducing functions
* @param {Any} initialState – initial state of this part of the store
* @param {Object} handlers – object with keys as action types, and
* newValues to set at store as values
* @return {Function} – function to act as a reducer
*/
function createReducer(initialState, handlers) {
return createReducerFromObject(initialState, mapValues(handlers, function (value) {
return function (state, action) {
return reducerCreator({
state: state,
action: action,
newValue: isFunction(value) ? value(state, action) : value
});
};
}));
}
/**
* @overview reducer function, which changes the state with new values
* @param {Object} action – reducer action object, with type and payload
* @param {Object} state – previous redux state in this branch
* @param {Any} newValue – new value to set up in state in corresponding path
* @return {Object} – changed reducer
*/
function reducerCreator(_a) {
var action = _a.action,
state = _a.state,
newValue = _a.newValue;
var path = action.payload.path;
var hasNoNestInStore = !path;
if (hasNoNestInStore) {
return newValue;
}
var result = {};
var lookupPath;
var length = path.length;
for (var i = length - 1; i >= 0; i = i - 1) {
var el = path[i];
var isLastItem = i === path.length - 1;
var newNestedResult = (_b = {}, _b[el] = isLastItem ? newValue : result, _b);
lookupPath = path.slice(0, i);
var oldState = get(state, lookupPath) || {};
result = __assign$3({}, oldState, newNestedResult);
}
return __assign$3({}, state, result);
var _b;
}
var __assign$1 = undefined && undefined.__assign || Object.assign || function (t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) {
if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
}
return t;
};
var prefix = "Redux_Tiles_";
function createTile(params) {
var type = params.type,
fn = params.fn,
caching = params.caching,
nesting = params.nesting,
_a = params.selectorFallback,
selectorFallback = _a === void 0 ? null : _a;
// initial state is equal to empty object, because of possible nesting
// basically every object should contain default properties, so we handle
// this situation using selectors
var initialState = nesting ? {} : null;
var identificator = createType({ type: type });
var types = {
START: "" + prefix + identificator + "_START",
SUCCESS: "" + prefix + identificator + "_SUCCESS",
FAILURE: "" + prefix + identificator + "_FAILURE",
RESET: "" + prefix + identificator + "_RESET"
};
var selectorParams = {
selectorFallback: {
isPending: false,
error: null,
data: selectorFallback,
fetched: false
},
tileName: type,
nesting: nesting
};
var selectors = createSelectors(selectorParams);
var actionParams = {
START: types.START,
SUCCESS: types.SUCCESS,
FAILURE: types.FAILURE,
fn: fn,
type: type,
caching: caching,
nesting: nesting,
selectors: selectors
};
var action = asyncAction(actionParams);
action.reset = createResetAction({ type: types.RESET });
var reducerObject = (_b = {}, _b[types.START] = {
data: null,
isPending: true,
error: null,
fetched: false
}, _b[types.FAILURE] = function (_storeState, storeAction) {
return {
data: null,
isPending: false,
error: storeAction.error,
fetched: true
};
}, _b[types.SUCCESS] = function (_storeState, storeAction) {
return {
error: null,
isPending: false,
data: storeAction.payload && storeAction.payload.data,
fetched: true
};
}, _b[types.RESET] = initialState, _b);
var reducer = createReducer(initialState, reducerObject);
return {
action: action,
reducer: reducer,
selectors: selectors,
tileName: type,
constants: types,
reflect: params
};
var _b;
}
function createSyncTile(params) {
var type = params.type,
nesting = params.nesting,
_a = params.fn,
fn = _a === void 0 ? function (fnParams) {
return fnParams.params;
} : _a,
fns = params.fns,
// we have default state as an object because of the possible nesting
_b = params.initialState,
// we have default state as an object because of the possible nesting
initialState = _b === void 0 ? nesting ? {} : null : _b,
selectorFallback = params.selectorFallback;
var identificator = createType({ type: type });
var types = {
SET: "" + prefix + identificator + "_SET",
RESET: "" + prefix + identificator + "_RESET"
};
var selectorParams = {
selectorFallback: selectorFallback,
tileName: type,
nesting: nesting
};
var selectors = createSelectors(selectorParams);
var actionParams = {
SET: types.SET,
nesting: nesting,
fn: fn,
selector: selectors.get
};
var action = syncAction(actionParams);
action.reset = createResetAction({ type: types.RESET });
if (fns) {
Object.keys(fns).forEach(function (methodName) {
var method = fns[methodName];
var customActionParams = __assign$1({}, actionParams, { fn: method });
action[methodName] = syncAction(customActionParams);
});
}
var reducerObject = (_c = {}, _c[types.SET] = function (_storeState, storeAction) {
return storeAction.payload && storeAction.payload.data;
}, _c[types.RESET] = initialState, _c);
var reducer = createReducer(initialState, reducerObject);
return {
action: action,
selectors: selectors,
reducer: reducer,
tileName: type,
constants: types,
reflect: params
};
var _c;
}
exports.createTile = createTile;
exports.createSyncTile = createSyncTile;
exports.createReducers = createReducers;
exports.createActions = createActions;
exports.createSelectors = createSelectors$1;
exports.createMiddleware = createMiddleware;
exports.createEntities = createEntities;
Object.defineProperty(exports, '__esModule', { value: true });
})));