npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@flixydev/prisma-to-drizzle-v1-generator

v0.0.9

Published

Prisma 6 generator that emits Drizzle ORM v1-rc PostgreSQL schema and relations.

Readme

Prisma to Drizzle V1 Generator

Generate Drizzle ORM 1.0 RC PostgreSQL schema files from a Prisma ^6 schema.

The generator is built for teams that want to move runtime code from Prisma to Drizzle without letting Drizzle migrations invent a different database. It fails closed: if a Prisma feature cannot be mapped to migration-equivalent Drizzle output, generation stops with a diagnostic instead of emitting an approximation.

Status

  • Target database: PostgreSQL.
  • Target Prisma schema: Prisma ^6.
  • Target Drizzle ORM: 1.0.0-rc.
  • Main output: Drizzle table definitions, enums, foreign keys, indexes, primary keys, unique indexes, and Drizzle V1 relations.
  • Other databases are intentionally not supported yet.

Install

pnpm add drizzle-orm pg
pnpm add -D @flixydev/prisma-to-drizzle-v1-generator drizzle-kit prisma

drizzle-orm is a peer dependency. pg is not required by this generator itself, but Drizzle Kit needs a PostgreSQL driver for pull, migrate, and similar database commands. You may use another Drizzle-supported PostgreSQL driver if your project already has one.

Add the Prisma generator

