Overview
@woltz/rich-domain-cli provides CLI tools for scaffolding DDD projects and generating domain entities from Prisma schemas.
npm install -D @woltz/rich-domain-cli
# Or run directly with npx
npx rich-domain <command>
Project Scaffolding
Initialize complete projects from templates
Prisma Introspection
Generate domain from existing schemas
Smart Classification
Auto-detects Aggregates vs Entities
Full Stack Generation
Schemas, entities, repositories, mappers
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.
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
# Interactive mode
npx rich-domain init my-app
# Specify template and package manager
npx rich-domain init my-app --template fullstack -p pnpm
# Initialize in current directory
npx rich-domain init . --template fullstack
# Skip all prompts
npx rich-domain init my-app -t fullstack -p npm -f
generate
Generate domain entities, repositories, and mappers from your Prisma schema.
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
# 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:
🔍 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 |
Repository and mapper files are only generated when @woltz/rich-domain-prisma is installed.
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)
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
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
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)
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
- Review classifications - Adjust Aggregate/Entity based on actual domain boundaries
- Add business logic - The generated code is a starting point
- Add validation rules - Customize schemas with business constraints
- 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
Use --dry-run first to preview changes before overwriting files.
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.
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
# 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
# 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:
- Validation Library: Checks
package.json for zod, valibot, or arktype
- Prisma Adapter: Detects
@woltz/rich-domain-prisma for repository/mapper generation
- Output Directory: Looks for existing
src/domain or src directories
If @woltz/rich-domain-prisma is not installed, generic implementations are generated that you’ll need to customize for your database.