The purescript-node-process environment API
provides environment variables in the form of an
Object String
(a string map), but it is left up to us to validate and to parse the values into some configuration model that can be used
safely throughout the rest of the program.
One of the more popular solutions would be something like this applicative-style lookup/validation/parsing into a record:
type Config =
{ greeting :: String
, count :: Int
}
parseConfig :: Object String -> Either String Config
parseConfig env =
(\greeting count -> { greeting, count })
<$> value "GREETING"
<*> ( value "COUNT"
>>= Int.fromString
>>> Either.note "Invalid COUNT"
)
where
value name =
note ("Missing variable " <> name) $ lookup name envHowever, this is a bit unsatisfying because the explicit lookups, parsing logic, and error handling are somewhat
verbose and might start to look like a lot of boilerplate as the Config model is extended with additional fields.
The value-level logic creates additional touchpoints when fields are added or removed, or their types change.
Instead, this library uses a type-directed approach, which starts with renaming the Config fields according to the
environment variable names from which their values are sourced:
type Config =
{ "GREETING" :: String
, "COUNT" :: Int
}The fromEnv function now has enough information to convert the environment Object String to a typed record with
no need for explicit lookups, parsing, or error handling:
parseConfig :: Object String -> Either String Config
parseConfig = Either.lmap printEnvError <<< TypedEnv.fromEnv (Proxy :: _ Config)Note An additional benefit not demonstrated here is that the
TypedEnv.fromEnvfunction accumulates a list of errors, whereas the former example can only present one error at a time.
To run one of the examples, clone the repository and run the following command, replacing <example-name> with the name of the example.
spago -x example.dhall run -m Example.<example-name>via spago:
spago install typedenv