> ## Documentation Index
> Fetch the complete documentation index at: https://woltz.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# CLI

> Initialize projects and generate domain entities from Prisma schemas

## Overview

`@woltz/rich-domain-cli` provides CLI tools for scaffolding DDD projects and generating domain entities from Prisma schemas.

```bash theme={null}
npm install -D @woltz/rich-domain-cli

# Or run directly with npx
npx rich-domain <command>
```

<CardGroup cols={2}>
  <Card title="Project Scaffolding" icon="rocket">
    Initialize complete projects from templates
  </Card>

  <Card title="Prisma Introspection" icon="database">
    Generate domain from existing schemas
  </Card>

  <Card title="Smart Classification" icon="brain">
    Auto-detects Aggregates vs Entities
  </Card>

  <Card title="Full Stack Generation" icon="layer-group">
    Schemas, entities, repositories, mappers
  </Card>
</CardGroup>

***

## Requirements

* Node.js >= 20
* Prisma schema file (for `generate` command)
* `@woltz/rich-domain` (required)
* `@woltz/rich-domain-prisma` (optional, for repositories/mappers)
* Validation library (optional, for runtime validation)

***

## Commands

The CLI provides three main commands:

| Command    | Description                                        |
| ---------- | -------------------------------------------------- |
| `init`     | Initialize a new project from a template           |
| `generate` | Generate domain entities from Prisma schema        |
| `add`      | Manually create entity, aggregate, or value object |

***

## init

Initialize a new DDD project from a template with all infrastructure pre-configured.

```bash theme={null}
npx rich-domain init [directory] [options]
```

### Options

| Option                   | Alias | Default | Description                         |
| ------------------------ | ----- | ------- | ----------------------------------- |
| `--template <n>`         | `-t`  | Prompt  | Template to use                     |
| `--package-manager <pm>` | `-p`  | Prompt  | `npm`, `pnpm`, `yarn`, or `bun`     |
| `--force`                | `-f`  | `false` | Skip prompts and overwrite existing |

### Examples

```bash theme={null}
# Interactive mode
npx rich-domain init my-app

# Specify template and package manager
npx rich-domain init my-app --template fullstack-prisma -p pnpm

# Initialize in current directory
npx rich-domain init . --template fullstack-drizzle

# Skip all prompts
npx rich-domain init my-app -t fullstack-typeorm -p npm -f
```

***

## Templates

### Available Templates

| Template            | Stack                                | Description                            |
| ------------------- | ------------------------------------ | -------------------------------------- |
| `fullstack-prisma`  | Fastify + Prisma + BullMQ + Zod      | Prisma v7 with driver adapter (pg)     |
| `fullstack-drizzle` | Fastify + Drizzle ORM + BullMQ + Zod | Drizzle with node-postgres             |
| `fullstack-typeorm` | Fastify + TypeORM + BullMQ + Zod     | TypeORM with decorators and DataSource |

All templates share the same DDD architecture and generate the same project structure. They differ only in the ORM layer.

### Generated Project Structure

```
my-app/
├── prisma.config.ts              # ORM config (Prisma) / drizzle.config.ts (Drizzle)
├── docker-compose.yml            # PostgreSQL + Redis
├── .env.example
├── tsconfig.json
└── src/
    ├── env.ts                    # Zod-validated environment variables
    ├── server.ts                 # Fastify app entry point
    ├── constants.ts              # Queue name constants
    ├── domain/
    │   ├── entities/
    │   │   └── user.aggregate.ts
    │   ├── repositories/
    │   │   └── user.repository.ts
    │   ├── events/
    │   │   └── user-created.event.ts
    │   └── value-objects/
    │       └── email.ts
    ├── application/
    │   ├── service/
    │   │   └── user.service.ts
    │   └── processor/
    │       ├── events.processor.ts   # Observe-only handlers (logging, emails)
    │       └── action.processor.ts   # Mutation handlers
    ├── infra/
    │   ├── database/
    │   │   ├── <orm>/              # Schema/entity files
    │   │   ├── mappers/            # Domain ↔ persistence mappers
    │   │   ├── repositories/       # Concrete repository implementations
    │   │   ├── schemas/            # Persistence type definitions
    │   │   └── seed/
    │   ├── queue/
    │   │   ├── connection.ts       # IORedis connection
    │   │   ├── event-bus.ts        # BullMQ IDomainEventBus implementation
    │   │   ├── event-worker.ts     # BullMQ domain event worker
    │   │   └── queue-publisher.ts
    │   └── di/
    │       ├── container.ts        # DI container
    │       └── fastify-plugin.ts   # Fastify DI decorator
    └── presentation/
        ├── controllers/
        │   └── user.controller.ts
        └── dto/
            └── user/
                └── user.dto.ts
```

