@relaybus/core 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/errors.ts","../src/event.ts","../src/internal/timers.ts","../src/internal/validation.ts"],"names":[],"mappings":"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","file":"chunk-3OHMEMZA.cjs","sourcesContent":["/**\n * Base class of every error thrown by relaybus.\n */\nexport class RelayBusError extends Error {\n // Explicit names survive minification, unlike `new.target.name`.\n override name = 'RelayBusError';\n /**\n * Stable, machine-readable identifier of the error class, such as `RELAYBUS_LEASE_LOST`.\n * Unlike `name` and `message`, a code is never renamed once released; branch on it in\n * alerts and dashboards. Subclasses declared outside relaybus inherit `RELAYBUS_ERROR`.\n */\n readonly code: string = 'RELAYBUS_ERROR';\n}\n\n/** Invalid options passed to a relaybus component. */\nexport class ConfigurationError extends RelayBusError {\n override name = 'ConfigurationError';\n override readonly code: string = 'RELAYBUS_CONFIGURATION';\n}\n\n/**\n * Thrown by `publish` when no transaction can be found and the bus runs with\n * `transactionMode: 'required'` (the default). Publishing outside a transaction\n * would reintroduce the dual-write problem the outbox exists to prevent.\n */\nexport class TransactionRequiredError extends RelayBusError {\n override name = 'TransactionRequiredError';\n override readonly code: string = 'RELAYBUS_TRANSACTION_REQUIRED';\n}\n\n/**\n * A `bus.transaction` (or `@RelayBusTransaction()` method) ran past its `transactionTimeout` and\n * was rolled back. Its `cause` is the error the database raised when it ended the transaction,\n * when there was one. Usually a slow call to another service made inside the transaction.\n */\nexport class TransactionTimeoutError extends RelayBusError {\n override name = 'TransactionTimeoutError';\n override readonly code: string = 'RELAYBUS_TRANSACTION_TIMEOUT';\n}\n\n/**\n * Throw from a handler to dead-letter the delivery immediately, skipping the\n * remaining retry attempts.\n */\nexport class NonRetryableError extends RelayBusError {\n override name = 'NonRetryableError';\n override readonly code: string = 'RELAYBUS_NON_RETRYABLE';\n}\n\n/** A payload failed its event schema. Never retried: the payload will not change. */\nexport class EventValidationError extends NonRetryableError {\n override name = 'EventValidationError';\n override readonly code: string = 'RELAYBUS_EVENT_VALIDATION';\n\n constructor(\n message: string,\n readonly issues: readonly ValidationIssue[],\n ) {\n super(message);\n }\n}\n\n/**\n * A message received from a broker is not a valid event. Never retried:\n * transports should dead-letter it instead of redelivering it forever.\n */\nexport class InvalidEnvelopeError extends NonRetryableError {\n override name = 'InvalidEnvelopeError';\n override readonly code: string = 'RELAYBUS_INVALID_ENVELOPE';\n}\n\n/** The worker no longer owns the delivery it was processing. */\nexport class LeaseLostError extends RelayBusError {\n override name = 'LeaseLostError';\n override readonly code: string = 'RELAYBUS_LEASE_LOST';\n /**\n * Whether the store said so (a fenced write returned false). A worker that only noticed\n * locally that its lease ran out may still own the delivery in the store and has to give it back.\n */\n readonly storeConfirmed: boolean;\n\n constructor(message: string, options: { readonly storeConfirmed?: boolean } = {}) {\n super(message);\n this.storeConfirmed = options.storeConfirmed ?? false;\n }\n}\n\n/** A handler did not settle within its configured timeout. Retried like any failure. */\nexport class HandlerTimeoutError extends RelayBusError {\n override name = 'HandlerTimeoutError';\n override readonly code: string = 'RELAYBUS_HANDLER_TIMEOUT';\n}\n\n/**\n * Reason of a handler's abort signal when the bus stops before the handler\n * finished. The delivery is released and runs again without losing an attempt.\n */\nexport class DispatcherStoppedError extends RelayBusError {\n override name = 'DispatcherStoppedError';\n override readonly code: string = 'RELAYBUS_DISPATCHER_STOPPED';\n}\n\n/**\n * A delivery came back after its lease expired on its last attempt, so it is\n * dead-lettered without running its handler again.\n */\nexport class AttemptsExhaustedError extends RelayBusError {\n override name = 'AttemptsExhaustedError';\n override readonly code: string = 'RELAYBUS_ATTEMPTS_EXHAUSTED';\n}\n\n/** A lifecycle method was called in a state that does not allow it, such as starting a bus twice. */\nexport class LifecycleError extends RelayBusError {\n override name = 'LifecycleError';\n override readonly code: string = 'RELAYBUS_LIFECYCLE';\n}\n\n/** `drain` still found due deliveries after its maximum number of batches. */\nexport class DrainIncompleteError extends RelayBusError {\n override name = 'DrainIncompleteError';\n override readonly code: string = 'RELAYBUS_DRAIN_INCOMPLETE';\n}\n\nexport interface ValidationIssue {\n readonly message: string;\n readonly path?: readonly PropertyKey[] | undefined;\n}\n\n/** Serializable snapshot of an error, stored with failed deliveries. */\nexport interface ErrorInfo {\n readonly name: string;\n readonly message: string;\n readonly stack?: string | undefined;\n /** The {@link RelayBusError.code} of a relaybus error; absent for any other error. */\n readonly code?: string | undefined;\n}\n\nexport function toErrorInfo(error: unknown): ErrorInfo {\n if (error instanceof RelayBusError) {\n return { name: error.name, message: error.message, stack: error.stack, code: error.code };\n }\n if (error instanceof Error) {\n return { name: error.name, message: error.message, stack: error.stack };\n }\n return { name: 'NonError', message: safeStringify(error) };\n}\n\nfunction safeStringify(value: unknown): string {\n if (typeof value === 'string') {\n return value;\n }\n try {\n return JSON.stringify(value) ?? String(value);\n } catch {\n return String(value);\n }\n}\n","import { ConfigurationError, EventValidationError } from './errors.js';\nimport type { StandardSchemaV1 } from './standard-schema.js';\n\n/** String metadata carried with an event, such as `traceparent`. */\nexport type EventHeaders = Readonly<Record<string, string>>;\n\n/**\n * An event as stored and delivered. Field names follow CloudEvents where they\n * overlap (`id`, `type`, `source`, `time` as `occurredAt`, `subject` as `key`).\n */\nexport interface EventEnvelope<TPayload = unknown> {\n /** Globally unique id. Handlers and transports deduplicate on it. */\n readonly id: string;\n /** Event type, for example `order.created.v1`. */\n readonly type: string;\n /** Logical name of the publishing service. */\n readonly source: string;\n /** Ordering and partition key. Events sharing a key are handled in publish order. */\n readonly key: string | null;\n readonly payload: TPayload;\n readonly headers: EventHeaders;\n /** Id shared by every event of one business flow. */\n readonly correlationId: string | null;\n /** Id of the event whose handler published this one. */\n readonly causationId: string | null;\n readonly occurredAt: Date;\n}\n\n/** An instance of a class created with {@link defineEvent}. */\nexport interface DomainEvent<TPayload = unknown> {\n readonly type: string;\n readonly payload: TPayload;\n}\n\n/**\n * Derives the ordering key of an event from its validated payload. Declared bivariantly so an\n * event class stays assignable wherever its payload type is widened.\n */\nexport type EventKeyFunction<TPayload> = {\n bivarianceHack(payload: TPayload): string;\n}['bivarianceHack'];\n\n/** A class created with {@link defineEvent}. */\nexport interface EventClass<TPayload = unknown> {\n new (payload: TPayload): DomainEvent<TPayload>;\n readonly type: string;\n readonly schema: StandardSchemaV1<unknown, TPayload> | undefined;\n /** The `key` given to {@link defineEvent}; undefined for events without one. */\n readonly key?: EventKeyFunction<TPayload> | undefined;\n}\n\n/** Payload type of an event class: `PayloadOf<typeof OrderPlaced>`. */\nexport type PayloadOf<TEvent> = TEvent extends EventClass<infer TPayload> ? TPayload : never;\n\n/** Anything that names an event type: an event class or the type string itself. */\nexport type EventReference = { readonly type: string } | string;\n\nexport interface DefineEventOptions<TSchema extends StandardSchemaV1> {\n /** Validates the payload on publish and before every handler call. */\n readonly schema: TSchema;\n /** Ordering key of every event of this type, from its validated payload. See {@link DefineEventKeyOptions}. */\n readonly key?: (payload: StandardSchemaV1.InferOutput<TSchema>) => string;\n}\n\nexport interface DefineEventKeyOptions<TPayload> {\n /**\n * Ordering key of every event of this type, from its payload: `(payload) => payload.orderId`.\n * Typed from the payload, so a missing field or a non-string fails to compile. `publish` uses it\n * when it is given no `key`; an explicit `key` option wins (for `publishAll`, the one key of the\n * call applies to every event). It must return a non-empty string.\n */\n readonly key: (payload: TPayload) => string;\n}\n\nconst EVENT_TYPE_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._:/-]{0,254}$/;\n\nexport function assertEventType(type: string): void {\n if (!EVENT_TYPE_PATTERN.test(type)) {\n throw new ConfigurationError(\n `Event type '${type}' must be 1-255 characters of letters, digits, '.', '_', ':', '/' or '-', starting with a letter or digit`,\n );\n }\n}\n\n/**\n * Defines an event type. Extend the returned class to name it:\n *\n * ```ts\n * export class OrderPlaced extends defineEvent<{ orderId: string }>('order.placed.v1') {}\n * export class OrderShipped extends defineEvent('order.shipped.v1', { schema: orderShippedSchema }) {}\n * export class OrderPaid extends defineEvent('order.paid.v1', {\n * schema: orderPaidSchema,\n * key: (payload) => payload.orderId,\n * }) {}\n * export class OrderCancelled extends defineEvent<{ orderId: string }>('order.cancelled.v1', {\n * key: (payload) => payload.orderId,\n * }) {}\n * ```\n */\nexport function defineEvent<TSchema extends StandardSchemaV1>(\n type: string,\n options: DefineEventOptions<TSchema>,\n): EventClass<StandardSchemaV1.InferOutput<TSchema>>;\nexport function defineEvent<TPayload>(\n type: string,\n options?: DefineEventKeyOptions<TPayload>,\n): EventClass<TPayload>;\nexport function defineEvent(\n type: string,\n options?: Partial<DefineEventOptions<StandardSchemaV1>>,\n): EventClass<unknown> {\n assertEventType(type);\n const schema = options?.schema;\n const key = options?.key;\n return class DefinedEvent implements DomainEvent<unknown> {\n static readonly type = type;\n static readonly schema = schema;\n static readonly key = key;\n readonly type = type;\n constructor(readonly payload: unknown) {}\n };\n}\n\n/** Runs a Standard Schema and returns its output, or throws {@link EventValidationError}. */\n// eslint-disable-next-line relaybus/max-two-params -- exported API validatePayload keeps its public signature\nexport async function validatePayload<TPayload>(\n type: string,\n schema: StandardSchemaV1<unknown, TPayload> | undefined,\n payload: unknown,\n): Promise<TPayload> {\n if (schema === undefined) {\n return payload as TPayload;\n }\n const result = await schema['~standard'].validate(payload);\n if (result.issues !== undefined) {\n const issues = result.issues.map((issue) => ({\n message: issue.message,\n path: issue.path?.map((segment) => (typeof segment === 'object' ? segment.key : segment)),\n }));\n throw new EventValidationError(\n `Payload of '${type}' failed validation: ${issues.map((issue) => issue.message).join('; ')}`,\n issues,\n );\n }\n return result.value;\n}\n\n/**\n * The ordering key an event of `event`'s class takes from its definition, or null when the class\n * defines no key.\n *\n * @throws ConfigurationError when the key function returns an empty string or no string.\n */\nexport function keyFromDefinition(event: DomainEvent, payload: unknown): string | null {\n const keyOf = (event.constructor as Partial<EventClass>).key;\n if (keyOf === undefined) {\n return null;\n }\n const key: unknown = keyOf(payload);\n if (typeof key !== 'string' || key.length === 0) {\n throw new ConfigurationError(\n `The key function of '${event.type}' must return a non-empty string | returned=${typeof key === 'string' ? \"''\" : typeof key}`,\n );\n }\n return key;\n}\n","import type { Clock } from '../clock.js';\n\n/** A task for {@link schedule}: what runs, after how long, whether it repeats and keeps the process alive. */\nexport type ScheduledTask = Parameters<NonNullable<Clock['schedule']>>[0];\n\n/** Cancels a scheduled task; harmless once it ran or was cancelled. */\nexport type CancelTimer = () => void;\n\n/**\n * The one place relaybus starts timers: through `clock.schedule` when the clock controls timers,\n * else with the platform timers.\n */\nexport function schedule(clock: Clock, task: ScheduledTask): CancelTimer {\n return clock.schedule === undefined ? scheduleOnPlatform(task) : clock.schedule(task);\n}\n\n/** Resolves after `milliseconds` on the timers of `clock`. */\nexport function sleep(clock: Clock, milliseconds: number): Promise<void> {\n return new Promise((resolve) => {\n schedule(clock, { run: resolve, delayMs: milliseconds });\n });\n}\n\nfunction scheduleOnPlatform(task: ScheduledTask): CancelTimer {\n if (task.repeat === true) {\n const interval = setInterval(task.run, task.delayMs);\n if (task.unref === true) {\n interval.unref();\n }\n return () => clearInterval(interval);\n }\n const timeout = setTimeout(task.run, task.delayMs);\n if (task.unref === true) {\n timeout.unref();\n }\n return () => clearTimeout(timeout);\n}\n","import { ConfigurationError } from '../errors.js';\n\n/** Returns `value` when it is an integer of at least 1, else throws a {@link ConfigurationError} naming the option. */\nexport function assertPositiveInteger(value: number, name: string): number {\n if (!Number.isInteger(value) || value < 1) {\n throw new ConfigurationError(`${name} must be a positive integer, received ${String(value)}`);\n }\n return value;\n}\n"]}
@@ -0,0 +1,183 @@
1
+ // src/errors.ts
2
+ var RelayBusError = class extends Error {
3
+ // Explicit names survive minification, unlike `new.target.name`.
4
+ name = "RelayBusError";
5
+ /**
6
+ * Stable, machine-readable identifier of the error class, such as `RELAYBUS_LEASE_LOST`.
7
+ * Unlike `name` and `message`, a code is never renamed once released; branch on it in
8
+ * alerts and dashboards. Subclasses declared outside relaybus inherit `RELAYBUS_ERROR`.
9
+ */
10
+ code = "RELAYBUS_ERROR";
11
+ };
12
+ var ConfigurationError = class extends RelayBusError {
13
+ name = "ConfigurationError";
14
+ code = "RELAYBUS_CONFIGURATION";
15
+ };
16
+ var TransactionRequiredError = class extends RelayBusError {
17
+ name = "TransactionRequiredError";
18
+ code = "RELAYBUS_TRANSACTION_REQUIRED";
19
+ };
20
+ var TransactionTimeoutError = class extends RelayBusError {
21
+ name = "TransactionTimeoutError";
22
+ code = "RELAYBUS_TRANSACTION_TIMEOUT";
23
+ };
24
+ var NonRetryableError = class extends RelayBusError {
25
+ name = "NonRetryableError";
26
+ code = "RELAYBUS_NON_RETRYABLE";
27
+ };
28
+ var EventValidationError = class extends NonRetryableError {
29
+ constructor(message, issues) {
30
+ super(message);
31
+ this.issues = issues;
32
+ }
33
+ issues;
34
+ name = "EventValidationError";
35
+ code = "RELAYBUS_EVENT_VALIDATION";
36
+ };
37
+ var InvalidEnvelopeError = class extends NonRetryableError {
38
+ name = "InvalidEnvelopeError";
39
+ code = "RELAYBUS_INVALID_ENVELOPE";
40
+ };
41
+ var LeaseLostError = class extends RelayBusError {
42
+ name = "LeaseLostError";
43
+ code = "RELAYBUS_LEASE_LOST";
44
+ /**
45
+ * Whether the store said so (a fenced write returned false). A worker that only noticed
46
+ * locally that its lease ran out may still own the delivery in the store and has to give it back.
47
+ */
48
+ storeConfirmed;
49
+ constructor(message, options = {}) {
50
+ super(message);
51
+ this.storeConfirmed = options.storeConfirmed ?? false;
52
+ }
53
+ };
54
+ var HandlerTimeoutError = class extends RelayBusError {
55
+ name = "HandlerTimeoutError";
56
+ code = "RELAYBUS_HANDLER_TIMEOUT";
57
+ };
58
+ var DispatcherStoppedError = class extends RelayBusError {
59
+ name = "DispatcherStoppedError";
60
+ code = "RELAYBUS_DISPATCHER_STOPPED";
61
+ };
62
+ var AttemptsExhaustedError = class extends RelayBusError {
63
+ name = "AttemptsExhaustedError";
64
+ code = "RELAYBUS_ATTEMPTS_EXHAUSTED";
65
+ };
66
+ var LifecycleError = class extends RelayBusError {
67
+ name = "LifecycleError";
68
+ code = "RELAYBUS_LIFECYCLE";
69
+ };
70
+ var DrainIncompleteError = class extends RelayBusError {
71
+ name = "DrainIncompleteError";
72
+ code = "RELAYBUS_DRAIN_INCOMPLETE";
73
+ };
74
+ function toErrorInfo(error) {
75
+ if (error instanceof RelayBusError) {
76
+ return { name: error.name, message: error.message, stack: error.stack, code: error.code };
77
+ }
78
+ if (error instanceof Error) {
79
+ return { name: error.name, message: error.message, stack: error.stack };
80
+ }
81
+ return { name: "NonError", message: safeStringify(error) };
82
+ }
83
+ function safeStringify(value) {
84
+ if (typeof value === "string") {
85
+ return value;
86
+ }
87
+ try {
88
+ return JSON.stringify(value) ?? String(value);
89
+ } catch {
90
+ return String(value);
91
+ }
92
+ }
93
+
94
+ // src/event.ts
95
+ var EVENT_TYPE_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._:/-]{0,254}$/;
96
+ function assertEventType(type) {
97
+ if (!EVENT_TYPE_PATTERN.test(type)) {
98
+ throw new ConfigurationError(
99
+ `Event type '${type}' must be 1-255 characters of letters, digits, '.', '_', ':', '/' or '-', starting with a letter or digit`
100
+ );
101
+ }
102
+ }
103
+ function defineEvent(type, options) {
104
+ assertEventType(type);
105
+ const schema = options?.schema;
106
+ const key = options?.key;
107
+ return class DefinedEvent {
108
+ constructor(payload) {
109
+ this.payload = payload;
110
+ }
111
+ payload;
112
+ static type = type;
113
+ static schema = schema;
114
+ static key = key;
115
+ type = type;
116
+ };
117
+ }
118
+ async function validatePayload(type, schema, payload) {
119
+ if (schema === void 0) {
120
+ return payload;
121
+ }
122
+ const result = await schema["~standard"].validate(payload);
123
+ if (result.issues !== void 0) {
124
+ const issues = result.issues.map((issue) => ({
125
+ message: issue.message,
126
+ path: issue.path?.map((segment) => typeof segment === "object" ? segment.key : segment)
127
+ }));
128
+ throw new EventValidationError(
129
+ `Payload of '${type}' failed validation: ${issues.map((issue) => issue.message).join("; ")}`,
130
+ issues
131
+ );
132
+ }
133
+ return result.value;
134
+ }
135
+ function keyFromDefinition(event, payload) {
136
+ const keyOf = event.constructor.key;
137
+ if (keyOf === void 0) {
138
+ return null;
139
+ }
140
+ const key = keyOf(payload);
141
+ if (typeof key !== "string" || key.length === 0) {
142
+ throw new ConfigurationError(
143
+ `The key function of '${event.type}' must return a non-empty string | returned=${typeof key === "string" ? "''" : typeof key}`
144
+ );
145
+ }
146
+ return key;
147
+ }
148
+
149
+ // src/internal/timers.ts
150
+ function schedule(clock, task) {
151
+ return clock.schedule === void 0 ? scheduleOnPlatform(task) : clock.schedule(task);
152
+ }
153
+ function sleep(clock, milliseconds) {
154
+ return new Promise((resolve) => {
155
+ schedule(clock, { run: resolve, delayMs: milliseconds });
156
+ });
157
+ }
158
+ function scheduleOnPlatform(task) {
159
+ if (task.repeat === true) {
160
+ const interval = setInterval(task.run, task.delayMs);
161
+ if (task.unref === true) {
162
+ interval.unref();
163
+ }
164
+ return () => clearInterval(interval);
165
+ }
166
+ const timeout = setTimeout(task.run, task.delayMs);
167
+ if (task.unref === true) {
168
+ timeout.unref();
169
+ }
170
+ return () => clearTimeout(timeout);
171
+ }
172
+
173
+ // src/internal/validation.ts
174
+ function assertPositiveInteger(value, name) {
175
+ if (!Number.isInteger(value) || value < 1) {
176
+ throw new ConfigurationError(`${name} must be a positive integer, received ${String(value)}`);
177
+ }
178
+ return value;
179
+ }
180
+
181
+ export { AttemptsExhaustedError, ConfigurationError, DispatcherStoppedError, DrainIncompleteError, EventValidationError, HandlerTimeoutError, InvalidEnvelopeError, LeaseLostError, LifecycleError, NonRetryableError, RelayBusError, TransactionRequiredError, TransactionTimeoutError, assertEventType, assertPositiveInteger, defineEvent, keyFromDefinition, schedule, sleep, toErrorInfo, validatePayload };
182
+ //# sourceMappingURL=chunk-WS274DL3.js.map
183
+ //# sourceMappingURL=chunk-WS274DL3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/errors.ts","../src/event.ts","../src/internal/timers.ts","../src/internal/validation.ts"],"names":[],"mappings":"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","file":"chunk-WS274DL3.js","sourcesContent":["/**\n * Base class of every error thrown by relaybus.\n */\nexport class RelayBusError extends Error {\n // Explicit names survive minification, unlike `new.target.name`.\n override name = 'RelayBusError';\n /**\n * Stable, machine-readable identifier of the error class, such as `RELAYBUS_LEASE_LOST`.\n * Unlike `name` and `message`, a code is never renamed once released; branch on it in\n * alerts and dashboards. Subclasses declared outside relaybus inherit `RELAYBUS_ERROR`.\n */\n readonly code: string = 'RELAYBUS_ERROR';\n}\n\n/** Invalid options passed to a relaybus component. */\nexport class ConfigurationError extends RelayBusError {\n override name = 'ConfigurationError';\n override readonly code: string = 'RELAYBUS_CONFIGURATION';\n}\n\n/**\n * Thrown by `publish` when no transaction can be found and the bus runs with\n * `transactionMode: 'required'` (the default). Publishing outside a transaction\n * would reintroduce the dual-write problem the outbox exists to prevent.\n */\nexport class TransactionRequiredError extends RelayBusError {\n override name = 'TransactionRequiredError';\n override readonly code: string = 'RELAYBUS_TRANSACTION_REQUIRED';\n}\n\n/**\n * A `bus.transaction` (or `@RelayBusTransaction()` method) ran past its `transactionTimeout` and\n * was rolled back. Its `cause` is the error the database raised when it ended the transaction,\n * when there was one. Usually a slow call to another service made inside the transaction.\n */\nexport class TransactionTimeoutError extends RelayBusError {\n override name = 'TransactionTimeoutError';\n override readonly code: string = 'RELAYBUS_TRANSACTION_TIMEOUT';\n}\n\n/**\n * Throw from a handler to dead-letter the delivery immediately, skipping the\n * remaining retry attempts.\n */\nexport class NonRetryableError extends RelayBusError {\n override name = 'NonRetryableError';\n override readonly code: string = 'RELAYBUS_NON_RETRYABLE';\n}\n\n/** A payload failed its event schema. Never retried: the payload will not change. */\nexport class EventValidationError extends NonRetryableError {\n override name = 'EventValidationError';\n override readonly code: string = 'RELAYBUS_EVENT_VALIDATION';\n\n constructor(\n message: string,\n readonly issues: readonly ValidationIssue[],\n ) {\n super(message);\n }\n}\n\n/**\n * A message received from a broker is not a valid event. Never retried:\n * transports should dead-letter it instead of redelivering it forever.\n */\nexport class InvalidEnvelopeError extends NonRetryableError {\n override name = 'InvalidEnvelopeError';\n override readonly code: string = 'RELAYBUS_INVALID_ENVELOPE';\n}\n\n/** The worker no longer owns the delivery it was processing. */\nexport class LeaseLostError extends RelayBusError {\n override name = 'LeaseLostError';\n override readonly code: string = 'RELAYBUS_LEASE_LOST';\n /**\n * Whether the store said so (a fenced write returned false). A worker that only noticed\n * locally that its lease ran out may still own the delivery in the store and has to give it back.\n */\n readonly storeConfirmed: boolean;\n\n constructor(message: string, options: { readonly storeConfirmed?: boolean } = {}) {\n super(message);\n this.storeConfirmed = options.storeConfirmed ?? false;\n }\n}\n\n/** A handler did not settle within its configured timeout. Retried like any failure. */\nexport class HandlerTimeoutError extends RelayBusError {\n override name = 'HandlerTimeoutError';\n override readonly code: string = 'RELAYBUS_HANDLER_TIMEOUT';\n}\n\n/**\n * Reason of a handler's abort signal when the bus stops before the handler\n * finished. The delivery is released and runs again without losing an attempt.\n */\nexport class DispatcherStoppedError extends RelayBusError {\n override name = 'DispatcherStoppedError';\n override readonly code: string = 'RELAYBUS_DISPATCHER_STOPPED';\n}\n\n/**\n * A delivery came back after its lease expired on its last attempt, so it is\n * dead-lettered without running its handler again.\n */\nexport class AttemptsExhaustedError extends RelayBusError {\n override name = 'AttemptsExhaustedError';\n override readonly code: string = 'RELAYBUS_ATTEMPTS_EXHAUSTED';\n}\n\n/** A lifecycle method was called in a state that does not allow it, such as starting a bus twice. */\nexport class LifecycleError extends RelayBusError {\n override name = 'LifecycleError';\n override readonly code: string = 'RELAYBUS_LIFECYCLE';\n}\n\n/** `drain` still found due deliveries after its maximum number of batches. */\nexport class DrainIncompleteError extends RelayBusError {\n override name = 'DrainIncompleteError';\n override readonly code: string = 'RELAYBUS_DRAIN_INCOMPLETE';\n}\n\nexport interface ValidationIssue {\n readonly message: string;\n readonly path?: readonly PropertyKey[] | undefined;\n}\n\n/** Serializable snapshot of an error, stored with failed deliveries. */\nexport interface ErrorInfo {\n readonly name: string;\n readonly message: string;\n readonly stack?: string | undefined;\n /** The {@link RelayBusError.code} of a relaybus error; absent for any other error. */\n readonly code?: string | undefined;\n}\n\nexport function toErrorInfo(error: unknown): ErrorInfo {\n if (error instanceof RelayBusError) {\n return { name: error.name, message: error.message, stack: error.stack, code: error.code };\n }\n if (error instanceof Error) {\n return { name: error.name, message: error.message, stack: error.stack };\n }\n return { name: 'NonError', message: safeStringify(error) };\n}\n\nfunction safeStringify(value: unknown): string {\n if (typeof value === 'string') {\n return value;\n }\n try {\n return JSON.stringify(value) ?? String(value);\n } catch {\n return String(value);\n }\n}\n","import { ConfigurationError, EventValidationError } from './errors.js';\nimport type { StandardSchemaV1 } from './standard-schema.js';\n\n/** String metadata carried with an event, such as `traceparent`. */\nexport type EventHeaders = Readonly<Record<string, string>>;\n\n/**\n * An event as stored and delivered. Field names follow CloudEvents where they\n * overlap (`id`, `type`, `source`, `time` as `occurredAt`, `subject` as `key`).\n */\nexport interface EventEnvelope<TPayload = unknown> {\n /** Globally unique id. Handlers and transports deduplicate on it. */\n readonly id: string;\n /** Event type, for example `order.created.v1`. */\n readonly type: string;\n /** Logical name of the publishing service. */\n readonly source: string;\n /** Ordering and partition key. Events sharing a key are handled in publish order. */\n readonly key: string | null;\n readonly payload: TPayload;\n readonly headers: EventHeaders;\n /** Id shared by every event of one business flow. */\n readonly correlationId: string | null;\n /** Id of the event whose handler published this one. */\n readonly causationId: string | null;\n readonly occurredAt: Date;\n}\n\n/** An instance of a class created with {@link defineEvent}. */\nexport interface DomainEvent<TPayload = unknown> {\n readonly type: string;\n readonly payload: TPayload;\n}\n\n/**\n * Derives the ordering key of an event from its validated payload. Declared bivariantly so an\n * event class stays assignable wherever its payload type is widened.\n */\nexport type EventKeyFunction<TPayload> = {\n bivarianceHack(payload: TPayload): string;\n}['bivarianceHack'];\n\n/** A class created with {@link defineEvent}. */\nexport interface EventClass<TPayload = unknown> {\n new (payload: TPayload): DomainEvent<TPayload>;\n readonly type: string;\n readonly schema: StandardSchemaV1<unknown, TPayload> | undefined;\n /** The `key` given to {@link defineEvent}; undefined for events without one. */\n readonly key?: EventKeyFunction<TPayload> | undefined;\n}\n\n/** Payload type of an event class: `PayloadOf<typeof OrderPlaced>`. */\nexport type PayloadOf<TEvent> = TEvent extends EventClass<infer TPayload> ? TPayload : never;\n\n/** Anything that names an event type: an event class or the type string itself. */\nexport type EventReference = { readonly type: string } | string;\n\nexport interface DefineEventOptions<TSchema extends StandardSchemaV1> {\n /** Validates the payload on publish and before every handler call. */\n readonly schema: TSchema;\n /** Ordering key of every event of this type, from its validated payload. See {@link DefineEventKeyOptions}. */\n readonly key?: (payload: StandardSchemaV1.InferOutput<TSchema>) => string;\n}\n\nexport interface DefineEventKeyOptions<TPayload> {\n /**\n * Ordering key of every event of this type, from its payload: `(payload) => payload.orderId`.\n * Typed from the payload, so a missing field or a non-string fails to compile. `publish` uses it\n * when it is given no `key`; an explicit `key` option wins (for `publishAll`, the one key of the\n * call applies to every event). It must return a non-empty string.\n */\n readonly key: (payload: TPayload) => string;\n}\n\nconst EVENT_TYPE_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._:/-]{0,254}$/;\n\nexport function assertEventType(type: string): void {\n if (!EVENT_TYPE_PATTERN.test(type)) {\n throw new ConfigurationError(\n `Event type '${type}' must be 1-255 characters of letters, digits, '.', '_', ':', '/' or '-', starting with a letter or digit`,\n );\n }\n}\n\n/**\n * Defines an event type. Extend the returned class to name it:\n *\n * ```ts\n * export class OrderPlaced extends defineEvent<{ orderId: string }>('order.placed.v1') {}\n * export class OrderShipped extends defineEvent('order.shipped.v1', { schema: orderShippedSchema }) {}\n * export class OrderPaid extends defineEvent('order.paid.v1', {\n * schema: orderPaidSchema,\n * key: (payload) => payload.orderId,\n * }) {}\n * export class OrderCancelled extends defineEvent<{ orderId: string }>('order.cancelled.v1', {\n * key: (payload) => payload.orderId,\n * }) {}\n * ```\n */\nexport function defineEvent<TSchema extends StandardSchemaV1>(\n type: string,\n options: DefineEventOptions<TSchema>,\n): EventClass<StandardSchemaV1.InferOutput<TSchema>>;\nexport function defineEvent<TPayload>(\n type: string,\n options?: DefineEventKeyOptions<TPayload>,\n): EventClass<TPayload>;\nexport function defineEvent(\n type: string,\n options?: Partial<DefineEventOptions<StandardSchemaV1>>,\n): EventClass<unknown> {\n assertEventType(type);\n const schema = options?.schema;\n const key = options?.key;\n return class DefinedEvent implements DomainEvent<unknown> {\n static readonly type = type;\n static readonly schema = schema;\n static readonly key = key;\n readonly type = type;\n constructor(readonly payload: unknown) {}\n };\n}\n\n/** Runs a Standard Schema and returns its output, or throws {@link EventValidationError}. */\n// eslint-disable-next-line relaybus/max-two-params -- exported API validatePayload keeps its public signature\nexport async function validatePayload<TPayload>(\n type: string,\n schema: StandardSchemaV1<unknown, TPayload> | undefined,\n payload: unknown,\n): Promise<TPayload> {\n if (schema === undefined) {\n return payload as TPayload;\n }\n const result = await schema['~standard'].validate(payload);\n if (result.issues !== undefined) {\n const issues = result.issues.map((issue) => ({\n message: issue.message,\n path: issue.path?.map((segment) => (typeof segment === 'object' ? segment.key : segment)),\n }));\n throw new EventValidationError(\n `Payload of '${type}' failed validation: ${issues.map((issue) => issue.message).join('; ')}`,\n issues,\n );\n }\n return result.value;\n}\n\n/**\n * The ordering key an event of `event`'s class takes from its definition, or null when the class\n * defines no key.\n *\n * @throws ConfigurationError when the key function returns an empty string or no string.\n */\nexport function keyFromDefinition(event: DomainEvent, payload: unknown): string | null {\n const keyOf = (event.constructor as Partial<EventClass>).key;\n if (keyOf === undefined) {\n return null;\n }\n const key: unknown = keyOf(payload);\n if (typeof key !== 'string' || key.length === 0) {\n throw new ConfigurationError(\n `The key function of '${event.type}' must return a non-empty string | returned=${typeof key === 'string' ? \"''\" : typeof key}`,\n );\n }\n return key;\n}\n","import type { Clock } from '../clock.js';\n\n/** A task for {@link schedule}: what runs, after how long, whether it repeats and keeps the process alive. */\nexport type ScheduledTask = Parameters<NonNullable<Clock['schedule']>>[0];\n\n/** Cancels a scheduled task; harmless once it ran or was cancelled. */\nexport type CancelTimer = () => void;\n\n/**\n * The one place relaybus starts timers: through `clock.schedule` when the clock controls timers,\n * else with the platform timers.\n */\nexport function schedule(clock: Clock, task: ScheduledTask): CancelTimer {\n return clock.schedule === undefined ? scheduleOnPlatform(task) : clock.schedule(task);\n}\n\n/** Resolves after `milliseconds` on the timers of `clock`. */\nexport function sleep(clock: Clock, milliseconds: number): Promise<void> {\n return new Promise((resolve) => {\n schedule(clock, { run: resolve, delayMs: milliseconds });\n });\n}\n\nfunction scheduleOnPlatform(task: ScheduledTask): CancelTimer {\n if (task.repeat === true) {\n const interval = setInterval(task.run, task.delayMs);\n if (task.unref === true) {\n interval.unref();\n }\n return () => clearInterval(interval);\n }\n const timeout = setTimeout(task.run, task.delayMs);\n if (task.unref === true) {\n timeout.unref();\n }\n return () => clearTimeout(timeout);\n}\n","import { ConfigurationError } from '../errors.js';\n\n/** Returns `value` when it is an integer of at least 1, else throws a {@link ConfigurationError} naming the option. */\nexport function assertPositiveInteger(value: number, name: string): number {\n if (!Number.isInteger(value) || value < 1) {\n throw new ConfigurationError(`${name} must be a positive integer, received ${String(value)}`);\n }\n return value;\n}\n"]}
@@ -0,0 +1,142 @@
1
+ /** Source of the current time. Replace it in tests to control retries and leases. */
2
+ interface Clock {
3
+ now(): Date;
4
+ /**
5
+ * Runs `task.run` after `task.delayMs` milliseconds, again every `delayMs` when `repeat` is set, and
6
+ * returns a function that cancels it. `unref` marks a timer that must not keep the process alive.
7
+ * Optional: without it relaybus uses the platform timers. Implement it to control timers in tests
8
+ * (`FakeClock` does with `controlTimers: true`).
9
+ */
10
+ schedule?(task: {
11
+ readonly run: () => void;
12
+ readonly delayMs: number;
13
+ readonly repeat?: boolean;
14
+ readonly unref?: boolean;
15
+ }): () => void;
16
+ }
17
+ declare const systemClock: Clock;
18
+
19
+ /**
20
+ * The Standard Schema interface (https://standardschema.dev), copied as the
21
+ * specification recommends so relaybus needs no runtime dependency. Zod,
22
+ * Valibot, ArkType and other libraries implement it.
23
+ */
24
+ interface StandardSchemaV1<Input = unknown, Output = Input> {
25
+ readonly '~standard': StandardSchemaV1.Props<Input, Output>;
26
+ }
27
+ declare namespace StandardSchemaV1 {
28
+ interface Props<Input = unknown, Output = Input> {
29
+ readonly version: 1;
30
+ readonly vendor: string;
31
+ readonly validate: (value: unknown) => Result<Output> | Promise<Result<Output>>;
32
+ readonly types?: Types<Input, Output> | undefined;
33
+ }
34
+ type Result<Output> = SuccessResult<Output> | FailureResult;
35
+ interface SuccessResult<Output> {
36
+ readonly value: Output;
37
+ readonly issues?: undefined;
38
+ }
39
+ interface FailureResult {
40
+ readonly issues: ReadonlyArray<Issue>;
41
+ }
42
+ interface Issue {
43
+ readonly message: string;
44
+ readonly path?: ReadonlyArray<PropertyKey | PathSegment> | undefined;
45
+ }
46
+ interface PathSegment {
47
+ readonly key: PropertyKey;
48
+ }
49
+ interface Types<Input = unknown, Output = Input> {
50
+ readonly input: Input;
51
+ readonly output: Output;
52
+ }
53
+ type InferInput<Schema extends StandardSchemaV1> = NonNullable<Schema['~standard']['types']>['input'];
54
+ type InferOutput<Schema extends StandardSchemaV1> = NonNullable<Schema['~standard']['types']>['output'];
55
+ }
56
+
57
+ /** String metadata carried with an event, such as `traceparent`. */
58
+ type EventHeaders = Readonly<Record<string, string>>;
59
+ /**
60
+ * An event as stored and delivered. Field names follow CloudEvents where they
61
+ * overlap (`id`, `type`, `source`, `time` as `occurredAt`, `subject` as `key`).
62
+ */
63
+ interface EventEnvelope<TPayload = unknown> {
64
+ /** Globally unique id. Handlers and transports deduplicate on it. */
65
+ readonly id: string;
66
+ /** Event type, for example `order.created.v1`. */
67
+ readonly type: string;
68
+ /** Logical name of the publishing service. */
69
+ readonly source: string;
70
+ /** Ordering and partition key. Events sharing a key are handled in publish order. */
71
+ readonly key: string | null;
72
+ readonly payload: TPayload;
73
+ readonly headers: EventHeaders;
74
+ /** Id shared by every event of one business flow. */
75
+ readonly correlationId: string | null;
76
+ /** Id of the event whose handler published this one. */
77
+ readonly causationId: string | null;
78
+ readonly occurredAt: Date;
79
+ }
80
+ /** An instance of a class created with {@link defineEvent}. */
81
+ interface DomainEvent<TPayload = unknown> {
82
+ readonly type: string;
83
+ readonly payload: TPayload;
84
+ }
85
+ /**
86
+ * Derives the ordering key of an event from its validated payload. Declared bivariantly so an
87
+ * event class stays assignable wherever its payload type is widened.
88
+ */
89
+ type EventKeyFunction<TPayload> = {
90
+ bivarianceHack(payload: TPayload): string;
91
+ }['bivarianceHack'];
92
+ /** A class created with {@link defineEvent}. */
93
+ interface EventClass<TPayload = unknown> {
94
+ new (payload: TPayload): DomainEvent<TPayload>;
95
+ readonly type: string;
96
+ readonly schema: StandardSchemaV1<unknown, TPayload> | undefined;
97
+ /** The `key` given to {@link defineEvent}; undefined for events without one. */
98
+ readonly key?: EventKeyFunction<TPayload> | undefined;
99
+ }
100
+ /** Payload type of an event class: `PayloadOf<typeof OrderPlaced>`. */
101
+ type PayloadOf<TEvent> = TEvent extends EventClass<infer TPayload> ? TPayload : never;
102
+ /** Anything that names an event type: an event class or the type string itself. */
103
+ type EventReference = {
104
+ readonly type: string;
105
+ } | string;
106
+ interface DefineEventOptions<TSchema extends StandardSchemaV1> {
107
+ /** Validates the payload on publish and before every handler call. */
108
+ readonly schema: TSchema;
109
+ /** Ordering key of every event of this type, from its validated payload. See {@link DefineEventKeyOptions}. */
110
+ readonly key?: (payload: StandardSchemaV1.InferOutput<TSchema>) => string;
111
+ }
112
+ interface DefineEventKeyOptions<TPayload> {
113
+ /**
114
+ * Ordering key of every event of this type, from its payload: `(payload) => payload.orderId`.
115
+ * Typed from the payload, so a missing field or a non-string fails to compile. `publish` uses it
116
+ * when it is given no `key`; an explicit `key` option wins (for `publishAll`, the one key of the
117
+ * call applies to every event). It must return a non-empty string.
118
+ */
119
+ readonly key: (payload: TPayload) => string;
120
+ }
121
+ declare function assertEventType(type: string): void;
122
+ /**
123
+ * Defines an event type. Extend the returned class to name it:
124
+ *
125
+ * ```ts
126
+ * export class OrderPlaced extends defineEvent<{ orderId: string }>('order.placed.v1') {}
127
+ * export class OrderShipped extends defineEvent('order.shipped.v1', { schema: orderShippedSchema }) {}
128
+ * export class OrderPaid extends defineEvent('order.paid.v1', {
129
+ * schema: orderPaidSchema,
130
+ * key: (payload) => payload.orderId,
131
+ * }) {}
132
+ * export class OrderCancelled extends defineEvent<{ orderId: string }>('order.cancelled.v1', {
133
+ * key: (payload) => payload.orderId,
134
+ * }) {}
135
+ * ```
136
+ */
137
+ declare function defineEvent<TSchema extends StandardSchemaV1>(type: string, options: DefineEventOptions<TSchema>): EventClass<StandardSchemaV1.InferOutput<TSchema>>;
138
+ declare function defineEvent<TPayload>(type: string, options?: DefineEventKeyOptions<TPayload>): EventClass<TPayload>;
139
+ /** Runs a Standard Schema and returns its output, or throws {@link EventValidationError}. */
140
+ declare function validatePayload<TPayload>(type: string, schema: StandardSchemaV1<unknown, TPayload> | undefined, payload: unknown): Promise<TPayload>;
141
+
142
+ export { type Clock as C, type DomainEvent as D, type EventEnvelope as E, type PayloadOf as P, StandardSchemaV1 as S, type EventHeaders as a, type EventReference as b, type EventClass as c, type DefineEventKeyOptions as d, type DefineEventOptions as e, type EventKeyFunction as f, assertEventType as g, defineEvent as h, systemClock as s, validatePayload as v };
@@ -0,0 +1,142 @@
1
+ /** Source of the current time. Replace it in tests to control retries and leases. */
2
+ interface Clock {
3
+ now(): Date;
4
+ /**
5
+ * Runs `task.run` after `task.delayMs` milliseconds, again every `delayMs` when `repeat` is set, and
6
+ * returns a function that cancels it. `unref` marks a timer that must not keep the process alive.
7
+ * Optional: without it relaybus uses the platform timers. Implement it to control timers in tests
8
+ * (`FakeClock` does with `controlTimers: true`).
9
+ */
10
+ schedule?(task: {
11
+ readonly run: () => void;
12
+ readonly delayMs: number;
13
+ readonly repeat?: boolean;
14
+ readonly unref?: boolean;
15
+ }): () => void;
16
+ }
17
+ declare const systemClock: Clock;
18
+
19
+ /**
20
+ * The Standard Schema interface (https://standardschema.dev), copied as the
21
+ * specification recommends so relaybus needs no runtime dependency. Zod,
22
+ * Valibot, ArkType and other libraries implement it.
23
+ */
24
+ interface StandardSchemaV1<Input = unknown, Output = Input> {
25
+ readonly '~standard': StandardSchemaV1.Props<Input, Output>;
26
+ }
27
+ declare namespace StandardSchemaV1 {
28
+ interface Props<Input = unknown, Output = Input> {
29
+ readonly version: 1;
30
+ readonly vendor: string;
31
+ readonly validate: (value: unknown) => Result<Output> | Promise<Result<Output>>;
32
+ readonly types?: Types<Input, Output> | undefined;
33
+ }
34
+ type Result<Output> = SuccessResult<Output> | FailureResult;
35
+ interface SuccessResult<Output> {
36
+ readonly value: Output;
37
+ readonly issues?: undefined;
38
+ }
39
+ interface FailureResult {
40
+ readonly issues: ReadonlyArray<Issue>;
41
+ }
42
+ interface Issue {
43
+ readonly message: string;
44
+ readonly path?: ReadonlyArray<PropertyKey | PathSegment> | undefined;
45
+ }
46
+ interface PathSegment {
47
+ readonly key: PropertyKey;
48
+ }
49
+ interface Types<Input = unknown, Output = Input> {
50
+ readonly input: Input;
51
+ readonly output: Output;
52
+ }
53
+ type InferInput<Schema extends StandardSchemaV1> = NonNullable<Schema['~standard']['types']>['input'];
54
+ type InferOutput<Schema extends StandardSchemaV1> = NonNullable<Schema['~standard']['types']>['output'];
55
+ }
56
+
57
+ /** String metadata carried with an event, such as `traceparent`. */
58
+ type EventHeaders = Readonly<Record<string, string>>;
59
+ /**
60
+ * An event as stored and delivered. Field names follow CloudEvents where they
61
+ * overlap (`id`, `type`, `source`, `time` as `occurredAt`, `subject` as `key`).
62
+ */
63
+ interface EventEnvelope<TPayload = unknown> {
64
+ /** Globally unique id. Handlers and transports deduplicate on it. */
65
+ readonly id: string;
66
+ /** Event type, for example `order.created.v1`. */
67
+ readonly type: string;
68
+ /** Logical name of the publishing service. */
69
+ readonly source: string;
70
+ /** Ordering and partition key. Events sharing a key are handled in publish order. */
71
+ readonly key: string | null;
72
+ readonly payload: TPayload;
73
+ readonly headers: EventHeaders;
74
+ /** Id shared by every event of one business flow. */
75
+ readonly correlationId: string | null;
76
+ /** Id of the event whose handler published this one. */
77
+ readonly causationId: string | null;
78
+ readonly occurredAt: Date;
79
+ }
80
+ /** An instance of a class created with {@link defineEvent}. */
81
+ interface DomainEvent<TPayload = unknown> {
82
+ readonly type: string;
83
+ readonly payload: TPayload;
84
+ }
85
+ /**
86
+ * Derives the ordering key of an event from its validated payload. Declared bivariantly so an
87
+ * event class stays assignable wherever its payload type is widened.
88
+ */
89
+ type EventKeyFunction<TPayload> = {
90
+ bivarianceHack(payload: TPayload): string;
91
+ }['bivarianceHack'];
92
+ /** A class created with {@link defineEvent}. */
93
+ interface EventClass<TPayload = unknown> {
94
+ new (payload: TPayload): DomainEvent<TPayload>;
95
+ readonly type: string;
96
+ readonly schema: StandardSchemaV1<unknown, TPayload> | undefined;
97
+ /** The `key` given to {@link defineEvent}; undefined for events without one. */
98
+ readonly key?: EventKeyFunction<TPayload> | undefined;
99
+ }
100
+ /** Payload type of an event class: `PayloadOf<typeof OrderPlaced>`. */
101
+ type PayloadOf<TEvent> = TEvent extends EventClass<infer TPayload> ? TPayload : never;
102
+ /** Anything that names an event type: an event class or the type string itself. */
103
+ type EventReference = {
104
+ readonly type: string;
105
+ } | string;
106
+ interface DefineEventOptions<TSchema extends StandardSchemaV1> {
107
+ /** Validates the payload on publish and before every handler call. */
108
+ readonly schema: TSchema;
109
+ /** Ordering key of every event of this type, from its validated payload. See {@link DefineEventKeyOptions}. */
110
+ readonly key?: (payload: StandardSchemaV1.InferOutput<TSchema>) => string;
111
+ }
112
+ interface DefineEventKeyOptions<TPayload> {
113
+ /**
114
+ * Ordering key of every event of this type, from its payload: `(payload) => payload.orderId`.
115
+ * Typed from the payload, so a missing field or a non-string fails to compile. `publish` uses it
116
+ * when it is given no `key`; an explicit `key` option wins (for `publishAll`, the one key of the
117
+ * call applies to every event). It must return a non-empty string.
118
+ */
119
+ readonly key: (payload: TPayload) => string;
120
+ }
121
+ declare function assertEventType(type: string): void;
122
+ /**
123
+ * Defines an event type. Extend the returned class to name it:
124
+ *
125
+ * ```ts
126
+ * export class OrderPlaced extends defineEvent<{ orderId: string }>('order.placed.v1') {}
127
+ * export class OrderShipped extends defineEvent('order.shipped.v1', { schema: orderShippedSchema }) {}
128
+ * export class OrderPaid extends defineEvent('order.paid.v1', {
129
+ * schema: orderPaidSchema,
130
+ * key: (payload) => payload.orderId,
131
+ * }) {}
132
+ * export class OrderCancelled extends defineEvent<{ orderId: string }>('order.cancelled.v1', {
133
+ * key: (payload) => payload.orderId,
134
+ * }) {}
135
+ * ```
136
+ */
137
+ declare function defineEvent<TSchema extends StandardSchemaV1>(type: string, options: DefineEventOptions<TSchema>): EventClass<StandardSchemaV1.InferOutput<TSchema>>;
138
+ declare function defineEvent<TPayload>(type: string, options?: DefineEventKeyOptions<TPayload>): EventClass<TPayload>;
139
+ /** Runs a Standard Schema and returns its output, or throws {@link EventValidationError}. */
140
+ declare function validatePayload<TPayload>(type: string, schema: StandardSchemaV1<unknown, TPayload> | undefined, payload: unknown): Promise<TPayload>;
141
+
142
+ export { type Clock as C, type DomainEvent as D, type EventEnvelope as E, type PayloadOf as P, StandardSchemaV1 as S, type EventHeaders as a, type EventReference as b, type EventClass as c, type DefineEventKeyOptions as d, type DefineEventOptions as e, type EventKeyFunction as f, assertEventType as g, defineEvent as h, systemClock as s, validatePayload as v };