Getting Started
The shortest path is:
- Define a schema in
@farming-labs/orm - Add
farm-orm.config.ts - Generate target output
- Pick a runtime driver
1. Define a schema
import {
belongsTo,
boolean,
datetime,
defineSchema,
hasMany,
hasOne,
id,
model,
string,
} from "@farming-labs/orm";
export const authSchema = defineSchema({
user: model({
table: "users",
fields: {
id: id(),
name: string(),
email: string().unique().map("email_address"),
emailVerified: boolean().default(false),
createdAt: datetime().defaultNow(),
updatedAt: datetime().defaultNow(),
},
relations: {
profile: hasOne("profile", { foreignKey: "userId" }),
accounts: hasMany("account", { foreignKey: "userId" }),
sessions: hasMany("session", { foreignKey: "userId" }),
},
}),
profile: model({
table: "profiles",
fields: {
id: id(),
userId: string().unique().references("user.id"),
bio: string().nullable(),
},
relations: {
user: belongsTo("user", { foreignKey: "userId" }),
},
}),
session: model({
table: "sessions",
fields: {
id: id(),
userId: string().references("user.id"),
token: string().unique(),
expiresAt: datetime(),
},
relations: {
user: belongsTo("user", { foreignKey: "userId" }),
},
}),
account: model({
table: "accounts",
fields: {
id: id(),
userId: string().references("user.id"),
provider: string(),
accountId: string(),
},
constraints: {
unique: [["provider", "accountId"]],
indexes: [["userId", "provider"]],
},
relations: {
user: belongsTo("user", { foreignKey: "userId" }),
},
}),
});2. Add farm-orm.config.ts
import { defineConfig } from "@farming-labs/orm-cli";
import { authSchema } from "./src/schema";
export default defineConfig({
schemas: [authSchema],
targets: {
prisma: {
out: "./generated/prisma/schema.prisma",
provider: "postgresql",
},
drizzle: {
out: "./generated/drizzle/schema.ts",
dialect: "pg",
},
sql: {
out: "./generated/sql/0001_init.sql",
dialect: "postgres",
},
},
});3. Generate artifacts
farm-orm generate prisma
farm-orm generate drizzle
farm-orm generate sql
farm-orm check prismaGenerated Prisma and Drizzle output already includes direct relation metadata for:
belongsTohasOnehasMany
Join-table manyToMany stays explicit through the join model.
The same schema can also declare compound uniques and indexes. In the example
above, account(provider, accountId) becomes:
- a generated unique constraint in Prisma / Drizzle / SQL
- a runtime-safe
findUnique(...)andupsert(...)key across supported drivers
4. Pick a runtime
Memory
import { createMemoryDriver, createOrm } from "@farming-labs/orm";
const orm = createOrm({
schema: authSchema,
driver: createMemoryDriver(),
});Prisma
import { createOrm } from "@farming-labs/orm";
import { createPrismaDriver } from "@farming-labs/orm-prisma";
import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient();
const orm = createOrm({
schema: authSchema,
driver: createPrismaDriver({ client: prisma }),
});Drizzle
import { createOrm } from "@farming-labs/orm";
import { createDrizzleDriver } from "@farming-labs/orm-drizzle";
import { drizzle } from "drizzle-orm/node-postgres";
import { Pool } from "pg";
const db = drizzle(
new Pool({
connectionString: process.env.DATABASE_URL,
}),
);
const orm = createOrm({
schema: authSchema,
driver: createDrizzleDriver({
db,
dialect: "postgres",
}),
});Direct SQL
import { createOrm } from "@farming-labs/orm";
import { createPgPoolDriver } from "@farming-labs/orm-sql";
import { Pool } from "pg";
const orm = createOrm({
schema: authSchema,
driver: createPgPoolDriver(
new Pool({
connectionString: process.env.DATABASE_URL,
}),
),
});EdgeDB / Gel
import { createOrm } from "@farming-labs/orm";
import { createEdgeDbDriver } from "@farming-labs/orm-edgedb";
import { createClient } from "gel";
const orm = createOrm({
schema: authSchema,
driver: createEdgeDbDriver({
client: createClient(),
}),
});Cloudflare D1
import { createOrm } from "@farming-labs/orm";
import { createD1Driver } from "@farming-labs/orm-d1";
export type Env = {
DB: D1Database;
};
export default {
async fetch(_request: Request, env: Env) {
const orm = createOrm({
schema: authSchema,
driver: createD1Driver({
client: env.DB,
}),
});
return Response.json(await orm.user.count());
},
};Cloudflare KV
import { createOrm } from "@farming-labs/orm";
import { createKvDriver } from "@farming-labs/orm-kv";
export type Env = {
KV: KVNamespace;
};
export default {
async fetch(_request: Request, env: Env) {
const orm = createOrm({
schema: authSchema,
driver: createKvDriver({
client: env.KV,
}),
});
return Response.json(await orm.session.count());
},
};Redis / Upstash Redis
import { createClient } from "redis";
import { createOrm } from "@farming-labs/orm";
import { createRedisDriver } from "@farming-labs/orm-redis";
const redis = createClient({
url: process.env.REDIS_URL,
});
await redis.connect();
const orm = createOrm({
schema: authSchema,
driver: createRedisDriver({
client: redis,
}),
});Supabase JS
import { createClient } from "@supabase/supabase-js";
import { createOrm } from "@farming-labs/orm";
import { createSupabaseDriver } from "@farming-labs/orm-supabase";
const supabase = createClient(process.env.SUPABASE_URL!, process.env.SUPABASE_SERVICE_ROLE_KEY!);
const orm = createOrm({
schema: authSchema,
driver: createSupabaseDriver({
client: supabase,
}),
});TypeORM
import { createOrm } from "@farming-labs/orm";
import { createTypeormDriver } from "@farming-labs/orm-typeorm";
import { DataSource } from "typeorm";
const dataSource = new DataSource({
type: "postgres",
url: process.env.DATABASE_URL,
entities: [],
});
await dataSource.initialize();
const orm = createOrm({
schema: authSchema,
driver: createTypeormDriver({
dataSource,
}),
});MikroORM
import { createOrm } from "@farming-labs/orm";
import { createMikroormDriver } from "@farming-labs/orm-mikroorm";
import { MikroORM } from "@mikro-orm/postgresql";
const mikroorm = await MikroORM.init({
clientUrl: process.env.DATABASE_URL,
entities: [],
discovery: {
warnWhenNoEntities: false,
},
});
const orm = createOrm({
schema: authSchema,
driver: createMikroormDriver({
orm: mikroorm,
}),
});Sequelize
import { createOrm } from "@farming-labs/orm";
import { createSequelizeDriver } from "@farming-labs/orm-sequelize";
import { Sequelize } from "sequelize";
const sequelize = new Sequelize(process.env.DATABASE_URL!, {
dialect: "postgres",
logging: false,
});
const orm = createOrm({
schema: authSchema,
driver: createSequelizeDriver({
sequelize,
}),
});MongoDB
import { createOrm } from "@farming-labs/orm";
import { createMongoDriver } from "@farming-labs/orm-mongo";
import { MongoClient } from "mongodb";
const client = new MongoClient(process.env.MONGODB_URL!);
await client.connect();
const orm = createOrm({
schema: authSchema,
driver: createMongoDriver({
db: client.db("app"),
client,
}),
});DynamoDB
import { createOrm } from "@farming-labs/orm";
import { createDynamodbDriver } from "@farming-labs/orm-dynamodb";
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
const client = new DynamoDBClient({
region: process.env.AWS_REGION ?? "us-east-1",
});
const orm = createOrm({
schema: authSchema,
driver: createDynamodbDriver({
client,
}),
});Unstorage
import { createOrm } from "@farming-labs/orm";
import { createUnstorageDriver } from "@farming-labs/orm-unstorage";
import { createStorage } from "unstorage";
import memoryDriver from "unstorage/drivers/memory";
const storage = createStorage({
driver: memoryDriver(),
});
const orm = createOrm({
schema: authSchema,
driver: createUnstorageDriver({
storage,
}),
});Mongoose
import { createOrm } from "@farming-labs/orm";
import { createMongooseDriver } from "@farming-labs/orm-mongoose";
const orm = createOrm({
schema: authSchema,
driver: createMongooseDriver<typeof authSchema>({
models: {
user: UserModel,
profile: ProfileModel,
session: SessionModel,
account: AccountModel,
},
connection: mongoose.connection,
}),
});Or detect the runtime automatically
If you already have the raw runtime instance and want the helper to build the
driver for you, use @farming-labs/orm-runtime:
import { createOrmFromRuntime } from "@farming-labs/orm-runtime";
const orm = await createOrmFromRuntime({
schema: authSchema,
client: prisma,
});That path is especially useful for higher-level integrations that want to accept a raw Prisma, Drizzle, Kysely, MikroORM, TypeORM, Sequelize, SQL, EdgeDB / Gel, Cloudflare D1, Cloudflare KV, Redis, Supabase, Firestore, DynamoDB, Unstorage, MongoDB, or Mongoose runtime.
5. Use the client
const user = await orm.user.findUnique({
where: {
email: "ada@farminglabs.dev",
},
select: {
id: true,
email: true,
profile: {
select: {
bio: true,
},
},
sessions: {
select: {
token: true,
expiresAt: true,
},
},
},
});6. Verify with local databases
pnpm test already runs the real integration matrix. These commands are useful
when you want to rerun the database-backed suites directly.
pnpm test:local
pnpm test:local:prisma
pnpm test:local:drizzle
pnpm test:local:sqlite
pnpm test:local:postgres
pnpm test:local:mysql
pnpm test:local:supabase
pnpm test:local:sequelize
pnpm test:local:typeorm
pnpm test:local:mikroorm
pnpm test:local:dynamodb
pnpm test:local:unstorage
pnpm test:local:mongodbContinue
How is this guide?