gleager

Package Version Hex 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
Search Document