@buka/nestjs-config
TypeScript icon, indicating that this package has built-in type declarations

2.1.1 • Public • Published

@buka/nestjs-config

version downloads dependencies license Codecov

This is an easy-to-use nestjs config module with many surprising features.

Feature

  • Config verification by class-validator
  • Config transform by class-transformer
  • Load configuration files from anywhere
  • Perfect coding tips
  • Automatically handle naming styles
  • Injectable config class

Install

npm install @buka/nestjs-config
yarn install @buka/nestjs-config
pnpm install @buka/nestjs-config

Usage

@buka/nestjs-config load config from process.env and .env in process.cwd() by defaulted. let us create .env first:

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

Then, define a AppConfig class with the @Configuration() decorator. And add decorators of class-validator to properties:

// 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 {
  // set default value
  @IsIp()
  host = "0.0.0.0";

  // CACHE_DIR in .env
  @IsString()
  @IsOptional()
  cacheDir?: string;

  // process.env.NODE_ENV
  @IsIn(["dev", "test", "prod"])
  nodeEnv: string;

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

@buka/nestjs-config automatically convert naming styles. For example: cache_dirCACHE_DIRcacheDirCacheDircache-dirCache_Dir are considered to be the same config name.

Import ConfigModule in your AppModule:

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

@Module({
  // use process.env and read .env by defaulted
  imports: [
    ConfigModule.register({
      isGlobal: true,
      providers: [AppConfig],
    }),
  ],
})
export class AppModule {}

Inject and use AppConfig in your service:

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

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

Add more dotenv files

import { Module } from "@nestjs/common";
import {
  ConfigModule,
  processEnvLoader,
  dotenvLoader,
} from "@buka/nestjs-config";
import { AppConfig } from "./app.config";

@Module({
  imports: [
    ConfigModule.register({
      isGlobal: true,
      providers: [AppConfig],
      loaders: [
        processEnvLoader,
        // transform DATABASE__HOST="0.0.0.0"
        // to DATABASE = { HOST: "0.0.0.0" }
        // transform LOG="true"
        // to LOG = true
        dotenvLoader(".env", { separator: "__", jsonParse: true }),
        dotenvLoader(`.${process.env.NODE_ENV}.env`),
      ],
    }),
  ],
})
export class AppModule {}

Custom config loader

// yaml-config-loader.ts
import { ConfigLoader } from "@buka/nestjs-config";
import { parse } from "yaml";

export async function yamlConfigLoader(filepath: string): ConfigLoader {
  return (options: ConfigModuleOptions) => {
    if (!existsSync(filepath)) {
      if (!options.suppressWarnings) {
        Logger.warn(`yaml file not found: ${filepath}`);
      }

      return {};
    }

    const content = await readFile(filepath);
    return parse(content);
  };
}

Use yamlConfigLoader:

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

@Module({
  imports: [
    ConfigModule.register({
      isGlobal: true,
      providers: [AppConfig],
      loaders: [yamlConfigLoader("my-yaml-config.yaml")],
    }),
  ],
})
export class AppModule {}

Add prefix to all class properties

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

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

Custom the config name of property

// app.config.ts
import { Configuration, ConfigName } from "@buka/nestjs-config";
import { IsString } from "class-validator";

@Configuration("mysql.master")
export class MysqlConfig {
  // process : process.env.DATABASE_HOST
  // .env    : DATABASE_HOST
  // .json   : { databaseHost: "" }
  @ConfigName("DATABASE_HOST")
  @IsString()
  host: string;
}

@ConfigName(name) will overwrite the prefix of @Configuration([prefix])

Remove warning logs

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

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

ConfigModule.inject(ConfigProvider, DynamicModule[, dynamicModuleOptions])

Simplify the writing of .forRootAsync/.registerAsync.

import { Module } from "@nestjs/common";
import { ConfigModule } from "@buka/nestjs-config";
import { KafkaModule, KafkaModuleOptions } from "@buka/nestjs-kafka";
import { AppConfig } from "./app.config";
import { KafkaConfig } from "./kafka.config";

@Module({
  imports: [
    ConfigModule.register({
      isGlobal: true,
      providers: [AppConfig, KafkaConfig],
    }),

    ConfigModule.inject(KafkaConfig, KafkaModule, { name: "my-kafka" }),
    // this is equal to
    KafkaModule.forRootAsync({
      name: "my-kafka",
      inject: [KafkaConfig],
      useFactory: (config: KafkaModuleOptions) => config,
    }),

    // Mapping KafkaConfig to options of KafkaModule manually
    ConfigModule.inject(
      KafkaConfig,
      KafkaModule,
      // override asyncOptions of KafkaModule
      { name: "my-kafka" },
      // override options of KafkaModule
      (config: KafkaConfig) => ({
        ...config,
        groupId: `prefix_${config.groupId}`,
      })
    ),

    // if you don't need override asyncOptions
    ConfigModule.inject(KafkaConfig, KafkaModule, (config: KafkaConfig) => ({
      ...config,
      groupId: `prefix_${config.groupId}`,
    })),
  ],
})
export class AppModule {}

Package Sidebar

Install

npm i @buka/nestjs-config

Weekly Downloads

70

Version

2.1.1

License

MIT

Unpacked Size

77.6 kB

Total Files

89

Last publish

Collaborators

  • val.istar.guo