From 64eeb9bf00b608a60facdaa8c9c2f4d11b6fedda Mon Sep 17 00:00:00 2001 From: anizozina Date: Tue, 18 Mar 2025 06:57:47 +0900 Subject: [PATCH] fix(core): dependencies not resolving for request-scoped lazy providers --- .../e2e/lazy-import-request-providers.spec.ts | 30 +++++++++++++++++++ .../lazy-modules/src/lazy.controller.ts | 10 +++++++ .../lazy-modules/src/request.module.ts | 11 +++++++ .../lazy-modules/src/request.service.ts | 11 +++++++ packages/core/injector/module.ts | 9 +++++- 5 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 integration/lazy-modules/e2e/lazy-import-request-providers.spec.ts create mode 100644 integration/lazy-modules/src/request.module.ts create mode 100644 integration/lazy-modules/src/request.service.ts diff --git a/integration/lazy-modules/e2e/lazy-import-request-providers.spec.ts b/integration/lazy-modules/e2e/lazy-import-request-providers.spec.ts new file mode 100644 index 000000000..a437cf741 --- /dev/null +++ b/integration/lazy-modules/e2e/lazy-import-request-providers.spec.ts @@ -0,0 +1,30 @@ +import { INestApplication } from '@nestjs/common'; +import { Test } from '@nestjs/testing'; +import { expect } from 'chai'; +import * as request from 'supertest'; +import { LazyController } from '../src/lazy.controller'; + +describe('Lazy Requested Scoped 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/request'); + + expect(resultOne.text).to.be.equal('Hi! Counter is 1'); + expect(resultOne.statusCode).to.be.equal(200); + + const resultTwo = await request(app.getHttpServer()).get('/lazy/request'); + + expect(resultTwo.text).to.be.equal('Hi! Counter is 2'); + expect(resultTwo.statusCode).to.be.equal(200); + }); +}); diff --git a/integration/lazy-modules/src/lazy.controller.ts b/integration/lazy-modules/src/lazy.controller.ts index 58575d729..45ab41bcf 100644 --- a/integration/lazy-modules/src/lazy.controller.ts +++ b/integration/lazy-modules/src/lazy.controller.ts @@ -13,6 +13,16 @@ export class LazyController { const { TransientService } = await import('./transient.service'); const _service = await moduleRef.resolve(TransientService); + return _service.eager(); + } + @Get('request') + async execRequestScope() { + const { RequestLazyModule } = await import('./request.module'); + const moduleRef = await this.lazyLoadModule.load(() => RequestLazyModule); + + const { RequestService } = await import('./request.service'); + const _service = await moduleRef.resolve(RequestService); + return _service.eager(); } } diff --git a/integration/lazy-modules/src/request.module.ts b/integration/lazy-modules/src/request.module.ts new file mode 100644 index 000000000..8cd549fce --- /dev/null +++ b/integration/lazy-modules/src/request.module.ts @@ -0,0 +1,11 @@ +import { Module } from '@nestjs/common'; +import { EagerService } from './eager.module'; +import { GlobalService } from './global.module'; +import { RequestService } from './request.service'; + +@Module({ + imports: [], + providers: [RequestService, GlobalService, EagerService], + exports: [RequestService], +}) +export class RequestLazyModule {} diff --git a/integration/lazy-modules/src/request.service.ts b/integration/lazy-modules/src/request.service.ts new file mode 100644 index 000000000..846b542c8 --- /dev/null +++ b/integration/lazy-modules/src/request.service.ts @@ -0,0 +1,11 @@ +import { Injectable, Scope } from '@nestjs/common'; +import { EagerService } from './eager.module'; + +@Injectable({ scope: Scope.REQUEST }) +export class RequestService { + constructor(private eagerService: EagerService) {} + + eager() { + return this.eagerService.sayHello(); + } +} diff --git a/packages/core/injector/module.ts b/packages/core/injector/module.ts index 5dd1d4386..42712d588 100644 --- a/packages/core/injector/module.ts +++ b/packages/core/injector/module.ts @@ -255,7 +255,11 @@ export class Module { } const isAlreadyDeclared = this._providers.has(provider); - if (this.isTransientProvider(provider) && isAlreadyDeclared) { + if ( + (this.isTransientProvider(provider) || + this.isRequestScopeProvider(provider)) && + isAlreadyDeclared + ) { return provider; } @@ -664,4 +668,7 @@ export class Module { private isTransientProvider(provider: Type): boolean { return getClassScope(provider) === Scope.TRANSIENT; } + private isRequestScopeProvider(provider: Type): boolean { + return getClassScope(provider) === Scope.REQUEST; + } }