UNPKG

@carlosv2/glue

Version:

Dependency injection library that stays out of the way

249 lines (248 loc) 10.1 kB
"use strict"; 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;