UNPKG

vuex-help

Version:

a utilies library reduce boilerplate for vuex

583 lines (505 loc) 17 kB
/** * vuex-help v0.7.1 * (c) 2019 Steven Lin * @license MIT */ 'use strict'; function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } var Vue = _interopDefault(require('vue')); var ramda = require('ramda'); function normalizeMap (map) { return Array.isArray(map) ? map.map(function (key) { return ({ key: key, val: key }); }) : Object.keys(map).map(function (key) { return ({ key: key, val: map[key] }); }) } function isFunction (functionToCheck) { return functionToCheck && {}.toString.call(functionToCheck) === '[object Function]' || functionToCheck.constructor.name === 'AsyncFunction' } function normalizeNamespace (fn) { return function (namespace, map) { if (typeof namespace !== 'string') { map = namespace; namespace = ''; } else if (namespace.charAt(namespace.length - 1) !== '/') { namespace += '/'; } return fn(namespace, map) } } function getModuleByNamespace (store, helper, namespace) { var module = store._modulesNamespaceMap[namespace]; if (process.env.NODE_ENV !== 'production' && !module) { console.error(("[vuex] module namespace not found in " + helper + "(): " + namespace)); } return module } function objectWithoutProperties (obj, exclude) { var target = {}; for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k) && exclude.indexOf(k) === -1) target[k] = obj[k]; return target; } /** * get the object from selectors and pass the result to assert function as parameters. * @param selectors * @param assert * @returns {Function} */ var toHelper = function (key, obj) { if (obj === Object(obj)) { return obj; } var help = {}; help[key] = obj; if (obj === true) { help.invalid = obj; } else if (obj === false) { help.valid = obj; } return help }; function selectOn(selectors, assert) { return function (value, context) { var getters = context.getters; var entry = normalizeMap(selectors); var handler = function (ref) { var key = ref.key; var selector = ref.val; var data = getters[key]; if (selector instanceof Function) { data = selector(getters); } return data }; var values = entry.map(handler); if (value) { return assert.apply(void 0, values.concat( [value] )) } else { return assert.apply(void 0, values) } } } /** * create validation result base on validation of fields * @param dependsOn other fields * @param assert * @returns {Function} */ function dependsOn(dependsOn, assert) { return async function (context, value) { var getters = context.getters; var dispatch = context.dispatch; var handler = function (ref) { var key = ref.key; var assert = ref.val; var value = getters[key]; if (assert instanceof Function) { value = assert(value, context); } return dispatch('_help', {key: key, value: value}) }; var entry = normalizeMap(dependsOn); var helps = await Promise.all(entry.map(function (item) { return handler(item); })); if (assert) { return assert(helps, value) } var invalid = helps.some(function (help) { return help.invalid; }); if (invalid) { return {invalid: invalid} } return {valid: true} } } /** * * @param asserts * @param failFast * @returns {Function} */ function groupOn(asserts) { return async function (context, value) { var entry = normalizeMap(asserts); var helps = {}; for (var i = 0; i < entry.length; i++) { var ref = entry[i]; var assert = ref.val; var key = ref.key; var help = await assert(value, Object.assign({}, {helps: helps}, context)); var aHelp = toHelper(key, help); Object.assign(helps, aHelp); if (aHelp && aHelp.invalid) { delete helps.valid; helps.invalid = true; return helps } else { helps.valid = true; } } // todo: print out warning message if assert function returns null value if (!helps) { throw Error('validation function returns null object') } helps.valid = true; return helps } } var mapHelps = normalizeNamespace(function (namespace, map) { var res = {}; normalizeMap(map).forEach(function (ref) { var key = ref.key; var type = ref.val; // The namespace has been mutated by normalizeNamespace var val = namespace + '_mapHelp'; res[key + 'Help'] = function mappedGetter() { if (namespace && !getModuleByNamespace(this.$store, 'mapGetters', namespace)) { return } if (process.env.NODE_ENV !== 'production' && !(val in this.$store.getters)) { console.error(("[vuex] unknown getter: " + val)); return } return this.$store.getters[val](type) }; // mark vuex getter for devtools // res[key].vuex = true }); return res }); function mapHelpDelegates(options) { var helps = {}; normalizeMap(options).forEach(function (ref) { var key = ref.key; var val = ref.val; var isFunc = isFunction(val); if (isFunc) { helps[key] = val; } else { var noUse = val['default']; var rest = objectWithoutProperties( val, ['default'] ); var validators = rest; helps[key] = groupOn(validators); } }); return helps } var createActions = function (keys) { var actions = {}; keys.map(function (key) { actions[key] = function (context, value) {return context.commit(key, value)}; }); return actions; }; var createMutations = function (keys) { var actions = {}; keys.map(function (key) { actions[key] = function (state, value) { if(value && Array.isArray(value)) { Vue.set(state, key, [].concat( value )); } else { state[key] = value; } }; }); return actions; }; var createStateGetters = function (keys) { var getters = {}; keys.map(function (key) { return getters[key] = function (state){ return state[key]} }); return getters; }; var createMappedCommit = function (ref, key) { var commit = ref.commit; return function (value) { return Promise.resolve(value).then(function (data) { commit(key, data); return data; }) } }; var StoreFactory = function StoreFactory(ref) { var state = ref.state; var mutations = ref.mutations; var actions = ref.actions; var getters = ref.getters; this.keys = Object.keys(state); this.state = state; this.actions = createActions(this.keys); this.mutations = createMutations(this.keys); this.getters = createStateGetters(this.keys); this._actions = actions || {}; this._mutations = mutations || {}; this._getters = getters || {}; this._mutations = mutations || {}; }; StoreFactory.prototype.addActions = function addActions (actions) { Object.assign(this._actions, actions); return this; }; StoreFactory.prototype.addGetters = function addGetters (getters) { Object.assign(this._getters, getters); return this; }; StoreFactory.prototype.addMutations = function addMutations (mutations) { Object.assign(this._mutations, mutations); return this; }; StoreFactory.prototype.build = function build () { var this$1 = this; var userActions = normalizeMap(this._actions); // wrap auto generated action functions userActions.forEach(function (ref) { var key = ref.key; var val = ref.val; var generatedAction = this$1.actions[key]; var userAction = val; if (generatedAction) { userAction = function (context, value) { context.commitValue = createMappedCommit(context, key); val = val.bind(this); return val(context, value) }; } this$1.actions[key] = userAction; }); Object.assign(this.mutations, this._mutations); Object.assign(this.getters, this._getters); return { namespaced: true, state: this.state, getters: this.getters, actions: this.actions, mutations: this.mutations } }; function objectWithoutProperties$1 (obj, exclude) { var target = {}; for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k) && exclude.indexOf(k) === -1) target[k] = obj[k]; return target; } var action_help = '_help'; var helpActions = function (helpDelegates) { return { _helpReset: function (ref) { var commit = ref.commit; commit('_helpReset'); }, _help: async function (context, ref) { var key = ref.key; var value = ref.value; var helps = null; var delegate = helpDelegates[key]; context.$api = this.$api; if (delegate) { helps = await delegate(context, value) || {}; } if (!helps.invalid) { helps.valid = true; } context.commit(action_help, {key: key, helps: helps}); return helps }, _mapUpdate: function (context, ref) { var key = ref.key; var value = ref.value; context.dispatch(key, value); }, _helpUpdate: function (context, ref) { var key = ref.key; var value = ref.value; context.dispatch(key, value); } } }; var helpGetters = function (namespace) { return { _onlyModel: function (state, getters, rootState) { return function (modelName) { if ( modelName === void 0 ) modelName = namespace; var state = rootState[modelName]; return ramda.dissoc('_help', state); } }, _only: function (state, getters) { return function (props) { return props.reduce(function (a, e) { return (a[e] = getters[e], a); }, {}); } }, _onlyDirty: function (state) { return function (dirtyRule) { var dirtyProp = function (dirtyObject, parentKey) { if (Array.isArray(dirtyObject)) { return dirtyObject.map(function (item) { return dirtyProp(item); }).filter(function (item) { return Object.keys(item).length > 0; }) } var ref = Object(dirtyObject); var _help = ref._help; var rest = objectWithoutProperties$1( ref, ["_help"] ); var dirtyProps = rest; if (!_help) { return dirtyObject } var keys = Object.keys(dirtyProps).filter(function (key) { if (dirtyRule && dirtyRule(dirtyObject, key, parentKey)) { return true } var helpElement = _help[key]; if (!helpElement) { return true } return helpElement.dirty }); return keys.reduce(function (obj, key) { obj[key] = dirtyProp(dirtyObject[key], key); return obj }, {}) }; return dirtyProp(state) } }, _onlyHelps: function (state, getters) { return function (helps) { return helps.reduce(function (a, e) { return (a[(e + "Help")] = getters._mapHelp(e)); }, {}) } }, _helps: function (state, getters, rootState) { return state._help }, _mapHelp: function (state, getters, rootState) { return function (name) { var help = state._help[name]; var value = getters[name]; return { name: name, value: value, help: help, namespace: namespace } } }, _state: function (state, getters, rootState) { return state } } }; var helpMutations = { _update: function (state, value) { Object.keys(state).map(function (key) { if (value.hasOwnProperty(key)) { state[key] = value[key]; } }); }, _helpDirty: function (state, key) { var help = state._help[key]; help.dirty = true; state._help[key] = Object.assign({}, help); }, _help: function async (state, ref) { var key = ref.key; var helps = ref.helps; if ( helps === void 0 ) helps = {}; if (!helps) { return } var ref$1 = state._help[key]; var dirty = ref$1.dirty; var start = ref$1.start; if (!helps.invalid) { helps.valid = true; } var value = Object.assign({}, {dirty: dirty, start: start}, helps); state._help[key] = value; }, _helpError: function (state, ref) { var key = ref.key; var e = ref.e; var help = state._help[key]; help.invalid = true; help.error = e.message; if (e.response) { help.status = e.response.status; } delete help.valid; }, _helpStart: function (state, key) { var help = state._help[key]; help.start = true; }, _helpDone: function (state, key) { var help = state._help[key]; help.start = false; }, _helpClear: function (state, key) { state._help[key] = {}; }, _helpReset: function (state, key) { Object.keys(state._help).map(function (key) { state._help[key] = {}; }); } }; var helpHelpers = { helpActions: helpActions, helpGetters: helpGetters, helpMutations: helpMutations }; var commitHelps = function (key, context) { return function (value) { context.commit('_help', {key: key, helps: value}); return value } }; var createMappedCommit$1 = function (ref, key) { var commit = ref.commit; return function (value) { return Promise.resolve(value).then(function (data) { commit(key, data); return data; }) } }; var createModule = function (namespace, ref) { var state = ref.state; var mutations = ref.mutations; var actions = ref.actions; var getters = ref.getters; var helps = ref.helps; var factory = new StoreFactory({state: state, mutations: mutations, actions: actions, getters: getters}); var store = factory.build(); var action_helpStart = '_helpStart'; var action_helpDone = '_helpDone'; var action_helpDirty = '_helpDirty'; var action_helpError = '_helpError'; if (helps) { var helpDelegates = mapHelpDelegates(helps); var _help = {}; normalizeMap(store.actions).forEach(function (ref) { var key = ref.key; var action = ref.val; var option = helps[key]; _help[key] = option ? option.default || {} : {}; store.actions[key] = async function (context, value) { context.commit(action_helpStart, key); var helps = {}; if (helpDelegates[key]) { helps = await context.dispatch('_help', {key: key, value: value}); } context.helps = helps || {}; context.commitHelp = commitHelps(key, context); context.mappedCommit = createMappedCommit$1(context, key); try { action = action.bind(this); return await action(context, value) } catch (e) { context.commit(action_helpError, {key: key, e: e}); throw e } finally { context.commit(action_helpDirty, key); context.commit(action_helpDone, key); } }; }); Object.assign(state, {_help: _help}); Object.assign(store.mutations, helpHelpers.helpMutations); Object.assign(store.actions, helpHelpers.helpActions(helpDelegates)); Object.assign(store.getters, helpHelpers.helpGetters(namespace)); } return store; }; var index = { createModule: createModule, version: '0.7.1', selectOn: selectOn, dependsOn: dependsOn, groupOn: groupOn, mapHelps: mapHelps, validator: mapHelpDelegates }; module.exports = index;