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

@gerkirill/config

v1.0.0

Published

Hierarchical configuration management library based on dotenv.

Downloads

2

Readme

Standard configuration library

This module implements configuration management. The configuration is stored in .env format.

Usage

Installation

npm install @gerkirill/config
import path from 'path';
import { loadEnvConfig } from '@gerkirill/config';
import { Environment } from '../models';

const env = loadEnvConfig(path.resolve(__dirname, '../environment'), Environment);
Example model file
import { IsPort } from '@gerkirill/config';

export class Environment {
  @IsPort()
  API_PORT!: number;
}
Example .env file
API_PORT=3000

Folder with .env files

In the code above - ../environment is a relative path to the environment folder, containing three .env files:

  • .env.default — Contains all env variables. The variables having common values for different environments (prod/qae/int) MUST have a value set. Other variables must be mentioned but have an empty value in this file.
  • .env — Contains only environment-specific variables, e.g. Kafka instance host/login/password. We store credentials for the INT env in this file.
  • .env.local — Empty by default. The file is used for the development at the local machine only. The library guarantees values from these files will not be ever used in the cloud, because Dockerfile contains NODE_ENV=production which makes the library ignore this file.

Configuration files priority

The priority is the following:

  • First - values are read from .env.default.
  • Second - values present in .env override values from .env.default.
  • If NODE_ENV isn't set to production - values from .env.local override values from the previous two files.

Configuration validation

It is important to shut down micro-service early in a case no proper configuration provided. Environment from the example above is a class with class-validator annotations. It is used to validate the configuration. E.g.:

export class Environment {
  @IsPort()
  API_PORT!: number;

  @IsString()
  BUCKET_NAME!: string;
  @IsString()
  BUCKET_PROJECT_ID!: string;
  @IsString()
  @IsUrl()
  BUCKET_PROXY!: string;
}

Configuration transformation

All the values in the env files are strings. But Environment must declare them with a proper target type, which could be e.g. number or array of strings. To convert strings to some other representation here is a @Transform annotation provided by the class-transformer. The annotation is re-exported by the @gerkirill/config library. But in order to perform some widely-used transformations - the @gerkirill/config library declares more helper functions, like @Split and @ParseInt:

import { ParseInt, Split, Contains, EACH } from '@gerkirill/config';

export class Environment {
  @ParseInt()
  S3_PART_SIZE!: number;

  @Contains(':', EACH)
  @Split(',')
  KAFKA_BROKERS!: string[];
}

Above you can also see EACH constant, defined by the @gerkirill/config library. It is just a handy shortcut to { each: true } flag used to instruct class validator to apply the rule to each element in the array.

Reasons behind the three .env files

.env.default

API_PORT=5000

BUCKET_NAME=
BUCKET_PROJECT_ID=
BUCKET_PROXY=

.env file exists for two main reasons:

  1. It contains a full list of all config options available. As we have three configuration files - gathering a list of all options required - can be a hard task for the DevOps. Assuming each file has a set of config options, which may (or may not) overlap with options in other files.

  2. It provides default values for the options which aren't environment-specific. This point has two pros. DevOps can write less configuration, in order to provide only environment-specific values. And developers can change default values in one place, w/o the need to update each env-specific configuration in helm files. Even more - no helm update required at all in order to add or change a default value.

.env

This file contains options having environment-specific values. e.g. resource URLs, usernames, passwords (assuming they are different across environments).

BUCKET_NAME=int-ba-origin.sinclairplatform.com
BUCKET_PROJECT_ID=common-int
BUCKET_PROXY=https://int-ba-gateway.sinclairplatform.com

IMPORTANT! We store only INT environment values here, including usernames and passwords. The reason for that is an easy development process. E.g. to develop micro-service locally - the developer just needs to clone the repository, install dependencies and execute npm start. The micro-service will connect to the INT environment and will be up and running in seconds.

Values for the other environments are set in corresponding .helm files. Secret information, like e.g. passwords and keys - can be stored in some kind of secrets store.

.env.local

Sometimes when you develop locally - you need to adjust some config parameters. E.g. if you want to connect to the local Redis instance instead of the one in INT environment.

Changing .env or .env.default can be dangerous - the changes can be committed to git accidentally, leak to the cloud environment and break something. Despite we keep env.local empty in git (not ignored, just empty) - even if you commit the changes - nothing will happen in the cloud. That's because in the cloud the code is executed in a docker container, which is configured like that:

ENV NODE_ENV=production

And the library ignores env.local in the production environment.