@codeforbreakfast/eventsourcing-commands
Version:
Wire command validation and dispatch for event sourcing systems - External boundary layer with schema validation
233 lines • 10.1 kB
TypeScript
import { Schema, Effect } from 'effect';
import type { ReadonlyDeep } from 'type-fest';
/**
* Wire command for transport/serialization
* Used by APIs, message queues, and other external interfaces
*/
export declare const WireCommand: Schema.Struct<{
id: typeof Schema.String;
target: typeof Schema.String;
name: typeof Schema.String;
payload: typeof Schema.Unknown;
}>;
export type WireCommand = typeof WireCommand.Type;
/**
* Base domain command interface
* The validated internal representation
*/
export interface DomainCommand<TPayload> {
readonly id: string;
readonly target: string;
readonly name: string;
readonly payload: TPayload;
}
declare const CommandValidationError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => import("effect/Cause").YieldableError & {
readonly _tag: "CommandValidationError";
} & Readonly<A>;
export declare class CommandValidationError extends CommandValidationError_base<{
readonly commandId: string;
readonly commandName: string;
readonly validationErrors: ReadonlyArray<string>;
}> {
}
declare const CommandHandlerNotFoundError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => import("effect/Cause").YieldableError & {
readonly _tag: "CommandHandlerNotFoundError";
} & Readonly<A>;
export declare class CommandHandlerNotFoundError extends CommandHandlerNotFoundError_base<{
readonly commandId: string;
readonly commandName: string;
readonly availableHandlers: ReadonlyArray<string>;
}> {
}
declare const CommandExecutionError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => import("effect/Cause").YieldableError & {
readonly _tag: "CommandExecutionError";
} & Readonly<A>;
export declare class CommandExecutionError extends CommandExecutionError_base<{
readonly commandId: string;
readonly commandName: string;
readonly cause: unknown;
}> {
}
declare const AggregateNotFoundError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => import("effect/Cause").YieldableError & {
readonly _tag: "AggregateNotFoundError";
} & Readonly<A>;
export declare class AggregateNotFoundError extends AggregateNotFoundError_base<{
readonly commandId: string;
readonly aggregateId: string;
readonly aggregateType: string;
}> {
}
declare const ConcurrencyConflictError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => import("effect/Cause").YieldableError & {
readonly _tag: "ConcurrencyConflictError";
} & Readonly<A>;
export declare class ConcurrencyConflictError extends ConcurrencyConflictError_base<{
readonly commandId: string;
readonly expectedVersion: number;
readonly actualVersion: number;
}> {
}
export declare const CommandSuccess: Schema.Struct<{
_tag: Schema.Literal<["Success"]>;
position: Schema.Struct<{
streamId: Schema.brand<Schema.filter<typeof Schema.String>, "EventStreamId">;
eventNumber: Schema.filter<typeof Schema.Number>;
}>;
}>;
export type CommandSuccess = typeof CommandSuccess.Type;
export declare const CommandFailure: Schema.Struct<{
_tag: Schema.Literal<["Failure"]>;
error: Schema.Union<[Schema.Struct<{
_tag: Schema.Literal<["ValidationError"]>;
commandId: typeof Schema.String;
commandName: typeof Schema.String;
validationErrors: Schema.Array$<typeof Schema.String>;
}>, Schema.Struct<{
_tag: Schema.Literal<["HandlerNotFound"]>;
commandId: typeof Schema.String;
commandName: typeof Schema.String;
availableHandlers: Schema.Array$<typeof Schema.String>;
}>, Schema.Struct<{
_tag: Schema.Literal<["ExecutionError"]>;
commandId: typeof Schema.String;
commandName: typeof Schema.String;
message: typeof Schema.String;
}>, Schema.Struct<{
_tag: Schema.Literal<["AggregateNotFound"]>;
commandId: typeof Schema.String;
aggregateId: typeof Schema.String;
aggregateType: typeof Schema.String;
}>, Schema.Struct<{
_tag: Schema.Literal<["ConcurrencyConflict"]>;
commandId: typeof Schema.String;
expectedVersion: typeof Schema.Number;
actualVersion: typeof Schema.Number;
}>, Schema.Struct<{
_tag: Schema.Literal<["UnknownError"]>;
commandId: typeof Schema.String;
message: typeof Schema.String;
}>]>;
}>;
export type CommandFailure = typeof CommandFailure.Type;
export declare const CommandResult: Schema.Union<[Schema.Struct<{
_tag: Schema.Literal<["Success"]>;
position: Schema.Struct<{
streamId: Schema.brand<Schema.filter<typeof Schema.String>, "EventStreamId">;
eventNumber: Schema.filter<typeof Schema.Number>;
}>;
}>, Schema.Struct<{
_tag: Schema.Literal<["Failure"]>;
error: Schema.Union<[Schema.Struct<{
_tag: Schema.Literal<["ValidationError"]>;
commandId: typeof Schema.String;
commandName: typeof Schema.String;
validationErrors: Schema.Array$<typeof Schema.String>;
}>, Schema.Struct<{
_tag: Schema.Literal<["HandlerNotFound"]>;
commandId: typeof Schema.String;
commandName: typeof Schema.String;
availableHandlers: Schema.Array$<typeof Schema.String>;
}>, Schema.Struct<{
_tag: Schema.Literal<["ExecutionError"]>;
commandId: typeof Schema.String;
commandName: typeof Schema.String;
message: typeof Schema.String;
}>, Schema.Struct<{
_tag: Schema.Literal<["AggregateNotFound"]>;
commandId: typeof Schema.String;
aggregateId: typeof Schema.String;
aggregateType: typeof Schema.String;
}>, Schema.Struct<{
_tag: Schema.Literal<["ConcurrencyConflict"]>;
commandId: typeof Schema.String;
expectedVersion: typeof Schema.Number;
actualVersion: typeof Schema.Number;
}>, Schema.Struct<{
_tag: Schema.Literal<["UnknownError"]>;
commandId: typeof Schema.String;
message: typeof Schema.String;
}>]>;
}>]>;
export type CommandResult = typeof CommandResult.Type;
export declare const isCommandSuccess: (u: unknown, overrideOptions?: import("effect/SchemaAST").ParseOptions | number) => u is {
readonly _tag: "Success";
readonly position: {
readonly streamId: string & import("effect/Brand").Brand<"EventStreamId">;
readonly eventNumber: number;
};
};
export declare const isCommandFailure: (u: unknown, overrideOptions?: import("effect/SchemaAST").ParseOptions | number) => u is {
readonly _tag: "Failure";
readonly error: {
readonly commandId: string;
readonly commandName: string;
readonly validationErrors: readonly string[];
readonly _tag: "ValidationError";
} | {
readonly commandId: string;
readonly commandName: string;
readonly availableHandlers: readonly string[];
readonly _tag: "HandlerNotFound";
} | {
readonly commandId: string;
readonly commandName: string;
readonly _tag: "ExecutionError";
readonly message: string;
} | {
readonly commandId: string;
readonly aggregateId: string;
readonly aggregateType: string;
readonly _tag: "AggregateNotFound";
} | {
readonly commandId: string;
readonly expectedVersion: number;
readonly actualVersion: number;
readonly _tag: "ConcurrencyConflict";
} | {
readonly commandId: string;
readonly _tag: "UnknownError";
readonly message: string;
};
};
/**
* Command definition that pairs a name with its payload schema
*/
export interface CommandDefinition<TName extends string, TPayload> {
readonly name: TName;
readonly payloadSchema: Schema.Schema<TPayload, any>;
}
/**
* Creates a command definition
*/
export declare const defineCommand: <TName extends string, TPayload, TPayloadInput>(name: TName, payloadSchema: Schema.Schema<TPayload, TPayloadInput>) => CommandDefinition<TName, TPayload>;
/**
* Helper type to extract command union from command definitions
*/
export type CommandFromDefinitions<T extends readonly CommandDefinition<string, any>[]> = {
readonly [K in keyof T]: T[K] extends CommandDefinition<infer Name, infer Payload> ? {
readonly id: string;
readonly target: string;
readonly name: Name;
readonly payload: Payload;
} : never;
}[number];
/**
* Builds a discriminated union schema from command definitions
* This creates an exhaustive schema that can parse any registered command
*/
export declare const buildCommandSchema: <const T extends readonly CommandDefinition<string, any>[]>(commands: ReadonlyDeep<T>) => Schema.Schema<CommandFromDefinitions<T>, {
readonly id: string;
readonly target: string;
readonly name: string;
readonly payload: unknown;
}>;
/**
* Validates and transforms a wire command into a domain command
*/
export declare const validateCommand: <TPayload, TPayloadInput>(payloadSchema: Schema.Schema<TPayload, TPayloadInput>) => (wireCommand: ReadonlyDeep<WireCommand>) => Effect.Effect<DomainCommand<TPayload>, CommandValidationError, never>;
/**
* Command matcher function type
* Uses Effect's pattern matching for exhaustive command handling
*/
export type CommandMatcher<TCommands extends DomainCommand<any>> = (command: ReadonlyDeep<TCommands>) => Effect.Effect<CommandResult, never, never>;
export {};
//# sourceMappingURL=commands.d.ts.map