{"id":15020884,"url":"https://github.com/gamote/nestjs-zod-config","last_synced_at":"2026-03-02T10:02:39.694Z","repository":{"id":217149680,"uuid":"743225219","full_name":"Gamote/nestjs-zod-config","owner":"Gamote","description":"NestJS module to load, type and validate configuration using Zod","archived":false,"fork":false,"pushed_at":"2025-11-06T22:52:33.000Z","size":365,"stargazers_count":3,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-11-07T00:20:49.955Z","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":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Gamote.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-01-14T17:48:47.000Z","updated_at":"2025-11-06T22:52:38.000Z","dependencies_parsed_at":null,"dependency_job_id":"b80e5f86-ab08-44fc-abbf-e28181bce5b4","html_url":"https://github.com/Gamote/nestjs-zod-config","commit_stats":null,"previous_names":["gamote/nestjs-zod-config"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/Gamote/nestjs-zod-config","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Gamote%2Fnestjs-zod-config","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Gamote%2Fnestjs-zod-config/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Gamote%2Fnestjs-zod-config/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Gamote%2Fnestjs-zod-config/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Gamote","download_url":"https://codeload.github.com/Gamote/nestjs-zod-config/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Gamote%2Fnestjs-zod-config/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29998084,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-02T09:59:02.300Z","status":"ssl_error","status_checked_at":"2026-03-02T09:59:02.001Z","response_time":60,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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-09-24T19:55:48.459Z","updated_at":"2026-03-02T10:02:39.681Z","avatar_url":"https://github.com/Gamote.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# NestJS Zod Config\n\n[![NPM version](https://img.shields.io/npm/v/nestjs-zod-config.svg?style=flat)](https://www.npmjs.com/package/nestjs-zod-config)\n[![NPM downloads](https://img.shields.io/npm/dm/nestjs-zod-config.svg?style=flat)](https://www.npmjs.com/package/nestjs-zod-config)\n![Fastify](https://img.shields.io/badge/-Vitest-86b91a?style=flat\u0026logo=vitest\u0026logoColor=white)\n\n**nestjs-zod-config** - NestJS module to load, type and validate configuration using Zod. Inside and outside the NestJS context.\n\nWe’re also providing some handy utility functions. ✨\n\n## Installation\n\n```bash\nyarn add nestjs-zod-config\n```\n\u003e Peer dependencies: `yarn add @nestjs/common zod`\n\n## Setup\n\nThe first thing that we need to do is to create a config class that extends `ZodConfig` and pass it our Zod schema.\n\n```ts\n// app.config.ts\nimport { ZodConfig } from 'nestjs-zod-config';\nimport { z } from 'zod';\n\nconst appConfigSchema = z.object({\n   HOSTNAME: z.string().min(1).default('0.0.0.0'),\n   PORT: z.coerce.number().default(3000),\n});\n\nexport class AppConfig extends ZodConfig(appConfigSchema) {}\n\n// You can also pass a custom path to the .env file(s)\nexport class AppConfig extends ZodConfig(appConfigSchema, {\n  envFilePath: '.env.custom'\n}) {}\n```\n\n\u003e By default, this assumes that you have a `.env` file in the root of your project or that you’ve set the environment variables in `process.env` in some other way. You can customize the path to the .env file using the `envFilePath` option.\n\n✨ All done. Let's see how we can use it.\n\n## Usage\n\n### Inside NestJS context\n\nWe will have to register the config class in a module:\n\n```ts\n// app.module.ts\nimport { Module } from '@nestjs/common';\nimport { ZodConfigModule } from 'nestjs-zod-config';\nimport { AppConfig } from './app.config';\n\n@Module({\n   imports: [\n     ZodConfigModule.forRoot({\n       config: AppConfig,\n       isGlobal: true, // optional, defaults to `false`\n     }),\n   ],\n})\nexport class AppModule {}\n```\n\n\u003e It is recommended to register the config class in the root module of your application.\n\nNow we can inject `AppConfig` in your services like this:\n\n```ts\n// app.service.ts\nimport { Injectable } from '@nestjs/common';\nimport { AppConfig } from './app.config';\n\n@Injectable()\nexport class AppService {\n   constructor(private readonly appConfig: AppConfig) {}\n\n   getPort(): number {\n     return this.appConfig.get('PORT');\n   }\n}\n```\n\nor in our `main.ts`, like this:\n\n```ts\n// main.ts\nimport { NestFactory } from '@nestjs/core';\nimport { AppConfig } from './app.config';\nimport { AppModule } from './app.module';\n\nconst main = async () =\u003e {\n  const app = await NestFactory.create(AppModule);\n\n  const appConfig = app.get(AppConfig);\n\n  const hostname = appConfig.get('HOSTNAME');\n  const port = appConfig.get('PORT');\n\n  await app.listen(port, hostname);\n};\n\nvoid main();\n```\n\n### Outside NestJS context\n\nThere are cases where we need to access the config outside the NestJS context. For example, we might want to use the config in a seeder script:\n\n```ts\n// seed.ts\nimport { loadZodConfig } from 'nestjs-zod-config';\n\nconst seedDb = async () =\u003e {\n  const appConfig = loadZodConfig(AppConfig);\n\n  const databaseurl = appConfig.get('DATABASE_URL');\n\n  // use the `databaseurl` to connect to the database and seed it\n};\n```\n\n\u003e In this case we can’t inject the `AppConfig` and we don't have access to the `app` instance. The file is executed outside the NestJS context.\n\n## Testing with Overrides\n\nFor testing purposes, you can override configuration values without modifying environment variables or `.env` files. This is particularly useful for unit tests, integration tests, or when you need different configuration values for specific test scenarios.\n\n### Using overrides in ZodConfig\n\nYou can pass overrides directly when creating your config class:\n\n```ts\n// test-app.config.ts\nimport { ZodConfig } from 'nestjs-zod-config';\nimport { appConfigSchema } from './app.config';\n\nexport class TestAppConfig extends ZodConfig(appConfigSchema, {\n  overrides: {\n    DATABASE_URL: 'sqlite://test.db',\n    JWT_SECRET: 'test-secret',\n    PORT: 4000,\n  }\n}) {}\n```\n\n### Using withOverrides static method\n\nYou can also create new instances with overrides directly from the config class:\n\n```ts\n// In your tests\nimport { AppConfig } from './app.config';\n\nconst testConfig = AppConfig.withOverrides({\n  DATABASE_URL: 'sqlite://test.db',\n  DEBUG: true,\n});\n\n// testConfig is a new instance with the overridden values\n// You can create multiple independent instances with different overrides\nconst anotherTestConfig = AppConfig.withOverrides({\n  DATABASE_URL: 'sqlite://another-test.db',\n  PORT: 4000,\n});\n```\n\n\u003e **Note:** Overrides have the highest priority and will take precedence over both environment variables and `.env` file values. All override values are fully type-safe and validated against your Zod schema.\n\n## Utility functions\n\n### Use `safeBooleanCoerce` to coerce strings to booleans safely\n\nThis is a utility function that can be used to coerce a string value to a boolean in a strict manner.\n\nNormally you will do: `z.coerce.boolean()` but this will also coerce the string `'false'` to `true`.\nSo instead we use this function to only allow `'false'` or `false` to be coerced to `false`, `'true'` or `true` to `true` and everything else will throw an error.\n\n```ts\n// In your schema\nconst configSchema = z.object({\n  DEBUG_MODE: safeBooleanCoerce,\n});\n\n// When parsed:\n// \"true\" or true -\u003e true\n// \"false\" or false -\u003e false\n// Any other value -\u003e Error: \"Invalid boolean value\"\n```\n\n### Use `commaDelimitedArray` to parse comma-separated strings into arrays\n\nThis is a utility function that can be used to parse a comma-delimited string into an array of strings.\n\nIt's particularly useful when dealing with environment variables that contain multiple values separated by commas. For example, you might have an environment variable like `ALLOWED_ORIGINS=http://localhost:3000,https://example.com` that you want to parse into an array.\n\n```ts\n// In your schema\nconst configSchema = z.object({\n  ALLOWED_ORIGINS: commaDelimitedArray,\n  // Or require at least one item:\n  REQUIRED_ORIGINS: commaDelimitedArray.min(1),\n});\n\n// When parsed, this will transform \"http://localhost:3000,https://example.com\" into:\n// [\"http://localhost:3000\", \"https://example.com\"]\n```\n\nThe function trims whitespace from each item and filters out empty values. Empty strings result in empty arrays. If you need to ensure at least one element, you can chain `.min(1)` to the schema. If the input is not a string, it will throw a validation error.\n\n### Use `jsonStringCoerce` to parse JSON strings into objects\n\nThis is a utility function that can be used to transform a JSON string into an object. It's particularly useful when dealing with environment variables that contain JSON data.\n\n```ts\n// In your schema\nconst configSchema = z.object({\n  SERVICE_ACCOUNT: jsonStringCoerce.pipe(\n    z.object({\n      type: z.literal('service_account'),\n      project_id: z.string().min(1),\n      private_key_id: z.string().min(1),\n      private_key: z.string().min(1),\n      client_email: z.string().min(1),\n      client_id: z.string().min(1),\n      auth_uri: z.string().url(),\n      token_uri: z.string().url(),\n      auth_provider_x509_cert_url: z.string().url(),\n      client_x509_cert_url: z.string().url(),\n    }).required(),\n  ),\n});\n\n// When parsed, this will transform a JSON string like:\n// '{\"type\":\"service_account\",\"project_id\":\"my-project\",...}'\n// into a properly validated object with the specified structure\n```\n\nThe function first attempts to parse the input string as JSON. If parsing fails, it will throw a validation error with the message \"Invalid JSON string - cannot be parsed\". After successful parsing, you can pipe the result to additional Zod schemas for further validation and transformation.\n\n### Use `strictCoerceStringDate` for strict date coercion\n\nThis is a utility function that can be used to coerce a string to a date in a strict manner.\n\nWhen using `z.coerce.date()`, you might get unexpected results. For example, `z.coerce.date().parse(null)` returns `1970-01-01T00:00:00.000Z`, which may not be the desired behavior in many cases.\n\nThis utility is particularly useful in DTOs where `null` or `undefined` may be passed, but their resolution to a date is not desired. It ensures that only valid string representations of dates are coerced to Date objects.\n\n```ts\n// In your schema\nconst configSchema = z.object({\n  EXPIRATION_DATE: strictCoerceStringDate,\n});\n\n// When parsed:\n// \"2023-01-01\" -\u003e Date object (2023-01-01T00:00:00.000Z)\n// null or undefined -\u003e Error: Expected string, received null/undefined\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgamote%2Fnestjs-zod-config","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgamote%2Fnestjs-zod-config","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgamote%2Fnestjs-zod-config/lists"}