@farming-labs/orm

Xata

Xata integration is runtime-first.

Use @farming-labs/orm-xata when:

Supported Xata runtime inputs

The current runtime uses Xata's own SQL surface directly. It does not invent another hidden PostgreSQL client.

Runtime setup

xata-runtime.ts
import { createOrm } from "@farming-labs/orm";
import { createXataDriver } from "@farming-labs/orm-xata";
import { xata } from "./xata-client";
import { appSchema } from "./schema";

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

From there, shared code keeps using the same unified API:

const user = await orm.user.findUnique({
  where: {
    email: "ada@farminglabs.dev",
  },
  select: {
    id: true,
    email: true,
    sessions: {
      select: {
        token: true,
      },
    },
  },
});

What the Xata driver is doing

The Xata driver keeps the shared ORM surface and translates it through client.sql(...) against Xata's SQL layer.

It:

  1. accepts the app's real Xata client
  2. executes reads and writes through Xata's SQL API
  3. keeps the same normalized error and capability surface as the rest of the repo
  4. preserves Postgres-style features such as generated numeric IDs and schema namespaces

That means a package can write its storage layer once while each app decides whether the actual execution stack is Xata, Prisma, Drizzle, Kysely, MikroORM, TypeORM, Sequelize, direct SQL, Supabase, Neo4j, Firestore, DynamoDB, Redis, MongoDB, or Mongoose.

Runtime helper path

If a framework or shared package wants to accept the raw Xata client directly, use the runtime helpers:

import { createOrmFromRuntime } from "@farming-labs/orm-runtime";

const orm = await createOrmFromRuntime({
  schema: appSchema,
  client: xata,
});

That is the cleanest path for higher-level integrations that do not want to branch on Xata specifically.

Setup helpers

The setup helpers work with Xata too:

import { bootstrapDatabase, pushSchema } from "@farming-labs/orm-runtime/setup";

await pushSchema({
  schema: appSchema,
  client: xata,
});

const orm = await bootstrapDatabase({
  schema: appSchema,
  client: xata,
});

For Xata runtimes, that setup path renders safe PostgreSQL DDL and applies it through the Xata client.

That is useful when a package or framework wants:

Transactions and limits

The current Xata runtime is intentionally conservative about transactions.

That means:

This keeps the runtime honest while still making it useful for real package and framework storage layers.

Numeric IDs and namespaces

Because the Xata runtime uses the PostgreSQL SQL surface, it supports the same high-value pieces many shared packages care about:

Local verification

Run the local Xata suite with:

terminal
pnpm test:local:xata

That package-local suite uses a real local PostgreSQL-backed Xata-shaped runtime harness so the query, setup, generated numeric ID, and namespace paths are all exercised against a live SQL backend.

If you also want to verify the runtime against a real Xata project, run:

terminal
export XATA_API_KEY=your-xata-api-key
export XATA_DATABASE_URL=https://workspace.region.xata.sh/db/database:branch
pnpm test:xata:real

That opt-in suite talks to the official Xata client directly and is meant for a dedicated test branch or database URL.