@buka/nestjs-config

中文文档
2.4.3发布于 2026/05/17MITTypeScriptESM + CJS构建来源已验证近 30 天下载 2万

An easy to use nestjs config module

原始使用文档
文档目录24 节
  1. Features
  2. Installation
  3. Quick Start
  4. 1. Create Configuration Class
  5. 2. Create Environment File
  6. 3. Import ConfigModule
  7. 4. Inject Configuration
  8. Configuration
  9. Global Configuration (Recommended)
  10. Configuration Options
  11. Custom Loaders
  12. Advanced Usage
  13. Nested Configuration
  14. Configuration Prefix
  15. Custom Config Keys
  16. Preload Config (Outside NestJS)
  17. Module Integration
  18. Configuration Hot Reload
  19. Built-in Loaders
  20. Custom Loader Example
  21. Troubleshooting
  22. Error: "Every field in my Config class was missing"
  23. Error: "Nest could not find YourConfig element"
  24. License

@buka/nestjs-config

version downloads dependencies license Codecov

An easy-to-use NestJS config module with powerful features and type safety.

Features

  • ✅ Type-Safe Configuration: Config verification by class-validator
  • ✅ Config Transformation: Config transform by class-transformer
  • ✅ Flexible Loading: Load configuration from multiple sources (env, files, etc.)
  • ✅ Hot Reload: Automatically reload configuration when files change (opt-in)
  • ✅ Auto Naming Convention: Automatically handles naming styles (camelCase, snake_case, etc.)
  • ✅ Injectable Classes: Configuration classes can be injected like any other provider
  • ✅ Global Configuration: Define configuration once, use everywhere
  • ✅ Perfect Type Hints: Full TypeScript support with excellent IDE autocomplete

Installation

npm install @buka/nestjs-config
# or
yarn add @buka/nestjs-config
# or
pnpm add @buka/nestjs-config

Quick Start

1. Create Configuration Class

Define your configuration using decorators from class-validator:

// app.config.ts
import { Configuration } from "@buka/nestjs-config";
import { IsString, IsOptional, IsIn, IsIp } from "class-validator";
import { Split } from "@miaooo/class-transformer-split";

@Configuration()
export class AppConfig {
  @IsIp()
  host = "0.0.0.0"; // default value

  @IsString()
  @IsOptional()
  cacheDir?: string;

  @IsIn(["dev", "test", "prod"])
  nodeEnv: string;

  @Split(",")
  brokers: string[];
}

2. Create Environment File

Create a .env file in your project root:

# .env
CACHE_DIR="./tmp"
NODE_ENV="dev"
BROKERS="test01.test.com,test02.test.com,test03.test.com"

[!TIP] @buka/nestjs-config automatically converts naming styles. cache_dir, CACHE_DIR, cacheDir, CacheDir, cache-dir, Cache_Dir are all recognized as the same config name.

3. Import ConfigModule

Import ConfigModule in your NestJS application:

// app.module.ts
import { Module } from "@nestjs/common";
import { ConfigModule } from "@buka/nestjs-config";

@Module({
  imports: [ConfigModule.register({ isGlobal: true })],
})
export class AppModule {}

By default, ConfigModule loads config from process.env and .env file.

4. Inject Configuration

Use configuration in your services:

// app.service.ts
import { Injectable } from "@nestjs/common";
import { AppConfig } from "./app.config";

@Injectable()
export class AppService {
  constructor(private readonly appConfig: AppConfig) {}

  getInfo() {
    return `Host: ${this.appConfig.host}, Env: ${this.appConfig.nodeEnv}`;
  }
}

Configuration

When you need to use configuration in multiple places (NestJS modules, ORM configs, scripts), use ConfigModule.configure() to avoid duplication:

Step 1: Create Configuration File

// config/index.ts
import {
  ConfigModule,
  processEnvLoader,
  yamlFileLoader,
} from "@buka/nestjs-config";

