CLI Generation
@farming-labs/orm-cli reads schema objects exported by @farming-labs/orm.
It does not invent a second schema language.
Config shape
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
farm-orm generate prisma
farm-orm generate drizzle
farm-orm generate sql
farm-orm check prisma
farm-orm check drizzle
farm-orm check sqlgenerate
generate renders output to disk.
Prisma
farm-orm generate prismaSupported options:
provider:"postgresql" | "mysql" | "sqlite"datasourceNamegeneratorNameoutmode:"block" | "replace"
Drizzle
farm-orm generate drizzleSupported options:
dialect:"pg" | "mysql" | "sqlite"out
SQL
farm-orm generate sqlSupported 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:
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.prismacontentsrenderDrizzleSchema(...)-> generated Drizzle TypeScript sourcerenderSafeSql(...)-> 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:
// @farming-labs/orm:start:prisma
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
// ...
// @farming-labs/orm:end:prismaThat 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:
email: string().unique().map("email_address");the Prisma generator will emit:
email String @unique @map("email_address")Drizzle output
For PostgreSQL, a simple user model becomes output shaped like:
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:
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:
pnpm release:latestFor prereleases:
pnpm release:betaUseful safety commands:
pnpm publish:latest:dry-run
pnpm publish:beta:dry-runThe 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
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.
How is this guide?