From f022a627235315bf23a9ac7d4ccc24d9dfd201bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Anesi?= Date: Sat, 23 Jul 2022 12:37:59 +0200 Subject: [PATCH 1/2] fix(core): allow importing providers from global modules in lazy modules --- .../e2e/lazy-import-global-modules.spec.ts | 29 +++++++++++++++++++ integration/lazy-modules/src/app.module.ts | 16 ++++++++++ integration/lazy-modules/src/eager.module.ts | 12 ++++++++ integration/lazy-modules/src/global.module.ts | 13 +++++++++ integration/lazy-modules/src/lazy.module.ts | 12 ++++++++ integration/lazy-modules/src/main.ts | 8 +++++ packages/core/injector/lazy-module-loader.ts | 7 +++-- packages/core/scanner.ts | 12 ++++++++ 8 files changed, 106 insertions(+), 3 deletions(-) create mode 100644 integration/lazy-modules/e2e/lazy-import-global-modules.spec.ts create mode 100644 integration/lazy-modules/src/app.module.ts create mode 100644 integration/lazy-modules/src/eager.module.ts create mode 100644 integration/lazy-modules/src/global.module.ts create mode 100644 integration/lazy-modules/src/lazy.module.ts create mode 100644 integration/lazy-modules/src/main.ts diff --git a/integration/lazy-modules/e2e/lazy-import-global-modules.spec.ts b/integration/lazy-modules/e2e/lazy-import-global-modules.spec.ts new file mode 100644 index 00000000000..c55581d403b --- /dev/null +++ b/integration/lazy-modules/e2e/lazy-import-global-modules.spec.ts @@ -0,0 +1,29 @@ +import { INestApplication } from '@nestjs/common'; +import { Test } from '@nestjs/testing'; +import * as chai from 'chai'; +import { expect } from 'chai'; +import chaiAsPromised = require('chai-as-promised'); +import { AppModule } from '../src/app.module'; +chai.use(chaiAsPromised); + +describe('Lazy imports', () => { + let server; + let app: INestApplication; + + beforeEach(async () => { + const module = await Test.createTestingModule({ + imports: [AppModule], + }).compile(); + + app = module.createNestApplication(); + server = app.getHttpAdapter().getInstance(); + }); + + it(`Should allow imports of global modules`, async () => { + await expect(app.init()).to.eventually.be.fulfilled; + }); + + afterEach(async () => { + await app.close(); + }); +}); diff --git a/integration/lazy-modules/src/app.module.ts b/integration/lazy-modules/src/app.module.ts new file mode 100644 index 00000000000..65d38dadcc9 --- /dev/null +++ b/integration/lazy-modules/src/app.module.ts @@ -0,0 +1,16 @@ +import { Module } from '@nestjs/common'; +import { LazyModuleLoader } from '@nestjs/core'; +import { EagerModule } from './eager.module'; +import { GlobalModule } from './global.module'; +import { LazyModule } from './lazy.module'; + +@Module({ + imports: [GlobalModule, EagerModule], +}) +export class AppModule { + constructor(public loader: LazyModuleLoader) {} + + async onApplicationBootstrap() { + await this.loader.load(() => LazyModule); + } +} diff --git a/integration/lazy-modules/src/eager.module.ts b/integration/lazy-modules/src/eager.module.ts new file mode 100644 index 00000000000..e64f898a75c --- /dev/null +++ b/integration/lazy-modules/src/eager.module.ts @@ -0,0 +1,12 @@ +import { Module, Injectable } from '@nestjs/common'; +import { GlobalService } from './global.module'; + +@Injectable() +export class EagerService { + constructor(public globalService: GlobalService) {} +} + +@Module({ + providers: [EagerService], +}) +export class EagerModule {} diff --git a/integration/lazy-modules/src/global.module.ts b/integration/lazy-modules/src/global.module.ts new file mode 100644 index 00000000000..8eaa76cd557 --- /dev/null +++ b/integration/lazy-modules/src/global.module.ts @@ -0,0 +1,13 @@ +import { Module, Injectable, Global } from '@nestjs/common'; + +@Injectable() +export class GlobalService { + constructor() {} +} + +@Global() +@Module({ + providers: [GlobalService], + exports: [GlobalService], +}) +export class GlobalModule {} diff --git a/integration/lazy-modules/src/lazy.module.ts b/integration/lazy-modules/src/lazy.module.ts new file mode 100644 index 00000000000..69c056435e1 --- /dev/null +++ b/integration/lazy-modules/src/lazy.module.ts @@ -0,0 +1,12 @@ +import { Module, Injectable } from '@nestjs/common'; +import { GlobalService } from './global.module'; + +@Injectable() +export class LazyService { + constructor(public globalService: GlobalService) {} +} + +@Module({ + providers: [LazyService], +}) +export class LazyModule {} diff --git a/integration/lazy-modules/src/main.ts b/integration/lazy-modules/src/main.ts new file mode 100644 index 00000000000..13cad38cff9 --- /dev/null +++ b/integration/lazy-modules/src/main.ts @@ -0,0 +1,8 @@ +import { NestFactory } from '@nestjs/core'; +import { AppModule } from './app.module'; + +async function bootstrap() { + const app = await NestFactory.create(AppModule); + await app.listen(3000); +} +bootstrap(); diff --git a/packages/core/injector/lazy-module-loader.ts b/packages/core/injector/lazy-module-loader.ts index 6b39e520449..96aa297a37f 100644 --- a/packages/core/injector/lazy-module-loader.ts +++ b/packages/core/injector/lazy-module-loader.ts @@ -21,9 +21,10 @@ export class LazyModuleLoader { | DynamicModule, ): Promise { const moduleClassOrDynamicDefinition = await loaderFn(); - const moduleInstances = await this.dependenciesScanner.scanForModules( - moduleClassOrDynamicDefinition, - ); + const moduleInstances = + await this.dependenciesScanner.scanForModulesForLazyModules( + moduleClassOrDynamicDefinition, + ); if (moduleInstances.length === 0) { // The module has been loaded already. In this case, we must // retrieve a module reference from the existing container. diff --git a/packages/core/scanner.ts b/packages/core/scanner.ts index 97a78f66dea..47be0945ee3 100644 --- a/packages/core/scanner.ts +++ b/packages/core/scanner.ts @@ -77,6 +77,18 @@ export class DependenciesScanner { this.container.bindGlobalScope(); } + public async scanForModulesForLazyModules( + moduleDefinition: Type | DynamicModule, + ): Promise { + const modules = await this.scanForModules(moduleDefinition); + // We need to bind global scope to the lazy module because the bind phase happens before it was created + // The only one we need to bind is the actual module we are scanning the dependencies for, + // this modules is the first element in the modules list comming from the scan + this.container.bindGlobalsToImports(modules[0]); + + return modules; + } + public async scanForModules( moduleDefinition: | ForwardReference From 899bd93c233410a33cf8761722b966e367c28d9c Mon Sep 17 00:00:00 2001 From: Kamil Mysliwiec Date: Thu, 28 Jul 2022 11:15:18 +0200 Subject: [PATCH 2/2] Update integration/lazy-modules/e2e/lazy-import-global-modules.spec.ts --- integration/lazy-modules/e2e/lazy-import-global-modules.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration/lazy-modules/e2e/lazy-import-global-modules.spec.ts b/integration/lazy-modules/e2e/lazy-import-global-modules.spec.ts index c55581d403b..93f5910d034 100644 --- a/integration/lazy-modules/e2e/lazy-import-global-modules.spec.ts +++ b/integration/lazy-modules/e2e/lazy-import-global-modules.spec.ts @@ -19,7 +19,7 @@ describe('Lazy imports', () => { server = app.getHttpAdapter().getInstance(); }); - it(`Should allow imports of global modules`, async () => { + it(`should allow imports of global modules`, async () => { await expect(app.init()).to.eventually.be.fulfilled; });