# Getting Started
URL: /docs/getting-started
LLM index: /llms.txt
Description: Define a schema, add a config file, and generate your first artifacts.

# Getting Started

The shortest path is:

1. Define a schema in `@farming-labs/orm`
2. Add `farm-orm.config.ts`
3. Generate target output
4. Pick a runtime driver

## 1. Define a schema

```ts title="src/schema.ts"
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`

```ts title="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

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

Generated Prisma and Drizzle output already includes direct relation metadata for:

- `belongsTo`
- `hasOne`
- `hasMany`

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(...)` and `upsert(...)` key across supported drivers

## 4. Pick a runtime

### Memory

```ts title="memory-runtime.ts"
import { createMemoryDriver, createOrm } from "@farming-labs/orm";

const orm = createOrm({
  schema: authSchema,
  driver: createMemoryDriver(),
});
```

### Prisma

```ts title="prisma-runtime.ts"
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

```ts title="drizzle-runtime.ts"
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

```ts title="sql-runtime.ts"
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

```ts title="edgedb-runtime.ts"
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(),
  }),
});
```

### Xata

```ts title="xata-runtime.ts"
import { createOrm } from "@farming-labs/orm";
import { createXataDriver } from "@farming-labs/orm-xata";
import { xata } from "./xata-client";

const orm = createOrm({
  schema: authSchema,
  driver: createXataDriver({
    client: xata,
  }),
});
```

### Cloudflare D1

```ts title="cloudflare-d1-runtime.ts"
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

```ts title="cloudflare-kv-runtime.ts"
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

```ts title="redis-runtime.ts"
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

```ts title="supabase-runtime.ts"
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

```ts title="typeorm-runtime.ts"
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

```ts title="mikroorm-runtime.ts"
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

```ts title="sequelize-runtime.ts"
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

```ts title="mongo-runtime.ts"
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

```ts title="dynamodb-runtime.ts"
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

```ts title="unstorage-runtime.ts"
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

```ts title="mongoose-runtime.ts"
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`:

```ts title="auto-runtime.ts"
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

```ts title="user-query.ts"
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.

```bash title="terminal"
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:mongodb
```

## Continue

- [Runtime](/docs/runtime)
- [Prisma integration](/docs/integrations/prisma)
- [Drizzle integration](/docs/integrations/drizzle)
- [Sequelize integration](/docs/integrations/sequelize)
- [TypeORM integration](/docs/integrations/typeorm)
- [MikroORM integration](/docs/integrations/mikroorm)
- [SQL databases](/docs/integrations/sql-databases)
- [Cloudflare KV](/docs/integrations/cloudflare-kv)
- [Redis / Upstash Redis](/docs/integrations/redis)
- [Supabase](/docs/integrations/supabase)
- [DynamoDB](/docs/integrations/dynamodb)
- [Unstorage](/docs/integrations/unstorage)
- [MongoDB](/docs/integrations/mongodb)