Files
nest/packages/core/hooks/on-module-init.hook.ts
2019-12-27 13:11:52 +01:00

55 lines
1.9 KiB
TypeScript

import { OnModuleInit } from '@nestjs/common';
import { isNil } from '@nestjs/common/utils/shared.utils';
import iterate from 'iterare';
import { InstanceWrapper } from '../injector/instance-wrapper';
import { Module } from '../injector/module';
import {
getNonTransientInstances,
getTransientInstances,
} from '../injector/transient-instances';
/**
* Returns true or false if the given instance has a `onModuleInit` function
*
* @param instance The instance which should be checked
*/
function hasOnModuleInitHook(instance: unknown): instance is OnModuleInit {
return !isNil((instance as OnModuleInit).onModuleInit);
}
/**
* Calls the given instances
*/
function callOperator(instances: InstanceWrapper[]): Promise<any>[] {
return iterate(instances)
.filter(instance => !isNil(instance))
.filter(hasOnModuleInitHook)
.map(async instance => ((instance as any) as OnModuleInit).onModuleInit())
.toArray();
}
/**
* Calls the `onModuleInit` function on the module and its children
* (providers / controllers).
*
* @param module The module which will be initialized
*/
export async function callModuleInitHook(module: Module): Promise<void> {
const providers = module.getNonAliasProviders();
// Module (class) instance is the first element of the providers array
// Lifecycle hook has to be called once all classes are properly initialized
const [_, { instance: moduleClassInstance }] = providers.shift();
const instances = [...module.controllers, ...providers];
const nonTransientInstances = getNonTransientInstances(instances);
await Promise.all(callOperator(nonTransientInstances));
const transientInstances = getTransientInstances(instances);
await Promise.all(callOperator(transientInstances));
// Call the instance itself
if (moduleClassInstance && hasOnModuleInitHook(moduleClassInstance)) {
await (moduleClassInstance as OnModuleInit).onModuleInit();
}
}