UNPKG

redux-tiles

Version:

Library to create and easily compose redux pieces together in less verbose manner

97 lines (81 loc) 3.27 kB
import { get, isString } from 'lodash'; import { createType, ensureArray } from '../helpers'; import { ICreateSelectorsTypes, IData, ISelectors, SyncData } from './types'; export let DEFAULT_REDUCER: string = ''; export function changeDefaultReducer(newReducer: string): void { DEFAULT_REDUCER = newReducer; } function checkValue(result: any, defaultValue?: any): {} { return result === undefined || result === null ? defaultValue : result; } interface ILookupParams { selectorFallback: any; state: Object; params: any; nesting: ((params: any) => string[])|undefined; tileName: string|string[]; } /** * @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({ state, params, nesting, tileName, selectorFallback }: ILookupParams): IData|SyncData { let path: string[] = []; const topReducer: string = DEFAULT_REDUCER; if (nesting) { path = nesting(params); } const nestedNames: string[] = ensureArray(tileName); const topReducerArray: string[] = Boolean(topReducer) ? [topReducer] : []; return checkValue(get(state, [...topReducerArray, ...nestedNames, ...path]), selectorFallback); } interface ICheckArgumentsParams { state: {}; params: any; tileName: string|string[]; fn: Function; } /** * @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({ state, params, tileName, fn }: ICheckArgumentsParams): {} { if (!state) { throw new Error(` Error in Redux-Tiles Selector – you have to provide 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 */ export function createSelectors( { tileName, nesting, selectorFallback }: ICreateSelectorsTypes ): ISelectors { const getAll: Function = (state: any): any => { const topReducerArray: string[] = Boolean(DEFAULT_REDUCER) ? [DEFAULT_REDUCER] : []; return checkValue(get(state, [...topReducerArray, ...ensureArray(tileName)])); }; const getSpecific: Function = (state: {}, params: any): IData|SyncData => lookup({ state, params, nesting, tileName, selectorFallback }); return { getAll: (state: any): {} => checkArguments({ state, tileName, fn: getAll } as any), get: (state: any, params?: any): IData|SyncData => checkArguments({ state, params, tileName, fn: getSpecific }) }; }