vuex-help
Version:
a utilies library reduce boilerplate for vuex
583 lines (505 loc) • 17 kB
JavaScript
/**
* vuex-help v0.7.1
* (c) 2019 Steven Lin
* @license MIT
*/
;
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;