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

good-env

v7.1.0

Published

Better environment variable handling for Twelve-Factor node apps

Downloads

845

Readme

good-env

workflow

js-semistandard-style

🚨 v7 requires Node version 18.20.4 or higher! 🚨

good-env provides a more intuitive way to interface with environment variables for node apps. Reasoning about raw strings is OK for some things but for non-trivial applications, booleans, numbers, lists or even the existence (or non-existence) of environment configurations can play a key role in how an application behaves. Lastly, good-env has no production dependencies.

$ npm install good-env --save

With normal process.env

$ export HOST=localhost
$ export SECRET=shhh
$ export FOO=10
$ export A_TRUE_VAL=true
$ export A_FALSE_VAL=false
$ export LIST=foo,bar,bang
$ export ENDPOINT=https://foo.com
$ node
> process.env.FOO
'10'
> process.env.A_TRUE_VAL
'true'
> process.env.A_FALSE_VAL
'false'
> process.env.LIST
'foo,bar,bang'
>

Using good-env

const env = require('good-env')
env.getNumber('FOO') // 10
env.getBool('A_TRUE_VAL') // true
env.getBool('A_FALSE_VAL') // false

Warning Checking the existence of a boolean value which resolves to false will return true because ok() doesn't give you a value.

export A_BOOL_VAL=false
env.ok('A_BOOL_VAL') // true

Specify defaults

env.get('NOT_SET', 'foo') // 'foo'

Batch Gets

env.getAll(['SECRET', 'HOST']) // ['shhh', 'localhost']

// defaults work here too
env.getAll({
  A_SECRET: 'lolz', 
  HOST: null // null means no default
}) // { A_SECRET: 'lolz', HOST: 'localhost' }

Use the first available environment variable

// old and busted
const host = process.env.THE_HOST || process.env.HOST // 'localhost'

// new hotness
const host = env.get(['THE_HOST', 'HOST']) // 'localhost'

// works with defaults
const host = env.get(['THE_HOST', 'A_HOST'], 'localhost') // 'localhost'

Lists

env.getList('LIST') // ['foo', 'bar', 'bang']
env.getList('LIST_NOT_SET') // []

Number Lists

$ export LIST=1,2,3
process.env.LIST // '1,2,3'
env.list('LIST', { cast: 'number' }) // [1, 2, 3]

Sometimes you just need to know if something exists

env.ok('NOT_SET') // false
env.ok('FOO') // true

// works with multiple arguments.
// Returns true if ALL keys exist
env.ok('FOO', 'BAR') // true
env.ok('FOO', 'BAR', 'NOT_SET') // false

Use .assert(item1, item2...) to check the existence and/or type of a few items at once Note: If any variable passed to assert() doesn't exist or is otherwise invalid, an error will be thrown.


env.assert(
    // Will ensure 'HOSTNAME' exists
    'HOSTNAME',
    
    // Will ensure 'PORT' both exists and is a number
    { 'PORT': { type: 'number' }},
    
    // Will ensure 'INTERVAL' exists, it's a number and its value is greater
    // than or equal to 1000
    { 'INTERVAL': { type: 'number', ok: s => s >= 1000 }}
    
    // ... any number of arguments
)

Fetch AWS Credentials

const {
  awsKeyId,
  awsSecretAccessKey,
  awsRegion,
} = env.getAWS();

// Use a default region
const {
  awsKeyId,
  awsSecretAccessKey,
  awsRegion,
} = env.getAWS({ region: 'region' });

Fetch URL objects from url strings

  env.getUrl('ENDPOINT')
  /*
  {
    httpOk: true,
    href: 'https://foo.com/',
    raw: URL {
      href: 'https://foo.com/',
      origin: 'https://foo.com',
      protocol: 'https:',
      username: '',
      password: '',
      host: 'foo.com',
      hostname: 'foo.com',
      port: '',
      pathname: '/',
      search: '',
      searchParams: URLSearchParams {},
      hash: ''
    }  
  }
  */

  env.getUrl('FAKE_ENDPOINT') // null

  // It works with defaults
  env.getUrl('FAKE_ENDPOINT', 'http://localhost:3000')
  /*
  {
    httpOk: true,
    href: 'http://localhost:3000/',
    raw: URL {
      href: 'http://localhost:3000/',
      origin: 'http://localhost:3000',
      protocol: 'http:',
      username: '',
      password: '',
      host: 'localhost:3000',
      hostname: 'localhost',
      port: '3000',
      pathname: '/',
      search: '',
      searchParams: URLSearchParams {},
      hash: ''
    }
  }
  */

About URLs

Why would one use env.getUrl() if one just wishes to grab the url string value? The best reason to use getUrl() and grab the href property is that env.get() doesn't care about the format of the value. Using getUrl() will ensure the url is properly formatted and return a null value if it isn't. In practice, having an invalid url is the same as having no value at all. Then again, it's your code. Do what you want!

As of now, http, redis and postgresql are the only supported protocols. Other protocols will return null. I'm not against adding new protocol support, but these are the ones that seemed most obvious to me. If you want other protocols supported, I'd recommend making a PR. You may create an issue, but I can't guarantee when I'll get around to implementation.

Shortcut Methods

env.num() ==> env.getNumber()
env.bool() ==> env.getBool()
env.list() ==> env.getList()
env.url() ==> env.getUrl()