mirror of
https://github.com/nestjs/nest.git
synced 2026-02-21 23:11:44 +00:00
feat(core): initialize on preview allowlist
This commit is contained in:
@@ -13,6 +13,7 @@ export * from './discovery';
|
||||
export * from './exceptions';
|
||||
export * from './helpers';
|
||||
export * from './injector';
|
||||
export * from './inspector';
|
||||
export * from './metadata-scanner';
|
||||
export * from './middleware';
|
||||
export * from './nest-application';
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
UndefinedForwardRefException,
|
||||
UnknownModuleException,
|
||||
} from '../errors/exceptions';
|
||||
import { InitializeOnPreviewAllowlist } from '../inspector/initialize-on-preview.allowlist';
|
||||
import { SerializedGraph } from '../inspector/serialized-graph';
|
||||
import { REQUEST } from '../router/request/request-constants';
|
||||
import { ModuleCompiler } from './compiler';
|
||||
@@ -80,6 +81,7 @@ export class NestContainer {
|
||||
}
|
||||
const moduleRef = new Module(type, this);
|
||||
moduleRef.token = token;
|
||||
moduleRef.initOnPreview = this.shouldInitOnPreview(type);
|
||||
this.modules.set(token, moduleRef);
|
||||
|
||||
const updatedScope = [].concat(scope, type);
|
||||
@@ -255,4 +257,8 @@ export class NestContainer {
|
||||
isResolved: true,
|
||||
});
|
||||
}
|
||||
|
||||
private shouldInitOnPreview(type: Type) {
|
||||
return InitializeOnPreviewAllowlist.has(type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -717,7 +717,7 @@ export class Injector {
|
||||
wrapper.isLazyTransient(contextId, inquirer) ||
|
||||
wrapper.isExplicitlyRequested(contextId, inquirer);
|
||||
|
||||
if (this.options?.preview) {
|
||||
if (this.options?.preview && !wrapper.host?.initOnPreview) {
|
||||
instanceHost.isResolved = true;
|
||||
return instanceHost.instance;
|
||||
}
|
||||
|
||||
@@ -63,6 +63,7 @@ export class Module {
|
||||
>();
|
||||
private readonly _exports = new Set<InstanceToken>();
|
||||
private _distance = 0;
|
||||
private _initOnPreview = false;
|
||||
private _isGlobal = false;
|
||||
private _token: string;
|
||||
|
||||
@@ -98,6 +99,14 @@ export class Module {
|
||||
this._isGlobal = global;
|
||||
}
|
||||
|
||||
get initOnPreview() {
|
||||
return this._initOnPreview;
|
||||
}
|
||||
|
||||
set initOnPreview(initOnPreview: boolean) {
|
||||
this._initOnPreview = initOnPreview;
|
||||
}
|
||||
|
||||
get providers(): Map<InstanceToken, InstanceWrapper<Injectable>> {
|
||||
return this._providers;
|
||||
}
|
||||
|
||||
2
packages/core/inspector/index.ts
Normal file
2
packages/core/inspector/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from './graph-inspector';
|
||||
export * from './initialize-on-preview.allowlist';
|
||||
13
packages/core/inspector/initialize-on-preview.allowlist.ts
Normal file
13
packages/core/inspector/initialize-on-preview.allowlist.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { Type } from '@nestjs/common';
|
||||
|
||||
export class InitializeOnPreviewAllowlist {
|
||||
private static readonly allowlist = new WeakMap<Type, boolean>();
|
||||
|
||||
public static add(type: Type) {
|
||||
this.allowlist.set(type, true);
|
||||
}
|
||||
|
||||
public static has(type: Type) {
|
||||
return this.allowlist.has(type);
|
||||
}
|
||||
}
|
||||
@@ -52,7 +52,7 @@ export class NestApplicationContext<
|
||||
private readonly moduleCompiler = new ModuleCompiler();
|
||||
private shutdownCleanupRef?: (...args: unknown[]) => unknown;
|
||||
private _instanceLinksHost: InstanceLinksHost;
|
||||
private _moduleRefsByDistance?: Array<Module>;
|
||||
private _moduleRefsForHooksByDistance?: Array<Module>;
|
||||
|
||||
protected get instanceLinksHost() {
|
||||
if (!this._instanceLinksHost) {
|
||||
@@ -372,10 +372,7 @@ export class NestApplicationContext<
|
||||
* modules and its children.
|
||||
*/
|
||||
protected async callInitHook(): Promise<void> {
|
||||
if (this.appOptions.preview) {
|
||||
return;
|
||||
}
|
||||
const modulesSortedByDistance = this.getModulesSortedByDistance();
|
||||
const modulesSortedByDistance = this.getModulesToTriggerHooksOn();
|
||||
for (const module of modulesSortedByDistance) {
|
||||
await callModuleInitHook(module);
|
||||
}
|
||||
@@ -386,10 +383,7 @@ export class NestApplicationContext<
|
||||
* modules and its children.
|
||||
*/
|
||||
protected async callDestroyHook(): Promise<void> {
|
||||
if (this.appOptions.preview) {
|
||||
return;
|
||||
}
|
||||
const modulesSortedByDistance = this.getModulesSortedByDistance();
|
||||
const modulesSortedByDistance = this.getModulesToTriggerHooksOn();
|
||||
for (const module of modulesSortedByDistance) {
|
||||
await callModuleDestroyHook(module);
|
||||
}
|
||||
@@ -400,10 +394,7 @@ export class NestApplicationContext<
|
||||
* modules and its children.
|
||||
*/
|
||||
protected async callBootstrapHook(): Promise<void> {
|
||||
if (this.appOptions.preview) {
|
||||
return;
|
||||
}
|
||||
const modulesSortedByDistance = this.getModulesSortedByDistance();
|
||||
const modulesSortedByDistance = this.getModulesToTriggerHooksOn();
|
||||
for (const module of modulesSortedByDistance) {
|
||||
await callModuleBootstrapHook(module);
|
||||
}
|
||||
@@ -414,10 +405,7 @@ export class NestApplicationContext<
|
||||
* modules and children.
|
||||
*/
|
||||
protected async callShutdownHook(signal?: string): Promise<void> {
|
||||
if (this.appOptions.preview) {
|
||||
return;
|
||||
}
|
||||
const modulesSortedByDistance = this.getModulesSortedByDistance();
|
||||
const modulesSortedByDistance = this.getModulesToTriggerHooksOn();
|
||||
for (const module of modulesSortedByDistance) {
|
||||
await callAppShutdownHook(module, signal);
|
||||
}
|
||||
@@ -428,10 +416,7 @@ export class NestApplicationContext<
|
||||
* modules and children.
|
||||
*/
|
||||
protected async callBeforeShutdownHook(signal?: string): Promise<void> {
|
||||
if (this.appOptions.preview) {
|
||||
return;
|
||||
}
|
||||
const modulesSortedByDistance = this.getModulesSortedByDistance();
|
||||
const modulesSortedByDistance = this.getModulesToTriggerHooksOn();
|
||||
for (const module of modulesSortedByDistance) {
|
||||
await callBeforeAppShutdownHook(module, signal);
|
||||
}
|
||||
@@ -445,17 +430,20 @@ export class NestApplicationContext<
|
||||
}
|
||||
}
|
||||
|
||||
private getModulesSortedByDistance(): Module[] {
|
||||
if (this._moduleRefsByDistance) {
|
||||
return this._moduleRefsByDistance;
|
||||
private getModulesToTriggerHooksOn(): Module[] {
|
||||
if (this._moduleRefsForHooksByDistance) {
|
||||
return this._moduleRefsForHooksByDistance;
|
||||
}
|
||||
const modulesContainer = this.container.getModules();
|
||||
const compareFn = (a: Module, b: Module) => b.distance - a.distance;
|
||||
|
||||
this._moduleRefsByDistance = Array.from(modulesContainer.values()).sort(
|
||||
const modulesSortedByDistance = Array.from(modulesContainer.values()).sort(
|
||||
compareFn,
|
||||
);
|
||||
return this._moduleRefsByDistance;
|
||||
|
||||
this._moduleRefsForHooksByDistance = this.appOptions?.preview
|
||||
? modulesSortedByDistance.filter(moduleRef => moduleRef.initOnPreview)
|
||||
: modulesSortedByDistance;
|
||||
return this._moduleRefsForHooksByDistance;
|
||||
}
|
||||
|
||||
private printInPreviewModeWarning() {
|
||||
|
||||
@@ -26,7 +26,6 @@ import { TestingModule } from './testing-module';
|
||||
export class TestingModuleBuilder {
|
||||
private readonly applicationConfig = new ApplicationConfig();
|
||||
private readonly container = new NestContainer(this.applicationConfig);
|
||||
private readonly injector = new TestingInjector();
|
||||
private readonly overloadsMap = new Map();
|
||||
private readonly module: any;
|
||||
private testingLogger: LoggerService;
|
||||
@@ -70,7 +69,7 @@ export class TestingModuleBuilder {
|
||||
}
|
||||
|
||||
public async compile(
|
||||
options: Pick<NestApplicationContextOptions, 'snapshot'> = {},
|
||||
options: Pick<NestApplicationContextOptions, 'snapshot' | 'preview'> = {},
|
||||
): Promise<TestingModule> {
|
||||
this.applyLogger();
|
||||
|
||||
@@ -92,7 +91,7 @@ export class TestingModuleBuilder {
|
||||
await scanner.scan(this.module);
|
||||
|
||||
this.applyOverloadsMap();
|
||||
await this.createInstancesOfDependencies(graphInspector);
|
||||
await this.createInstancesOfDependencies(graphInspector, options);
|
||||
scanner.applyApplicationProviders();
|
||||
|
||||
const root = this.getRootModule();
|
||||
@@ -137,10 +136,16 @@ export class TestingModuleBuilder {
|
||||
return modules.next().value;
|
||||
}
|
||||
|
||||
private async createInstancesOfDependencies(graphInspector: GraphInspector) {
|
||||
private async createInstancesOfDependencies(
|
||||
graphInspector: GraphInspector,
|
||||
options: { preview?: boolean },
|
||||
) {
|
||||
const injector = new TestingInjector({
|
||||
preview: options?.preview ?? false,
|
||||
});
|
||||
const instanceLoader = new TestingInstanceLoader(
|
||||
this.container,
|
||||
this.injector,
|
||||
injector,
|
||||
graphInspector,
|
||||
);
|
||||
await instanceLoader.createInstancesOfDependencies(
|
||||
|
||||
Reference in New Issue
Block a user