### Scripts

All templates include the same base scripts:

| Script        | Description                     |
| ------------- | ------------------------------- |
| `dev`         | Start dev server with tsx watch |
| `build`       | Compile TypeScript              |
| `start`       | Start production server         |
| `lint`        | Type-check without emitting     |
| `db:generate` | Generate ORM client/migrations  |
| `db:migrate`  | Run migrations                  |
| `db:push`     | Push schema to database         |
| `db:studio`   | Open ORM studio UI              |
| `db:seed`     | Run seed script                 |
| `docker:up`   | Start PostgreSQL + Redis        |
| `docker:down` | Stop Docker services            |

<Note>
  TypeORM does not include `db:generate`, `db:migrate`, `db:push`, or `db:studio` — schema synchronization is handled by `synchronize: true` in development mode.
</Note>

### fullstack-prisma

Uses **Prisma v7** with the `@prisma/adapter-pg` driver adapter (required in v7) and `prisma.config.ts` for schema configuration.

**Key dependencies:** `@prisma/client`, `@prisma/adapter-pg`, `pg`, `@woltz/rich-domain-prisma`

```typescript theme={null}
// src/infra/database/prisma.ts
import { PrismaClient } from "@prisma/client";
import { PrismaPg } from "@prisma/adapter-pg";

const adapter = new PrismaPg({ connectionString: env.DATABASE_URL });
export const prisma = new PrismaClient({ adapter });
```

```typescript theme={null}
// prisma.config.ts
import { defineConfig } from "prisma/config";

export default defineConfig({
  schema: path.join("src", "infra", "database", "prisma", "schema.prisma"),
  datasource: {
    url: env.DATABASE_URL,
  },
  migrations: {
    path: path.join("src", "infra", "database", "prisma", "migrations"),
    seed: path.join("src", "infra", "database", "seed", "seed.ts"),
  },
});
```

### fullstack-drizzle

Uses **Drizzle ORM** with `drizzle-orm/node-postgres` and a lazy-initialized connection pool.

**Key dependencies:** `drizzle-orm`, `pg`, `@woltz/rich-domain-drizzle`

```typescript theme={null}
// src/infra/database/db.ts
export async function initializeDatabase() {
  pool = new Pool({ connectionString: env.DATABASE_URL });
  db = drizzle(pool, { schema });
}
```

```typescript theme={null}
// drizzle.config.ts
export default defineConfig({
  schema: "./src/infra/database/drizzle/schema.ts",
  out: "./src/infra/database/drizzle/migrations",
  dialect: "postgresql",
});
```

### fullstack-typeorm

Uses **TypeORM** with `DataSource`, decorator-based entities, and `synchronize: true` in development.

**Key dependencies:** `typeorm`, `pg`, `reflect-metadata`, `@woltz/rich-domain-typeorm`

```typescript theme={null}
// src/infra/database/db.ts
export const AppDataSource = new DataSource({
  type: "postgres",
  url: env.DATABASE_URL,
  synchronize: env.NODE_ENV === "development",
  entities: [UserEntity],
});
```

<Warning>
  The TypeORM template enables `synchronize: true` in development mode. Disable this and use migrations in production.
</Warning>

### Getting Started

After running `init`:

```bash theme={null}
cd my-app
pnpm install
cp .env.example .env
pnpm docker:up
pnpm db:push       # or db:migrate for Prisma/Drizzle
pnpm dev
```

```
API:     http://localhost:3000
Swagger: http://localhost:3000/doc
```

***

## generate

Generate domain entities, repositories, and mappers from your Prisma schema.

```bash theme={null}
npx rich-domain generate [options]
```

### Options

| Option                | Alias | Default     | Description                            |
| --------------------- | ----- | ----------- | -------------------------------------- |
| `--schema <path>`     | `-s`  | Auto-detect | Path to Prisma schema file             |
| `--output <path>`     | `-o`  | `src`       | Output directory                       |
| `--validation <type>` | `-v`  | Auto-detect | `zod`, `valibot`, `arktype`, or `none` |
| `--models <names>`    | `-m`  | All models  | Comma-separated list of models         |
| `--dry-run`           | -     | `false`     | Preview without writing files          |
| `--force`             | `-f`  | `false`     | Skip confirmation prompts              |

