{"id":13682395,"url":"https://github.com/nsaunders/purescript-typedenv","last_synced_at":"2025-03-23T18:31:30.295Z","repository":{"id":58222856,"uuid":"205947776","full_name":"nsaunders/purescript-typedenv","owner":"nsaunders","description":"Type-directed environment parsing","archived":false,"fork":false,"pushed_at":"2023-11-27T12:55:48.000Z","size":107,"stargazers_count":20,"open_issues_count":0,"forks_count":4,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-18T22:35:51.137Z","etag":null,"topics":["configuration","devops","node","purescript"],"latest_commit_sha":null,"homepage":"","language":"PureScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nsaunders.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2019-09-02T22:50:34.000Z","updated_at":"2023-06-14T00:13:56.000Z","dependencies_parsed_at":"2023-09-25T02:34:15.126Z","dependency_job_id":"3be01c7d-6958-4b9e-a3cf-566614ceb8cf","html_url":"https://github.com/nsaunders/purescript-typedenv","commit_stats":{"total_commits":79,"total_committers":4,"mean_commits":19.75,"dds":"0.11392405063291144","last_synced_commit":"3328a46efda08de171f5f74402392618cdb9036e"},"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nsaunders%2Fpurescript-typedenv","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nsaunders%2Fpurescript-typedenv/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nsaunders%2Fpurescript-typedenv/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nsaunders%2Fpurescript-typedenv/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nsaunders","download_url":"https://codeload.github.com/nsaunders/purescript-typedenv/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245149239,"owners_count":20568858,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["configuration","devops","node","purescript"],"created_at":"2024-08-02T13:01:45.447Z","updated_at":"2025-03-23T18:31:25.284Z","avatar_url":"https://github.com/nsaunders.png","language":"PureScript","funding_links":[],"categories":["PureScript"],"sub_categories":[],"readme":"# purescript-typedenv [![Build](https://github.com/nsaunders/purescript-typedenv/workflows/CI/badge.svg)](https://github.com/nsaunders/purescript-typedenv/actions/workflows/ci.yml) [![Latest release](http://img.shields.io/github/release/nsaunders/purescript-typedenv.svg)](https://github.com/nsaunders/purescript-typedenv/releases) [![PureScript registry](https://img.shields.io/badge/dynamic/json?color=informational\u0026label=registry\u0026query=%24.typedenv.version\u0026url=https%3A%2F%2Fraw.githubusercontent.com%2Fpurescript%2Fpackage-sets%2Fmaster%2Fpackages.json)](https://github.com/purescript/registry) [![purescript-typedenv on Pursuit](https://pursuit.purescript.org/packages/purescript-typedenv/badge)](https://pursuit.purescript.org/packages/purescript-typedenv)\n## Type-directed environment parsing\n\n\u003cimg src=\"https://github.com/nsaunders/purescript-typedenv/raw/master/meta/img/tile.png\" alt=\"purescript-typedenv\" align=\"right\" /\u003e\n\nThe [`purescript-node-process` environment API](https://pursuit.purescript.org/packages/purescript-node-process/10.0.0/docs/Node.Process#v:getEnv)\nprovides environment variables in the form of an\n[`Object String`](https://pursuit.purescript.org/packages/purescript-foreign-object/2.0.2/docs/Foreign.Object#t:Object)\n(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\nsafely throughout the rest of the program.\n\nOne of the more popular solutions would be something like this applicative-style lookup/validation/parsing into a record:\n\n```purescript\ntype Config =\n  { greeting :: String\n  , count    :: Int\n  }\n\nparseConfig :: Object String -\u003e Either String Config\nparseConfig env =\n  (\\greeting count -\u003e { greeting, count })\n  \u003c$\u003e value \"GREETING\"\n  \u003c*\u003e ( value \"COUNT\"\n        \u003e\u003e= Int.fromString\n        \u003e\u003e\u003e Either.note \"Invalid COUNT\"\n      )\n  where\n    value name =\n      note (\"Missing variable \" \u003c\u003e name) $ lookup name env\n```\n\nHowever, this is a bit unsatisfying because the explicit lookups, parsing logic, and error handling are somewhat\nverbose and might start to look like a lot of boilerplate as the `Config` model is extended with additional fields.\nThe value-level logic creates additional touchpoints when fields are added or removed, or their types change.\n\nInstead, this library uses a type-directed approach, which starts with renaming the `Config` fields according to the\nenvironment variable names from which their values are sourced:\n\n```purescript\ntype Config =\n  { \"GREETING\" :: String\n  , \"COUNT\"    :: Int\n  }\n```\n\nThe `fromEnv` function now has enough information to convert the environment `Object String` to a typed record with\nno need for explicit lookups, parsing, or error handling:\n\n```purescript\nparseConfig :: Object String -\u003e Either String Config\nparseConfig = Either.lmap printEnvError \u003c\u003c\u003c TypedEnv.fromEnv (Proxy :: _ Config)\n```\n\n\u003e **Note**\n\u003e An additional benefit not demonstrated here is that the `TypedEnv.fromEnv` function accumulates a list of\n\u003e errors, whereas the former example can only present one error at a time.\n\n### Examples\n\nTo run one of the [examples](examples), clone the repository and run the following command, replacing `\u003cexample-name\u003e` with the name of the example.\n\n```bash\nspago -x example.dhall run -m Example.\u003cexample-name\u003e\n```\n\n### Installation\n\nvia [spago](https://github.com/spacchetti/spago):\n```bash\nspago install typedenv\n```\n\n### Similar ideas\n* [TypedEnv](https://github.com/freight-hub/TypedEnv)\n* [dotenv-hs](https://github.com/stackbuilders/dotenv-hs) can validate variables against a `.schema.yml` file.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnsaunders%2Fpurescript-typedenv","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnsaunders%2Fpurescript-typedenv","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnsaunders%2Fpurescript-typedenv/lists"}