UNPKG

skypager-project

Version:
119 lines (94 loc) 3.1 kB
import stringify from "./stringify"; import { pluralize } from 'skypager-util/lib/string' import mapKeys from 'lodash/mapKeys' import mapValues from 'lodash/mapValues' import reduce from 'lodash/reduce' import isUndefined from 'lodash/isUndefined' const featuresReq = require.context('./features', false, /\.js$/) const reducersReq = require.context('./reducers', false, /\.js$/) const es6 = (mod) => mod.default ? mod.default : mod export const defaultFeatures = featuresReq .keys() .reduce((memo, key) => ({ ...memo, [key.replace(/\.\//,'').replace(/\.js$/,'')]: es6(featuresReq(key)), }), {}) export const defaultReducers = reducersReq .keys() .reduce((memo, key) => ({ ...memo, [key.replace(/\.\//,'').replace(/\.js$/,'')]: es6(reducersReq(key)), }), {}) export function api(options = {}) { let { history = [], scope = this, features = {}, reducers = {}, keyFn = pluralize } = options features = mapValues({ ...defaultFeatures, ...features }, (fn) => fn.bind ? fn.bind(scope) : fn); reducers = mapValues({ ...defaultReducers, ...reducers }, (fn) => fn.bind ? fn.bind(scope) : fn); const getState = () => { const initialState = reduce(features, (acc, feature, name) => { const defaultValue = feature(); if (isUndefined(defaultValue)) { return acc; } return { ...acc, [name]: defaultValue, }; }, {}); const state = history.reduce((acc, { name, args }) => { const featureState = acc[name]; const feature = features[name]; return { ...acc, [name]: feature(featureState, ...args), }; }, initialState); Object.defineProperty(state, "toString", { value: () => stringify(state), }); return state; }; const getConfig = (tap = options.tap) => { const state = getState(); let config = reduce(reducers, (config, reducer, name) => { const reduced = reducer(state); if (isUndefined(reduced)) { return config; } return { ...config, [name]: reducer(state), }; }, {}); if (typeof tap === 'function') { config = tap.call(scope, config, options) } Object.defineProperty(config, "toString", { value: () => stringify(config), }); return config; }; const when = (env, configure) => { const envs = Array.isArray(env) ? env : [env]; const { NODE_ENV = "development" } = process.env; if (env === true || envs.indexOf(NODE_ENV) !== -1) { return configure(api({features,reducers,history})); } else if (typeof env === 'function' && env(getState(), getConfig)) { return configure({features, reducers, history}) } return api({features, reducers, history}); }; return reduce(features, (acc, feature, name) => ({ ...acc, [name]: (...args) => api({ features, reducers, history: history.concat({ args, name }), }), }), { getConfig: (...args) => mapKeys(getConfig(...args),(v,k) => keyFn(k)), getState, history, when, }); } export default api