glimr/db/driver
Database Connection Drivers
Database connections are configured in config/database.toml with environment variable interpolation for secrets. This module parses those configs into typed Connection values that the pool startup code consumes — so a missing DATABASE_URL blows up at boot with a clear message rather than on the first query ten minutes later.
Types
Config fields are wrapped in Result because they come from environment variables that might not be set yet. Deferring the error to pool startup (via to_config) means the config module doesn’t panic during parsing, and the error message can name the exact missing env var. Postgres supports both a single URL and individual host/port/db params because some hosting providers give you one format, some the other.
pub type Connection {
PostgresUriConnection(
name: String,
url: Result(String, String),
pool_size: Result(Int, String),
)
PostgresConnection(
name: String,
host: Result(String, String),
port: Result(Int, String),
database: Result(String, String),
username: Result(String, String),
password: Result(String, String),
pool_size: Result(Int, String),
)
SqliteConnection(
name: String,
database: Result(String, String),
pool_size: Result(Int, String),
)
}
Constructors
-
PostgresUriConnection( name: String, url: Result(String, String), pool_size: Result(Int, String), ) -
PostgresConnection( name: String, host: Result(String, String), port: Result(Int, String), database: Result(String, String), username: Result(String, String), password: Result(String, String), pool_size: Result(Int, String), ) -
SqliteConnection( name: String, database: Result(String, String), pool_size: Result(Int, String), )
The migration generator needs to know which SQL dialect to emit (SERIAL vs INTEGER PRIMARY KEY AUTOINCREMENT, BOOLEAN vs INTEGER, etc.) without caring about connection details. This simple enum is enough to branch on.
pub type DriverType {
Postgres
Sqlite
}
Constructors
-
Postgres -
Sqlite
Values
pub fn clear_cache() -> Nil
Tests that exercise different database configurations need to start fresh between runs. Without clearing, the persistent_term cache would serve stale config from the previous test case.
pub fn connection_name(connection: Connection) -> String
Every connection variant has a name field but in a different position. This saves callers from writing the same three-branch pattern match every time they just need the name — which comes up constantly in logging and config lookups.
pub fn connection_type(connection: Connection) -> DriverType
The migration generator and SQL emitter need to know which dialect to use without caring about URLs or credentials. Both Postgres variants map to the same DriverType since they produce the same SQL.
pub fn find_by_name(
name: String,
connections: List(Connection),
) -> Connection
When a developer passes --connection main to a CLI command
and that connection doesn’t exist, the worst thing we could
do is silently continue. Panicking with the exact name and
pointing at config/database.toml tells them what to fix.
pub fn get_connection_safe(
connections: List(Connection),
name: String,
) -> Result(Connection, Nil)
Some callers need to check whether a connection exists without crashing — like the database watcher checking if a connection name from a file path is valid. Returns Error instead of panicking so those callers can handle the miss gracefully.
pub fn load_connections() -> List(Connection)
Connections are loaded once and cached in persistent_term so every subsequent call is a fast lookup. The first call reads config/database.toml, parses each [connections.*] entry, and caches the result. Returns an empty list if no config exists — which is fine for projects that don’t use a database.
pub fn to_config(connection: Connection) -> db.Config
This is where env var errors finally surface. The Connection holds Results from config parsing; this function unwraps them all at once. If DATABASE_URL isn’t set, you get a panic naming the exact connection and parameter rather than a cryptic driver error later.
pub fn to_pascal_case(name: String) -> String
Connection names like “main_db” need to become “MainDb” when generating Gleam type names and module references. The code generator calls this to produce valid PascalCase identifiers from user-chosen connection names.
pub fn validate(connection: Connection) -> List(String)
The ./glimr db:check command calls this to report all
missing env vars at once instead of crashing on the first
one. Returning a list lets the CLI show “missing: host,
username, password” in a single message so you can fix
everything in one pass.
pub fn with_pool_size(
connection: Connection,
size: Int,
) -> Connection
Console commands like ./glimr migrate only need one
database connection, not the pool of 10 the web server uses.
Overriding the pool size to 1 avoids wasting connections and
speeds up command startup.