Domain.View reference
Source:
packages/domain/src/View.ts
A read model: events folded into state per key, kept up to date as new events arrive. A view can emit events of its own, route one event to several keys, and decide who may read it.
View: Folding events into state
Section titled “View: Folding events into state”import * as Domain from "@alchemy.run/domain";import * as Schema from "effect/Schema";import { Account } from "./Account.ts";
export class AccountSummary extends Domain.View("AccountSummary", { from: [Account], key: Account, state: Schema.Struct({ balance: Schema.Int }), initial: { balance: 0 }, evolve: { MoneyDeposited: (v, e) => ({ ...v, balance: e.balanceAfter }), MoneyWithdrawn: (v, e) => ({ ...v, balance: e.balanceAfter }), },}) {}View: Emitting events
Section titled “View: Emitting events”import * as Domain from "@alchemy.run/domain";import * as Schema from "effect/Schema";import { Account } from "./Account.ts";
export class StatementLine extends Domain.Event("StatementLine", { kind: Schema.Literals(["deposit", "withdrawal"]), amount: Schema.Int,}) {}
export class Statement extends Domain.View("Statement", { from: [Account], key: Account, events: [StatementLine], emit: { MoneyDeposited: (e) => new StatementLine({ kind: "deposit", amount: e.amount }), MoneyWithdrawn: (e) => new StatementLine({ kind: "withdrawal", amount: e.amount }), },}) {}View: Routing one event to several keys
Section titled “View: Routing one event to several keys”keyOf: { TransferRequested: { out: ({ event }) => Account.ref(event.from), in: ({ event }) => Account.ref(event.to), },},View: Validating reads
Section titled “View: Validating reads”middleware: [Session],rejects: [NotOwner],validate: Effect.fn(function* (_request, summary) { const actor = yield* CurrentActor; if (summary?.owner && summary.owner !== actor.customerId) return yield* new NotOwner();}),