-
-
Notifications
You must be signed in to change notification settings - Fork 7.8k
/
Copy pathon-app-bootstrap.hook.ts
66 lines (61 loc) · 2.13 KB
/
on-app-bootstrap.hook.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import { OnApplicationBootstrap } from '@nestjs/common';
import { isFunction, isNil } from '@nestjs/common/utils/shared.utils';
import { iterate } from 'iterare';
import { Module } from '../injector/module';
import { getInstancesGroupedByHierarchyLevel } from './utils/get-instances-grouped-by-hierarchy-level';
import { getSortedHierarchyLevels } from './utils/get-sorted-hierarchy-levels';
/**
* Checks if the given instance has the `onApplicationBootstrap` function
*
* @param instance The instance which should be checked
*/
function hasOnAppBootstrapHook(
instance: unknown,
): instance is OnApplicationBootstrap {
return isFunction(
(instance as OnApplicationBootstrap).onApplicationBootstrap,
);
}
/**
* Calls the given instances
*/
function callOperator(instances: unknown[]): Promise<any>[] {
return iterate(instances)
.filter(instance => !isNil(instance))
.filter(hasOnAppBootstrapHook)
.map(async instance =>
(instance as any as OnApplicationBootstrap).onApplicationBootstrap(),
)
.toArray();
}
/**
* Calls the `onApplicationBootstrap` function on the module and its children
* (providers / controllers).
*
* @param moduleRef The module which will be initialized
*/
export async function callModuleBootstrapHook(moduleRef: Module): Promise<any> {
const providers = moduleRef.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 [_, moduleClassHost] = providers.shift()!;
const groupedInstances = getInstancesGroupedByHierarchyLevel(
moduleRef.controllers,
moduleRef.injectables,
moduleRef.middlewares,
providers,
);
const levels = getSortedHierarchyLevels(groupedInstances);
for (const level of levels) {
await Promise.all(callOperator(groupedInstances.get(level)!));
}
// Call the instance itself
const moduleClassInstance = moduleClassHost.instance;
if (
moduleClassInstance &&
hasOnAppBootstrapHook(moduleClassInstance) &&
moduleClassHost.isDependencyTreeStatic()
) {
await moduleClassInstance.onApplicationBootstrap();
}
}