gleager
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:
exec(sql, args)— run SQL statements, optionally with parametersquery(sql, args, decoder)— run a parameterised query and decode the result rows
See gleager/types for the full type definition, or the sqlight example above
for a working adapter.
Development
gleam test # Run the test suite