ConfigModule.configure({
  loaders: [processEnvLoader(), yamlFileLoader("config.yaml")],
  suppressWarnings: true,
});

Step 2: Use in NestJS Module

// app.module.ts
import { Module } from "@nestjs/common";
import { ConfigModule } from "@buka/nestjs-config";
import "./config"; // Import configuration

@Module({
  imports: [
    ConfigModule.register({ isGlobal: true }), // Uses global config
  ],
})
export class AppModule {}

Step 3: Use in External Files (ORM configs, scripts, etc.)

// mikro-orm.config.ts
import { ConfigModule } from "@buka/nestjs-config";
import { DatabaseConfig } from "./config/database.config";
import "./config"; // Import configuration

export default (async function () {
  await ConfigModule.preload(); // Uses global config
  const config = await ConfigModule.getOrFail(DatabaseConfig);
  return { ...config };
})();

[!TIP] Benefits of Global Configuration:

  • Configure once, use everywhere
  • No duplication between preload() and register()
  • Guaranteed consistency across your application
  • Can still override settings when needed by passing options directly

Configuration Options

interface ConfigModuleOptions {
  /**
   * Configuration loaders (default: processEnvLoader + .env file)
   */
  loaders?: (string | ConfigLoader)[];

  /**
   * Suppress warning messages
   */
  suppressWarnings?: boolean;

  /**
   * Enable debug logging
   */
  debug?: boolean;

  /**
   * Manually specify config providers (usually auto-detected)
   */
  providers?: Type[];
}

Custom Loaders

You can customize how configuration is loaded:

import {
  ConfigModule,
  processEnvLoader,
  dotenvLoader,
} from "@buka/nestjs-config";

ConfigModule.configure({
  loaders: [
    processEnvLoader(),
    dotenvLoader(".env", { separator: "__", jsonParse: true }),
    dotenvLoader(`.env.${process.env.NODE_ENV}`),
  ],
});

Advanced Usage

Nested Configuration

import { Configuration } from "@buka/nestjs-config";
import { ValidateNested, Type } from "class-transformer";
import { IsString } from "class-validator";

export class DatabaseConfig {
  @IsString()
  host: string; // DATABASE__HOST

  @IsString()
  password: string; // DATABASE__PASSWORD
}

@Configuration()
export class AppConfig {
  @ValidateNested()
  @Type(() => DatabaseConfig)
  database: DatabaseConfig;
}

Environment variables: DATABASE__HOST=localhost, DATABASE__PASSWORD=secret

Configuration Prefix

Use @Configuration(prefix) to add a prefix to all properties:

import { Configuration } from "@buka/nestjs-config";
import { IsString } from "class-validator";

@Configuration("mysql.master")
export class MysqlConfig {
  @IsString()
  host: string; // MYSQL__MASTER__HOST
}

Mapping:

  • process.env: MYSQL__MASTER__HOST
  • .env file: MYSQL__MASTER__HOST
  • JSON file: { mysql: { master: { host: "..." } } }

Custom Config Keys

Use @ConfigKey() to override the property name:

import { Configuration, ConfigKey } from "@buka/nestjs-config";
import { IsString } from "class-validator";

@Configuration("mysql")
export class MysqlConfig {
  @ConfigKey("DATABASE_HOST")
  @IsString()
  host: string; // Now reads from DATABASE_HOST instead of MYSQL__HOST
}

[!NOTE] @ConfigKey(name) overwrites the prefix from @Configuration(prefix)

Preload Config (Outside NestJS)

Use ConfigModule.preload() to load configuration before NestJS initialization:

// database-migration.ts
import { ConfigModule } from "@buka/nestjs-config";
import { DatabaseConfig } from "./config/database.config";
import "./config"; // Import global configuration

async function migrate() {
  await ConfigModule.preload(); // Uses global config

  // Get configuration
  const config = await ConfigModule.getOrFail(DatabaseConfig);

  // Use config for migration...
}

Module Integration