generator drizzle {
  provider         = "prisma-to-drizzle-v1-generator"
  output           = "../src/db/generated"
  dialect          = "postgresql"
  importSpecifiers = "js"
  format           = true
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

Then run:

pnpm prisma generate

The generated folder is flat:

src/db/generated/
  index.ts
  schema.ts
  relations.ts
  users.ts
  posts.ts
  user-role-enum.ts

relations.ts is the Drizzle connection entrypoint:

import { drizzle } from "drizzle-orm/node-postgres";
import { relations } from "./db/generated/relations.js";

export const db = drizzle(client, { relations });

index.ts is the application barrel and exports only generated tables and enums:

import { users, userRoleEnum } from "./db/generated/index.js";

For Drizzle Kit CLI, pass the generated directory, not only schema.ts:

// drizzle.config.ts
import { defineConfig } from "drizzle-kit";

export default defineConfig({
  dialect: "postgresql",
  schema: "./src/db/generated",
  out: "./drizzle",
  dbCredentials: {
    url: process.env.DATABASE_URL!,
  },
});

Drizzle Kit 1.0.0-rc.1 scans exported tables from schema files. The aggregate schema object exported by schema.ts is an internal helper for generated relations and tooling, not the Drizzle connection config.

Configuration

type GeneratorConfig = {
  output: string;
  dialect?: "postgresql";
  importSpecifiers?: "extensionless" | "js" | "ts";
  format?: boolean;
};
  • output: required output directory.
  • dialect: only postgresql is supported.
  • importSpecifiers: generated relative import style.
  • format: runs oxfmt on generated files when true.

Import specifier modes:

extensionless -> import { users } from "./users";
js            -> import { users } from "./users.js";
ts            -> import { users } from "./users.ts";

Use js for NodeNext/Node ESM TypeScript projects that compile to JavaScript. Use extensionless for bundler-style resolution. Use ts when a tool reads the generated TypeScript files directly.

CLI

The package also exposes a debug CLI:

prisma-to-drizzle-v1 generate \
  --schema prisma/schema.prisma \
  --output src/db/generated \
  --dialect postgresql \
  --import-specifiers js \
  --format true

--schema accepts either one schema.prisma file or a Prisma schema directory.

DMMF audit helper:

prisma-to-drizzle-v1 audit-dmmf --schema prisma

Migration handoff from Prisma to Drizzle

There are two separate steps:

  1. Generate Drizzle runtime schema from Prisma.
  2. Baseline Drizzle Kit migrations against the existing database.

Do not apply a first Drizzle migration generated from an empty migration history to an existing Prisma database. That migration would describe creating the whole database from scratch.

Recommended handoff:

# 1. Generate Drizzle schema files.
pnpm prisma generate

# 2. Create Drizzle Kit baseline metadata from the existing DB.
pnpm drizzle-kit pull --init --config drizzle.config.ts

# 3. Verify that the generated schema produces no follow-up migration.
pnpm drizzle-kit generate --config drizzle.config.ts

Expected result for step 3: no schema changes. If Drizzle Kit generates a migration after pull --init, treat that as a migration fidelity bug to investigate before switching production migration ownership.

Directives

Directives are written in Prisma documentation comments with the drizzle. namespace.

Unknown or malformed drizzle.* directives are hard errors.

Runtime defaults

Prisma runtime defaults such as cuid() are application behavior, not database DDL. Add an explicit runtime default function:

model User {
  /// drizzle.defaultFn @paralleldrive/cuid2::createId
  id String @id @default(cuid())
}

Emits:

id: text("id")
  .notNull()
  .$defaultFn(() => createId());

For compatibility, drizzle.default module::export is also accepted for this runtime-default use case. Prefer drizzle.defaultFn in new schemas.

Database defaults

Use drizzle.default to explain an existing Prisma @default when the mapping cannot be inferred safely:

model Token {
  /// drizzle.default sql`gen_random_uuid()`
  id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
}

drizzle.default may only explain an existing Prisma @default; it cannot add a new default that Prisma does not have.

Known defaults are mapped automatically:

  • now() -> sql.raw("CURRENT_TIMESTAMP")
  • autoincrement() -> serial, smallserial, or bigserial
  • scalar and enum literals
  • PostgreSQL array defaults
  • dbgenerated("...") where Prisma exposes the SQL expression

Typed JSON and JSON arrays

model StorePageUrgency {
  /// drizzle.defaultFn @paralleldrive/cuid2::createId
  id String @id @default(cuid())

  /// drizzle.type @flixydev/flixy-types/prisma::StorePageUrgency
  urgency Json
}

Emits:

import { createId } from "@paralleldrive/cuid2";
import type { StorePageUrgency } from "@flixydev/flixy-types/prisma";

export const storePageUrgencies = pgTable("StorePageUrgency", {
  id: text("id")
    .notNull()
    .$defaultFn(() => createId()),
  urgency: jsonb("urgency").$type<StorePageUrgency>().notNull(),
});

For Prisma list fields, drizzle.type describes the element type before Drizzle .array() is applied:

model Page {
  /// drizzle.type @app/types::Block
  blocks Json[]
}

Emits:

blocks: jsonb("blocks").$type<Block>().array();

If you want a PostgreSQL array whose element is itself an array, put the array in the type:

/// drizzle.type @app/types::Block[]
nestedBlocks Json[]

Custom column builders

Use drizzle.column when Prisma uses an unsupported database type or when your project has a custom Drizzle column builder:

model Place {
  /// drizzle.column @app/db/columns::geometryPoint
  /// drizzle.type @app/types::GeoPoint
  location Unsupported("geometry(Point,4326)")
}

The generator still applies Prisma nullability, defaults, primary keys, unique indexes, and foreign keys where valid.

Custom @updatedAt

Prisma @updatedAt emits:

.$onUpdate(() => new Date())

Override it when your runtime needs a different expression:

model Post {
  /// drizzle.onUpdateFn () => new Date()
  updatedAt DateTime @updatedAt
}

Table symbol override

The exported TypeScript table symbol is plural-ish by default. Override it when needed:

/// drizzle.tableSymbol people
model Person {
  id String @id

  @@map("people")
}

SQL table names still come from Prisma @@map or the Prisma model name.

What is generated

The generator currently supports:

  • tables and columns
  • nullability
  • Prisma @map and @@map
  • PostgreSQL native scalar types in the supported matrix
  • enums via pgEnum
  • primary keys, including compound primary keys
  • Prisma @unique and @@unique as PostgreSQL unique indexes
  • non-unique @@index, including mapped names, sort direction, and GIN indexes
  • foreign keys and referential actions
  • Prisma implicit many-to-many join tables
  • Drizzle V1 defineRelations(...)
  • strongly typed Json and Json[]
  • multi-file Prisma schema input

Important fidelity details:

  • @default(now()) emits CURRENT_TIMESTAMP, not .defaultNow(), so Drizzle Kit baseline introspection does not create a handoff diff.
  • sort: Desc emits .desc().nullsFirst() because PostgreSQL's default null ordering for descending index columns is NULLS FIRST.
  • Prisma scalar lists are emitted as PostgreSQL arrays without .notNull(), matching Prisma Migrate's nullable array DDL.
  • Implicit many-to-many relations generate Prisma's hidden join table shape, including _RelationName, A, B, composite primary key, foreign keys, and B index.

Unsupported features

These are hard errors:

  • non-PostgreSQL datasources
  • relationMode = "prisma" or referentialIntegrity = "prisma"
  • PostgreSQL multi-schema output
  • views
  • @ignore and @@ignore
  • implicit self many-to-many relations
  • Unsupported("...") without drizzle.column
  • PostgreSQL native types outside the supported matrix unless a custom builder is supplied
  • runtime defaults such as cuid() or uuid() without drizzle.defaultFn

File ownership

Generated files contain this header:

// This file was generated by prisma-to-drizzle-v1-generator. Do not edit manually.

The generator overwrites files in its configured output directory. It does not write a manifest, metadata file, or metadata directory.

Obsolete generated files are not deleted automatically when models are removed or renamed. Keep the output directory in git and review generated diffs. Legacy manifest artifacts from earlier generator versions are cleaned up when they can be identified as generator-owned.

Testing a migration handoff

This repository includes an end-to-end handoff test:

pnpm run test:postgres

It uses Testcontainers to start postgres:16-alpine, applies Prisma SQL from an empty database, runs drizzle-kit pull --init, and verifies that drizzle-kit generate creates no additional migration snapshot.

Package installation can be smoke-tested with:

pnpm run test:package

That test builds the package, runs pnpm pack, installs the packed tarball into a temporary consumer project, runs prisma generate through the package provider, and typechecks the generated schema.

The real Flixy multi-file fixture can be checked with:

pnpm run test:real-world

That test compares the PostgreSQL SQL footprint from Prisma migrate diff against the SQL footprint produced from the generated Drizzle schema.

Requirements:

  • Docker, OrbStack, or another Testcontainers-compatible container runtime.
  • A shell with access to the container runtime socket.

You can also run the same test against an existing PostgreSQL server:

P2D_POSTGRES_URL=postgresql://postgres:postgres@localhost:5432/postgres \
  pnpm exec vitest run test/integration/drizzle-baseline-handoff.test.ts

In that mode the test creates and drops a temporary database under the provided server.

Development

pnpm install
pnpm run typecheck
pnpm exec vitest run
pnpm run test:package
pnpm run test:postgres
pnpm run test:real-world
pnpm run format:check
pnpm build

pnpm exec vitest run skips the live PostgreSQL handoff test by default. Use pnpm run test:postgres when Docker is available.