@shahen.poghosyan/awilix
Version:
Extremely powerful dependency injection container.
135 lines • 4.71 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const lifetime_1 = require("./lifetime");
const resolvers_1 = require("./resolvers");
const utils_1 = require("./utils");
const camelCase = require('camel-case');
const nameFormatters = {
camelCase
};
/**
* Given an array of glob strings, will call `require`
* on them, and call their default exported function with the
* container as the first parameter.
*
* @param {AwilixContainer} dependencies.container
* The container to install loaded modules in.
*
* @param {Function} dependencies.listModules
* The listModules function to use for listing modules.
*
* @param {Function} dependencies.require
* The require function - it's a dependency because it makes testing easier.
*
* @param {String[]} globPatterns
* The array of globs to use when loading modules.
*
* @param {Object} opts
* Passed to `listModules`, e.g. `{ cwd: '...' }`.
*
* @param {(string, ModuleDescriptor) => string} opts.formatName
* Used to format the name the module is registered with in the container.
*
* @return {Object}
* Returns an object describing the result.
*/
function loadModules(dependencies, globPatterns, opts) {
const container = dependencies.container;
opts = optsWithDefaults(opts, container);
const modules = dependencies.listModules(globPatterns, opts);
const result = modules.map(m => {
const items = [];
const loaded = dependencies.require(m.path);
// Meh, it happens.
if (!loaded) {
return items;
}
if (utils_1.isFunction(loaded)) {
// for module.exports = ...
items.push({
name: m.name,
path: m.path,
value: loaded,
opts: m.opts
});
return items;
}
if (loaded.default && utils_1.isFunction(loaded.default)) {
// ES6 default export
items.push({
name: m.name,
path: m.path,
value: loaded.default,
opts: m.opts
});
}
// loop through non-default exports, but require the RESOLVER property set for
// it to be a valid service module export.
for (const key of Object.keys(loaded)) {
if (key === 'default') {
// default case handled separately due to its different name (file name)
continue;
}
if (utils_1.isFunction(loaded[key]) && resolvers_1.RESOLVER in loaded[key]) {
items.push({
name: key,
path: m.path,
value: loaded[key],
opts: m.opts
});
}
}
return items;
});
result
.reduce((acc, cur) => acc.concat(cur), [])
.filter(x => x)
.forEach(registerDescriptor.bind(null, container, opts));
return {
loadedModules: modules
};
}
exports.loadModules = loadModules;
/**
* Returns a new options object with defaults applied.
*/
function optsWithDefaults(opts, container) {
return Object.assign({
// Does a somewhat-deep merge on the registration options.
resolverOptions: Object.assign({ lifetime: lifetime_1.Lifetime.TRANSIENT }, (opts && opts.resolverOptions)) }, opts);
}
/**
* Given a module descriptor, reads it and registers it's value with the container.
*
* @param {AwilixContainer} container
* @param {LoadModulesOptions} opts
* @param {ModuleDescriptor} moduleDescriptor
*/
function registerDescriptor(container, opts, moduleDescriptor) {
const inlineConfig = moduleDescriptor.value[resolvers_1.RESOLVER];
let name = inlineConfig && inlineConfig.name;
if (!name) {
name = moduleDescriptor.name;
let formatter = opts.formatName;
if (formatter) {
if (typeof formatter === 'string') {
formatter = nameFormatters[formatter];
}
if (formatter) {
name = formatter(name, moduleDescriptor);
}
}
}
let moduleDescriptorOpts = moduleDescriptor.opts;
if (typeof moduleDescriptorOpts === 'string') {
moduleDescriptorOpts = { lifetime: moduleDescriptorOpts };
}
const regOpts = Object.assign({}, opts.resolverOptions, moduleDescriptorOpts, inlineConfig);
const reg = regOpts.register
? regOpts.register
: utils_1.isClass(moduleDescriptor.value)
? resolvers_1.asClass
: resolvers_1.asFunction;
container.register(name, reg(moduleDescriptor.value, regOpts));
}
//# sourceMappingURL=load-modules.js.map