forked from nestjs/nest
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscanner.ts
More file actions
120 lines (98 loc) · 4.92 KB
/
Copy pathscanner.ts
File metadata and controls
120 lines (98 loc) · 4.92 KB
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import 'reflect-metadata';
import { NestContainer } from './injector/container';
import { Controller } from '@nestjs/common/interfaces/controllers/controller.interface';
import { Injectable } from '@nestjs/common/interfaces/injectable.interface';
import { metadata, EXCEPTION_FILTERS_METADATA, GUARDS_METADATA } from '@nestjs/common/constants';
import { NestModuleMetatype } from '@nestjs/common/interfaces/modules/module-metatype.interface';
import { Metatype } from '@nestjs/common/interfaces/metatype.interface';
import { GATEWAY_MIDDLEWARES } from '@nestjs/websockets/constants';
import { MetadataScanner } from '../core/metadata-scanner';
export class DependenciesScanner {
constructor(
private readonly container: NestContainer,
private readonly metadataScanner: MetadataScanner) {}
public scan(module: NestModuleMetatype) {
this.scanForModules(module);
this.scanModulesForDependencies();
}
private scanForModules(module: NestModuleMetatype, scope: NestModuleMetatype[] = []) {
this.storeModule(module, scope);
const importedModules = this.reflectMetadata(module, metadata.MODULES);
importedModules.map((innerModule) => {
this.scanForModules(innerModule, [].concat(scope, module));
});
}
private storeModule(module: NestModuleMetatype, scope: NestModuleMetatype[]) {
this.container.addModule(module, scope);
}
private scanModulesForDependencies() {
const modules = this.container.getModules();
modules.forEach(({ metatype }, token) => {
this.reflectRelatedModules(metatype, token);
this.reflectComponents(metatype, token);
this.reflectControllers(metatype, token);
this.reflectExports(metatype, token);
});
}
private reflectRelatedModules(module: NestModuleMetatype, token: string) {
const modules = this.reflectMetadata(module, metadata.MODULES);
modules.map((related) => this.storeRelatedModule(related, token));
}
private reflectComponents(module: NestModuleMetatype, token: string) {
const components = this.reflectMetadata(module, metadata.COMPONENTS);
components.map((component) => {
this.storeComponent(component, token);
this.reflectComponentMetadata(component, token);
});
}
private reflectComponentMetadata(component: Metatype<Injectable>, token: string) {
this.reflectGatewaysMiddlewares(component, token);
}
private reflectControllers(module: NestModuleMetatype, token: string) {
const routes = this.reflectMetadata(module, metadata.CONTROLLERS);
routes.map((route) => {
this.storeRoute(route, token);
this.reflectControllersMetadata(route, token);
});
}
private reflectControllersMetadata(route: Metatype<Injectable>, token: string) {
this.reflectGuards(route, token);
}
private reflectExports(module: NestModuleMetatype, token: string) {
const exports = this.reflectMetadata(module, metadata.EXPORTS);
exports.map((exportedComponent) => this.storeExportedComponent(exportedComponent, token));
}
private reflectGatewaysMiddlewares(component: Metatype<Injectable>, token: string) {
const middlewares = this.reflectMetadata(component, GATEWAY_MIDDLEWARES);
middlewares.map((middleware) => this.storeComponent(middleware, token));
}
private reflectGuards(component: Metatype<Injectable>, token: string) {
const controllerGuards = this.reflectMetadata(component, GUARDS_METADATA);
const methodsGuards = this.metadataScanner.scanFromPrototype(null, component.prototype,
(method: string) => {
const descriptor = Reflect.getOwnPropertyDescriptor(component.prototype, method);
return descriptor ? Reflect.getMetadata(GUARDS_METADATA, descriptor.value) : undefined;
},
);
const flattenMethodsGuards = methodsGuards.reduce((a, b) => a.concat(b), []);
[...controllerGuards, ...flattenMethodsGuards].map((guard) => this.storeInjectable(guard, token));
}
private storeRelatedModule(related: NestModuleMetatype, token: string) {
this.container.addRelatedModule(related, token);
}
private storeComponent(component: Metatype<Injectable>, token: string) {
this.container.addComponent(component, token);
}
private storeInjectable(component: Metatype<Injectable>, token: string) {
this.container.addInjectable(component, token);
}
private storeExportedComponent(exportedComponent: Metatype<Injectable>, token: string) {
this.container.addExportedComponent(exportedComponent, token);
}
private storeRoute(route: Metatype<Controller>, token: string) {
this.container.addController(route, token);
}
private reflectMetadata(metatype, metadata: string) {
return Reflect.getMetadata(metadata, metatype) || [];
}
}