mirror of
https://github.com/nestjs/nest.git
synced 2026-02-21 23:11:44 +00:00
88 lines
2.9 KiB
TypeScript
88 lines
2.9 KiB
TypeScript
import { type Abstract, Scope, type Type } from '@nestjs/common';
|
|
import {
|
|
InvalidClassScopeException,
|
|
UnknownElementException,
|
|
} from '../errors/exceptions/index.js';
|
|
import { Injector } from './injector.js';
|
|
import { InstanceLink, InstanceLinksHost } from './instance-links-host.js';
|
|
import { ContextId } from './instance-wrapper.js';
|
|
import { Module } from './module.js';
|
|
import type { GetOrResolveOptions } from '@nestjs/common/internal';
|
|
|
|
export abstract class AbstractInstanceResolver {
|
|
protected abstract instanceLinksHost: InstanceLinksHost;
|
|
protected abstract injector: Injector;
|
|
|
|
protected abstract get<TInput = any, TResult = TInput>(
|
|
typeOrToken: Type<TInput> | Function | string | symbol,
|
|
options?: GetOrResolveOptions,
|
|
): TResult | Array<TResult>;
|
|
|
|
protected find<TInput = any, TResult = TInput>(
|
|
typeOrToken: Type<TInput> | Abstract<TInput> | string | symbol,
|
|
options: { moduleId?: string; each?: boolean },
|
|
): TResult | Array<TResult> {
|
|
const instanceLinkOrArray = this.instanceLinksHost.get<TResult>(
|
|
typeOrToken,
|
|
options,
|
|
);
|
|
const pluckInstance = ({ wrapperRef }: InstanceLink) => {
|
|
if (
|
|
wrapperRef.scope === Scope.REQUEST ||
|
|
wrapperRef.scope === Scope.TRANSIENT ||
|
|
!wrapperRef.isDependencyTreeStatic()
|
|
) {
|
|
throw new InvalidClassScopeException(typeOrToken);
|
|
}
|
|
return wrapperRef.instance;
|
|
};
|
|
if (Array.isArray(instanceLinkOrArray)) {
|
|
return instanceLinkOrArray.map(pluckInstance);
|
|
}
|
|
return pluckInstance(instanceLinkOrArray);
|
|
}
|
|
|
|
protected async resolvePerContext<TInput = any, TResult = TInput>(
|
|
typeOrToken: Type<TInput> | Abstract<TInput> | string | symbol,
|
|
contextModule: Module,
|
|
contextId: ContextId,
|
|
options?: GetOrResolveOptions,
|
|
): Promise<TResult | Array<TResult>> {
|
|
const instanceLinkOrArray = options?.strict
|
|
? this.instanceLinksHost.get(typeOrToken, {
|
|
moduleId: contextModule.id,
|
|
each: options.each,
|
|
})
|
|
: this.instanceLinksHost.get(typeOrToken, {
|
|
each: options?.each,
|
|
});
|
|
|
|
const pluckInstance = async (instanceLink: InstanceLink) => {
|
|
const { wrapperRef, collection } = instanceLink;
|
|
if (wrapperRef.isDependencyTreeStatic() && !wrapperRef.isTransient) {
|
|
return wrapperRef.instance;
|
|
}
|
|
|
|
const ctorHost = wrapperRef.instance || { constructor: typeOrToken };
|
|
const instance = await this.injector.loadPerContext(
|
|
ctorHost,
|
|
wrapperRef.host!,
|
|
collection,
|
|
contextId,
|
|
wrapperRef,
|
|
);
|
|
if (!instance) {
|
|
throw new UnknownElementException();
|
|
}
|
|
return instance;
|
|
};
|
|
|
|
if (Array.isArray(instanceLinkOrArray)) {
|
|
return Promise.all(
|
|
instanceLinkOrArray.map(instanceLink => pluckInstance(instanceLink)),
|
|
);
|
|
}
|
|
return pluckInstance(instanceLinkOrArray);
|
|
}
|
|
}
|