{"id":21144323,"url":"https://github.com/gilbert/readtheroom","last_synced_at":"2026-05-19T08:09:46.925Z","repository":{"id":169095825,"uuid":"644892923","full_name":"gilbert/readtheroom","owner":"gilbert","description":"Typesafe environment configuration","archived":false,"fork":false,"pushed_at":"2023-12-15T05:10:14.000Z","size":212,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-05T22:49:18.235Z","etag":null,"topics":["environment-variables","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","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/gilbert.png","metadata":{"files":{"readme":"README.md","changelog":null,"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":"2023-05-24T13:24:06.000Z","updated_at":"2023-11-28T21:07:25.000Z","dependencies_parsed_at":"2023-12-15T06:27:06.450Z","dependency_job_id":"efa2016a-6f5a-4840-af79-f2e4100cdd8b","html_url":"https://github.com/gilbert/readtheroom","commit_stats":null,"previous_names":["gilbert/readtheroom"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gilbert%2Freadtheroom","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gilbert%2Freadtheroom/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gilbert%2Freadtheroom/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gilbert%2Freadtheroom/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gilbert","download_url":"https://codeload.github.com/gilbert/readtheroom/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243588689,"owners_count":20315464,"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":["environment-variables","typescript"],"created_at":"2024-11-20T08:16:53.886Z","updated_at":"2025-12-29T08:34:08.904Z","avatar_url":"https://github.com/gilbert.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# readtheroom\n\n![banner](.github/readtheroom.png)\n\nA small, versatile TypeScript library for declaratively handling configuration settings from environment variables with type safety.\n\n## Motivation\n\nReading environment variables in a typesafe manner can get annoying quick. `readtheroom` simplifies the process by giving you helpers to read, validate, set environment-specific defaults, and even convert types in a single `const` statement that you can easily `export` from a single file.\n\n## Getting Started\n\n```shell\nnpm install readtheroom\n```\n\nOnce installed, import it like so:\n\n```typescript\nimport { Env, read } from 'readtheroom'\n```\n\n## Examples\n\nIn the comments below, \"present\" means a non-empty string, and \"not present\" means `undefined` or an empty string.\n\n### read\n\n```typescript\nimport { read } from 'readtheroom'\n\n//\n// Reads from process.env.DB_NAME\n// Throws if not present.\n//\nexport const dbName = read('DB_NAME')\n\n//\n// Reads from process.env.DB_USER\n// If not present, uses 'default_user' as its value.\n//\nexport const dbUser = read('DB_USER', 'default_user');\n\n\n//\n// Reads from process.env.MAX_CONNECTIONS\n// If present, converts the string value into a number.\n// If not present, throws.\n//\nexport const maxConnections = read('MAX_CONNECTIONS', Number);\n\n//\n// Same as above, but with a default value.\n// Note that you must provide the default value as a string,\n// so that your converter function retains a consistent input type.\n//\nexport const maxConnections2 = read('MAX_CONNECTIONS', '4', Number);\n\n//\n// Reads from process.env.APP_CREDENTIALS\n// If present, parses the value as JSON and assumes its type.\n// If not present, throws.\n//\nconst credentials = read\u003cMyType\u003e('APP_CREDENTIALS', JSON.parse)\n```\n\n### Env\n\nEnv allows you to:\n\n1. Validate your currently running NODE_ENV.\n2. Choose different config values based on that NODE_ENV.\n\n```typescript\nimport { read, Env } from 'readtheroom'\n\n//\n// Reads process.env.NODE_ENV\n// If present, validates that it is either 'development' or 'production'\n// If not present, defaults to 'development' (this is the default default)\n//\nexport const env = Env(['test', 'development', 'production'])\n\n//\n// Same as above, except defaults to 'test' instead of 'development'\n//\nexport const env2 = Env(['test', 'development', 'production'], 'test')\n\n\n//\n// Reads process.env.DATABASE_URL *unless* in test environment.\n// Wraps the default value in a thunk so `read` doesn't throw unnecessarily.\n//\nexport const dbConfig = env.branch(\n  () =\u003e read('DATABASE_URL'),\n  {\n    test: 'postgresql://postgres:postgres@127.0.0.1:54322/postgres'\n    //\n    // Could also be this if you wanted:\n    //\n    // test: () =\u003e read('TEST_DATABASE_URL')\n  }\n)\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgilbert%2Freadtheroom","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgilbert%2Freadtheroom","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgilbert%2Freadtheroom/lists"}