diff --git a/packages/framework/tests/provider-visibility-issue/auth-listener.ts b/packages/framework/tests/provider-visibility-issue/auth-listener.ts new file mode 100644 index 000000000..ff351e211 --- /dev/null +++ b/packages/framework/tests/provider-visibility-issue/auth-listener.ts @@ -0,0 +1,18 @@ +import { eventDispatcher } from '@deepkit/event'; +import { httpWorkflow } from '@deepkit/http'; +import { AuthenticationModule } from './auth-module.js'; +import { SessionForRequest } from './session-for-request.dto.js'; + +export class AuthenticationListener { + @eventDispatcher.listen(httpWorkflow.onAuth) + onServerMainBootstrap(event: typeof httpWorkflow.onAuth.event, module: AuthenticationModule) { + event.injectorContext.set( + SessionForRequest, + new SessionForRequest( + 'sidValue', + 'uidValue', + ), + module + ); + } +} diff --git a/packages/framework/tests/provider-visibility-issue/auth-module.ts b/packages/framework/tests/provider-visibility-issue/auth-module.ts new file mode 100644 index 000000000..a7758f4aa --- /dev/null +++ b/packages/framework/tests/provider-visibility-issue/auth-module.ts @@ -0,0 +1,23 @@ +import { createModule } from '@deepkit/app'; +import { SessionForRequest } from './session-for-request.dto.js'; +import { AuthenticationListener } from './auth-listener.js'; +import { http } from '@deepkit/http'; + + +@http.controller('/auth') +class OAuth2Controller { + @http.GET('/whoami') + whoami(sess: SessionForRequest) { + // Trying to consume "SessionForRequest" within the same module it's provided – no luck + return sess; + } +} + +export class AuthenticationModule extends createModule({ + providers: [ + { provide: SessionForRequest, scope: 'http', useValue: undefined }, + ], + controllers: [OAuth2Controller], + listeners: [AuthenticationListener], + exports: [SessionForRequest], +}) { } diff --git a/packages/framework/tests/provider-visibility-issue/provider-visibility-issue.spec.ts b/packages/framework/tests/provider-visibility-issue/provider-visibility-issue.spec.ts new file mode 100644 index 000000000..078daae4a --- /dev/null +++ b/packages/framework/tests/provider-visibility-issue/provider-visibility-issue.spec.ts @@ -0,0 +1,59 @@ +import { expect, test } from '@jest/globals'; +import { http, HttpKernel, HttpRequest } from '@deepkit/http'; +import { App, createModule } from '@deepkit/app'; +import { FrameworkModule } from '../../src/module.js'; +import { SessionForRequest } from './session-for-request.dto.js'; +import { AuthenticationModule } from './auth-module.js'; + +test('provider-visibility-issue', async () => { + class IAMModule extends createModule({ exports: [AuthenticationModule] }) { + imports = [new AuthenticationModule()]; + } + + + @http.controller('/another') + class AnotherDomainModuleController { + @http.GET('/action') + action(sess: SessionForRequest) { + // Trying to consume "SessionForRequest" within another module – still no luck + return sess; + } + } + class AnotherDomainModule extends createModule({}) { + controllers = [AnotherDomainModuleController]; + } + + class DomainModule extends createModule({ exports: [IAMModule] }) { + imports = [new IAMModule(), new AnotherDomainModule()]; + } + + class InfrastructureModule extends createModule({ + // The whole issue gets "fixed" if DomainModule gets exported here, but what if I don't need to export it? + exports: [], + }) { + imports = [new DomainModule()]; + } + + const app = new App({ + imports: [ + new FrameworkModule({ debug: true }), + new InfrastructureModule(), + ], + providers: [], + }); + + /** + * These fail due to the following error: + * + * Controller for route /auth/whoami parameter resolving error: + * DependenciesUnmetError: Parameter sess is required but provider returned undefined. + */ + expect((await app.get(HttpKernel).request(HttpRequest.GET('/auth/whoami'))).json).toMatchObject({ + sessionId: 'sidValue', + userId: 'uidValue' + }); + expect((await app.get(HttpKernel).request(HttpRequest.GET('/another/action'))).json).toMatchObject({ + sessionId: 'sidValue', + userId: 'uidValue' + }); +}); diff --git a/packages/framework/tests/provider-visibility-issue/session-for-request.dto.ts b/packages/framework/tests/provider-visibility-issue/session-for-request.dto.ts new file mode 100644 index 000000000..b66fd65fe --- /dev/null +++ b/packages/framework/tests/provider-visibility-issue/session-for-request.dto.ts @@ -0,0 +1,6 @@ +export class SessionForRequest { + constructor( + public readonly sessionId: string, + public readonly userId: string, + ) {} +} diff --git a/packages/framework/tests/service-container.spec.ts b/packages/framework/tests/service-container.spec.ts index 79e14d5a1..ba5793bc6 100644 --- a/packages/framework/tests/service-container.spec.ts +++ b/packages/framework/tests/service-container.spec.ts @@ -188,95 +188,3 @@ test('database injection useClass with defaults', () => { const registry = app.get(DatabaseRegistry); expect(registry.getDatabases()).toHaveLength(1); }); - - -test('provider-visibility-issue', async () => { - class SessionForRequest { - constructor( - public readonly sessionId: string, - public readonly userId: string, - ) {} - } - - class AuthenticationListener { - @eventDispatcher.listen(httpWorkflow.onAuth) - onServerMainBootstrap(event: typeof httpWorkflow.onAuth.event) { - event.injectorContext.set( - SessionForRequest, - new SessionForRequest( - 'sidValue', - 'uidValue', - ), - ); - } - } - - @http.controller('/auth') - class OAuth2Controller { - @http.GET('/whoami') - whoami(sess: SessionForRequest) { - // Trying to consume "SessionForRequest" within the same module it's provided – no luck - return sess; - } - } - - class AuthenticationModule extends createModule({ - providers: [ - { provide: SessionForRequest, scope: 'http', useValue: undefined }, - ], - controllers: [OAuth2Controller], - listeners: [AuthenticationListener], - exports: [SessionForRequest], - }) { } - - class IAMModule extends createModule({ exports: [AuthenticationModule] }) { - imports = [new AuthenticationModule()]; - } - - - @http.controller('/another') - class AnotherDomainModuleController { - @http.GET('/action') - action(sess: SessionForRequest) { - // Trying to consume "SessionForRequest" within another module – still no luck - return sess; - } - } - class AnotherDomainModule extends createModule({}) { - controllers = [AnotherDomainModuleController]; - } - - class DomainModule extends createModule({ exports: [IAMModule] }) { - imports = [new IAMModule(), new AnotherDomainModule()]; - } - - class InfrastructureModule extends createModule({ - // The whole issue gets "fixed" if DomainModule gets exported here, but what if I don't need to export it? - exports: [], - }) { - imports = [new DomainModule()]; - } - - const app = new App({ - imports: [ - new FrameworkModule({ debug: true }), - new InfrastructureModule(), - ], - providers: [], - }); - - /** - * These fail due to the following error: - * - * Controller for route /auth/whoami parameter resolving error: - * DependenciesUnmetError: Parameter sess is required but provider returned undefined. - */ - expect((await app.get(HttpKernel).request(HttpRequest.GET('/auth/whoami'))).json).toMatchObject({ - sessionId: 'sidValue', - userId: 'uidValue' - }); - expect((await app.get(HttpKernel).request(HttpRequest.GET('/another/action'))).json).toMatchObject({ - sessionId: 'sidValue', - userId: 'uidValue' - }); -});