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

envstore

v0.1.1

Published

Load casted environment variables or throw if they don't exist

Downloads

5

Readme

CircleCI codecov Prettier License: MIT

Your application requires Environment Variables. You must know if they have been setup properly before the application starts.

Envstore was made to help engineers like yourself to identify as soon as possible that the application is about to operate in an misconfigured environment. This saves countless debugging hours.

  • Zero dependencies
  • 100% test coverage
  • Typescript

Problem (use case)

You application sends email when your users signup and you forgot to setup the API_KEY of your email service provider. You'll find out about this problem after having some new users sadly not getting signup emails.

Solution

Check all environment variables required by your application before it starts running.

API

import Envstore from 'envstore'

const env = new Envstore(process.env)

// -- The basics --

env.array('ENV_VAR_NAME') // 'a,b,c' => ['a', 'b', 'c']

env.boolean('ENV_VAR_NAME') // 'true' or '1' => true | 'false' or '0' => false

env.float('ENV_VAR_NAME') // '2.5' => 2.5

env.integer('ENV_VAR_NAME') // '10' => 10

env.json('ENV_VAR_NAME') // '{"x":5}' => {x: 5}

env.string('ENV_VAR_NAME') // 'text' => 'text'

// All basic methods support a second argument as default value, for example:

env.string('USER', 'root') // If there is no `USER` in the environment variables, `root` is assigned


// -- Set variables per environment --

env.pick('ENV_VAR_NAME', {
  development: prop => env.string(prop)
}, prop => env.string(prop))


// -- ADVANCED: Dynamically configure your environment variables --

env.setup({
  production: (env) => {
    // Load your secrets from a configuration repository
    const secrets = ...

    // Merge secrets into Envstore
    env.merge(secrets)
  }
})

Use

Basic

// config.js
import Envstore from 'envstore'

const env = new Envstore(process.env, process.env.NODE_ENV || 'development')

const config = {
  PORT: env.integer('PORT'),
  AUTH: env.boolean('AUTH', true) // default = true
}

export default config

In the config.js above we're specifying the following:

Variable | Cast | Comments -- | -- | -- PORT | integer | required (no default value) AUTH | boolean | not required (default = true), accept only '1', 'true', '0', 'false'

Note: Environment variables in NodeJS are string or undefined. However, Envstore takes a step further and let you cast those variables for later use.

Import your config file in your application the way you like:

import config from './config'
console.log(config.PORT) // => number
console.log(config.AUTH) // => boolean

Multiple Environments

Now you want to run your application in development and test mode in your local machine. Let's setup those environments:

const config = {
  URI: env.pick('URI', {
    development: () => 'http://localhost:3000',
    test: () => 'http://localhost:4000'
  }, prop => env.string(prop))
}

When you run you application in test mode NODE_ENV=test, you will see this result:

// app.js
import config from './config'
console.log(config.HOST) // => http://localhost:4000

Default Values

In the example below, all environments will use URI = 'http://localhost:3000' except the production environment that will use URI = 'https://mysite.com'.

const config = {
  URI: env.pick('URI', {
    production: () => 'https://mysite.com'
  }, () => 'http://localhost:3000')
}

Custom Defaults

You work on a tem of developers and want to specify your own defaults without breaking others workflow. Overwrite the default value by the URI in your local environment.

const config = {
  URI: env.pick({
    production: () => 'https://mysite.com'
  }, () => env.string('URI', 'http://localhost:3000')
}

Advanced

Do you use IoC (Inversion of Control) and Dependency Injection? This section is for you.

Let's assume you are a professional engineer that cares about your database credentials and is aware that hosting them in the Environment Variable is not the safest option. Credentials repository and dynamic configuration to the rescue.

If you are interested in this topic, check out AWS Secrets Manager.

A more robust implementation of your config file is presented below:

  // config.js
  import Envstore from 'envstore'

  export default class Config {
    env

    readonly database = {
      username: undefined,
      password: undefined,
    }

    async setup() {
      this.env = new Envstore(process.env, process.env.NODE_ENV || 'development')

      await this.env.setup({
        production: async () => {
          // Load your secrets from a configuration repository
          const secrets = ...

          // Merge secrets into Envstore
          env.merge(secrets)
        }
      })
    }
  }