A Bridge CLI to manage Cloudflare D1 migrations with Prisma 7
npm install -g d1-prisma
# or
yarn global add d1-prisma
# or
pnpm add -g d1-prisma
# or
bun add -g d1-prismaTo install dependencies:
bun installTo build:
bun run buildTo run from source:
bun run src/index.ts- Prisma 7 Compatible: Works with Prisma 7's
prisma.config.tsconfiguration - Seamless Integration: Bridges Cloudflare D1 and Prisma migrations for a smooth development workflow
- Migration Creation: Generates SQL migration files based on Prisma schema changes using
prisma migrate diff - Migration Application: Applies migrations to local or remote D1 databases
- Migration Status: View applied and pending migrations
- Baseline Support: Create baseline migrations for existing databases
- Dry Run: Preview SQL diffs without writing files
- CI/CD Mode: Non-interactive mode for automated pipelines
- Cross-Platform: Works on Windows, macOS, and Linux
- Multiple Package Managers: Compatible with npm, yarn, pnpm, and bun
- Node.js (v20 or higher)
- Wrangler CLI (v3.39.0 or higher)
- Prisma CLI (v7 or higher)
- A configured Cloudflare D1 database
Ensure you have a wrangler.jsonc or wrangler.toml file with your D1 database configuration:
Create a prisma.config.ts file in your project root:
// prisma.config.ts
import "dotenv/config";
import { defineConfig, env } from "prisma/config";
import { listLocalDatabases } from "@prisma/adapter-d1";
export default defineConfig({
schema: "prisma/schema.prisma",
migrations: {
path: "prisma/migrations",
},
datasource: {
url: `file:${listLocalDatabases().pop()}`, // resolve d1 .sqlite files in ./.wrangler/state/..."
},
});And set up your Prisma schema:
// prisma/schema.prisma
generator client {
provider = "prisma-client"
output = "../src/generated/prisma"
runtime = "cloudflare"
}
datasource db {
provider = "sqlite"
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
}To create a new migration:
d1-prisma create --name "add-users-table"The CLI will:
- Validate your Prisma schema
- Read the migrations directory from
prisma.config.ts - Determine if this is an initial migration or a schema change
- Generate the SQL diff using
prisma migrate diff - Write the migration file
For subsequent migrations, the tool uses --from-config-datasource to compare against your local D1 database state. If you have pending migrations not yet applied locally, you'll be warned to apply them first.
To apply migrations locally:
d1-prisma applyTo apply migrations to remote database:
d1-prisma apply --remoteAfter applying, the CLI automatically regenerates your Prisma client.
d1-prisma statusShows applied and pending migrations.
For existing D1 databases, create a baseline migration:
d1-prisma create --name "baseline" --baselineThis creates a migration representing the current database state and marks it as applied.
Preview the SQL diff without writing:
d1-prisma create --name "add-users-table" --dry-run| Option | Description |
|---|---|
-d, --database <name> |
D1 database name (overrides config) |
--wrangler-config <path> |
Custom wrangler config path |
--non-interactive |
Skip prompts (CI/CD mode) |
--log <level> |
Log level (info, debug) |
| Option | Description |
|---|---|
--name, -n <name> |
Migration name (required in non-interactive mode) |
--schema <path> |
Custom Prisma schema path (default: ./prisma/schema.prisma) |
--migrations-dir <path> |
Custom migrations directory (overrides prisma.config.ts) |
--baseline |
Mark migration as applied in local state |
--dry-run |
Preview SQL without writing |
--verbose |
Show detailed output |
| Option | Description |
|---|---|
--local |
Apply to local D1 (default) |
--remote |
Apply to remote D1 |
The tool automatically detects your configuration files:
d1-prisma.config.jsonfor tool-specific settings (recommended)wrangler.jsonc,wrangler.json, orwrangler.tomlfor D1 database configurationprisma.config.tsfor migrations directory path
You can create a d1-prisma.config.json file in your project root to avoid passing flags manually.
{
"$schema": "./node_modules/d1-prisma/schema.json",
"database": "my-database-name",
"wranglerConfig": "wrangler.toml",
"wranglerDataDir": ".wrangler/state",
"migrationsDir": "./prisma/migrations",
"schema": "./prisma/schema.prisma"
}When using d1-prisma in a monorepo (e.g., Turborepo, Nx), the local D1 state might be located in a different directory than the package root.
To ensure d1-prisma finds your local D1 database, you should define wranglerDataDir in your d1-prisma.config.json. This value is also passed to Wrangler commands via the --persist-to flag.
my-monorepo/
├── wrangler.toml # Global wrangler config
├── packages/
│ └── database/
│ ├── prisma/
│ ├── d1-prisma.config.json
│ └── package.json
└── .wrangler/ # Local D1 state is here
In packages/database/d1-prisma.config.json:
{
"wranglerConfig": "../../wrangler.json",
"wranglerDataDir": "../../.wrangler/state"
}This configuration tells d1-prisma to:
- Look for the D1 database definitions in the root
wrangler.json. - Look for the local SQLite files and apply migrations using the state located in the root
.wranglerdirectory.
To ensure Prisma 7 correctly connects to the local D1 database managed by Wrangler in a monorepo, we recommend using a dynamic datasource.url in your prisma.config.ts:
// packages/database/prisma.config.ts
import path from "node:path";
import fs from "node:fs";
import "dotenv/config";
import { defineConfig } from "prisma/config";
const localD1DatabasePath = path.join(
"..",
"..",
".wrangler",
"state",
"v3",
"d1",
"miniflare-D1DatabaseObject"
);
function listCustomLocalDatabases() {
const cwd = process.cwd();
const d1DirPath = path.join(cwd, localD1DatabasePath);
try {
const files = fs.readdirSync(d1DirPath);
return files
.filter((file) => file.endsWith(".sqlite"))
.map((file) => path.join(d1DirPath, file));
} catch {
return [];
}
}
export function getLocalDb() {
const db = listCustomLocalDatabases()
.filter((v) => !v.includes("metadata"))
.pop();
return db ? `file:${db}` : process.env.DATABASE_URL;
}
export default defineConfig({
schema: "prisma/schema.prisma",
migrations: {
path: "prisma/migrations",
},
datasource: {
url: getLocalDb(),
},
});If the library is not behaving as expected, you can use the --log debug flag to see detailed information about:
- Resolved configuration paths
- Environment variables
- Commands being executed
- Local database discovery process
d1-prisma status --log debugFor automated pipelines, use the --non-interactive flag:
d1-prisma create --name "add-users" --database my-database --non-interactive
d1-prisma apply --database my-database --non-interactive
d1-prisma apply --database my-database --remote --non-interactive
d1-prisma status --database my-database --non-interactivebuild: Build the project todist/directorydev: Watch mode for developmentstart: Run the built CLI
The project consists of:
src/index.ts: Main CLI entry pointsrc/utils/config.ts: Wrangler configuration file parsingsrc/utils/shell.ts: Shell command utilitiessrc/utils/migrations.ts: Migration file management utilities
Contributions are welcome! Please feel free to submit a Pull Request.
This project is open source and available under the MIT License.
- Cloudflare D1 - Serverless database
- Prisma - Database toolkit
- Wrangler - Cloudflare CLI tool
- Inspired by Alex Anderson Migrator CLI
If you encounter any issues or have questions, please open an issue on GitHub.
- Prisma 7 compatibility
prisma.config.tssupport- Migration status command
- Baseline migration support
- Dry run mode
- Non-interactive/CI mode
- Improved error handling
- Local D1 sync detection
- Initial release
- Basic migration creation and application
- Support for local and remote databases