@ddd-ts-kit/kernel 0.1.1 → 0.3.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/README.md +156 -36
- package/dist/declarations/decorators/adapter.d.ts +5 -4
- package/dist/declarations/decorators/adapter.d.ts.map +1 -1
- package/dist/declarations/decorators/adapter.js.map +1 -1
- package/dist/declarations/decorators/command-handler.d.ts +7 -5
- package/dist/declarations/decorators/command-handler.d.ts.map +1 -1
- package/dist/declarations/decorators/command-handler.js +4 -3
- package/dist/declarations/decorators/command-handler.js.map +1 -1
- package/dist/declarations/decorators/declaring.d.ts +2 -2
- package/dist/declarations/decorators/declaring.d.ts.map +1 -1
- package/dist/declarations/decorators/declaring.js +5 -2
- package/dist/declarations/decorators/declaring.js.map +1 -1
- package/dist/declarations/decorators/domain-event-handler.d.ts +5 -4
- package/dist/declarations/decorators/domain-event-handler.d.ts.map +1 -1
- package/dist/declarations/decorators/domain-event-handler.js +3 -3
- package/dist/declarations/decorators/domain-event-handler.js.map +1 -1
- package/dist/declarations/decorators/gateway.d.ts +5 -4
- package/dist/declarations/decorators/gateway.d.ts.map +1 -1
- package/dist/declarations/decorators/gateway.js.map +1 -1
- package/dist/declarations/decorators/handling.d.ts +2 -2
- package/dist/declarations/decorators/handling.d.ts.map +1 -1
- package/dist/declarations/decorators/handling.js +1 -1
- package/dist/declarations/decorators/handling.js.map +1 -1
- package/dist/declarations/decorators/integration-event-handler.d.ts +4 -3
- package/dist/declarations/decorators/integration-event-handler.d.ts.map +1 -1
- package/dist/declarations/decorators/integration-event-handler.js +2 -2
- package/dist/declarations/decorators/integration-event-handler.js.map +1 -1
- package/dist/declarations/decorators/policy.d.ts +3 -2
- package/dist/declarations/decorators/policy.d.ts.map +1 -1
- package/dist/declarations/decorators/policy.js +1 -1
- package/dist/declarations/decorators/policy.js.map +1 -1
- package/dist/declarations/decorators/projection.d.ts +4 -3
- package/dist/declarations/decorators/projection.d.ts.map +1 -1
- package/dist/declarations/decorators/projection.js +2 -2
- package/dist/declarations/decorators/projection.js.map +1 -1
- package/dist/declarations/decorators/query-handler.d.ts +4 -3
- package/dist/declarations/decorators/query-handler.d.ts.map +1 -1
- package/dist/declarations/decorators/query-handler.js +1 -1
- package/dist/declarations/decorators/query-handler.js.map +1 -1
- package/dist/declarations/decorators/repository.d.ts +5 -5
- package/dist/declarations/decorators/repository.d.ts.map +1 -1
- package/dist/declarations/decorators/repository.js.map +1 -1
- package/dist/declarations/decorators/scheduled.d.ts +4 -3
- package/dist/declarations/decorators/scheduled.d.ts.map +1 -1
- package/dist/declarations/decorators/scheduled.js +2 -2
- package/dist/declarations/decorators/scheduled.js.map +1 -1
- package/dist/declarations/dependencies/class-declarator.d.ts +2 -1
- package/dist/declarations/dependencies/class-declarator.d.ts.map +1 -1
- package/dist/declarations/dependencies/declared-dependencies.d.ts +5 -0
- package/dist/declarations/dependencies/declared-dependencies.d.ts.map +1 -0
- package/dist/declarations/dependencies/declared-dependencies.js +2 -0
- package/dist/declarations/dependencies/declared-dependencies.js.map +1 -0
- package/dist/declarations/dependencies/dependencies-from-signature.d.ts +7 -0
- package/dist/declarations/dependencies/dependencies-from-signature.d.ts.map +1 -0
- package/dist/declarations/dependencies/dependencies-from-signature.js +2 -0
- package/dist/declarations/dependencies/dependencies-from-signature.js.map +1 -0
- package/dist/declarations/dependencies/matching-dependencies.d.ts +5 -2
- package/dist/declarations/dependencies/matching-dependencies.d.ts.map +1 -1
- package/dist/declarations/injection/injected-dependencies.d.ts +4 -0
- package/dist/declarations/injection/injected-dependencies.d.ts.map +1 -0
- package/dist/declarations/injection/injected-dependencies.js +9 -0
- package/dist/declarations/injection/injected-dependencies.js.map +1 -0
- package/dist/declarations/injection/injected-registry.d.ts +4 -0
- package/dist/declarations/injection/injected-registry.d.ts.map +1 -0
- package/dist/declarations/injection/injected-registry.js +19 -0
- package/dist/declarations/injection/injected-registry.js.map +1 -0
- package/dist/declarations/injection/injected.d.ts +11 -0
- package/dist/declarations/injection/injected.d.ts.map +1 -0
- package/dist/declarations/injection/injected.js +24 -0
- package/dist/declarations/injection/injected.js.map +1 -0
- package/dist/declarations/model/domain-event-handler-declaration.d.ts +2 -1
- package/dist/declarations/model/domain-event-handler-declaration.d.ts.map +1 -1
- package/dist/declarations/model/handler-declaration.d.ts +2 -1
- package/dist/declarations/model/handler-declaration.d.ts.map +1 -1
- package/dist/declarations/model/integration-event-handler-declaration.d.ts +2 -1
- package/dist/declarations/model/integration-event-handler-declaration.d.ts.map +1 -1
- package/dist/declarations/model/job-declaration.d.ts +2 -1
- package/dist/declarations/model/job-declaration.d.ts.map +1 -1
- package/dist/declarations/model/policy-declaration.d.ts +2 -1
- package/dist/declarations/model/policy-declaration.d.ts.map +1 -1
- package/dist/declarations/model/port-declaration.d.ts +2 -1
- package/dist/declarations/model/port-declaration.d.ts.map +1 -1
- package/dist/declarations/model/projection-declaration.d.ts +2 -1
- package/dist/declarations/model/projection-declaration.d.ts.map +1 -1
- package/dist/declarations/token/token.d.ts +2 -2
- package/dist/declarations.d.ts +4 -0
- package/dist/declarations.d.ts.map +1 -1
- package/dist/declarations.js +2 -0
- package/dist/declarations.js.map +1 -1
- package/dist/domain/errors/code-of.d.ts +4 -0
- package/dist/domain/errors/code-of.d.ts.map +1 -0
- package/dist/domain/errors/code-of.js +2 -0
- package/dist/domain/errors/code-of.js.map +1 -0
- package/dist/domain/errors/concept-error.d.ts +43 -0
- package/dist/domain/errors/concept-error.d.ts.map +1 -0
- package/dist/domain/errors/concept-error.js +54 -0
- package/dist/domain/errors/concept-error.js.map +1 -0
- package/dist/domain/errors/domain-error-json.d.ts +10 -0
- package/dist/domain/errors/domain-error-json.d.ts.map +1 -0
- package/dist/domain/errors/domain-error-json.js +2 -0
- package/dist/domain/errors/domain-error-json.js.map +1 -0
- package/dist/domain/errors/domain-error.d.ts +3 -0
- package/dist/domain/errors/domain-error.d.ts.map +1 -1
- package/dist/domain/errors/domain-error.js +4 -0
- package/dist/domain/errors/domain-error.js.map +1 -1
- package/dist/domain/errors/is-refusal.d.ts +9 -0
- package/dist/domain/errors/is-refusal.d.ts.map +1 -0
- package/dist/domain/errors/is-refusal.js +9 -0
- package/dist/domain/errors/is-refusal.js.map +1 -0
- package/dist/domain/errors/refusal-facts.d.ts +5 -0
- package/dist/domain/errors/refusal-facts.d.ts.map +1 -0
- package/dist/domain/errors/refusal-facts.js +2 -0
- package/dist/domain/errors/refusal-facts.js.map +1 -0
- package/dist/domain/errors/refusal-of.d.ts +15 -0
- package/dist/domain/errors/refusal-of.d.ts.map +1 -0
- package/dist/domain/errors/refusal-of.js +2 -0
- package/dist/domain/errors/refusal-of.js.map +1 -0
- package/dist/domain/errors/refusal.d.ts +7 -0
- package/dist/domain/errors/refusal.d.ts.map +1 -0
- package/dist/domain/errors/refusal.js +2 -0
- package/dist/domain/errors/refusal.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ npm i @ddd-ts-kit/kernel
|
|
|
12
12
|
|
|
13
13
|
| Area | Exports |
|
|
14
14
|
|---|---|
|
|
15
|
-
| Domain | `Entity`, `AggregateRoot` (version, recorded events), `ValueObject`, `DomainEvent`, `DomainError` with a stable `code` (`InvariantViolation`, `NotFoundError`, `ConflictError`, `ConcurrencyError
|
|
15
|
+
| Domain | `Entity`, `AggregateRoot` (version, recorded events), `ValueObject`, `DomainEvent`, `DomainError` with a stable `code`, `ConceptError` (the errors of one concept, each built by a static factory: see "Domain errors"), `isRefusal`, `CodeOf`, `RefusalOf`, `Refusal`, `RefusalFacts`, the generic `InvariantViolation`, `NotFoundError`, `ConflictError`, `ConcurrencyError`, `Result` with `ok`, `err`, `unwrap` |
|
|
16
16
|
| Ports | `Clock`, `IdGenerator`, `UnitOfWork`, `Repository` (abstract classes: each one is its own injection token), `UseCase`, `DependencyKind` (the roles a binding declares, read by di, tracing and aspects: `repository`, `gateway`, `external`, `use-case`, `publisher`, `consumer`, `domain-event-handler`, `job`) |
|
|
17
17
|
| Buses | `Command`, `Query`, `CommandBus`, `QueryBus`, `BusMiddleware`, the in-process `InMemoryCommandBus` and `InMemoryQueryBus` (`register(type, handler, { context })` names the bounded context in `MessageInfo`), `unitOfWorkMiddleware` |
|
|
18
18
|
| Events | `IntegrationEvent`, `IntegrationEventPublisher`, `IntegrationEventSubscriber`, `EventBus` (both at once), `EventSubscribers` (the subscriber of each bounded context), `ProcessedEventStore`, `idempotent`, `InMemoryEventBus`, `DomainEventDispatcher`, `IntegrationEventCallback` and `DomainEventCallback` (the functions a subscriber and a dispatcher are given), `executionContextOfEvent`, `inEventScope`, `scopedPublisher`, `EventDelivery` (what a provider says of one delivery: attempt, last attempt, transport, source, consumer), `messagingSystemOf` |
|
|
@@ -24,10 +24,97 @@ npm i @ddd-ts-kit/kernel
|
|
|
24
24
|
| Persistence helpers | `optimisticUpdate`, `schemaNameOf`, `stampCreation`, `stampUpdate`, `tenantScopeOf`, `encodeCursor`, `decodeCursor` |
|
|
25
25
|
| Error reporting | `ErrorReporter`, `ErrorReport`, `errorReportOf`, `reportOnce`, `isUnexpectedError`, `errorReportingMiddleware`, `DeadLetterReports`, `reportProcessFailures`, `NoopErrorReporter` |
|
|
26
26
|
| Doubles | `FixedClock`, `SequentialIdGenerator`, `InMemoryUnitOfWork`, `FixedActorContext`, `FixedExecutionScope`, `InMemoryLogger`, `InMemoryMetrics`, `InMemoryErrorReporter`, `InMemoryCache`, `InMemoryLock`, `InMemoryRateLimiter` |
|
|
27
|
-
| Declarations (`@ddd-ts-kit/kernel/declarations`) | `Requires`, `Public`, `CommandHandler`, `QueryHandler`, `IntegrationEventHandler`, `DomainEventHandler`, `Scheduled`, `Projection`, `On`, `Repository`, `Gateway`, `Adapter`, `Policy`, `declarationOf`, `listDeclarations`, `Token`, `describeToken`, `tokenIdentity`, `portDefect` |
|
|
27
|
+
| Declarations (`@ddd-ts-kit/kernel/declarations`) | `Requires`, `Public`, `CommandHandler`, `QueryHandler`, `IntegrationEventHandler`, `DomainEventHandler`, `Scheduled`, `Projection`, `On`, `Repository`, `Gateway`, `Adapter`, `Policy`, `injected`, `injectedDependencies`, `declarationOf`, `listDeclarations`, `Token`, `describeToken`, `tokenIdentity`, `portDefect` |
|
|
28
28
|
|
|
29
29
|
The rules these blocks serve are in `docs/ARCHITECTURE.md`.
|
|
30
30
|
|
|
31
|
+
## Domain errors
|
|
32
|
+
|
|
33
|
+
A business refusal is a `DomainError`: an answer the code planned for, known everywhere by its
|
|
34
|
+
`code`. A context has one error class per concept of its language, and each refusal is a static
|
|
35
|
+
factory of that class, named in the words of the business:
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
import { ConceptError } from '@ddd-ts-kit/kernel';
|
|
39
|
+
|
|
40
|
+
export class AppointmentError extends ConceptError {
|
|
41
|
+
static slotTaken(calendarId: string, startsAt: Date) {
|
|
42
|
+
return AppointmentError.refusal(
|
|
43
|
+
'SLOT_TAKEN',
|
|
44
|
+
`The slot starting at ${startsAt.toISOString()} on calendar ${calendarId} is already held.`,
|
|
45
|
+
{ calendarId, startsAt },
|
|
46
|
+
).exposing('startsAt');
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
static notFound(appointmentId: string) {
|
|
50
|
+
return AppointmentError.refusal('APPOINTMENT_NOT_FOUND', `Appointment ${appointmentId} does not exist.`, {
|
|
51
|
+
appointmentId,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
throw AppointmentError.slotTaken(calendar.id, slot.startsAt);
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
| Member | What it does |
|
|
60
|
+
|---|---|
|
|
61
|
+
| `protected static refusal(code, message, facts?)` | builds the refusal of a factory: an instance of the class it is called on, typed with that code and those facts. The constructor is protected and a subclass declares none, so outside its class a refusal exists only through a factory |
|
|
62
|
+
| `protected exposing(...names)` | called on the refusal by its factory: these facts may leave the process. None does by default |
|
|
63
|
+
| `protected causedBy(cause)` | called by its factory: the error this refusal translates, as `cause` |
|
|
64
|
+
| `code`, `message`, `name`, `cause` | as on any `DomainError`; `name` is the class, `code` the identity of the refusal |
|
|
65
|
+
| `facts` | every fact the factory was given, as plain data (`RefusalFacts`: text, numbers, booleans, dates, `null`, lists of them), for the code that catches the error and for the tests |
|
|
66
|
+
| `exposedFacts` | the facts a client may read: what `@ddd-ts-kit/http` writes under `facts` in the problem document |
|
|
67
|
+
| `toJSON()` | `{ name, code, message }`, plus `facts` when some are exposed: never the stack, the cause or a private fact |
|
|
68
|
+
| `static is(error, code?)` | narrows what was caught to a refusal of this class, of this code when one is given |
|
|
69
|
+
|
|
70
|
+
The codes of a class are a closed vocabulary the compiler derives from its factories, so a
|
|
71
|
+
`switch` is exhaustive and each case knows its facts:
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
import { isRefusal, type CodeOf } from '@ddd-ts-kit/kernel';
|
|
75
|
+
|
|
76
|
+
type AppointmentErrorCode = CodeOf<typeof AppointmentError>; // 'SLOT_TAKEN' | 'APPOINTMENT_NOT_FOUND'
|
|
77
|
+
|
|
78
|
+
if (AppointmentError.is(error)) {
|
|
79
|
+
switch (error.code) {
|
|
80
|
+
case 'SLOT_TAKEN':
|
|
81
|
+
return retryAfter(error.facts.startsAt); // a Date
|
|
82
|
+
case 'APPOINTMENT_NOT_FOUND':
|
|
83
|
+
return forget(error.facts.appointmentId);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (AppointmentError.is(error, 'SLOT_TAKEN')) {
|
|
88
|
+
error.facts.calendarId; // a string
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
isRefusal(error, 'SLOT_TAKEN'); // whatever the class: the code is what everything downstream keys on
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
`error instanceof AppointmentError && error.code === 'SLOT_TAKEN'` works too, without the facts
|
|
95
|
+
of that code. A factory lets its return type be inferred: an annotation `: AppointmentError`
|
|
96
|
+
would hide its code from `CodeOf`.
|
|
97
|
+
|
|
98
|
+
**Facts are private.** A message is written for a human and answered to the client as `detail`;
|
|
99
|
+
the facts are data, and stay in the process unless the factory names the ones that may leave.
|
|
100
|
+
Never expose what identifies a person. The audit trail and the spans record the code alone.
|
|
101
|
+
|
|
102
|
+
**One class per error** is the form of 0.1 and 0.2, and keeps working: `DomainError` is still
|
|
103
|
+
abstract over `code`, its constructor still public, and `InvariantViolation`, `NotFoundError`,
|
|
104
|
+
`ConflictError` and `ConcurrencyError`, each one refusal under a fixed code, are still built
|
|
105
|
+
with `new`.
|
|
106
|
+
|
|
107
|
+
```ts
|
|
108
|
+
export class SlotTakenError extends DomainError {
|
|
109
|
+
readonly code = 'SLOT_TAKEN';
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
A project says which form it writes with `"stack.refusals"` in `ddd-ts-kit.config.json`
|
|
114
|
+
(`factories`, what `init` writes, or `classes`, what a config without the key means); the
|
|
115
|
+
`errors/*` rules hold the first, and `ddd-ts-kit error-factories` moves a project from the
|
|
116
|
+
second. Both forms can live in one project.
|
|
117
|
+
|
|
31
118
|
## Domain events and the unit of work
|
|
32
119
|
|
|
33
120
|
An effect of a domain event exists only if the state change that recorded it is committed.
|
|
@@ -72,7 +159,7 @@ a repository adapter never call it. An aggregate is recognised by what it does (
|
|
|
72
159
|
| `after-commit` | `dispatcher.on(name, callback, { phase: 'after-commit' })` | once the transaction has committed, never when it rolled back, in dispatch order, awaited before the command answers | never fails the command: reported, and the other handlers still run |
|
|
73
160
|
|
|
74
161
|
With declarations the phase is an option of the decorator:
|
|
75
|
-
`@DomainEventHandler(OrderPaid, { name: 'ordering.order.paid', phase: 'after-commit' }
|
|
162
|
+
`@DomainEventHandler(OrderPaid, { name: 'ordering.order.paid', phase: 'after-commit' })`.
|
|
76
163
|
|
|
77
164
|
The `after-commit` phase is at most once: a crash between the commit and the run loses it. What
|
|
78
165
|
must not be lost goes through the outbox as an integration event. A `before-commit` handler
|
|
@@ -131,7 +218,7 @@ declarations into bindings is the job of `@ddd-ts-kit/di` (`contextModule`,
|
|
|
131
218
|
```ts
|
|
132
219
|
// contexts/ordering/domain/repositories/order.repository.ts
|
|
133
220
|
import { Repository } from '@ddd-ts-kit/kernel';
|
|
134
|
-
import type { Order } from '@/contexts/ordering/domain/aggregates/order.aggregate
|
|
221
|
+
import type { Order } from '@/contexts/ordering/domain/aggregates/order.aggregate';
|
|
135
222
|
|
|
136
223
|
export abstract class OrderRepository extends Repository<Order> {
|
|
137
224
|
abstract findOpenOf(customerId: string): Promise<readonly Order[]>;
|
|
@@ -142,10 +229,10 @@ export abstract class OrderRepository extends Repository<Order> {
|
|
|
142
229
|
// contexts/ordering/application/commands/place-order/place-order.handler.ts
|
|
143
230
|
import { Clock } from '@ddd-ts-kit/kernel';
|
|
144
231
|
import { CommandHandler } from '@ddd-ts-kit/kernel/declarations';
|
|
145
|
-
import { OrderRepository } from '@/contexts/ordering/domain/repositories/order.repository
|
|
146
|
-
import { PlaceOrder } from '@/contexts/ordering/application/commands/place-order/place-order.command
|
|
232
|
+
import { OrderRepository } from '@/contexts/ordering/domain/repositories/order.repository';
|
|
233
|
+
import { PlaceOrder } from '@/contexts/ordering/application/commands/place-order/place-order.command';
|
|
147
234
|
|
|
148
|
-
@CommandHandler(PlaceOrder
|
|
235
|
+
@CommandHandler(PlaceOrder)
|
|
149
236
|
export class PlaceOrderHandler implements CommandHandler<PlaceOrder> {
|
|
150
237
|
constructor(
|
|
151
238
|
private readonly orders: OrderRepository,
|
|
@@ -160,10 +247,10 @@ export class PlaceOrderHandler implements CommandHandler<PlaceOrder> {
|
|
|
160
247
|
// contexts/ordering/infrastructure/persistence/knex-order.repository.ts
|
|
161
248
|
import { Clock, ExecutionScope } from '@ddd-ts-kit/kernel';
|
|
162
249
|
import { Repository } from '@ddd-ts-kit/kernel/declarations';
|
|
163
|
-
import { Database } from '@/contexts/ordering/application/ports/database.port
|
|
164
|
-
import { OrderRepository } from '@/contexts/ordering/domain/repositories/order.repository
|
|
250
|
+
import { Database } from '@/contexts/ordering/application/ports/database.port';
|
|
251
|
+
import { OrderRepository } from '@/contexts/ordering/domain/repositories/order.repository';
|
|
165
252
|
|
|
166
|
-
@Repository(OrderRepository
|
|
253
|
+
@Repository(OrderRepository)
|
|
167
254
|
export class KnexOrderRepository implements OrderRepository {
|
|
168
255
|
constructor(
|
|
169
256
|
private readonly database: Database,
|
|
@@ -182,7 +269,7 @@ imported by the adapter). No file needs both.
|
|
|
182
269
|
### Ports and tokens
|
|
183
270
|
|
|
184
271
|
**A port is an abstract class, and the class is the injection token.** The class names the
|
|
185
|
-
dependency and carries its type: a
|
|
272
|
+
dependency and carries its type: a constructor parameter typed by it names what is injected, and
|
|
186
273
|
`app.resolve(Clock)` answers a `Clock`. `Token<T>` is that type: `abstract new (...args: never) => T`.
|
|
187
274
|
There is no token constant and no token file. A port has one place, one abstract class per file:
|
|
188
275
|
|
|
@@ -270,14 +357,47 @@ export abstract class BusinessClock extends Clock {
|
|
|
270
357
|
}
|
|
271
358
|
```
|
|
272
359
|
|
|
360
|
+
**What a class depends on is said by its constructor.** A decorator lists nothing: each
|
|
361
|
+
constructor parameter is typed by one class, its token, and `ddd-ts-kit docs` reads the
|
|
362
|
+
signatures from the sources into the generated file of the context, which registers them with
|
|
363
|
+
`injected`:
|
|
364
|
+
|
|
365
|
+
```ts
|
|
366
|
+
@CommandHandler(PlaceOrder)
|
|
367
|
+
export class PlaceOrderHandler implements CommandHandler<PlaceOrder> {
|
|
368
|
+
constructor(
|
|
369
|
+
private readonly orders: OrderRepository,
|
|
370
|
+
private readonly clock: Clock,
|
|
371
|
+
) {}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// contexts/ordering/ordering.declarations.ts, generated
|
|
375
|
+
injected(PlaceOrderHandler, [OrderRepository, Clock]);
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
`injected(Class, [Tokens])` records one token per constructor parameter, in order, in a
|
|
379
|
+
registry shared by every copy of the kernel a process loads; `injectedDependencies(Class)`
|
|
380
|
+
reads it back, and a container (`@ddd-ts-kit/di`) is what uses it. Nothing here reads
|
|
381
|
+
`design:paramtypes`: that metadata exists only with legacy decorators compiled by `tsc` or
|
|
382
|
+
swc, not with standard decorators nor under `tsx` or esbuild. A decorator still accepts a list
|
|
383
|
+
as its last argument, `@CommandHandler(PlaceOrder, [OrderRepository, Clock])`: the form 0.1
|
|
384
|
+
projects wrote. A declaration then carries it in `dependencies`, which is `undefined` when
|
|
385
|
+
the constructor is the statement, and a container gives it precedence.
|
|
386
|
+
|
|
273
387
|
**What the compiler refuses**, in both decorator modes:
|
|
274
388
|
|
|
275
|
-
- a
|
|
276
|
-
its parameter, in order: a missing
|
|
389
|
+
- a list, of `injected` or of a decorator, that does not name one port per constructor
|
|
390
|
+
parameter, each of the type of its parameter, in order: a missing or extra entry, a wrong
|
|
391
|
+
type, a wrong order; `injected(Class)` without a list for a constructor that takes something;
|
|
277
392
|
- a class that does not implement the port it is declared the adapter of, and an abstract class;
|
|
278
393
|
- a concrete class named where its port is expected: `[InMemoryOrderRepository, Clock]` for a
|
|
279
394
|
parameter typed `OrderRepository`. A list names ports, never what implements them.
|
|
280
395
|
|
|
396
|
+
What changed with the list becoming optional: a decorator without a list accepts any
|
|
397
|
+
constructor, so the compiler no longer tells, at the decorator, a class whose list was
|
|
398
|
+
forgotten. It does not have to: the list is derived from the constructor, checked where it is
|
|
399
|
+
generated, and a class left without one is refused by name when the application is composed.
|
|
400
|
+
|
|
281
401
|
**What is refused when the file loads**, with a `DeclarationError` from `@Repository`,
|
|
282
402
|
`@Gateway` and `@Adapter`, because the compiler cannot see it:
|
|
283
403
|
|
|
@@ -296,16 +416,16 @@ left alone.
|
|
|
296
416
|
|---|---|---|
|
|
297
417
|
| `Requires(permission, options?)` | a command or query that carries its actor | `@Requires(permissions['visit.schedule'], { resource: (c: ScheduleVisit) => ({ type: 'patient', id: c.patientId }), audited: ['startsAt'] })` |
|
|
298
418
|
| `Public(options?)` | a command or query anybody may send | `@Public()` |
|
|
299
|
-
| `CommandHandler(Message
|
|
300
|
-
| `QueryHandler(Message
|
|
301
|
-
| `IntegrationEventHandler(definition, { consumer, actorOf? }
|
|
302
|
-
| `DomainEventHandler(Event, { name }
|
|
303
|
-
| `Scheduled(name, schedule and options
|
|
304
|
-
| `Projection(name
|
|
305
|
-
| `Repository(Port, options
|
|
306
|
-
| `Gateway(Port, options
|
|
307
|
-
| `Adapter(Port, options
|
|
308
|
-
| `Policy(permission, { name }
|
|
419
|
+
| `CommandHandler(Message)` | the one handler of a command | `@CommandHandler(PlaceOrder)` |
|
|
420
|
+
| `QueryHandler(Message)` | the one handler of a query | `@QueryHandler(GetOrder)` |
|
|
421
|
+
| `IntegrationEventHandler(definition, { consumer, actorOf? })` | the handler of an integration event of another context | `@IntegrationEventHandler(OrderPlaced, { consumer: 'billing.invoice-on-order-placed' })` |
|
|
422
|
+
| `DomainEventHandler(Event, { name })` | a handler of a domain event of its own context | `@DomainEventHandler(OrderPaid, { name: 'ordering.order.paid' })` |
|
|
423
|
+
| `Scheduled(name, schedule and options)` | a job run by time, which triggers use cases | `@Scheduled('billing.send-reminders', { cron: '0 7 * * 1-5', timeZone: 'Europe/Paris' })` |
|
|
424
|
+
| `Projection(name)` with `On(definition)` on its methods | a projector: the class that keeps one read model up to date | `@Projection('scheduling.appointment-list')`, `@On(PaymentCaptured)` |
|
|
425
|
+
| `Repository(Port, options?)` | the adapter of a repository of the domain | `@Repository(OrderRepository)` |
|
|
426
|
+
| `Gateway(Port, options?)` | the adapter of a port that calls another context | `@Gateway(StockGateway)` |
|
|
427
|
+
| `Adapter(Port, options?)` | the adapter of any other port | `@Adapter(PaymentGateway, { kind: 'external' })` |
|
|
428
|
+
| `Policy(permission, { name })` | a rule that needs the loaded element | `@Policy(permissions['invoice.void'], { name: 'billing.only-issuer-voids' })` |
|
|
309
429
|
|
|
310
430
|
- **Access is said on the message.** A command extends `Command` or `AuthorizedCommand`, a
|
|
311
431
|
query `Query` or `AuthorizedQuery`: the base class already says which of the two it is, so
|
|
@@ -365,7 +485,7 @@ the integration event handlers of a context on `EventSubscribers.forContext(<con
|
|
|
365
485
|
|
|
366
486
|
```ts
|
|
367
487
|
// contexts/billing/application/scheduling/send-reminders.job.ts
|
|
368
|
-
@Scheduled('billing.send-reminders', { cron: '0 7 * * 1-5', timeZone: 'Europe/Paris' }
|
|
488
|
+
@Scheduled('billing.send-reminders', { cron: '0 7 * * 1-5', timeZone: 'Europe/Paris' })
|
|
369
489
|
export class SendRemindersJob implements ScheduledJob {
|
|
370
490
|
constructor(private readonly commands: CommandBus) {}
|
|
371
491
|
|
|
@@ -376,7 +496,7 @@ export class SendRemindersJob implements ScheduledJob {
|
|
|
376
496
|
```
|
|
377
497
|
|
|
378
498
|
A job lives in `application/scheduling/`, in a `*.job.ts` file, and only triggers use cases:
|
|
379
|
-
it receives buses and ports by its
|
|
499
|
+
it receives buses and ports by its constructor and typically sends one command. The second
|
|
380
500
|
argument is the schedule and, next to it, the options:
|
|
381
501
|
|
|
382
502
|
| Key | Default | |
|
|
@@ -399,7 +519,9 @@ are in the README of `@ddd-ts-kit/scheduling`.
|
|
|
399
519
|
### Decorator modes
|
|
400
520
|
|
|
401
521
|
Every decorator of this entry works under both decorator modes of TypeScript, and the same
|
|
402
|
-
source line type-checks under both, checks of the role and of
|
|
522
|
+
source line type-checks under both, checks of the role and of a dependency list included.
|
|
523
|
+
Neither needs `emitDecoratorMetadata`, and what a constructor takes is known in both the same
|
|
524
|
+
way: read from the source, registered by `injected`.
|
|
403
525
|
|
|
404
526
|
| Stack | `tsconfig.json` |
|
|
405
527
|
|---|---|
|
|
@@ -910,7 +1032,7 @@ else: it sends no command and reads no other context.
|
|
|
910
1032
|
import { stampOf, type IntegrationEvent } from '@ddd-ts-kit/kernel';
|
|
911
1033
|
import { On, Projection } from '@ddd-ts-kit/kernel/declarations';
|
|
912
1034
|
|
|
913
|
-
@Projection('scheduling.appointment-list'
|
|
1035
|
+
@Projection('scheduling.appointment-list')
|
|
914
1036
|
export class AppointmentListProjection {
|
|
915
1037
|
constructor(private readonly appointments: AppointmentList) {}
|
|
916
1038
|
|
|
@@ -933,8 +1055,8 @@ export class AppointmentListProjection {
|
|
|
933
1055
|
}
|
|
934
1056
|
```
|
|
935
1057
|
|
|
936
|
-
`@Projection('<context>.<name>'
|
|
937
|
-
modes,
|
|
1058
|
+
`@Projection('<context>.<name>')` is a declaration like the others: both decorator
|
|
1059
|
+
modes, its dependencies stated by its constructor, one class per file, in
|
|
938
1060
|
`application/projections/`, in a `*.projection.ts` file. `@On(definition)` on a method says
|
|
939
1061
|
"this method applies that integration event"; `@On(EventClass, { name })` says it for a domain
|
|
940
1062
|
event of the projection's own context. A method that takes another event is refused by the
|
|
@@ -942,13 +1064,11 @@ compiler, a projection without any `@On` and an `@On` on a class without `@Proje
|
|
|
942
1064
|
when the file loads. A method answers what its store answered, which is how the application
|
|
943
1065
|
counts what was applied and what was stale.
|
|
944
1066
|
|
|
945
|
-
**
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
(`declarations/barrel-current`): the projection is then registered by discovery or with
|
|
951
|
-
`builder.include(...)`, see the README of `@ddd-ts-kit/di`.
|
|
1067
|
+
**A role of the CLI.** `application/projections/` is a directory of the canonical tree,
|
|
1068
|
+
`ddd-ts-kit generate projection <context> <Name> <event-type>` writes a projector with its
|
|
1069
|
+
spec, the generated barrel `<context>.declarations.ts` exports it and registers what its
|
|
1070
|
+
constructor takes, and `ddd-ts-kit describe` and the reference of `CONTEXT.md` list it with
|
|
1071
|
+
the events it applies.
|
|
952
1072
|
|
|
953
1073
|
### Idempotent and ordered by construction
|
|
954
1074
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ClassDeclarator } from '../dependencies/class-declarator.js';
|
|
2
|
-
import type {
|
|
2
|
+
import type { DeclaredDependencies } from '../dependencies/declared-dependencies.js';
|
|
3
|
+
import type { DependenciesFromSignature } from '../dependencies/dependencies-from-signature.js';
|
|
3
4
|
import type { Token } from '../token/token.js';
|
|
4
5
|
import type { PortOptions } from './port-options.js';
|
|
5
6
|
export interface AdapterOptions extends PortOptions {
|
|
@@ -8,8 +9,8 @@ export interface AdapterOptions extends PortOptions {
|
|
|
8
9
|
}
|
|
9
10
|
/**
|
|
10
11
|
* The adapter of any other port of the application layer:
|
|
11
|
-
* `@Adapter(PaymentGateway, { kind: 'external' }
|
|
12
|
+
* `@Adapter(PaymentGateway, { kind: 'external' })`.
|
|
12
13
|
*/
|
|
13
|
-
export declare function Adapter<T, const D extends
|
|
14
|
-
export declare function Adapter<T, const D extends
|
|
14
|
+
export declare function Adapter<T, const D extends DeclaredDependencies = DependenciesFromSignature>(port: Token<T>, dependencies?: D): ClassDeclarator<T, D>;
|
|
15
|
+
export declare function Adapter<T, const D extends DeclaredDependencies = DependenciesFromSignature>(port: Token<T>, options: AdapterOptions, dependencies?: D): ClassDeclarator<T, D>;
|
|
15
16
|
//# sourceMappingURL=adapter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../src/declarations/decorators/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AAC3E,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../src/declarations/decorators/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AAC3E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,0CAA0C,CAAC;AACrF,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,gDAAgD,CAAC;AAChG,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAG/C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGrD,MAAM,WAAW,cAAe,SAAQ,WAAW;IACjD,wFAAwF;IACxF,QAAQ,CAAC,IAAI,CAAC,EAAE,UAAU,GAAG,WAAW,CAAC;CAC1C;AAED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,SAAS,oBAAoB,GAAG,yBAAyB,EACzF,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,EACd,YAAY,CAAC,EAAE,CAAC,GACf,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACzB,wBAAgB,OAAO,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,SAAS,oBAAoB,GAAG,yBAAyB,EACzF,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,EACd,OAAO,EAAE,cAAc,EACvB,YAAY,CAAC,EAAE,CAAC,GACf,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../../src/declarations/decorators/adapter.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../../src/declarations/decorators/adapter.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAuBtD,MAAM,UAAU,OAAO,CACrB,IAAc,EACd,GAAG,QAAqC;IAExC,MAAM,CAAC,KAAK,CAAC,GAAG,QAAQ,CAAC;IACzB,MAAM,IAAI,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC;IAE7D,OAAO,SAAS,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,IAAI,UAAU,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,QAAQ,CAAC,CAAC;AACzF,CAAC"}
|
|
@@ -2,14 +2,16 @@ import type { CommandHandler as CommandHandlerPort } from '../../application/mes
|
|
|
2
2
|
import type { Command } from '../../application/messaging/command.js';
|
|
3
3
|
import type { MessageType } from '../../application/messaging/message-type.js';
|
|
4
4
|
import type { ClassDeclarator } from '../dependencies/class-declarator.js';
|
|
5
|
-
import type {
|
|
5
|
+
import type { DeclaredDependencies } from '../dependencies/declared-dependencies.js';
|
|
6
|
+
import type { DependenciesFromSignature } from '../dependencies/dependencies-from-signature.js';
|
|
6
7
|
import type { MessageHandler } from '../model/message-handler.js';
|
|
7
8
|
/** The interface of the kernel under the name of its decorator, so one import serves both. */
|
|
8
9
|
export type CommandHandler<C extends Command<unknown>> = CommandHandlerPort<C>;
|
|
9
10
|
/**
|
|
10
|
-
* The one handler of a command
|
|
11
|
-
*
|
|
12
|
-
*
|
|
11
|
+
* The one handler of a command: `@CommandHandler(PlaceOrder)`. Its dependencies are the ports
|
|
12
|
+
* that type its constructor parameters, read from the source by `ddd-ts-kit docs`. A list given
|
|
13
|
+
* as the last argument, `@CommandHandler(PlaceOrder, [OrderRepository, Clock])`, is the form
|
|
14
|
+
* 0.1 projects wrote: it is checked against the constructor and wins over the signature.
|
|
13
15
|
*/
|
|
14
|
-
export declare function CommandHandler<C extends Command<unknown>, const D extends
|
|
16
|
+
export declare function CommandHandler<C extends Command<unknown>, const D extends DeclaredDependencies = DependenciesFromSignature>(message: MessageType<C>, dependencies?: D): ClassDeclarator<MessageHandler<C>, D>;
|
|
15
17
|
//# sourceMappingURL=command-handler.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command-handler.d.ts","sourceRoot":"","sources":["../../../src/declarations/decorators/command-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,IAAI,kBAAkB,EAAE,MAAM,gDAAgD,CAAC;AAC3G,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wCAAwC,CAAC;AACtE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6CAA6C,CAAC;AAC/E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AAC3E,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"command-handler.d.ts","sourceRoot":"","sources":["../../../src/declarations/decorators/command-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,IAAI,kBAAkB,EAAE,MAAM,gDAAgD,CAAC;AAC3G,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wCAAwC,CAAC;AACtE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6CAA6C,CAAC;AAC/E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AAC3E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,0CAA0C,CAAC;AACrF,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,gDAAgD,CAAC;AAChG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAIlE,8FAA8F;AAC9F,MAAM,MAAM,cAAc,CAAC,CAAC,SAAS,OAAO,CAAC,OAAO,CAAC,IAAI,kBAAkB,CAAC,CAAC,CAAC,CAAC;AAE/E;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,CAAC,SAAS,OAAO,CAAC,OAAO,CAAC,EAC1B,KAAK,CAAC,CAAC,SAAS,oBAAoB,GAAG,yBAAyB,EAChE,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,YAAY,CAAC,EAAE,CAAC,GAAG,eAAe,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAIlF"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { record } from '../registry/record.js';
|
|
2
2
|
import { handling } from './handling.js';
|
|
3
3
|
/**
|
|
4
|
-
* The one handler of a command
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* The one handler of a command: `@CommandHandler(PlaceOrder)`. Its dependencies are the ports
|
|
5
|
+
* that type its constructor parameters, read from the source by `ddd-ts-kit docs`. A list given
|
|
6
|
+
* as the last argument, `@CommandHandler(PlaceOrder, [OrderRepository, Clock])`, is the form
|
|
7
|
+
* 0.1 projects wrote: it is checked against the constructor and wins over the signature.
|
|
7
8
|
*/
|
|
8
9
|
export function CommandHandler(message, dependencies) {
|
|
9
10
|
return (target) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command-handler.js","sourceRoot":"","sources":["../../../src/declarations/decorators/command-handler.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"command-handler.js","sourceRoot":"","sources":["../../../src/declarations/decorators/command-handler.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAKzC;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAG5B,OAAuB,EAAE,YAAgB;IACzC,OAAO,CAAC,MAAM,EAAE,EAAE;QAChB,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,EAAE,YAAY,CAAC,CAAC,CAAC;IACvG,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { DependencyKind } from '../../application/dependency-kind.js';
|
|
2
2
|
import type { ClassDeclarator } from '../dependencies/class-declarator.js';
|
|
3
|
-
import type {
|
|
3
|
+
import type { DeclaredDependencies } from '../dependencies/declared-dependencies.js';
|
|
4
4
|
import type { PortDeclaration } from '../model/port-declaration.js';
|
|
5
5
|
import type { Token } from '../token/token.js';
|
|
6
6
|
import type { PortOptions } from './port-options.js';
|
|
@@ -10,6 +10,6 @@ interface Port<T> {
|
|
|
10
10
|
readonly kind: DependencyKind;
|
|
11
11
|
readonly token: Token<T>;
|
|
12
12
|
}
|
|
13
|
-
export declare function declaring<T, D extends
|
|
13
|
+
export declare function declaring<T, D extends DeclaredDependencies>(port: Port<T>, [first, second]: Settings<PortOptions, D>): ClassDeclarator<T, D>;
|
|
14
14
|
export {};
|
|
15
15
|
//# sourceMappingURL=declaring.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"declaring.d.ts","sourceRoot":"","sources":["../../../src/declarations/decorators/declaring.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AAC3E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AAC3E,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"declaring.d.ts","sourceRoot":"","sources":["../../../src/declarations/decorators/declaring.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AAC3E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AAC3E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,0CAA0C,CAAC;AACrF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAIpE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAE/C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,UAAU,IAAI,CAAC,CAAC;IACd,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC,MAAM,CAAC,CAAC;IACvC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;CAC1B;AAED,wBAAgB,SAAS,CAAC,CAAC,EAAE,CAAC,SAAS,oBAAoB,EACzD,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,EACb,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC,GACxC,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,CAgBvB"}
|
|
@@ -3,8 +3,8 @@ import { record } from '../registry/record.js';
|
|
|
3
3
|
import { portDefect } from '../token/port-defect.js';
|
|
4
4
|
import { isDependencies } from './is-dependencies.js';
|
|
5
5
|
export function declaring(port, [first, second]) {
|
|
6
|
-
const options =
|
|
7
|
-
const dependencies = isDependencies(first) ? first :
|
|
6
|
+
const options = isOptions(first) ? first : {};
|
|
7
|
+
const dependencies = isDependencies(first) ? first : second;
|
|
8
8
|
return (target) => {
|
|
9
9
|
assertImplements(port.token, target);
|
|
10
10
|
record(target, {
|
|
@@ -17,6 +17,9 @@ export function declaring(port, [first, second]) {
|
|
|
17
17
|
});
|
|
18
18
|
};
|
|
19
19
|
}
|
|
20
|
+
function isOptions(value) {
|
|
21
|
+
return typeof value === 'object' && value !== null && !isDependencies(value);
|
|
22
|
+
}
|
|
20
23
|
function assertImplements(port, adapter) {
|
|
21
24
|
const defect = portDefect(port, adapter);
|
|
22
25
|
if (defect !== undefined) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"declaring.js","sourceRoot":"","sources":["../../../src/declarations/decorators/declaring.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAErD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAUtD,MAAM,UAAU,SAAS,CACvB,IAAa,EACb,CAAC,KAAK,EAAE,MAAM,CAA2B;IAEzC,MAAM,OAAO,
|
|
1
|
+
{"version":3,"file":"declaring.js","sourceRoot":"","sources":["../../../src/declarations/decorators/declaring.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAErD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAUtD,MAAM,UAAU,SAAS,CACvB,IAAa,EACb,CAAC,KAAK,EAAE,MAAM,CAA2B;IAEzC,MAAM,OAAO,GAAgB,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IAC3D,MAAM,YAAY,GAAyB,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;IAElF,OAAO,CAAC,MAAM,EAAE,EAAE;QAChB,gBAAgB,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAErC,MAAM,CAAC,MAAM,EAAE;YACb,GAAG,IAAI;YACP,QAAQ,EAAE,OAAO,CAAC,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW;YAChE,QAAQ,EAAE,OAAO,CAAC,QAAQ,KAAK,IAAI;YACnC,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,EAAE;YAC9B,cAAc,EAAE,MAAM;YACtB,YAAY;SACb,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC;AAED,SAAS,SAAS,CAAC,KAAc;IAC/B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;AAC/E,CAAC;AAED,SAAS,gBAAgB,CAAC,IAAoB,EAAE,OAAuB;IACrE,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAEzC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,MAAM,IAAI,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACrC,CAAC;AACH,CAAC"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { DomainEventPhase } from '../../application/events/domain-event-phase.js';
|
|
2
2
|
import type { DomainEvent } from '../../domain/domain-event.js';
|
|
3
3
|
import type { ClassDeclarator } from '../dependencies/class-declarator.js';
|
|
4
|
-
import type {
|
|
4
|
+
import type { DeclaredDependencies } from '../dependencies/declared-dependencies.js';
|
|
5
|
+
import type { DependenciesFromSignature } from '../dependencies/dependencies-from-signature.js';
|
|
5
6
|
import type { DomainEventHandler as DomainEventHandlerShape } from '../model/domain-event-handler.js';
|
|
6
7
|
import type { DomainEventType } from '../model/domain-event-type.js';
|
|
7
8
|
import type { Named } from './named.js';
|
|
@@ -22,9 +23,9 @@ export type DomainEventHandler<E extends DomainEvent> = DomainEventHandlerShape<
|
|
|
22
23
|
/**
|
|
23
24
|
* A handler of a domain event of its own context, run at the end of the unit of work that
|
|
24
25
|
* recorded the event, before the commit:
|
|
25
|
-
* `@DomainEventHandler(OrderPaid, { name: 'ordering.order.paid' }
|
|
26
|
+
* `@DomainEventHandler(OrderPaid, { name: 'ordering.order.paid' })`. One whose
|
|
26
27
|
* effect is outside the transaction runs after it:
|
|
27
|
-
* `@DomainEventHandler(OrderPaid, { name: 'ordering.order.paid', phase: 'after-commit' }
|
|
28
|
+
* `@DomainEventHandler(OrderPaid, { name: 'ordering.order.paid', phase: 'after-commit' })`.
|
|
28
29
|
*/
|
|
29
|
-
export declare function DomainEventHandler<E extends DomainEvent, const Name extends string, const D extends
|
|
30
|
+
export declare function DomainEventHandler<E extends DomainEvent, const Name extends string, const D extends DeclaredDependencies = DependenciesFromSignature>(event: DomainEventType<E>, options: DomainEventHandlerOptions<Name> & Named<Name, 'name'>, dependencies?: D): ClassDeclarator<DomainEventHandlerShape<E>, D>;
|
|
30
31
|
//# sourceMappingURL=domain-event-handler.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"domain-event-handler.d.ts","sourceRoot":"","sources":["../../../src/declarations/decorators/domain-event-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gDAAgD,CAAC;AACvF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AAC3E,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"domain-event-handler.d.ts","sourceRoot":"","sources":["../../../src/declarations/decorators/domain-event-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gDAAgD,CAAC;AACvF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AAC3E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,0CAA0C,CAAC;AACrF,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,gDAAgD,CAAC;AAChG,OAAO,KAAK,EAAE,kBAAkB,IAAI,uBAAuB,EAAE,MAAM,kCAAkC,CAAC;AACtG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAGrE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC,MAAM,WAAW,yBAAyB,CAAC,IAAI,SAAS,MAAM,GAAG,MAAM;IACrE,+GAA+G;IAC/G,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB;;;OAGG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,gBAAgB,CAAC;CACnC;AAED;;;GAGG;AACH,MAAM,MAAM,kBAAkB,CAAC,CAAC,SAAS,WAAW,IAAI,uBAAuB,CAAC,CAAC,CAAC,CAAC;AAEnF;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,CAAC,SAAS,WAAW,EACrB,KAAK,CAAC,IAAI,SAAS,MAAM,EACzB,KAAK,CAAC,CAAC,SAAS,oBAAoB,GAAG,yBAAyB,EAEhE,KAAK,EAAE,eAAe,CAAC,CAAC,CAAC,EACzB,OAAO,EAAE,yBAAyB,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,EAC9D,YAAY,CAAC,EAAE,CAAC,GACf,eAAe,CAAC,uBAAuB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAehD"}
|
|
@@ -3,9 +3,9 @@ import { assertNamed } from './assert-named.js';
|
|
|
3
3
|
/**
|
|
4
4
|
* A handler of a domain event of its own context, run at the end of the unit of work that
|
|
5
5
|
* recorded the event, before the commit:
|
|
6
|
-
* `@DomainEventHandler(OrderPaid, { name: 'ordering.order.paid' }
|
|
6
|
+
* `@DomainEventHandler(OrderPaid, { name: 'ordering.order.paid' })`. One whose
|
|
7
7
|
* effect is outside the transaction runs after it:
|
|
8
|
-
* `@DomainEventHandler(OrderPaid, { name: 'ordering.order.paid', phase: 'after-commit' }
|
|
8
|
+
* `@DomainEventHandler(OrderPaid, { name: 'ordering.order.paid', phase: 'after-commit' })`.
|
|
9
9
|
*/
|
|
10
10
|
export function DomainEventHandler(event, options, dependencies) {
|
|
11
11
|
const { name, phase = 'before-commit' } = options;
|
|
@@ -16,7 +16,7 @@ export function DomainEventHandler(event, options, dependencies) {
|
|
|
16
16
|
name,
|
|
17
17
|
phase,
|
|
18
18
|
event,
|
|
19
|
-
dependencies
|
|
19
|
+
dependencies,
|
|
20
20
|
pair: (use) => use(event, target),
|
|
21
21
|
});
|
|
22
22
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"domain-event-handler.js","sourceRoot":"","sources":["../../../src/declarations/decorators/domain-event-handler.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"domain-event-handler.js","sourceRoot":"","sources":["../../../src/declarations/decorators/domain-event-handler.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAmBhD;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAKhC,KAAyB,EACzB,OAA8D,EAC9D,YAAgB;IAEhB,MAAM,EAAE,IAAI,EAAE,KAAK,GAAG,eAAe,EAAE,GAAG,OAAO,CAAC;IAElD,WAAW,CAAC,IAAI,EAAE,gBAAgB,KAAK,CAAC,IAAI,kCAAkC,CAAC,CAAC;IAEhF,OAAO,CAAC,MAAM,EAAE,EAAE;QAChB,MAAM,CAAC,MAAM,EAAE;YACb,IAAI,EAAE,sBAAsB;YAC5B,IAAI;YACJ,KAAK;YACL,KAAK;YACL,YAAY;YACZ,IAAI,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC;SAClC,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import type { ClassDeclarator } from '../dependencies/class-declarator.js';
|
|
2
|
-
import type {
|
|
2
|
+
import type { DeclaredDependencies } from '../dependencies/declared-dependencies.js';
|
|
3
|
+
import type { DependenciesFromSignature } from '../dependencies/dependencies-from-signature.js';
|
|
3
4
|
import type { Token } from '../token/token.js';
|
|
4
5
|
import type { PortOptions } from './port-options.js';
|
|
5
6
|
/**
|
|
6
7
|
* The adapter of a port through which this context calls another one synchronously: in
|
|
7
|
-
* process today, a remote client tomorrow. `@Gateway(StockGateway
|
|
8
|
+
* process today, a remote client tomorrow. `@Gateway(StockGateway)`.
|
|
8
9
|
*/
|
|
9
|
-
export declare function Gateway<T, const D extends
|
|
10
|
-
export declare function Gateway<T, const D extends
|
|
10
|
+
export declare function Gateway<T, const D extends DeclaredDependencies = DependenciesFromSignature>(port: Token<T>, dependencies?: D): ClassDeclarator<T, D>;
|
|
11
|
+
export declare function Gateway<T, const D extends DeclaredDependencies = DependenciesFromSignature>(port: Token<T>, options: PortOptions, dependencies?: D): ClassDeclarator<T, D>;
|
|
11
12
|
//# sourceMappingURL=gateway.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gateway.d.ts","sourceRoot":"","sources":["../../../src/declarations/decorators/gateway.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AAC3E,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"gateway.d.ts","sourceRoot":"","sources":["../../../src/declarations/decorators/gateway.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AAC3E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,0CAA0C,CAAC;AACrF,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,gDAAgD,CAAC;AAChG,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAE/C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGrD;;;GAGG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,SAAS,oBAAoB,GAAG,yBAAyB,EACzF,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,EACd,YAAY,CAAC,EAAE,CAAC,GACf,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACzB,wBAAgB,OAAO,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,SAAS,oBAAoB,GAAG,yBAAyB,EACzF,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,EACd,OAAO,EAAE,WAAW,EACpB,YAAY,CAAC,EAAE,CAAC,GACf,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gateway.js","sourceRoot":"","sources":["../../../src/declarations/decorators/gateway.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"gateway.js","sourceRoot":"","sources":["../../../src/declarations/decorators/gateway.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAkB3C,MAAM,UAAU,OAAO,CACrB,IAAc,EACd,GAAG,QAAkC;IAErC,OAAO,SAAS,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,QAAQ,CAAC,CAAC;AAChF,CAAC"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type { MessageType } from '../../application/messaging/message-type.js';
|
|
2
2
|
import type { Message } from '../../application/messaging/message.js';
|
|
3
|
-
import type {
|
|
3
|
+
import type { DeclaredDependencies } from '../dependencies/declared-dependencies.js';
|
|
4
4
|
import type { HandlerDeclaration } from '../model/handler-declaration.js';
|
|
5
5
|
type Handling = Omit<HandlerDeclaration, 'dependencies' | 'message'> & {
|
|
6
6
|
readonly message: MessageType<Message>;
|
|
7
7
|
};
|
|
8
|
-
export declare function handling(declared: Handling, dependencies
|
|
8
|
+
export declare function handling(declared: Handling, dependencies: DeclaredDependencies): HandlerDeclaration;
|
|
9
9
|
export {};
|
|
10
10
|
//# sourceMappingURL=handling.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handling.d.ts","sourceRoot":"","sources":["../../../src/declarations/decorators/handling.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6CAA6C,CAAC;AAC/E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wCAAwC,CAAC;AACtE,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"handling.d.ts","sourceRoot":"","sources":["../../../src/declarations/decorators/handling.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6CAA6C,CAAC;AAC/E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wCAAwC,CAAC;AACtE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,0CAA0C,CAAC;AACrF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAE1E,KAAK,QAAQ,GAAG,IAAI,CAAC,kBAAkB,EAAE,cAAc,GAAG,SAAS,CAAC,GAAG;IAAE,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,OAAO,CAAC,CAAA;CAAE,CAAC;AAElH,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,oBAAoB,GAAG,kBAAkB,CAEnG"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handling.js","sourceRoot":"","sources":["../../../src/declarations/decorators/handling.ts"],"names":[],"mappings":"AAOA,MAAM,UAAU,QAAQ,CAAC,QAAkB,EAAE,
|
|
1
|
+
{"version":3,"file":"handling.js","sourceRoot":"","sources":["../../../src/declarations/decorators/handling.ts"],"names":[],"mappings":"AAOA,MAAM,UAAU,QAAQ,CAAC,QAAkB,EAAE,YAAkC;IAC7E,OAAO,EAAE,GAAG,QAAQ,EAAE,YAAY,EAAE,CAAC;AACvC,CAAC"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { Actor } from '../../application/actor/actor.js';
|
|
2
2
|
import type { IntegrationEvent } from '../../application/events/integration-event.js';
|
|
3
3
|
import type { ClassDeclarator } from '../dependencies/class-declarator.js';
|
|
4
|
-
import type {
|
|
4
|
+
import type { DeclaredDependencies } from '../dependencies/declared-dependencies.js';
|
|
5
|
+
import type { DependenciesFromSignature } from '../dependencies/dependencies-from-signature.js';
|
|
5
6
|
import type { EventContract } from '../model/event-contract.js';
|
|
6
7
|
import type { IntegrationEventHandler as IntegrationEventHandlerShape } from '../model/integration-event-handler.js';
|
|
7
8
|
import type { Named } from './named.js';
|
|
@@ -24,7 +25,7 @@ export interface IntegrationEventHandlerOptions<Name extends string = string> {
|
|
|
24
25
|
export type IntegrationEventHandler<Payload> = IntegrationEventHandlerShape<Payload>;
|
|
25
26
|
/**
|
|
26
27
|
* The handler of an integration event of another context, subscribed under a stable consumer name:
|
|
27
|
-
* `@IntegrationEventHandler(OrderPlaced, { consumer: 'billing.invoice-on-order-placed' }
|
|
28
|
+
* `@IntegrationEventHandler(OrderPlaced, { consumer: 'billing.invoice-on-order-placed' })`.
|
|
28
29
|
*/
|
|
29
|
-
export declare function IntegrationEventHandler<Payload, const Name extends string, const D extends
|
|
30
|
+
export declare function IntegrationEventHandler<Payload, const Name extends string, const D extends DeclaredDependencies = DependenciesFromSignature>(contract: EventContract<Payload>, options: IntegrationEventHandlerOptions<Name> & Named<Name, 'consumer'>, dependencies?: D): ClassDeclarator<IntegrationEventHandlerShape<Payload>, D>;
|
|
30
31
|
//# sourceMappingURL=integration-event-handler.d.ts.map
|