|
1 | 1 | import { Type } from '@nestjs/common'; |
2 | | -import { isFunction } from '@nestjs/common/utils/shared.utils'; |
3 | | -import { UnknownElementException } from '../errors/exceptions/unknown-element.exception'; |
4 | | -import { InstanceWrapper, NestContainer } from './container'; |
| 2 | +import { NestContainer } from './container'; |
| 3 | +import { ContainerScanner } from './container-scanner'; |
| 4 | +import { Injector } from './injector'; |
5 | 5 | import { Module } from './module'; |
6 | 6 |
|
7 | 7 | export abstract class ModuleRef { |
8 | | - private flattenModuleFixture: Partial<Module>; |
| 8 | + private readonly injector = new Injector(); |
| 9 | + private readonly containerScanner: ContainerScanner; |
9 | 10 |
|
10 | | - constructor(protected readonly container: NestContainer) {} |
| 11 | + constructor(protected readonly container: NestContainer) { |
| 12 | + this.containerScanner = new ContainerScanner(container); |
| 13 | + } |
11 | 14 |
|
12 | 15 | public abstract get<TInput = any, TResult = TInput>( |
13 | 16 | typeOrToken: Type<TInput> | string | symbol, |
14 | 17 | options?: { strict: boolean }, |
15 | 18 | ): TResult; |
16 | 19 |
|
| 20 | + public abstract create<T = any>(type: Type<T>): Promise<T>; |
| 21 | + |
17 | 22 | protected find<TInput = any, TResult = TInput>( |
18 | 23 | typeOrToken: Type<TInput> | string | symbol, |
19 | 24 | ): TResult { |
20 | | - this.initFlattenModule(); |
21 | | - return this.findInstanceByPrototypeOrToken<TInput, TResult>( |
22 | | - typeOrToken, |
23 | | - this.flattenModuleFixture, |
24 | | - ); |
| 25 | + return this.containerScanner.find<TInput, TResult>(typeOrToken); |
| 26 | + } |
| 27 | + |
| 28 | + protected async instantiateClass<T = any>( |
| 29 | + type: Type<T>, |
| 30 | + module: Module, |
| 31 | + ): Promise<T> { |
| 32 | + const wrapper = { |
| 33 | + name: type.name, |
| 34 | + metatype: type, |
| 35 | + instance: undefined, |
| 36 | + isResolved: false, |
| 37 | + }; |
| 38 | + return new Promise<T>(async (resolve, reject) => { |
| 39 | + try { |
| 40 | + await this.injector.resolveConstructorParams<T>( |
| 41 | + wrapper, |
| 42 | + module, |
| 43 | + undefined, |
| 44 | + async instances => resolve(new type(...instances)), |
| 45 | + ); |
| 46 | + } catch (err) { |
| 47 | + reject(err); |
| 48 | + } |
| 49 | + }); |
25 | 50 | } |
26 | 51 |
|
27 | 52 | protected findInstanceByPrototypeOrToken<TInput = any, TResult = TInput>( |
28 | 53 | metatypeOrToken: Type<TInput> | string | symbol, |
29 | 54 | contextModule: Partial<Module>, |
30 | 55 | ): TResult { |
31 | | - const dependencies = new Map([ |
32 | | - ...contextModule.components, |
33 | | - ...contextModule.routes, |
34 | | - ...contextModule.injectables, |
35 | | - ]); |
36 | | - const name = isFunction(metatypeOrToken) |
37 | | - ? (metatypeOrToken as any).name |
38 | | - : metatypeOrToken; |
39 | | - const instanceWrapper = dependencies.get(name); |
40 | | - if (!instanceWrapper) { |
41 | | - throw new UnknownElementException(); |
42 | | - } |
43 | | - return (instanceWrapper as InstanceWrapper<any>).instance; |
44 | | - } |
45 | | - |
46 | | - private initFlattenModule() { |
47 | | - if (this.flattenModuleFixture) { |
48 | | - return void 0; |
49 | | - } |
50 | | - const modules = this.container.getModules(); |
51 | | - const initialValue = { |
52 | | - components: [], |
53 | | - routes: [], |
54 | | - injectables: [], |
55 | | - }; |
56 | | - this.flattenModuleFixture = [...modules.values()].reduce( |
57 | | - (flatten, curr) => ({ |
58 | | - components: [...flatten.components, ...curr.components], |
59 | | - routes: [...flatten.routes, ...curr.routes], |
60 | | - injectables: [...flatten.injectables, ...curr.injectables], |
61 | | - }), |
62 | | - initialValue, |
63 | | - ) as any; |
| 56 | + return this.containerScanner.findInstanceByPrototypeOrToken< |
| 57 | + TInput, |
| 58 | + TResult |
| 59 | + >(metatypeOrToken, contextModule); |
64 | 60 | } |
65 | 61 | } |
0 commit comments