vuex-pathify
Version:
Ridiculously simple Vuex setup + wiring
1,167 lines (1,037 loc) • 35.1 kB
JavaScript
/**
* Bundle of: vuex-pathify
* Generated: 2019-12-16
* Version: 1.4.1
*/
var vuex = {
/**
* THIS OBJECT IS REPLACED AT RUNTIME WITH THE ACTUAL VUEX STORE
*/
store: {
state: null,
commit: function commit () {
if (process.env.NODE_ENV !== 'production') {
console.error('[Vuex Pathify] Plugin not initialized!');
}
},
dispatch: function dispatch () {
if (process.env.NODE_ENV !== 'production') {
console.error('[Vuex Pathify] Plugin not initialized!');
}
}
}
};
function commit() {
var ref;
var args = [], len = arguments.length;
while ( len-- ) args[ len ] = arguments[ len ];
(ref = vuex.store).commit.apply(ref, args);
}
function dispatch() {
var ref;
var args = [], len = arguments.length;
while ( len-- ) args[ len ] = arguments[ len ];
return (ref = vuex.store).dispatch.apply(ref, args)
}
/**
* Tests whether a passed value is an Object
*
* @param {*} value The value to be assessed
* @returns {boolean} Whether the value is a true Object
*/
/**
* Tests whether a passed value is an Object or Array
*
* @param {*} value The value to be assessed
* @returns {boolean} Whether the value is an Object or Array
*/
function isObject (value) {
return !!value && typeof value === 'object'
}
/**
* Tests whether a passed value is an Object and has the specified key
*
* @param {Object} obj The source object
* @param {string} key The key to check that exists
* @returns {boolean} Whether the predicate is satisfied
*/
function hasKey(obj, key) {
return isObject(obj) && key in obj
}
/**
* Gets an array of keys from a value
*
* The function handles various types:
*
* - string - match all words
* - object - return keys
* - array - return a string array of its values
*
* @param {*} value The value to get keys from
* @returns {Array}
*/
function getKeys (value) {
return !value
? []
: Array.isArray(value)
? value.map(function (key) { return String(key); })
: typeof value === 'object'
? Object.keys(value)
: typeof value === 'string'
? value.match(/[-$\w]+/g) || []
: []
}
/**
* Gets a value from an object, based on a path to the property
*
* @param {Object} obj The Object to get the value from
* @param {string|Array|Object} [path] The optional path to a sub-property
* @returns {*}
*/
function getValue (obj, path) {
var value = obj;
var keys = getKeys(path);
keys.every(function (key) {
var valid = isObject(value) && value.hasOwnProperty(key);
value = valid ? value[key] : void 0;
return valid
});
return value
}
/**
* Sets a value on an object, based on a path to the property
*
* @param {Object} obj The Object to set the value on
* @param {string|Array|Object} path The path to a sub-property
* @param {*} value The value to set
* @param {boolean} [create] Optional flag to create sub-properties; defaults to false
* @returns {Boolean} True or false, depending if value was set
*/
function setValue (obj, path, value, create) {
if ( create === void 0 ) create = false;
var keys = getKeys(path);
return keys.reduce(function (obj, key, index) {
var isIndex = /^\d+$/.test(key);
if (isIndex) {
key = parseInt(key);
}
if (!obj) {
return false
}
else if (index === keys.length - 1) {
obj[key] = value;
return true
}
else if (!isObject(obj[key]) || !(key in obj)) {
if (create) {
obj[key] = isIndex ? [] : {};
} else {
return false
}
}
return obj[key]
}, obj)
}
/**
* Checks an object has a property, based on a path to the property
*
* @param {Object} obj The Object to check the value on
* @param {string|Array|Object} path The path to a sub-property
* @returns {boolean} Boolean true or false
*/
function hasValue(obj, path) {
var keys = getKeys(path);
if (isObject(obj)) {
while (keys.length) {
var key = keys.shift();
if (hasKey(obj, key)) {
obj = obj[key];
} else {
return false
}
}
return true
}
return false
}
function clone (obj) {
return JSON.parse(JSON.stringify(obj))
}
var options = {
mapping: 'standard', // map states to store members using the "standard" scheme
strict: true, // throw an error if the store member cannot be found
cache: true, // cache generated functions for faster re-use
deep: 1, // allow sub-property access, but not creation
};
var formatters = {
camel: function () {
var args = [], len = arguments.length;
while ( len-- ) args[ len ] = arguments[ len ];
return args.shift() + args
.map(function (text) { return text.replace(/\w/, function (c) { return c.toUpperCase(); }); })
.join('')
},
snake: function () {
var ref;
var args = [], len = arguments.length;
while ( len-- ) args[ len ] = arguments[ len ];
return (ref = this)
.camel.apply(ref, args)
.replace(/([a-z])([A-Z])/g, function (match, a, b) { return a + '_' + b; })
.toLowerCase()
},
const: function () {
var ref;
var args = [], len = arguments.length;
while ( len-- ) args[ len ] = arguments[ len ];
return (ref = this)
.snake.apply(ref, args)
.toUpperCase()
}
};
/**
* Map of store members
*/
var members = {
state: 'state',
getters: 'getters',
actions: '_actions',
mutations: '_mutations',
};
/**
* Map of default resolver functions
*/
var resolvers = {
/**
* Standard name mapping function
*
* Adheres to seemingly the most common Vuex naming pattern
*
* @param {string} type The member type, i.e state, getters, mutations, or actions
* @param {string} name The name of the property being targeted, i.e. value
* @param {object} formatters A formatters object with common format functions, camel, snake, const
* @returns {string}
*/
standard: function standard (type, name, formatters$$1) {
switch(type) {
case 'mutations':
return formatters$$1.const('set', name) // SET_BAR
case 'actions':
return formatters$$1.camel('set', name) // setBar
}
return name // bar
},
/**
* Simple name mapping function
*/
simple: function simple (type, name, formatters$$1) {
if (type === 'actions') {
return formatters$$1.camel('set', name) // setBar
}
return name // bar
},
};
/**
* Configured resolver
*/
var resolver;
/**
* Internal function to resolve member name using configured mapping function
*
* @param {string} type The member type, i.e. actions
* @param {string} name The supplied path member id, i.e. value
* @returns {string} The resolved member name, i.e. SET_VALUE
*/
function resolveName (type, name) {
// bypass resolver
if (name.match(/!$/)) {
return name.substr(0, name.length - 1)
}
// configured resolver
var fn = resolver;
// unconfigured resolver! (runs once)
if (!fn) {
if (typeof options.mapping === 'function') {
fn = options.mapping;
}
else {
fn = resolvers[options.mapping];
if (!fn) {
throw new Error(("[Vuex Pathify] Unknown mapping '" + (options.mapping) + "' in options\n - Choose one of '" + (Object.keys(resolvers).join("', '")) + "'\n - Or, supply a custom function\n"))
}
}
resolver = fn;
}
// resolve!
return resolver(type, name, formatters)
}
/**
* Creates a resolver object that caches properties and can resolve store member properties
*
* @param {object} store The Vuex store instance
* @param {string} path A pathify path to the store target, i.e. 'foo/bar@a.b.c'
* @returns {object}
*/
function resolve (store, path) {
// state
var absPath = path.replace(/[/@!]+/g, '.');
// paths
var ref = path.split('@');
var statePath = ref[0];
var objPath = ref[1];
// parent
var modPath, trgName;
if (statePath.indexOf('/') > -1) {
var keys = statePath.split('/');
trgName = keys.pop();
modPath = keys.join('/');
}
else {
trgName = statePath;
}
// throw error if module does not exist
if (modPath && !store._modulesNamespaceMap[modPath + '/']) {
throw new Error(("[Vuex Pathify] Unknown module '" + modPath + "' via path '" + path + "'"))
}
// resolve targets
return {
absPath: absPath,
module: modPath,
target: statePath,
name: trgName.replace('!', ''),
isDynamic: path.indexOf(':') > -1,
/**
* Returns properties about the targeted member
*
* @param {string} type The member type, i.e state, getters, mutations, or actions
* @returns {{exists: boolean, member: object, type: string, path: string}}
*/
get: function (type) {
// targeted member, i.e. store._getters
var member = store[members[type]];
// resolved target name, i.e. SET_VALUE
var resName = resolveName(type, trgName);
// target path, i.e. store._getters['module/SET_VALUE']
var trgPath = modPath
? modPath + '/' + resName
: resName;
// return values
return {
exists: type === 'state'
? hasValue(member, trgPath)
: trgPath in member,
member: member,
trgPath: trgPath,
trgName: resName,
objPath: objPath,
}
}
}
}
/**
* Error generation function for accessors
*/
function getError(path, resolver, aName, a, bName, b) {
var error = "[Vuex Pathify] Unable to map path '" + path + "':";
if (path.indexOf('!') > -1) {
error += "\n - Did not find " + aName + " or " + bName + " named '" + (resolver.name) + "' on " + (resolver.module ? ("module '" + (resolver.module) + "'"): 'root store');
}
else {
var aText = a
? (aName + " '" + (a.trgName) + "' or ")
: '';
var bText = bName + " '" + (b.trgName) + "'";
error += "\n - Did not find " + aText + bText + " on " + (resolver.module ? ("module '" + (resolver.module) + "'"): 'store') + "\n - Use direct syntax '" + (resolver.target.replace(/(@|$)/, '!$1')) + "' (if member exists) to target directly";
}
return error
}
/**
* Handles passing and setting of sub-property values
*/
var Payload = function Payload (expr, path, value) {
this.expr = expr;
this.path = path;
this.value = value;
};
/**
* Set sub-property on target
* @param target
*/
Payload.prototype.update = function update (target) {
if (!options.deep) {
console.error(("[Vuex Pathify] Unable to access sub-property for path '" + (this.expr) + "':\n - Set option 'deep' to 1 to allow it"));
return target
}
var success = setValue(target, this.path, this.value, options.deep > 1);
// unable to set sub-property
if (!success && process.env.NODE_ENV !== 'production') {
console.error(("[Vuex Pathify] Unable to create sub-property for path '" + (this.expr) + "':\n - Set option 'deep' to 2 to allow it"));
return target
}
// set sub-property
return Array.isArray(target)
? [].concat(target)
: Object.assign({}, target)
};
/**
* Creates a setter function for the store, automatically targeting actions or mutations
*
* Also supports setting of sub-properties as part of the path
*
* @see documentation for more detail
*
* @param {Object} store The store object
* @param {string} path The path to the target node
* @returns {*|Promise} The return value from the commit() or dispatch()
*/
function makeSetter (store, path) {
var resolver = resolve(store, path);
var action = resolver.get('actions');
if (action.exists) {
return function (value) {
var payload = action.objPath
? new Payload(path, action.objPath, value)
: value;
return store.dispatch(action.trgPath, payload)
}
}
var mutation = resolver.get('mutations');
if (mutation.exists || resolver.isDynamic) {
return function (value) {
// rebuild mutation if using dynamic path
if (resolver.isDynamic) {
var interpolated = interpolate(path, this);
mutation = resolve(store, interpolated).get('mutations');
}
var payload = mutation.objPath
? new Payload(path, mutation.objPath, value)
: value;
return store.commit(mutation.trgPath, payload)
}
}
if (process.env.NODE_ENV !== 'production') {
console.error(getError(path, resolver, 'action', action, 'mutation', mutation));
}
return function (value) {}
}
/**
* Creates a getter function for the store, automatically targeting getters or state
*
* Also supports returning of sub-properties as part of the path
*
* @see documentation for more detail
*
* @param {Object} store The store object
* @param {string} path The path to the target node
* @param {boolean} [stateOnly] An optional flag to get from state only (used when syncing)
* @returns {*|Function} The state value or getter function
*/
function makeGetter (store, path, stateOnly) {
var resolver = resolve(store, path);
// for sync, we don't want to read only from state
var getter;
if (!stateOnly) {
getter = resolver.get('getters');
if (getter.exists) {
return function () {
var value = getter.member[getter.trgPath];
return getter.objPath
? getValueIfEnabled(path, value, getter.objPath)
: value
}
}
}
var state = resolver.get('state');
if (state.exists || resolver.isDynamic) {
return function () {
var absPath = resolver.isDynamic
? interpolate(resolver.absPath, this)
: resolver.absPath;
return getValueIfEnabled(path, store.state, absPath)
}
}
if (process.env.NODE_ENV !== 'production') {
console.error(getError(path, resolver, 'getter', getter, 'state', state));
}
return function () {}
}
/**
* Utility function to get value from store, but only if options allow
*
* @param {string} expr The full path expression
* @param {object} source The source object to get property from
* @param {string} path The full dot-path on the source object
* @returns {*}
*/
function getValueIfEnabled(expr, source, path) {
if (!options.deep && expr.indexOf('@') > -1) {
console.error(("[Vuex Pathify] Unable to access sub-property for path '" + expr + "':\n - Set option 'deep' to 1 to allow it"));
return
}
return getValue(source, path)
}
/**
* Utility function to interpolate a string with properties
* @param {string} path The path containing interpolation :tokens
* @param {object} scope The scope containing properties to be used
* @return {string}
*/
function interpolate (path, scope) {
return path.replace(/:(\w+)/g, function replace (all, token) {
if (!(token in scope)) {
console.error(("Error resolving dynamic store path: The property \"" + token + "\" does not exist on the scope"), scope);
}
return scope[token]
})
}
function accessorize (store) {
/**
* Set a property on the store, automatically using actions or mutations
*
* @param {string} path The path to the store member
* @param {*} value The value to set
* @returns {Promise|*} Any return value from the action / commit
*/
store.set = function (path, value) {
var setter = makeSetter(store, path);
if (typeof setter !== 'undefined') {
return setter(value)
}
};
/**
* Get a property from the store, automatically using getters or state
*
* @param {string} path The path to the store member
* @param {*} args Optional getter function parameters
* @returns {*|undefined} The state value / getter value / getter function / or undefined
*/
store.get = function (path) {
var args = [], len = arguments.length - 1;
while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ];
var getter = makeGetter(store, path);
if (typeof getter !== 'undefined') {
var value = getter();
return typeof value === 'function'
? value.apply(void 0, args)
: value
}
};
/**
* Get a copy of a property from the store, automatically using actions or mutations
*
* @param {string} path The path to the store member
* @param {*} args Optional getter function parameters
* @returns {*|undefined} The value, or undefined
*/
store.copy = function (path) {
var args = [], len = arguments.length - 1;
while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ];
var value = store.get.apply(store, [ path ].concat( args ));
return isObject(value)
? clone(value)
: value
};
}
function resolve$1 (type) {
return resolveName(type, 'value')
}
function debug () {
console.log(("\n [Vuex Pathify] Options:\n\n Mapping (" + (typeof options.mapping === 'function' ? 'custom' : options.mapping) + ")\n-------------------------------\n path : value\n state : " + (resolve$1('state')) + "\n getters : " + (resolve$1('getters')) + "\n actions : " + (resolve$1('actions')) + "\n mutations : " + (resolve$1('mutations')) + "\n\n Settings\n-------------------------------\n strict : " + (options.strict) + "\n cache : " + (options.cache) + "\n deep : " + (options.deep) + "\n\n"));
}
// plugin
/**
* Store plugin which updates the store object with set() and get() methods
*
* @param {Object} store The store object
*/
function plugin (store) {
// cache store instance
vuex.store = store;
// add pathify accessors
accessorize(store);
}
var pathify = {
options: options,
plugin: plugin,
debug: debug,
};
/**
* Utility function to grab keys for state
*
* @param {Object|Function|Array|String} state State object, state function, array or string of key names
* @returns {Array}
*/
function getStateKeys (state) {
return getKeys(typeof state === 'function' ? state() : state)
}
/**
* Helper function to mass-create default getter functions for an existing state object
*
* Note that you don't need to create top-level getter functions if using $store.get(...)
*
* @param {Object|Function|Array|String} state State object, state function, array or string of key names
*/
function makeGetters (state) {
return getStateKeys(state)
.reduce(function (obj, key) {
var getter = resolveName('getters', key);
obj[getter] = function (state) {
return state[key]
};
return obj
}, {})
}
/**
* Helper function to mass-create default mutation functions for an existing state object
*
* @param {Object|Function|Array|String} state State object, state function, array or string of key names
*/
function makeMutations (state) {
return getStateKeys(state)
.reduce(function (obj, key) {
var mutation = resolveName('mutations', key);
obj[mutation] = function (state, value) {
state[key] = value instanceof Payload
? value.update(state[key])
: value;
};
return obj
}, {})
}
/**
* Helper function to mass-create default actions functions for an existing state object
*
* @param {Object|Function|Array|String} state State object, state function, array or string of key names
*/
function makeActions (state) {
return getStateKeys(state)
.reduce(function (obj, key) {
var action = resolveName('actions', key);
var mutation = resolveName('mutations', key);
obj[action] = function (ref, value) {
var commit = ref.commit;
commit(mutation, value);
};
return obj
}, {})
}
var store = {
getters: makeGetters,
mutations: makeMutations,
actions: makeActions,
};
// -------------------------------------------------------------------------------------------------------------------
// external
// -------------------------------------------------------------------------------------------------------------------
/**
* Utility function to expand wildcard path for get()
*
* @param {string} path wildcard path
* @param {object} state state hash
* @param {object} getters getters hash
* @returns {array|string}
*/
function expandGet (path, state, getters) {
if (!init(path, state)) {
return ''
}
return resolveStates(path, state).concat( resolveHandlers(path, getters) )
}
/**
* Utility function to expand wildcard path for sync()
*
* @param {string} path wildcard path
* @param {object} state state hash
* @returns {array|string}
*/
function expandSync (path, state) {
if (!init(path, state)) {
return ''
}
return resolveStates(path, state)
}
/**
* Utility function to expand wildcard path for actions()
*
* @param {string} path wildcard path
* @param {object} actions actions hash
* @returns {array|string}
*/
function expandCall (path, actions) {
if (!init(path, actions)) {
return ''
}
return resolveHandlers(path, actions)
}
// -------------------------------------------------------------------------------------------------------------------
// internal
// -------------------------------------------------------------------------------------------------------------------
/**
* Helper function to resolve state properties from a wildcard path
*
* Note: this function traverses into the state object and any properties / sub-properties
*
* @param {string} path A path with a wildcard at the end
* @param {object} state A state object on which to look up the sub-properties
* @returns {string[]} An array of paths
*/
function resolveStates (path, state) {
// grab segments
var last = path.match(/([^/@\.]+)$/)[1];
var main = path.substring(0, path.length - last.length);
var keys = main.replace(/\W+$/, '').split(/[/@.]/);
// find state parent
var obj = main
? getValue(state, keys)
: state;
if (!obj) {
console.error(("[Vuex Pathify] Unable to expand wildcard path '" + path + "':\n - It looks like '" + (main.replace(/\W+$/, '')) + "' does not resolve to an existing state property"));
return []
}
// filter children
var rx = new RegExp('^' + last.replace(/\*/g, '\\w+') + '$');
return Object
.keys(obj)
.filter(function (key) { return rx.test(key); })
.map(function (key) { return main + key; })
}
/**
* Helper function to resolve getters, actions or mutations from a wildcard path
*
* Note: this function filters the top-level flat hash of members
*
* @param {string} path A path with a wildcard at the end
* @param {object} hash A hash on which to filter by key => wildcard
* @returns {string[]} An array of paths
*/
function resolveHandlers (path, hash) {
var rx = new RegExp('^' + path.replace(/\*/g, '\\w+') + '$');
return Object.keys(hash).filter(function (key) { return rx.test(key); })
}
// -------------------------------------------------------------------------------------------------------------------
// utility
// -------------------------------------------------------------------------------------------------------------------
/**
* Pre-flight check for wildcard paths
*
* @param {string} path
* @param {object} state
* @returns {boolean}
*/
function init (path, state) {
// only wildcards in final path segment are supported
if (path.indexOf('*') > -1 && /\*.*[/@.]/.test(path)) {
console.error(("[Vuex Pathify] Invalid wildcard placement for path '" + path + "':\n - Wildcards may only be used in the last segment of a path"));
return false
}
// edge case where store sometimes doesn't exist
if (!state) {
console.error(("[Vuex Pathify] Unable to expand wildcard path '" + path + "':\n - The usual reason for this is that the router was set up before the store\n - Make sure the store is imported before the router, then reload"));
return false
}
return true
}
/**
* Helper function to convert Pathify path syntax paths to objects
*
* Handles:
*
* - string path
* - object and array formats
* - path + object/array format
* - wildcards in path
*
* Returns a single string, or hash of key => paths
*
* @param {string|object|array} [path] An optional path prefix
* @param {object} props An optional hash or array of paths / segments
* @param {function} fnResolver A function to resolve wildcards
* @returns {object|string}
*/
function makePaths (path, props, fnResolver) {
// handle wildcards
if (typeof path === 'string' && path.indexOf('*') > -1) {
return makePathsHash(fnResolver(path))
}
// handle array as path
if (Array.isArray(path)) {
return makePathsHash(path)
}
// handle object as path
if (isObject(path)) {
props = path;
path = '';
}
// if props is an array
if (Array.isArray(props)) {
var paths = props
.map(function (prop) {
return makePath(path, prop)
});
return makePathsHash(paths)
}
// if props is an object
if (isObject(props)) {
return Object
.keys(props)
.reduce(function (paths, key) {
paths[key] = makePath(path, props[key]);
return paths
}, {})
}
// if path is a single string without wildcards
return path
}
/**
* Helper function to concatenate two path components into a valid path
*
* Handles one or no "/" "@" or '.' characters in either string
*
* @param {string} path
* @param {string} target
* @returns {string}
*/
function makePath (path, target) {
if ( target === void 0 ) target = '';
path = path.replace(/\/+$/, '');
var value = path.indexOf('@') > -1
? path + '.' + target
: path + '/' + target;
return value
.replace(/^\/|[.@/]+$/, '')
.replace(/\/@/, '@')
.replace(/@\./, '@')
}
/**
* Helper function to convert an array of paths to a hash
*
* Uses the last path segment as the key
*
* @param {string[]} paths An array of paths to convert to a hash
* @returns {object} A hash of paths
*/
function makePathsHash (paths) {
return paths.reduce(function (paths, path) {
var key = path.match(/\w+$/);
paths[key] = path;
return paths
}, {})
}
// -------------------------------------------------------------------------------------------------------------------
// entry
// -------------------------------------------------------------------------------------------------------------------
function get (path, props) {
return make(path, props, getOne, function (path) {
return expandGet(path, vuex.store.state, vuex.store.getters)
})
}
function sync (path, props) {
return make(path, props, syncOne, function (path) {
return expandSync(path, vuex.store.state)
})
}
function call (path, props) {
return make(path, props, callOne, function (path) {
return expandCall(path, vuex.store._actions)
})
}
// -------------------------------------------------------------------------------------------------------------------
// utility
// -------------------------------------------------------------------------------------------------------------------
/**
* Creates multiple 2-way vue:vuex computed properties
*
* The function has multiple usages:
*
* 1. multiple properties from multiple modules
*
* - @usage ...sync({foo: 'module1/foo', bar: 'module2/bar'})
*
* - @param {Object} props a hash of key:path state/getter or commit/action references
*
* 2. multiple properties from a single module (object shorthand)
*
* - @usage ...sync('module', {foo: 'foo', bar: 'bar'})
*
* - @param {string} path a path to a module
* - @param {Object} props a hash of key:prop state/getter or commit/action references
*
* 3. multiple properties from a single module (array shorthand)
*
* - @usage ...sync('module', ['foo', 'bar'])
*
* - @param {string} path a path to a module
* - @param {Array} props an Array of state/getter or commit/action references
*
* Where different getter / setters need to be specified, pass getter and setter in
* the same string, separating with a | character:
*
* - @usage ...sync('module', ['foo|updateFoo'])
*
* @param {string|Object} path a path to a module, or a hash of state/getter or commit/action references
* @param {Object|Array} props a hash of state/getter or commit/action references
* @param {Function} fnHandler a callback function to create the handler
* @param {Function} fnResolver
* @returns {{set, get}} a hash of Objects
*/
function make (path, props, fnHandler, fnResolver) {
// expand path / props
var data = makePaths(path, props, fnResolver);
// handle single paths
if (typeof data === 'string') {
return fnHandler(data)
}
// handle multiple properties
Object
.keys(data)
.forEach(function (key) {
data[key] = fnHandler(data[key]);
});
return data
}
// -------------------------------------------------------------------------------------------------------------------
// one
// -------------------------------------------------------------------------------------------------------------------
/**
* Creates a single 2-way vue:vuex computed property
*
* @param {string} path a path to a state/getter reference. Path can contain an optional commit / action reference, separated by a |, i.e. foo/bar|updateBar
* @returns {Object} a single get/set Object
*/
function syncOne (path) {
var ref = path.split('|');
var getter = ref[0];
var setter = ref[1];
if (setter) {
setter = getter.replace(/\w+!?$/, setter.replace('!', '') + '!');
}
return getter && setter
? { get: getOne(getter, true), set: setOne(setter) }
: { get: getOne(getter, true), set: setOne(getter) }
}
/**
* Creates a single 1-way vue:vuex computed getter
*
* @param {string} path A path to a state/getter reference
* @param {boolean} [stateOnly] An optional flag to get from state only (used when syncing)
* @returns {Object} A single getter function
*/
function getOne (path, stateOnly) {
var getter, store;
return function () {
var args = [], len = arguments.length;
while ( len-- ) args[ len ] = arguments[ len ];
if (!this.$store) {
throw new Error('[Vuex Pathify] Unexpected condition: this.$store is undefined.\n\nThis is a known edge case with some setups and will cause future lookups to fail')
}
if (!getter || store !== this.$store) {
store = this.$store;
getter = makeGetter(store, path, stateOnly);
}
return getter.call.apply(getter, [ this ].concat( args ))
}
}
/**
* Creates a single 1-way vue:vuex setter
*
* @param {string} path a path to an action/commit reference
* @returns {Function} a single setter function
*/
function setOne (path) {
var setter, store;
return function (value) {
var this$1 = this;
if (!setter || store !== this.$store) {
store = this.$store;
setter = makeSetter(store, path);
}
this.$nextTick(function () { return this$1.$emit('sync', path, value); });
return setter.call(this, value)
}
}
/**
* Creates a single action dispatcher
*
* @param {string} path a path to an action/commit reference
* @returns {Function} a single setter function
*/
function callOne (path) {
return function (value) {
return this.$store.dispatch(path, value)
}
}
/**
* @module
* @description Decorators for Vuex Pathify component helpers
*
* For example:
* ```js
* @Component
* class MyComponent extends Vue {
* @Get('name')
* @Set('name')
* @Call('setName')
* }
* ```
*/
var createDecorator = require('vue-class-component').createDecorator;
/**
* Decorator for `get` component helper.
* @param {string} path The path to store property
* @returns {VueDecorator} Vue decorator to be used in Vue class component.
*/
function Get (path) {
if (typeof path !== 'string' || arguments.length > 1) { throw new Error('Property decorators can only be used for single property access') }
return createDecorator(function (options, key) {
if (!options.computed) { options.computed = {}; }
options.computed[key] = get(path);
})
}
/**
* Decorator for `sync` component helper.
* @param {string} path The path to store property
* @returns {VueDecorator} Vue decorator to be used in Vue class component.
*/
function Sync (path) {
if (typeof path !== 'string' || arguments.length > 1) { throw new Error('Property decorators can only be used for single property access') }
return createDecorator(function (options, key) {
if (!options.computed) { options.computed = {}; }
options.computed[key] = sync(path);
})
}
/**
* Decorator for `call` component helper.
* @param {string} path The path to store property
* @returns {VueDecorator} Vue decorator to be used in Vue class component.
*/
function Call (path) {
if (typeof path !== 'string' || arguments.length > 1) { throw new Error('Property decorators can only be used for single property access') }
return createDecorator(function (options, key) {
if (!options.methods) { options.methods = {}; }
options.methods[key] = call(path);
})
}
/**
* Helper function to generate a mixin that registers module and computed properties on component creation
*
* @param {string|Array} path The path to register the Vuex module on
* @param {object} module The module definition to register when the
* @param {function} callback A callback returning store members to be added to the component definition
* @param {object} [options] Optional Vuex module registration options
* @returns {object} The mixin
*/
function registerModule(path, module, callback, options) {
return {
beforeCreate: function beforeCreate () {
this.$store.registerModule(path, module, options);
var members = callback();
this.$options.computed = Object.assign(this.$options.computed || {}, members.computed || {});
this.$options.methods = Object.assign(this.$options.methods || {}, members.methods || {});
},
destoyed: function destoyed () {
this.$store.unregisterModule(path);
}
}
}
export default pathify;
export { store as make, Payload, get, sync, call, Get, Sync, Call, commit, dispatch, registerModule };