# fiction
[](https://hex.pm/packages/fiction)
[](https://hexdocs.pm/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](https://crates.io/crates/figment)
## Usage
```sh
gleam add fiction@2
```
```gleam
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
- [fiction_toml](https://hex.pm/packages/fiction_toml) - A simple TOML provider utilizing [simplifile](https://hex.pm/packages/simplifile) and [tom](https://hex.pm/packages/tom)
- [fiction_env](https://hex.pm/packages/fiction_env) - An environment provider utilizing [envoy](https://hex.pm/packages/envoy)
## Development
```sh
gleam test # Run the tests
```