Skip to content

Commit ee66faf

Browse files
feature(@nejsts/core) create nest application context feature nestjs#201
1 parent 33cb589 commit ee66faf

7 files changed

Lines changed: 88 additions & 11 deletions

File tree

package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,7 @@
8686
"src/**/*.spec.ts",
8787
"src/core/adapters/*.ts",
8888
"src/websockets/adapters/*.ts",
89-
"src/core/nest-application.ts",
90-
"src/core/nest-factory.ts",
89+
"src/core/nest-*.ts",
9190
"src/common/exceptions/*.ts",
9291
"src/common/services/logger.service.ts",
9392
"src/core/errors/exceptions",

src/common/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export {
2828
RpcExceptionFilter,
2929
WsExceptionFilter,
3030
NestInterceptor,
31+
INestApplicationContext,
3132
} from './interfaces';
3233
export * from './services/logger.service';
3334
export * from './pipes';

src/common/interfaces/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export * from './modules/module-metadata.interface';
88
export * from './metatype.interface';
99
export * from './nest-application.interface';
1010
export * from './nest-microservice.interface';
11+
export * from './nest-application-context.interface';
1112
export * from './modules/on-init.interface';
1213
export * from './modules/on-destroy.interface';
1314
export * from './exceptions/exception-filter.interface';
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { Metatype } from './metatype.interface';
2+
3+
export interface INestApplicationContext {
4+
/**
5+
* Allows you to navigate through the modules tree, for example, to pull out a specific instance from the selected module.
6+
* @returns INestApplicationContext
7+
*/
8+
select<T>(module: Metatype<T>): INestApplicationContext;
9+
10+
/**
11+
* Makes possible to retrieve the instance of the component or controller available inside the processed module.
12+
* @returns T
13+
*/
14+
get<T>(metatypeOrToken: Metatype<T> | string): T;
15+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
2+
import { ModuleTokenFactory } from './injector/module-token-factory';
3+
import { NestContainer, InstanceWrapper } from './injector/container';
4+
import { NestModuleMetatype } from '@nestjs/common/interfaces/modules/module-metatype.interface';
5+
import { Metatype } from '@nestjs/common/interfaces';
6+
import { isFunction } from '@nestjs/common/utils/shared.utils';
7+
import { INestApplicationContext } from '@nestjs/common';
8+
9+
export class NestApplicationContext {
10+
private readonly moduleTokenFactory = new ModuleTokenFactory();
11+
12+
constructor(
13+
private readonly container: NestContainer,
14+
private readonly scope: NestModuleMetatype[],
15+
private readonly contextModule) {}
16+
17+
public select<T>(module: Metatype<T>): INestApplicationContext {
18+
const modules = this.container.getModules();
19+
const moduleMetatype = this.contextModule.metatype;
20+
const scope = this.scope.concat(moduleMetatype);
21+
22+
const token = this.moduleTokenFactory.create(module as any, scope);
23+
const selectedModule = modules.get(token);
24+
return selectedModule
25+
? new NestApplicationContext(this.container, scope, selectedModule)
26+
: null;
27+
}
28+
29+
public get<T>(metatypeOrToken: Metatype<T> | string): T {
30+
return this.findInstanceByPrototypeOrToken<T>(metatypeOrToken);
31+
}
32+
33+
private findInstanceByPrototypeOrToken<T>(metatypeOrToken: Metatype<T> | string) {
34+
const dependencies = new Map([
35+
...this.contextModule.components,
36+
...this.contextModule.routes,
37+
]);
38+
const name = isFunction(metatypeOrToken) ? (metatypeOrToken as any).name : metatypeOrToken;
39+
const instanceWrapper = dependencies.get(name);
40+
return instanceWrapper
41+
? (instanceWrapper as InstanceWrapper<any>).instance
42+
: null;
43+
}
44+
}

src/core/nest-application.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@ export class NestApplication implements INestApplication {
5454
}
5555

5656
public setupParserMiddlewares() {
57-
this.express.use(bodyParser.json());
58-
this.express.use(bodyParser.urlencoded({ extended: true }));
57+
this.express.use(bodyParser.json());
58+
this.express.use(bodyParser.urlencoded({ extended: true }));
5959
}
6060

6161
public async setupModules() {
@@ -82,11 +82,11 @@ export class NestApplication implements INestApplication {
8282
}
8383

8484
public async setupRouter() {
85-
const router = ExpressAdapter.createRouter();
86-
await this.setupMiddlewares(router);
85+
const router = ExpressAdapter.createRouter();
86+
await this.setupMiddlewares(router);
8787

88-
this.routesResolver.resolve(router);
89-
this.express.use(validatePath(this.config.getGlobalPrefix()), router);
88+
this.routesResolver.resolve(router);
89+
this.express.use(validatePath(this.config.getGlobalPrefix()), router);
9090
}
9191

9292
public connectMicroservice(config: MicroserviceConfiguration): INestMicroservice {

src/core/nest-factory.ts

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@ import { NestApplication } from './nest-application';
1010
import { isFunction } from '@nestjs/common/utils/shared.utils';
1111
import { MicroserviceConfiguration } from '@nestjs/common/interfaces/microservices/microservice-configuration.interface';
1212
import { ExpressAdapter } from './adapters/express-adapter';
13-
import { INestApplication, INestMicroservice } from '@nestjs/common';
13+
import { INestApplication, INestMicroservice, INestApplicationContext } from '@nestjs/common';
1414
import { MetadataScanner } from './metadata-scanner';
1515
import { MicroservicesPackageNotFoundException } from './errors/exceptions/microservices-package-not-found.exception';
16+
import { NestApplicationContext } from './nest-application-context';
1617

1718
const { NestMicroservice } = optional('@nestjs/microservices/nest-microservice') || {} as any;
1819

@@ -27,7 +28,7 @@ export class NestFactoryStatic {
2728
/**
2829
* Creates an instance of the NestApplication (returns Promise)
2930
*
30-
* @param {} module Entry ApplicationModule class
31+
* @param {} module Entry (root) application module class
3132
* @param {} express Optional express() server instance
3233
* @returns an `Promise` of the INestApplication instance
3334
*/
@@ -41,7 +42,7 @@ export class NestFactoryStatic {
4142
/**
4243
* Creates an instance of the NestMicroservice (returns Promise)
4344
*
44-
* @param {} module Entry ApplicationModule class
45+
* @param {} module Entry (root) application module class
4546
* @param {MicroserviceConfiguration} config Optional microservice configuration
4647
* @returns an `Promise` of the INestMicroservice instance
4748
*/
@@ -59,6 +60,22 @@ export class NestFactoryStatic {
5960
);
6061
}
6162

63+
/**
64+
* Creates an instance of the NestApplicationContext (returns Promise)
65+
*
66+
* @param {} module Entry (root) application module class
67+
* @returns an `Promise` of the INestApplicationContext instance
68+
*/
69+
public async createApplicationContext(module): Promise<INestApplicationContext> {
70+
await this.initialize(module);
71+
72+
const modules = this.container.getModules().values();
73+
const root = modules.next().value;
74+
return this.createNestInstance<INestApplicationContext>(
75+
new NestApplicationContext(this.container, [], root),
76+
);
77+
}
78+
6279
private createNestInstance<T>(instance: T) {
6380
return this.createProxy(instance);
6481
}

0 commit comments

Comments
 (0)