A powerful, database-agnostic migration CLI tool with multi-database support and type-safe code generation
npm install graft-ormA powerful, database-agnostic migration CLI tool built in Go with multi-database support, visual database editor (Graft Studio), and type-safe code generation for JavaScript/TypeScript.
- šØ Graft Studio: Visual database editor with React-based schema visualization
- šļø Multi-Database Support: PostgreSQL, MySQL, SQLite
- š Migration Management: Create, apply, and track migrations
- š Safe Migration System: Transaction-based execution with automatic rollback
- š¤ Smart Export System: Multiple formats (JSON, CSV, SQLite)
- š§ Type-Safe Code Generation: Generate fully typed JavaScript/TypeScript code
- ā” Blazing Fast: 2.5x faster than Drizzle, 10x faster than Prisma
- š» Raw SQL Execution: Execute SQL files or inline queries
- šÆ Prisma-like Commands: Familiar CLI interface
- šØ Enum Support: Full PostgreSQL ENUM support
| Operation | Graft | Drizzle | Prisma |
|-----------|-------|---------|--------|
| Insert 1000 Users | 158ms | 224ms | 230ms |
| Complex Query x500 | 4071ms | 12500ms | 56322ms |
| Mixed Workload x1000 | 186ms | 1174ms | 10863ms |
| TOTAL | 6947ms | 17149ms | 71551ms |
``bash`
npm install -g graft-orm
Bun blocks postinstall scripts by default. After installation, run:
`bash`
bun pm trust graft-orm
Or add to your package.json:`json`
{
"trustedDependencies": ["graft-orm"]
}
`bash`
graft init --postgresql # or --mysql, --sqlite
This creates:
``
your-project/
āāā graft.config.json
āāā .env
āāā db/
āāā schema/
ā āāā schema.sql
āāā queries/
āāā users.sql
`bash`.env file
DATABASE_URL=postgresql://user:password@localhost:5432/mydb
db/schema/schema.sql
`sql`
CREATE TABLE users (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
email VARCHAR(255) UNIQUE NOT NULL,
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
);
db/queries/users.sql
`sql
-- name: GetUser :one
SELECT id, name, email, created_at, updated_at FROM users
WHERE id = $1 LIMIT 1;
-- name: CreateUser :one
INSERT INTO users (name, email)
VALUES ($1, $2)
RETURNING id, name, email, created_at, updated_at;
-- name: ListUsers :many
SELECT id, name, email, created_at, updated_at FROM users
ORDER BY created_at DESC;
-- name: UpdateUser :one
UPDATE users
SET name = $2, email = $3, updated_at = NOW()
WHERE id = $1
RETURNING id, name, email, created_at, updated_at;
-- name: DeleteUser :exec
DELETE FROM users WHERE id = $1;
`
`bash`
graft migrate "create users table"
`bash`
graft apply
`bash`
graft gen
Generated Types (graft_gen/index.d.ts)
`typescript
// Code generated by Graft. DO NOT EDIT.
export interface Users {
id: number | null;
name: string;
email: string;
created_at: Date;
updated_at: Date;
}
export interface GetUserResult {
id: number | null;
name: string;
email: string;
created_at: Date;
updated_at: Date;
}
export class Queries {
constructor(db: any);
getUser(id: number): Promise
createUser(name: string, email: string): Promise
listUsers(): Promise
updateUser(id: number, name: string, email: string): Promise
deleteUser(id: number): Promise
}
export function New(db: any): Queries;
`
index.ts
`typescript
import { Pool } from 'pg';
import { New } from './graft_gen/database';
const DATABASE_URL = process.env.DATABASE_URL || 'postgresql://postgres:postgres@localhost:5432/mydb';
async function main() {
const pool = new Pool({
connectionString: DATABASE_URL,
});
const db = New(pool);
// Create user - fully type-safe!
const newUser = await db.createUser('Alice', 'alice@example.com');
console.log('New user:', newUser);
// Get user by ID
const user = await db.getUser(newUser.id);
console.log('Found user:', user);
// List all users
const users = await db.listUsers();
console.log('All users:', users);
// Update user
const updated = await db.updateUser(newUser.id, 'Alice Smith', 'alice.smith@example.com');
console.log('Updated user:', updated);
await pool.end();
}
main().catch((err) => {
console.error('Error:', err);
process.exit(1);
});
`
`bashLaunch Graft Studio (web-based database editor)
graft studio
Studio Features:
- š Data Browser: View and edit table data with inline editing
- š» SQL Editor: Execute queries with CodeMirror syntax highlighting
- šØ Schema Visualization: Interactive database diagram with React + ReactFlow
- š¤ CSV Export: Export query results to CSV
- š Search & Filter: Search across all tables
- ā” Real-time Updates: See changes immediately
$3
`bash
Initialize new project
graft init --postgresql
graft init --mysql
graft init --sqlite
`$3
`bash
Create new migration
graft migrate "migration name"Create empty migration
graft migrate "custom migration" --emptyApply all pending migrations
graft applyApply with force (skip confirmations)
graft apply --forceCheck migration status
graft status
`$3
`bash
Generate type-safe code
graft gen
`$3
`bash
Pull schema from existing database
graft pullPull with backup
graft pull --backupPull to custom file
graft pull --output custom-schema.sql
`$3
`bash
Export as JSON (default)
graft export
graft export --jsonExport as CSV
graft export --csvExport as SQLite
graft export --sqlite
`$3
`bash
Reset database (destructive!)
graft resetReset with force
graft reset --forceExecute raw SQL file
graft raw script.sql
graft raw migrations/seed.sqlExecute inline SQL query
graft raw -q "SELECT * FROM users WHERE active = true"
graft raw "SELECT COUNT(*) FROM orders"Force file mode
graft raw --file queries/complex.sql
`$3
`bash
Launch Graft Studio
graft studioShow version
graft --version
graft -vShow help
graft --help
graft --help
`āļø Configuration
graft.config.json
`json
{
"version": "2",
"schema_path": "db/schema/schema.sql",
"queries": "db/queries/",
"migrations_path": "db/migrations",
"export_path": "db/export",
"database": {
"provider": "postgresql",
"url_env": "DATABASE_URL"
},
"gen": {
"js": {
"enabled": true,
"out": "graft_gen"
}
}
}
`šØ PostgreSQL ENUM Support
Schema with ENUMs
`sql
CREATE TYPE user_role AS ENUM ('admin', 'user', 'guest');CREATE TABLE users (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
role user_role NOT NULL DEFAULT 'user'
);
`Query with ENUM
`sql
-- name: GetUsersByRole :many
SELECT id, name, role FROM users
WHERE role = $1;
`Generated TypeScript
`typescript
export type UserRole = 'admin' | 'user' | 'guest';export interface Users {
id: number | null;
name: string;
role: UserRole;
}
`š Safe Migrations
Every migration runs in a transaction with automatic rollback on failure:
`bash
$ graft apply
š¦ Applying 2 migration(s)...
[1/2] 20251103_create_users
ā
Applied
[2/2] 20251103_add_email_index
ā
Applied
ā
All migrations applied successfully
`If a migration fails:
`bash
ā Failed at migration: 20251103_bad_migration
Error: syntax error at or near "INVALID"
Transaction rolled back. Fix the error and run 'graft apply' again.
`š”ļø Conflict Detection
Graft automatically detects schema conflicts:
`bash
ā ļø Migration conflicts detected:
- Table 'users' already exists
- Column 'email' conflicts with existing columnReset database to resolve conflicts? (y/n): y
Create export before applying? (y/n): y
š¦ Creating export...
ā
Export created successfully
š Resetting database and applying all migrations...
`š¤ Export Formats
$3
`bash
graft export --json
`
`json
{
"timestamp": "2025-11-03 16:30:00",
"version": "1.0",
"tables": {
"users": [
{"id": 1, "name": "Alice", "email": "alice@example.com"}
]
}
}
`$3
`bash
graft export --csv
`
Creates directory with individual CSV files per table.$3
`bash
graft export --sqlite
`
Creates portable .db file.šØ Graft Studio
Launch the visual database editor:
`bash
graft studio
`Open http://localhost:5555 (or your custom port)
Features:
$3
- View all tables in sidebar
- Click any table to view/edit data
- Double-click cells for inline editing
- Add/delete rows with intuitive modals
- Pagination (50 rows per page)
- Search across tables
- Foreign key hints$3
- Execute custom SQL queries
- CodeMirror editor with syntax highlighting
- Press Ctrl+Enter to run queries
- Export results to CSV
- Resizable split-pane interface
- Query history$3
- Interactive database diagram
- React + ReactFlow rendering
- Automatic layout with Dagre algorithm
- Drag and drop tables
- Zoom and pan controls
- Foreign key relationship arrows
- MiniMap for navigationTech Stack:
- Backend: Go Fiber v2.52.9
- Frontend: React 18.2.0, ReactFlow 12.8.4, CodeMirror 5.65.2
- All assets embedded in single binary
š» Raw SQL Execution
Execute SQL files or inline queries:
`bash
Execute SQL file
graft raw script.sqlExecute inline query
graft raw -q "SELECT * FROM users LIMIT 10"Auto-detection (file if exists, otherwise query)
graft raw "SELECT COUNT(*) FROM orders"
`Features:
- ā
Beautiful table output for SELECT queries
- ā
Multi-statement execution
- ā
Transaction support
- ā
Auto-detection of file vs query
- ā
Formatted error messages
Example Output:
`bash
$ graft raw -q "SELECT id, name, email FROM users LIMIT 3"šÆ Database: postgresql
ā” Executing query...
ā
Query executed successfully
š 3 row(s) returned
āāāāāā¬āāāāāāāāāāāāā¬āāāāāāāāāāāāāāāāāāāāāā
ā id ā name ā email ā
āāāāāā¼āāāāāāāāāāāāā¼āāāāāāāāāāāāāāāāāāāāāā¤
ā 1 ā Alice ā alice@example.com ā
ā 2 ā Bob ā bob@example.com ā
ā 3 ā Charlie ā charlie@example.com ā
āāāāāā“āāāāāāāāāāāāā“āāāāāāāāāāāāāāāāāāāāāā
`š§ Programmatic API
`javascript
const graft = require('graft-orm');// Execute commands
graft.exec('status');
graft.exec('migrate "add users"');
graft.exec('apply');
graft.exec('studio'); // Launch Studio
// Get binary path
const binaryPath = graft.getBinaryPath();
`š Examples
Check out complete examples:
- TypeScript Example
- Go Example
š Troubleshooting
$3
`bash
bun pm trust graft-orm
`$3
`bash
npm install -g graft-orm --force
`$3
Check your
DATABASE_URL in .env file.$3
Make sure port 5555 is not in use, or specify a different port:
`bash
graft studio --port 3000
``- Full Documentation
- How It Works
- Technology Stack
- Contributing
- Visual Database Editor: Manage your database visually with Graft Studio
- Raw SQL Support: Execute SQL files or queries directly from CLI
- Type-Safe: Full TypeScript support with generated types
- Fast: 2.5x-10x faster than popular ORMs
- Multi-DB: PostgreSQL, MySQL, and SQLite support
- Zero Config: Works out of the box with sensible defaults
MIT License - see LICENSE
---