npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@itanium.be/nestjs-dynamic-config

v0.0.11

Published

Hot-reloading drop-in replacement configuration provider for NestJS

Downloads

54

Readme

nestjs-dynamic-config

Drop-in dynamic configuration module for Nest with automatic reload on file update and environment variable substitution

Install

npm install -s  @itanium.be/nestjs-dynamic-config

Usage

create a new Nestjs app

Create a .js or .json configuration file

// <project root>/config.js
exports.default = () => ({
  name: "some-name",
  length: 100,
  database: {
    host: "myHost",
    user: "root",
  },
  environment: '{{ENV_NODE_ENV}}',
  app_name: '{{pkg.name}}',
});

Remark: In this case the configuration file is located in the project's root. In real life you'll probably want your config file to be located in a specific folder so that - when you're deploying in docker containers - you can link to the host filesystem

Define the module in your project's app module

@Module({
  imports: [
    ConfigModule.register({
      configFile: "config.js",
    }),
  ],
  controllers: [
    /* your controllers */
  ],
  providers: [
    /* your providers */
  ],
})
export class AppModule {}

The configuration file location is resolved relative to the project root. You can add path information to the configFile option.
There's plenty more options that can be passed in the register function, most of them work the same like in the original @nestjs/config module.

Use the configuration module in your code

Change the app.controller.ts code to

@Controller()
export class AppController {
  private readonly nameProxy: () => string;

  constructor(private readonly config: ConfigService) {
    this.nameProxy = config.createProxy("name");
  }

  @Get("name")
  getName() {
    return this.nameProxy();
  }

  @Get("db")
  getDb() {
    return this.config.get("database");
  }

  @Get("all")
  getAll() {
    return this.config.config;
  }
}

Run your app and call the API endpoints using your favorite browser. Change the name property in the config file and reload the browser.

This code demonstrates

  • dynamic configuration updating
  • different ways to consume the configuration
  • environment variable substitution

Proxies

The this.nameProxy is a proxy to the "name" configuration element. When the name configuration element in the config file changes, the change is immediately reflected without the need to restart the nest app.

A proxy is created with config.createProxy(configElementName). A second default argument can be passed to createProxy. When the configuration element is not found and a default value was defined then the default value will be returned from the proxy.

A generic parameter can be passed to the createProxy function . f.i. config.createProxy<number>(['wellKnown'.'numbers'.'pi']). If the generic parameter is omitted, string is assumed.

.get<T>(name, default) function

The configService.get(configElementName) can also be used to extract configuration elements. Beware that the information will not be automatically refreshed in this case. Next to the feature of the original, the .get() can also be called with an array of strings that make a path into the configuration object. These statements are equivalent

  config.get<object>('database')['port'];
  config.get<{ port: number }>('database').port;
  config.get<number>('database.host');
  config.get(['database', 3306]); // generic type inferred from `default` value

Variable substitution

Configuration elements defined as {{ENV_xxx}} or {{pkg.xxx}} will be substituted either from environment variables or from the package.json file. For instance, {{ENV_NODE_ENV}} will be substituted with the value of process.env.NODE_ENV, {{pkg.version}} will be substituted with the package version. .env file are loaded with the help of the dotenv package. All the usual naming rules apply for the filenames. Multiple files can be loaded.

Debugging

This module will try it's best to collect all the needed information. It will make a educated guess about where the root folder of your project is located and what .env files exist. This process can fail depending on your project setup. If you experience problems, activate debugging by adding the below options in the .register() function

{
  ...
  debug: true,
  logger: new ConsoleLogger(),
}

Hint: Consolelogger is imported from '@nestjs/common'

Validation

A Joi validation object can be passed to sanitize the configuration. These properties are available

  • validationSchema Joi object
  • validationOptions validation options
  • validationCallback function to be called in case of validation errors

Add this code to your app.module.ts

const validationSchema = Joi.object({
  other: Joi.string().default('my other string'),
});

@Module({
  imports: [
    ConfigModule.register({
      ...
      validationSchema,
      validationOptions: { allowUnknown: true },
      validationCallback: (error: Joi.ValidationError) => console.log(error),
    })],
...
})

Hint: Joi is imported from the 'Joi' module

Restart the Nestjs app and reload the browser. "other": "my other string" will be in the displayed configuration even though it 's not in the configuration file.
That's because it is defined in the validation schema with a default value.

If you comment out the line with validationOptions, an error message will be printed because the configuration file contains (many) elements that are not defined in the validationSchema.

If you also comment out the line where the validationCallback is defined, the program will deliberately crash because it's configuration is not valid.

Crashing your program

This module will purposefully crash your program if the configuration file is not found, when it is not a *.js or *.json file or when validation fails. This is considered the best option because having your program run with missing or invalid configuration will usually be even worse.

To prevent this, you can

  • set validationCallback when you use validation - the validation errors will be sent to the callback instead of printed to the screen (and crashing the program)
  • set onLoadErrorCallback - this callback will be called with the error thrown when attempting to load the configuration file and the program will not crash.