Domain.Command reference
Command
Section titled “Command”Source:
packages/domain/src/Command.ts
A request to change one aggregate instance. It names the instance it targets, its input, the events it may record, the rejections it may return, the middleware that guards it, and the reply its caller receives.
Command: Declaring a command
Section titled “Command: Declaring a command”import * as Domain from "@alchemy.run/domain";import * as Schema from "effect/Schema";
export const AccountId = Schema.String.pipe(Schema.brand("AccountId"));
export class MoneyWithdrawn extends Domain.Event("MoneyWithdrawn", { amount: Schema.Int, balanceAfter: Schema.Int,}) {}
export class InsufficientFunds extends Domain.Rejection("InsufficientFunds", { balance: Schema.Int, requested: Schema.Int,}) {}
export class WithdrawMoney extends Domain.Command("WithdrawMoney", { target: AccountId, input: { amount: Schema.Int }, events: [MoneyWithdrawn], rejects: [InsufficientFunds], reply: { balance: Schema.Int },}) {}Command: Guarding it with middleware
Section titled “Command: Guarding it with middleware”middleware runs in order before the command reaches its aggregate. What
it provides, such as the current actor, is what decide may read.
import * as Domain from "@alchemy.run/domain";import * as Schema from "effect/Schema";import { AccountId, MoneyWithdrawn } from "./Account.ts";import { MfaChallenge } from "./MfaChallenge.ts";import { Session } from "./Session.ts";
export class WithdrawMoney extends Domain.Command("WithdrawMoney", { target: AccountId, middleware: [Session, MfaChallenge], input: { amount: Schema.Int }, events: [MoneyWithdrawn], reply: { balance: Schema.Int },}) {}Command: Sending it once
Section titled “Command: Sending it once”Pass a commandId, and a resend with the same id returns the first
receipt instead of applying the command again.
const receipt = yield* bank.WithdrawMoney({ target: accountId, amount: 2_000, commandId: requestId });