# CLI Generation
URL: /docs/cli
LLM index: /llms.txt
Description: How the CLI loads schemas and writes Prisma, Drizzle, and SQL output.

# CLI Generation

`@farming-labs/orm-cli` reads schema objects exported by `@farming-labs/orm`.
It does not invent a second schema language.

## Config shape

```ts
import { defineConfig } from "@farming-labs/orm-cli";
import { authSchema } from "./src/auth-schema";
import { billingSchema } from "./src/billing-schema";

export default defineConfig({
  schemas: [authSchema, billingSchema],
  targets: {
    prisma: {
      out: "./generated/prisma/schema.prisma",
      provider: "postgresql",
      datasourceName: "db",
      generatorName: "client",
      mode: "replace",
    },
    drizzle: {
      out: "./generated/drizzle/schema.ts",
      dialect: "pg",
    },
    sql: {
      out: "./generated/sql/0001_init.sql",
      dialect: "postgres",
    },
  },
});
```

## How schema merging works

The CLI merges all schemas from `config.schemas` into one combined schema before
rendering targets.

Important rule:

- duplicate model names are rejected

That keeps package composition explicit and prevents silent overwrites.

## Core commands

```bash title="terminal"
farm-orm generate prisma
farm-orm generate drizzle
farm-orm generate sql
farm-orm check prisma
farm-orm check drizzle
farm-orm check sql
```

## `generate`

`generate` renders output to disk.

### Prisma

```bash title="terminal"
farm-orm generate prisma
```

Supported options:

- `provider`: `"postgresql" | "mysql" | "sqlite"`
- `datasourceName`
- `generatorName`
- `out`
- `mode`: `"block" | "replace"`

### Drizzle

```bash title="terminal"
farm-orm generate drizzle
```

Supported options:

- `dialect`: `"pg" | "mysql" | "sqlite"`
- `out`

### SQL

```bash title="terminal"
farm-orm generate sql
```

Supported options:

- `dialect`: `"postgres" | "mysql" | "sqlite"`
- `out`

## `check`

`check` renders the same target in memory and compares it to the file already on disk.

That makes it useful for:

- CI validation
- generator drift checks
- confirming committed artifacts are still current

## Render as a string

If you want the generated output in memory instead of writing it to disk, use
the render helpers from `@farming-labs/orm` directly:

```ts
import { renderDrizzleSchema, renderPrismaSchema, renderSafeSql } from "@farming-labs/orm";

const prismaSchema = renderPrismaSchema(authSchema, {
  provider: "postgresql",
});

const drizzleSchema = renderDrizzleSchema(authSchema, {
  dialect: "pg",
});

const sqlSchema = renderSafeSql(authSchema, {
  dialect: "postgres",
});
```

Those helpers return strings:

- `renderPrismaSchema(...)` -> `schema.prisma` contents
- `renderDrizzleSchema(...)` -> generated Drizzle TypeScript source
- `renderSafeSql(...)` -> generated SQL DDL

This is useful when you want to:

- inspect generated output in tests
- embed generated schema text in another tool
- preview generated content without writing a file

If you are using multiple schemas through the CLI config, the CLI merges them
before writing files. The public string helpers work directly on a schema
object, so multi-schema rendering still needs a merged schema first.

## Prisma block mode vs replace mode

### `mode: "replace"`

Writes the generated Prisma file as the whole file contents.

### `mode: "block"`

If the file already exists, the CLI inserts or updates a generated block:

```prisma
// @farming-labs/orm:start:prisma
generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}
// ...
// @farming-labs/orm:end:prisma
```

That is useful when the application wants to keep non-generated Prisma content
around the generated schema region.

## What generators actually read

The generators consume normalized manifest data from the schema:

- table names
- field names
- mapped columns
- scalar kinds
- nullability
- uniqueness
- default/generated values
- foreign-key references

They also consume direct relation metadata for:

- `belongsTo(...)`
- `hasOne(...)`
- `hasMany(...)`

Explicit join-table `manyToMany(...)` stays explicit in generated Prisma and
Drizzle output through the join model instead of becoming an implicit shortcut.

## Target examples

### Prisma output

From:

```ts
email: string().unique().map("email_address");
```

the Prisma generator will emit:

```prisma
email String @unique @map("email_address")
```

### Drizzle output

For PostgreSQL, a simple user model becomes output shaped like:

```ts
export const user = pgTable("users", {
  id: text("id").primaryKey(),
  email: text("email_address").notNull().unique(),
});
```

### Safe SQL output

The SQL generator writes forward-safe DDL like:

```sql
create table if not exists "users" (
  "id" text primary key not null,
  "email_address" text not null unique
);
```

## What the CLI intentionally does not do

- It does not maintain its own schema DSL
- It does not silently merge duplicate model names
- It does not execute generated Prisma or Drizzle code for you
- It does not replace a full migration framework by itself beyond the safe SQL generation path

## Release and publish flow

The repo’s package release flow is `bumpp`-driven through a checked-in
`bump.config.ts`:

```bash title="terminal"
pnpm release:latest
```

For prereleases:

```bash title="terminal"
pnpm release:beta
```

Useful safety commands:

```bash title="terminal"
pnpm publish:latest:dry-run
pnpm publish:beta:dry-run
```

The `bump.config.ts` file is the source of truth for the release files, commit
message, and git tag shape. `release:latest` runs that bump flow and then
publishes the new version to npm. `publish:*` is still useful when you need to
retry a publish without bumping again.

## Where each target fits

- [Prisma integration](/docs/integrations/prisma)
- [Drizzle integration](/docs/integrations/drizzle)
- [SQL databases](/docs/integrations/sql-databases)

## Design constraint

The CLI depends on `@farming-labs/orm` directly, so schema semantics only exist
in one place. That is one of the most important architectural rules in the repo.