Skip to main content

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:
CommandDescription
initInitialize a new project from a template
generateGenerate domain entities from Prisma schema
addManually 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

OptionAliasDefaultDescription
--template <n>-tPromptTemplate to use
--package-manager <pm>-pPromptnpm, pnpm, yarn, or bun
--force-ffalseSkip 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

OptionAliasDefaultDescription
--schema <path>-sAuto-detectPath to Prisma schema file
--output <path>-osrcOutput directory
--validation <type>-vAuto-detectzod, valibot, arktype, or none
--models <names>-mAll modelsComma-separated list of models
--dry-run-falsePreview without writing files
--force-ffalseSkip 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
PackageEffect
@woltz/rich-domain-prismaGenerates repositories and mappers
zodUses Zod for schema validation
valibotUses Valibot for schema validation
arktypeUses ArkType for schema validation
NoneGenerates 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

ConditionClassificationReason
Referenced by others via FKAggregateIt’s a parent/root
Has list relations (1:N)AggregateIt owns children
Has N:N relationsAggregateBoth sides are roots
Only has FKs, not referencedEntityIt’s a child/owned
No relationsAggregateStandalone 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

  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
Use --dry-run first to preview changes before overwriting files.

Manual Adjustments

Some scenarios require manual adjustment:
ScenarioAdjustment Needed
Lookup tables (Tag, Category)May want to be Value Objects
Self-referential relationsReview aggregate boundaries
Complex N:NDecide 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

OptionAliasDefaultDescription
--aggregate-atrueCreate an Aggregate (default)
--entity-efalseCreate an Entity
--value-object-vfalseCreate a Value Object
--with-repo-falseGenerate repository interface and implementation
--with-mapper-falseGenerate ToDomain and ToPersistence mappers
--with-all-falseGenerate repository and mappers
--output <path>-oAuto-detectOutput directory
--force-ffalseSkip 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:
SyntaxDescriptionExample
name:stringRequired stringemail:string
name:numberRequired numberage:number
name:booleanRequired booleanisActive:boolean
name:dateRequired datecreatedAt:date
name:type?Optional (nullable)bio:string?
name:type[]Arraytags:string[]
name:(A,B,C)Inline enumstatus:(ACTIVE,INACTIVE)
name:EntityRelation (PascalCase)author:User
name:Entity[]Array relationposts: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:
  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
If @woltz/rich-domain-prisma is not installed, generic implementations are generated that you’ll need to customize for your database.