Skip to content

Commit 93536ac

Browse files
committed
refactor(core): Move callModuleInitHook into dedicated file
1 parent f0e9b40 commit 93536ac

3 files changed

Lines changed: 92 additions & 87 deletions

File tree

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import iterate from 'iterare';
2+
3+
import { OnModuleInit } from '@nestjs/common';
4+
import { isNil, isUndefined } from '@nestjs/common/utils/shared.utils';
5+
6+
import { Module } from '../injector/module';
7+
import { InstanceWrapper } from '../injector/instance-wrapper';
8+
import { getTransientInstances, getNonTransientInstances } from '../injector/instance-trancient';
9+
10+
/**
11+
* Returns true or false if the given instance has a `onModuleInit` function
12+
*
13+
* @param instance The instance which should be checked
14+
*/
15+
function hasOnModuleInitHook(instance: unknown): instance is OnModuleInit {
16+
return !isUndefined((instance as OnModuleInit).onModuleInit);
17+
}
18+
19+
/**
20+
* Calls the given instances
21+
*/
22+
function callOperator(instances: InstanceWrapper[]): Promise<any>[] {
23+
return iterate(instances)
24+
.filter(instance => !isNil(instance))
25+
.filter(hasOnModuleInitHook)
26+
.map(async instance => (instance as any as OnModuleInit).onModuleInit())
27+
.toArray();
28+
}
29+
30+
/**
31+
* Calls the `onModuleInit` function on the module and its children
32+
* (providers / controllers).
33+
*
34+
* @param module The module which will be initialized
35+
*/
36+
export async function callModuleInitHook(module: Module): Promise<void> {
37+
const providers = [...module.providers];
38+
// Module (class) instance is the first element of the providers array
39+
// Lifecycle hook has to be called once all classes are properly initialized
40+
const [_, { instance: moduleClassInstance }] = providers.shift();
41+
const instances = [...module.controllers, ...providers];
42+
43+
const nonTransientInstances = getNonTransientInstances(instances);
44+
await Promise.all(callOperator(nonTransientInstances));
45+
46+
const transientInstances = getTransientInstances(instances);
47+
await Promise.all(callOperator(transientInstances));
48+
49+
// Call the instance itself
50+
if (moduleClassInstance && hasOnModuleInitHook(moduleClassInstance)) {
51+
await (moduleClassInstance as OnModuleInit).onModuleInit();
52+
}
53+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import iterate from 'iterare';
2+
3+
import { InstanceWrapper } from './instance-wrapper';
4+
5+
/**
6+
* Returns the instances which are transient
7+
* @param instances The instances which should be checked whether they are transcient
8+
*/
9+
export function getTransientInstances(
10+
instances: [string, InstanceWrapper][],
11+
): InstanceWrapper[] {
12+
return iterate(instances)
13+
.filter(([_, wrapper]) => wrapper.isDependencyTreeStatic())
14+
.map(([_, wrapper]) => wrapper.getStaticTransientInstances())
15+
.flatten()
16+
.filter(item => !!item)
17+
.map(({ instance }: any) => instance)
18+
.toArray() as InstanceWrapper[];
19+
}
20+
21+
/**
22+
* Returns the instances which are not transient
23+
* @param instances The instances which should be checked whether they are transcient
24+
*/
25+
export function getNonTransientInstances(
26+
instances: [string, InstanceWrapper][]
27+
): InstanceWrapper[] {
28+
return iterate(instances)
29+
.filter(
30+
([key, wrapper]) =>
31+
wrapper.isDependencyTreeStatic() && !wrapper.isTransient,
32+
)
33+
.map(([key, { instance }]) => instance)
34+
.toArray() as InstanceWrapper[];
35+
}

packages/core/nest-application-context.ts

Lines changed: 4 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ import { NestContainer } from './injector/container';
1515
import { ContainerScanner } from './injector/container-scanner';
1616
import { Module } from './injector/module';
1717
import { ModuleTokenFactory } from './injector/module-token-factory';
18+
import { callModuleInitHook } from './hooks/on-module-init.hook';
19+
import { callModuleBootstrapHook } from 'hooks/on-app-bootstrap.hook';
1820

1921
export class NestApplicationContext implements INestApplicationContext {
2022
private readonly moduleTokenFactory = new ModuleTokenFactory();
@@ -76,44 +78,10 @@ export class NestApplicationContext implements INestApplicationContext {
7678
protected async callInitHook(): Promise<any> {
7779
const modulesContainer = this.container.getModules();
7880
for (const module of [...modulesContainer.values()].reverse()) {
79-
await this.callModuleInitHook(module);
81+
await callModuleInitHook(module);
8082
}
8183
}
8284

83-
protected async callModuleInitHook(module: Module): Promise<any> {
84-
const providers = [...module.providers];
85-
// Module (class) instance is the first element of the providers array
86-
// Lifecycle hook has to be called once all classes are properly initialized
87-
const [_, { instance: moduleClassInstance }] = providers.shift();
88-
const instances = [...module.controllers, ...providers];
89-
const callOperator = (list: any) =>
90-
list
91-
.filter(instance => !isNil(instance))
92-
.filter(this.hasOnModuleInitHook)
93-
.map(async instance => (instance as OnModuleInit).onModuleInit());
94-
95-
await Promise.all(
96-
callOperator(
97-
iterate(instances)
98-
.filter(
99-
([key, wrapper]) =>
100-
wrapper.isDependencyTreeStatic() && !wrapper.isTransient,
101-
)
102-
.map(([key, { instance }]) => instance),
103-
),
104-
);
105-
const transientInstances = this.getTransientInstances(instances);
106-
await Promise.all(callOperator(iterate(transientInstances)));
107-
108-
if (moduleClassInstance && this.hasOnModuleInitHook(moduleClassInstance)) {
109-
await (moduleClassInstance as OnModuleInit).onModuleInit();
110-
}
111-
}
112-
113-
protected hasOnModuleInitHook(instance: any): instance is OnModuleInit {
114-
return !isUndefined((instance as OnModuleInit).onModuleInit);
115-
}
116-
11785
protected async callDestroyHook(): Promise<any> {
11886
const modulesContainer = this.container.getModules();
11987
for (const module of modulesContainer.values()) {
@@ -161,49 +129,10 @@ export class NestApplicationContext implements INestApplicationContext {
161129
protected async callBootstrapHook(): Promise<any> {
162130
const modulesContainer = this.container.getModules();
163131
for (const module of [...modulesContainer.values()].reverse()) {
164-
await this.callModuleBootstrapHook(module);
132+
await callModuleBootstrapHook(module);
165133
}
166134
}
167135

168-
protected async callModuleBootstrapHook(module: Module): Promise<any> {
169-
const providers = [...module.providers];
170-
const [_, { instance: moduleClassInstance }] = providers.shift();
171-
const instances = [...module.controllers, ...providers];
172-
173-
const callOperator = (list: any) =>
174-
list
175-
.filter(instance => !isNil(instance))
176-
.filter(this.hasOnAppBotstrapHook)
177-
.map(async instance =>
178-
(instance as OnApplicationBootstrap).onApplicationBootstrap(),
179-
);
180-
181-
await Promise.all(
182-
callOperator(
183-
iterate(instances)
184-
.filter(
185-
([key, wrapper]) =>
186-
wrapper.isDependencyTreeStatic() && !wrapper.isTransient,
187-
)
188-
.map(([key, { instance }]) => instance),
189-
),
190-
);
191-
const transientInstances = this.getTransientInstances(instances);
192-
await Promise.all(callOperator(iterate(transientInstances)));
193-
194-
if (moduleClassInstance && this.hasOnAppBotstrapHook(moduleClassInstance)) {
195-
await (moduleClassInstance as OnApplicationBootstrap).onApplicationBootstrap();
196-
}
197-
}
198-
199-
protected hasOnAppBotstrapHook(
200-
instance: any,
201-
): instance is OnApplicationBootstrap {
202-
return !isUndefined(
203-
(instance as OnApplicationBootstrap).onApplicationBootstrap,
204-
);
205-
}
206-
207136
protected find<TInput = any, TResult = TInput>(
208137
typeOrToken: Type<TInput> | string | symbol,
209138
): TResult {
@@ -219,16 +148,4 @@ export class NestApplicationContext implements INestApplicationContext {
219148
TResult
220149
>(metatypeOrToken, contextModule);
221150
}
222-
223-
private getTransientInstances(
224-
instances: [string, InstanceWrapper][],
225-
): InstanceWrapper[] {
226-
return iterate(instances)
227-
.filter(([key, wrapper]) => wrapper.isDependencyTreeStatic())
228-
.map(([key, wrapper]) => wrapper.getStaticTransientInstances())
229-
.flatten()
230-
.filter(item => !!item)
231-
.map(({ instance }: any) => instance)
232-
.toArray() as InstanceWrapper[];
233-
}
234151
}

0 commit comments

Comments
 (0)