diff --git a/package.json b/package.json index e2b4c75..608ddee 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "ts-eventsourcing", "private": false, - "version": "1.2.0", + "version": "1.2.1", "description": "Typed event sourcing framework", "main": "build/index.js", "types": "build/index.d.ts", diff --git a/src/QueryHandling/Error/IncorrectQueryHandlerError.ts b/src/QueryHandling/Error/IncorrectQueryHandlerError.ts index 07d5962..133b5bf 100644 --- a/src/QueryHandling/Error/IncorrectQueryHandlerError.ts +++ b/src/QueryHandling/Error/IncorrectQueryHandlerError.ts @@ -13,4 +13,9 @@ export class IncorrectQueryHandlerError extends Error { return new this(`Missing a Query handler on ${QueryHandlerName}. Don't forget @HandleQuery annotation`); } + public static missingQuery(queryHandler: QueryHandler, functionName: string) { + const QueryHandlerName = ClassUtil.nameOffInstance(queryHandler); + return new this(`Missing a Query in @HandleQuery() arguments ${QueryHandlerName}.${functionName}`); + } + } diff --git a/src/QueryHandling/HandleQuery.ts b/src/QueryHandling/HandleQuery.ts index a6e6210..b21771b 100644 --- a/src/QueryHandling/HandleQuery.ts +++ b/src/QueryHandling/HandleQuery.ts @@ -19,7 +19,7 @@ export function getHandleQueryMetadata(target: QueryHandler): QueryHandlerMetada return metadata; } -export function HandleQuery(target: any, key: string): void { +function HandleQueryByParameterTypes(target: any, key: string): void { const types = Reflect.getMetadata('design:paramtypes', target, key); const constructor = target.constructor as QueryHandlerConstructor; let handlers = Metadata.getMetadata(QUERY_HANDLERS, constructor); @@ -36,3 +36,26 @@ export function HandleQuery(target: any, key: string): void { Metadata.defineMetadata(QUERY_HANDLERS, handlers, constructor); } + +export function HandleQuery(target: any, functionName: string): void; +export function HandleQuery(...queries: QueryConstructor[]): (target: any, functionName: string) => void; +export function HandleQuery(...args: any[]): ((target: any, functionName: string) => void) | void { + if (args.length === 0 || typeof args[0] === 'function') { + return (target: any, functionName: string) => { + const constructor = target.constructor as QueryHandlerConstructor; + if (args.length === 0) { + throw IncorrectQueryHandlerError.missingQuery(constructor, functionName); + } + let handlers = Metadata.getMetadata(QUERY_HANDLERS, constructor); + handlers = handlers ? handlers : []; + for (const Query of args) { + handlers.push({ + functionName, + Query, + }); + } + Metadata.defineMetadata(QUERY_HANDLERS, handlers, constructor); + }; + } + return HandleQueryByParameterTypes(args[0], args[1]); +} diff --git a/src/QueryHandling/__test__/handleQuery.test.ts b/src/QueryHandling/__test__/handleQuery.test.ts index 3779510..d9b13bb 100644 --- a/src/QueryHandling/__test__/handleQuery.test.ts +++ b/src/QueryHandling/__test__/handleQuery.test.ts @@ -83,3 +83,60 @@ it('Should have an handle function', () => { getHandleQueryMetadata(new TestQueryHandler()); }).toThrow(IncorrectQueryHandlerError); }); + +it('Can register multiple Query handler by arguments', () => { + class TestQuery1 implements Query { + + } + + class TestQuery2 implements Query { + + } + + class TestQueryHandler implements QueryHandler { + + @HandleQuery(TestQuery1, TestQuery2) + public handle(_Query: TestQuery1 | TestQuery2): void { + // noop + } + + @HandleQuery(TestQuery1, TestQuery2) + public handleExtra(_Query: TestQuery1 | TestQuery2): void { + // noop + } + } + + const queryHandler = new TestQueryHandler(); + const metadata = getHandleQueryMetadata(queryHandler); + + expect(metadata).toEqual([ + { + functionName: 'handle', + Query: TestQuery1, + }, { + functionName: 'handle', + Query: TestQuery2, + }, + { + functionName: 'handleExtra', + Query: TestQuery1, + }, { + functionName: 'handleExtra', + Query: TestQuery2, + }, + ]); +}); + +it('Should pass Query to handler by arguments', () => { + expect(() => { + class TestQueryHandler implements QueryHandler { + + @HandleQuery() + public handle(): void { + // noop + } + } + const handler = new TestQueryHandler(); + handler.handle(); + }).toThrow(IncorrectQueryHandlerError); +});