{"id":17251052,"url":"https://github.com/fumieval/evp-ts","last_synced_at":"2025-04-14T05:19:29.829Z","repository":{"id":237609290,"uuid":"794875832","full_name":"fumieval/evp-ts","owner":"fumieval","description":"simple environment variable parser for TypeScript","archived":false,"fork":false,"pushed_at":"2025-02-06T06:59:02.000Z","size":368,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-22T14:16:40.266Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/fumieval.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,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-05-02T06:14:49.000Z","updated_at":"2025-02-06T06:59:06.000Z","dependencies_parsed_at":"2025-01-15T05:29:01.839Z","dependency_job_id":"02a0c63f-89e0-41d4-8edd-55bcd6dae22d","html_url":"https://github.com/fumieval/evp-ts","commit_stats":null,"previous_names":["fumieval/evp-ts"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fumieval%2Fevp-ts","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fumieval%2Fevp-ts/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fumieval%2Fevp-ts/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fumieval%2Fevp-ts/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fumieval","download_url":"https://codeload.github.com/fumieval/evp-ts/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248824761,"owners_count":21167356,"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":[],"created_at":"2024-10-15T06:50:13.158Z","updated_at":"2025-04-14T05:19:29.810Z","avatar_url":"https://github.com/fumieval.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# evp-ts: Environment Variable Parser for TypeScript\n\n[![npm version](https://badge.fury.io/js/evp-ts.svg)](https://badge.fury.io/js/evp-ts)\n\nevp-ts is a lightweight and easy-to-use library for parsing environment variables in TypeScript projects. It provides a simple way to collect and validate environment variables.\n\nThis package is inspired by [zod](https://zod.dev/) and [EVP](https://github.com/fumieval/EVP), an environment variable parser library for Haskell.\n\n## Features\n\n- 🐾 Low dependency footprint\n- 🧹 Clutter-free code\n- 🪺 Supports nested structure\n- 🧩 Well-typed interface\n- ⚗️ Derive types from the parser\n- 📝 Explicit logging of parsed environment variables\n- 🔒 Hiding sensitive values (e.g. API keys) from logs\n- 🛡️ Handle errors comprehensively\n- 📜 Generate dotenv-style help text from the parser\n- 🎭 Dynamically toggle between different sets of environment variables (discriminated unions)\n- 🗑️ Detect unused environment variables\n\n## Usage\n\nHere's an example of how to use evp-ts in your TypeScript project:\n\n```typescript\nimport { EVP } from 'evp-ts';\n\nconst parser = EVP.object({\n    API_ENDPOINT: EVP.string(),\n    API_TOKEN: EVP.string().secret(),\n    HTTP_PORT: EVP.number(),\n    DEBUG_MODE: EVP.boolean().default(false),\n});\n\ntype Config = EVP.infer\u003ctypeof parser\u003e;\nconst result: Config = parser.parse();\n\nconsole.log(result);\n```\n\n```\n[EVP] API_ENDPOINT=https://example.com\n[EVP] API_TOKEN=\u003cSHA256:2bb80d53\u003e\n[EVP] HTTP_PORT=8080\n[EVP] DEBUG_MODE=false (default)\n[EVP] MYSQL_HOST=localhost (default)\n[EVP] MYSQL_PORT=3306 (default)\n{\n  API_ENDPOINT: 'https://api.example.com',\n  API_TOKEN: 'secret',\n  HTTP_PORT: 3000,\n  DEBUG_MODE: false,\n  mysql: { host: 'localhost', port: '3306', user: 'root' }\n}\n```\n\nIn this example, we define a parser using the `EVP.object()` function, which takes an object describing the structure and types of the environment variables. Each key in the object represents an environment variable, and the corresponding value defines its type and any additional options (e.g. default values, secret flag).\n\nYou can infer the type of the result using the `EVP.infer\u003ctypeof parser\u003e`, rather than defining it manually.\n\nThe `parse()` method is then called on the parser to parse the environment variables and return an object with the parsed values. If any required environment variables are missing or have invalid values, evp-ts will log an error message but continue parsing the remaining variables to provide a comprehensive error report.\n\n## Supported Types\n\nevp-ts supports the following types for parsing environment variables:\n\n- `EVP.string()`: Get the value as a string.\n- `EVP.number()`: Parses the value as a number.\n- `EVP.boolean()`: Parses the value as a boolean (`true`, `yes`, and `1` becomes `true` and `false`, `no`, `0` becomes `false`).\n- `EVP.object()`: Defines a nested object structure for grouping related environment variables.\n\n## Modifiers\n\nevp-ts provides additional options for configuring the behavior of environment variable parsing:\n\n- `.default(value)`: Specifies a default value to use if the environment variable is not set.\n- `.secret()`: Logs its SHA-256 hash instead of the actual value.\n- `.optional()`: Marks the environment variable as optional, allowing it to be missing without causing an error.\n- `.env(name)`: Specifies the name of the environment variable to use for parsing.\n## Generating Help Text\n\n`parser.describe()` generates a dotenv-style help text from the parser.\nFor this purpose, `.description(text)` and `.metavar(name)` methods are provided.\nIf `.metavar(name)` is not specified, the default value or the type name is used as the metavariable name.\n\n```typescript\nimport { EVP } from 'evp-ts';\n\nconst parser = EVP.object({\n    API_ENDPOINT: EVP.string().description('The base URL of the API'),\n    API_TOKEN: EVP.string().secret().metavar('TOKEN'),\n    HTTP_PORT: EVP.number().description('The port number to listen on'),\n    DEBUG_MODE: EVP.boolean().default(false),\n});\n\nconsole.log(parser.describe());\n```\n\n```\n# The base URL of the API\nAPI_ENDPOINT=\u003cstring\u003e\nAPI_TOKEN=TOKEN\n# The port number to listen on\nHTTP_PORT=\u003cnumber\u003e\nDEBUG_MODE=false\n```\n\n## Discriminated Unions\n\nIn the following example, the `DATABASE_BACKEND` environment variable is used to switch between different sets of environment variables for different database backends.\n\nThe `EVP.union()` function is used to define a union of different parsers.\nThe `options()` method is then used to define a set of parsers for each possible value of `DATABASE_BACKEND`.\nThe field specified by the `discriminator()` contains the value of `DATABASE_BACKEND`.\nIf `DATABASE_BACKEND` is not set, it will use the default option specified by the `.default()` method.\n\n```typescript\nimport { EVP } from 'evp-ts';\n\nconst parser = EVP.object({\n    DATABASE_BACKEND: EVP.union({\n        mysql: EVP.object({\n            host: EVP.string().env('MYSQL_HOST').default('localhost'),\n            port: EVP.number().env('MYSQL_PORT').default(3306),\n        }).description('MySQL database connection settings'),\n        sqlite: EVP.object({\n            path: EVP.string().env('SQLITE_PATH'),\n        }),\n    }).tag('backend');\n    // .default('sqlite'),\n});\n\nconsole.log(parser.describe());\nconsole.log(parser.parse());\n```\n\n## Customising the logger\n\nBy default, evp-ts uses `console` to log messages.\nYou can attach a custom logger, such as [winston](https://www.npmjs.com/package/winston)'s to the parser using the `.logger()` method.\n\n```typescript\nimport { EVP } from 'evp-ts';\nimport * as winston from 'winston';\n\nconst logger = winston.createLogger();\nconst parser = EVP.object({\n    LOG_LEVEL: EVP.enum(['error', 'warn', 'info', 'debug']).default('info'),\n}).logger(logger);\n\nconst result = parser.parse();\nlogger.level = result.LOG_LEVEL;\n```\n\n## Detecting unused environment variables\n\nTypos in environment variable names can lead to bugs that are difficult to detect, especially when the intended variable is optional.\n\nTo detect unused environment variables, call `parser.reportUnused()` or `parser.rejectUnused()`.\n\n```typescript\nconst result = parser.logger(logger).safeParse({\n    APP_BAR: 'bar', // logged as unused\n    HOME: '/home/user', // ignored\n}).assumePrefix('APP_').rejectUnused();\n```\n\nIn practice, you may want to prefix the environment variables you intend to parse, then set `assumePrefix` to specify the prefix (or prefices). When an environment variable with the given prefix is not used, it is considered unused and will be logged.\n\n## License\n\nevp-ts is open-source software licensed under the [MIT License](https://opensource.org/licenses/MIT).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffumieval%2Fevp-ts","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffumieval%2Fevp-ts","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffumieval%2Fevp-ts/lists"}