Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Bower components Debian packages RPM packages NuGet packages

sentry / @nestjs/core   js

Repository URL to install this package:

Version: 7.0.10 

/ injector / injector.js

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const constants_1 = require("@nestjs/common/constants");
const shared_utils_1 = require("@nestjs/common/utils/shared.utils");
const runtime_exception_1 = require("../errors/exceptions/runtime.exception");
const undefined_dependency_exception_1 = require("../errors/exceptions/undefined-dependency.exception");
const unknown_dependencies_exception_1 = require("../errors/exceptions/unknown-dependencies.exception");
const constants_2 = require("./constants");
const inquirer_1 = require("./inquirer");
const instance_wrapper_1 = require("./instance-wrapper");
const iterare_1 = require("iterare");
class Injector {
    async loadMiddleware(wrapper, collection, moduleRef, contextId = constants_2.STATIC_CONTEXT, inquirer) {
        const { metatype } = wrapper;
        const targetWrapper = collection.get(metatype.name);
        if (!shared_utils_1.isUndefined(targetWrapper.instance)) {
            return;
        }
        const loadInstance = (instances) => {
            targetWrapper.instance = targetWrapper.isDependencyTreeStatic()
                ? new metatype(...instances)
                : Object.create(metatype.prototype);
        };
        await this.resolveConstructorParams(wrapper, moduleRef, null, loadInstance, contextId, inquirer);
    }
    async loadController(wrapper, moduleRef, contextId = constants_2.STATIC_CONTEXT) {
        const controllers = moduleRef.controllers;
        await this.loadInstance(wrapper, controllers, moduleRef, contextId, wrapper);
        await this.loadEnhancersPerContext(wrapper, contextId, wrapper);
    }
    async loadInjectable(wrapper, moduleRef, contextId = constants_2.STATIC_CONTEXT, inquirer) {
        const injectables = moduleRef.injectables;
        await this.loadInstance(wrapper, injectables, moduleRef, contextId, inquirer);
    }
    async loadProvider(wrapper, moduleRef, contextId = constants_2.STATIC_CONTEXT, inquirer) {
        const providers = moduleRef.providers;
        await this.loadInstance(wrapper, providers, moduleRef, contextId, inquirer);
        await this.loadEnhancersPerContext(wrapper, contextId, wrapper);
    }
    loadPrototype({ name }, collection, contextId = constants_2.STATIC_CONTEXT) {
        if (!collection) {
            return;
        }
        const target = collection.get(name);
        const instance = target.createPrototype(contextId);
        if (instance) {
            const wrapper = new instance_wrapper_1.InstanceWrapper(Object.assign(Object.assign({}, target), { instance }));
            collection.set(name, wrapper);
        }
    }
    applyDoneHook(wrapper) {
        let done;
        wrapper.donePromise = new Promise((resolve, reject) => {
            done = resolve;
        });
        wrapper.isPending = true;
        return done;
    }
    async loadInstance(wrapper, collection, moduleRef, contextId = constants_2.STATIC_CONTEXT, inquirer) {
        const inquirerId = this.getInquirerId(inquirer);
        const instanceHost = wrapper.getInstanceByContextId(contextId, inquirerId);
        if (instanceHost.isPending) {
            return instanceHost.donePromise;
        }
        const done = this.applyDoneHook(instanceHost);
        const { name, inject } = wrapper;
        const targetWrapper = collection.get(name);
        if (shared_utils_1.isUndefined(targetWrapper)) {
            throw new runtime_exception_1.RuntimeException();
        }
        if (instanceHost.isResolved) {
            return done();
        }
        const callback = async (instances) => {
            const properties = await this.resolveProperties(wrapper, moduleRef, inject, contextId, wrapper, inquirer);
            const instance = await this.instantiateClass(instances, wrapper, targetWrapper, contextId, inquirer);
            this.applyProperties(instance, properties);
            done();
        };
        await this.resolveConstructorParams(wrapper, moduleRef, inject, callback, contextId, wrapper, inquirer);
    }
    async resolveConstructorParams(wrapper, moduleRef, inject, callback, contextId = constants_2.STATIC_CONTEXT, inquirer, parentInquirer) {
        const inquirerId = this.getInquirerId(inquirer);
        const metadata = wrapper.getCtorMetadata();
        if (metadata && contextId !== constants_2.STATIC_CONTEXT) {
            const deps = await this.loadCtorMetadata(metadata, contextId, inquirer, parentInquirer);
            return callback(deps);
        }
        const dependencies = shared_utils_1.isNil(inject)
            ? this.reflectConstructorParams(wrapper.metatype)
            : inject;
        const optionalDependenciesIds = shared_utils_1.isNil(inject)
            ? this.reflectOptionalParams(wrapper.metatype)
            : [];
        let isResolved = true;
        const resolveParam = async (param, index) => {
            try {
                if (this.isInquirer(param, parentInquirer)) {
                    return parentInquirer && parentInquirer.instance;
                }
                const paramWrapper = await this.resolveSingleParam(wrapper, param, { index, dependencies }, moduleRef, contextId, inquirer, index);
                const instanceHost = paramWrapper.getInstanceByContextId(contextId, inquirerId);
                if (!instanceHost.isResolved && !paramWrapper.forwardRef) {
                    isResolved = false;
                }
                return instanceHost && instanceHost.instance;
            }
            catch (err) {
                const isOptional = optionalDependenciesIds.includes(index);
                if (!isOptional) {
                    throw err;
                }
                return undefined;
            }
        };
        const instances = await Promise.all(dependencies.map(resolveParam));
        isResolved && (await callback(instances));
    }
    reflectConstructorParams(type) {
        const paramtypes = Reflect.getMetadata(constants_1.PARAMTYPES_METADATA, type) || [];
        const selfParams = this.reflectSelfParams(type);
        selfParams.forEach(({ index, param }) => (paramtypes[index] = param));
        return paramtypes;
    }
    reflectOptionalParams(type) {
        return Reflect.getMetadata(constants_1.OPTIONAL_DEPS_METADATA, type) || [];
    }
    reflectSelfParams(type) {
        return Reflect.getMetadata(constants_1.SELF_DECLARED_DEPS_METADATA, type) || [];
    }
    async resolveSingleParam(wrapper, param, dependencyContext, moduleRef, contextId = constants_2.STATIC_CONTEXT, inquirer, keyOrIndex) {
        if (shared_utils_1.isUndefined(param)) {
            throw new undefined_dependency_exception_1.UndefinedDependencyException(wrapper.name, dependencyContext, moduleRef);
        }
        const token = this.resolveParamToken(wrapper, param);
        return this.resolveComponentInstance(moduleRef, shared_utils_1.isFunction(token) ? token.name : token, dependencyContext, wrapper, contextId, inquirer, keyOrIndex);
    }
    resolveParamToken(wrapper, param) {
        if (!param.forwardRef) {
            return param;
        }
        wrapper.forwardRef = true;
        return param.forwardRef();
    }
    async resolveComponentInstance(moduleRef, name, dependencyContext, wrapper, contextId = constants_2.STATIC_CONTEXT, inquirer, keyOrIndex) {
        const providers = moduleRef.providers;
        const instanceWrapper = await this.lookupComponent(providers, moduleRef, Object.assign(Object.assign({}, dependencyContext), { name }), wrapper, contextId, inquirer, keyOrIndex);
        return this.resolveComponentHost(moduleRef, instanceWrapper, contextId, inquirer);
    }
    async resolveComponentHost(moduleRef, instanceWrapper, contextId = constants_2.STATIC_CONTEXT, inquirer) {
        const inquirerId = this.getInquirerId(inquirer);
        const instanceHost = instanceWrapper.getInstanceByContextId(contextId, inquirerId);
        if (!instanceHost.isResolved && !instanceWrapper.forwardRef) {
            await this.loadProvider(instanceWrapper, moduleRef, contextId, inquirer);
        }
        else if (!instanceHost.isResolved &&
            instanceWrapper.forwardRef &&
            (contextId !== constants_2.STATIC_CONTEXT || !!inquirerId)) {
            /**
             * When circular dependency has been detected between
             * either request/transient providers, we have to asynchronously
             * resolve instance host for a specific contextId or inquirer, to ensure
             * that eventual lazily created instance will be merged with the prototype
             * instantiated beforehand.
             */
            instanceHost.donePromise &&
                instanceHost.donePromise.then(() => this.loadProvider(instanceWrapper, moduleRef, contextId, inquirer));
        }
        if (instanceWrapper.async) {
            const host = instanceWrapper.getInstanceByContextId(contextId, inquirerId);
            host.instance = await host.instance;
            instanceWrapper.setInstanceByContextId(contextId, host, inquirerId);
        }
        return instanceWrapper;
    }
    async lookupComponent(providers, moduleRef, dependencyContext, wrapper, contextId = constants_2.STATIC_CONTEXT, inquirer, keyOrIndex) {
        const { name } = dependencyContext;
        if (wrapper && wrapper.name === name) {
            throw new unknown_dependencies_exception_1.UnknownDependenciesException(wrapper.name, dependencyContext, moduleRef);
        }
        if (providers.has(name)) {
            const instanceWrapper = providers.get(name);
            this.addDependencyMetadata(keyOrIndex, wrapper, instanceWrapper);
            return instanceWrapper;
        }
        return this.lookupComponentInParentModules(dependencyContext, moduleRef, wrapper, contextId, inquirer, keyOrIndex);
    }
    async lookupComponentInParentModules(dependencyContext, moduleRef, wrapper, contextId = constants_2.STATIC_CONTEXT, inquirer, keyOrIndex) {
        const instanceWrapper = await this.lookupComponentInImports(moduleRef, dependencyContext.name, wrapper, [], contextId, inquirer, keyOrIndex);
        if (shared_utils_1.isNil(instanceWrapper)) {
            throw new unknown_dependencies_exception_1.UnknownDependenciesException(wrapper.name, dependencyContext, moduleRef);
        }
        return instanceWrapper;
    }
    async lookupComponentInImports(moduleRef, name, wrapper, moduleRegistry = [], contextId = constants_2.STATIC_CONTEXT, inquirer, keyOrIndex, isTraversing) {
        let instanceWrapperRef = null;
        const imports = moduleRef.imports || new Set();
        const identity = (item) => item;
        let children = [...imports.values()].filter(identity);
        if (isTraversing) {
            const contextModuleExports = moduleRef.exports;
            children = children.filter(child => contextModuleExports.has(child.metatype && child.metatype.name));
        }
        for (const relatedModule of children) {
            if (moduleRegistry.includes(relatedModule.id)) {
                continue;
            }
            moduleRegistry.push(relatedModule.id);
            const { providers, exports } = relatedModule;
            if (!exports.has(name) || !providers.has(name)) {
                const instanceRef = await this.lookupComponentInImports(relatedModule, name, wrapper, moduleRegistry, contextId, inquirer, keyOrIndex, true);
                if (instanceRef) {
                    this.addDependencyMetadata(keyOrIndex, wrapper, instanceRef);
                    return instanceRef;
                }
                continue;
            }
            instanceWrapperRef = providers.get(name);
            this.addDependencyMetadata(keyOrIndex, wrapper, instanceWrapperRef);
            const inquirerId = this.getInquirerId(inquirer);
            const instanceHost = instanceWrapperRef.getInstanceByContextId(contextId, inquirerId);
            if (!instanceHost.isResolved && !instanceWrapperRef.forwardRef) {
                await this.loadProvider(instanceWrapperRef, relatedModule, contextId, wrapper);
                break;
            }
        }
        return instanceWrapperRef;
    }
    async resolveProperties(wrapper, moduleRef, inject, contextId = constants_2.STATIC_CONTEXT, inquirer, parentInquirer) {
        if (!shared_utils_1.isNil(inject)) {
            return [];
        }
        const metadata = wrapper.getPropertiesMetadata();
        if (metadata && contextId !== constants_2.STATIC_CONTEXT) {
            return this.loadPropertiesMetadata(metadata, contextId, inquirer);
        }
        const properties = this.reflectProperties(wrapper.metatype);
        const instances = await Promise.all(properties.map(async (item) => {
            try {
                const dependencyContext = {
                    key: item.key,
                    name: item.name,
                };
                if (this.isInquirer(item.name, parentInquirer)) {
                    return parentInquirer && parentInquirer.instance;
                }
                const paramWrapper = await this.resolveSingleParam(wrapper, item.name, dependencyContext, moduleRef, contextId, inquirer, item.key);
                if (!paramWrapper) {
                    return undefined;
                }
                const inquirerId = this.getInquirerId(inquirer);
                const instanceHost = paramWrapper.getInstanceByContextId(contextId, inquirerId);
                return instanceHost.instance;
            }
            catch (err) {
                if (!item.isOptional) {
                    throw err;
                }
                return undefined;
            }
        }));
        return properties.map((item, index) => (Object.assign(Object.assign({}, item), { instance: instances[index] })));
    }
    reflectProperties(type) {
        const properties = Reflect.getMetadata(constants_1.PROPERTY_DEPS_METADATA, type) || [];
        const optionalKeys = Reflect.getMetadata(constants_1.OPTIONAL_PROPERTY_DEPS_METADATA, type) || [];
        return properties.map((item) => (Object.assign(Object.assign({}, item), { name: item.type, isOptional: optionalKeys.includes(item.key) })));
    }
    applyProperties(instance, properties) {
        if (!shared_utils_1.isObject(instance)) {
            return undefined;
        }
        iterare_1.iterate(properties)
            .filter(item => !shared_utils_1.isNil(item.instance))
            .forEach(item => (instance[item.key] = item.instance));
    }
    async instantiateClass(instances, wrapper, targetMetatype, contextId = constants_2.STATIC_CONTEXT, inquirer) {
        const { metatype, inject } = wrapper;
        const inquirerId = this.getInquirerId(inquirer);
        const instanceHost = targetMetatype.getInstanceByContextId(contextId, inquirerId);
        const isStatic = wrapper.isStatic(contextId, inquirer);
        const isInRequestScope = wrapper.isInRequestScope(contextId, inquirer);
        const isLazyTransient = wrapper.isLazyTransient(contextId, inquirer);
        const isExplicitlyRequested = wrapper.isExplicitlyRequested(contextId, inquirer);
        const isInContext = isStatic || isInRequestScope || isLazyTransient || isExplicitlyRequested;
        if (shared_utils_1.isNil(inject) && isInContext) {
            instanceHost.instance = wrapper.forwardRef
                ? Object.assign(instanceHost.instance, new metatype(...instances))
                : new metatype(...instances);
        }
        else if (isInContext) {
            const factoryReturnValue = targetMetatype.metatype(...instances);
            instanceHost.instance = await factoryReturnValue;
        }
        instanceHost.isResolved = true;
        return instanceHost.instance;
    }
    async loadPerContext(instance, moduleRef, collection, ctx, wrapper) {
        if (!wrapper) {
            const ctor = instance.constructor;
            wrapper = collection.get(ctor && ctor.name);
        }
        await this.loadInstance(wrapper, collection, moduleRef, ctx, wrapper);
        await this.loadEnhancersPerContext(wrapper, ctx, wrapper);
        const host = wrapper.getInstanceByContextId(ctx, wrapper.id);
        return host && host.instance;
    }
    async loadEnhancersPerContext(wrapper, ctx, inquirer) {
        const enhancers = wrapper.getEnhancersMetadata() || [];
        const loadEnhancer = (item) => {
            const hostModule = item.host;
            return this.loadInstance(item, hostModule.injectables, hostModule, ctx, inquirer);
        };
        await Promise.all(enhancers.map(loadEnhancer));
    }
    async loadCtorMetadata(metadata, contextId, inquirer, parentInquirer) {
        const hosts = await Promise.all(metadata.map(async (item) => this.resolveScopedComponentHost(item, contextId, inquirer, parentInquirer)));
        const inquirerId = this.getInquirerId(inquirer);
        return hosts.map(item => item.getInstanceByContextId(contextId, inquirerId).instance);
    }
    async loadPropertiesMetadata(metadata, contextId, inquirer) {
        const dependenciesHosts = await Promise.all(metadata.map(async ({ wrapper: item, key }) => ({
            key,
            host: await this.resolveComponentHost(item.host, item, contextId, inquirer),
        })));
        const inquirerId = this.getInquirerId(inquirer);
        return dependenciesHosts.map(({ key, host }) => ({
            key,
            name: key,
            instance: host.getInstanceByContextId(contextId, inquirerId).instance,
        }));
    }
    getInquirerId(inquirer) {
        return inquirer && inquirer.id;
    }
    resolveScopedComponentHost(item, contextId, inquirer, parentInquirer) {
        return this.isInquirerRequest(item, parentInquirer)
            ? parentInquirer
            : this.resolveComponentHost(item.host, item, contextId, inquirer);
    }
    isInquirerRequest(item, parentInquirer) {
        return item.isTransient && item.name === inquirer_1.INQUIRER && parentInquirer;
    }
    isInquirer(param, parentInquirer) {
        return param === inquirer_1.INQUIRER && parentInquirer;
    }
    addDependencyMetadata(keyOrIndex, hostWrapper, instanceWrapper) {
        shared_utils_1.isString(keyOrIndex)
            ? hostWrapper.addPropertiesMetadata(keyOrIndex, instanceWrapper)
            : hostWrapper.addCtorMetadata(keyOrIndex, instanceWrapper);
    }
}
exports.Injector = Injector;