"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const interfaces_1 = require("@nestjs/common/interfaces");
const shared_utils_1 = require("@nestjs/common/utils/shared.utils");
const invalid_class_scope_exception_1 = require("../errors/exceptions/invalid-class-scope.exception");
const unknown_element_exception_1 = require("../errors/exceptions/unknown-element.exception");
class ContainerScanner {
constructor(container) {
this.container = container;
}
find(typeOrToken) {
this.initFlatContainer();
return this.findInstanceByToken(typeOrToken, this.flatContainer);
}
getWrapperCollectionPair(typeOrToken) {
this.initFlatContainer();
return this.getWrapperCollectionPairByHost(typeOrToken, this.flatContainer);
}
findInstanceByToken(metatypeOrToken, contextModule) {
const [instanceWrapper] = this.getWrapperCollectionPairByHost(metatypeOrToken, contextModule);
if (instanceWrapper.scope === interfaces_1.Scope.REQUEST ||
instanceWrapper.scope === interfaces_1.Scope.TRANSIENT) {
throw new invalid_class_scope_exception_1.InvalidClassScopeException(metatypeOrToken);
}
return instanceWrapper.instance;
}
getWrapperCollectionPairByHost(metatypeOrToken, contextModule) {
const name = shared_utils_1.isFunction(metatypeOrToken)
? metatypeOrToken.name
: metatypeOrToken;
const collectionName = this.getHostCollection(name, contextModule);
const instanceWrapper = contextModule[collectionName].get(name);
if (!instanceWrapper) {
throw new unknown_element_exception_1.UnknownElementException(name && name.toString());
}
return [
instanceWrapper,
contextModule[collectionName],
];
}
initFlatContainer() {
if (this.flatContainer) {
return;
}
const modules = this.container.getModules();
const initialValue = {
providers: [],
controllers: [],
injectables: [],
};
const merge = (initial, arr) => [...initial, ...arr];
const partialModule = [...modules.values()].reduce((current, next) => ({
providers: merge(current.providers, next.providers),
controllers: merge(current.controllers, next.controllers),
injectables: merge(current.injectables, next.injectables),
}), initialValue);
this.flatContainer = {
providers: new Map(partialModule.providers),
controllers: new Map(partialModule.controllers),
injectables: new Map(partialModule.injectables),
};
}
getHostCollection(token, { providers, controllers }) {
if (providers.has(token)) {
return 'providers';
}
if (controllers.has(token)) {
return 'controllers';
}
return 'injectables';
}
}
exports.ContainerScanner = ContainerScanner;