@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
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { GatewayFailure, StoredEvent, OutboxEnvelope, Notification } from '../shapes/index.cjs';
|
|
2
|
+
import { D as DomainEvent, S as StreamKey } from '../../../DomainEvent-CSzUMw46.cjs';
|
|
3
|
+
import { I as Intent } from '../../../Intent-B6l0bHZU.cjs';
|
|
4
|
+
import '../../../core/shapes/index.cjs';
|
|
5
|
+
import '../../../Message-c9XdBoh4.cjs';
|
|
6
|
+
import '../../../Rejection-D9PlzquK.cjs';
|
|
7
|
+
|
|
8
|
+
interface AdvanceCheckpoint<TResult = Promise<void | GatewayFailure>> {
|
|
9
|
+
advanceCheckpoint(position: number): TResult;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface AppendToEventStore<TDomainEvent extends DomainEvent, TReturn = Promise<void>> {
|
|
13
|
+
append(events: TDomainEvent[], expectedPosition?: number): TReturn;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface LoadCheckpoint<TResult = Promise<number | GatewayFailure>> {
|
|
17
|
+
loadCheckpoint(): TResult;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
interface LoadDomainEvents<TEvent extends DomainEvent, TResult = Promise<TEvent[]>> {
|
|
21
|
+
load(concerns: readonly StreamKey[]): TResult;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
interface LoadEventsFrom<TEvent extends DomainEvent, TResult = Promise<StoredEvent<TEvent>[] | GatewayFailure>> {
|
|
25
|
+
loadFrom(globalPosition: number, limit?: number): TResult;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
interface LoadPendingIntents<TIntent extends Intent, TResult = Promise<OutboxEnvelope<TIntent>[] | GatewayFailure>> {
|
|
29
|
+
loadPending(limit?: number): TResult;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
interface LoadProjection<TState, TResult = Promise<TState | GatewayFailure>> {
|
|
33
|
+
load(): TResult;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
interface MarkIntentDispatched<TResult = Promise<void | GatewayFailure>> {
|
|
37
|
+
markDispatched(intentId: string): TResult;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
interface MarkIntentFailed<TResult = Promise<void | GatewayFailure>> {
|
|
41
|
+
markFailed(intentId: string, reason: string): TResult;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
interface SaveProjection<TState, TResult = Promise<void | GatewayFailure>> {
|
|
45
|
+
save(state: TState): TResult;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Describes the fault to simulate on an adapter that implements `SimulatesFaults`.
|
|
50
|
+
*
|
|
51
|
+
* Built-in modes:
|
|
52
|
+
* - `offline` — the gateway is unreachable, operations fail immediately
|
|
53
|
+
* - `timeout` — the gateway is reachable but operations hang or take too long
|
|
54
|
+
*
|
|
55
|
+
* The type accepts any string to allow custom fault modes in user-land,
|
|
56
|
+
* while preserving autocomplete for the built-in modes.
|
|
57
|
+
*/
|
|
58
|
+
type FaultSimulationMode = "offline" | "timeout" | (string & {});
|
|
59
|
+
/**
|
|
60
|
+
* Capability for adapters that support fault simulation.
|
|
61
|
+
*
|
|
62
|
+
* Has a way to simulate faults for testing purposes, such as
|
|
63
|
+
* an offline gateway or a timeout. Useful for testing resilience
|
|
64
|
+
* and failure handling in use cases without real infrastructure.
|
|
65
|
+
*/
|
|
66
|
+
interface SimulateFaults {
|
|
67
|
+
simulate(fault: FaultSimulationMode): void;
|
|
68
|
+
restore(): void;
|
|
69
|
+
get isSimulating(): boolean;
|
|
70
|
+
get activeFault(): FaultSimulationMode | undefined;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
interface StageNotifications<TNotification extends Notification, TResult = Promise<void>> {
|
|
74
|
+
stage(notifications: TNotification[]): TResult;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export type { AdvanceCheckpoint, AppendToEventStore, FaultSimulationMode, LoadCheckpoint, LoadDomainEvents, LoadEventsFrom, LoadPendingIntents, LoadProjection, MarkIntentDispatched, MarkIntentFailed, SaveProjection, SimulateFaults, StageNotifications };
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { GatewayFailure, StoredEvent, OutboxEnvelope, Notification } from '../shapes/index.js';
|
|
2
|
+
import { D as DomainEvent, S as StreamKey } from '../../../DomainEvent-w1jyCjai.js';
|
|
3
|
+
import { I as Intent } from '../../../Intent-BLNY6RoG.js';
|
|
4
|
+
import '../../../core/shapes/index.js';
|
|
5
|
+
import '../../../Message-c9XdBoh4.js';
|
|
6
|
+
import '../../../Rejection-D9PlzquK.js';
|
|
7
|
+
|
|
8
|
+
interface AdvanceCheckpoint<TResult = Promise<void | GatewayFailure>> {
|
|
9
|
+
advanceCheckpoint(position: number): TResult;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface AppendToEventStore<TDomainEvent extends DomainEvent, TReturn = Promise<void>> {
|
|
13
|
+
append(events: TDomainEvent[], expectedPosition?: number): TReturn;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface LoadCheckpoint<TResult = Promise<number | GatewayFailure>> {
|
|
17
|
+
loadCheckpoint(): TResult;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
interface LoadDomainEvents<TEvent extends DomainEvent, TResult = Promise<TEvent[]>> {
|
|
21
|
+
load(concerns: readonly StreamKey[]): TResult;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
interface LoadEventsFrom<TEvent extends DomainEvent, TResult = Promise<StoredEvent<TEvent>[] | GatewayFailure>> {
|
|
25
|
+
loadFrom(globalPosition: number, limit?: number): TResult;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
interface LoadPendingIntents<TIntent extends Intent, TResult = Promise<OutboxEnvelope<TIntent>[] | GatewayFailure>> {
|
|
29
|
+
loadPending(limit?: number): TResult;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
interface LoadProjection<TState, TResult = Promise<TState | GatewayFailure>> {
|
|
33
|
+
load(): TResult;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
interface MarkIntentDispatched<TResult = Promise<void | GatewayFailure>> {
|
|
37
|
+
markDispatched(intentId: string): TResult;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
interface MarkIntentFailed<TResult = Promise<void | GatewayFailure>> {
|
|
41
|
+
markFailed(intentId: string, reason: string): TResult;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
interface SaveProjection<TState, TResult = Promise<void | GatewayFailure>> {
|
|
45
|
+
save(state: TState): TResult;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Describes the fault to simulate on an adapter that implements `SimulatesFaults`.
|
|
50
|
+
*
|
|
51
|
+
* Built-in modes:
|
|
52
|
+
* - `offline` — the gateway is unreachable, operations fail immediately
|
|
53
|
+
* - `timeout` — the gateway is reachable but operations hang or take too long
|
|
54
|
+
*
|
|
55
|
+
* The type accepts any string to allow custom fault modes in user-land,
|
|
56
|
+
* while preserving autocomplete for the built-in modes.
|
|
57
|
+
*/
|
|
58
|
+
type FaultSimulationMode = "offline" | "timeout" | (string & {});
|
|
59
|
+
/**
|
|
60
|
+
* Capability for adapters that support fault simulation.
|
|
61
|
+
*
|
|
62
|
+
* Has a way to simulate faults for testing purposes, such as
|
|
63
|
+
* an offline gateway or a timeout. Useful for testing resilience
|
|
64
|
+
* and failure handling in use cases without real infrastructure.
|
|
65
|
+
*/
|
|
66
|
+
interface SimulateFaults {
|
|
67
|
+
simulate(fault: FaultSimulationMode): void;
|
|
68
|
+
restore(): void;
|
|
69
|
+
get isSimulating(): boolean;
|
|
70
|
+
get activeFault(): FaultSimulationMode | undefined;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
interface StageNotifications<TNotification extends Notification, TResult = Promise<void>> {
|
|
74
|
+
stage(notifications: TNotification[]): TResult;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export type { AdvanceCheckpoint, AppendToEventStore, FaultSimulationMode, LoadCheckpoint, LoadDomainEvents, LoadEventsFrom, LoadPendingIntents, LoadProjection, MarkIntentDispatched, MarkIntentFailed, SaveProjection, SimulateFaults, StageNotifications };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.cjs"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { Failure } from '../../../core/shapes/index.cjs';
|
|
2
|
+
import { M as Message } from '../../../Message-c9XdBoh4.cjs';
|
|
3
|
+
import { R as Rejection } from '../../../Rejection-D9PlzquK.cjs';
|
|
4
|
+
import { I as Intent } from '../../../Intent-B6l0bHZU.cjs';
|
|
5
|
+
import { D as DomainEvent } from '../../../DomainEvent-CSzUMw46.cjs';
|
|
6
|
+
export { S as StreamKey } from '../../../DomainEvent-CSzUMw46.cjs';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* A specialisation of `Failure` for I/O related infrastructure failures.
|
|
10
|
+
*
|
|
11
|
+
* A `GatewayFailure` is returned as `Err` when an outbound adapter cannot
|
|
12
|
+
* reach its underlying infrastructure — for example, when the event store
|
|
13
|
+
* is offline, a database times out, or an external service is unavailable.
|
|
14
|
+
*
|
|
15
|
+
* It is never the result of a business rule violation. Use `Rejection` for
|
|
16
|
+
* those cases.
|
|
17
|
+
*
|
|
18
|
+
* The `gateway` field identifies which infrastructure component failed,
|
|
19
|
+
* enabling the adapter to map it to an appropriate response — typically
|
|
20
|
+
* HTTP 503.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* const failure: GatewayFailure = {
|
|
24
|
+
* kind: 'failure',
|
|
25
|
+
* code: 'GATEWAY_FAILURE',
|
|
26
|
+
* gateway: 'EventStore',
|
|
27
|
+
* reason: 'Connection refused',
|
|
28
|
+
* cause: originalError,
|
|
29
|
+
* };
|
|
30
|
+
*/
|
|
31
|
+
type GatewayFailure<TCode = string> = Failure<TCode> & {
|
|
32
|
+
readonly code: "GATEWAY_FAILURE";
|
|
33
|
+
readonly gateway: string;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* StoredEvent wraps a DomainEvent for persistence in the event store based on its concerns.
|
|
38
|
+
* This table must be immutable, append-only.
|
|
39
|
+
*/
|
|
40
|
+
type StoredEvent<TEvent extends DomainEvent> = {
|
|
41
|
+
/** Global position in the store */
|
|
42
|
+
readonly globalPosition: number;
|
|
43
|
+
/** Write-time, distinct from event.timestamp */
|
|
44
|
+
readonly insertedAt: number;
|
|
45
|
+
/** The actual domain event. */
|
|
46
|
+
readonly event: TEvent;
|
|
47
|
+
/** Concerns (streamkeys) of the event, hoisted */
|
|
48
|
+
readonly concerns: TEvent["concerns"];
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
interface Notification<TType = string, TPayload = unknown, TCode = string, TDetails = Rejection<TCode> | Failure<TCode>> extends Message<TType, TPayload> {
|
|
52
|
+
readonly kind: "failure" | "rejection";
|
|
53
|
+
readonly details: TDetails;
|
|
54
|
+
readonly commandType: string;
|
|
55
|
+
readonly commandId: string;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
type OutboxEnvelope<TEntry extends Intent | Notification> = {
|
|
59
|
+
status: "pending" | "dispatched" | "failed";
|
|
60
|
+
readonly stagedAt: number;
|
|
61
|
+
attemptCount: number;
|
|
62
|
+
dispatchedAt?: number;
|
|
63
|
+
failedAt?: number;
|
|
64
|
+
lastError?: string;
|
|
65
|
+
readonly entry: TEntry;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export type { GatewayFailure, Notification, OutboxEnvelope, StoredEvent };
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { Failure } from '../../../core/shapes/index.js';
|
|
2
|
+
import { M as Message } from '../../../Message-c9XdBoh4.js';
|
|
3
|
+
import { R as Rejection } from '../../../Rejection-D9PlzquK.js';
|
|
4
|
+
import { I as Intent } from '../../../Intent-BLNY6RoG.js';
|
|
5
|
+
import { D as DomainEvent } from '../../../DomainEvent-w1jyCjai.js';
|
|
6
|
+
export { S as StreamKey } from '../../../DomainEvent-w1jyCjai.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* A specialisation of `Failure` for I/O related infrastructure failures.
|
|
10
|
+
*
|
|
11
|
+
* A `GatewayFailure` is returned as `Err` when an outbound adapter cannot
|
|
12
|
+
* reach its underlying infrastructure — for example, when the event store
|
|
13
|
+
* is offline, a database times out, or an external service is unavailable.
|
|
14
|
+
*
|
|
15
|
+
* It is never the result of a business rule violation. Use `Rejection` for
|
|
16
|
+
* those cases.
|
|
17
|
+
*
|
|
18
|
+
* The `gateway` field identifies which infrastructure component failed,
|
|
19
|
+
* enabling the adapter to map it to an appropriate response — typically
|
|
20
|
+
* HTTP 503.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* const failure: GatewayFailure = {
|
|
24
|
+
* kind: 'failure',
|
|
25
|
+
* code: 'GATEWAY_FAILURE',
|
|
26
|
+
* gateway: 'EventStore',
|
|
27
|
+
* reason: 'Connection refused',
|
|
28
|
+
* cause: originalError,
|
|
29
|
+
* };
|
|
30
|
+
*/
|
|
31
|
+
type GatewayFailure<TCode = string> = Failure<TCode> & {
|
|
32
|
+
readonly code: "GATEWAY_FAILURE";
|
|
33
|
+
readonly gateway: string;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* StoredEvent wraps a DomainEvent for persistence in the event store based on its concerns.
|
|
38
|
+
* This table must be immutable, append-only.
|
|
39
|
+
*/
|
|
40
|
+
type StoredEvent<TEvent extends DomainEvent> = {
|
|
41
|
+
/** Global position in the store */
|
|
42
|
+
readonly globalPosition: number;
|
|
43
|
+
/** Write-time, distinct from event.timestamp */
|
|
44
|
+
readonly insertedAt: number;
|
|
45
|
+
/** The actual domain event. */
|
|
46
|
+
readonly event: TEvent;
|
|
47
|
+
/** Concerns (streamkeys) of the event, hoisted */
|
|
48
|
+
readonly concerns: TEvent["concerns"];
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
interface Notification<TType = string, TPayload = unknown, TCode = string, TDetails = Rejection<TCode> | Failure<TCode>> extends Message<TType, TPayload> {
|
|
52
|
+
readonly kind: "failure" | "rejection";
|
|
53
|
+
readonly details: TDetails;
|
|
54
|
+
readonly commandType: string;
|
|
55
|
+
readonly commandId: string;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
type OutboxEnvelope<TEntry extends Intent | Notification> = {
|
|
59
|
+
status: "pending" | "dispatched" | "failed";
|
|
60
|
+
readonly stagedAt: number;
|
|
61
|
+
attemptCount: number;
|
|
62
|
+
dispatchedAt?: number;
|
|
63
|
+
failedAt?: number;
|
|
64
|
+
lastError?: string;
|
|
65
|
+
readonly entry: TEntry;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export type { GatewayFailure, Notification, OutboxEnvelope, StoredEvent };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.cjs"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { I as Intent } from '../../Intent-B6l0bHZU.cjs';
|
|
2
|
+
import { D as DomainEvent } from '../../DomainEvent-CSzUMw46.cjs';
|
|
3
|
+
import '../../Message-c9XdBoh4.cjs';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Encapsulates a single business rule as a named, testable, composable predicate.
|
|
7
|
+
*
|
|
8
|
+
* An EvaluateCandidate answers one question about a candidate: does it satisfy
|
|
9
|
+
* this rule? It keeps business rules explicit, reusable across use cases,
|
|
10
|
+
* and independently testable without going through a decider.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* const membershipIsInitial: EvaluateCandidate<MembershipState> = {
|
|
14
|
+
* isSatisfiedBy: (candidate) => candidate.status === 'initial',
|
|
15
|
+
* };
|
|
16
|
+
*
|
|
17
|
+
* if (!membershipIsInitial.isSatisfiedBy(state)) {
|
|
18
|
+
* return { accepted: false, rejection: { code: 'MEMBERSHIP_ALREADY_EXISTS', reason: '...' } };
|
|
19
|
+
* }
|
|
20
|
+
*/
|
|
21
|
+
interface EvaluateCandidate<TCandidate> {
|
|
22
|
+
isSatisfiedBy(candidate: TCandidate): boolean;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
interface StageIntents<TIntent extends Intent, TResult = Promise<void>> {
|
|
26
|
+
stage(intents: TIntent[]): TResult;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
interface StoreDomainEvents<TDomainEvent extends DomainEvent, TReturn = Promise<void>> {
|
|
30
|
+
store(events: TDomainEvent[]): TReturn;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export type { EvaluateCandidate, StageIntents, StoreDomainEvents };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { I as Intent } from '../../Intent-BLNY6RoG.js';
|
|
2
|
+
import { D as DomainEvent } from '../../DomainEvent-w1jyCjai.js';
|
|
3
|
+
import '../../Message-c9XdBoh4.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Encapsulates a single business rule as a named, testable, composable predicate.
|
|
7
|
+
*
|
|
8
|
+
* An EvaluateCandidate answers one question about a candidate: does it satisfy
|
|
9
|
+
* this rule? It keeps business rules explicit, reusable across use cases,
|
|
10
|
+
* and independently testable without going through a decider.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* const membershipIsInitial: EvaluateCandidate<MembershipState> = {
|
|
14
|
+
* isSatisfiedBy: (candidate) => candidate.status === 'initial',
|
|
15
|
+
* };
|
|
16
|
+
*
|
|
17
|
+
* if (!membershipIsInitial.isSatisfiedBy(state)) {
|
|
18
|
+
* return { accepted: false, rejection: { code: 'MEMBERSHIP_ALREADY_EXISTS', reason: '...' } };
|
|
19
|
+
* }
|
|
20
|
+
*/
|
|
21
|
+
interface EvaluateCandidate<TCandidate> {
|
|
22
|
+
isSatisfiedBy(candidate: TCandidate): boolean;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
interface StageIntents<TIntent extends Intent, TResult = Promise<void>> {
|
|
26
|
+
stage(intents: TIntent[]): TResult;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
interface StoreDomainEvents<TDomainEvent extends DomainEvent, TReturn = Promise<void>> {
|
|
30
|
+
store(events: TDomainEvent[]): TReturn;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export type { EvaluateCandidate, StageIntents, StoreDomainEvents };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.cjs"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export { D as DomainEvent } from '../../DomainEvent-CSzUMw46.cjs';
|
|
2
|
+
export { I as Intent } from '../../Intent-B6l0bHZU.cjs';
|
|
3
|
+
export { M as Message, a as Metadata, W as WithIdentifier } from '../../Message-c9XdBoh4.cjs';
|
|
4
|
+
export { R as Rejection } from '../../Rejection-D9PlzquK.cjs';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A generic failure value object representing something that went wrong
|
|
8
|
+
* outside of the domain's control.
|
|
9
|
+
*
|
|
10
|
+
* `Failure` is a sans-I/O building block — it carries no infrastructure
|
|
11
|
+
* concerns. Adapters specialise it into concrete failure types such as
|
|
12
|
+
* `GatewayFailure` for I/O related failures.
|
|
13
|
+
*
|
|
14
|
+
* Failures are modelled as `Err` values via neverthrow, not as thrown
|
|
15
|
+
* exceptions. A `Failure` is always unexpected — if the domain explicitly
|
|
16
|
+
* said no, that is a `Rejection`, not a `Failure`.
|
|
17
|
+
*/
|
|
18
|
+
interface Failure<TCode = string> {
|
|
19
|
+
/** Tag that distinguishes a `Failure` from a `Rejection` at runtime. */
|
|
20
|
+
readonly kind: "failure";
|
|
21
|
+
/** Specific failure subtype, e.g. `"GATEWAY_FAILURE"`. */
|
|
22
|
+
readonly code: TCode;
|
|
23
|
+
readonly reason: string;
|
|
24
|
+
readonly cause?: unknown;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export type { Failure };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export { D as DomainEvent } from '../../DomainEvent-w1jyCjai.js';
|
|
2
|
+
export { I as Intent } from '../../Intent-BLNY6RoG.js';
|
|
3
|
+
export { M as Message, a as Metadata, W as WithIdentifier } from '../../Message-c9XdBoh4.js';
|
|
4
|
+
export { R as Rejection } from '../../Rejection-D9PlzquK.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A generic failure value object representing something that went wrong
|
|
8
|
+
* outside of the domain's control.
|
|
9
|
+
*
|
|
10
|
+
* `Failure` is a sans-I/O building block — it carries no infrastructure
|
|
11
|
+
* concerns. Adapters specialise it into concrete failure types such as
|
|
12
|
+
* `GatewayFailure` for I/O related failures.
|
|
13
|
+
*
|
|
14
|
+
* Failures are modelled as `Err` values via neverthrow, not as thrown
|
|
15
|
+
* exceptions. A `Failure` is always unexpected — if the domain explicitly
|
|
16
|
+
* said no, that is a `Rejection`, not a `Failure`.
|
|
17
|
+
*/
|
|
18
|
+
interface Failure<TCode = string> {
|
|
19
|
+
/** Tag that distinguishes a `Failure` from a `Rejection` at runtime. */
|
|
20
|
+
readonly kind: "failure";
|
|
21
|
+
/** Specific failure subtype, e.g. `"GATEWAY_FAILURE"`. */
|
|
22
|
+
readonly code: TCode;
|
|
23
|
+
readonly reason: string;
|
|
24
|
+
readonly cause?: unknown;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export type { Failure };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.cjs"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { D as DomainEvent } from '../../../DomainEvent-CSzUMw46.cjs';
|
|
2
|
+
import { I as Intent } from '../../../Intent-B6l0bHZU.cjs';
|
|
3
|
+
import { Decision, Command } from '../shapes/index.cjs';
|
|
4
|
+
import '../../../Message-c9XdBoh4.cjs';
|
|
5
|
+
import '../../../Rejection-D9PlzquK.cjs';
|
|
6
|
+
|
|
7
|
+
interface Decide<TCommand, TState, TEvent extends DomainEvent, TIntent extends Intent = never> {
|
|
8
|
+
decide(command: TCommand, currentState: TState): Decision<TEvent, TIntent>;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
interface Evolve<TState, TEvent extends DomainEvent> {
|
|
12
|
+
evolve(currentState: TState, event: TEvent): TState;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface HandleCommand<TCommand extends Command, TResult = Promise<void>> {
|
|
16
|
+
handle(input: TCommand): TResult;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
interface InitializeState<TState> {
|
|
20
|
+
initialize(id: string): TState;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
interface LoadDecisionState<TState, TReturn = Promise<TState>> {
|
|
24
|
+
load(id: string, ...otherIds: string[]): TReturn;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export type { Decide, Evolve, HandleCommand, InitializeState, LoadDecisionState };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { D as DomainEvent } from '../../../DomainEvent-w1jyCjai.js';
|
|
2
|
+
import { I as Intent } from '../../../Intent-BLNY6RoG.js';
|
|
3
|
+
import { Decision, Command } from '../shapes/index.js';
|
|
4
|
+
import '../../../Message-c9XdBoh4.js';
|
|
5
|
+
import '../../../Rejection-D9PlzquK.js';
|
|
6
|
+
|
|
7
|
+
interface Decide<TCommand, TState, TEvent extends DomainEvent, TIntent extends Intent = never> {
|
|
8
|
+
decide(command: TCommand, currentState: TState): Decision<TEvent, TIntent>;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
interface Evolve<TState, TEvent extends DomainEvent> {
|
|
12
|
+
evolve(currentState: TState, event: TEvent): TState;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface HandleCommand<TCommand extends Command, TResult = Promise<void>> {
|
|
16
|
+
handle(input: TCommand): TResult;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
interface InitializeState<TState> {
|
|
20
|
+
initialize(id: string): TState;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
interface LoadDecisionState<TState, TReturn = Promise<TState>> {
|
|
24
|
+
load(id: string, ...otherIds: string[]): TReturn;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export type { Decide, Evolve, HandleCommand, InitializeState, LoadDecisionState };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.cjs"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { M as Message } from '../../../Message-c9XdBoh4.cjs';
|
|
2
|
+
import { D as DomainEvent } from '../../../DomainEvent-CSzUMw46.cjs';
|
|
3
|
+
import { I as Intent } from '../../../Intent-B6l0bHZU.cjs';
|
|
4
|
+
import { R as Rejection } from '../../../Rejection-D9PlzquK.cjs';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Represents a successful decision made by a decider.
|
|
8
|
+
*
|
|
9
|
+
* An accepted decision is the result of a command passing all business rules.
|
|
10
|
+
* It carries one or more domain events to be appended to the event stream,
|
|
11
|
+
* and zero or more intents to be staged in the outbox.
|
|
12
|
+
*
|
|
13
|
+
* An accepted decision does NOT mean the command has been fully processed —
|
|
14
|
+
* it means the domain has decided what should happen. Infrastructure concerns
|
|
15
|
+
* (persisting events, dispatching intents) are handled by the use case handler.
|
|
16
|
+
*/
|
|
17
|
+
type Accepted<TEvent extends DomainEvent, TIntent extends Intent = never> = {
|
|
18
|
+
readonly accepted: true;
|
|
19
|
+
readonly events: [TEvent, ...TEvent[]];
|
|
20
|
+
readonly intents: TIntent[];
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Represents a rejection decision made by a decider.
|
|
24
|
+
*
|
|
25
|
+
* A rejection is a first-class business outcome — not an exception or an error.
|
|
26
|
+
* It means the command was valid and understood, but one or more business rules
|
|
27
|
+
* prevented it from being accepted. The domain explicitly said no.
|
|
28
|
+
*
|
|
29
|
+
* Rejections are never appended to the event stream. They may be recorded in
|
|
30
|
+
* an audit log by the use case handler, and can be published as an integration
|
|
31
|
+
* event if other bounded contexts need to know the command did not get through.
|
|
32
|
+
*/
|
|
33
|
+
type Rejected<TRejection extends Rejection> = {
|
|
34
|
+
readonly accepted: false;
|
|
35
|
+
readonly rejection: TRejection;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* The return type of a decider's decide() function.
|
|
39
|
+
*
|
|
40
|
+
* A Decision is a discriminated union on `accepted`, enabling exhaustive
|
|
41
|
+
* pattern matching at the use case handler and adapter level.
|
|
42
|
+
*
|
|
43
|
+
* Both `Accepted` and `Rejected` are expected business outcomes and are
|
|
44
|
+
* returned as `Ok` from the use case. Only infrastructure failures such as
|
|
45
|
+
* a unavailable event store are modelled as `Err` via `GatewayFailure`.
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* // Use case handler
|
|
49
|
+
* const decision = decider.decide(command, state);
|
|
50
|
+
*
|
|
51
|
+
* if (!decision.accepted) {
|
|
52
|
+
* await auditLog.record(command, decision.rejection);
|
|
53
|
+
* }
|
|
54
|
+
*
|
|
55
|
+
* return okAsync(decision);
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* // Adapter
|
|
59
|
+
* const result = await useCase.execute(command);
|
|
60
|
+
*
|
|
61
|
+
* result.match(
|
|
62
|
+
* (decision) => {
|
|
63
|
+
* if (!decision.accepted) {
|
|
64
|
+
* const status = rejectionCodeToStatus[decision.rejection.code];
|
|
65
|
+
* return reply.status(status).send({ error: decision.rejection.reason });
|
|
66
|
+
* }
|
|
67
|
+
* return reply.status(200).send({ events: decision.events });
|
|
68
|
+
* },
|
|
69
|
+
* (error) => reply.status(503).send({ error: 'Service unavailable' }) // GatewayFailure
|
|
70
|
+
* );
|
|
71
|
+
*/
|
|
72
|
+
type Decision<TEvent extends DomainEvent, TIntent extends Intent = never, TRejection extends Rejection = never> = Accepted<TEvent, TIntent> | Rejected<TRejection>;
|
|
73
|
+
|
|
74
|
+
interface Command<TType = string, TPayload = unknown> extends Message<TType, TPayload> {
|
|
75
|
+
readonly kind: "command";
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export type { Accepted, Command, Decision, Rejected };
|