From 91beaf7bc2f9d0c382e61f1374a4d04a7abfbc6b Mon Sep 17 00:00:00 2001 From: Patrick Acioli Date: Fri, 19 Jul 2024 02:35:05 -0300 Subject: [PATCH 1/2] fix(core): dependencies not resolving for transient lazy providers --- .../lazy-import-transient-providers.spec.ts | 32 +++++++++++++++++++ integration/lazy-modules/src/eager.module.ts | 6 ++++ .../lazy-modules/src/lazy.controller.ts | 18 +++++++++++ .../lazy-modules/src/transient.module.ts | 11 +++++++ .../lazy-modules/src/transient.service.ts | 11 +++++++ packages/core/injector/module.ts | 10 ++++++ 6 files changed, 88 insertions(+) create mode 100644 integration/lazy-modules/e2e/lazy-import-transient-providers.spec.ts create mode 100644 integration/lazy-modules/src/lazy.controller.ts create mode 100644 integration/lazy-modules/src/transient.module.ts create mode 100644 integration/lazy-modules/src/transient.service.ts diff --git a/integration/lazy-modules/e2e/lazy-import-transient-providers.spec.ts b/integration/lazy-modules/e2e/lazy-import-transient-providers.spec.ts new file mode 100644 index 00000000000..ce34a3347a6 --- /dev/null +++ b/integration/lazy-modules/e2e/lazy-import-transient-providers.spec.ts @@ -0,0 +1,32 @@ +import { INestApplication } from '@nestjs/common'; +import { Test } from '@nestjs/testing'; +import { TransientLazyModule } from '../src/transient.module'; +import { LazyController } from '../src/lazy.controller'; +import * as chai from 'chai'; +import { expect } from 'chai'; +import * as request from 'supertest'; + +describe('Lazy Transient providers', () => { + let app: INestApplication; + + beforeEach(async () => { + const module = await Test.createTestingModule({ + controllers: [LazyController], + }).compile(); + + app = module.createNestApplication(); + await app.init(); + }); + + it('should not recreate dependencies for default scope', async () => { + const resultOne = await request(app.getHttpServer()).get('/lazy/transient'); + + const resultTwo = await request(app.getHttpServer()).get('/lazy/transient'); + + expect(resultOne.text).to.be.equal('Hi! Counter is 1'); + expect(resultOne.statusCode).to.be.equal(200); + + expect(resultTwo.text).to.be.equal('Hi! Counter is 2'); + expect(resultTwo.statusCode).to.be.equal(200); + }); +}); diff --git a/integration/lazy-modules/src/eager.module.ts b/integration/lazy-modules/src/eager.module.ts index e64f898a75c..f50669ee92e 100644 --- a/integration/lazy-modules/src/eager.module.ts +++ b/integration/lazy-modules/src/eager.module.ts @@ -3,7 +3,13 @@ import { GlobalService } from './global.module'; @Injectable() export class EagerService { + private counter = 0; constructor(public globalService: GlobalService) {} + + sayHello() { + this.counter++; + return 'Hi! Counter is ' + this.counter; + } } @Module({ diff --git a/integration/lazy-modules/src/lazy.controller.ts b/integration/lazy-modules/src/lazy.controller.ts new file mode 100644 index 00000000000..58575d7293c --- /dev/null +++ b/integration/lazy-modules/src/lazy.controller.ts @@ -0,0 +1,18 @@ +import { Controller, Get } from '@nestjs/common'; +import { LazyModuleLoader } from '@nestjs/core'; + +@Controller('lazy') +export class LazyController { + constructor(private lazyLoadModule: LazyModuleLoader) {} + + @Get('transient') + async exec() { + const { TransientLazyModule } = await import('./transient.module'); + const moduleRef = await this.lazyLoadModule.load(() => TransientLazyModule); + + const { TransientService } = await import('./transient.service'); + const _service = await moduleRef.resolve(TransientService); + + return _service.eager(); + } +} diff --git a/integration/lazy-modules/src/transient.module.ts b/integration/lazy-modules/src/transient.module.ts new file mode 100644 index 00000000000..b76a686fec9 --- /dev/null +++ b/integration/lazy-modules/src/transient.module.ts @@ -0,0 +1,11 @@ +import { Module } from '@nestjs/common'; +import { GlobalService } from './global.module'; +import { EagerService } from './eager.module'; +import { TransientService } from './transient.service'; + +@Module({ + imports: [], + providers: [TransientService, GlobalService, EagerService], + exports: [TransientService], +}) +export class TransientLazyModule {} diff --git a/integration/lazy-modules/src/transient.service.ts b/integration/lazy-modules/src/transient.service.ts new file mode 100644 index 00000000000..fca76322860 --- /dev/null +++ b/integration/lazy-modules/src/transient.service.ts @@ -0,0 +1,11 @@ +import { Injectable, Scope } from '@nestjs/common'; +import { EagerService } from './eager.module'; + +@Injectable({ scope: Scope.TRANSIENT }) +export class TransientService { + constructor(private eagerService: EagerService) {} + + eager() { + return this.eagerService.sayHello(); + } +} diff --git a/packages/core/injector/module.ts b/packages/core/injector/module.ts index 634377544b9..c4a72028b18 100644 --- a/packages/core/injector/module.ts +++ b/packages/core/injector/module.ts @@ -12,6 +12,7 @@ import { InjectionToken, NestModule, Provider, + Scope, Type, ValueProvider, } from '@nestjs/common/interfaces'; @@ -253,6 +254,10 @@ export class Module { return this.addCustomProvider(provider, this._providers, enhancerSubtype); } + if (this.isTransientProvider(provider) && this.getProviderByKey(provider)) { + return provider; + } + this._providers.set( provider, new InstanceWrapper({ @@ -292,6 +297,11 @@ export class Module { ); } + public isTransientProvider(provider: Provider): boolean { + const metadata = Reflect.getMetadata('scope:options', provider); + return metadata && metadata?.scope === Scope.TRANSIENT; + } + public addCustomProvider( provider: | ClassProvider From daf0f883660fffa61e67f48ce6ae68e1f8518026 Mon Sep 17 00:00:00 2001 From: Patrick Acioli Date: Fri, 19 Jul 2024 02:35:05 -0300 Subject: [PATCH 2/2] fix(core): dependencies not resolving for transient lazy providers --- packages/core/injector/module.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/core/injector/module.ts b/packages/core/injector/module.ts index c4a72028b18..5396cd2e422 100644 --- a/packages/core/injector/module.ts +++ b/packages/core/injector/module.ts @@ -297,9 +297,8 @@ export class Module { ); } - public isTransientProvider(provider: Provider): boolean { - const metadata = Reflect.getMetadata('scope:options', provider); - return metadata && metadata?.scope === Scope.TRANSIENT; + private isTransientProvider(provider: Type): boolean { + return getClassScope(provider) === Scope.TRANSIENT; } public addCustomProvider(