### Examples

```bash theme={null}
# Basic usage (auto-detect schema and validation)
npx rich-domain generate

# Specify schema path
npx rich-domain generate --schema ./prisma/schema.prisma

# Generate to custom directory with Zod
npx rich-domain generate --output ./src/domain --validation zod

# Generate only specific models
npx rich-domain generate --models User,Post,Comment

# Preview without writing files
npx rich-domain generate --dry-run
```

### Package Detection

The CLI automatically detects installed packages and adjusts generation accordingly:

```bash theme={null}
🔍 Rich Domain Generator

Reading schema from prisma/schema.prisma

Detected packages:
  • @woltz/rich-domain-prisma: ✓ installed
  • Validation library: zod
```

| Package                     | Effect                               |
| --------------------------- | ------------------------------------ |
| `@woltz/rich-domain-prisma` | Generates repositories and mappers   |
| `zod`                       | Uses Zod for schema validation       |
| `valibot`                   | Uses Valibot for schema validation   |
| `arktype`                   | Uses ArkType for schema validation   |
| None                        | Generates TypeScript interfaces only |

<Warning>
  Repository and mapper files are only generated when `@woltz/rich-domain-prisma` is installed.
</Warning>

### Generated Structure

For a Prisma schema with `User`, `Post`, and `Comment` models:

```
src/
├── shared/
│   └── enums.ts                        # All Prisma enums
├── user/
│   ├── index.ts                        # Barrel export
│   ├── user.schema.ts                  # Zod schema
│   ├── user.aggregate.ts               # Aggregate class
│   ├── user.repository.ts              # Repository*
│   ├── user-to-domain.mapper.ts        # Domain mapper*
│   └── user-to-persistence.mapper.ts   # Persistence mapper*
├── post/
│   ├── index.ts
│   ├── post.schema.ts
│   ├── post.aggregate.ts               # Aggregate (has children)
│   └── ...
└── comment/
    ├── index.ts
    ├── comment.schema.ts
    └── comment.entity.ts               # Entity (owned by Post)

* Only generated when @woltz/rich-domain-prisma is installed
```

***

## Classification Logic

The CLI classifies models as **Aggregates** or **Entities** based on their relationships.

### Classification Rules

| Condition                    | Classification | Reason               |
| ---------------------------- | -------------- | -------------------- |
| Referenced by others via FK  | **Aggregate**  | It's a parent/root   |
| Has list relations (1:N)     | **Aggregate**  | It owns children     |
| Has N:N relations            | **Aggregate**  | Both sides are roots |
| Only has FKs, not referenced | **Entity**     | It's a child/owned   |
| No relations                 | **Aggregate**  | Standalone root      |

***

## Validation Libraries

### Zod (Default)

```typescript theme={null}
import { z } from "zod";

export const userSchema = z.object({
  id: z.custom<Id>((v) => v instanceof Id),
  email: z.string().email(),
  name: z.string(),
  age: z.number().int().min(0),
  isActive: z.boolean(),
  createdAt: z.date(),
});
```

### Valibot

```typescript theme={null}
import * as v from "valibot";

export const userSchema = v.object({
  id: v.custom<Id>((v) => v instanceof Id),
  email: v.pipe(v.string(), v.email()),
  name: v.string(),
  age: v.pipe(v.number(), v.integer(), v.minValue(0)),
  isActive: v.boolean(),
  createdAt: v.date(),
});
```

### ArkType

```typescript theme={null}
import { type } from "arktype";

export const userSchema = type({
  id: "instanceof Id",
  email: "string.email",
  name: "string",
  age: "integer >= 0",
  isActive: "boolean",
  createdAt: "Date",
});
```

### None (Interfaces Only)

```typescript theme={null}
import { Id } from "@woltz/rich-domain";

export interface UserProps {
  id: Id;
  email: string;
  name: string;
  age: number;
  isActive: boolean;
  createdAt: Date;
}
```

***

## Best Practices

### After Generation

1. **Review classifications** - Adjust Aggregate/Entity based on actual domain boundaries
2. **Add business logic** - The generated code is a starting point
3. **Add validation rules** - Customize schemas with business constraints
4. **Configure hooks** - Add lifecycle hooks as needed

