CommandGateway
One entry point for the commands of several aggregates, like Axon’s
CommandGateway: the caller hands over a command and the gateway finds the
aggregate that takes it.
const gateway = yield* CommandGateway.make([Todo, Account], { interceptors: [audit]})
// Typed: the payload and the errors follow from the aggregate and the type.yield* gateway.send({ aggregateName: "todo", aggregateId: "a", type: "createTodo", payload: { title: "Buy Milk" } })
// Untyped JSON from a transport, routed by `aggregateName`, or by `type` alone// when a single aggregate has a command of that name.yield* gateway.dispatch({ aggregateId: "a", type: "completeTodo", payload: {} })The gateway composes aggregate services. Give it an aggregate and it builds the
service with the default options; give it a service built with
AggregateService.make to choose them, or to share the service, and its state
cache, with code that uses it directly.
Interceptors run around every command the gateway routes, for what Axon’s
dispatch interceptors do: authorize, log, add metadata with
Metadata.withMetadata. They run in the caller’s fiber, so what they need, such
as the current user, comes from the caller’s context rather than the gateway’s.
Classes
Section titled “Classes”UnroutableCommand
Section titled “UnroutableCommand”Defined in: src/CommandGateway.ts:41
The gateway can’t tell which aggregate a command is for: the envelope names an aggregate the gateway doesn’t have, or it names none and the type is a command of no aggregate, or of more than one.
Extends
Section titled “Extends”object&YieldableError<this>
Constructors
Section titled “Constructors”Constructor
Section titled “Constructor”new UnroutableCommand(…
args):UnroutableCommand
Defined in: node_modules/.pnpm/effect@4.0.6/node_modules/effect/dist/Schema.d.ts:10979
Parameters
Section titled “Parameters”…[props: object, options?: MakeOptions]
Returns
Section titled “Returns”Inherited from
Section titled “Inherited from”Schema.TaggedError<UnroutableCommand>()("UnroutableCommand", { type: Schema.String, /** The aggregate the envelope named, if it named one. */ aggregateName: Schema.optional(Schema.String), /** The aggregates of the gateway that have a command of this type. */ candidates: Schema.Array(Schema.String), message: Schema.String }).constructor
Properties
Section titled “Properties”aggregateName?
Section titled “aggregateName?”
readonlyoptionalaggregateName?:string
Defined in: src/CommandGateway.ts:44
The aggregate the envelope named, if it named one.
Inherited from
Section titled “Inherited from”Schema.TaggedError<UnroutableCommand>()("UnroutableCommand", { type: Schema.String, /** The aggregate the envelope named, if it named one. */ aggregateName: Schema.optional(Schema.String), /** The aggregates of the gateway that have a command of this type. */ candidates: Schema.Array(Schema.String), message: Schema.String }).aggregateName
candidates
Section titled “candidates”
readonlycandidates: readonlystring[]
Defined in: src/CommandGateway.ts:46
The aggregates of the gateway that have a command of this type.
Inherited from
Section titled “Inherited from”Schema.TaggedError<UnroutableCommand>()("UnroutableCommand", { type: Schema.String, /** The aggregate the envelope named, if it named one. */ aggregateName: Schema.optional(Schema.String), /** The aggregates of the gateway that have a command of this type. */ candidates: Schema.Array(Schema.String), message: Schema.String }).candidates
message
Section titled “message”message:
string=Schema.String
Defined in: src/CommandGateway.ts:47
Inherited from
Section titled “Inherited from”Schema.TaggedError<UnroutableCommand>()("UnroutableCommand", { type: Schema.String, /** The aggregate the envelope named, if it named one. */ aggregateName: Schema.optional(Schema.String), /** The aggregates of the gateway that have a command of this type. */ candidates: Schema.Array(Schema.String), message: Schema.String }).message
readonlytype:string=Schema.String
Defined in: src/CommandGateway.ts:42
Inherited from
Section titled “Inherited from”Schema.TaggedError<UnroutableCommand>()("UnroutableCommand", { type: Schema.String, /** The aggregate the envelope named, if it named one. */ aggregateName: Schema.optional(Schema.String), /** The aggregates of the gateway that have a command of this type. */ candidates: Schema.Array(Schema.String), message: Schema.String }).type
Interfaces
Section titled “Interfaces”CommandGateway
Section titled “CommandGateway”Defined in: src/CommandGateway.ts:119
Type Parameters
Section titled “Type Parameters”A extends Any
E = never
R = never
Properties
Section titled “Properties”dispatch
Section titled “dispatch”
readonlydispatch: (input) =>Effect<CommandResult<EventOf<A>>,UnknownCommand|CommandFailure|UnroutableCommand|E|HandlerError<A,string>,R>
Defined in: src/CommandGateway.ts:139
Runs a { aggregateName, aggregateId, type, payload } envelope received as
JSON from outside the process, with the other fields AggregateService.dispatch
takes. aggregateName can be left out when a single aggregate of the gateway
has a command of that type.
Parameters
Section titled “Parameters”unknown
Returns
Section titled “Returns”Effect<CommandResult<EventOf<A>>, UnknownCommand | CommandFailure | UnroutableCommand | E | HandlerError<A, string>, R>
readonlysend: <C>(command) =>Effect<CommandResult<Event<Extract<A, {name:C["aggregateName"]; }>>>,CommandFailure|E|HandlerError<Extract<A, {name:C["aggregateName"]; }>,C["type"]>,R>
Defined in: src/CommandGateway.ts:126
Runs a typed command on the aggregate it names.
Type Parameters
Section titled “Type Parameters”C extends object & CommandOptions
Parameters
Section titled “Parameters”command
Section titled “command”C
Returns
Section titled “Returns”Effect<CommandResult<Event<Extract<A, { name: C["aggregateName"]; }>>>, CommandFailure | E | HandlerError<Extract<A, { name: C["aggregateName"]; }>, C["type"]>, R>
services
Section titled “services”
readonlyservices:{ readonly [X in Any as Name<X>]: AggregateService<X> }
Defined in: src/CommandGateway.ts:124
The service of each aggregate, by name, for reading with state and
history. Commands run through a service directly skip the interceptors.
CommandInfo
Section titled “CommandInfo”Defined in: src/CommandGateway.ts:51
What an interceptor learns about the command it runs around.
Properties
Section titled “Properties”aggregateId
Section titled “aggregateId”
readonlyaggregateId:string
Defined in: src/CommandGateway.ts:53
aggregateName
Section titled “aggregateName”
readonlyaggregateName:string
Defined in: src/CommandGateway.ts:52
readonlytype:string
Defined in: src/CommandGateway.ts:54
Interceptor()
Section titled “Interceptor()”Defined in: src/CommandGateway.ts:71
Runs around a command. It may run effects before and after next, fail
instead of running it, or run it with more context, and adds its own errors
E and requirements R to every command of the gateway.
const audit: CommandGateway.Interceptor<Unauthorized, CurrentUser> = (command, next) => Effect.gen(function*() { const user = yield* CurrentUser if (!user.may(command.type)) return yield* new Unauthorized({ type: command.type }) return yield* Metadata.withMetadata(next, { userId: user.id }) })Type Parameters
Section titled “Type Parameters”E = never
R = never
Interceptor<
A,E1,R1>(command,next):Effect<A,E|E1,R|R1>
Defined in: src/CommandGateway.ts:72
Runs around a command. It may run effects before and after next, fail
instead of running it, or run it with more context, and adds its own errors
E and requirements R to every command of the gateway.
const audit: CommandGateway.Interceptor<Unauthorized, CurrentUser> = (command, next) => Effect.gen(function*() { const user = yield* CurrentUser if (!user.may(command.type)) return yield* new Unauthorized({ type: command.type }) return yield* Metadata.withMetadata(next, { userId: user.id }) })Type Parameters
Section titled “Type Parameters”A
E1
R1
Parameters
Section titled “Parameters”command
Section titled “command”Effect<A, E1, R1>
Returns
Section titled “Returns”Effect<A, E | E1, R | R1>
Options
Section titled “Options”Defined in: src/CommandGateway.ts:152
Type Parameters
Section titled “Type Parameters”Interceptors
Section titled “Interceptors”Interceptors extends ReadonlyArray<Interceptor<any, any>>
Properties
Section titled “Properties”interceptors?
Section titled “interceptors?”
readonlyoptionalinterceptors?:Interceptors
Defined in: src/CommandGateway.ts:154
Run around every command, the first outermost.
Type Aliases
Section titled “Type Aliases”AggregateOf
Section titled “AggregateOf”AggregateOf<
X> =Xextendsobject?A:XextendsAny?X:never
Defined in: src/CommandGateway.ts:79
The aggregate of an entry.
Type Parameters
Section titled “Type Parameters”X
Command
Section titled “Command”Command<
A> =AextendsAny?{ readonly [K in CommandName<A>]: { aggregateId: string; aggregateName: Name<A>; payload: Payload<A, K>; type: K } & CommandOptions }[CommandName<A>] :never
Defined in: src/CommandGateway.ts:96
A typed command for one of the aggregates A, what CommandGateway.send takes.
Type Parameters
Section titled “Type Parameters”A extends Any
Entry =
Any|AggregateService<any>
Defined in: src/CommandGateway.ts:76
What a gateway routes to: an aggregate, or the service of one.
EventOf
Section titled “EventOf”Defined in: src/CommandGateway.ts:117
The events of any aggregate of A.
Type Parameters
Section titled “Type Parameters”A extends Any
HandlerError
Section titled “HandlerError”HandlerError<
A,Type> =AextendsAny?CommandError<A,Type&CommandName<A>> :never
Defined in: src/CommandGateway.ts:112
The errors the handler of a command declares.
Type Parameters
Section titled “Type Parameters”A extends Any
Type
InterceptorContext
Section titled “InterceptorContext”InterceptorContext<
I> =IextendsInterceptor<any, infer R> ?R:never
Defined in: src/CommandGateway.ts:93
What an interceptor requires from the caller, read from its type like InterceptorError.
Type Parameters
Section titled “Type Parameters”I
InterceptorError
Section titled “InterceptorError”InterceptorError<
I> =IextendsInterceptor<infer E,any> ?E:never
Defined in: src/CommandGateway.ts:90
The errors an interceptor adds. They are read from its type, so declare an
interceptor as an Interceptor<E, R> rather than inline in the options.
Type Parameters
Section titled “Type Parameters”I
Named<
A,Name> =Extract<A, {name:Name; }>
Defined in: src/CommandGateway.ts:109
The aggregate of A with this name.
Type Parameters
Section titled “Type Parameters”A extends Any
Name
Requirements
Section titled “Requirements”Requirements<
X> =XextendsAny?EventStore|Context<X> :never
Defined in: src/CommandGateway.ts:84
What building the services of the entries requires: entries that are services are already built.
Type Parameters
Section titled “Type Parameters”X
Functions
Section titled “Functions”make()
Section titled “make()”make<
Entries,Interceptors>(entries,options?):Effect<CommandGateway<AggregateOf<Entries[number]>,InterceptorError<Interceptors[number]>,InterceptorContext<Interceptors[number]>>,never,Requirements<Entries[number]>>
Defined in: src/CommandGateway.ts:263
Builds a gateway over aggregates, or over services of them. Two entries for the same aggregate are a defect.
Type Parameters
Section titled “Type Parameters”Entries
Section titled “Entries”Entries extends readonly Entry[]
Interceptors
Section titled “Interceptors”Interceptors extends readonly Interceptor<any, any>[] = []
Parameters
Section titled “Parameters”entries
Section titled “entries”Entries
options?
Section titled “options?”Options<Interceptors>
Returns
Section titled “Returns”Effect<CommandGateway<AggregateOf<Entries[number]>, InterceptorError<Interceptors[number]>, InterceptorContext<Interceptors[number]>>, never, Requirements<Entries[number]>>