soldotno/aurora-core

View on GitHub
src/utils/resolve-modules.js

Summary

Maintainability
A
1 hr
Test Coverage
// 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));
    });
  };
}