wizzle-cli
v0.31.6
Published
Experimental fork of drizzle-kit for custom modifications
Maintainers
Readme
Wizzle CLI
Wizzle is an experimental fork of Drizzle Kit - a CLI migrator tool for Drizzle ORM. It is probably the one and only tool that lets you completely automatically generate SQL migrations and covers ~95% of the common cases like deletions and renames by prompting user input.
Note: This is a custom fork for experimental modifications. The package is published as wizzle-cli on npm. For the official version, see drizzle-kit.
Documentation
Check the full documentation for Drizzle Kit on the website.
How it works
Wizzle traverses a schema module and generates a snapshot to compare with the previous version, if there is one. Based on the difference, it will generate all needed SQL migrations. If there are any cases that can't be resolved automatically, such as renames, it will prompt the user for input.
For example, for this schema module:
// src/db/schema.ts
import { integer, pgTable, serial, text, varchar } from "drizzle-orm/pg-core";
const users = pgTable("users", {
id: serial("id").primaryKey(),
fullName: varchar("full_name", { length: 256 }),
}, (table) => ({
nameIdx: index("name_idx", table.fullName),
})
);
export const authOtp = pgTable("auth_otp", {
id: serial("id").primaryKey(),
phone: varchar("phone", { length: 256 }),
userId: integer("user_id").references(() => users.id),
});It will generate:
CREATE TABLE IF NOT EXISTS auth_otp (
"id" SERIAL PRIMARY KEY,
"phone" character varying(256),
"user_id" INT
);
CREATE TABLE IF NOT EXISTS users (
"id" SERIAL PRIMARY KEY,
"full_name" character varying(256)
);
DO $$ BEGIN
ALTER TABLE auth_otp ADD CONSTRAINT auth_otp_user_id_fkey FOREIGN KEY ("user_id") REFERENCES users(id);
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
CREATE INDEX IF NOT EXISTS users_full_name_index ON users (full_name);Installation & configuration
npm install -D wizzle-cliRunning with CLI options:
// package.json
{
"scripts": {
"generate": "wizzle-cli generate --out migrations-folder --schema src/db/schema.ts"
}
}npm run generateRuntime Migrations
Wizzle provides runtime migrators that work with snapshot chains instead of journal files. This makes wizzle fully independent from drizzle-orm's migration system.
Migration Structure
Wizzle uses a folder-based migration structure where each migration is self-contained:
migrations/
├── 1700000000000_initial_setup/
│ ├── up.sql
│ └── snapshot.json
└── 1700000001000_add_users/
├── up.sql
└── snapshot.jsonEach migration folder contains:
up.sql- The SQL statements to applysnapshot.json- Complete schema snapshot with metadata andprevIdchain reference
How it works
Unlike drizzle-orm's runtime migrator which relies on _journal.json, wizzle's runtime migrator:
- Uses snapshot chains to determine migration order by following
prevIdreferences in each snapshot - Each migration is self-contained in its own folder
- Reads migration metadata directly from snapshot files
- Provides detailed logging for each migration being applied
- Maintains the same external API as drizzle-orm for easy migration
Installation
npm install wizzle-cli drizzle-ormUsage
Import the migrator for your database driver and call it with your drizzle database instance:
PostgreSQL (node-postgres)
import { drizzle } from 'drizzle-orm/node-postgres';
import { migrate } from 'wizzle-cli/migrator/node-postgres';
import { Pool } from 'pg';
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
const db = drizzle(pool);
// Run migrations
await migrate(db, { migrationsFolder: './drizzle' });PostgreSQL (postgres.js)
import { drizzle } from 'drizzle-orm/postgres-js';
import { migrate } from 'wizzle-cli/migrator/postgres-js';
import postgres from 'postgres';
const sql = postgres(process.env.DATABASE_URL, { max: 1 });
const db = drizzle(sql);
await migrate(db, { migrationsFolder: './drizzle' });MySQL (mysql2)
import { drizzle } from 'drizzle-orm/mysql2';
import { migrate } from 'wizzle-cli/migrator/mysql2';
import mysql from 'mysql2/promise';
const connection = await mysql.createConnection(process.env.DATABASE_URL);
const db = drizzle(connection);
await migrate(db, { migrationsFolder: './drizzle' });SQLite (better-sqlite3)
import { drizzle } from 'drizzle-orm/better-sqlite3';
import { migrate } from 'wizzle-cli/migrator/better-sqlite3';
import Database from 'better-sqlite3';
const sqlite = new Database('sqlite.db');
const db = drizzle(sqlite);
await migrate(db, { migrationsFolder: './drizzle' });SQLite (libsql)
import { drizzle } from 'drizzle-orm/libsql';
import { migrate } from 'wizzle-cli/migrator/libsql';
import { createClient } from '@libsql/client';
const client = createClient({ url: 'file:local.db' });
const db = drizzle(client);
await migrate(db, { migrationsFolder: './drizzle' });Supported Drivers
Wizzle supports all major database drivers:
PostgreSQL
wizzle-cli/migrator/node-postgres- node-postgres (pg)wizzle-cli/migrator/postgres-js- postgres.jswizzle-cli/migrator/neon-serverless- Neon serverlesswizzle-cli/migrator/neon-http- Neon HTTPwizzle-cli/migrator/pglite- PGlitewizzle-cli/migrator/pg-proxy- PostgreSQL proxywizzle-cli/migrator/vercel-postgres- Vercel Postgreswizzle-cli/migrator/xata-http- Xata HTTPwizzle-cli/migrator/aws-data-api-pg- AWS Data API for PostgreSQL
MySQL
wizzle-cli/migrator/mysql2- mysql2wizzle-cli/migrator/mysql-proxy- MySQL proxywizzle-cli/migrator/planetscale-serverless- PlanetScale serverlesswizzle-cli/migrator/tidb-serverless- TiDB serverless
SQLite
wizzle-cli/migrator/better-sqlite3- better-sqlite3wizzle-cli/migrator/libsql- libSQLwizzle-cli/migrator/bun-sqlite- Bun SQLitewizzle-cli/migrator/bun-sql- Bun SQLwizzle-cli/migrator/sqlite-proxy- SQLite proxywizzle-cli/migrator/sql-js- sql.jswizzle-cli/migrator/d1- Cloudflare D1wizzle-cli/migrator/durable-sqlite- Durable SQLitewizzle-cli/migrator/expo-sqlite- Expo SQLitewizzle-cli/migrator/op-sqlite- OP SQLite
SingleStore
wizzle-cli/migrator/singlestore- SingleStorewizzle-cli/migrator/singlestore-proxy- SingleStore proxy
Migration Configuration
The migrate function accepts a configuration object:
interface MigrationConfig {
migrationsFolder: string; // Path to migrations folder (required)
migrationsTable?: string; // Custom migrations table name (default: "__wizzle_migrations")
migrationsSchema?: string; // Schema for migrations table (PostgreSQL only, default: "wizzle")
}Example with custom configuration:
await migrate(db, {
migrationsFolder: './drizzle',
migrationsTable: 'my_migrations',
migrationsSchema: 'public', // PostgreSQL only
});Migration Logging
Wizzle provides detailed logging during migration:
Applying 3 migration(s)...
[1/3] 1234567890_bold_thor
[2/3] 1234567891_brave_loki
[3/3] 1234567892_wise_odin
✓ 3 migration(s) applied successfully in 145msMigrating from drizzle-orm migrators
If you're currently using drizzle-orm's runtime migrators, switching to wizzle is straightforward:
Before (drizzle-orm):
import { migrate } from 'drizzle-orm/node-postgres/migrator';After (wizzle):
import { migrate } from 'wizzle-cli/migrator/node-postgres';The API remains identical - only the import path changes.
Note on Migration Structure: Wizzle uses a different folder structure than drizzle-kit:
- drizzle-kit: Flat structure with
meta/folder containing snapshots - wizzle: Folder per migration containing
up.sqlandsnapshot.json
If migrating from drizzle-kit, you'll need to manually restructure your migrations to the new folder-based format.
