mirror of
https://github.com/nestjs/nest.git
synced 2026-02-21 23:11:44 +00:00
201 lines
6.5 KiB
TypeScript
201 lines
6.5 KiB
TypeScript
import { type IntrospectionResult, Scope, type Type } from '@nestjs/common';
|
|
import { getClassScope } from '../helpers/get-class-scope.js';
|
|
import { isDurable } from '../helpers/is-durable.js';
|
|
import { AbstractInstanceResolver } from './abstract-instance-resolver.js';
|
|
import { NestContainer } from './container.js';
|
|
import { Injector } from './injector.js';
|
|
import { InstanceLinksHost } from './instance-links-host.js';
|
|
import { ContextId, InstanceWrapper } from './instance-wrapper.js';
|
|
import { Module } from './module.js';
|
|
|
|
export interface ModuleRefGetOrResolveOpts {
|
|
/**
|
|
* If enabled, lookup will only be performed in the host module.
|
|
* @default true
|
|
*/
|
|
strict?: boolean;
|
|
/**
|
|
* If enabled, instead of returning a first instance registered under a given token,
|
|
* a list of instances will be returned.
|
|
* @default false
|
|
*/
|
|
each?: boolean;
|
|
}
|
|
|
|
export abstract class ModuleRef extends AbstractInstanceResolver {
|
|
protected readonly injector: Injector;
|
|
private _instanceLinksHost: InstanceLinksHost;
|
|
|
|
protected get instanceLinksHost() {
|
|
if (!this._instanceLinksHost) {
|
|
this._instanceLinksHost = new InstanceLinksHost(this.container);
|
|
}
|
|
return this._instanceLinksHost;
|
|
}
|
|
|
|
constructor(protected readonly container: NestContainer) {
|
|
super();
|
|
|
|
this.injector = new Injector({
|
|
preview: container.contextOptions?.preview!,
|
|
instanceDecorator:
|
|
container.contextOptions?.instrument?.instanceDecorator,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Retrieves an instance of either injectable or controller, otherwise, throws exception.
|
|
* @returns {TResult}
|
|
*/
|
|
abstract get<TInput = any, TResult = TInput>(
|
|
typeOrToken: Type<TInput> | Function | string | symbol,
|
|
): TResult;
|
|
/**
|
|
* Retrieves an instance of either injectable or controller, otherwise, throws exception.
|
|
* @returns {TResult}
|
|
*/
|
|
abstract get<TInput = any, TResult = TInput>(
|
|
typeOrToken: Type<TInput> | Function | string | symbol,
|
|
options: {
|
|
/**
|
|
* If enabled, lookup will only be performed in the host module.
|
|
* @default true
|
|
*/
|
|
strict?: boolean;
|
|
/** This indicates that only the first instance registered will be returned. */
|
|
each?: undefined | false;
|
|
},
|
|
): TResult;
|
|
/**
|
|
* Retrieves a list of instances of either injectables or controllers, otherwise, throws exception.
|
|
* @returns {Array<TResult>}
|
|
*/
|
|
abstract get<TInput = any, TResult = TInput>(
|
|
typeOrToken: Type<TInput> | Function | string | symbol,
|
|
options: {
|
|
/**
|
|
* If enabled, lookup will only be performed in the host module.
|
|
* @default true
|
|
*/
|
|
strict?: boolean;
|
|
/** This indicates that a list of instances will be returned. */
|
|
each: true;
|
|
},
|
|
): Array<TResult>;
|
|
/**
|
|
* Retrieves an instance (or a list of instances) of either injectable or controller, otherwise, throws exception.
|
|
* @returns {TResult | Array<TResult>}
|
|
*/
|
|
abstract get<TInput = any, TResult = TInput>(
|
|
typeOrToken: Type<TInput> | Function | string | symbol,
|
|
options?: ModuleRefGetOrResolveOpts,
|
|
): TResult | Array<TResult>;
|
|
|
|
/**
|
|
* Resolves transient or request-scoped instance of either injectable or controller, otherwise, throws exception.
|
|
* @returns {Array<TResult>}
|
|
*/
|
|
abstract resolve<TInput = any, TResult = TInput>(
|
|
typeOrToken: Type<TInput> | Function | string | symbol,
|
|
): Promise<TResult>;
|
|
/**
|
|
* Resolves transient or request-scoped instance of either injectable or controller, otherwise, throws exception.
|
|
* @returns {Array<TResult>}
|
|
*/
|
|
abstract resolve<TInput = any, TResult = TInput>(
|
|
typeOrToken: Type<TInput> | Function | string | symbol,
|
|
contextId?: { id: number },
|
|
): Promise<TResult>;
|
|
/**
|
|
* Resolves transient or request-scoped instance of either injectable or controller, otherwise, throws exception.
|
|
* @returns {Array<TResult>}
|
|
*/
|
|
abstract resolve<TInput = any, TResult = TInput>(
|
|
typeOrToken: Type<TInput> | Function | string | symbol,
|
|
contextId?: { id: number },
|
|
options?: { strict?: boolean; each?: undefined | false },
|
|
): Promise<TResult>;
|
|
/**
|
|
* Resolves transient or request-scoped instances of either injectables or controllers, otherwise, throws exception.
|
|
* @returns {Array<TResult>}
|
|
*/
|
|
abstract resolve<TInput = any, TResult = TInput>(
|
|
typeOrToken: Type<TInput> | Function | string | symbol,
|
|
contextId?: { id: number },
|
|
options?: { strict?: boolean; each: true },
|
|
): Promise<Array<TResult>>;
|
|
/**
|
|
* Resolves transient or request-scoped instance (or a list of instances) of either injectable or controller, otherwise, throws exception.
|
|
* @returns {Promise<TResult | Array<TResult>>}
|
|
*/
|
|
abstract resolve<TInput = any, TResult = TInput>(
|
|
typeOrToken: Type<TInput> | Function | string | symbol,
|
|
contextId?: { id: number },
|
|
options?: ModuleRefGetOrResolveOpts,
|
|
): Promise<TResult | Array<TResult>>;
|
|
|
|
public abstract create<T = any>(
|
|
type: Type<T>,
|
|
contextId?: ContextId,
|
|
): Promise<T>;
|
|
|
|
public introspect<T = any>(
|
|
token: Type<T> | string | symbol,
|
|
): IntrospectionResult {
|
|
const { wrapperRef } = this.instanceLinksHost.get(token);
|
|
|
|
let scope = Scope.DEFAULT;
|
|
if (!wrapperRef.isDependencyTreeStatic()) {
|
|
scope = Scope.REQUEST;
|
|
} else if (wrapperRef.isTransient) {
|
|
scope = Scope.TRANSIENT;
|
|
}
|
|
return { scope };
|
|
}
|
|
|
|
public registerRequestByContextId<T = any>(request: T, contextId: ContextId) {
|
|
this.container.registerRequestProvider(request, contextId);
|
|
}
|
|
|
|
protected async instantiateClass<T = any>(
|
|
type: Type<T>,
|
|
moduleRef: Module,
|
|
contextId?: ContextId,
|
|
): Promise<T> {
|
|
const wrapper = new InstanceWrapper({
|
|
name: type && type.name,
|
|
metatype: type,
|
|
isResolved: false,
|
|
scope: getClassScope(type),
|
|
durable: isDurable(type),
|
|
host: moduleRef,
|
|
});
|
|
|
|
/* eslint-disable-next-line no-async-promise-executor */
|
|
return new Promise<T>(async (resolve, reject) => {
|
|
try {
|
|
const callback = async (instances: any[]) => {
|
|
const properties = await this.injector.resolveProperties(
|
|
wrapper,
|
|
moduleRef,
|
|
undefined,
|
|
contextId,
|
|
);
|
|
const instance = new type(...instances);
|
|
this.injector.applyProperties(instance, properties);
|
|
resolve(instance);
|
|
};
|
|
await this.injector.resolveConstructorParams<T>(
|
|
wrapper,
|
|
moduleRef,
|
|
undefined,
|
|
callback,
|
|
contextId,
|
|
);
|
|
} catch (err) {
|
|
reject(err);
|
|
}
|
|
});
|
|
}
|
|
}
|