//// Types used by the Gleager migration engine. //// //// The central type is `Driver(e)`, which abstracts over database backends so //// that gleager can work with any Gleam SQL library. The `e` type parameter //// represents the database library's native error type, which gets mapped //// to `MigrationError` by gleager's internal functions. import gleam/dynamic/decode /// Errors that can occur during migration operations. /// pub type MigrationError { /// The migration directory was not found at the given path. FileNotFound(at: String) /// A migration file exists but could not be read. UnableToRead(at: String) /// A migration filename does not have a valid version prefix. InvalidMigrationVersion(at: String) /// The `schema_migrations` tracking table could not be created. SchemaTableFailed /// The query to list applied migrations failed. SelectMigrationsFailed /// Recording a migration in the tracking table failed. InsertMigrationFailed(for: String) /// Removing a migration from the tracking table failed. DeleteMigrationFailed(for: String) /// One of the SQL statements in a migration could not be executed. MigrationStatementFailed(for: String) /// An `up` migration failed to apply. UpMigrationFailed(for: String) /// A `down` migration failed to apply. DownMigrationFailed(for: String) } /// A parsed migration consisting of its version and the up and down SQL. /// pub type Migration { Migration(version: String, up: String, down: String) } /// Operations that can be performed on migrations. /// pub type MigrationOp { /// Apply pending migrations. Up /// Roll back applied migrations. Down /// Generate a new migration file with the given name. Generate(name: String) } /// A row from the `schema_migrations` tracking table. /// pub type MigrationRow { MigrationRow(version: String) } /// A database driver for executing SQL and running parameterised queries. /// /// The `e` type parameter is the database library's native error type. /// gleager maps these errors to `MigrationError` internally, so the /// driver does not need to perform any error conversion. /// /// ## Example — sqlight driver /// /// ```gleam /// 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) /// }, /// ) /// ``` /// pub type Driver(e) { Driver( /// The filesystem path to the directory containing migration files. migration_dir: String, /// Execute one or more SQL statements, optionally with parameters. /// When called with an empty args list, run the SQL directly. /// When called with parameters, bind them to the `?` placeholders. exec: fn(String, List(String)) -> Result(Nil, e), /// Run a parameterised query and decode the result rows. query: fn(String, List(String), decode.Decoder(MigrationRow)) -> Result(List(MigrationRow), e), ) }