@farming-labs/orm

Sequelize

Sequelize integration is runtime-first.

Use @farming-labs/orm-sequelize when:

Supported Sequelize dialect families

The current repo verifies the live matrix on PostgreSQL and MySQL. MariaDB flows through the same MySQL-family path.

Runtime setup

sequelize-runtime.ts
import { createOrm } from "@farming-labs/orm";
import { createSequelizeDriver } from "@farming-labs/orm-sequelize";
import { Sequelize } from "sequelize";
import { authSchema } from "./schema";

const sequelize = new Sequelize(process.env.DATABASE_URL!, {
  dialect: "postgres",
  logging: false,
});

const orm = createOrm({
  schema: authSchema,
  driver: createSequelizeDriver({
    sequelize,
  }),
});

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,
    profile: {
      select: {
        bio: true,
      },
    },
    sessions: {
      select: {
        token: true,
      },
    },
  },
});

What the Sequelize driver is doing

The Sequelize driver does not invent a second schema system.

It:

  1. accepts the app's real Sequelize instance
  2. executes through sequelize.query(...) and Sequelize transactions
  3. reuses the shared SQL runtime semantics for filtering, mutations, relation loading, compound unique lookups, numeric IDs, namespaces, and normalized errors

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

Runtime helper path

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

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

const sequelize = new Sequelize(process.env.DATABASE_URL!, {
  dialect: "postgres",
  logging: false,
});

const orm = await createOrmFromRuntime({
  schema: authSchema,
  client: sequelize,
});

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

Setup helpers

The setup helpers work with Sequelize too:

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

await pushSchema({
  schema: authSchema,
  client: sequelize,
});

const orm = await bootstrapDatabase({
  schema: authSchema,
  client: sequelize,
});

For Sequelize runtimes, that setup path renders safe SQL from the Farming Labs schema and applies it through the live connection.

That is especially useful when a package or framework wants:

Relation support

The Sequelize runtime inherits the current SQL-family relation behavior:

That means auth-style and framework-style relation reads still work through the same unified API surface.

Transactions and mutations

Sequelize transactions map into the unified ORM transaction surface:

await orm.transaction(async (tx) => {
  const user = await tx.user.create({
    data: {
      email: "ada@farminglabs.dev",
      name: "Ada",
    },
    select: {
      id: true,
    },
  });

  await tx.session.upsert({
    where: {
      token: "session-token",
    },
    create: {
      userId: user.id,
      token: "session-token",
      expiresAt: new Date("2027-01-01T00:00:00.000Z"),
    },
    update: {
      expiresAt: new Date("2027-01-01T00:00:00.000Z"),
    },
  });
});

The same runtime also supports:

Local verification

The repo verifies Sequelize locally against PostgreSQL and MySQL.

Run it with:

terminal
pnpm test:local:sequelize

If you want to point the suite at your own local database URLs, use:

export FARM_ORM_LOCAL_PG_ADMIN_URL=postgres://postgres:postgres@127.0.0.1:5432/postgres
export FARM_ORM_LOCAL_MYSQL_ADMIN_URL=mysql://root:root@127.0.0.1:3306

pnpm test:local:sequelize

You can also target a single Sequelize family while debugging:

FARM_ORM_LOCAL_SEQUELIZE_TARGETS=postgresql pnpm --filter @farming-labs/orm-sequelize test
FARM_ORM_LOCAL_SEQUELIZE_TARGETS=mysql pnpm --filter @farming-labs/orm-sequelize test

The PostgreSQL and MySQL paths create isolated temporary databases during the run and clean those databases up afterward.

Why it fits well

Sequelize already gives apps a familiar runtime abstraction.

Farming Labs ORM sits one layer above that:

That is the main value: Sequelize apps can participate in the same package-level storage contract as TypeORM, Prisma, Drizzle, Kysely, direct SQL, Firestore, MongoDB, and Mongoose apps.