From 1ff1389c9c92283a22e53d72f3a3fd6223bbded3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20My=C5=9Bliwiec?= Date: Tue, 12 Jul 2022 09:55:08 +0200 Subject: [PATCH 1/3] fix(core): scoped factories should not fail with optional deps --- packages/core/injector/injector.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/core/injector/injector.ts b/packages/core/injector/injector.ts index a0d68f5d62b..ed1a5bfc810 100644 --- a/packages/core/injector/injector.ts +++ b/packages/core/injector/injector.ts @@ -778,7 +778,7 @@ export class Injector { inquirer?: InstanceWrapper, parentInquirer?: InstanceWrapper, ): Promise { - const hosts = await Promise.all( + const hosts: Array | undefined> = await Promise.all( metadata.map(async item => this.resolveScopedComponentHost( item, @@ -791,7 +791,7 @@ export class Injector { const inquirerId = this.getInquirerId(inquirer); return hosts.map( item => - item.getInstanceByContextId( + item?.getInstanceByContextId( this.getContextId(contextId, item), inquirerId, ).instance, From 8e5b1f426cd5bb2735e326d03c01d7759d3ec3a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20My=C5=9Bliwiec?= Date: Tue, 12 Jul 2022 09:58:45 +0200 Subject: [PATCH 2/3] test(): add test case for optional deps in scoped providers --- .../e2e/optional-factory-provider-dep.spec.ts | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/integration/injector/e2e/optional-factory-provider-dep.spec.ts b/integration/injector/e2e/optional-factory-provider-dep.spec.ts index e5162d03c30..732bf1fc2e4 100644 --- a/integration/injector/e2e/optional-factory-provider-dep.spec.ts +++ b/integration/injector/e2e/optional-factory-provider-dep.spec.ts @@ -1,3 +1,4 @@ +import { Scope } from '@nestjs/common'; import { UnknownDependenciesException } from '@nestjs/core/errors/exceptions/unknown-dependencies.exception'; import { Test } from '@nestjs/testing'; import { expect } from 'chai'; @@ -38,6 +39,42 @@ describe('Optional factory provider deps', () => { const factoryProvider = moduleRef.get('FACTORY'); expect(factoryProvider).to.equal(defaultValue); }); + it('"undefined" should be injected into the factory function (scoped provider)', async () => { + const MY_PROVIDER = 'MY_PROVIDER'; + const FIRST_OPTIONAL_DEPENDENCY = 'FIRST_OPTIONAL_DEPENDENCY'; + const SECOND_OPTIONAL_DEPENDENCY = 'SECOND_OPTIONAL_DEPENDENCY'; + + const module = await Test.createTestingModule({ + providers: [ + { + provide: FIRST_OPTIONAL_DEPENDENCY, + useValue: 'first', + }, + { + provide: MY_PROVIDER, + scope: Scope.REQUEST, + inject: [ + { + token: FIRST_OPTIONAL_DEPENDENCY, + optional: true, + }, + { + token: SECOND_OPTIONAL_DEPENDENCY, + optional: true, + }, + ], + useFactory: (first?: string, second?: string) => { + return { first, second }; + }, + }, + ], + }).compile(); + + expect(await module.resolve(MY_PROVIDER)).to.equal({ + first: 'first', + second: undefined, + }); + }); }); }); describe('otherwise', () => { From ced2acff6138c0bf95a5aafcceba2fc0fad1a237 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20My=C5=9Bliwiec?= Date: Tue, 12 Jul 2022 10:07:16 +0200 Subject: [PATCH 3/3] test(): hotfix - use deep equal instead --- integration/injector/e2e/optional-factory-provider-dep.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration/injector/e2e/optional-factory-provider-dep.spec.ts b/integration/injector/e2e/optional-factory-provider-dep.spec.ts index 732bf1fc2e4..b3a1c405c10 100644 --- a/integration/injector/e2e/optional-factory-provider-dep.spec.ts +++ b/integration/injector/e2e/optional-factory-provider-dep.spec.ts @@ -70,7 +70,7 @@ describe('Optional factory provider deps', () => { ], }).compile(); - expect(await module.resolve(MY_PROVIDER)).to.equal({ + expect(await module.resolve(MY_PROVIDER)).to.deep.equal({ first: 'first', second: undefined, });