{"id":23272927,"url":"https://github.com/buka-inc/npm.nestjs-config","last_synced_at":"2025-08-21T04:31:42.351Z","repository":{"id":215502502,"uuid":"738654667","full_name":"buka-inc/npm.nestjs-config","owner":"buka-inc","description":"An easy to use nestjs config module","archived":false,"fork":false,"pushed_at":"2024-12-18T17:38:07.000Z","size":77,"stargazers_count":6,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-12-18T18:37:12.667Z","etag":null,"topics":["config","configration","nconf","nestjs","npm"],"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/buka-inc.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":".github/CODE_OF_CONDUCT.md","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-01-03T18:20:57.000Z","updated_at":"2024-12-18T17:38:11.000Z","dependencies_parsed_at":"2024-01-04T20:27:36.759Z","dependency_job_id":"d6c494e0-b4b9-4051-bf32-763a861cf0c3","html_url":"https://github.com/buka-inc/npm.nestjs-config","commit_stats":null,"previous_names":["buka-lnc/npm.nestjs-config","buka-inc/npm.nestjs-config"],"tags_count":24,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/buka-inc%2Fnpm.nestjs-config","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/buka-inc%2Fnpm.nestjs-config/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/buka-inc%2Fnpm.nestjs-config/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/buka-inc%2Fnpm.nestjs-config/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/buka-inc","download_url":"https://codeload.github.com/buka-inc/npm.nestjs-config/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":230491086,"owners_count":18234357,"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":["config","configration","nconf","nestjs","npm"],"created_at":"2024-12-19T19:29:50.298Z","updated_at":"2025-08-21T04:31:42.345Z","avatar_url":"https://github.com/buka-inc.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# @buka/nestjs-config\n\n[npm]: https://www.npmjs.com/package/@buka/nestjs-config\n\n[![version](https://img.shields.io/npm/v/@buka/nestjs-config.svg?logo=npm\u0026style=for-the-badge)][npm]\n[![downloads](https://img.shields.io/npm/dm/@buka/nestjs-config.svg?logo=npm\u0026style=for-the-badge)][npm]\n[![dependencies](https://img.shields.io/librariesio/release/npm/@buka/nestjs-config?logo=npm\u0026style=for-the-badge)][npm]\n[![license](https://img.shields.io/npm/l/@buka/nestjs-config.svg?logo=github\u0026style=for-the-badge)][npm]\n[![Codecov](https://img.shields.io/codecov/c/gh/buka-lnc/npm.nestjs-config?logo=codecov\u0026token=PLF0DT6869\u0026style=for-the-badge)](https://codecov.io/gh/buka-lnc/npm.nestjs-config)\n\nThis is an easy-to-use nestjs config module with many surprising features.\n\n## Feature\n\n- Config verification by `class-validator`\n- Config transform by `class-transformer`\n- Load configuration files from anywhere\n- Perfect coding tips\n- Automatically handle naming styles\n- Injectable config class\n\n## Install\n\n```bash\nnpm install @buka/nestjs-config\nyarn install @buka/nestjs-config\npnpm install @buka/nestjs-config\n```\n\n## Usage\n\n`@buka/nestjs-config` load config from `process.env` and `.env`(local `process.cwd()`) by defaulted. let us create `.env` first:\n\n```bash\n# .env\nCACHE_DIR=\"./tmp\"\nBROKERS=\"test01.test.com,test02.test.com,test03.test.com\"\n```\n\nThen, define a `AppConfig` class with the `@Configuration()` decorator.\n\n```typescript\n// app.config.ts\nimport { Configuration } from \"@buka/nestjs-config\";\nimport { IsString, IsOptional, IsIn, IsIp } from \"class-validator\";\nimport { Split } from \"@miaooo/class-transformer-split\";\n\n@Configuration()\nexport class AppConfig {\n  // set default value\n  @IsIp()\n  host = \"0.0.0.0\";\n\n  // CACHE_DIR in .env\n  @IsString()\n  @IsOptional()\n  cacheDir?: string;\n\n  // process.env.NODE_ENV\n  @IsIn([\"dev\", \"test\", \"prod\"])\n  nodeEnv: string;\n\n  @Split(\",\")\n  brokers: string[];\n}\n```\n\n\u003e [!TIP]\n\u003e\n\u003e `@buka/nestjs-config` automatically convert naming styles. For example: `cache_dir`、`CACHE_DIR`、`cacheDir`、`CacheDir`、`cache-dir`、`Cache_Dir` are considered to be the same config name.\n\nImport `ConfigModule` in your `AppModule`:\n\n```typescript\n// app.module.ts\nimport { Module } from \"@nestjs/common\";\nimport { ConfigModule } from \"@buka/nestjs-config\";\nimport { AppConfig } from \"./app.config\";\n\n@Module({\n  // use process.env and read .env by defaulted\n  imports: [ConfigModule.register({ isGlobal: true })],\n})\nexport class AppModule {}\n```\n\nInject and use `AppConfig` in your service:\n\n```typescript\nimport { Injectable } from \"@nestjs/common\";\nimport { AppConfig } from \"./app.config\";\n\n@Injectable()\nexport class AppService {\n  constructor(private readonly appConfig: AppConfig) {}\n}\n```\n\n### Nested Configuration\n\nNested configuration is the same as using `class-validator` and `class-transformer`:\n\n```typescript\nimport { Configuration } from \"@buka/nestjs-config\";\nimport { IsString } from \"class-validator\";\n\nexport class SubConfig {\n  // process.env.{ParentFieldName}__KEY\n  @IsString()\n  key: string;\n}\n\n@Configuration()\nexport class AppConfig {\n  // process.env.SUB_FIRST__KEY\n  @ValidateNested()\n  @Type(() =\u003e SmsTemplate)\n  subFirst!: SubConfig;\n\n  // process.env.SUB_SECOND__KEY\n  @ValidateNested()\n  @Type(() =\u003e SmsTemplate)\n  subSecond!: SubConfig;\n}\n```\n\n### Add more dotenv files\n\n```typescript\nimport { Module } from \"@nestjs/common\";\nimport {\n  ConfigModule,\n  processEnvLoader,\n  dotenvLoader,\n} from \"@buka/nestjs-config\";\nimport { AppConfig } from \"./app.config\";\n\n@Module({\n  imports: [\n    ConfigModule.register({\n      isGlobal: true,\n      loaders: [\n        processEnvLoader,\n        // transform DATABASE__HOST=\"0.0.0.0\"\n        // to DATABASE = { HOST: \"0.0.0.0\" }\n        // transform LOG=\"true\"\n        // to LOG = true\n        dotenvLoader(\".env\", { separator: \"__\", jsonParse: true }),\n        dotenvLoader(`.${process.env.NODE_ENV}.env`),\n      ],\n    }),\n  ],\n})\nexport class AppModule {}\n```\n\n### Custom config loader\n\n```typescript\n// yaml-config-loader.ts\nimport { ConfigLoader } from \"@buka/nestjs-config\";\nimport { parse } from \"yaml\";\n\nexport async function yamlConfigLoader(filepath: string): ConfigLoader {\n  return (options: ConfigModuleOptions) =\u003e {\n    if (!existsSync(filepath)) {\n      if (!options.suppressWarnings) {\n        Logger.warn(`yaml file not found: ${filepath}`, '@buka/nestjs-config');\n      }\n\n      return {};\n    }\n\n    const content = await readFile(filepath);\n    return parse(content);\n  };\n}\n```\n\nUse `yamlConfigLoader`:\n\n```typescript\nimport { Module } from \"@nestjs/common\";\nimport { ConfigModule } from \"@buka/nestjs-config\";\nimport { AppConfig } from \"./app.config\";\nimport { yamlConfigLoader } from \"./yamlConfigLoader\";\n\n@Module({\n  imports: [\n    ConfigModule.register({\n      isGlobal: true,\n      loaders: [yamlConfigLoader(\"my-yaml-config.yaml\")],\n    }),\n  ],\n})\nexport class AppModule {}\n```\n\n### Add prefix to all class properties\n\n```typescript\n// mysql.config.ts\nimport { Configuration } from \"@buka/nestjs-config\";\nimport { IsString } from \"class-validator\";\n\n@Configuration(\"mysql.master\")\nexport class MysqlConfig {\n  // process : process.env.MYSQL__MASTER__HOST\n  // .env    : MYSQL__MASTER__HOST\n  // .json   : { mysql: { master: { host: \"\" } } }\n  @IsString()\n  host: string;\n}\n```\n\n### Custom the config name of property\n\n```typescript\n// app.config.ts\nimport { Configuration, ConfigKey } from \"@buka/nestjs-config\";\nimport { IsString } from \"class-validator\";\n\n@Configuration(\"mysql.master\")\nexport class MysqlConfig {\n  // process : process.env.DATABASE_HOST\n  // .env    : DATABASE_HOST\n  // .json   : { databaseHost: \"\" }\n  @ConfigKey(\"DATABASE_HOST\")\n  @IsString()\n  host: string;\n}\n```\n\n\u003e `@ConfigKey(name)` will overwrite the prefix of `@Configuration([prefix])`\n\n### Remove warning logs\n\n```typescript\nimport { Module } from \"@nestjs/common\";\nimport { ConfigModule } from \"@buka/nestjs-config\";\nimport { AppConfig } from \"./app.config\";\n\n@Module({\n  imports: [\n    ConfigModule.register({\n      isGlobal: true,\n      suppressWarnings: true,\n    }),\n  ],\n})\nexport class AppModule {}\n```\n\n### ConfigModule.inject(ConfigProvider, DynamicModule[, dynamicModuleOptions])\n\nSimplify the writing of `.forRootAsync`/`.registerAsync`.\n\n```typescript\n// pino.config.ts\n@Configuration(\"pino\")\nexport class PinoConfig implements Pick\u003cParams, \"assignResponse\"\u003e {\n  @ToBoolean()\n  @IsBoolean()\n  assignResponse?: boolean | undefined;\n}\n\n// app.module.ts\n@Module({\n  imports: [\n    ConfigModule.register({ isGlobal: true }),\n    ConfigModule.inject(PinoConfig, LoggerModule),\n  ],\n})\nclass AppModule {}\n```\n\nIf the config class implement options of module `.forRootAsync`/`.registerAsync`,\nThe code will become very beautiful.\n\nAnd `implement` is not necessary:\n\n```typescript\nimport { Module } from \"@nestjs/common\";\nimport { ConfigModule } from \"@buka/nestjs-config\";\n\n// pino.config.ts\n@Configuration(\"pino\")\nexport class PinoConfig {\n  @IsIn([\"fatal\", \"error\", \"warn\", \"info\", \"debug\", \"trace\"])\n  level: string = \"info\";\n}\n\n// app.module.ts\n@Module({\n  imports: [\n    ConfigModule.register({ isGlobal: true }),\n    // map .level to .pinoHttp.level\n    ConfigModule.inject(PinoConfig, LoggerModule, (config) =\u003e ({\n      pinoHttp: { level: config.level },\n    })),\n  ],\n})\nclass AppModule {}\n```\n\nSometimes, a `name` property is need by options of `.forRootAsync`/`.registerAsync`,\nlike [add multiple database in `@nestjs/typeorm`](https://docs.nestjs.com/techniques/database#multiple-databases).\n\n\u003e Another one is `isGlobal`\n\n```typescript\n@Module({\n  imports: [\n    ConfigModule.register({ isGlobal: true }),\n\n    ConfigModule.inject(\n      TypeOrmConfig,\n      TypeOrmModule,\n      { name: \"my-orm\" },\n      (config) =\u003e config // config mapping function is optional\n    ),\n\n    // this is equal to\n    TypeOrmModule.forRootAsync({\n      name: \"my-orm\",\n      inject: [TypeOrmConfig],\n      useFactory: (config: TypeOrmConfig) =\u003e config,\n    }),\n  ],\n})\nexport class AppModule {}\n```\n\n### Preload Config\n\nSometimes, we have to get config outside the nestjs lifecycle. `ConfigModule.preload(options)` is designed for this.\n\nThere is an example of [MikroORM](https://mikro-orm.io/) config file:\n\n```typescript\n// mikro-orm.config.ts\nimport { ConfigModule } from \"@buka/nestjs-config\";\nimport { MySqlDriver, defineConfig } from \"@mikro-orm/mysql\";\nimport { MysqlConfig } from \"./config/mysql.config\";\nimport { Migrator } from \"@mikro-orm/migrations\";\nimport { BadRequestException } from \"@nestjs/common\";\n\nexport default (async function loadConfig() {\n  // Load MysqlConfig\n  await ConfigModule.preload();\n\n  // Get MysqlConfig Instance\n  const config = await ConfigModule.get(MysqlConfig);\n  if (!config) throw new Error(\"Config Not Founded\");\n\n  // or\n  // const config = await ConfigModule.getOrFail(MysqlConfig);\n\n  return defineConfig({\n    ...config,\n    entities: [\"dist/**/*.entity.js\"],\n    driver: MySqlDriver,\n  });\n})();\n```\n\n\u003e [!TIP]\n\u003e\n\u003e The `options` of `ConfigModule.preload(options)` is the `options` of `ConfigModule.register(options)`\n\n## Loaders\n\n| **Name**           | **Description**                                                                          |\n| :----------------- | :--------------------------------------------------------------------------------------- |\n| `processEnvLoader` | load from `process.env`                                                                  |\n| `dotenvLoader`     | load `.env` file by [`dotenv`](https://www.npmjs.com/package/dotenv)                     |\n| `dotenvxLoader`    | load `.env` file by [`@dotenvx/dotenvx`](https://www.npmjs.com/package/@dotenvx/dotenvx) |\n| `jsonFileLoader`   | load json file by `JSON.parse`                                                           |\n| `yamlFileLoader`   | load yaml file by [`yaml`](https://www.npmjs.com/package/yaml)                           |\n| `tomlFileLoader`   | load toml file by [`smol-toml`](https://www.npmjs.com/package/smol-toml)                 |\n\n## Q\u0026A\n\n### Reported every field in my Config class was missing, even though they weren't.\n\n**This may be due to `target` in tsconfig.json is `ES2021` or lower.** We recommend using `ES2022` and above.\nBut, if you must use `ES2021`, every property key should add `@ConfigKey()` decorator ([See More](https://github.com/buka-inc/npm.nestjs-config/issues/26)):\n\n```typescript\n// app.config.ts\nimport { Configuration, ConfigKey } from \"@buka/nestjs-config\";\nimport { IsIp, IsIn } from \"class-validator\";\n\n@Configuration()\nexport class AppConfig {\n  @ConfigKey()\n  @IsIp()\n  host = \"0.0.0.0\";\n\n  @ConfigKey()\n  @IsIn([\"dev\", \"test\", \"prod\"])\n  nodeEnv: string;\n}\n```\n\n### Nest could not find `YourConfig` element.\n\n**`@buka/nestjs-config` will autoload all the config classes injected by service.**\nHowever, a config that is not used by any service may not be injected into the nestjs app.\nAnd this will causes you to get this error when attempt to `app.get(YourConfig)`.\n\nOne solution is use `ConfigModule.get(YourConfig)` replace `app.get(YourConfig)`:\n\n```typescript\nawait ConfigModule.preload();\nconst yourConfig = await ConfigModule.get(YourConfig);\n\n// If you do this, you probably want to do something outside of the nestjs runtime.\n// do...\n```\n\nIf you have to inject config class which is not used by any service, you can do it like this:\n\n```typescript\n@Module({\n  ConfigModule.register({\n    isGlobal: true,\n    providers: [YourConfig]\n  }),\n})\nclass AppModule {}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbuka-inc%2Fnpm.nestjs-config","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbuka-inc%2Fnpm.nestjs-config","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbuka-inc%2Fnpm.nestjs-config/lists"}