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 env
However, 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.fromEnv
function 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