@carlosv2/glue
Version:
Dependency injection library that stays out of the way
249 lines (248 loc) • 10.1 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Loader = void 0;
const alias_1 = require("../alias");
const processor_1 = require("../processor");
const index_1 = require("../service/index");
const utils_1 = require("../utils");
const index_2 = require("../value/index");
const error_1 = require("../error");
const parameter_1 = require("../error/parameter");
const alias_2 = require("../error/alias");
const service_1 = require("../error/service");
const index_3 = require("../container/index");
class Loader extends processor_1.Processor {
constructor(defaultScope) {
super();
this.defaultScope = defaultScope !== null && defaultScope !== void 0 ? defaultScope : Symbol();
this.parameters = {};
this.aliases = {};
this.services = {};
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
glob(_) {
throw new error_1.DiError("Unfortunately, Loaders don't have this functionality. Please, use a Compiler instead.");
}
getFullPath(baseFile, relative) {
return `${baseFile.replace(/\/[^/]*$/, '')}/${relative}`;
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
readContents(_) {
throw new error_1.DiError("Unfortunately, Loaders don't have this functionality. Please, use a Compiler instead.");
}
importPath(baseFile, relative) {
return __awaiter(this, void 0, void 0, function* () {
let path = this.getFullPath(baseFile, relative);
if (path.endsWith('.ts') || path.endsWith('js')) {
path = path.substring(0, path.length - 3);
}
return Promise.resolve(`${path}`).then(s => __importStar(require(s)));
});
}
addExtend(path) {
this.fromPath(path);
}
addParameter(id, definition) {
this.parameters[id] = definition;
}
hasParameter(id) {
return (0, utils_1.has)(id, this.parameters);
}
getParameter(id) {
if ((0, utils_1.has)(id, this.parameters)) {
return this.parameters[id];
}
throw new parameter_1.ParameterNotFoundError(id);
}
getAllParameters() {
return Object.keys(this.parameters);
}
removeParameter(id) {
delete this.parameters[id];
}
addAlias(id, definition) {
this.aliases[id] = definition;
}
hasAlias(id) {
return (0, utils_1.has)(id, this.aliases);
}
getAlias(id) {
if ((0, utils_1.has)(id, this.aliases)) {
return this.aliases[id];
}
throw new alias_2.AliasNotFoundError(id);
}
getAllAliases() {
return Object.keys(this.aliases);
}
removeAlias(id) {
delete this.aliases[id];
}
addService(id, definition) {
var _a;
this.removeService(id);
const scope = (_a = definition.getScope()) !== null && _a !== void 0 ? _a : this.defaultScope;
if (!(0, utils_1.has)(scope, this.services)) {
this.services[scope] = {};
}
this.services[scope][id] = definition;
}
hasService(id) {
return Object.values(this.services).some(services => (0, utils_1.has)(id, services));
}
getService(id) {
for (const scope of Object.keys(this.services)) {
if ((0, utils_1.has)(id, this.services[scope])) {
return this.services[scope][id];
}
}
throw new service_1.ServiceNotFoundError(id);
}
getAllServices() {
return Object.values(this.services)
.map(services => Object.keys(services))
.flat();
}
removeService(id) {
for (const scope of Object.keys(this.services)) {
delete this.services[scope][id];
}
}
processEnvStrValue(context, name, fallback) {
return new index_2.EnvStr(context, name, fallback);
}
processEnvBoolValue(context, name, fallback) {
return new index_2.EnvBool(context, name, fallback);
}
processEnvNumValue(context, name, fallback) {
return new index_2.EnvNum(context, name, fallback);
}
processEvalValue(context, code) {
return new index_2.Eval(context, code);
}
processLiteralValue(context, value) {
return new index_2.Literal(context, value);
}
processParameterValue(context, id) {
return new index_2.Parameter(context, id);
}
processServiceValue(context, id) {
return new index_2.Service(context, id);
}
isClass(value) {
if (!(0, utils_1.isFunction)(value)) {
return false;
}
const representation = value.toString();
return (representation.startsWith('class ') ||
representation.startsWith('class{') ||
[String(Object), String(Date), String(Error)].includes(representation));
}
isFunc(value) {
return (0, utils_1.isFunction)(value) && !this.isClass(value);
}
getTheOnlyOne(context, haystack, filter) {
let token = undefined;
for (const value of Object.values(haystack)) {
if (filter(value)) {
if (token) {
throw new error_1.DiError('Multiple exported symbols where found', context);
}
else {
token = value;
}
}
}
if (token) {
return token;
}
throw new error_1.DiError('A suitable exported symbol was not found', context);
}
processSymbolValue(context, path, name) {
// Importing module. For example: (my/path
if (!(0, utils_1.isString)(name)) {
return new index_2.Symbol(context, this.importPath(context.getPath(), path));
}
// Importing the default symbol. For example: (my/path)
if (name.length === 0) {
return new index_2.Symbol(context, this.importPath(context.getPath(), path).then(module => module['default']));
}
// Importing the only exported symbol. For example: (my/path)~
if (name === '~') {
return new index_2.Symbol(context, this.importPath(context.getPath(), path).then(module => this.getTheOnlyOne(context, module, () => true)));
}
// Importing the only exported class. For example: (my/path)~class
if (name === '~class') {
return new index_2.Symbol(context, this.importPath(context.getPath(), path).then(module => this.getTheOnlyOne(context, module, this.isClass.bind(this))));
}
// Importing the only exported function. For example: (my/path)~func
if (name === '~func') {
return new index_2.Symbol(context, this.importPath(context.getPath(), path).then(module => this.getTheOnlyOne(context, module, this.isFunc.bind(this))));
}
// Importing the symbol found before or a known one. For example: (my/path)MyObj
return new index_2.Symbol(context, this.importPath(context.getPath(), path).then(module => module[name]));
}
processTagListValue(context, name) {
return new index_2.TagList(context, name);
}
processTagObjectValue(context, name) {
return new index_2.TagObject(context, name);
}
processAlias(context, aliased) {
return new alias_1.Alias(context, aliased);
}
processConstructorService(context, symbol, args, scope, tags, calls) {
return new index_1.Constructor(symbol, args, context, scope, tags, calls);
}
processFactoryService(context, symbol, factory, args, scope, tags, calls) {
return new index_1.Factory(symbol, factory, args, context, scope, tags, calls);
}
processPropertyService(context, symbol, property, scope, tags, calls) {
return new index_1.Property(symbol, property, context, scope, tags, calls);
}
getContainer(scope, parent) {
var _a;
const containerScope = scope !== null && scope !== void 0 ? scope : this.defaultScope;
const params = this.parameters;
const aliases = this.aliases;
const services = (_a = this.services[containerScope]) !== null && _a !== void 0 ? _a : {};
const container = new index_3.AssemblingContainer(params, aliases, services);
if (parent) {
return new index_3.FallbackContainer(container, parent);
}
return container;
}
}
exports.Loader = Loader;