CommandApi
Serves an aggregate over HTTP with effect/http-api: one POST endpoint per
command, and GET endpoints for history and, given a schema of the state,
state.
const TodoApi = CommandApi.group(Todo, { state: TodoStateSchema, errors: [TodoAlreadyCreated, TodoNotFound, TodoAlreadyDeleted]})
class Api extends HttpApi.make("api").add(TodoApi) {}
const TodoHandlers = CommandApi.layer(Api, "todo", AggregateService.make(Todo))| Endpoint | Does |
|---|---|
POST /todo/:aggregateId/createTodo |
Runs createTodo with the body as payload |
GET /todo/:aggregateId |
state, with an optional finishTime |
GET /todo/:aggregateId/history |
history, with optional payload, startTime, finishTime, afterVersion and limit |
The group is an ordinary HttpApiGroup, so it takes middleware, a different
prefix and OpenAPI annotations like any other, and HttpApiClient calls it.
A command’s response carries the store position of its last event, in the body
and in an Event-Position header. ReadAfter is middleware for your own
query endpoints: a request with a Read-After header waits until the view models
have handled that position, so a client reads what it just wrote.
Classes
Section titled “Classes”CommandRejected
Section titled “CommandRejected”Defined in: src/CommandApi.ts:82
A command handler failed with an error that errors doesn’t declare. Its tag
and message are kept, and the rest of it is left out of the response.
Extends
Section titled “Extends”object&YieldableError<this>
Constructors
Section titled “Constructors”Constructor
Section titled “Constructor”new CommandRejected(…
args):CommandRejected
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<CommandRejected>()("CommandRejected", { aggregateName: Schema.String, command: Schema.String, /** The tag of the handler's error. */ error: Schema.String, message: Schema.String }, { httpApiStatus: 422 }).constructor
Properties
Section titled “Properties”aggregateName
Section titled “aggregateName”
readonlyaggregateName:string=Schema.String
Defined in: src/CommandApi.ts:83
Inherited from
Section titled “Inherited from”Schema.TaggedError<CommandRejected>()("CommandRejected", { aggregateName: Schema.String, command: Schema.String, /** The tag of the handler's error. */ error: Schema.String, message: Schema.String }, { httpApiStatus: 422 }).aggregateName
command
Section titled “command”
readonlycommand:string=Schema.String
Defined in: src/CommandApi.ts:84
Inherited from
Section titled “Inherited from”Schema.TaggedError<CommandRejected>()("CommandRejected", { aggregateName: Schema.String, command: Schema.String, /** The tag of the handler's error. */ error: Schema.String, message: Schema.String }, { httpApiStatus: 422 }).command
readonlyerror:string=Schema.String
Defined in: src/CommandApi.ts:86
The tag of the handler’s error.
Inherited from
Section titled “Inherited from”Schema.TaggedError<CommandRejected>()("CommandRejected", { aggregateName: Schema.String, command: Schema.String, /** The tag of the handler's error. */ error: Schema.String, message: Schema.String }, { httpApiStatus: 422 }).error
message
Section titled “message”message:
string=Schema.String
Defined in: src/CommandApi.ts:87
Inherited from
Section titled “Inherited from”Schema.TaggedError<CommandRejected>()("CommandRejected", { aggregateName: Schema.String, command: Schema.String, /** The tag of the handler's error. */ error: Schema.String, message: Schema.String }, { httpApiStatus: 422 }).message
NotCaughtUp
Section titled “NotCaughtUp”Defined in: src/CommandApi.ts:375
The view models didn’t reach the position a Read-After header asked for in
time, because they are behind or stalled on a failing handler. Answered with
503: the client can try again, or read without the header and accept an older
answer.
Extends
Section titled “Extends”object&YieldableError<this>
Constructors
Section titled “Constructors”Constructor
Section titled “Constructor”new NotCaughtUp(…
args):NotCaughtUp
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<NotCaughtUp>()("NotCaughtUp", { /** The position the request asked for. */ position: Schema.Int, message: Schema.String }, { httpApiStatus: 503 }).constructor
Properties
Section titled “Properties”message
Section titled “message”message:
string=Schema.String
Defined in: src/CommandApi.ts:378
Inherited from
Section titled “Inherited from”Schema.TaggedError<NotCaughtUp>()("NotCaughtUp", { /** The position the request asked for. */ position: Schema.Int, message: Schema.String }, { httpApiStatus: 503 }).message
position
Section titled “position”
readonlyposition:number=Schema.Int
Defined in: src/CommandApi.ts:377
The position the request asked for.
Inherited from
Section titled “Inherited from”Schema.TaggedError<NotCaughtUp>()("NotCaughtUp", { /** The position the request asked for. */ position: Schema.Int, message: Schema.String }, { httpApiStatus: 503 }).position
ReadAfter
Section titled “ReadAfter”Defined in: src/CommandApi.ts:398
Middleware for query endpoints that read view models. A request with a
Read-After: <position> header waits until every view model of this process has
handled that position, the one a command answered with, before the endpoint
runs. A request without the header runs at once. A header that isn’t a position
is answered with 400.
const Catalog = HttpApiGroup.make("catalog") .add(HttpApiEndpoint.get("available", "/books/available", { success: Books })) .middleware(CommandApi.ReadAfter)
const ReadAfterLive = CommandApi.layerReadAfter({ timeout: "2 seconds" })Implement it with layerReadAfter.
Extends
Section titled “Extends”Shape<"effect-cqrs/CommandApi/ReadAfter",HttpApiMiddleware<never, readonly [typeofNotCaughtUp, typeofBadRequest],never>,this> &object
Constructors
Section titled “Constructors”Constructor
Section titled “Constructor”new ReadAfter(
_):ReadAfter
Defined in: node_modules/.pnpm/effect@4.0.6/node_modules/effect/dist/http-api/HttpApiMiddleware.d.ts:265
Parameters
Section titled “Parameters”never
Returns
Section titled “Returns”Inherited from
Section titled “Inherited from”HttpApiMiddleware.Service<ReadAfter>()("effect-cqrs/CommandApi/ReadAfter", { error: [NotCaughtUp, HttpApiError.BadRequest] }).constructor
Interfaces
Section titled “Interfaces”LayerOptions
Section titled “LayerOptions”Defined in: src/CommandApi.ts:276
Properties
Section titled “Properties”historyLimit?
Section titled “historyLimit?”
readonlyoptionalhistoryLimit?:number
Defined in: src/CommandApi.ts:282
The most events one history response lists, so that a long stream can’t make
one response as large as the stream. A client reads further with
afterVersion. Defaults to 1,000.
Options
Section titled “Options”Defined in: src/CommandApi.ts:176
Type Parameters
Section titled “Type Parameters”Name extends string
State extends Schema.Top
Errors
Section titled “Errors”Errors extends ReadonlyArray<Schema.Top>
Properties
Section titled “Properties”errors?
Section titled “errors?”
readonlyoptionalerrors?:Errors
Defined in: src/CommandApi.ts:192
Errors of the command handlers to answer with as they are. Others become
CommandRejected. An error without an httpApiStatus annotation is
answered with 422.
readonlyoptionalname?:Name
Defined in: src/CommandApi.ts:182
The identifier of the group, the aggregate’s name by default.
prefix?
Section titled “prefix?”
readonlyoptionalprefix?:`/${string}`
Defined in: src/CommandApi.ts:184
Where the endpoints start, /<aggregate name> by default.
state?
Section titled “state?”
readonlyoptionalstate?:State
Defined in: src/CommandApi.ts:186
The schema of the state. Without it there is no state endpoint.
ReadAfterOptions
Section titled “ReadAfterOptions”Defined in: src/CommandApi.ts:402
Properties
Section titled “Properties”timeout?
Section titled “timeout?”
readonlyoptionaltimeout?:Input
Defined in: src/CommandApi.ts:404
How long a request waits before it is answered with NotCaughtUp. Defaults to 5 seconds.
Type Aliases
Section titled “Type Aliases”Endpoints
Section titled “Endpoints”Endpoints<
A,State,Errors> ={ readonly [K in CommandName<A>]: CommandEndpoint<A, K, Errors> }[CommandName<A>] |HistoryEndpoint<A> | [State] extends [never] ?never:StateEndpoint<State>
Defined in: src/CommandApi.ts:171
The endpoints of group.
Type Parameters
Section titled “Type Parameters”A extends Any
State extends Schema.Top
Errors
Section titled “Errors”Errors extends Schema.Top
Variables
Section titled “Variables”ConcurrencyConflictError
Section titled “ConcurrencyConflictError”
constConcurrencyConflictError:decodeTo<declareConstructor<ConcurrencyConflict, {aggregateId:string;aggregateName:string;expectedVersion:number; }, readonly [TaggedStruct<"ConcurrencyConflict", {aggregateId:String;aggregateName:String;expectedVersion:Int; }>], {aggregateId:string;aggregateName:string;expectedVersion:number; }>,TaggedStruct<"ConcurrencyConflict", {aggregateId:String;aggregateName:String;expectedVersion:Int; }>,never,never>
Defined in: src/CommandApi.ts:73
The stream moved on while the command was decided, and retries ran out. Answered with 409.
InvalidCommandError
Section titled “InvalidCommandError”
constInvalidCommandError:decodeTo<declareConstructor<InvalidCommand, {aggregateName:string;message:string;type:string; }, readonly [TaggedStruct<"InvalidCommand", {aggregateName:String;message:String;type:String; }>], {aggregateName:string;message:string;type:string; }>,TaggedStruct<"InvalidCommand", {aggregateName:String;message:String;type:String; }>,never,never>
Defined in: src/CommandApi.ts:70
A command whose payload doesn’t match its schema, or a body that isn’t JSON.
The same error as AggregateService.InvalidCommand, answered with 400.
WrongExpectedVersionError
Section titled “WrongExpectedVersionError”
constWrongExpectedVersionError:decodeTo<declareConstructor<WrongExpectedVersion, {actualVersion:number;aggregateId:string;aggregateName:string;expectedVersion:number; }, readonly [TaggedStruct<"WrongExpectedVersion", {actualVersion:Int;aggregateId:String;aggregateName:String;expectedVersion:Int; }>], {actualVersion:number;aggregateId:string;aggregateName:string;expectedVersion:number; }>,TaggedStruct<"WrongExpectedVersion", {actualVersion:Int;aggregateId:String;aggregateName:String;expectedVersion:Int; }>,never,never>
Defined in: src/CommandApi.ts:76
The stream is no longer at the version If-Match named. Answered with 409.
Functions
Section titled “Functions”commandResult()
Section titled “commandResult()”commandResult<
Events>(events):Struct<{aggregateId:String;aggregateName:String;correlationId:String;events:$Array<Events>;position:Int;version:Int; }>
Defined in: src/CommandApi.ts:91
The body of a successful command, CommandResult with the events in their JSON form.
Type Parameters
Section titled “Type Parameters”Events
Section titled “Events”Events extends EventSchema<any>
Parameters
Section titled “Parameters”events
Section titled “events”Events
Returns
Section titled “Returns”Struct<{ aggregateId: String; aggregateName: String; correlationId: String; events: $Array<Events>; position: Int; version: Int; }>
group()
Section titled “group()”group<
A,Name,State,Errors>(aggregate,options?):HttpApiGroup<Name,Endpoints<A,State,Errors[number]>>
Defined in: src/CommandApi.ts:205
Builds the endpoints of an aggregate. Add the group to an HttpApi and
implement it with layer.
Type Parameters
Section titled “Type Parameters”A extends Any
Name extends string = A["name"]
State extends Top = never
Errors
Section titled “Errors”Errors extends readonly Top[] = []
Parameters
Section titled “Parameters”aggregate
Section titled “aggregate”A
options?
Section titled “options?”Options<Name, State, Errors>
Returns
Section titled “Returns”HttpApiGroup<Name, Endpoints<A, State, Errors[number]>>
historyEntry()
Section titled “historyEntry()”historyEntry<
Events>(events):Struct<{causationId:NullOr<String>;correlationId:NullOr<String>;metadata:Codec<JsonObject,JsonObject,never,never>;payload:optionalKey<Events>;timestamp:DateTimeUtc;type:String;version:Int; }>
Defined in: src/CommandApi.ts:102
One entry of history. payload is there when the request asks for it.
Type Parameters
Section titled “Type Parameters”Events
Section titled “Events”Events extends EventSchema<any>
Parameters
Section titled “Parameters”events
Section titled “events”Events
Returns
Section titled “Returns”Struct<{ causationId: NullOr<String>; correlationId: NullOr<String>; metadata: Codec<JsonObject, JsonObject, never, never>; payload: optionalKey<Events>; timestamp: DateTimeUtc; type: String; version: Int; }>
layer()
Section titled “layer()”layer<
ApiId,Groups,Name,A,E,R>(api,name,service,options?):Layer<Service<ApiId,Name>,E,Exclude<R,Scope>>
Defined in: src/CommandApi.ts:292
Implements a group built by group with an aggregate service, or an effect that builds one when the layer starts.
Unexpected failures, such as a store that can’t be reached, are defects and
answered with 500.
Type Parameters
Section titled “Type Parameters”ApiId extends string
Groups
Section titled “Groups”Groups extends Constraint
Name extends string
A extends Any
E = never
R = never
Parameters
Section titled “Parameters”HttpApi<ApiId, Groups>
Name
service
Section titled “service”AggregateService<A> | Effect<AggregateService<A>, E, R>
options?
Section titled “options?”Returns
Section titled “Returns”Layer<Service<ApiId, Name>, E, Exclude<R, Scope>>
layerReadAfter()
Section titled “layerReadAfter()”layerReadAfter(
options?):Layer<ReadAfter,never,ViewModels>
Defined in: src/CommandApi.ts:415
Implements ReadAfter with the ViewModels of this process. View models
that another process holds are not waited for, as with ViewModels.caughtUp.
Parameters
Section titled “Parameters”options?
Section titled “options?”Returns
Section titled “Returns”Layer<ReadAfter, never, ViewModels>