Commands
Commands represent actions you want to perform against the system. Arc generates their HTTP surface from model-bound commands, and in C# also from discovered controller actions. Either style can use validation and authorization; neither requires Chronicle or event sourcing.
Overview
Section titled “Overview”Commands provide a structured way to:
- Encapsulate business operations and state changes
- Validate input before execution
- Track changes from original values
- Integrate with React’s rendering pipeline
- Handle authorization and error scenarios
Quick Start
Section titled “Quick Start”Backend fragment: these are the declarations the proxy below is generated from.
public record OpenDebitAccount(AccountId AccountId, AccountName Name, CustomerId Owner);@Commandpublic record OpenDebitAccount(AccountId accountId, AccountName name, CustomerId owner) { public void handle(@FromServices AccountService accounts) { accounts.open(accountId, name, owner); }}@Commanddata class OpenDebitAccount(val accountId: AccountId, val name: AccountName, val owner: CustomerId) { suspend fun handle(@FromServices accounts: AccountService) { accounts.open(accountId, name, owner) }}import { field } from '@cratis/fundamentals';import { command, inject } from '@cratis/arc.core';
@command()export class OpenDebitAccount { @field(AccountId) accountId!: AccountId; @field(AccountName) name!: AccountName; @field(CustomerId) owner!: CustomerId;
@inject(AccountService) handle(accounts: AccountService): Promise<void> { return accounts.open(this.accountId, this.name, this.owner); }}The backend tabs reach the shared generated-command runtime from different starting points. The C# record is a payload DTO: it requires an already-defined controller endpoint accepting it, because a record alone is not enough for proxy discovery. The JVM has no controller-based discovery, so the model-bound @Command is the endpoint. TypeScript’s source preview generates from decorated @command() classes with a handle() method; see its generator setup. For a complete model-bound C# example, follow getting started.
Consumer fragment: call this hook inside a component, and execute from its event handler. This example assumes string-backed AccountId and CustomerId; use Fundamentals Guid values instead if the generated model maps Guid-backed concepts.
import { OpenDebitAccount } from './generated/commands';
export function OpenAccount() { const [command] = OpenDebitAccount.use({ accountId: 'a23edccc-6cb5-44fd-a7a7-7563716fb080', name: 'My Account', owner: '84cda809-9201-4d8c-8589-0be37c6e3f18' }); async function open() { const result = await command.execute(); console.log(result.isSuccess ? 'Opened.' : 'Could not open account.'); } return <button onClick={() => void open()}>Open account</button>;}HTTP Headers
Section titled “HTTP Headers”Command fetches include httpHeadersCallback headers configured in Arc. Supply Authorization or application headers there; cookies are browser-managed, not configurable Cookie request headers.
Proxy Generation
Section titled “Proxy Generation”Commands are automatically generated from your backend using the proxy generator. The generator scans HTTP Post actions during compile time and creates TypeScript classes that:
- Match your backend command structure
- Provide type-safe properties
- Include validation support
- Offer a
.use()method for React integration - Track changes automatically
See Proxy Generation for setup details.
Command Result
Section titled “Command Result”When executed, commands return a CommandResult with detailed information about the outcome:
const result = await command.execute();
if (result.isSuccess) { console.log('Success!', result.response);} else { if (!result.isAuthorized) { // Handle authorization failure } if (!result.isValid) { // Handle validation errors }}For comprehensive details, see Command Result documentation.
Topics
Section titled “Topics”| Topic | Description |
|---|---|
| React Usage | Using the .use() hook in React components (recommended). |
| Data Binding | Binding to command properties and managing initial values for change tracking. |
| Validation | Pre-flight validation, progressive validation, and error handling. |
| Command Scope | Tracking changes across multiple commands in composite UIs. |
| Imperative Usage | Advanced direct instantiation for non-React scenarios. |
Related Documentation
Section titled “Related Documentation”- CommandForm - Declarative form component for commands
- Queries - Data retrieval operations
- Core Commands - Lower-level command concepts
- Proxy Generation - Setting up command generation