Bunch.Config (Bunch v1.6.3)

View Source

A bunch of helpers for parsing and validating configurations.

Summary

Functions

Parses config according to fields_specs.

Functions

parse(config, fields_specs)

@spec parse(
  config :: Keyword.t(v),
  [field | {field, field_specs | (parsed_config -> field_specs)}]
) :: Bunch.Type.try_t(parsed_config, reason)
when parsed_config: %{required(atom()) => v},
     field: atom(),
     v: any(),
     field_specs:
       [
         validate:
           (v | any() -> Bunch.Type.try_t() | boolean())
           | (v | any(), parsed_config -> Bunch.Type.try_t() | boolean()),
         in: Enumerable.t(),
         default: v,
         require?: boolean(),
         require_if: (parsed_config -> boolean())
       ]
       | nil,
     reason:
       {:config_not_keyword, any()}
       | {:config_duplicates, [atom()]}
       | {:config_invalid_keys, [atom()]}
       | {:config_field,
          {:key_not_found, atom()}
          | {:invalid_value, key: atom(), value: any()}
          | {:invalid_value,
             key: atom(),
             value: any(),
             reason: {:not_in, Enumerable.t()} | any()}}

Parses config according to fields_specs.

fields_specs consist of constraints on each field. Supported constraints are:

  • validate - function determining if field's value is correct
  • in - enumerable containing all valid values
  • default - value returned if a field is not found in config
  • require? - determines whether a field is required, defaults to false when default is set and true when default is not set
  • require_if - deprecated, pass function returning constraints instead

Instead of a list of constraints, a function accepting fields parsed so far and returning the constraints can be passed. If the function returns nil, field is considered non existent, as if it wasn't passed at all.

This function can return error with the following reasons:

  • {:config_not_keyword, config} - provided config is not a keyword list.
  • {:config_duplicates, duplicates} - keys in duplicates have appeared more than once in passed config.
  • {:config_invalid_keys, invalid_keys} - keys in invalid_keys weren't expected.
  • {:config_field, config_field_reason} - there is an error associated with a specific config field. There can be the following reasons:
    • {:key_not_found, key} - key was expected, but wasn't present in config.
    • {:invalid_value, key: key, value: value} - Key key has been provided an invalid value value without known reason. This can occur when a function passed to :validate constraint returns false.
    • {:invalid_value, key: key, value: value, reason: {:not_in, in_enum}} - Key key has been provided value value that is outside of enumerable passed to :in constraint.
    • {:invalid_value, key: key, value: value, reason: reason} - Key key has been provided an invalid value value with known reason reason. This can occur when a function passed as :validate constrain returns {:error, reason}.

Examples

iex> Bunch.Config.parse([a: 1, b: 2], a: [validate: & &1 > 0], b: [in: -2..2])
{:ok, %{a: 1, b: 2}}
iex> Bunch.Config.parse([a: 1, b: 4], a: [validate: & &1 > 0], b: [in: -2..2])
{:error, {:config_field, {:invalid_value, [key: :b, value: 4, reason: {:not_in, -2..2}]}}}
iex> Bunch.Config.parse(
...> [a: 1, b: 2],
...> a: [validate: & &1 > 0],
...> b: [in: -2..2],
...> c: [default: 5]
...> )
{:ok, %{a: 1, b: 2, c: 5}}
iex> Bunch.Config.parse(
...> [a: 1, b: 2],
...> a: [validate: & &1 > 0],
...> b: [in: -2..2],
...> c: [require?: false]
...> )
{:ok, %{a: 1, b: 2}}
iex> Bunch.Config.parse(
...> [a: 1, b: 1],
...> a: [validate: & &1 > 0],
...> b: [in: -2..2],
...> c: &(if &1.a == &1.b, do: [in: 0..1])
...> )
{:error, {:config_field, {:key_not_found, :c}}}