@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
|
@@ -44,7 +44,7 @@ interface Command<TType = string, TPayload = unknown> extends WithIdentifier {
|
|
|
44
44
|
/** Optional metadata. */
|
|
45
45
|
metadata?: Partial<CommandMetadata>;
|
|
46
46
|
/** Discriminator for the message intent. */
|
|
47
|
-
kind:
|
|
47
|
+
kind: "command";
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
interface CommandHandler<CommandType extends Command, TReturnType = Promise<void>> {
|
|
@@ -81,7 +81,7 @@ interface DomainEvent<TPayload = unknown> {
|
|
|
81
81
|
/** Optional metadata; keep it small and stable. */
|
|
82
82
|
metadata: Partial<DomainEventMetadata>;
|
|
83
83
|
/** Discriminator for the message intent. */
|
|
84
|
-
kind:
|
|
84
|
+
kind: "domain";
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
/**
|
|
@@ -108,7 +108,7 @@ interface ExternalEvent<TPayload = unknown> {
|
|
|
108
108
|
/** Optional metadata from the producer. */
|
|
109
109
|
metadata?: Partial<ExternalEventMetadata>;
|
|
110
110
|
/** Discriminator for the message intent. */
|
|
111
|
-
kind:
|
|
111
|
+
kind: "external";
|
|
112
112
|
}
|
|
113
113
|
|
|
114
114
|
/**
|
|
@@ -118,7 +118,7 @@ interface ExternalEvent<TPayload = unknown> {
|
|
|
118
118
|
*/
|
|
119
119
|
interface IntegrationEventMetadata extends BaseMetadata {
|
|
120
120
|
/** Outcome of the decision. */
|
|
121
|
-
outcome?:
|
|
121
|
+
outcome?: "accepted" | "rejected";
|
|
122
122
|
/** Correlation and routing fields. */
|
|
123
123
|
aggregateType?: string;
|
|
124
124
|
aggregateId?: string;
|
|
@@ -139,7 +139,7 @@ interface IntegrationEvent<TPayload = unknown> {
|
|
|
139
139
|
/** Standardized, extensible metadata. */
|
|
140
140
|
metadata: Partial<IntegrationEventMetadata>;
|
|
141
141
|
/** Discriminator for the message intent. */
|
|
142
|
-
kind:
|
|
142
|
+
kind: "integration";
|
|
143
143
|
}
|
|
144
144
|
|
|
145
145
|
interface Handling<TEvent extends DomainEvent | IntegrationEvent | ExternalEvent, TReturnType> {
|
|
@@ -156,7 +156,7 @@ interface Query<TType = string, TPayload = unknown> extends WithIdentifier {
|
|
|
156
156
|
timestamp: number;
|
|
157
157
|
metadata: Partial<QueryMetadata>;
|
|
158
158
|
/** Discriminator for the message intent. */
|
|
159
|
-
kind:
|
|
159
|
+
kind: "query";
|
|
160
160
|
}
|
|
161
161
|
|
|
162
162
|
interface QueryHandler<TQuery extends Query, TProjection = Promise<unknown>> {
|
|
@@ -235,17 +235,17 @@ interface Rejection<TDetails = object> {
|
|
|
235
235
|
/** Rejection type, format e.g., "{commandType}Rejected", "{commandType}Failed". Example "CreateUserRejected" */
|
|
236
236
|
type: string;
|
|
237
237
|
/** Discriminator for the message intent. */
|
|
238
|
-
kind:
|
|
238
|
+
kind: "rejection";
|
|
239
239
|
/** The command that was rejected. */
|
|
240
240
|
commandId: string;
|
|
241
241
|
/** The command type, e.g., "CreateOrder". */
|
|
242
242
|
commandType: string;
|
|
243
243
|
/** Short machine-readable code, e.g., "VERSION_CONFLICT", "VALIDATION_FAILED". */
|
|
244
|
-
reasonCode: string |
|
|
244
|
+
reasonCode: string | "VERSION_CONFLICT" | "VALIDATION_FAILED";
|
|
245
245
|
/** Human-readable summary (avoid PII if externalized). */
|
|
246
246
|
reason?: string;
|
|
247
247
|
/** Classification for routing/metrics. */
|
|
248
|
-
classification?:
|
|
248
|
+
classification?: "business" | "validation" | "concurrency" | "technical";
|
|
249
249
|
/** Hint to infra/ops whether retry makes sense. */
|
|
250
250
|
retryable?: boolean;
|
|
251
251
|
/** Structured details specific to this rejection. */
|
|
@@ -281,14 +281,14 @@ interface Repository<TEvent, TLoadReturnType, TStoreReturnType = Promise<void>>
|
|
|
281
281
|
}
|
|
282
282
|
|
|
283
283
|
type QueryNode = {
|
|
284
|
-
type:
|
|
284
|
+
type: "eq" | "gt" | "lt";
|
|
285
285
|
field: string | number | symbol;
|
|
286
286
|
value: Primitive;
|
|
287
287
|
} | {
|
|
288
|
-
type:
|
|
288
|
+
type: "and" | "or";
|
|
289
289
|
nodes: QueryNode[];
|
|
290
290
|
} | {
|
|
291
|
-
type:
|
|
291
|
+
type: "not";
|
|
292
292
|
node: QueryNode;
|
|
293
293
|
};
|
|
294
294
|
|
|
@@ -340,9 +340,9 @@ declare class FieldGreaterThan<T> extends CompositeSpecification<T> {
|
|
|
340
340
|
toQuery(): QueryNode;
|
|
341
341
|
}
|
|
342
342
|
|
|
343
|
-
declare function createQueryNode(type:
|
|
344
|
-
declare function createQueryNode(type:
|
|
345
|
-
declare function createQueryNode(type:
|
|
343
|
+
declare function createQueryNode(type: "eq" | "gt" | "lt", field: string | number | symbol, value: Primitive): QueryNode;
|
|
344
|
+
declare function createQueryNode(type: "and" | "or", field: undefined, value: QueryNode[]): QueryNode;
|
|
345
|
+
declare function createQueryNode(type: "not", field: undefined, value: QueryNode): QueryNode;
|
|
346
346
|
|
|
347
347
|
declare function convertDomainEventToIntegrationEvent(event: DomainEvent): IntegrationEvent;
|
|
348
348
|
|
|
@@ -351,14 +351,14 @@ declare function convertRejectionToIntegrationEvent(rejection: Rejection): Integ
|
|
|
351
351
|
declare function createDomainEvent<TPayload = unknown>(type: string, aggregateId: string, aggregateType: string, payload: TPayload, metadata?: Partial<DomainEventMetadata>): DomainEvent<TPayload>;
|
|
352
352
|
|
|
353
353
|
declare function createRejection<TDetails = unknown>(rejectionSpecifics: {
|
|
354
|
-
commandId: Rejection[
|
|
355
|
-
commandType: Rejection[
|
|
356
|
-
reasonCode: Rejection[
|
|
357
|
-
reason?: Rejection[
|
|
358
|
-
classification: Rejection[
|
|
359
|
-
retryable?: Rejection[
|
|
360
|
-
validationErrors?: Rejection[
|
|
361
|
-
type:
|
|
354
|
+
commandId: Rejection["commandId"];
|
|
355
|
+
commandType: Rejection["commandType"];
|
|
356
|
+
reasonCode: Rejection["reasonCode"];
|
|
357
|
+
reason?: Rejection["reason"];
|
|
358
|
+
classification: Rejection["classification"];
|
|
359
|
+
retryable?: Rejection["retryable"];
|
|
360
|
+
validationErrors?: Rejection["validationErrors"];
|
|
361
|
+
type: "Failed" | "Rejected" | string;
|
|
362
362
|
details?: TDetails;
|
|
363
363
|
}, metadata?: Partial<RejectionMetadata>): Rejection<TDetails>;
|
|
364
364
|
|
|
@@ -369,7 +369,7 @@ declare function isEvent(event: unknown): event is DomainEvent | IntegrationEven
|
|
|
369
369
|
declare function isRejection(candidate: unknown): candidate is Rejection;
|
|
370
370
|
|
|
371
371
|
interface Registerable$1<TCommand extends Command, TResult = void> {
|
|
372
|
-
register(aTypeOfCommand: TCommand[
|
|
372
|
+
register(aTypeOfCommand: TCommand["type"], anHandler: CommandHandler<TCommand>): TResult;
|
|
373
373
|
}
|
|
374
374
|
interface Executable$3<TCommand extends Command, TResult = Promise<void>> {
|
|
375
375
|
execute(aCommand: TCommand): TResult;
|
|
@@ -379,7 +379,7 @@ interface CommandBus<TCommand extends Command, TExecutionResult = Promise<void>,
|
|
|
379
379
|
|
|
380
380
|
declare class SimpleCommandBus<TCommand extends Command> implements CommandBus<TCommand> {
|
|
381
381
|
private handlers;
|
|
382
|
-
register(aTypeOfCommand: TCommand[
|
|
382
|
+
register(aTypeOfCommand: TCommand["type"], anHandler: CommandHandler<TCommand>): void;
|
|
383
383
|
execute(aCommand: TCommand): Promise<void>;
|
|
384
384
|
}
|
|
385
385
|
|
|
@@ -452,23 +452,12 @@ declare class SimpleEventBus<TEvent extends DomainEvent | IntegrationEvent | Ext
|
|
|
452
452
|
|
|
453
453
|
declare function createExternalEvent<TPayload = unknown>(type: string, payload: TPayload, metadata?: Partial<ExternalEventMetadata>): ExternalEvent<TPayload>;
|
|
454
454
|
|
|
455
|
-
declare function createIntegrationEvent<TPayload = unknown>(type: string, payload: TPayload, metadata?: Partial<IntegrationEventMetadata
|
|
455
|
+
declare function createIntegrationEvent<TPayload = unknown>(type: string, payload: TPayload, metadata?: Partial<IntegrationEventMetadata>, timestamp?: string): IntegrationEvent<TPayload>;
|
|
456
456
|
|
|
457
457
|
declare function isExternalEvent<TPayload>(event: unknown): event is ExternalEvent<TPayload>;
|
|
458
458
|
|
|
459
459
|
declare function isIntegrationEvent<TPayload>(event: unknown): event is IntegrationEvent<TPayload>;
|
|
460
460
|
|
|
461
|
-
declare function mapDomainEventToIntegrationEvent<TPayload>(domainEvent: DomainEvent<TPayload>): IntegrationEvent<TPayload>;
|
|
462
|
-
|
|
463
|
-
declare function mapRejectionToIntegrationEvent<TDetails>(rejection: Rejection<TDetails>): IntegrationEvent<{
|
|
464
|
-
reasonCode: Rejection<TDetails>['reasonCode'];
|
|
465
|
-
reason?: string;
|
|
466
|
-
classification?: Rejection<TDetails>['classification'];
|
|
467
|
-
retryable?: boolean;
|
|
468
|
-
details?: TDetails;
|
|
469
|
-
validationErrors?: Rejection<TDetails>['validationErrors'];
|
|
470
|
-
}>;
|
|
471
|
-
|
|
472
461
|
type StreamKey = `${string}#${string}`;
|
|
473
462
|
|
|
474
463
|
/**
|
|
@@ -559,7 +548,7 @@ declare class InMemoryOutbox implements Outbox {
|
|
|
559
548
|
declare function createOutboxEntry(event: IntegrationEvent): OutboxEntry;
|
|
560
549
|
|
|
561
550
|
interface Registerable<TQuery extends Query, TResult = void> {
|
|
562
|
-
register(aTypeOfQuery: TQuery[
|
|
551
|
+
register(aTypeOfQuery: TQuery["type"], anHandler: QueryHandler<TQuery>): TResult;
|
|
563
552
|
}
|
|
564
553
|
interface Executable<TQuery extends Query, TResult = Promise<unknown>> {
|
|
565
554
|
execute(aQuery: TQuery): TResult;
|
|
@@ -569,7 +558,7 @@ interface QueryBus<TQuery extends Query, TExecutionResult, TRegisterResult = voi
|
|
|
569
558
|
|
|
570
559
|
declare class SimpleQueryBus<TQuery extends Query, TProjection> implements QueryBus<TQuery, Promise<TProjection>> {
|
|
571
560
|
private handlers;
|
|
572
|
-
register(aTypeOfQuery: TQuery[
|
|
561
|
+
register(aTypeOfQuery: TQuery["type"], anHandler: QueryHandler<TQuery, Promise<TProjection>>): void;
|
|
573
562
|
execute(aQuery: TQuery): Promise<TProjection>;
|
|
574
563
|
}
|
|
575
564
|
|
|
@@ -578,7 +567,7 @@ declare class SimpleRepository<TState, TCommand, TEvent extends DomainEvent> imp
|
|
|
578
567
|
readonly streamName: string;
|
|
579
568
|
private readonly evolveFn;
|
|
580
569
|
private readonly initialState;
|
|
581
|
-
constructor(eventStore: EventStore<TEvent, Promise<void>, Promise<TEvent[]>>, streamName: string, evolveFn: Decider<TState, TCommand, TEvent>[
|
|
570
|
+
constructor(eventStore: EventStore<TEvent, Promise<void>, Promise<TEvent[]>>, streamName: string, evolveFn: Decider<TState, TCommand, TEvent>["evolve"], initialState: Decider<TState, TCommand, TEvent>["initialState"]);
|
|
582
571
|
load(aggregateId: string): Promise<TState>;
|
|
583
572
|
store(events: TEvent[]): Promise<void>;
|
|
584
573
|
}
|
|
@@ -598,14 +587,14 @@ declare class ScenarioTest<TState, TEvent extends DomainEvent> {
|
|
|
598
587
|
private givenInput;
|
|
599
588
|
private whenInput;
|
|
600
589
|
constructor(streamName: string, eventBus: EventProducer<DomainEvent | IntegrationEvent | ExternalEvent> & EventConsumer<DomainEvent | IntegrationEvent | ExternalEvent>, eventStore: EventStore<TEvent, Promise<void>, Promise<TEvent[]>>, commandBus: CommandBus<Command>, queryBus: QueryBus<Query, Promise<Record<string, unknown>[]>>, repository: Repository<DomainEvent, Promise<TState>>, outboxWorker: OutboxWorker, outbox: Outbox);
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
590
|
+
Given(...events: GivenInput): {
|
|
591
|
+
When(action: WhenInput): ReturnType<ScenarioTest<TState, TEvent>["When"]>;
|
|
592
|
+
Then(outcome: ThenInput): Promise<void>;
|
|
604
593
|
};
|
|
605
|
-
|
|
606
|
-
|
|
594
|
+
When(action: WhenInput): {
|
|
595
|
+
Then(outcome: ThenInput): Promise<void>;
|
|
607
596
|
};
|
|
608
|
-
|
|
597
|
+
Then(thenInput: ThenInput): Promise<void>;
|
|
609
598
|
private handleCommand;
|
|
610
599
|
private handleQuery;
|
|
611
600
|
private handleEvent;
|
|
@@ -621,4 +610,4 @@ declare function parseAsError(value: unknown): Error;
|
|
|
621
610
|
|
|
622
611
|
declare function makeStreamKey(streamName: string, aggregateId: string): StreamKey;
|
|
623
612
|
|
|
624
|
-
export { type AggregateRoot, AndSpecification, type BaseMetadata, type Command, type CommandBus, type CommandHandler, type CommandMetadata, CompositeSpecification, type CreateStatement, type Database, type Decider, type DeleteStatement, type Directive, type DomainEvent, type DomainEventMetadata, type EventBasedAggregateRoot, type EventConsumer, type EventHandler, type EventProducer, type EventStore, FieldEquals, FieldGreaterThan, type FilledArray, GenericOutboxWorker, type ISODateTime, InMemoryOutbox, type IntegrationEvent, type IntegrationEventMetadata, type Maybe, NotSpecification, type Nullable, Operation, OrSpecification, type Outbox, type OutboxEntry, type OutboxWorker, type PatchStatement, type Primitive, type PutStatement, type Query, type QueryBus, type QueryHandler, type QueryMetadata, type QueryNode, type Rejection, type RejectionMetadata, type Repository, ScenarioTest, SimpleCommandBus, SimpleDatabase, SimpleEventBus, SimpleEventStore, SimpleQueryBus, SimpleRepository, type Specification, type StoredEvent, type StreamKey, type UnixTimestampInSeconds, type WithIdentifier, convertDomainEventToIntegrationEvent, convertRejectionToIntegrationEvent, createCommand, createDomainEvent, createExternalEvent, createIntegrationEvent, createOutboxEntry, createQuery, createQueryNode, createRejection, createStoredEvent, fail, getTimestamp, invariant, isCommand, isDomainEvent, isEqual, isEvent, isExternalEvent, isIntegrationEvent, isQuery, isRejection, makeStreamKey,
|
|
613
|
+
export { type AggregateRoot, AndSpecification, type BaseMetadata, type Command, type CommandBus, type CommandHandler, type CommandMetadata, CompositeSpecification, type CreateStatement, type Database, type Decider, type DeleteStatement, type Directive, type DomainEvent, type DomainEventMetadata, type EventBasedAggregateRoot, type EventConsumer, type EventHandler, type EventProducer, type EventStore, FieldEquals, FieldGreaterThan, type FilledArray, GenericOutboxWorker, type ISODateTime, InMemoryOutbox, type IntegrationEvent, type IntegrationEventMetadata, type Maybe, NotSpecification, type Nullable, Operation, OrSpecification, type Outbox, type OutboxEntry, type OutboxWorker, type PatchStatement, type Primitive, type PutStatement, type Query, type QueryBus, type QueryHandler, type QueryMetadata, type QueryNode, type Rejection, type RejectionMetadata, type Repository, ScenarioTest, SimpleCommandBus, SimpleDatabase, SimpleEventBus, SimpleEventStore, SimpleQueryBus, SimpleRepository, type Specification, type StoredEvent, type StreamKey, type UnixTimestampInSeconds, type WithIdentifier, convertDomainEventToIntegrationEvent, convertRejectionToIntegrationEvent, createCommand, createDomainEvent, createExternalEvent, createIntegrationEvent, createOutboxEntry, createQuery, createQueryNode, createRejection, createStoredEvent, fail, getTimestamp, invariant, isCommand, isDomainEvent, isEqual, isEvent, isExternalEvent, isIntegrationEvent, isQuery, isRejection, makeStreamKey, parseAsError };
|
|
@@ -31,23 +31,17 @@ function createQuery(type, payload, metadata = {}) {
|
|
|
31
31
|
|
|
32
32
|
// src/core/utils/isCommand.ts
|
|
33
33
|
function isCommand(candidate) {
|
|
34
|
-
if (candidate === null)
|
|
35
|
-
|
|
36
|
-
if (
|
|
37
|
-
return false;
|
|
38
|
-
if (!("type" in candidate))
|
|
39
|
-
return false;
|
|
34
|
+
if (candidate === null) return false;
|
|
35
|
+
if (typeof candidate !== "object") return false;
|
|
36
|
+
if (!("type" in candidate)) return false;
|
|
40
37
|
return "kind" in candidate && candidate.kind === "command";
|
|
41
38
|
}
|
|
42
39
|
|
|
43
40
|
// src/core/utils/isQuery.ts
|
|
44
41
|
function isQuery(candidate) {
|
|
45
|
-
if (candidate === null)
|
|
46
|
-
|
|
47
|
-
if (
|
|
48
|
-
return false;
|
|
49
|
-
if (!("type" in candidate))
|
|
50
|
-
return false;
|
|
42
|
+
if (candidate === null) return false;
|
|
43
|
+
if (typeof candidate !== "object") return false;
|
|
44
|
+
if (!("type" in candidate)) return false;
|
|
51
45
|
return "kind" in candidate && candidate.kind === "query";
|
|
52
46
|
}
|
|
53
47
|
|
|
@@ -150,8 +144,7 @@ function fail(anExpression) {
|
|
|
150
144
|
|
|
151
145
|
// src/utils/invariant/invariant.ts
|
|
152
146
|
function invariant(condition, onInvalid) {
|
|
153
|
-
if (!condition)
|
|
154
|
-
onInvalid();
|
|
147
|
+
if (!condition) onInvalid();
|
|
155
148
|
}
|
|
156
149
|
|
|
157
150
|
// src/domain/Specification/implementations/FieldGreaterThan.specification.ts
|
|
@@ -168,9 +161,7 @@ var FieldGreaterThan = class extends CompositeSpecification {
|
|
|
168
161
|
const field = entity[this.field];
|
|
169
162
|
invariant(
|
|
170
163
|
this.isNumber(field),
|
|
171
|
-
fail(
|
|
172
|
-
new TypeError(`Field ${String(this.field)} is not a number`)
|
|
173
|
-
)
|
|
164
|
+
fail(new TypeError(`Field ${String(this.field)} is not a number`))
|
|
174
165
|
);
|
|
175
166
|
return field > this.value;
|
|
176
167
|
}
|
|
@@ -178,12 +169,12 @@ var FieldGreaterThan = class extends CompositeSpecification {
|
|
|
178
169
|
return createQueryNode("gt", this.field, this.value);
|
|
179
170
|
}
|
|
180
171
|
};
|
|
181
|
-
function createIntegrationEvent(type, payload, metadata) {
|
|
172
|
+
function createIntegrationEvent(type, payload, metadata = {}, timestamp = (/* @__PURE__ */ new Date()).toISOString()) {
|
|
182
173
|
return Object.freeze({
|
|
183
174
|
id: randomUUID(),
|
|
184
175
|
type,
|
|
185
176
|
payload,
|
|
186
|
-
timestamp
|
|
177
|
+
timestamp,
|
|
187
178
|
metadata: {
|
|
188
179
|
...metadata
|
|
189
180
|
},
|
|
@@ -193,11 +184,16 @@ function createIntegrationEvent(type, payload, metadata) {
|
|
|
193
184
|
|
|
194
185
|
// src/domain/utils/convertDomainEventToIntegrationEvent.ts
|
|
195
186
|
function convertDomainEventToIntegrationEvent(event) {
|
|
196
|
-
return createIntegrationEvent(
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
187
|
+
return createIntegrationEvent(
|
|
188
|
+
event.type,
|
|
189
|
+
event.payload,
|
|
190
|
+
{
|
|
191
|
+
outcome: "accepted",
|
|
192
|
+
aggregateType: event.aggregateType,
|
|
193
|
+
aggregateId: event.aggregateId
|
|
194
|
+
},
|
|
195
|
+
new Date(event.timestamp).toISOString()
|
|
196
|
+
);
|
|
201
197
|
}
|
|
202
198
|
|
|
203
199
|
// src/domain/utils/convertRejectionToIntegrationEvent.ts
|
|
@@ -211,7 +207,8 @@ function convertRejectionToIntegrationEvent(rejection) {
|
|
|
211
207
|
aggregateId: rejection.metadata?.aggregateId,
|
|
212
208
|
commandType: rejection.commandType,
|
|
213
209
|
commandId: rejection.commandId
|
|
214
|
-
}
|
|
210
|
+
},
|
|
211
|
+
new Date(rejection.timestamp).toISOString()
|
|
215
212
|
);
|
|
216
213
|
}
|
|
217
214
|
function createDomainEvent(type, aggregateId, aggregateType, payload, metadata = {}) {
|
|
@@ -246,12 +243,9 @@ function createRejection(rejectionSpecifics, metadata = {}) {
|
|
|
246
243
|
|
|
247
244
|
// src/domain/utils/isEvent.ts
|
|
248
245
|
function isEvent(event) {
|
|
249
|
-
if (typeof event !== "object")
|
|
250
|
-
|
|
251
|
-
if (event
|
|
252
|
-
return false;
|
|
253
|
-
if (!("type" in event))
|
|
254
|
-
return false;
|
|
246
|
+
if (typeof event !== "object") return false;
|
|
247
|
+
if (event === null) return false;
|
|
248
|
+
if (!("type" in event)) return false;
|
|
255
249
|
return "kind" in event;
|
|
256
250
|
}
|
|
257
251
|
|
|
@@ -262,8 +256,7 @@ function isDomainEvent(event) {
|
|
|
262
256
|
|
|
263
257
|
// src/domain/utils/isRejection.ts
|
|
264
258
|
function isRejection(candidate) {
|
|
265
|
-
if (candidate === null || typeof candidate !== "object")
|
|
266
|
-
return false;
|
|
259
|
+
if (candidate === null || typeof candidate !== "object") return false;
|
|
267
260
|
return "commandId" in candidate && "commandType" in candidate && "reasonCode" in candidate && "timestamp" in candidate;
|
|
268
261
|
}
|
|
269
262
|
|
|
@@ -316,43 +309,36 @@ var SimpleDatabase = class {
|
|
|
316
309
|
datasource = /* @__PURE__ */ new Map();
|
|
317
310
|
simulateOffline = false;
|
|
318
311
|
async query(tableName, specification) {
|
|
319
|
-
if (this.simulateOffline)
|
|
320
|
-
throw new DatabaseOfflineException();
|
|
312
|
+
if (this.simulateOffline) throw new DatabaseOfflineException();
|
|
321
313
|
const tableRecords = this.datasource.get(tableName) || [];
|
|
322
314
|
return tableRecords.filter((record) => specification.isSatisfiedBy(record));
|
|
323
315
|
}
|
|
324
316
|
async execute(tableName, statement) {
|
|
325
|
-
if (this.simulateOffline)
|
|
326
|
-
|
|
327
|
-
if (!this.datasource.has(tableName))
|
|
328
|
-
this.datasource.set(tableName, []);
|
|
317
|
+
if (this.simulateOffline) throw new DatabaseOfflineException();
|
|
318
|
+
if (!this.datasource.has(tableName)) this.datasource.set(tableName, []);
|
|
329
319
|
const table = this.datasource.get(tableName);
|
|
330
320
|
switch (statement.operation) {
|
|
331
321
|
case "CREATE" /* CREATE */: {
|
|
332
322
|
const isDuplicate = table.some((item) => item.id === statement.payload.id);
|
|
333
|
-
if (isDuplicate)
|
|
334
|
-
throw new DuplicateRecordException(statement.payload.id);
|
|
323
|
+
if (isDuplicate) throw new DuplicateRecordException(statement.payload.id);
|
|
335
324
|
table.push(statement.payload);
|
|
336
325
|
break;
|
|
337
326
|
}
|
|
338
327
|
case "PUT" /* PUT */: {
|
|
339
328
|
const index = table.findIndex((item) => item.id === statement.payload.id);
|
|
340
|
-
if (index === -1)
|
|
341
|
-
throw new RecordNotFoundException(statement.payload.id);
|
|
329
|
+
if (index === -1) throw new RecordNotFoundException(statement.payload.id);
|
|
342
330
|
table[index] = statement.payload;
|
|
343
331
|
break;
|
|
344
332
|
}
|
|
345
333
|
case "PATCH" /* PATCH */: {
|
|
346
334
|
const index = table.findIndex((item) => item.id === statement.payload.id);
|
|
347
|
-
if (index === -1)
|
|
348
|
-
throw new RecordNotFoundException(statement.payload.id);
|
|
335
|
+
if (index === -1) throw new RecordNotFoundException(statement.payload.id);
|
|
349
336
|
table[index] = { ...table[index], ...statement.payload };
|
|
350
337
|
break;
|
|
351
338
|
}
|
|
352
339
|
case "DELETE" /* DELETE */: {
|
|
353
340
|
const index = table.findIndex((item) => item.id === statement.payload.id);
|
|
354
|
-
if (index === -1)
|
|
355
|
-
throw new RecordNotFoundException(statement.payload.id);
|
|
341
|
+
if (index === -1) throw new RecordNotFoundException(statement.payload.id);
|
|
356
342
|
table.splice(index, 1);
|
|
357
343
|
break;
|
|
358
344
|
}
|
|
@@ -372,12 +358,13 @@ var SimpleEventBus = class {
|
|
|
372
358
|
this.handlers.set(stream, handlersForType);
|
|
373
359
|
}
|
|
374
360
|
async consume(stream, anEvent) {
|
|
375
|
-
if (!this.handlers.has(stream))
|
|
376
|
-
return;
|
|
361
|
+
if (!this.handlers.has(stream)) return;
|
|
377
362
|
const handlers = this.handlers.get(stream);
|
|
378
|
-
await Promise.all(
|
|
379
|
-
|
|
380
|
-
|
|
363
|
+
await Promise.all(
|
|
364
|
+
handlers.map(async (handler) => {
|
|
365
|
+
return handler.handle(anEvent);
|
|
366
|
+
})
|
|
367
|
+
);
|
|
381
368
|
}
|
|
382
369
|
async publish(stream, anEvent) {
|
|
383
370
|
await this.consume(stream, anEvent);
|
|
@@ -406,49 +393,6 @@ function isIntegrationEvent(event) {
|
|
|
406
393
|
return isEvent(event) && event.kind === "integration";
|
|
407
394
|
}
|
|
408
395
|
|
|
409
|
-
// src/infrastructure/EventBus/utils/mapDomainEventToIntegrationEvent.ts
|
|
410
|
-
function mapDomainEventToIntegrationEvent(domainEvent) {
|
|
411
|
-
const metadata = {
|
|
412
|
-
...domainEvent.metadata,
|
|
413
|
-
aggregateType: domainEvent.aggregateType,
|
|
414
|
-
aggregateId: domainEvent.aggregateId,
|
|
415
|
-
outcome: "accepted"
|
|
416
|
-
};
|
|
417
|
-
return {
|
|
418
|
-
id: domainEvent.id,
|
|
419
|
-
type: domainEvent.type,
|
|
420
|
-
payload: domainEvent.payload,
|
|
421
|
-
timestamp: new Date(domainEvent.timestamp).toISOString(),
|
|
422
|
-
metadata,
|
|
423
|
-
kind: "integration"
|
|
424
|
-
};
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
// src/infrastructure/EventBus/utils/mapRejectionToIntegrationEvent.ts
|
|
428
|
-
function mapRejectionToIntegrationEvent(rejection) {
|
|
429
|
-
const metadata = {
|
|
430
|
-
...rejection.metadata,
|
|
431
|
-
outcome: "rejected",
|
|
432
|
-
commandId: rejection.commandId,
|
|
433
|
-
commandType: rejection.commandType
|
|
434
|
-
};
|
|
435
|
-
return {
|
|
436
|
-
id: rejection.id,
|
|
437
|
-
type: rejection.type,
|
|
438
|
-
payload: {
|
|
439
|
-
reasonCode: rejection.reasonCode,
|
|
440
|
-
reason: rejection.reason,
|
|
441
|
-
classification: rejection.classification,
|
|
442
|
-
retryable: rejection.retryable,
|
|
443
|
-
details: rejection.details,
|
|
444
|
-
validationErrors: rejection.validationErrors
|
|
445
|
-
},
|
|
446
|
-
timestamp: new Date(rejection.timestamp).toISOString(),
|
|
447
|
-
metadata,
|
|
448
|
-
kind: "integration"
|
|
449
|
-
};
|
|
450
|
-
}
|
|
451
|
-
|
|
452
396
|
// src/utils/streamKey/makeStreamKey.ts
|
|
453
397
|
function makeStreamKey(streamName, aggregateId) {
|
|
454
398
|
return `${streamName}#${aggregateId}`;
|
|
@@ -467,10 +411,8 @@ function isEqual(a, b) {
|
|
|
467
411
|
|
|
468
412
|
// src/utils/parseAsError/parseAsError.ts
|
|
469
413
|
function parseAsError(value) {
|
|
470
|
-
if (value instanceof Error)
|
|
471
|
-
|
|
472
|
-
if (typeof value === "string")
|
|
473
|
-
return new Error(value);
|
|
414
|
+
if (value instanceof Error) return value;
|
|
415
|
+
if (typeof value === "string") return new Error(value);
|
|
474
416
|
try {
|
|
475
417
|
const json = JSON.stringify(value);
|
|
476
418
|
return new Error(json ?? String(value));
|
|
@@ -512,11 +454,12 @@ var SimpleEventStore = class {
|
|
|
512
454
|
}
|
|
513
455
|
async append(streamName, events) {
|
|
514
456
|
const uniqueAggregateIds = new Set(events.map((event2) => event2.aggregateId));
|
|
515
|
-
if (uniqueAggregateIds.size > 1)
|
|
516
|
-
throw new MultipleAggregatesException();
|
|
457
|
+
if (uniqueAggregateIds.size > 1) throw new MultipleAggregatesException();
|
|
517
458
|
const event = events[0];
|
|
518
459
|
const currentStream = await this.load(streamName, event.aggregateId);
|
|
519
|
-
const eventsToStore = events.map(
|
|
460
|
+
const eventsToStore = events.map(
|
|
461
|
+
(event2) => createStoredEvent(streamName, currentStream.length + 1, event2)
|
|
462
|
+
);
|
|
520
463
|
await Promise.all(
|
|
521
464
|
eventsToStore.map(
|
|
522
465
|
async (payload) => this.database.execute(this.tableName, { operation: "CREATE" /* CREATE */, payload })
|
|
@@ -535,14 +478,16 @@ var GenericOutboxWorker = class {
|
|
|
535
478
|
}
|
|
536
479
|
async runOnce() {
|
|
537
480
|
const pending = await this.outbox.getPending();
|
|
538
|
-
await Promise.all(
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
481
|
+
await Promise.all(
|
|
482
|
+
pending.map(async (entry) => {
|
|
483
|
+
try {
|
|
484
|
+
await this.eventBus.publish(this.stream, entry.event);
|
|
485
|
+
await this.outbox.markAsPublished(entry.id);
|
|
486
|
+
} catch {
|
|
487
|
+
await this.outbox.markAsFailed(entry.id);
|
|
488
|
+
}
|
|
489
|
+
})
|
|
490
|
+
);
|
|
546
491
|
}
|
|
547
492
|
async tick() {
|
|
548
493
|
await this.runOnce();
|
|
@@ -621,12 +566,7 @@ var SimpleRepository = class {
|
|
|
621
566
|
}
|
|
622
567
|
async store(events) {
|
|
623
568
|
await Promise.all(
|
|
624
|
-
events.map(
|
|
625
|
-
async (event) => this.eventStore.append(
|
|
626
|
-
this.streamName,
|
|
627
|
-
[event]
|
|
628
|
-
)
|
|
629
|
-
)
|
|
569
|
+
events.map(async (event) => this.eventStore.append(this.streamName, [event]))
|
|
630
570
|
);
|
|
631
571
|
}
|
|
632
572
|
};
|
|
@@ -645,20 +585,20 @@ var ScenarioTest = class {
|
|
|
645
585
|
}
|
|
646
586
|
givenInput = [];
|
|
647
587
|
whenInput;
|
|
648
|
-
|
|
588
|
+
Given(...events) {
|
|
649
589
|
this.givenInput = events;
|
|
650
590
|
return {
|
|
651
|
-
|
|
652
|
-
|
|
591
|
+
When: this.When.bind(this),
|
|
592
|
+
Then: this.Then.bind(this)
|
|
653
593
|
};
|
|
654
594
|
}
|
|
655
|
-
|
|
595
|
+
When(action) {
|
|
656
596
|
this.whenInput = action;
|
|
657
597
|
return {
|
|
658
|
-
|
|
598
|
+
Then: this.Then.bind(this)
|
|
659
599
|
};
|
|
660
600
|
}
|
|
661
|
-
async
|
|
601
|
+
async Then(thenInput) {
|
|
662
602
|
await Promise.all([
|
|
663
603
|
this.repository.store(this.givenInput),
|
|
664
604
|
...this.givenInput.map(async (event) => this.eventBus.consume(this.streamName, event))
|
|
@@ -684,7 +624,11 @@ var ScenarioTest = class {
|
|
|
684
624
|
}
|
|
685
625
|
invariant(
|
|
686
626
|
isDomainEvent(thenInput),
|
|
687
|
-
fail(
|
|
627
|
+
fail(
|
|
628
|
+
new TypeError(
|
|
629
|
+
'When "domain event" or "integration event" expects a domain event in the then-step'
|
|
630
|
+
)
|
|
631
|
+
)
|
|
688
632
|
);
|
|
689
633
|
await this.handleEvent(this.whenInput, thenInput);
|
|
690
634
|
}
|
|
@@ -695,7 +639,10 @@ var ScenarioTest = class {
|
|
|
695
639
|
const foundRejection = pending.find(
|
|
696
640
|
(entry) => entry.event.metadata.outcome === "rejected" && entry.event.metadata.commandType === outcome.commandType && entry.event.payload.reasonCode === outcome.reasonCode
|
|
697
641
|
);
|
|
698
|
-
invariant(
|
|
642
|
+
invariant(
|
|
643
|
+
!!foundRejection,
|
|
644
|
+
fail(new Error("ScenarioTest: rejection was not found in outbox"))
|
|
645
|
+
);
|
|
699
646
|
return;
|
|
700
647
|
}
|
|
701
648
|
const actualEvents = await this.eventStore.load(this.streamName, outcome.aggregateId);
|
|
@@ -747,6 +694,6 @@ var ScenarioTest = class {
|
|
|
747
694
|
}
|
|
748
695
|
};
|
|
749
696
|
|
|
750
|
-
export { AndSpecification, CompositeSpecification, FieldEquals, FieldGreaterThan, GenericOutboxWorker, InMemoryOutbox, NotSpecification, Operation, OrSpecification, ScenarioTest, SimpleCommandBus, SimpleDatabase, SimpleEventBus, SimpleEventStore, SimpleQueryBus, SimpleRepository, convertDomainEventToIntegrationEvent, convertRejectionToIntegrationEvent, createCommand, createDomainEvent, createExternalEvent, createIntegrationEvent, createOutboxEntry, createQuery, createQueryNode, createRejection, createStoredEvent, fail, getTimestamp, invariant, isCommand, isDomainEvent, isEqual, isEvent, isExternalEvent, isIntegrationEvent, isQuery, isRejection, makeStreamKey,
|
|
697
|
+
export { AndSpecification, CompositeSpecification, FieldEquals, FieldGreaterThan, GenericOutboxWorker, InMemoryOutbox, NotSpecification, Operation, OrSpecification, ScenarioTest, SimpleCommandBus, SimpleDatabase, SimpleEventBus, SimpleEventStore, SimpleQueryBus, SimpleRepository, convertDomainEventToIntegrationEvent, convertRejectionToIntegrationEvent, createCommand, createDomainEvent, createExternalEvent, createIntegrationEvent, createOutboxEntry, createQuery, createQueryNode, createRejection, createStoredEvent, fail, getTimestamp, invariant, isCommand, isDomainEvent, isEqual, isEvent, isExternalEvent, isIntegrationEvent, isQuery, isRejection, makeStreamKey, parseAsError };
|
|
751
698
|
//# sourceMappingURL=index.js.map
|
|
752
699
|
//# sourceMappingURL=index.js.map
|