@farming-labs/orm

Cloudflare D1

Cloudflare D1 support in Farming Labs ORM is the worker-native SQLite answer for teams that want one storage layer without introducing a separate Cloudflare-only adapter surface.

The supported path is the real D1 binding:

That keeps the runtime Cloudflare-friendly while still letting package and framework code stay backend-agnostic.

What this gives you

You still write the schema and storage layer once.

Then the runtime translates that layer into D1-backed SQLite operations with:

That is a strong fit for framework modules, auth state, billing state, cache metadata, and other shared storage contracts running inside Workers.

Create the runtime directly

cloudflare-d1-runtime.ts
import { createOrm } from "@farming-labs/orm";
import { createD1Driver } from "@farming-labs/orm-d1";
import { appSchema } from "./schema";

type Env = {
  DB: D1Database;
};

export default {
  async fetch(_request: Request, env: Env) {
    const orm = createOrm({
      schema: appSchema,
      driver: createD1Driver({
        client: env.DB,
      }),
    });

    const count = await orm.user.count();
    return Response.json({ count });
  },
};

Use the runtime helper path

If a framework or shared package wants to accept the raw D1 binding and normalize it later, use the runtime helpers:

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

const orm = await createOrmFromRuntime({
  schema: appSchema,
  client: env.DB,
});

That keeps the package boundary generic instead of forcing a D1-specific branch.

Setup helpers

The D1 runtime itself is Worker-friendly. The setup helpers are different:

That means the common pattern is:

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

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

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

Joins, relations, and transactions

D1 is still SQLite-backed, so the relational query surface works well.

That means:

At the same time, the runtime stays conservative about transaction semantics:

That keeps the capability story honest for framework and auth integrations.

What is supported well

Important limits

Why it matters

This keeps Cloudflare D1 inside the same bigger ORM story: