gleager

Package VersionHex Docs

A database migration tool for Gleam. Works with any SQL driver that implements the Driver type — sqlight, pturso, or your own.

gleam add gleager

Quick start

Create a migrations directory with versioned SQL files:

-- migrations/001_create_users.sql
-- migrate:up
CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT NOT NULL, email TEXT);
-- migrate:down
DROP TABLE users;
-- migrations/002_add_posts.sql
-- migrate:up
CREATE TABLE posts (id INTEGER PRIMARY KEY, user_id INTEGER NOT NULL, title TEXT, body TEXT);
CREATE INDEX idx_posts_user_id ON posts(user_id);
-- migrate:down
DROP INDEX idx_posts_user_id;
DROP TABLE posts;

Then apply them with sqlight:

import gleager
import gleager/types.{Driver}
import gleam/dynamic/decode
import gleam/list
import sqlight
pub fn main() {
use conn <- sqlight.with_connection("dev.db")
let driver = Driver(
migration_dir: "migrations",
exec: fn(sql, args) {
case args {
[] -> sqlight.exec(sql, on: conn)
_ -> {
let values = list.map(args, sqlight.text)
case sqlight.query(sql, on: conn, with: values, expecting: decode.int) {
Ok(_) -> Ok(Nil)
Error(e) -> Error(e)
}
}
}
},
query: fn(sql, args, decoder) {
let values = list.map(args, sqlight.text)
sqlight.query(sql, on: conn, with: values, expecting: decoder)
},
)
// Apply all pending migrations
let assert Ok(Nil) = gleager.up(driver, steps: None)
// Or apply only the next 2
let assert Ok(Nil) = gleager.up(driver, steps: Some(2))
// Roll back all applied migrations
let assert Ok(Nil) = gleager.down(driver, steps: None)
// Or roll back only the last one
let assert Ok(Nil) = gleager.down(driver, steps: Some(1))
}

Migration file format

Migration files live in a single directory. The version is extracted from the filename prefix:

migrations/
001_create_users.sql
002_add_posts.sql
003_add_settings.sql

Each file uses annotated sections:

-- migrate:up
<SQL to apply>
-- migrate:down
<SQL to roll back>

Migrations are applied in version order (up) and rolled back in reverse (down). Each migration runs inside a transaction: either all statements succeed and the migration is recorded in the schema_migrations tracking table, or any failure rolls back the entire migration.

Driver

gleager is database-agnostic. The Driver(e) type defines two callbacks:

See gleager/types for the full type definition, or the sqlight example above for a working adapter.

Development

gleam test # Run the test suite