/ Docs

Code Generation

What is Code Generation?

Code generation in Bounda automatically creates type-safe interfaces from your domain and read model files. Rather than writing type definitions by hand, Bounda inspects your file structure and exports, then generates +types/ directories with fully typed interfaces for commands, events, policies, queries, projections, and process managers.

How It Works

When you run the code generator, Bounda scans your domain/ and read/ directories, analyzes the exported payload and apply functions, and produces typed interfaces in co-located +types/ directories:

domain/
  order/
    order-placed.ts
    +types/
      order-placed.ts       <- generated
    commands/
      place-order.ts
      +types/
        place-order.ts      <- generated
    policies/
      send-confirmation-on-order-placed.ts
      +types/
        send-confirmation-on-order-placed.ts  <- generated

These generated files provide the types you import in your domain code:

import type { Event } from "./+types/order-placed";
import type { Command } from "./+types/place-order";
import type { Policy } from "./+types/send-confirmation-on-order-placed";

Running the Generator

One-Time Generation

npx bounda generate

Scans the project and generates all +types/ files. Run this after adding new files or changing payload schemas.

Watch Mode

npx bounda generate --watch

Continuously watches for file changes and regenerates types automatically. Useful during active development.

Cleaning Generated Files

npx bounda clean

Removes all generated +types/ directories. Useful when switching branches or troubleshooting stale types.

Vite Plugin

For projects using Vite, Bounda provides a plugin that triggers code generation automatically during development:

import { bounda } from "@bounda-dev/codegen/vite";
import { defineConfig } from "vite";

export default defineConfig({
  plugins: [bounda()],
});

The plugin watches for file changes and regenerates types in the background, eliminating the need to run the CLI separately during development.

TypeScript Configuration

To make TypeScript recognize the generated +types/ files, add the following to your tsconfig.json:

{
  "include": [".bounda/**/*"],
  "compilerOptions": {
    "rootDirs": [".", "./.bounda"]
  }
}

This tells TypeScript to treat the .bounda directory as a virtual root alongside your project root, enabling the +types/ imports to resolve correctly.

What Gets Generated

The code generator produces typed interfaces for each domain concept:

ConceptGenerated Types
EventsEvent.PayloadFunction, Event.ApplierArgs
CommandsCommand.PayloadFunction, Command.HandlerArgs, Command.CollaboratorArgs
PoliciesPolicy.HandlerArgs
Process ManagersProcessManager.ConfigFunction, ProcessManager.HandlerArgs
ProjectionsProjection.HandlerArgs
QueriesQuery.PayloadFunction, Query.Repository, Query.HandlerArgs

These types encode the relationships between your domain files. For example, Command.HandlerArgs includes typed events builders based on the events defined in the same aggregate, and collaborator arguments based on the collaborator files in the command folder.

Guidelines

  • Run npx bounda generate after creating new domain or read model files before writing the implementation. The generated types guide your code with autocompletion and compile-time checks.
  • Never edit files inside +types/ directories. They are overwritten on every generation run.
  • Add +types/ directories to .gitignore if you prefer to generate them as a build step rather than checking them in.
  • If types seem stale or incorrect, run npx bounda clean followed by npx bounda generate to rebuild from scratch.
  • Aggregates — events and commands that code generation scans
  • Commands — generated Command.HandlerArgs types
  • Events — generated Event.PayloadFunction and Event.ApplierArgs types
  • Queries — generated Query.Repository and Query.HandlerArgs types