@arts-n-crafts/ts 3.19.0 → 5.0.0-rc.2
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 +221 -6
- package/package.json +109 -22
- package/packages/v3/dist/index.cjs +63 -72
- package/packages/v3/dist/index.cjs.map +1 -1
- package/packages/v3/dist/index.d.cts +22 -22
- package/packages/v3/dist/index.d.ts +22 -22
- package/packages/v3/dist/index.js +63 -72
- package/packages/v3/dist/index.js.map +1 -1
- package/packages/v3/package.json +49 -50
- package/packages/v4/dist/index.cjs +71 -126
- package/packages/v4/dist/index.cjs.map +1 -1
- package/packages/v4/dist/index.d.cts +36 -47
- package/packages/v4/dist/index.d.ts +36 -47
- package/packages/v4/dist/index.js +72 -125
- package/packages/v4/dist/index.js.map +1 -1
- package/packages/v4/package.json +49 -50
- package/packages/v5/dist/DomainEvent-CSzUMw46.d.cts +23 -0
- package/packages/v5/dist/DomainEvent-w1jyCjai.d.ts +23 -0
- package/packages/v5/dist/Intent-B6l0bHZU.d.cts +13 -0
- package/packages/v5/dist/Intent-BLNY6RoG.d.ts +13 -0
- package/packages/v5/dist/Message-c9XdBoh4.d.cts +36 -0
- package/packages/v5/dist/Message-c9XdBoh4.d.ts +36 -0
- package/packages/v5/dist/Rejection-D9PlzquK.d.cts +19 -0
- package/packages/v5/dist/Rejection-D9PlzquK.d.ts +19 -0
- package/packages/v5/dist/adapters/outbound/capabilities/index.cjs +4 -0
- package/packages/v5/dist/adapters/outbound/capabilities/index.cjs.map +1 -0
- package/packages/v5/dist/adapters/outbound/capabilities/index.d.cts +77 -0
- package/packages/v5/dist/adapters/outbound/capabilities/index.d.ts +77 -0
- package/packages/v5/dist/adapters/outbound/capabilities/index.js +3 -0
- package/packages/v5/dist/adapters/outbound/capabilities/index.js.map +1 -0
- package/packages/v5/dist/adapters/outbound/shapes/index.cjs +4 -0
- package/packages/v5/dist/adapters/outbound/shapes/index.cjs.map +1 -0
- package/packages/v5/dist/adapters/outbound/shapes/index.d.cts +68 -0
- package/packages/v5/dist/adapters/outbound/shapes/index.d.ts +68 -0
- package/packages/v5/dist/adapters/outbound/shapes/index.js +3 -0
- package/packages/v5/dist/adapters/outbound/shapes/index.js.map +1 -0
- package/packages/v5/dist/core/capabilities/index.cjs +4 -0
- package/packages/v5/dist/core/capabilities/index.cjs.map +1 -0
- package/packages/v5/dist/core/capabilities/index.d.cts +33 -0
- package/packages/v5/dist/core/capabilities/index.d.ts +33 -0
- package/packages/v5/dist/core/capabilities/index.js +3 -0
- package/packages/v5/dist/core/capabilities/index.js.map +1 -0
- package/packages/v5/dist/core/shapes/index.cjs +4 -0
- package/packages/v5/dist/core/shapes/index.cjs.map +1 -0
- package/packages/v5/dist/core/shapes/index.d.cts +27 -0
- package/packages/v5/dist/core/shapes/index.d.ts +27 -0
- package/packages/v5/dist/core/shapes/index.js +3 -0
- package/packages/v5/dist/core/shapes/index.js.map +1 -0
- package/packages/v5/dist/useCases/command/capabilities/index.cjs +4 -0
- package/packages/v5/dist/useCases/command/capabilities/index.cjs.map +1 -0
- package/packages/v5/dist/useCases/command/capabilities/index.d.cts +27 -0
- package/packages/v5/dist/useCases/command/capabilities/index.d.ts +27 -0
- package/packages/v5/dist/useCases/command/capabilities/index.js +3 -0
- package/packages/v5/dist/useCases/command/capabilities/index.js.map +1 -0
- package/packages/v5/dist/useCases/command/shapes/index.cjs +4 -0
- package/packages/v5/dist/useCases/command/shapes/index.cjs.map +1 -0
- package/packages/v5/dist/useCases/command/shapes/index.d.cts +78 -0
- package/packages/v5/dist/useCases/command/shapes/index.d.ts +78 -0
- package/packages/v5/dist/useCases/command/shapes/index.js +3 -0
- package/packages/v5/dist/useCases/command/shapes/index.js.map +1 -0
- package/packages/v5/dist/useCases/policy/capabilities/index.cjs +4 -0
- package/packages/v5/dist/useCases/policy/capabilities/index.cjs.map +1 -0
- package/packages/v5/dist/useCases/policy/capabilities/index.d.cts +12 -0
- package/packages/v5/dist/useCases/policy/capabilities/index.d.ts +12 -0
- package/packages/v5/dist/useCases/policy/capabilities/index.js +3 -0
- package/packages/v5/dist/useCases/policy/capabilities/index.js.map +1 -0
- package/packages/v5/dist/useCases/query/capabilities/index.cjs +4 -0
- package/packages/v5/dist/useCases/query/capabilities/index.cjs.map +1 -0
- package/packages/v5/dist/useCases/query/capabilities/index.d.cts +8 -0
- package/packages/v5/dist/useCases/query/capabilities/index.d.ts +8 -0
- package/packages/v5/dist/useCases/query/capabilities/index.js +3 -0
- package/packages/v5/dist/useCases/query/capabilities/index.js.map +1 -0
- package/packages/v5/dist/useCases/query/shapes/index.cjs +4 -0
- package/packages/v5/dist/useCases/query/shapes/index.cjs.map +1 -0
- package/packages/v5/dist/useCases/query/shapes/index.d.cts +7 -0
- package/packages/v5/dist/useCases/query/shapes/index.d.ts +7 -0
- package/packages/v5/dist/useCases/query/shapes/index.js +3 -0
- package/packages/v5/dist/useCases/query/shapes/index.js.map +1 -0
- package/packages/v5/package.json +59 -0
|
@@ -11,7 +11,7 @@ interface Command<TType = string, TPayload = unknown> extends WithIdentifier {
|
|
|
11
11
|
type: TType;
|
|
12
12
|
aggregateId: string;
|
|
13
13
|
payload: TPayload;
|
|
14
|
-
kind:
|
|
14
|
+
kind: "command";
|
|
15
15
|
timestamp: string;
|
|
16
16
|
metadata: Partial<CommandMetadata>;
|
|
17
17
|
}
|
|
@@ -28,7 +28,7 @@ interface IntegrationEventMetadata {
|
|
|
28
28
|
interface IntegrationEvent<TPayload = unknown> {
|
|
29
29
|
id: string;
|
|
30
30
|
type: string;
|
|
31
|
-
source:
|
|
31
|
+
source: "external";
|
|
32
32
|
payload: TPayload;
|
|
33
33
|
timestamp: string;
|
|
34
34
|
metadata: {} & Partial<IntegrationEventMetadata>;
|
|
@@ -43,7 +43,7 @@ interface DomainEvent<TPayload = unknown> {
|
|
|
43
43
|
id: string;
|
|
44
44
|
type: string;
|
|
45
45
|
aggregateId: string;
|
|
46
|
-
source:
|
|
46
|
+
source: "internal";
|
|
47
47
|
payload: TPayload;
|
|
48
48
|
timestamp: string;
|
|
49
49
|
metadata: Partial<DomainEventMetadata>;
|
|
@@ -65,7 +65,7 @@ interface QueryMetadata {
|
|
|
65
65
|
interface Query<TType = string, TPayload = unknown> extends WithIdentifier {
|
|
66
66
|
type: TType;
|
|
67
67
|
payload: TPayload;
|
|
68
|
-
kind:
|
|
68
|
+
kind: "query";
|
|
69
69
|
timestamp: string;
|
|
70
70
|
metadata: Partial<QueryMetadata>;
|
|
71
71
|
}
|
|
@@ -129,14 +129,14 @@ interface Repository<TEvent, TLoadReturnType, TStoreReturnType = Promise<void>>
|
|
|
129
129
|
}
|
|
130
130
|
|
|
131
131
|
type QueryNode = {
|
|
132
|
-
type:
|
|
132
|
+
type: "eq" | "gt" | "lt";
|
|
133
133
|
field: string | number | symbol;
|
|
134
134
|
value: Primitive;
|
|
135
135
|
} | {
|
|
136
|
-
type:
|
|
136
|
+
type: "and" | "or";
|
|
137
137
|
nodes: QueryNode[];
|
|
138
138
|
} | {
|
|
139
|
-
type:
|
|
139
|
+
type: "not";
|
|
140
140
|
node: QueryNode;
|
|
141
141
|
};
|
|
142
142
|
|
|
@@ -185,9 +185,9 @@ declare class FieldGreaterThan<T> extends Specification<T> {
|
|
|
185
185
|
toQuery(): QueryNode;
|
|
186
186
|
}
|
|
187
187
|
|
|
188
|
-
declare function createQueryNode(type:
|
|
189
|
-
declare function createQueryNode(type:
|
|
190
|
-
declare function createQueryNode(type:
|
|
188
|
+
declare function createQueryNode(type: "eq" | "gt" | "lt", field: string | number | symbol, value: Primitive): QueryNode;
|
|
189
|
+
declare function createQueryNode(type: "and" | "or", field: undefined, value: QueryNode[]): QueryNode;
|
|
190
|
+
declare function createQueryNode(type: "not", field: undefined, value: QueryNode): QueryNode;
|
|
191
191
|
|
|
192
192
|
declare function createDomainEvent<TPayload = unknown>(type: string, aggregateId: string, payload: TPayload, metadata?: Partial<DomainEventMetadata>): DomainEvent<TPayload>;
|
|
193
193
|
|
|
@@ -196,7 +196,7 @@ declare function isDomainEvent(event: unknown): event is DomainEvent;
|
|
|
196
196
|
declare function isEvent(event: unknown): event is BaseEvent;
|
|
197
197
|
|
|
198
198
|
interface Registerable$1<TCommand extends Command, TResult = void> {
|
|
199
|
-
register(aTypeOfCommand: TCommand[
|
|
199
|
+
register(aTypeOfCommand: TCommand["type"], anHandler: CommandHandler<TCommand>): TResult;
|
|
200
200
|
}
|
|
201
201
|
interface Executable$2<TCommand extends Command, TResult = Promise<void>> {
|
|
202
202
|
execute(aCommand: TCommand): TResult;
|
|
@@ -206,7 +206,7 @@ interface CommandBus<TCommand extends Command, TExecutionResult = Promise<void>,
|
|
|
206
206
|
|
|
207
207
|
declare class SimpleCommandBus<TCommand extends Command> implements CommandBus<TCommand> {
|
|
208
208
|
private handlers;
|
|
209
|
-
register(aTypeOfCommand: TCommand[
|
|
209
|
+
register(aTypeOfCommand: TCommand["type"], anHandler: CommandHandler<TCommand>): void;
|
|
210
210
|
execute(aCommand: TCommand): Promise<void>;
|
|
211
211
|
}
|
|
212
212
|
|
|
@@ -303,7 +303,7 @@ interface OutboxEntry {
|
|
|
303
303
|
}
|
|
304
304
|
|
|
305
305
|
interface Queueable<TReturnType = Promise<void>> {
|
|
306
|
-
enqueue(event: OutboxEntry[
|
|
306
|
+
enqueue(event: OutboxEntry["event"]): TReturnType;
|
|
307
307
|
}
|
|
308
308
|
interface Outbox<TEnqueueReturnType = Promise<void>, TGetPendingReturnType = Promise<OutboxEntry[]>, TMarkAsPublishedReturnType = Promise<void>, TMarkAsFailedReturnType = Promise<void>> extends Queueable<TEnqueueReturnType> {
|
|
309
309
|
getPending(limit?: number): TGetPendingReturnType;
|
|
@@ -356,7 +356,7 @@ declare class InMemoryOutbox implements Outbox {
|
|
|
356
356
|
declare function createOutboxEntry(event: DomainEvent<unknown>): OutboxEntry;
|
|
357
357
|
|
|
358
358
|
interface Registerable<TQuery extends Query, TResult = void> {
|
|
359
|
-
register(aTypeOfQuery: TQuery[
|
|
359
|
+
register(aTypeOfQuery: TQuery["type"], anHandler: QueryHandler<TQuery>): TResult;
|
|
360
360
|
}
|
|
361
361
|
interface Executable<TQuery extends Query, TResult = Promise<unknown>> {
|
|
362
362
|
execute(aQuery: TQuery): TResult;
|
|
@@ -366,7 +366,7 @@ interface QueryBus<TQuery extends Query, TExecutionResult, TRegisterResult = voi
|
|
|
366
366
|
|
|
367
367
|
declare class SimpleQueryBus<TQuery extends Query, TProjection> implements QueryBus<TQuery, Promise<TProjection>> {
|
|
368
368
|
private handlers;
|
|
369
|
-
register(aTypeOfQuery: TQuery[
|
|
369
|
+
register(aTypeOfQuery: TQuery["type"], anHandler: QueryHandler<TQuery, Promise<TProjection>>): void;
|
|
370
370
|
execute(aQuery: TQuery): Promise<TProjection>;
|
|
371
371
|
}
|
|
372
372
|
|
|
@@ -375,7 +375,7 @@ declare class SimpleRepository<TState, TCommand, TEvent extends DomainEvent> imp
|
|
|
375
375
|
readonly streamName: string;
|
|
376
376
|
private readonly evolveFn;
|
|
377
377
|
private readonly initialState;
|
|
378
|
-
constructor(eventStore: EventStore<TEvent, Promise<void>, Promise<TEvent[]>>, streamName: string, evolveFn: Decider<TState, TCommand, TEvent>[
|
|
378
|
+
constructor(eventStore: EventStore<TEvent, Promise<void>, Promise<TEvent[]>>, streamName: string, evolveFn: Decider<TState, TCommand, TEvent>["evolve"], initialState: Decider<TState, TCommand, TEvent>["initialState"]);
|
|
379
379
|
load(aggregateId: string): Promise<TState>;
|
|
380
380
|
store(events: TEvent[]): Promise<void>;
|
|
381
381
|
}
|
|
@@ -394,14 +394,14 @@ declare class ScenarioTest<TState, TEvent extends DomainEvent> {
|
|
|
394
394
|
private givenInput;
|
|
395
395
|
private whenInput;
|
|
396
396
|
constructor(streamName: string, eventBus: EventProducer<BaseEvent> & EventConsumer<BaseEvent>, eventStore: EventStore<TEvent, Promise<void>, Promise<TEvent[]>>, commandBus: CommandBus<Command>, queryBus: QueryBus<Query, Promise<Record<string, unknown>[]>>, repository: Repository<DomainEvent, Promise<TState>>, outboxWorker: OutboxWorker);
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
397
|
+
Given(...events: GivenInput): {
|
|
398
|
+
When(action: WhenInput): ReturnType<ScenarioTest<TState, TEvent>["When"]>;
|
|
399
|
+
Then(outcome: ThenInput): Promise<void>;
|
|
400
400
|
};
|
|
401
|
-
|
|
402
|
-
|
|
401
|
+
When(action: WhenInput): {
|
|
402
|
+
Then(outcome: ThenInput): Promise<void>;
|
|
403
403
|
};
|
|
404
|
-
|
|
404
|
+
Then(thenInput: ThenInput): Promise<void>;
|
|
405
405
|
private handleCommand;
|
|
406
406
|
private handleQuery;
|
|
407
407
|
private handleEvent;
|
|
@@ -11,7 +11,7 @@ interface Command<TType = string, TPayload = unknown> extends WithIdentifier {
|
|
|
11
11
|
type: TType;
|
|
12
12
|
aggregateId: string;
|
|
13
13
|
payload: TPayload;
|
|
14
|
-
kind:
|
|
14
|
+
kind: "command";
|
|
15
15
|
timestamp: string;
|
|
16
16
|
metadata: Partial<CommandMetadata>;
|
|
17
17
|
}
|
|
@@ -28,7 +28,7 @@ interface IntegrationEventMetadata {
|
|
|
28
28
|
interface IntegrationEvent<TPayload = unknown> {
|
|
29
29
|
id: string;
|
|
30
30
|
type: string;
|
|
31
|
-
source:
|
|
31
|
+
source: "external";
|
|
32
32
|
payload: TPayload;
|
|
33
33
|
timestamp: string;
|
|
34
34
|
metadata: {} & Partial<IntegrationEventMetadata>;
|
|
@@ -43,7 +43,7 @@ interface DomainEvent<TPayload = unknown> {
|
|
|
43
43
|
id: string;
|
|
44
44
|
type: string;
|
|
45
45
|
aggregateId: string;
|
|
46
|
-
source:
|
|
46
|
+
source: "internal";
|
|
47
47
|
payload: TPayload;
|
|
48
48
|
timestamp: string;
|
|
49
49
|
metadata: Partial<DomainEventMetadata>;
|
|
@@ -65,7 +65,7 @@ interface QueryMetadata {
|
|
|
65
65
|
interface Query<TType = string, TPayload = unknown> extends WithIdentifier {
|
|
66
66
|
type: TType;
|
|
67
67
|
payload: TPayload;
|
|
68
|
-
kind:
|
|
68
|
+
kind: "query";
|
|
69
69
|
timestamp: string;
|
|
70
70
|
metadata: Partial<QueryMetadata>;
|
|
71
71
|
}
|
|
@@ -129,14 +129,14 @@ interface Repository<TEvent, TLoadReturnType, TStoreReturnType = Promise<void>>
|
|
|
129
129
|
}
|
|
130
130
|
|
|
131
131
|
type QueryNode = {
|
|
132
|
-
type:
|
|
132
|
+
type: "eq" | "gt" | "lt";
|
|
133
133
|
field: string | number | symbol;
|
|
134
134
|
value: Primitive;
|
|
135
135
|
} | {
|
|
136
|
-
type:
|
|
136
|
+
type: "and" | "or";
|
|
137
137
|
nodes: QueryNode[];
|
|
138
138
|
} | {
|
|
139
|
-
type:
|
|
139
|
+
type: "not";
|
|
140
140
|
node: QueryNode;
|
|
141
141
|
};
|
|
142
142
|
|
|
@@ -185,9 +185,9 @@ declare class FieldGreaterThan<T> extends Specification<T> {
|
|
|
185
185
|
toQuery(): QueryNode;
|
|
186
186
|
}
|
|
187
187
|
|
|
188
|
-
declare function createQueryNode(type:
|
|
189
|
-
declare function createQueryNode(type:
|
|
190
|
-
declare function createQueryNode(type:
|
|
188
|
+
declare function createQueryNode(type: "eq" | "gt" | "lt", field: string | number | symbol, value: Primitive): QueryNode;
|
|
189
|
+
declare function createQueryNode(type: "and" | "or", field: undefined, value: QueryNode[]): QueryNode;
|
|
190
|
+
declare function createQueryNode(type: "not", field: undefined, value: QueryNode): QueryNode;
|
|
191
191
|
|
|
192
192
|
declare function createDomainEvent<TPayload = unknown>(type: string, aggregateId: string, payload: TPayload, metadata?: Partial<DomainEventMetadata>): DomainEvent<TPayload>;
|
|
193
193
|
|
|
@@ -196,7 +196,7 @@ declare function isDomainEvent(event: unknown): event is DomainEvent;
|
|
|
196
196
|
declare function isEvent(event: unknown): event is BaseEvent;
|
|
197
197
|
|
|
198
198
|
interface Registerable$1<TCommand extends Command, TResult = void> {
|
|
199
|
-
register(aTypeOfCommand: TCommand[
|
|
199
|
+
register(aTypeOfCommand: TCommand["type"], anHandler: CommandHandler<TCommand>): TResult;
|
|
200
200
|
}
|
|
201
201
|
interface Executable$2<TCommand extends Command, TResult = Promise<void>> {
|
|
202
202
|
execute(aCommand: TCommand): TResult;
|
|
@@ -206,7 +206,7 @@ interface CommandBus<TCommand extends Command, TExecutionResult = Promise<void>,
|
|
|
206
206
|
|
|
207
207
|
declare class SimpleCommandBus<TCommand extends Command> implements CommandBus<TCommand> {
|
|
208
208
|
private handlers;
|
|
209
|
-
register(aTypeOfCommand: TCommand[
|
|
209
|
+
register(aTypeOfCommand: TCommand["type"], anHandler: CommandHandler<TCommand>): void;
|
|
210
210
|
execute(aCommand: TCommand): Promise<void>;
|
|
211
211
|
}
|
|
212
212
|
|
|
@@ -303,7 +303,7 @@ interface OutboxEntry {
|
|
|
303
303
|
}
|
|
304
304
|
|
|
305
305
|
interface Queueable<TReturnType = Promise<void>> {
|
|
306
|
-
enqueue(event: OutboxEntry[
|
|
306
|
+
enqueue(event: OutboxEntry["event"]): TReturnType;
|
|
307
307
|
}
|
|
308
308
|
interface Outbox<TEnqueueReturnType = Promise<void>, TGetPendingReturnType = Promise<OutboxEntry[]>, TMarkAsPublishedReturnType = Promise<void>, TMarkAsFailedReturnType = Promise<void>> extends Queueable<TEnqueueReturnType> {
|
|
309
309
|
getPending(limit?: number): TGetPendingReturnType;
|
|
@@ -356,7 +356,7 @@ declare class InMemoryOutbox implements Outbox {
|
|
|
356
356
|
declare function createOutboxEntry(event: DomainEvent<unknown>): OutboxEntry;
|
|
357
357
|
|
|
358
358
|
interface Registerable<TQuery extends Query, TResult = void> {
|
|
359
|
-
register(aTypeOfQuery: TQuery[
|
|
359
|
+
register(aTypeOfQuery: TQuery["type"], anHandler: QueryHandler<TQuery>): TResult;
|
|
360
360
|
}
|
|
361
361
|
interface Executable<TQuery extends Query, TResult = Promise<unknown>> {
|
|
362
362
|
execute(aQuery: TQuery): TResult;
|
|
@@ -366,7 +366,7 @@ interface QueryBus<TQuery extends Query, TExecutionResult, TRegisterResult = voi
|
|
|
366
366
|
|
|
367
367
|
declare class SimpleQueryBus<TQuery extends Query, TProjection> implements QueryBus<TQuery, Promise<TProjection>> {
|
|
368
368
|
private handlers;
|
|
369
|
-
register(aTypeOfQuery: TQuery[
|
|
369
|
+
register(aTypeOfQuery: TQuery["type"], anHandler: QueryHandler<TQuery, Promise<TProjection>>): void;
|
|
370
370
|
execute(aQuery: TQuery): Promise<TProjection>;
|
|
371
371
|
}
|
|
372
372
|
|
|
@@ -375,7 +375,7 @@ declare class SimpleRepository<TState, TCommand, TEvent extends DomainEvent> imp
|
|
|
375
375
|
readonly streamName: string;
|
|
376
376
|
private readonly evolveFn;
|
|
377
377
|
private readonly initialState;
|
|
378
|
-
constructor(eventStore: EventStore<TEvent, Promise<void>, Promise<TEvent[]>>, streamName: string, evolveFn: Decider<TState, TCommand, TEvent>[
|
|
378
|
+
constructor(eventStore: EventStore<TEvent, Promise<void>, Promise<TEvent[]>>, streamName: string, evolveFn: Decider<TState, TCommand, TEvent>["evolve"], initialState: Decider<TState, TCommand, TEvent>["initialState"]);
|
|
379
379
|
load(aggregateId: string): Promise<TState>;
|
|
380
380
|
store(events: TEvent[]): Promise<void>;
|
|
381
381
|
}
|
|
@@ -394,14 +394,14 @@ declare class ScenarioTest<TState, TEvent extends DomainEvent> {
|
|
|
394
394
|
private givenInput;
|
|
395
395
|
private whenInput;
|
|
396
396
|
constructor(streamName: string, eventBus: EventProducer<BaseEvent> & EventConsumer<BaseEvent>, eventStore: EventStore<TEvent, Promise<void>, Promise<TEvent[]>>, commandBus: CommandBus<Command>, queryBus: QueryBus<Query, Promise<Record<string, unknown>[]>>, repository: Repository<DomainEvent, Promise<TState>>, outboxWorker: OutboxWorker);
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
397
|
+
Given(...events: GivenInput): {
|
|
398
|
+
When(action: WhenInput): ReturnType<ScenarioTest<TState, TEvent>["When"]>;
|
|
399
|
+
Then(outcome: ThenInput): Promise<void>;
|
|
400
400
|
};
|
|
401
|
-
|
|
402
|
-
|
|
401
|
+
When(action: WhenInput): {
|
|
402
|
+
Then(outcome: ThenInput): Promise<void>;
|
|
403
403
|
};
|
|
404
|
-
|
|
404
|
+
Then(thenInput: ThenInput): Promise<void>;
|
|
405
405
|
private handleCommand;
|
|
406
406
|
private handleQuery;
|
|
407
407
|
private handleEvent;
|
|
@@ -25,23 +25,17 @@ function createQuery(type, payload, metadata = {}) {
|
|
|
25
25
|
|
|
26
26
|
// src/core/utils/isCommand.ts
|
|
27
27
|
function isCommand(candidate) {
|
|
28
|
-
if (candidate === null)
|
|
29
|
-
|
|
30
|
-
if (
|
|
31
|
-
return false;
|
|
32
|
-
if (!("type" in candidate))
|
|
33
|
-
return false;
|
|
28
|
+
if (candidate === null) return false;
|
|
29
|
+
if (typeof candidate !== "object") return false;
|
|
30
|
+
if (!("type" in candidate)) return false;
|
|
34
31
|
return "kind" in candidate && candidate.kind === "command";
|
|
35
32
|
}
|
|
36
33
|
|
|
37
34
|
// src/core/utils/isQuery.ts
|
|
38
35
|
function isQuery(candidate) {
|
|
39
|
-
if (candidate === null)
|
|
40
|
-
|
|
41
|
-
if (
|
|
42
|
-
return false;
|
|
43
|
-
if (!("type" in candidate))
|
|
44
|
-
return false;
|
|
36
|
+
if (candidate === null) return false;
|
|
37
|
+
if (typeof candidate !== "object") return false;
|
|
38
|
+
if (!("type" in candidate)) return false;
|
|
45
39
|
return "kind" in candidate && candidate.kind === "query";
|
|
46
40
|
}
|
|
47
41
|
|
|
@@ -144,8 +138,7 @@ function fail(anExpression) {
|
|
|
144
138
|
|
|
145
139
|
// src/utils/invariant/invariant.ts
|
|
146
140
|
function invariant(condition, onInvalid) {
|
|
147
|
-
if (!condition)
|
|
148
|
-
onInvalid();
|
|
141
|
+
if (!condition) onInvalid();
|
|
149
142
|
}
|
|
150
143
|
|
|
151
144
|
// src/domain/Specification/implementations/FieldGreaterThan.specification.ts
|
|
@@ -162,9 +155,7 @@ var FieldGreaterThan = class extends Specification {
|
|
|
162
155
|
const field = entity[this.field];
|
|
163
156
|
invariant(
|
|
164
157
|
this.isNumber(field),
|
|
165
|
-
fail(
|
|
166
|
-
new TypeError(`Field ${String(this.field)} is not a number`)
|
|
167
|
-
)
|
|
158
|
+
fail(new TypeError(`Field ${String(this.field)} is not a number`))
|
|
168
159
|
);
|
|
169
160
|
return field > this.value;
|
|
170
161
|
}
|
|
@@ -186,12 +177,9 @@ function createDomainEvent(type, aggregateId, payload, metadata = {}) {
|
|
|
186
177
|
|
|
187
178
|
// src/domain/utils/isEvent.ts
|
|
188
179
|
function isEvent(event) {
|
|
189
|
-
if (typeof event !== "object")
|
|
190
|
-
|
|
191
|
-
if (event
|
|
192
|
-
return false;
|
|
193
|
-
if (!("type" in event))
|
|
194
|
-
return false;
|
|
180
|
+
if (typeof event !== "object") return false;
|
|
181
|
+
if (event === null) return false;
|
|
182
|
+
if (!("type" in event)) return false;
|
|
195
183
|
return "source" in event;
|
|
196
184
|
}
|
|
197
185
|
|
|
@@ -249,43 +237,36 @@ var SimpleDatabase = class {
|
|
|
249
237
|
datasource = /* @__PURE__ */ new Map();
|
|
250
238
|
simulateOffline = false;
|
|
251
239
|
async query(tableName, specification) {
|
|
252
|
-
if (this.simulateOffline)
|
|
253
|
-
throw new DatabaseOfflineException();
|
|
240
|
+
if (this.simulateOffline) throw new DatabaseOfflineException();
|
|
254
241
|
const tableRecords = this.datasource.get(tableName) || [];
|
|
255
242
|
return tableRecords.filter((record) => specification.isSatisfiedBy(record));
|
|
256
243
|
}
|
|
257
244
|
async execute(tableName, statement) {
|
|
258
|
-
if (this.simulateOffline)
|
|
259
|
-
|
|
260
|
-
if (!this.datasource.has(tableName))
|
|
261
|
-
this.datasource.set(tableName, []);
|
|
245
|
+
if (this.simulateOffline) throw new DatabaseOfflineException();
|
|
246
|
+
if (!this.datasource.has(tableName)) this.datasource.set(tableName, []);
|
|
262
247
|
const table = this.datasource.get(tableName);
|
|
263
248
|
switch (statement.operation) {
|
|
264
249
|
case "CREATE" /* CREATE */: {
|
|
265
250
|
const isDuplicate = table.some((item) => item.id === statement.payload.id);
|
|
266
|
-
if (isDuplicate)
|
|
267
|
-
throw new DuplicateRecordException(statement.payload.id);
|
|
251
|
+
if (isDuplicate) throw new DuplicateRecordException(statement.payload.id);
|
|
268
252
|
table.push(statement.payload);
|
|
269
253
|
break;
|
|
270
254
|
}
|
|
271
255
|
case "PUT" /* PUT */: {
|
|
272
256
|
const index = table.findIndex((item) => item.id === statement.payload.id);
|
|
273
|
-
if (index === -1)
|
|
274
|
-
throw new RecordNotFoundException(statement.payload.id);
|
|
257
|
+
if (index === -1) throw new RecordNotFoundException(statement.payload.id);
|
|
275
258
|
table[index] = statement.payload;
|
|
276
259
|
break;
|
|
277
260
|
}
|
|
278
261
|
case "PATCH" /* PATCH */: {
|
|
279
262
|
const index = table.findIndex((item) => item.id === statement.payload.id);
|
|
280
|
-
if (index === -1)
|
|
281
|
-
throw new RecordNotFoundException(statement.payload.id);
|
|
263
|
+
if (index === -1) throw new RecordNotFoundException(statement.payload.id);
|
|
282
264
|
table[index] = { ...table[index], ...statement.payload };
|
|
283
265
|
break;
|
|
284
266
|
}
|
|
285
267
|
case "DELETE" /* DELETE */: {
|
|
286
268
|
const index = table.findIndex((item) => item.id === statement.payload.id);
|
|
287
|
-
if (index === -1)
|
|
288
|
-
throw new RecordNotFoundException(statement.payload.id);
|
|
269
|
+
if (index === -1) throw new RecordNotFoundException(statement.payload.id);
|
|
289
270
|
table.splice(index, 1);
|
|
290
271
|
break;
|
|
291
272
|
}
|
|
@@ -305,12 +286,13 @@ var SimpleEventBus = class {
|
|
|
305
286
|
this.handlers.set(stream, handlersForType);
|
|
306
287
|
}
|
|
307
288
|
async consume(stream, anEvent) {
|
|
308
|
-
if (!this.handlers.has(stream))
|
|
309
|
-
return;
|
|
289
|
+
if (!this.handlers.has(stream)) return;
|
|
310
290
|
const handlers = this.handlers.get(stream);
|
|
311
|
-
await Promise.all(
|
|
312
|
-
|
|
313
|
-
|
|
291
|
+
await Promise.all(
|
|
292
|
+
handlers.map(async (handler) => {
|
|
293
|
+
return handler.handle(anEvent);
|
|
294
|
+
})
|
|
295
|
+
);
|
|
314
296
|
}
|
|
315
297
|
async publish(stream, anEvent) {
|
|
316
298
|
await this.consume(stream, anEvent);
|
|
@@ -372,11 +354,12 @@ var SimpleEventStore = class {
|
|
|
372
354
|
}
|
|
373
355
|
async append(streamName, events) {
|
|
374
356
|
const uniqueAggregateIds = new Set(events.map((event2) => event2.aggregateId));
|
|
375
|
-
if (uniqueAggregateIds.size > 1)
|
|
376
|
-
throw new MultipleAggregatesException();
|
|
357
|
+
if (uniqueAggregateIds.size > 1) throw new MultipleAggregatesException();
|
|
377
358
|
const event = events[0];
|
|
378
359
|
const currentStream = await this.load(streamName, event.aggregateId);
|
|
379
|
-
const eventsToStore = events.map(
|
|
360
|
+
const eventsToStore = events.map(
|
|
361
|
+
(event2) => createStoredEvent(streamName, currentStream.length + 1, event2)
|
|
362
|
+
);
|
|
380
363
|
await Promise.all(
|
|
381
364
|
eventsToStore.map(
|
|
382
365
|
async (payload) => this.database.execute(this.tableName, { operation: "CREATE" /* CREATE */, payload })
|
|
@@ -395,14 +378,16 @@ var GenericOutboxWorker = class {
|
|
|
395
378
|
}
|
|
396
379
|
async runOnce() {
|
|
397
380
|
const pending = await this.outbox.getPending();
|
|
398
|
-
await Promise.all(
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
381
|
+
await Promise.all(
|
|
382
|
+
pending.map(async (entry) => {
|
|
383
|
+
try {
|
|
384
|
+
await this.eventBus.publish(this.stream, entry.event);
|
|
385
|
+
await this.outbox.markAsPublished(entry.id);
|
|
386
|
+
} catch {
|
|
387
|
+
await this.outbox.markAsFailed(entry.id);
|
|
388
|
+
}
|
|
389
|
+
})
|
|
390
|
+
);
|
|
406
391
|
}
|
|
407
392
|
async tick() {
|
|
408
393
|
await this.runOnce();
|
|
@@ -485,12 +470,7 @@ var SimpleRepository = class {
|
|
|
485
470
|
}
|
|
486
471
|
async store(events) {
|
|
487
472
|
await Promise.all(
|
|
488
|
-
events.map(
|
|
489
|
-
async (event) => this.eventStore.append(
|
|
490
|
-
this.streamName,
|
|
491
|
-
[event]
|
|
492
|
-
)
|
|
493
|
-
)
|
|
473
|
+
events.map(async (event) => this.eventStore.append(this.streamName, [event]))
|
|
494
474
|
);
|
|
495
475
|
}
|
|
496
476
|
};
|
|
@@ -519,20 +499,20 @@ var ScenarioTest = class {
|
|
|
519
499
|
}
|
|
520
500
|
givenInput = [];
|
|
521
501
|
whenInput;
|
|
522
|
-
|
|
502
|
+
Given(...events) {
|
|
523
503
|
this.givenInput = events;
|
|
524
504
|
return {
|
|
525
|
-
|
|
526
|
-
|
|
505
|
+
When: this.When.bind(this),
|
|
506
|
+
Then: this.Then.bind(this)
|
|
527
507
|
};
|
|
528
508
|
}
|
|
529
|
-
|
|
509
|
+
When(action) {
|
|
530
510
|
this.whenInput = action;
|
|
531
511
|
return {
|
|
532
|
-
|
|
512
|
+
Then: this.Then.bind(this)
|
|
533
513
|
};
|
|
534
514
|
}
|
|
535
|
-
async
|
|
515
|
+
async Then(thenInput) {
|
|
536
516
|
const domainEvents = this.givenInput.filter(isDomainEvent);
|
|
537
517
|
const integrationEvents = this.givenInput.filter(isIntegrationEvent);
|
|
538
518
|
await Promise.all([
|
|
@@ -543,15 +523,28 @@ var ScenarioTest = class {
|
|
|
543
523
|
throw new Error("In the ScenarioTest, the when-step cannot be empty");
|
|
544
524
|
}
|
|
545
525
|
if (isCommand(this.whenInput)) {
|
|
546
|
-
invariant(
|
|
526
|
+
invariant(
|
|
527
|
+
isDomainEvent(thenInput),
|
|
528
|
+
fail(new TypeError('When "command" expects a domain event in the then-step'))
|
|
529
|
+
);
|
|
547
530
|
await this.handleCommand(this.whenInput, thenInput);
|
|
548
531
|
}
|
|
549
532
|
if (isQuery(this.whenInput)) {
|
|
550
|
-
invariant(
|
|
533
|
+
invariant(
|
|
534
|
+
Array.isArray(thenInput),
|
|
535
|
+
fail(new TypeError('When "query" expects an array of expected results in the then-step'))
|
|
536
|
+
);
|
|
551
537
|
await this.handleQuery(this.whenInput, thenInput);
|
|
552
538
|
}
|
|
553
539
|
if (isDomainEvent(this.whenInput) || isIntegrationEvent(this.whenInput)) {
|
|
554
|
-
invariant(
|
|
540
|
+
invariant(
|
|
541
|
+
isDomainEvent(thenInput),
|
|
542
|
+
fail(
|
|
543
|
+
new TypeError(
|
|
544
|
+
'When "domain event" or "integration event" expects a domain event in the then-step'
|
|
545
|
+
)
|
|
546
|
+
)
|
|
547
|
+
);
|
|
555
548
|
await this.handleEvent(this.whenInput, thenInput);
|
|
556
549
|
}
|
|
557
550
|
}
|
|
@@ -608,10 +601,8 @@ var ScenarioTest = class {
|
|
|
608
601
|
|
|
609
602
|
// src/utils/parseAsError/parseAsError.ts
|
|
610
603
|
function parseAsError(value) {
|
|
611
|
-
if (value instanceof Error)
|
|
612
|
-
|
|
613
|
-
if (typeof value === "string")
|
|
614
|
-
return new Error(value);
|
|
604
|
+
if (value instanceof Error) return value;
|
|
605
|
+
if (typeof value === "string") return new Error(value);
|
|
615
606
|
try {
|
|
616
607
|
const json = JSON.stringify(value);
|
|
617
608
|
return new Error(json ?? String(value));
|