@farming-labs/orm

Use Cases

The strongest fit is anything that needs one storage-facing design while giving consuming applications room to choose their own persistence stack.

Sections

1. Auth-like libraries

This is one of the clearest use cases.

The usual problem

Auth libraries often end up maintaining:

What Farming Labs ORM changes

The auth package can define its schema once:

export const authSchema = defineSchema({
  user: model({
    table: "users",
    fields: {
      id: id(),
      email: string().unique(),
      name: string(),
      createdAt: datetime().defaultNow(),
    },
    relations: {
      sessions: hasMany("session", { foreignKey: "userId" }),
      accounts: hasMany("account", { foreignKey: "userId" }),
    },
  }),
  session: model({
    table: "sessions",
    fields: {
      id: id(),
      userId: string().references("user.id"),
      token: string().unique(),
    },
    relations: {
      user: belongsTo("user", { foreignKey: "userId" }),
    },
  }),
  account: model({
    table: "accounts",
    fields: {
      id: id(),
      userId: string().references("user.id"),
      provider: string(),
      accountId: string(),
    },
    relations: {
      user: belongsTo("user", { foreignKey: "userId" }),
    },
  }),
});

Then the consuming app decides how to generate it:

export default defineConfig({
  schemas: [authSchema],
  targets: {
    prisma: { out: "./generated/prisma/schema.prisma", provider: "postgresql" },
  },
});

The package also gets one runtime-facing contract for storage helpers:

export async function findUserByEmail(
  orm: ReturnType<typeof createOrm<typeof authSchema>>,
  email: string,
) {
  return orm.user.findFirst({
    where: { email },
    select: {
      id: true,
      email: true,
      sessions: {
        select: {
          token: true,
        },
      },
    },
  });
}

2. Billing and organization kits

Billing modules often need reusable data definitions for:

Instead of hand-writing those tables and examples for every consumer stack, the package can ship one schema contract and let apps generate their preferred output.

Example structure

export const billingSchema = defineSchema({
  plan: model({
    table: "plans",
    fields: {
      id: id(),
      slug: string().unique(),
      name: string(),
    },
  }),
  subscription: model({
    table: "subscriptions",
    fields: {
      id: id(),
      userId: string(),
      planId: string().references("plan.id"),
      status: string(),
      createdAt: datetime().defaultNow(),
    },
  }),
});

This is especially nice in a monorepo where many products need the same commercial model but not the same ORM choice.

3. Internal platform modules

Platform teams often own cross-cutting packages for:

The cost of drift grows fast when every app re-implements that schema individually.

With Farming Labs ORM, the platform team can:

  1. own the shared schema package
  2. publish docs and examples from the same contract
  3. generate stack-specific output for each consumer app

4. Greenfield apps that want a safe starting point

A greenfield app does not have to adopt a future runtime driver immediately.

It can start with:

Then later add richer drivers without replacing the source of truth.

5. Multi-package monorepos

The CLI supports multiple schema packages:

import { defineConfig } from "@farming-labs/orm-cli";
import { authSchema } from "@acme/auth";
import { billingSchema } from "@acme/billing";
import { orgSchema } from "@acme/org";

export default defineConfig({
  schemas: [authSchema, billingSchema, orgSchema],
  targets: {
    prisma: {
      out: "./generated/prisma/schema.prisma",
      provider: "postgresql",
    },
  },
});

That is one of the highest-leverage workflows in the project because it lets several reusable packages contribute models into one generated application surface.

6. When this approach is not the best fit

Farming Labs ORM is probably overkill when:

Practical decision rule

This approach becomes more valuable as these increase:

If your biggest pain is “we keep rewriting the same storage story for every consumer,” this project is aimed directly at that pain.