### When to Re-generate

* After changing Prisma schema structure
* After adding new models
* Use `--models` flag to regenerate specific models only

<Tip>
  Use `--dry-run` first to preview changes before overwriting files.
</Tip>

### Manual Adjustments

Some scenarios require manual adjustment:

| Scenario                      | Adjustment Needed                   |
| ----------------------------- | ----------------------------------- |
| Lookup tables (Tag, Category) | May want to be Value Objects        |
| Self-referential relations    | Review aggregate boundaries         |
| Complex N:N                   | Decide which side owns the relation |

***

## add

Manually create an entity, aggregate, or value object without requiring a Prisma schema.

```bash theme={null}
npx rich-domain add <name> [...props] [options]
```

### Options

| Option            | Alias | Default     | Description                                      |
| ----------------- | ----- | ----------- | ------------------------------------------------ |
| `--aggregate`     | `-a`  | `true`      | Create an Aggregate (default)                    |
| `--entity`        | `-e`  | `false`     | Create an Entity                                 |
| `--value-object`  | `-v`  | `false`     | Create a Value Object                            |
| `--with-repo`     | -     | `false`     | Generate repository interface and implementation |
| `--with-mapper`   | -     | `false`     | Generate ToDomain and ToPersistence mappers      |
| `--with-all`      | -     | `false`     | Generate repository and mappers                  |
| `--output <path>` | `-o`  | Auto-detect | Output directory                                 |
| `--force`         | `-f`  | `false`     | Skip prompts and overwrite                       |

### Examples

```bash theme={null}
# Create a simple aggregate
npx rich-domain add User

# Create with properties
npx rich-domain add User name:string email:string

# Create with optional and enum properties
npx rich-domain add User name:string role:(USER,ADMIN) age:number?

# Create a Value Object (single primitive property)
npx rich-domain add Email -v email:string

# Create an Entity
npx rich-domain add OrderItem -e quantity:number price:number

# Create with relations
npx rich-domain add Product name:string author:User tags:Tag[]

# Create with repository and mappers
npx rich-domain add Order --with-all
```

### Props Syntax

The props follow a `name:type` format with support for various modifiers:

| Syntax          | Description           | Example                    |
| --------------- | --------------------- | -------------------------- |
| `name:string`   | Required string       | `email:string`             |
| `name:number`   | Required number       | `age:number`               |
| `name:boolean`  | Required boolean      | `isActive:boolean`         |
| `name:date`     | Required date         | `createdAt:date`           |
| `name:type?`    | Optional (nullable)   | `bio:string?`              |
| `name:type[]`   | Array                 | `tags:string[]`            |
| `name:(A,B,C)`  | Inline enum           | `status:(ACTIVE,INACTIVE)` |
| `name:Entity`   | Relation (PascalCase) | `author:User`              |
| `name:Entity[]` | Array relation        | `posts:Post[]`             |

### Props Examples

```bash theme={null}
# Basic types
npx rich-domain add User \
  name:string \
  email:string \
  age:number \
  isAdmin:boolean \
  createdAt:date

# Optional fields
npx rich-domain add Profile \
  bio:string? \
  website:string? \
  avatar:string?

# Arrays
npx rich-domain add Article \
  title:string \
  tags:string[] \
  categories:string[]

# Enums
npx rich-domain add Order \
  status:(PENDING,PROCESSING,SHIPPED,DELIVERED) \
  priority:(LOW,MEDIUM,HIGH)

# Relations
npx rich-domain add Post \
  title:string \
  content:string \
  author:User \
  comments:Comment[]

# Combined
npx rich-domain add Product \
  name:string \
  price:number \
  description:string? \
  status:(DRAFT,PUBLISHED,ARCHIVED) \
  tags:string[] \
  category:Category \
  reviews:Review[]
```

### Auto-Detection

The `add` command automatically detects:

1. **Validation Library**: Checks `package.json` for `zod`, `valibot`, or `arktype`
2. **Prisma Adapter**: Detects `@woltz/rich-domain-prisma` for repository/mapper generation
3. **Output Directory**: Looks for existing `src/domain` or `src` directories

<Note>
  If `@woltz/rich-domain-prisma` is not installed, generic implementations are generated that you'll need to customize for your database.
</Note>
