UNPKG

confinode

Version:

Node application configuration reader

140 lines 5.25 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const utils_1 = require("../utils"); const loaders_1 = require("./loaders"); /** * Indicate if the description is a loaded loader. * * @param description - The description to check. * @returns True if loaded loader. */ function isLoadedLoader(description) { return 'loader__' in description; } /** * Asserts that the description contains a loaded loader. * * @param description - The description to test. */ function assertIsLoadedLoader(description) { /* istanbul ignore if */ if (!isLoadedLoader(description)) { throw new Error('Description should contain a loaded loader'); } } /** * Try to resolve the module. * * @param moduleName - The name of the module. * @param paths - The paths where modules are searched. * @returns The path of the file to load. */ function searchModulePath(moduleName, paths) { try { return require.resolve(moduleName, { paths }); } catch (_a) { return undefined; } } /** * Used to detect where there are no available loaders. */ class NoAvailableLoaderError extends Error { } /** * The loader manager is responsible of selecting the appropriate loader for each file. */ class LoaderManager { /** * Create the loader manager. * * @param applicationName - The application name, used to name custom loaders. * @param customLoaders - The custom loaders which will be added/replace the provided ones. */ constructor(applicationName, customLoaders) { const [customDescription, customExtensionsLoaders] = loaders_1.analyzeLoaders(customLoaders, applicationName + '#'); this.descriptions = { ...loaders_1.loaderDescriptions, ...customDescription }; this.extensionsLoaders = { ...loaders_1.extensionsLoaders, ...customExtensionsLoaders }; this.availableTypes = Object.keys(this.extensionsLoaders).sort((a, b) => b.length - a.length); } /** * Get the loader for the given file name. * * @param paths - The extra paths where modules are searched. * @param syncOnly - Do not use loaders if they cannot load synchronously. * @param fileName - The (base) name of the file to search. * @param extension - The extension of the file if already known. * @returns A generator of the most appropriate loader and its name, or undefined if none found. */ getLoaders(paths, syncOnly, fileName, extension) { const loaderGenerator = this.createLoaders(paths, syncOnly, this.availableTypes .filter(availableType => extension ? availableType === extension : fileName.length > availableType.length + 1 && fileName.endsWith('.' + availableType)) .reduce((previous, type) => [...previous, ...this.extensionsLoaders[type]], []) .filter(utils_1.unique) .map(loaderName => [loaderName, this.descriptions[loaderName]])); try { loaderGenerator.next(); return loaderGenerator; } catch (e) { /* istanbul ignore next */ if (e instanceof NoAvailableLoaderError) { return undefined; } else { throw e; } } } /** * Create an iterator over the loaders. Throws if no available iterator found. * * @param paths - The extra paths where modules are searched. * @param syncOnly - Do not use loaders if they cannot load synchronously. * @param matching - The loaders matching the given file name. * @returns The most appropriate loader and its name. */ *createLoaders(paths, syncOnly, matching) { let lastLoader; let nextLoader; for (const [loaderName, description] of matching) { let path; if (!isLoadedLoader(description) && description.module) { path = searchModulePath(description.module, paths); } if (isLoadedLoader(description) || !description.module || !!path) { if (!isLoadedLoader(description)) { // Load the loader and update the object const required = path ? require(path) : undefined; this.descriptions[loaderName] = { loader__: new description.Loader(required) }; } const loadedLoader = this.descriptions[loaderName]; assertIsLoadedLoader(loadedLoader); if (!syncOnly || loadedLoader.loader__.syncLoad) { nextLoader = [loadedLoader.loader__, loaderName]; } } if (nextLoader) { if (!lastLoader) { yield nextLoader; // Only for the first call } else { yield lastLoader; } lastLoader = nextLoader; nextLoader = undefined; } } if (lastLoader) { return lastLoader; } else { throw new NoAvailableLoaderError('No available loader'); } } } exports.default = LoaderManager; //# sourceMappingURL=LoaderManager.js.map