Simplify configuration injection into other modules using ConfigModule.inject():

import { Module } from "@nestjs/common";
import { ConfigModule, Configuration } from "@buka/nestjs-config";
import { LoggerModule } from "nestjs-pino";
import { IsIn } from "class-validator";

@Configuration("logger")
class LoggerConfig {
  @IsIn(["fatal", "error", "warn", "info", "debug", "trace"])
  level: string = "info";
}

@Module({
  imports: [
    ConfigModule.register({ isGlobal: true }),

    // Using ConfigModule.inject() - Simple and clean
    ConfigModule.inject(LoggerConfig, LoggerModule, (config) => ({
      pinoHttp: { level: config.level },
    })),
  ],
})
class AppModule {}

Configuration Hot Reload

The module supports hot-reloading of configuration files, allowing your application to automatically pick up configuration changes without restarting.

Basic Usage

Enable hot reload per loader using the hotReload option:

import {
  ConfigModule,
  dotenvLoader,
  jsonFileLoader,
  yamlFileLoader,
} from "@buka/nestjs-config";

@Module({
  imports: [
    ConfigModule.register({
      isGlobal: true,
      loaders: [
        // Enable hot reload with default settings (file watcher)
        dotenvLoader(".env", { hotReload: true }),

        // Enable hot reload for JSON file
        jsonFileLoader("./config.json", "utf-8", { hotReload: true }),

        // Enable hot reload for YAML file
        yamlFileLoader("./config.yaml", "utf-8", { hotReload: true }),
      ],
    }),
  ],
})
export class AppModule {}

Advanced Usage - Watch Types and Hooks

You can customize the watch behavior for each loader:

ConfigModule.register({
  loaders: [
    // File system watch (default, recommended)
    dotenvLoader(".env", {
      hotReload: {
        type: "watch", // Use chokidar file system watcher
        debounceMs: 500, // Wait 500ms before reloading (default: 300ms)

        onChange: async (newConfig) => {
          console.log("Config file changed, new config:", newConfig);
        },

        onError: async (error) => {
          console.error("Failed to reload config:", error);
        },
      },
    }),

    // Polling mode (for network drives or special filesystems)
    jsonFileLoader("./config.json", "utf-8", {
      hotReload: {
        type: "interval", // Use polling instead of file watching
        intervalMs: 5000, // Check every 5 seconds (default: 5000ms)
        debounceMs: 300,
      },
    }),
  ],
});

Manual Reload

You can also manually trigger configuration reload:

import { ConfigModule } from "@buka/nestjs-config";

// In your service or controller
async reloadConfig() {
  try {
    await ConfigModule.reload();
    return { message: "Configuration reloaded successfully" };
  } catch (error) {
    throw new Error(`Failed to reload config: ${error.message}`);
  }
}

This is useful when:

  • Configuration is updated programmatically (not via file changes)
  • You need to reload configuration on demand (e.g., admin endpoint)
  • Testing configuration changes

How It Works

  • Each loader can independently enable hot reload with its own settings
  • When a file changes, the loader triggers a global configuration reload
  • All configuration provider instances are updated in-place
  • Injected configuration objects automatically reflect the new values
  • If validation fails, the old configuration is preserved (rollback)

Notes

  • Hot reload is configured per loader (opt-in for each file)
  • Supports both watch mode (file system events) and interval mode (polling)
  • Environment variable loader (processEnvLoader) does not support watching
  • Each loader has independent debouncing (default: 300ms)
  • Configuration validation still applies on reload
  • Manual reload via ConfigModule.reload() is also available

Equivalent without ConfigModule.inject():

@Module({
  imports: [
    ConfigModule.register({ isGlobal: true }),

    // Using forRootAsync directly - More verbose
    LoggerModule.forRootAsync({
      inject: [LoggerConfig],
      useFactory: (config: LoggerConfig) => ({
        pinoHttp: { level: config.level },
      }),
    }),
  ],
})
class AppModule {}

