src/utils/resolve-modules.js
// Dependencies
import set from 'lodash.set';
import clone from 'stringify-clone';
// Utilities
import generateResolvers from './generate-resolvers';
const resolvedModuleCache = [];
/**
* A method for actually resolving a config
* from type names to React components.
* Takes a config object to be resolved and
* an array of paths generated by the
* function above (generatePaths)
*/
export default function resolveModules(
getModule = () => console.warn('No getModule() method supplied to constructor')
) {
return function resolveModules(config) {
/**
* Clone the config object to avoid mutation
*/
const configCopy = clone(config);
/**
* Create an array of resolver specifications
*/
const resolvers = generateResolvers('app', configCopy.app, ({
path,
module,
}) => {
return {
path: `${path}.type`,
type: module.type,
};
});
/**
* Return a Promise of the config
* resolved with modules
* (React components instead of type strings)
*/
return new Promise((resolve, reject) => {
const resolvingModules = [];
// Pick modules from cache or add them to queue to be resolved
resolvers.map((item) => { // eslint-disable-line array-callback-return
if (!resolvedModuleCache[item.type]) {
resolvedModuleCache[item.type] = 'adding';
resolvingModules.push(
getModule(item.type)
.then(module => resolvedModuleCache[item.type] = module) // eslint-disable-line no-return-assign
);
}
});
// When all new modules are resolved, add them to the configCopy object we are resolving to..
Promise.all(resolvingModules)
.then(() => {
resolvers.forEach((resolver) => {
const component = resolvedModuleCache[resolver.type];
set(configCopy, resolver.path, component);
});
resolve(configCopy);
})
.catch(err => reject(err));
});
};
}