@empathyco/x-components
Version:
Empathy X Components
103 lines (100 loc) • 4.07 kB
JavaScript
import { reduce } from '@empathyco/x-utils';
let cache = {};
/**
* Creates or return a proxy object of the getters of the storeModule passed.
*
* @param getters - The Vuex Store Getters.
* @param moduleName - The name of the module.
* @param storeModule - The store module.
* @returns A {@link GettersTree} object with only the getters of the {@link XModule}.
*
* @internal
*
* @remarks This proxy will be used by the stateSelector, of the module. This is done to ensure that
* a Vuex stateSelector can only access the getters of the {@link XModule} where it is registered.
* This function task can be done with {@link getGettersProxy}, just without passing the
* storeModule. But in that case every time we register emitters in a module, it will loop over all
* the getters of all the store. This way, passing the moduleNeeded, it only loops over the getters
* of that module. It is a performance question to have this two different implementations.
*
*/
function getGettersProxyFromModule(getters, moduleName, storeModule) {
/* TODO: Review why TS is not able to exclude undefined types from the Getters cache */
const cachedGetter = cache[moduleName];
if (isCacheGetterDefined(cachedGetter)) {
return cachedGetter;
}
const modulePath = `x/${moduleName}/`;
const safeGetters = reduce(storeModule.getters, (safeGettersProxy, getterName) => defineGetterProxy(safeGettersProxy, getterName, `${modulePath}${getterName}`, getters), {});
cache[moduleName] = safeGetters;
return safeGetters;
}
/**
* Creates or return a proxy object of the getters of the module with the moduleName passed.
*
* @param getters - The Vuex Store Getters.
* @param moduleName - The name of the module.
* @returns A {@link GettersTree} object with only the getters of the {@link XModule}.
*
* @internal
*
* @remarks This proxy will be used wireCommit to pass the module state and getters, to a function
* that will return the payload to commit the mutation.
*/
function getGettersProxy(getters, moduleName) {
/* TODO: Review why TS is not able to exclude undefined types from the Getters cache */
const cachedGetter = cache[moduleName];
if (isCacheGetterDefined(cachedGetter)) {
return cachedGetter;
}
const modulePath = `x/${moduleName}/`;
const getterKeys = Object.keys(getters).filter(getterKey => getterKey.startsWith(modulePath));
const safeGetters = getterKeys.reduce((safeGettersProxy, fullPathGetterName) => {
const getterName = fullPathGetterName.replace(modulePath, '');
return defineGetterProxy(safeGettersProxy, getterName, fullPathGetterName, getters);
}, {});
cache[moduleName] = safeGetters;
return safeGetters;
}
/**
* Defines a JS getter in safeGettersProxy object that returns the Vuex getter value.
*
* @param safeGettersProxy - The object where the proxy will be defined.
* @param getterName - The name of the Getter without path. For example: 'trimQuery'.
* @param fullPathGetterName - The name of the getter to be accessed with the full path.
* For example: 'x/searchBox/trimmedQuery'.
* @param getters - The Vuex Store Getters.
* @returns The same safeGetterProxy with new get defined.
*
* @internal
*/
function defineGetterProxy(safeGettersProxy, getterName, fullPathGetterName, getters) {
return Object.defineProperty(safeGettersProxy, getterName, {
get() {
// eslint-disable-next-line ts/no-unsafe-return
return getters[fullPathGetterName];
},
enumerable: true,
});
}
/**
* Clean the cache (This is for testing purpose).
*
* @internal
*/
function cleanGettersProxyCache() {
cache = {};
}
/**
* Checks if the getter cached is defined.
*
* @param cachedGetter - The getter cached.
* @returns If the getters is defined or not.
*
* @internal
*/
function isCacheGetterDefined(cachedGetter) {
return cachedGetter !== undefined;
}
export { cleanGettersProxyCache, getGettersProxy, getGettersProxyFromModule };
//# sourceMappingURL=getters-proxy.utils.js.map