@cqrs-ddd/cqrs 0.5.0
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/COMMERCIAL_LICENSE.txt +34 -0
- package/LICENSE +661 -0
- package/README.md +39 -0
- package/dist/command.bus.d.ts +35 -0
- package/dist/command.bus.d.ts.map +1 -0
- package/dist/command.bus.js +43 -0
- package/dist/command.bus.js.map +1 -0
- package/dist/create-cqrs.d.ts +62 -0
- package/dist/create-cqrs.d.ts.map +1 -0
- package/dist/create-cqrs.js +54 -0
- package/dist/create-cqrs.js.map +1 -0
- package/dist/decorators.d.ts +73 -0
- package/dist/decorators.d.ts.map +1 -0
- package/dist/decorators.js +104 -0
- package/dist/decorators.js.map +1 -0
- package/dist/dispatch.d.ts +31 -0
- package/dist/dispatch.d.ts.map +1 -0
- package/dist/dispatch.js +67 -0
- package/dist/dispatch.js.map +1 -0
- package/dist/errors.d.ts +26 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +37 -0
- package/dist/errors.js.map +1 -0
- package/dist/event.bus.d.ts +79 -0
- package/dist/event.bus.d.ts.map +1 -0
- package/dist/event.bus.js +86 -0
- package/dist/event.bus.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/interfaces.d.ts +68 -0
- package/dist/interfaces.d.ts.map +1 -0
- package/dist/interfaces.js +3 -0
- package/dist/interfaces.js.map +1 -0
- package/dist/query.bus.d.ts +35 -0
- package/dist/query.bus.d.ts.map +1 -0
- package/dist/query.bus.js +43 -0
- package/dist/query.bus.js.map +1 -0
- package/dist/registry.d.ts +38 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +92 -0
- package/dist/registry.js.map +1 -0
- package/dist/unhandled-exception.bus.d.ts +43 -0
- package/dist/unhandled-exception.bus.d.ts.map +1 -0
- package/dist/unhandled-exception.bus.js +56 -0
- package/dist/unhandled-exception.bus.js.map +1 -0
- package/package.json +62 -0
package/README.md
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# @cqrs-ddd/cqrs
|
|
2
|
+
|
|
3
|
+
Command, query and event buses for TypeScript, with a pipeline of behaviors around each
|
|
4
|
+
handler: `@CommandHandler`, `@QueryHandler` and `@EventsHandler` on handler classes,
|
|
5
|
+
`@UsePipeline` and `@SkipPipeline` of `@cqrs-ddd/pipeline` for their behaviors, and
|
|
6
|
+
`createCqrs()`, which builds the buses and registers handler instances. No framework and
|
|
7
|
+
no container.
|
|
8
|
+
|
|
9
|
+
**Documentation:** [guide](https://aristoteliss.github.io/ddd-cqrs/packages/cqrs/) · [API reference](https://aristoteliss.github.io/ddd-cqrs/api/cqrs-ddd/cqrs/) · [all packages](https://aristoteliss.github.io/ddd-cqrs/)
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pnpm add @cqrs-ddd/cqrs @cqrs-ddd/pipeline
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Requires Node.js 22.12 or later. The decorators work with TypeScript's standard decorators
|
|
18
|
+
and with `experimentalDecorators`. Published as an ES module; a CommonJS application loads
|
|
19
|
+
it with `require()`.
|
|
20
|
+
|
|
21
|
+
## Example
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
@CommandHandler(CreateUserCommand)
|
|
25
|
+
@UsePipeline(audit({ action: 'user.create' }))
|
|
26
|
+
class CreateUserHandler implements ICommandHandler<CreateUserCommand> {
|
|
27
|
+
constructor(private readonly users: Users) {}
|
|
28
|
+
async execute(command: CreateUserCommand) {}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const cqrs = createCqrs({ behaviors: [new AuditBehavior(sink)] });
|
|
32
|
+
cqrs.register(new CreateUserHandler(users));
|
|
33
|
+
await cqrs.commandBus.execute(new CreateUserCommand('Ann'));
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## License
|
|
37
|
+
|
|
38
|
+
Dual-licensed under **AGPLv3** and a **Commercial License**. See `LICENSE` and
|
|
39
|
+
`COMMERCIAL_LICENSE.txt`.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { RequestType } from './decorators.js';
|
|
2
|
+
import { type Dispatch } from './dispatch.js';
|
|
3
|
+
import type { ICommand } from './interfaces.js';
|
|
4
|
+
/**
|
|
5
|
+
* Sends a command to its one handler, through the handler's pipeline. `createCqrs()`
|
|
6
|
+
* builds it.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* const { commandBus } = createCqrs();
|
|
11
|
+
* const id = await commandBus.execute<CreateUserCommand, string>(new CreateUserCommand('ann'));
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
export declare class CommandBus<C extends ICommand = ICommand> {
|
|
15
|
+
private readonly handlers;
|
|
16
|
+
/**
|
|
17
|
+
* @param handlers - Maps each command class to the function that runs its handler. The
|
|
18
|
+
* bus reads it at every call, so it can be filled after the bus is created, as
|
|
19
|
+
* handlers that inject the bus require.
|
|
20
|
+
*/
|
|
21
|
+
constructor(handlers: ReadonlyMap<RequestType, Dispatch>);
|
|
22
|
+
/**
|
|
23
|
+
* Runs the handler of the command's class, or of its nearest parent class that has
|
|
24
|
+
* one, and resolves with what the handler returns, typed as `R`.
|
|
25
|
+
*
|
|
26
|
+
* @throws CommandHandlerNotFoundException (as a rejection) when no class in the
|
|
27
|
+
* command's chain has a handler.
|
|
28
|
+
* @example
|
|
29
|
+
* ```ts
|
|
30
|
+
* await commandBus.execute(new CreateUserCommand('ann'));
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
execute<T extends C, R = unknown>(command: T): Promise<R>;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=command.bus.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command.bus.d.ts","sourceRoot":"","sources":["../src/command.bus.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,KAAK,QAAQ,EAAW,MAAM,eAAe,CAAC;AAEvD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAEhD;;;;;;;;;GASG;AACH,qBAAa,UAAU,CAAC,CAAC,SAAS,QAAQ,GAAG,QAAQ;IAMvC,OAAO,CAAC,QAAQ,CAAC,QAAQ;IALrC;;;;OAIG;IACH,YAA6B,QAAQ,EAAE,WAAW,CAAC,WAAW,EAAE,QAAQ,CAAC,EAAI;IAE7E;;;;;;;;;;OAUG;IACG,OAAO,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC,GAAG,OAAO,EAAE,OAAO,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAK9D;CACF"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/* Copyright (C) 2026-present Aristotelis — see repository license. */
|
|
2
|
+
import { nearest } from './dispatch.js';
|
|
3
|
+
import { CommandHandlerNotFoundException } from './errors.js';
|
|
4
|
+
/**
|
|
5
|
+
* Sends a command to its one handler, through the handler's pipeline. `createCqrs()`
|
|
6
|
+
* builds it.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* const { commandBus } = createCqrs();
|
|
11
|
+
* const id = await commandBus.execute<CreateUserCommand, string>(new CreateUserCommand('ann'));
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
export class CommandBus {
|
|
15
|
+
handlers;
|
|
16
|
+
/**
|
|
17
|
+
* @param handlers - Maps each command class to the function that runs its handler. The
|
|
18
|
+
* bus reads it at every call, so it can be filled after the bus is created, as
|
|
19
|
+
* handlers that inject the bus require.
|
|
20
|
+
*/
|
|
21
|
+
constructor(handlers) {
|
|
22
|
+
this.handlers = handlers;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Runs the handler of the command's class, or of its nearest parent class that has
|
|
26
|
+
* one, and resolves with what the handler returns, typed as `R`.
|
|
27
|
+
*
|
|
28
|
+
* @throws CommandHandlerNotFoundException (as a rejection) when no class in the
|
|
29
|
+
* command's chain has a handler.
|
|
30
|
+
* @example
|
|
31
|
+
* ```ts
|
|
32
|
+
* await commandBus.execute(new CreateUserCommand('ann'));
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
async execute(command) {
|
|
36
|
+
const type = command.constructor;
|
|
37
|
+
const run = nearest(this.handlers, type);
|
|
38
|
+
if (!run)
|
|
39
|
+
throw new CommandHandlerNotFoundException(type.name);
|
|
40
|
+
return (await run(command));
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=command.bus.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command.bus.js","sourceRoot":"","sources":["../src/command.bus.ts"],"names":[],"mappings":"AAAA,sEAAsE;AAGtE,OAAO,EAAiB,OAAO,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,+BAA+B,EAAE,MAAM,aAAa,CAAC;AAG9D;;;;;;;;;GASG;AACH,MAAM,OAAO,UAAU;IAMQ,QAAQ;IALrC;;;;OAIG;IACH,YAA6B,QAA4C;wBAA5C,QAAQ;IAAuC,CAAC;IAE7E;;;;;;;;;;OAUG;IACH,KAAK,CAAC,OAAO,CAA2B,OAAU;QAChD,MAAM,IAAI,GAAG,OAAO,CAAC,WAAW,CAAC;QACjC,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACzC,IAAI,CAAC,GAAG;YAAE,MAAM,IAAI,+BAA+B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/D,OAAO,CAAC,MAAM,GAAG,CAAC,OAAO,CAAC,CAAM,CAAC;IACnC,CAAC;CACF"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { IPipelineBehavior, PipelineLogger } from '@cqrs-ddd/pipeline';
|
|
2
|
+
import { CommandBus } from './command.bus.js';
|
|
3
|
+
import { EventBus } from './event.bus.js';
|
|
4
|
+
import { QueryBus } from './query.bus.js';
|
|
5
|
+
import { type RegistrationOptions } from './registry.js';
|
|
6
|
+
import { UnhandledExceptionBus } from './unhandled-exception.bus.js';
|
|
7
|
+
/** Options of {@link createCqrs}. */
|
|
8
|
+
export interface CqrsOptions extends RegistrationOptions {
|
|
9
|
+
/**
|
|
10
|
+
* Instances of the behaviors that need dependencies, one per behavior class. A placed
|
|
11
|
+
* behavior without an instance is built with no arguments, `LoggingBehavior` on
|
|
12
|
+
* `logger`.
|
|
13
|
+
*/
|
|
14
|
+
readonly behaviors?: readonly IPipelineBehavior[];
|
|
15
|
+
/** The logger of `LoggingBehavior`, of failed event handlers and of the startup lines. */
|
|
16
|
+
readonly logger?: PipelineLogger;
|
|
17
|
+
/**
|
|
18
|
+
* Throw a failed event handler's error as an uncaught exception instead of publishing it
|
|
19
|
+
* on the `UnhandledExceptionBus` and logging it.
|
|
20
|
+
* @default false
|
|
21
|
+
*/
|
|
22
|
+
readonly rethrowUnhandled?: boolean;
|
|
23
|
+
}
|
|
24
|
+
/** The buses of {@link createCqrs}, and the handlers registered with them. */
|
|
25
|
+
export interface Cqrs {
|
|
26
|
+
readonly commandBus: CommandBus;
|
|
27
|
+
readonly queryBus: QueryBus;
|
|
28
|
+
readonly eventBus: EventBus;
|
|
29
|
+
readonly unhandledExceptionBus: UnhandledExceptionBus;
|
|
30
|
+
/**
|
|
31
|
+
* Registers handler instances: classes decorated with `@CommandHandler`,
|
|
32
|
+
* `@QueryHandler` or `@EventsHandler`. Each handler's pipeline is compiled here, once.
|
|
33
|
+
*
|
|
34
|
+
* @throws TypeError on an undecorated handler, or a second command or query handler.
|
|
35
|
+
* @throws PipelineConfigurationError on a behavior contract violation, in `'strict'`
|
|
36
|
+
* mode.
|
|
37
|
+
*/
|
|
38
|
+
register(...handlers: object[]): void;
|
|
39
|
+
/** Waits for the event handlers still running; call it before closing what they use. */
|
|
40
|
+
close(): Promise<void>;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Creates the command, query and event buses with no container: the application builds
|
|
44
|
+
* its handlers with `new` and registers them. Global behaviors are built here, so one
|
|
45
|
+
* whose required dependency is missing fails at once.
|
|
46
|
+
*
|
|
47
|
+
* @throws TypeError on two instances of one behavior class.
|
|
48
|
+
* @example
|
|
49
|
+
* ```ts
|
|
50
|
+
* const cqrs = createCqrs({
|
|
51
|
+
* behaviors: [new AuditBehavior(sink)],
|
|
52
|
+
* globalBehaviors: { before: [LoggingBehavior] },
|
|
53
|
+
* sources: { tenantId: tenantSource, correlationId: correlationSource },
|
|
54
|
+
* });
|
|
55
|
+
* cqrs.register(new CreateUserHandler(users, cqrs.eventBus), new GetUserHandler(users));
|
|
56
|
+
*
|
|
57
|
+
* const id = await cqrs.commandBus.execute(new CreateUserCommand('Ann'));
|
|
58
|
+
* await cqrs.close();
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
export declare function createCqrs(options?: CqrsOptions): Cqrs;
|
|
62
|
+
//# sourceMappingURL=create-cqrs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-cqrs.d.ts","sourceRoot":"","sources":["../src/create-cqrs.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAEV,iBAAiB,EACjB,cAAc,EACf,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAGL,KAAK,mBAAmB,EAEzB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAErE,qCAAqC;AACrC,MAAM,WAAW,WAAY,SAAQ,mBAAmB;IACtD;;;;OAIG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAClD,0FAA0F;IAC1F,QAAQ,CAAC,MAAM,CAAC,EAAE,cAAc,CAAC;IACjC;;;;OAIG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,CAAC;CACrC;AAED,8EAA8E;AAC9E,MAAM,WAAW,IAAI;IACnB,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAChC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,qBAAqB,EAAE,qBAAqB,CAAC;IACtD;;;;;;;OAOG;IACH,QAAQ,CAAC,GAAG,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACtC,wFAAwF;IACxF,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,UAAU,CAAC,OAAO,GAAE,WAAgB,GAAG,IAAI,CAgC1D"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/* Copyright (C) 2026-present Aristotelis — see repository license. */
|
|
2
|
+
import { CommandBus } from './command.bus.js';
|
|
3
|
+
import { commandOf, eventsOf, queryOf } from './decorators.js';
|
|
4
|
+
import { EventBus } from './event.bus.js';
|
|
5
|
+
import { QueryBus } from './query.bus.js';
|
|
6
|
+
import { behaviorResolver, Handlers, registerHandlers, } from './registry.js';
|
|
7
|
+
import { UnhandledExceptionBus } from './unhandled-exception.bus.js';
|
|
8
|
+
/**
|
|
9
|
+
* Creates the command, query and event buses with no container: the application builds
|
|
10
|
+
* its handlers with `new` and registers them. Global behaviors are built here, so one
|
|
11
|
+
* whose required dependency is missing fails at once.
|
|
12
|
+
*
|
|
13
|
+
* @throws TypeError on two instances of one behavior class.
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* const cqrs = createCqrs({
|
|
17
|
+
* behaviors: [new AuditBehavior(sink)],
|
|
18
|
+
* globalBehaviors: { before: [LoggingBehavior] },
|
|
19
|
+
* sources: { tenantId: tenantSource, correlationId: correlationSource },
|
|
20
|
+
* });
|
|
21
|
+
* cqrs.register(new CreateUserHandler(users, cqrs.eventBus), new GetUserHandler(users));
|
|
22
|
+
*
|
|
23
|
+
* const id = await cqrs.commandBus.execute(new CreateUserCommand('Ann'));
|
|
24
|
+
* await cqrs.close();
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export function createCqrs(options = {}) {
|
|
28
|
+
const logger = options.logger ?? console;
|
|
29
|
+
const behavior = behaviorResolver(options.behaviors ?? [], options.globalBehaviors, logger);
|
|
30
|
+
const handlers = new Handlers();
|
|
31
|
+
const unhandledExceptionBus = new UnhandledExceptionBus();
|
|
32
|
+
const eventBus = new EventBus(handlers.events, unhandledExceptionBus, {
|
|
33
|
+
rethrowUnhandled: options.rethrowUnhandled,
|
|
34
|
+
logger,
|
|
35
|
+
});
|
|
36
|
+
return {
|
|
37
|
+
commandBus: new CommandBus(handlers.commands),
|
|
38
|
+
queryBus: new QueryBus(handlers.queries),
|
|
39
|
+
eventBus,
|
|
40
|
+
unhandledExceptionBus,
|
|
41
|
+
register(...instances) {
|
|
42
|
+
const entries = instances.map((instance) => {
|
|
43
|
+
const type = instance.constructor;
|
|
44
|
+
if (!commandOf(type) && !queryOf(type) && !eventsOf(type)) {
|
|
45
|
+
throw new TypeError(`${type.name} has no @CommandHandler, @QueryHandler or @EventsHandler decorator.`);
|
|
46
|
+
}
|
|
47
|
+
return { type, resolve: () => instance };
|
|
48
|
+
});
|
|
49
|
+
registerHandlers(handlers, entries, behavior, options, logger);
|
|
50
|
+
},
|
|
51
|
+
close: () => eventBus.drain(),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=create-cqrs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-cqrs.js","sourceRoot":"","sources":["../src/create-cqrs.ts"],"names":[],"mappings":"AAAA,sEAAsE;AAOtE,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EACL,gBAAgB,EAChB,QAAQ,EAER,gBAAgB,GACjB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAuCrE;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,UAAU,CAAC,OAAO,GAAgB,EAAE;IAClD,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC;IACzC,MAAM,QAAQ,GAAG,gBAAgB,CAC/B,OAAO,CAAC,SAAS,IAAI,EAAE,EACvB,OAAO,CAAC,eAAe,EACvB,MAAM,CACP,CAAC;IACF,MAAM,QAAQ,GAAG,IAAI,QAAQ,EAAE,CAAC;IAChC,MAAM,qBAAqB,GAAG,IAAI,qBAAqB,EAAE,CAAC;IAC1D,MAAM,QAAQ,GAAG,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,qBAAqB,EAAE;QACpE,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;QAC1C,MAAM;KACP,CAAC,CAAC;IACH,OAAO;QACL,UAAU,EAAE,IAAI,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAC7C,QAAQ,EAAE,IAAI,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC;QACxC,QAAQ;QACR,qBAAqB;QACrB,QAAQ,CAAC,GAAG,SAAS;YACnB,MAAM,OAAO,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE;gBACzC,MAAM,IAAI,GAAG,QAAQ,CAAC,WAA0B,CAAC;gBACjD,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC1D,MAAM,IAAI,SAAS,CACjB,GAAG,IAAI,CAAC,IAAI,qEAAqE,CAClF,CAAC;gBACJ,CAAC;gBACD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC;YAC3C,CAAC,CAAC,CAAC;YACH,gBAAgB,CAAC,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;QACjE,CAAC;QACD,KAAK,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,KAAK,EAAE;KAC9B,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { AnyClass, DualClassDecorator } from '@cqrs-ddd/pipeline';
|
|
2
|
+
/** A request class: a command, a query or an event. */
|
|
3
|
+
export type RequestType = AnyClass;
|
|
4
|
+
/**
|
|
5
|
+
* Registers a class as the handler of one command class; the class implements
|
|
6
|
+
* `ICommandHandler`.
|
|
7
|
+
*
|
|
8
|
+
* @throws TypeError when `command` is not a class.
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* @CommandHandler(CreateUserCommand)
|
|
12
|
+
* class CreateUserHandler implements ICommandHandler<CreateUserCommand> {
|
|
13
|
+
* async execute(command: CreateUserCommand) {}
|
|
14
|
+
* }
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export declare function CommandHandler(command: RequestType): DualClassDecorator;
|
|
18
|
+
/**
|
|
19
|
+
* Registers a class as the handler of one query class; the class implements
|
|
20
|
+
* `IQueryHandler`.
|
|
21
|
+
*
|
|
22
|
+
* @throws TypeError when `query` is not a class.
|
|
23
|
+
* @example
|
|
24
|
+
* ```ts
|
|
25
|
+
* @QueryHandler(GetUserQuery)
|
|
26
|
+
* class GetUserHandler implements IQueryHandler<GetUserQuery> {
|
|
27
|
+
* async execute(query: GetUserQuery) {}
|
|
28
|
+
* }
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export declare function QueryHandler(query: RequestType): DualClassDecorator;
|
|
32
|
+
/**
|
|
33
|
+
* Registers a class as a handler of one or more event classes; the class implements
|
|
34
|
+
* `IEventHandler`.
|
|
35
|
+
*
|
|
36
|
+
* @throws TypeError when no event class is given, or one is not a class.
|
|
37
|
+
* @example
|
|
38
|
+
* ```ts
|
|
39
|
+
* @EventsHandler(UserCreatedEvent, UserInvitedEvent)
|
|
40
|
+
* class SendWelcomeEmail implements IEventHandler<UserCreatedEvent | UserInvitedEvent> {
|
|
41
|
+
* async handle(event: UserCreatedEvent | UserInvitedEvent) {}
|
|
42
|
+
* }
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export declare function EventsHandler(...events: RequestType[]): DualClassDecorator;
|
|
46
|
+
/**
|
|
47
|
+
* The command class a handler class handles, if it is a command handler.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```ts
|
|
51
|
+
* commandOf(CreateUserHandler); // CreateUserCommand
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
export declare function commandOf(handler: AnyClass): RequestType | undefined;
|
|
55
|
+
/**
|
|
56
|
+
* The query class a handler class handles, if it is a query handler.
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```ts
|
|
60
|
+
* queryOf(GetUserHandler); // GetUserQuery
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
export declare function queryOf(handler: AnyClass): RequestType | undefined;
|
|
64
|
+
/**
|
|
65
|
+
* The event classes a handler class handles, if it is an events handler.
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```ts
|
|
69
|
+
* eventsOf(SendWelcomeEmail); // [UserCreatedEvent]
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
72
|
+
export declare function eventsOf(handler: AnyClass): readonly RequestType[] | undefined;
|
|
73
|
+
//# sourceMappingURL=decorators.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../src/decorators.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAMvE,uDAAuD;AACvD,MAAM,MAAM,WAAW,GAAG,QAAQ,CAAC;AAkBnC;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,kBAAkB,CAGvE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,WAAW,GAAG,kBAAkB,CAGnE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAAC,GAAG,MAAM,EAAE,WAAW,EAAE,GAAG,kBAAkB,CAM1E;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,QAAQ,GAAG,WAAW,GAAG,SAAS,CAEpE;AAED;;;;;;;GAOG;AACH,wBAAgB,OAAO,CAAC,OAAO,EAAE,QAAQ,GAAG,WAAW,GAAG,SAAS,CAElE;AAED;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CACtB,OAAO,EAAE,QAAQ,GAChB,SAAS,WAAW,EAAE,GAAG,SAAS,CAEpC"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/* Copyright (C) 2026-present Aristotelis — see repository license. */
|
|
2
|
+
const COMMAND_HANDLER = Symbol.for('@cqrs-ddd/cqrs:command-handler');
|
|
3
|
+
const QUERY_HANDLER = Symbol.for('@cqrs-ddd/cqrs:query-handler');
|
|
4
|
+
const EVENTS_HANDLER = Symbol.for('@cqrs-ddd/cqrs:events-handler');
|
|
5
|
+
function define(target, key, value) {
|
|
6
|
+
Object.defineProperty(target, key, { value, configurable: true });
|
|
7
|
+
}
|
|
8
|
+
function read(target, key) {
|
|
9
|
+
return target[key];
|
|
10
|
+
}
|
|
11
|
+
function requireRequestType(value, decorator) {
|
|
12
|
+
if (typeof value !== 'function') {
|
|
13
|
+
throw new TypeError(`${decorator} takes a request class, received ${value === null ? 'null' : typeof value}.`);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Registers a class as the handler of one command class; the class implements
|
|
18
|
+
* `ICommandHandler`.
|
|
19
|
+
*
|
|
20
|
+
* @throws TypeError when `command` is not a class.
|
|
21
|
+
* @example
|
|
22
|
+
* ```ts
|
|
23
|
+
* @CommandHandler(CreateUserCommand)
|
|
24
|
+
* class CreateUserHandler implements ICommandHandler<CreateUserCommand> {
|
|
25
|
+
* async execute(command: CreateUserCommand) {}
|
|
26
|
+
* }
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export function CommandHandler(command) {
|
|
30
|
+
requireRequestType(command, '@CommandHandler');
|
|
31
|
+
return (target) => define(target, COMMAND_HANDLER, command);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Registers a class as the handler of one query class; the class implements
|
|
35
|
+
* `IQueryHandler`.
|
|
36
|
+
*
|
|
37
|
+
* @throws TypeError when `query` is not a class.
|
|
38
|
+
* @example
|
|
39
|
+
* ```ts
|
|
40
|
+
* @QueryHandler(GetUserQuery)
|
|
41
|
+
* class GetUserHandler implements IQueryHandler<GetUserQuery> {
|
|
42
|
+
* async execute(query: GetUserQuery) {}
|
|
43
|
+
* }
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export function QueryHandler(query) {
|
|
47
|
+
requireRequestType(query, '@QueryHandler');
|
|
48
|
+
return (target) => define(target, QUERY_HANDLER, query);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Registers a class as a handler of one or more event classes; the class implements
|
|
52
|
+
* `IEventHandler`.
|
|
53
|
+
*
|
|
54
|
+
* @throws TypeError when no event class is given, or one is not a class.
|
|
55
|
+
* @example
|
|
56
|
+
* ```ts
|
|
57
|
+
* @EventsHandler(UserCreatedEvent, UserInvitedEvent)
|
|
58
|
+
* class SendWelcomeEmail implements IEventHandler<UserCreatedEvent | UserInvitedEvent> {
|
|
59
|
+
* async handle(event: UserCreatedEvent | UserInvitedEvent) {}
|
|
60
|
+
* }
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
export function EventsHandler(...events) {
|
|
64
|
+
if (events.length === 0) {
|
|
65
|
+
throw new TypeError('@EventsHandler takes at least one event class.');
|
|
66
|
+
}
|
|
67
|
+
for (const event of events)
|
|
68
|
+
requireRequestType(event, '@EventsHandler');
|
|
69
|
+
return (target) => define(target, EVENTS_HANDLER, events);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* The command class a handler class handles, if it is a command handler.
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```ts
|
|
76
|
+
* commandOf(CreateUserHandler); // CreateUserCommand
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
export function commandOf(handler) {
|
|
80
|
+
return read(handler, COMMAND_HANDLER);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* The query class a handler class handles, if it is a query handler.
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* ```ts
|
|
87
|
+
* queryOf(GetUserHandler); // GetUserQuery
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
90
|
+
export function queryOf(handler) {
|
|
91
|
+
return read(handler, QUERY_HANDLER);
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* The event classes a handler class handles, if it is an events handler.
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```ts
|
|
98
|
+
* eventsOf(SendWelcomeEmail); // [UserCreatedEvent]
|
|
99
|
+
* ```
|
|
100
|
+
*/
|
|
101
|
+
export function eventsOf(handler) {
|
|
102
|
+
return read(handler, EVENTS_HANDLER);
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=decorators.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decorators.js","sourceRoot":"","sources":["../src/decorators.ts"],"names":[],"mappings":"AAAA,sEAAsE;AAItE,MAAM,eAAe,GAAG,MAAM,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC;AACrE,MAAM,aAAa,GAAG,MAAM,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;AACjE,MAAM,cAAc,GAAG,MAAM,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC;AAKnE,SAAS,MAAM,CAAC,MAAgB,EAAE,GAAW,EAAE,KAAc;IAC3D,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC;AACpE,CAAC;AAED,SAAS,IAAI,CAAI,MAAgB,EAAE,GAAW;IAC5C,OAAQ,MAAmD,CAAC,GAAG,CAAC,CAAC;AACnE,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAc,EAAE,SAAiB;IAC3D,IAAI,OAAO,KAAK,KAAK,UAAU,EAAE,CAAC;QAChC,MAAM,IAAI,SAAS,CACjB,GAAG,SAAS,oCAAoC,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,KAAK,GAAG,CAC1F,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,cAAc,CAAC,OAAoB;IACjD,kBAAkB,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAAC;IAC/C,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,EAAE,OAAO,CAAC,CAAC;AAC9D,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,YAAY,CAAC,KAAkB;IAC7C,kBAAkB,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC;IAC3C,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,CAAC,CAAC;AAC1D,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,aAAa,CAAC,GAAG,MAAqB;IACpD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,SAAS,CAAC,gDAAgD,CAAC,CAAC;IACxE,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,MAAM;QAAE,kBAAkB,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAC;IACxE,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,cAAc,EAAE,MAAM,CAAC,CAAC;AAC5D,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,SAAS,CAAC,OAAiB;IACzC,OAAO,IAAI,CAAc,OAAO,EAAE,eAAe,CAAC,CAAC;AACrD,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,OAAO,CAAC,OAAiB;IACvC,OAAO,IAAI,CAAc,OAAO,EAAE,aAAa,CAAC,CAAC;AACnD,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,QAAQ,CACtB,OAAiB;IAEjB,OAAO,IAAI,CAAgB,OAAO,EAAE,cAAc,CAAC,CAAC;AACtD,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type Constructor, type ContextSources, type DeclaredKind, type GlobalBehaviorsOptions, type IPipelineBehavior, type PipelineBehaviorDiagnostic } from '@cqrs-ddd/pipeline';
|
|
2
|
+
import type { RequestType } from './decorators.js';
|
|
3
|
+
/** Runs one request through its handler and the handler's pipeline. */
|
|
4
|
+
export type Dispatch = (request: unknown) => Promise<unknown>;
|
|
5
|
+
/** What every handler's pipeline shares. */
|
|
6
|
+
export interface PipelineSettings {
|
|
7
|
+
readonly globalBehaviors?: GlobalBehaviorsOptions | GlobalBehaviorsOptions[];
|
|
8
|
+
readonly sources?: ContextSources;
|
|
9
|
+
/** Returns the one instance of a behavior class. */
|
|
10
|
+
readonly behavior: (type: Constructor<IPipelineBehavior>) => IPipelineBehavior;
|
|
11
|
+
/** Receives contract violations; absent, contracts are not validated. */
|
|
12
|
+
readonly diagnostics?: PipelineBehaviorDiagnostic[];
|
|
13
|
+
/** Receives a line per handler that runs behaviors, naming them in order. */
|
|
14
|
+
readonly log?: (message: string) => void;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Compiles a handler class's pipeline once, from its decorators and the global behaviors,
|
|
18
|
+
* and returns the function the bus calls per request; `resolve` gives the instance that
|
|
19
|
+
* handles each request. The handler is named by its class.
|
|
20
|
+
*
|
|
21
|
+
* @throws InvalidCommandHandlerException, InvalidQueryHandlerException or
|
|
22
|
+
* InvalidEventsHandlerException when the handler lacks `execute`, or `handle` for an
|
|
23
|
+
* event.
|
|
24
|
+
* @throws Error when the handler both declares and skips one behavior.
|
|
25
|
+
*/
|
|
26
|
+
export declare function toDispatch(handlerType: Constructor, resolve: () => object, kind: DeclaredKind, settings: PipelineSettings): Dispatch;
|
|
27
|
+
/**
|
|
28
|
+
* The entry of a request class or, failing that, of its nearest parent class.
|
|
29
|
+
*/
|
|
30
|
+
export declare function nearest<T>(entries: ReadonlyMap<RequestType, T>, type: object): T | undefined;
|
|
31
|
+
//# sourceMappingURL=dispatch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../src/dispatch.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,cAAc,EAGnB,KAAK,YAAY,EACjB,KAAK,sBAAsB,EAC3B,KAAK,iBAAiB,EACtB,KAAK,0BAA0B,EAGhC,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAOnD,uEAAuE;AACvE,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAE9D,4CAA4C;AAC5C,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,eAAe,CAAC,EAAE,sBAAsB,GAAG,sBAAsB,EAAE,CAAC;IAC7E,QAAQ,CAAC,OAAO,CAAC,EAAE,cAAc,CAAC;IAClC,oDAAoD;IACpD,QAAQ,CAAC,QAAQ,EAAE,CACjB,IAAI,EAAE,WAAW,CAAC,iBAAiB,CAAC,KACjC,iBAAiB,CAAC;IACvB,yEAAyE;IACzE,QAAQ,CAAC,WAAW,CAAC,EAAE,0BAA0B,EAAE,CAAC;IACpD,6EAA6E;IAC7E,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAC1C;AAQD;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CACxB,WAAW,EAAE,WAAW,EACxB,OAAO,EAAE,MAAM,MAAM,EACrB,IAAI,EAAE,YAAY,EAClB,QAAQ,EAAE,gBAAgB,GACzB,QAAQ,CA4CV;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,CAAC,EACvB,OAAO,EAAE,WAAW,CAAC,WAAW,EAAE,CAAC,CAAC,EACpC,IAAI,EAAE,MAAM,GACX,CAAC,GAAG,SAAS,CAUf"}
|
package/dist/dispatch.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/* Copyright (C) 2026-present Aristotelis — see repository license. */
|
|
2
|
+
import { compilePipelinePlan, createPipelineRunner, pipelineOf, validateBehaviorContracts, } from '@cqrs-ddd/pipeline';
|
|
3
|
+
import { InvalidCommandHandlerException, InvalidEventsHandlerException, InvalidQueryHandlerException, } from './errors.js';
|
|
4
|
+
const INVALID = {
|
|
5
|
+
command: InvalidCommandHandlerException,
|
|
6
|
+
query: InvalidQueryHandlerException,
|
|
7
|
+
event: InvalidEventsHandlerException,
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Compiles a handler class's pipeline once, from its decorators and the global behaviors,
|
|
11
|
+
* and returns the function the bus calls per request; `resolve` gives the instance that
|
|
12
|
+
* handles each request. The handler is named by its class.
|
|
13
|
+
*
|
|
14
|
+
* @throws InvalidCommandHandlerException, InvalidQueryHandlerException or
|
|
15
|
+
* InvalidEventsHandlerException when the handler lacks `execute`, or `handle` for an
|
|
16
|
+
* event.
|
|
17
|
+
* @throws Error when the handler both declares and skips one behavior.
|
|
18
|
+
*/
|
|
19
|
+
export function toDispatch(handlerType, resolve, kind, settings) {
|
|
20
|
+
const name = kind === 'event' ? 'handle' : 'execute';
|
|
21
|
+
const method = Reflect.get(handlerType.prototype, name);
|
|
22
|
+
if (typeof method !== 'function')
|
|
23
|
+
throw new INVALID[kind]();
|
|
24
|
+
const handlerName = handlerType.name;
|
|
25
|
+
const declared = pipelineOf(handlerType);
|
|
26
|
+
const plan = compilePipelinePlan({
|
|
27
|
+
handlerName,
|
|
28
|
+
requestKind: kind,
|
|
29
|
+
handlerBehaviorTypes: declared.types,
|
|
30
|
+
handlerOptions: declared.options,
|
|
31
|
+
skippedBehaviorTypes: declared.skipped,
|
|
32
|
+
globalBehaviors: settings.globalBehaviors,
|
|
33
|
+
});
|
|
34
|
+
const behaviors = plan.behaviorTypes.map(settings.behavior);
|
|
35
|
+
if (plan.hasPipeline) {
|
|
36
|
+
settings.log?.(`Wrapping ${handlerName}.${name}() [${kind}] with pipeline: [${plan.behaviorTypes.map((type) => type.name).join(' → ')}]`);
|
|
37
|
+
}
|
|
38
|
+
if (settings.diagnostics) {
|
|
39
|
+
validateBehaviorContracts({
|
|
40
|
+
...plan,
|
|
41
|
+
handlerType,
|
|
42
|
+
handlerName,
|
|
43
|
+
requestKind: kind,
|
|
44
|
+
resolvedBehaviors: new Map(behaviors.map((b, i) => [i, b])),
|
|
45
|
+
diagnostics: settings.diagnostics,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
const run = createPipelineRunner(method, {
|
|
49
|
+
handlerType,
|
|
50
|
+
handlerName,
|
|
51
|
+
requestKind: kind,
|
|
52
|
+
behaviorOptions: plan.mergedOptions.size > 0 ? plan.mergedOptions : undefined,
|
|
53
|
+
}, behaviors, plan.hasPipeline, settings.sources);
|
|
54
|
+
return (request) => run(resolve(), request);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* The entry of a request class or, failing that, of its nearest parent class.
|
|
58
|
+
*/
|
|
59
|
+
export function nearest(entries, type) {
|
|
60
|
+
for (let current = type; current !== Function.prototype; current = Object.getPrototypeOf(current)) {
|
|
61
|
+
const entry = entries.get(current);
|
|
62
|
+
if (entry)
|
|
63
|
+
return entry;
|
|
64
|
+
}
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=dispatch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispatch.js","sourceRoot":"","sources":["../src/dispatch.ts"],"names":[],"mappings":"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"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/** Thrown by `CommandBus.execute()` when no handler is registered for the command's class. */
|
|
2
|
+
export declare class CommandHandlerNotFoundException extends Error {
|
|
3
|
+
readonly name = "CommandHandlerNotFoundException";
|
|
4
|
+
constructor(commandName: string);
|
|
5
|
+
}
|
|
6
|
+
/** Thrown by `QueryBus.execute()` when no handler is registered for the query's class. */
|
|
7
|
+
export declare class QueryHandlerNotFoundException extends Error {
|
|
8
|
+
readonly name = "QueryHandlerNotFoundException";
|
|
9
|
+
constructor(queryName: string);
|
|
10
|
+
}
|
|
11
|
+
/** Thrown at startup by a command handler without an `execute` method. */
|
|
12
|
+
export declare class InvalidCommandHandlerException extends Error {
|
|
13
|
+
readonly name = "InvalidCommandHandlerException";
|
|
14
|
+
constructor();
|
|
15
|
+
}
|
|
16
|
+
/** Thrown at startup by a query handler without an `execute` method. */
|
|
17
|
+
export declare class InvalidQueryHandlerException extends Error {
|
|
18
|
+
readonly name = "InvalidQueryHandlerException";
|
|
19
|
+
constructor();
|
|
20
|
+
}
|
|
21
|
+
/** Thrown at startup by an events handler without a `handle` method. */
|
|
22
|
+
export declare class InvalidEventsHandlerException extends Error {
|
|
23
|
+
readonly name = "InvalidEventsHandlerException";
|
|
24
|
+
constructor();
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAEA,8FAA8F;AAC9F,qBAAa,+BAAgC,SAAQ,KAAK;IACxD,SAAkB,IAAI,qCAAqC;IAE3D,YAAY,WAAW,EAAE,MAAM,EAE9B;CACF;AAED,0FAA0F;AAC1F,qBAAa,6BAA8B,SAAQ,KAAK;IACtD,SAAkB,IAAI,mCAAmC;IAEzD,YAAY,SAAS,EAAE,MAAM,EAE5B;CACF;AAED,0EAA0E;AAC1E,qBAAa,8BAA+B,SAAQ,KAAK;IACvD,SAAkB,IAAI,oCAAoC;IAE1D,cAIC;CACF;AAED,wEAAwE;AACxE,qBAAa,4BAA6B,SAAQ,KAAK;IACrD,SAAkB,IAAI,kCAAkC;IAExD,cAIC;CACF;AAED,wEAAwE;AACxE,qBAAa,6BAA8B,SAAQ,KAAK;IACtD,SAAkB,IAAI,mCAAmC;IAEzD,cAIC;CACF"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/* Copyright (C) 2026-present Aristotelis — see repository license. */
|
|
2
|
+
/** Thrown by `CommandBus.execute()` when no handler is registered for the command's class. */
|
|
3
|
+
export class CommandHandlerNotFoundException extends Error {
|
|
4
|
+
name = 'CommandHandlerNotFoundException';
|
|
5
|
+
constructor(commandName) {
|
|
6
|
+
super(`No handler found for the command: "${commandName}".`);
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
/** Thrown by `QueryBus.execute()` when no handler is registered for the query's class. */
|
|
10
|
+
export class QueryHandlerNotFoundException extends Error {
|
|
11
|
+
name = 'QueryHandlerNotFoundException';
|
|
12
|
+
constructor(queryName) {
|
|
13
|
+
super(`No handler found for the query: "${queryName}"`);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
/** Thrown at startup by a command handler without an `execute` method. */
|
|
17
|
+
export class InvalidCommandHandlerException extends Error {
|
|
18
|
+
name = 'InvalidCommandHandlerException';
|
|
19
|
+
constructor() {
|
|
20
|
+
super(`An invalid command handler has been provided. Please ensure that the provided handler is a class annotated with @CommandHandler and contains an 'execute' method.`);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/** Thrown at startup by a query handler without an `execute` method. */
|
|
24
|
+
export class InvalidQueryHandlerException extends Error {
|
|
25
|
+
name = 'InvalidQueryHandlerException';
|
|
26
|
+
constructor() {
|
|
27
|
+
super(`An invalid query handler has been provided. Please ensure that the provided handler is a class annotated with @QueryHandler and contains an 'execute' method.`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/** Thrown at startup by an events handler without a `handle` method. */
|
|
31
|
+
export class InvalidEventsHandlerException extends Error {
|
|
32
|
+
name = 'InvalidEventsHandlerException';
|
|
33
|
+
constructor() {
|
|
34
|
+
super(`An invalid events handler has been provided. Please ensure that the provided handler is a class annotated with @EventsHandler and contains a 'handle' method.`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,sEAAsE;AAEtE,8FAA8F;AAC9F,MAAM,OAAO,+BAAgC,SAAQ,KAAK;IACtC,IAAI,GAAG,iCAAiC,CAAC;IAE3D,YAAY,WAAmB;QAC7B,KAAK,CAAC,sCAAsC,WAAW,IAAI,CAAC,CAAC;IAC/D,CAAC;CACF;AAED,0FAA0F;AAC1F,MAAM,OAAO,6BAA8B,SAAQ,KAAK;IACpC,IAAI,GAAG,+BAA+B,CAAC;IAEzD,YAAY,SAAiB;QAC3B,KAAK,CAAC,oCAAoC,SAAS,GAAG,CAAC,CAAC;IAC1D,CAAC;CACF;AAED,0EAA0E;AAC1E,MAAM,OAAO,8BAA+B,SAAQ,KAAK;IACrC,IAAI,GAAG,gCAAgC,CAAC;IAE1D;QACE,KAAK,CACH,mKAAmK,CACpK,CAAC;IACJ,CAAC;CACF;AAED,wEAAwE;AACxE,MAAM,OAAO,4BAA6B,SAAQ,KAAK;IACnC,IAAI,GAAG,8BAA8B,CAAC;IAExD;QACE,KAAK,CACH,+JAA+J,CAChK,CAAC;IACJ,CAAC;CACF;AAED,wEAAwE;AACxE,MAAM,OAAO,6BAA8B,SAAQ,KAAK;IACpC,IAAI,GAAG,+BAA+B,CAAC;IAEzD;QACE,KAAK,CACH,+JAA+J,CAChK,CAAC;IACJ,CAAC;CACF"}
|