UNPKG

@micro.ts/core

Version:

Microservice framework with Typescript

164 lines (163 loc) 5.41 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ContainerModule = void 0; const DiRegistry_1 = require("./DiRegistry"); const DiOptionsTypes_1 = require("./types/DiOptionsTypes"); /** * Container Module is a scoped dependency resolver and container, * The module is used to manage the main container dependencies, * also the request scoped dependencies * A new module is created when calling Container.newModule * using the current container module as the parent of the new module * therefore treating the newly created module as request scoped */ class ContainerModule { /** * If a parent is provided, this module is a scoped module, * meaning for singleton scoped dependencies it will fall back to the parent module * @param registyr * @param parent */ constructor(registry = DiRegistry_1.ContainerRegistry, parent) { this.registry = registry; this.parent = parent; /** * Key value to store the resolved dependencies if they match the module scope */ this.instances = new Map(); this.set(ContainerModule, this); } /** * Return true only if it has a parent */ get isScoped() { return !!this.parent; } /** * Construct an object with its constructor, * using the information it has from the constructor metadata * If not in transient scope store the created value * @param ctor * @param keyMetadata */ buildValue(ctor, keyMetadata) { // Fetch the constructor metadata const ctorParams = keyMetadata.ctorParams || []; /** * Build or fetch each constructor argument using the modules's get method */ const args = ctorParams.map((x) => { if (x.injectOptions) { return this.get(x.injectOptions.key); } return this.get(x.type); }); /** * Create the object */ const value = new ctor(...args); /** * Check if the value should be stored */ if (keyMetadata.scope !== DiOptionsTypes_1.ServiceScope.Transient) { this.instances.set(ctor, value); } return value; } /** * Resolve with the resolver and store the value if not transient scoped * @param key * @param resolveItem */ resolve(key, resolveItem) { const value = resolveItem.resolver(this); if (resolveItem.scope !== DiOptionsTypes_1.ServiceScope.Transient) { this.instances.set(key, value); } return value; } /** * Return true if this module is scoped and the required scope is singleton scope * Throws error if this module is not scoped and the required scope is request scoped * @param scope */ useParentScope(scope) { if (this.isScoped && scope === DiOptionsTypes_1.ServiceScope.Singleton) { return true; } else if (scope === DiOptionsTypes_1.ServiceScope.Request && !this.isScoped) { throw new Error('Can not inject a scoped dependency in a singleton dependency'); } return false; } /** * Set an arbitrary value for the given key * @param key * @param value */ set(key, value) { this.instances.set(key, value); } /** * Try and resolve the value * Might return undefined if it doesn't find * the stored key and/or cannot construct the value * @param key */ get(key) { var _a, _b; /** * Check if module contains an instance */ const existing = this.instances.get(key); /** * Exists in own instances */ if (existing) { return existing; } /** * Check for resolvers */ if (this.registry.hasResolver(key)) { /** * Get resolver info and function from the registry */ const resolveItem = this.registry.getResolver(key); /** * Check if the parent should create the resolver */ if (this.useParentScope(resolveItem.scope)) { return (_a = this.parent) === null || _a === void 0 ? void 0 : _a.get(key); } /** * If not resolve dhe dependency */ return this.resolve(key, resolveItem); } if (typeof key === 'function') { /** * Doesn't exist in own instances */ let keyMetadata = this.registry.getMetadata(key); if (!keyMetadata) { /** * Initialize metadata and call this method again */ keyMetadata = this.registry.initializeMetadata(key); } /** * Check if parent should provide this dependency */ if (this.useParentScope(keyMetadata.scope || DiOptionsTypes_1.ServiceScope.Singleton)) { return (_b = this.parent) === null || _b === void 0 ? void 0 : _b.get(key); } /** * Construct the value */ return this.buildValue(key, keyMetadata); } return undefined; } } exports.ContainerModule = ContainerModule;