As you can see, ConfigModule.inject() provides a cleaner syntax for injecting configuration into other modules.

Advanced: Inject with additional options

import { TypeOrmModule } from "@nestjs/typeorm";

@Configuration("database")
class DatabaseConfig {
  @IsString()
  host: string;

  @IsNumber()
  port: number;

  @IsString()
  database: string;
}

@Module({
  imports: [
    ConfigModule.register({ isGlobal: true }),

    // With additional module options (e.g., multiple databases)
    ConfigModule.inject(
      DatabaseConfig,
      TypeOrmModule,
      { name: "primary" }, // Additional options
      (config) => config, // Config mapper (optional)
    ),
  ],
})
class AppModule {}

Equivalent to:

TypeOrmModule.forRootAsync({
  name: "primary",
  inject: [DatabaseConfig],
  useFactory: (config: DatabaseConfig) => config,
});

Built-in Loaders

LoaderDescription
processEnvLoader()Load from process.env
dotenvLoader(path, options?)Load .env file using dotenv
dotenvxLoader(path, options?)Load .env file using @dotenvx/dotenvx
jsonFileLoader(path)Load JSON file
yamlFileLoader(path, encoding?)Load YAML file using yaml
tomlFileLoader(path, encoding?)Load TOML file using smol-toml

Custom Loader Example

import { ConfigLoader, ConfigModuleOptions } from "@buka/nestjs-config";
import { readFileSync } from "fs";

export function customLoader(filepath: string): ConfigLoader {
  return (options: ConfigModuleOptions) => {
    const content = readFileSync(filepath, "utf-8");
    // Parse and return configuration object
    return JSON.parse(content);
  };
}

Troubleshooting

Error: "Every field in my Config class was missing"

This may occur when using TypeScript with target set to ES2021 or lower.

Solution 1 (Recommended): Upgrade to ES2022 or higher in tsconfig.json

Solution 2: Add @ConfigKey() decorator to every property:

import { Configuration, ConfigKey } from "@buka/nestjs-config";

@Configuration()
export class AppConfig {
  @ConfigKey()
  @IsIp()
  host = "0.0.0.0";

  @ConfigKey()
  @IsIn(["dev", "test", "prod"])
  nodeEnv: string;
}

Error: "Nest could not find YourConfig element"

This occurs when a config class is not injected into any service.

Solution 1: Use ConfigModule.get() instead of app.get():

await ConfigModule.preload();
const config = await ConfigModule.get(YourConfig);

Solution 2: Manually register the config class:

@Module({
  imports: [
    ConfigModule.register({
      isGlobal: true,
      providers: [YourConfig],
    }),
  ],
})
class AppModule {}

License

MIT

版本与发布记录

@buka/nestjs-config 共发布 29 个版本,首次发布于 2024/01/06;过去 12 个月发布了 2 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
2.4.3latest2026/05/175 个月前
2.4.22026/05/096 个月前
2.3.22025/05/091.5 年前
2.3.12025/03/041.7 年前
2.3.02025/03/031.7 年前
2.2.02025/03/021.7 年前

关于 @buka/nestjs-config 的常见问题

@buka/nestjs-config 是什么?

An easy to use nestjs config module

如何安装 @buka/nestjs-config?

在项目目录运行 npm install @buka/nestjs-config,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:@nestjs/common(^10 || ^11)、class-transformer(*)、class-validator(*)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@buka/nestjs-config 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@buka/nestjs-config 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@buka/nestjs-config 可以商用吗?

@buka/nestjs-config 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@buka/nestjs-config 的下载量有多少?

根据 npm 官方下载统计,@buka/nestjs-config 在 2026/10/09 – 2026/11/07 这 30 天内被下载 19,512 次,日均约 650 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@buka/nestjs-config 还在维护吗?

最新版本 2.4.3 发布于 2026/05/17(5 个月前);至今共发布 29 个版本,其中过去 12 个月发布了 2 个;首次发布于 2024/01/06。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。