fiction

Package Version Hex Docs

Jonathan Frakes telling you it’s fiction

A library to help combine app configuration from multiple sources into a single record. This core is pure gleam, though most useful providers will have target-specific code.

Heavily inspired by Figment

Usage

gleam add fiction@2
import gleam/dynamic/decode
import fiction
// this is provided by the separate package `fiction_toml`
import fiction/providers/toml
// this is provided by the separate package `fiction_env`
import fiction/providers/env

type Config {
  Config(
    port: Int,
    host: String
  )
}

fn config_decoder() {
  // The decoder can provide defaults if you want
  use port <- decode.optional_field("port", 5432, decode.int)
  // Or handle more complicated keys
  use host <- decode.one_of(decode.at(["host"], decode.string), [decode.at(["tools", "app", "dev", "host"], decode.string)])

  decode.success(Config(port:, host:))
}

pub fn main() -> Nil {
  let assert Ok(config) =
    // providers are layered onto a Builder with each layer being combined with all previous layers
    // the function used (`join`, `merge`, `concat_join`, or `concat_merge`) determines the strategy use when keys conflict
    // this can be used to give sources precendence over others
    fiction.new()
    // for example, the base values could come from `app.toml`
    |> fiction.join(toml.file("./priv/app.toml"))
    // next we can layer some common environment variables on top using `merge` to overwrite any conflicting keys
    |> fiction.merge(env.exact(["PORT", "HOST"]))
    // then we can layer relevant environment variables, again using `merge`
    // in this example, if `app.toml` had a top-level `port` key, then defining `APP_PORT` would overwrite that value
    |> fiction.merge(env.prefixed("APP_"))
    // we can include `gleam.toml` too, using `concat_join` to preserve the values of existing keys, but concatenating any list values together
    |> fiction.concat_join(toml.file("./gleam.toml"))
    // providers are just plain functions, so anything that returns a Result(List(#(String, fiction.Value)), String) will work as well
    // in this case using `join` will provide a default value for the `host` key without overwriting that value if it's been set already
    |> fiction.join(fn() { Ok([#("host", fiction.String("localhost"))])})
    // finally we extract the values we want into a single record with a standard gleam decoder that can be as simple or complicated as you need
    |> fiction.extract(with: config_decoder())
}

Further documentation can be found at https://hexdocs.pm/fiction.

Providers

Development

gleam test  # Run the tests
Search Document