Building Business Logic

This section covers everything you need to implement business capabilities in PURISTA: services, commands, subscriptions, streams, queues, schemas, error handling, and more.

The builder pattern

PURISTA uses a fluent builder API for every artifact. Each builder collects metadata, schemas, and functions, then produces a typed definition.

flowchart LR
    SB["ServiceBuilder"] -->|getCommandBuilder| CB["CommandBuilder"]
    SB -->|getSubscriptionBuilder| SUB["SubscriptionBuilder"]
    SB -->|getStreamBuilder| ST["StreamBuilder"]
    SB -->|getQueueBuilder| QB["QueueBuilder"]
    CB -->|getDefinition| CD["CommandDefinition"]
    SUB -->|getDefinition| SD["SubscriptionDefinition"]
    ST -->|getDefinition| STD["StreamDefinition"]
    QB -->|getDefinition| QD["QueueDefinition"]
    CD -->|add to| S["Service"]
    SD -->|add to| S
    STD -->|add to| S
    QD -->|add to| S

Core concepts

Concept Purpose Pattern
Service Business boundary with metadata, config, and resources Domain-driven grouping
Command Typed request/response operation Active, synchronous
Subscription Reaction to events matching filters Passive, asynchronous
Stream Multi-frame response for live updates Push, real-time
Queue Pull-based async work with workers Durable, background
Schema Zod-based validation and TypeScript types Boundary enforcement
Store Config, secret, and state persistence Externalized state

Suggested reading order

Follow this path to build a complete mental model:

  1. Builders — understand the builder pattern and shared configuration
  2. Schemas & Validation — define Zod schemas for inputs, outputs, and events
  3. Service — create a service with metadata, config, and resources
  4. Command — add request/response operations with guards and transforms
  5. Stream — implement live, incremental responses
  6. Subscription — react to events from other services
  7. Queue — handle durable background work
  8. AI Agents — add LLM-powered workflows (optional)
  9. Custom Events — emit and handle domain events
  10. Error Handling — structured errors and recovery
  11. Logging — structured logging with context
  12. Stores — config, secret, and state management
  13. Exposing Commands — REST, SSE, and GraphQL
  14. HTTP Client — call external APIs with typed clients
  15. Connect to PURISTA — build clients for your services
  16. Advanced — message structure, delivery semantics, protocol internals

How the pieces fit together

flowchart TB
    subgraph Client["External Client"]
        REST["REST / SSE"]
        GQL["GraphQL"]
    end
    subgraph PURISTA["PURISTA Application"]
        direction TB
        EB["Event Bridge"]
        S1["User Service"]
        S2["Order Service"]
        S3["Email Service"]
        Q["Queue + Worker"]
    end
    subgraph Infra["Infrastructure"]
        Broker["Message Broker"]
        DB["Database"]
        Cache["Cache"]
    end
    REST -->|HTTP| EB
    GQL -->|HTTP| EB
    EB -->|commands| S1
    EB -->|commands| S2
    EB -->|events| S3
    S1 -->|enqueue| Q
    Q -->|worker| S1
    S1 <-->|resources| DB
    S2 <-->|resources| Cache
    EB <-->|transport| Broker

Key design guidelines

  • One service per business capability — not per technical layer
  • Commands are named operationsuserSignUp, not POST /users
  • Subscriptions are decoupled — the producer does not know the consumer exists
  • Schemas at every boundary — no untyped data enters or leaves a service
  • State externalized — use stores, not in-memory state
  • Errors are typed — return UnhandledError or custom error schemas

Next: start with Builders to understand the foundation of every PURISTA artifact.