Filesystem Storage
Store migrations as files on the local filesystem (default storage driver)
Quick Start
import { createMigrationClient } from "viborm/migrations";
import { createFsStorageDriver } from "viborm/migrations/storage/fs";
const storage = createFsStorageDriver("./migrations");
const migrations = createMigrationClient(client, {
storageDriver: storage,
});
Configuration
const storage = createFsStorageDriver(baseDir);
| Parameter | Type | Description |
|---|---|---|
baseDir |
string |
Base directory for migration files |
The baseDir should be an absolute path or relative to the current working directory.
Directory Structure
migrations/ # baseDir
├── 0000_initial.sql # First migration
├── 0001_add-users.sql # Second migration
├── 0002_add-posts.sql # Third migration
└── meta/ # Metadata directory
├── _journal.json # Migration index
├── _snapshot.json # Current schema snapshot
├── _down/ # Down migrations
│ ├── 0000_initial.sql
│ ├── 0001_add-users.sql
│ └── 0002_add-posts.sql
├── _backup/ # Backups before modification
└── _archive/ # Archived (squashed) migrations
File Formats
Migration Files
SQL files with statements separated by semicolons:
-- 0001_add-users.sql
CREATE TABLE "users" (
"id" serial PRIMARY KEY,
"email" text NOT NULL UNIQUE,
"name" text,
"created_at" timestamp DEFAULT NOW()
);
CREATE INDEX "users_email_idx" ON "users" ("email");
Journal File
JSON file tracking all migrations:
{
"version": "1",
"dialect": "postgresql",
"entries": [
{
"idx": 0,
"version": "20240115120000",
"name": "initial",
"when": 1705320000000,
"checksum": "sha256:abc123..."
},
{
"idx": 1,
"version": "20240116140000",
"name": "add-users",
"when": 1705413600000,
"checksum": "sha256:def456..."
}
]
}
Snapshot File
JSON representation of the current schema:
{
"tables": [
{
"name": "users",
"columns": [
{ "name": "id", "type": "serial", "nullable": false },
{ "name": "email", "type": "text", "nullable": false }
],
"primaryKey": { "columns": ["id"] },
"indexes": [],
"foreignKeys": [],
"uniqueConstraints": []
}
],
"enums": []
}
Version Control
Migration files are designed to be committed to git:
# .gitignore - don't ignore migrations!
# migrations/ # DO NOT ADD THIS
# Commit migrations
git add migrations/
git commit -m "Add user table migration"
For the generate/apply/status workflow, see Migrate.
Error Handling
The filesystem driver handles common scenarios:
- Missing directory: Creates directories automatically on
put() - Missing file: Returns
nullonget(), no-op ondelete() - Permission errors: Throws standard Node.js errors
try {
await migrations.apply();
} catch (error) {
if (error.code === "EACCES") {
console.error("Permission denied - check file permissions");
}
}