@hg-ts/cqrs 0.1.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintcache +1 -0
- package/.turbo/turbo-build.log +2 -0
- package/.turbo/turbo-lint$colon$ts.log +2 -0
- package/.turbo/turbo-test.log +30 -0
- package/README.md +1 -0
- package/dist/abstracts/base.command-handler.d.ts +6 -0
- package/dist/abstracts/base.command-handler.d.ts.map +1 -0
- package/dist/abstracts/base.command-handler.js +7 -0
- package/dist/abstracts/base.command-handler.js.map +1 -0
- package/dist/abstracts/base.command.d.ts +6 -0
- package/dist/abstracts/base.command.d.ts.map +1 -0
- package/dist/abstracts/base.command.js +9 -0
- package/dist/abstracts/base.command.js.map +1 -0
- package/dist/abstracts/base.executor.d.ts +11 -0
- package/dist/abstracts/base.executor.d.ts.map +1 -0
- package/dist/abstracts/base.executor.js +22 -0
- package/dist/abstracts/base.executor.js.map +1 -0
- package/dist/abstracts/base.executor.test-suite.d.ts +17 -0
- package/dist/abstracts/base.executor.test-suite.d.ts.map +1 -0
- package/dist/abstracts/base.executor.test-suite.js +60 -0
- package/dist/abstracts/base.executor.test-suite.js.map +1 -0
- package/dist/abstracts/base.query-handler.d.ts +6 -0
- package/dist/abstracts/base.query-handler.d.ts.map +1 -0
- package/dist/abstracts/base.query-handler.js +7 -0
- package/dist/abstracts/base.query-handler.js.map +1 -0
- package/dist/abstracts/base.query.d.ts +6 -0
- package/dist/abstracts/base.query.d.ts.map +1 -0
- package/dist/abstracts/base.query.js +9 -0
- package/dist/abstracts/base.query.js.map +1 -0
- package/dist/abstracts/index.d.ts +8 -0
- package/dist/abstracts/index.d.ts.map +1 -0
- package/dist/abstracts/index.js +11 -0
- package/dist/abstracts/index.js.map +1 -0
- package/dist/command/command.executor.d.ts +6 -0
- package/dist/command/command.executor.d.ts.map +1 -0
- package/dist/command/command.executor.js +14 -0
- package/dist/command/command.executor.js.map +1 -0
- package/dist/command/index.d.ts +2 -0
- package/dist/command/index.d.ts.map +1 -0
- package/dist/command/index.js +5 -0
- package/dist/command/index.js.map +1 -0
- package/dist/command/query.executor.d.ts +6 -0
- package/dist/command/query.executor.d.ts.map +1 -0
- package/dist/command/query.executor.js +14 -0
- package/dist/command/query.executor.js.map +1 -0
- package/dist/cqrs.module.d.ts +12 -0
- package/dist/cqrs.module.d.ts.map +1 -0
- package/dist/cqrs.module.js +96 -0
- package/dist/cqrs.module.js.map +1 -0
- package/dist/decorators/command-handler.decorator.d.ts +4 -0
- package/dist/decorators/command-handler.decorator.d.ts.map +1 -0
- package/dist/decorators/command-handler.decorator.js +11 -0
- package/dist/decorators/command-handler.decorator.js.map +1 -0
- package/dist/decorators/index.d.ts +4 -0
- package/dist/decorators/index.d.ts.map +1 -0
- package/dist/decorators/index.js +7 -0
- package/dist/decorators/index.js.map +1 -0
- package/dist/decorators/query-handler.decorator.d.ts +4 -0
- package/dist/decorators/query-handler.decorator.d.ts.map +1 -0
- package/dist/decorators/query-handler.decorator.js +11 -0
- package/dist/decorators/query-handler.decorator.js.map +1 -0
- package/dist/exceptions/handler-already-added.exception.d.ts +6 -0
- package/dist/exceptions/handler-already-added.exception.d.ts.map +1 -0
- package/dist/exceptions/handler-already-added.exception.js +11 -0
- package/dist/exceptions/handler-already-added.exception.js.map +1 -0
- package/dist/exceptions/handler-not-found.exception.d.ts +6 -0
- package/dist/exceptions/handler-not-found.exception.d.ts.map +1 -0
- package/dist/exceptions/handler-not-found.exception.js +11 -0
- package/dist/exceptions/handler-not-found.exception.js.map +1 -0
- package/dist/exceptions/index.d.ts +3 -0
- package/dist/exceptions/index.d.ts.map +1 -0
- package/dist/exceptions/index.js +6 -0
- package/dist/exceptions/index.js.map +1 -0
- package/dist/executors/command.executor.d.ts +6 -0
- package/dist/executors/command.executor.d.ts.map +1 -0
- package/dist/executors/command.executor.js +14 -0
- package/dist/executors/command.executor.js.map +1 -0
- package/dist/executors/index.d.ts +3 -0
- package/dist/executors/index.d.ts.map +1 -0
- package/dist/executors/index.js +6 -0
- package/dist/executors/index.js.map +1 -0
- package/dist/executors/query.executor.d.ts +6 -0
- package/dist/executors/query.executor.d.ts.map +1 -0
- package/dist/executors/query.executor.js +14 -0
- package/dist/executors/query.executor.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/tests/command-executor.mock.d.ts +5 -0
- package/dist/tests/command-executor.mock.d.ts.map +1 -0
- package/dist/tests/command-executor.mock.js +13 -0
- package/dist/tests/command-executor.mock.js.map +1 -0
- package/dist/tests/command-executor.test.d.ts +9 -0
- package/dist/tests/command-executor.test.d.ts.map +1 -0
- package/dist/tests/command-executor.test.js +28 -0
- package/dist/tests/command-executor.test.js.map +1 -0
- package/dist/tests/commands/index.d.ts +3 -0
- package/dist/tests/commands/index.d.ts.map +1 -0
- package/dist/tests/commands/index.js +6 -0
- package/dist/tests/commands/index.js.map +1 -0
- package/dist/tests/commands/test.command.d.ts +6 -0
- package/dist/tests/commands/test.command.d.ts.map +1 -0
- package/dist/tests/commands/test.command.js +13 -0
- package/dist/tests/commands/test.command.js.map +1 -0
- package/dist/tests/commands/unknown.command.d.ts +6 -0
- package/dist/tests/commands/unknown.command.d.ts.map +1 -0
- package/dist/tests/commands/unknown.command.js +13 -0
- package/dist/tests/commands/unknown.command.js.map +1 -0
- package/dist/tests/cqrs-test.module.d.ts +3 -0
- package/dist/tests/cqrs-test.module.d.ts.map +1 -0
- package/dist/tests/cqrs-test.module.js +15 -0
- package/dist/tests/cqrs-test.module.js.map +1 -0
- package/dist/tests/cqrs.module.test.d.ts +13 -0
- package/dist/tests/cqrs.module.test.d.ts.map +1 -0
- package/dist/tests/cqrs.module.test.js +79 -0
- package/dist/tests/cqrs.module.test.js.map +1 -0
- package/dist/tests/queries/index.d.ts +3 -0
- package/dist/tests/queries/index.d.ts.map +1 -0
- package/dist/tests/queries/index.js +6 -0
- package/dist/tests/queries/index.js.map +1 -0
- package/dist/tests/queries/test.query.d.ts +6 -0
- package/dist/tests/queries/test.query.d.ts.map +1 -0
- package/dist/tests/queries/test.query.js +13 -0
- package/dist/tests/queries/test.query.js.map +1 -0
- package/dist/tests/queries/unknown.query.d.ts +6 -0
- package/dist/tests/queries/unknown.query.d.ts.map +1 -0
- package/dist/tests/queries/unknown.query.js +13 -0
- package/dist/tests/queries/unknown.query.js.map +1 -0
- package/dist/tests/query-executor.test.d.ts +9 -0
- package/dist/tests/query-executor.test.d.ts.map +1 -0
- package/dist/tests/query-executor.test.js +28 -0
- package/dist/tests/query-executor.test.js.map +1 -0
- package/dist/tests/test-command.handler.d.ts +6 -0
- package/dist/tests/test-command.handler.d.ts.map +1 -0
- package/dist/tests/test-command.handler.js +21 -0
- package/dist/tests/test-command.handler.js.map +1 -0
- package/dist/tests/test-query.handler.d.ts +6 -0
- package/dist/tests/test-query.handler.d.ts.map +1 -0
- package/dist/tests/test-query.handler.js +21 -0
- package/dist/tests/test-query.handler.js.map +1 -0
- package/dist/tests/test.command.d.ts +6 -0
- package/dist/tests/test.command.d.ts.map +1 -0
- package/dist/tests/test.command.js +13 -0
- package/dist/tests/test.command.js.map +1 -0
- package/dist/tests/test.query.d.ts +6 -0
- package/dist/tests/test.query.d.ts.map +1 -0
- package/dist/tests/test.query.js +13 -0
- package/dist/tests/test.query.js.map +1 -0
- package/dist/tests/unknown.command.d.ts +6 -0
- package/dist/tests/unknown.command.d.ts.map +1 -0
- package/dist/tests/unknown.command.js +13 -0
- package/dist/tests/unknown.command.js.map +1 -0
- package/dist/tests/unknown.query.d.ts +6 -0
- package/dist/tests/unknown.query.d.ts.map +1 -0
- package/dist/tests/unknown.query.js +13 -0
- package/dist/tests/unknown.query.js.map +1 -0
- package/dist/types.d.ts +7 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/eslint.config.mjs +3 -0
- package/package.json +38 -0
- package/src/abstracts/base.command-handler.ts +6 -0
- package/src/abstracts/base.command.ts +5 -0
- package/src/abstracts/base.executor.test-suite.ts +64 -0
- package/src/abstracts/base.executor.ts +46 -0
- package/src/abstracts/base.query-handler.ts +6 -0
- package/src/abstracts/base.query.ts +5 -0
- package/src/abstracts/index.ts +7 -0
- package/src/cqrs.module.ts +120 -0
- package/src/decorators/command-handler.decorator.ts +14 -0
- package/src/decorators/index.ts +4 -0
- package/src/decorators/query-handler.decorator.ts +14 -0
- package/src/exceptions/handler-already-added.exception.ts +8 -0
- package/src/exceptions/handler-not-found.exception.ts +8 -0
- package/src/exceptions/index.ts +2 -0
- package/src/executors/command.executor.ts +18 -0
- package/src/executors/index.ts +2 -0
- package/src/executors/query.executor.ts +18 -0
- package/src/index.ts +10 -0
- package/src/tests/command-executor.test.ts +31 -0
- package/src/tests/commands/index.ts +2 -0
- package/src/tests/commands/test.command.ts +11 -0
- package/src/tests/commands/unknown.command.ts +11 -0
- package/src/tests/cqrs-test.module.ts +7 -0
- package/src/tests/cqrs.module.test.ts +73 -0
- package/src/tests/queries/index.ts +2 -0
- package/src/tests/queries/test.query.ts +11 -0
- package/src/tests/queries/unknown.query.ts +11 -0
- package/src/tests/query-executor.test.ts +30 -0
- package/src/tests/test-command.handler.ts +17 -0
- package/src/tests/test-query.handler.ts +18 -0
- package/src/types.ts +29 -0
- package/tsconfig.json +9 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { WillNeverHappenedException } from '@hg-ts/exception';
|
|
2
|
+
import {
|
|
3
|
+
Dependency,
|
|
4
|
+
DiscoveryService,
|
|
5
|
+
INIT_HOOK,
|
|
6
|
+
Module,
|
|
7
|
+
} from '@hg-ts/ioc';
|
|
8
|
+
import assert from 'node:assert/strict';
|
|
9
|
+
import {
|
|
10
|
+
BaseCommand,
|
|
11
|
+
BaseCommandHandler,
|
|
12
|
+
BaseQuery,
|
|
13
|
+
BaseQueryHandler,
|
|
14
|
+
} from './abstracts';
|
|
15
|
+
|
|
16
|
+
import {
|
|
17
|
+
COMMAND_HANDLER_METADATA,
|
|
18
|
+
QUERY_HANDLER_METADATA,
|
|
19
|
+
} from './decorators';
|
|
20
|
+
import {
|
|
21
|
+
CommandExecutor,
|
|
22
|
+
QueryExecutor,
|
|
23
|
+
} from './executors';
|
|
24
|
+
|
|
25
|
+
@Module({
|
|
26
|
+
providers: [
|
|
27
|
+
CommandExecutor,
|
|
28
|
+
QueryExecutor,
|
|
29
|
+
],
|
|
30
|
+
exports: [
|
|
31
|
+
CommandExecutor,
|
|
32
|
+
QueryExecutor,
|
|
33
|
+
],
|
|
34
|
+
discovery: true,
|
|
35
|
+
|
|
36
|
+
})
|
|
37
|
+
export class CqrsModule {
|
|
38
|
+
@Dependency()
|
|
39
|
+
private readonly discoveryService: DiscoveryService;
|
|
40
|
+
|
|
41
|
+
@Dependency()
|
|
42
|
+
private readonly commandExecutor: CommandExecutor;
|
|
43
|
+
|
|
44
|
+
@Dependency()
|
|
45
|
+
private readonly queryExecutor: QueryExecutor;
|
|
46
|
+
|
|
47
|
+
public async [INIT_HOOK](): Promise<void> {
|
|
48
|
+
const providers = this.discoveryService.getProviders()
|
|
49
|
+
.filter(wrapper => wrapper.instance)
|
|
50
|
+
.map(wrapper => wrapper.instance);
|
|
51
|
+
|
|
52
|
+
providers.forEach(provider => {
|
|
53
|
+
const handlerCtor = Object.getPrototypeOf(provider)!.constructor;
|
|
54
|
+
|
|
55
|
+
const isCommandHandler = this.isCommandHandler(provider);
|
|
56
|
+
const isQueryHandler = this.isQueryHandler(provider);
|
|
57
|
+
|
|
58
|
+
const commandMetadata = this.getCommandMetadata(handlerCtor);
|
|
59
|
+
const queryMetadata = this.getQueryMetadata(handlerCtor);
|
|
60
|
+
|
|
61
|
+
if (isCommandHandler && commandMetadata) {
|
|
62
|
+
this.commandExecutor['addHandler'](commandMetadata, provider);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (isCommandHandler) {
|
|
67
|
+
throw new WillNeverHappenedException('Command handler instance provided without CommandHandler decorator');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (commandMetadata) {
|
|
71
|
+
throw new WillNeverHappenedException('CommandHandler decorate class that does not extended BaseCommandHandler');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (isQueryHandler && queryMetadata) {
|
|
75
|
+
this.queryExecutor['addHandler'](queryMetadata, provider);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (isQueryHandler) {
|
|
80
|
+
throw new WillNeverHappenedException('Query handler instance provided without QueryHandler decorator');
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (queryMetadata) {
|
|
84
|
+
throw new WillNeverHappenedException('QueryHandler decorate class that does not extended BaseQueryHandler');
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
private getCommandMetadata(handlerCtor: Class<any, any[]>): Nullable<Class<BaseCommand, any[]>> {
|
|
90
|
+
const metadata = Reflect.getMetadata(COMMAND_HANDLER_METADATA, handlerCtor);
|
|
91
|
+
|
|
92
|
+
if (!metadata) {
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
assert.ok(metadata.prototype instanceof BaseCommand);
|
|
97
|
+
|
|
98
|
+
return metadata;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
private getQueryMetadata(handlerCtor: Class<any, any[]>): Nullable<Class<BaseQuery<any>, any[]>> {
|
|
102
|
+
const metadata = Reflect.getMetadata(QUERY_HANDLER_METADATA, handlerCtor);
|
|
103
|
+
|
|
104
|
+
if (!metadata) {
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
assert.ok(metadata.prototype instanceof BaseQuery);
|
|
109
|
+
|
|
110
|
+
return metadata;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
private isCommandHandler(provider: any): provider is BaseCommandHandler<BaseCommand<any>> {
|
|
114
|
+
return provider instanceof BaseCommandHandler;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
private isQueryHandler(provider: any): provider is BaseQueryHandler<BaseQuery<any>> {
|
|
118
|
+
return provider instanceof BaseQueryHandler;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BaseCommand,
|
|
3
|
+
BaseCommandHandler,
|
|
4
|
+
} from '../abstracts';
|
|
5
|
+
|
|
6
|
+
export const COMMAND_HANDLER_METADATA = Symbol('COMMAND_HANDLER_METADATA');
|
|
7
|
+
|
|
8
|
+
export function CommandHandler<Command extends BaseCommand<any>>(
|
|
9
|
+
commandCtor: Class<Command, any[]>,
|
|
10
|
+
): TypedClassDecorator<Class<BaseCommandHandler<Command>>> {
|
|
11
|
+
return (ctor: Class<BaseCommandHandler<Command>>) => {
|
|
12
|
+
Reflect.defineMetadata(COMMAND_HANDLER_METADATA, commandCtor, ctor);
|
|
13
|
+
};
|
|
14
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BaseQuery,
|
|
3
|
+
BaseQueryHandler,
|
|
4
|
+
} from '../abstracts';
|
|
5
|
+
|
|
6
|
+
export const QUERY_HANDLER_METADATA = Symbol('QUERY_HANDLER_METADATA');
|
|
7
|
+
|
|
8
|
+
export function QueryHandler<Query extends BaseQuery<any>>(
|
|
9
|
+
queryCtor: Class<Query, any[]>,
|
|
10
|
+
): TypedClassDecorator<Class<BaseQueryHandler<Query>>> {
|
|
11
|
+
return (ctor: Class<BaseQueryHandler<Query>>) => {
|
|
12
|
+
Reflect.defineMetadata(QUERY_HANDLER_METADATA, queryCtor, ctor);
|
|
13
|
+
};
|
|
14
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { BaseException } from '@hg-ts/exception';
|
|
2
|
+
import { BaseCommandOrQuery } from '../types';
|
|
3
|
+
|
|
4
|
+
export class HandlerAlreadyAddedException extends BaseException {
|
|
5
|
+
public constructor(command: Class<BaseCommandOrQuery>) {
|
|
6
|
+
super(`Handler for command "${command.name}" already added`);
|
|
7
|
+
}
|
|
8
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { BaseException } from '@hg-ts/exception';
|
|
2
|
+
import { BaseCommandOrQuery } from '../types';
|
|
3
|
+
|
|
4
|
+
export class HandlerNotFoundException extends BaseException {
|
|
5
|
+
public constructor(command: Class<BaseCommandOrQuery>) {
|
|
6
|
+
super(`Handler for command "${command.name}" not found`);
|
|
7
|
+
}
|
|
8
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BaseCommand,
|
|
3
|
+
BaseExecutor,
|
|
4
|
+
} from '../abstracts';
|
|
5
|
+
import { CommonResult } from '../types';
|
|
6
|
+
|
|
7
|
+
export class CommandExecutor extends BaseExecutor<BaseCommand<any>> {
|
|
8
|
+
protected override async executeHandler<Command extends BaseCommand<any>>(
|
|
9
|
+
command: Command,
|
|
10
|
+
): Promise<CommonResult<Command>> {
|
|
11
|
+
const commandCtor = Object.getPrototypeOf(command)!.constructor as Class<Command>;
|
|
12
|
+
const handler = this.handlers.get(commandCtor) ?? null;
|
|
13
|
+
|
|
14
|
+
this.assertHandler(handler, commandCtor);
|
|
15
|
+
|
|
16
|
+
return handler.execute(command);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BaseQuery,
|
|
3
|
+
BaseExecutor,
|
|
4
|
+
} from '../abstracts';
|
|
5
|
+
import { CommonResult } from '../types';
|
|
6
|
+
|
|
7
|
+
export class QueryExecutor extends BaseExecutor<BaseQuery<any>> {
|
|
8
|
+
protected override async executeHandler<Query extends BaseQuery<any>>(
|
|
9
|
+
query: Query,
|
|
10
|
+
): Promise<CommonResult<Query>> {
|
|
11
|
+
const queryCtor = Object.getPrototypeOf(query)!.constructor as Class<Query>;
|
|
12
|
+
const handler = this.handlers.get(queryCtor) ?? null;
|
|
13
|
+
|
|
14
|
+
this.assertHandler(handler, queryCtor);
|
|
15
|
+
|
|
16
|
+
return handler.execute(query);
|
|
17
|
+
}
|
|
18
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export {
|
|
2
|
+
BaseQuery,
|
|
3
|
+
BaseQueryHandler,
|
|
4
|
+
BaseCommand,
|
|
5
|
+
BaseCommandHandler,
|
|
6
|
+
} from './abstracts';
|
|
7
|
+
export * from './exceptions';
|
|
8
|
+
export * from './executors';
|
|
9
|
+
export { CommandHandler, QueryHandler } from './decorators';
|
|
10
|
+
export { CqrsModule } from './cqrs.module';
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Describe } from '@hg-ts/tests';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
BaseCommand,
|
|
5
|
+
BaseCommandHandler,
|
|
6
|
+
BaseExecutor,
|
|
7
|
+
BaseExecutorTestSuite,
|
|
8
|
+
} from '../abstracts';
|
|
9
|
+
import { CommandExecutor } from '../executors';
|
|
10
|
+
import { TestCommand } from './commands';
|
|
11
|
+
|
|
12
|
+
import { TestCommandHandler } from './test-command.handler';
|
|
13
|
+
|
|
14
|
+
@Describe()
|
|
15
|
+
export class CommandExecutorTest extends BaseExecutorTestSuite<BaseCommand<any>> {
|
|
16
|
+
protected override getCommandOrQuery(input: string): TestCommand {
|
|
17
|
+
return new TestCommand(input);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
protected override getExecutor(): BaseExecutor<BaseCommand<any>> {
|
|
21
|
+
return new CommandExecutor();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
protected override getHandler(): BaseCommandHandler<BaseCommand<any>> {
|
|
25
|
+
return new TestCommandHandler();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
protected override getCommandOrQueryCtor(): Class<BaseCommand<any>, [string]> {
|
|
29
|
+
return TestCommand;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { BaseCommand } from '../../abstracts';
|
|
2
|
+
|
|
3
|
+
export class TestCommand extends BaseCommand<string> {
|
|
4
|
+
public readonly expectedResult: string;
|
|
5
|
+
|
|
6
|
+
public constructor(expectedResult: string) {
|
|
7
|
+
super();
|
|
8
|
+
|
|
9
|
+
this.expectedResult = expectedResult;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { BaseCommand } from '../../abstracts';
|
|
2
|
+
|
|
3
|
+
export class UnknownCommand extends BaseCommand<string> {
|
|
4
|
+
public readonly expectedResult: string;
|
|
5
|
+
|
|
6
|
+
public constructor(expectedResult: string) {
|
|
7
|
+
super();
|
|
8
|
+
|
|
9
|
+
this.expectedResult = expectedResult;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Module } from '@hg-ts/ioc';
|
|
2
|
+
import { CqrsModule } from '../cqrs.module';
|
|
3
|
+
import { TestCommandHandler } from './test-command.handler';
|
|
4
|
+
import { TestQueryHandler } from './test-query.handler';
|
|
5
|
+
|
|
6
|
+
@Module({ imports: [CqrsModule], providers: [TestCommandHandler, TestQueryHandler] })
|
|
7
|
+
export class CqrsTestModule {}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { TestContainer } from '@hg-ts/ioc';
|
|
2
|
+
import {
|
|
3
|
+
Describe,
|
|
4
|
+
expect,
|
|
5
|
+
ExpectException,
|
|
6
|
+
Suite,
|
|
7
|
+
Test,
|
|
8
|
+
} from '@hg-ts/tests';
|
|
9
|
+
|
|
10
|
+
import { HandlerNotFoundException } from '../exceptions';
|
|
11
|
+
import {
|
|
12
|
+
CommandExecutor,
|
|
13
|
+
QueryExecutor,
|
|
14
|
+
} from '../executors';
|
|
15
|
+
import {
|
|
16
|
+
TestCommand,
|
|
17
|
+
UnknownCommand,
|
|
18
|
+
} from './commands';
|
|
19
|
+
import { CqrsTestModule } from './cqrs-test.module';
|
|
20
|
+
import {
|
|
21
|
+
TestQuery,
|
|
22
|
+
UnknownQuery,
|
|
23
|
+
} from './queries';
|
|
24
|
+
|
|
25
|
+
@Describe()
|
|
26
|
+
export class QueryExecutorTest extends Suite {
|
|
27
|
+
private container: TestContainer;
|
|
28
|
+
private commandExecutor: CommandExecutor;
|
|
29
|
+
private queryExecutor: QueryExecutor;
|
|
30
|
+
|
|
31
|
+
@Test()
|
|
32
|
+
public async executorProvides(): Promise<void> {
|
|
33
|
+
expect(this.commandExecutor).toBeInstanceOf(CommandExecutor);
|
|
34
|
+
expect(this.queryExecutor).toBeInstanceOf(QueryExecutor);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
@Test()
|
|
38
|
+
public async commandSuccess(): Promise<void> {
|
|
39
|
+
const value = String(Math.random());
|
|
40
|
+
const result = await this.commandExecutor.execute(new TestCommand(value));
|
|
41
|
+
|
|
42
|
+
expect(result).toBe(value);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
@Test()
|
|
46
|
+
@ExpectException(HandlerNotFoundException)
|
|
47
|
+
public async unknownCommand(): Promise<void> {
|
|
48
|
+
await this.commandExecutor.execute(new UnknownCommand(''));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
@Test()
|
|
52
|
+
public async querySuccess(): Promise<void> {
|
|
53
|
+
const value = String(Math.random());
|
|
54
|
+
const result = await this.queryExecutor.execute(new TestQuery(value));
|
|
55
|
+
|
|
56
|
+
expect(result).toBe(value);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
@Test()
|
|
60
|
+
@ExpectException(HandlerNotFoundException)
|
|
61
|
+
public async unknownQuery(): Promise<void> {
|
|
62
|
+
await this.queryExecutor.execute(new UnknownQuery(''));
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
public override async beforeEach(): Promise<void> {
|
|
66
|
+
this.container = await TestContainer.create(CqrsTestModule);
|
|
67
|
+
|
|
68
|
+
await this.container.init();
|
|
69
|
+
|
|
70
|
+
this.queryExecutor = this.container.get(QueryExecutor);
|
|
71
|
+
this.commandExecutor = this.container.get(CommandExecutor);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Describe } from '@hg-ts/tests';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
BaseExecutor,
|
|
5
|
+
BaseExecutorTestSuite,
|
|
6
|
+
BaseQuery,
|
|
7
|
+
BaseQueryHandler,
|
|
8
|
+
} from '../abstracts';
|
|
9
|
+
import { QueryExecutor } from '../executors';
|
|
10
|
+
import { TestQuery } from './queries';
|
|
11
|
+
import { TestQueryHandler } from './test-query.handler';
|
|
12
|
+
|
|
13
|
+
@Describe()
|
|
14
|
+
export class QueryExecutorTest extends BaseExecutorTestSuite<BaseQuery<any>> {
|
|
15
|
+
protected override getCommandOrQuery(input: string): TestQuery {
|
|
16
|
+
return new TestQuery(input);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
protected override getExecutor(): BaseExecutor<BaseQuery<any>> {
|
|
20
|
+
return new QueryExecutor();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
protected override getHandler(): BaseQueryHandler<BaseQuery<any>> {
|
|
24
|
+
return new TestQueryHandler();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
protected override getCommandOrQueryCtor(): Class<BaseQuery<any>, [string]> {
|
|
28
|
+
return TestQuery;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { UnknownException } from '@hg-ts/exception';
|
|
2
|
+
import {
|
|
3
|
+
BaseCommandHandler,
|
|
4
|
+
INPUT_FOR_EXCEPTION,
|
|
5
|
+
} from '../abstracts';
|
|
6
|
+
import { CommandHandler } from '../decorators';
|
|
7
|
+
import { TestCommand } from './commands';
|
|
8
|
+
|
|
9
|
+
@CommandHandler(TestCommand)
|
|
10
|
+
export class TestCommandHandler extends BaseCommandHandler<TestCommand> {
|
|
11
|
+
public async execute(command: TestCommand): Promise<string> {
|
|
12
|
+
if (command.expectedResult === INPUT_FOR_EXCEPTION) {
|
|
13
|
+
throw new UnknownException(command.expectedResult);
|
|
14
|
+
}
|
|
15
|
+
return command.expectedResult;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { UnknownException } from '@hg-ts/exception';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
BaseQueryHandler,
|
|
5
|
+
INPUT_FOR_EXCEPTION,
|
|
6
|
+
} from '../abstracts';
|
|
7
|
+
import { QueryHandler } from '../decorators';
|
|
8
|
+
import { TestQuery } from './queries';
|
|
9
|
+
|
|
10
|
+
@QueryHandler(TestQuery)
|
|
11
|
+
export class TestQueryHandler extends BaseQueryHandler<TestQuery> {
|
|
12
|
+
public async execute(command: TestQuery): Promise<string> {
|
|
13
|
+
if (command.expectedResult === INPUT_FOR_EXCEPTION) {
|
|
14
|
+
throw new UnknownException(command.expectedResult);
|
|
15
|
+
}
|
|
16
|
+
return command.expectedResult;
|
|
17
|
+
}
|
|
18
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BaseQuery,
|
|
3
|
+
BaseCommand,
|
|
4
|
+
BaseQueryHandler,
|
|
5
|
+
BaseCommandHandler,
|
|
6
|
+
} from './abstracts';
|
|
7
|
+
|
|
8
|
+
export type CommandResult<Command extends BaseCommand<any>> = Command extends BaseCommand<infer Result>
|
|
9
|
+
? Result
|
|
10
|
+
: never;
|
|
11
|
+
export type QueryResult<Command extends BaseQuery<any>> = Command extends BaseQuery<infer Result>
|
|
12
|
+
? Result
|
|
13
|
+
: never;
|
|
14
|
+
|
|
15
|
+
export type BaseCommandOrQuery = BaseQuery<any> | BaseCommand<any>;
|
|
16
|
+
|
|
17
|
+
export type CommonHandler<CommandOrQuery extends BaseCommandOrQuery> =
|
|
18
|
+
CommandOrQuery extends BaseQuery<any>
|
|
19
|
+
? BaseQueryHandler<CommandOrQuery>
|
|
20
|
+
: CommandOrQuery extends BaseCommand<any>
|
|
21
|
+
? BaseCommandHandler<CommandOrQuery>
|
|
22
|
+
: never;
|
|
23
|
+
|
|
24
|
+
export type CommonResult<CommandOrQuery extends BaseCommandOrQuery> =
|
|
25
|
+
CommandOrQuery extends BaseQuery<any>
|
|
26
|
+
? QueryResult<CommandOrQuery>
|
|
27
|
+
: CommandOrQuery extends BaseCommand<any>
|
|
28
|
+
? CommandResult<CommandOrQuery>
|
|
29
|
+
: never;
|