feature(@nestjs/core) add hierarchical lifecycle hooks #938

This commit is contained in:
Kamil Myśliwiec
2018-08-16 16:11:18 +02:00
parent 6976ffe079
commit c38c91217c
2 changed files with 45 additions and 19 deletions

View File

@@ -1,6 +1,17 @@
import { Controller, DynamicModule, Injectable, NestModule } from '@nestjs/common/interfaces';
import {
Controller,
DynamicModule,
Injectable,
NestModule,
} from '@nestjs/common/interfaces';
import { Type } from '@nestjs/common/interfaces/type.interface';
import { isFunction, isNil, isString, isSymbol, isUndefined } from '@nestjs/common/utils/shared.utils';
import {
isFunction,
isNil,
isString,
isSymbol,
isUndefined,
} from '@nestjs/common/utils/shared.utils';
import { RuntimeException } from '../errors/exceptions/runtime.exception';
import { UnknownExportException } from '../errors/exceptions/unknown-export.exception';
import { GuardsConsumer } from '../guards/guards-consumer';
@@ -83,8 +94,8 @@ export class Module {
}
public addCoreInjectables(container: NestContainer) {
this.addModuleRef();
this.addModuleAsComponent();
this.addModuleRef();
this.addReflector();
this.addApplicationRef(container.getApplicationRef());
this.addExternalContextCreator(container);

View File

@@ -71,23 +71,29 @@ export class NestApplicationContext extends ModuleRef
}
protected async callInitHook(): Promise<any> {
const modules = this.container.getModules();
await Promise.all(
iterate(modules.values()).map(
async module => await this.callModuleInitHook(module),
),
);
const modulesContainer = this.container.getModules();
for (const module of [...modulesContainer.values()].reverse()) {
await this.callModuleInitHook(module);
}
}
protected async callModuleInitHook(module: Module): Promise<any> {
const components = [...module.routes, ...module.components];
const components = [...module.components];
// The Module (class) instance is the first element of the components array
// Lifecycle hook has to be called once all classes are properly initialized
const [_, { instance: moduleClassInstance }] = components.shift();
const instances = [...module.routes, ...components];
await Promise.all(
iterate(components)
iterate(instances)
.map(([key, { instance }]) => instance)
.filter(instance => !isNil(instance))
.filter(this.hasOnModuleInitHook)
.map(async instance => await (instance as OnModuleInit).onModuleInit()),
);
if (moduleClassInstance && this.hasOnModuleInitHook(moduleClassInstance)) {
await (moduleClassInstance as OnModuleInit).onModuleInit();
}
}
protected hasOnModuleInitHook(instance: any): instance is OnModuleInit {
@@ -95,18 +101,21 @@ export class NestApplicationContext extends ModuleRef
}
protected async callDestroyHook(): Promise<any> {
const modules = this.container.getModules();
await Promise.all(
iterate(modules.values()).map(
async module => await this.callModuleDestroyHook(module),
),
);
const modulesContainer = this.container.getModules();
for (const module of modulesContainer.values()) {
await this.callModuleDestroyHook(module);
}
}
protected async callModuleDestroyHook(module: Module): Promise<any> {
const components = [...module.routes, ...module.components];
const components = [...module.components];
// The Module (class) instance is the first element of the components array
// Lifecycle hook has to be called once all classes are properly destroyed
const [_, { instance: moduleClassInstance }] = components.shift();
const instances = [...module.routes, ...components];
await Promise.all(
iterate(components)
iterate(instances)
.map(([key, { instance }]) => instance)
.filter(instance => !isNil(instance))
.filter(this.hasOnModuleDestroyHook)
@@ -115,6 +124,12 @@ export class NestApplicationContext extends ModuleRef
await (instance as OnModuleDestroy).onModuleDestroy(),
),
);
if (
moduleClassInstance &&
this.hasOnModuleDestroyHook(moduleClassInstance)
) {
await (moduleClassInstance as OnModuleDestroy).onModuleDestroy();
}
}
protected hasOnModuleDestroyHook(instance): instance is OnModuleDestroy {