env-var icon indicating copy to clipboard operation
env-var copied to clipboard

Configure default behavior / Support dotenv-defaults

Open she11sh0cked opened this issue 3 years ago • 4 comments

Is your feature request related to a problem? Please describe. I'm using dotenv-defaults in my projects. This allows you to have your default values in a file called .env.defaults, which are overriden by the .env file. Now because of that the defaults are actually handled by this package and therefore I have to use the required method of your package a lot of times.

import 'dotenv-defaults/config'

import * as env from 'env-var'

export default {
    cms: {
        // has a default, but "required" is added because the resulting
        // type would be "string | undefined" without it
        app: env.get('VIDEOPLAYER__CMS__APP').required().asString(), 
        baseUrl: env.get('VIDEOPLAYER__CMS__BASE_URL').required().asString(),
        
        // here "required" is valid because it doesn't have a default
        password: env.get('VIDEOPLAYER__CMS__PASSWORD').required().asString(),
        username: env.get('VIDEOPLAYER__CMS__USERNAME').required().asString(),
    },
}

Describe the solution you'd like I think a general way to solve this would be a general way to configure the default behaviour:

import 'dotenv-defaults/config'

import { config } from 'env-var'

const env = config({ requiredByDefault: false })

export default {
    cms: {
        app: env.get('VIDEOPLAYER__CMS__APP').asString(), // => string
        baseUrl: env.get('VIDEOPLAYER__CMS__BASE_URL').asString(), // => string
        
        password: env.get('VIDEOPLAYER__CMS__PASSWORD').required().asString(),
        username: env.get('VIDEOPLAYER__CMS__USERNAME').required().asString(),
    },
}

Describe alternatives you've considered This is what I'm currently using, but I think having a general way to configure the default behavior of your package would be more beneficial.

import 'dotenv-defaults/config'

import { get } from 'env-var'

// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
const getEnv = (name: string, required = false) => get(name).required(required)

export default {
    cms: {
        app: getEnv('VIDEOPLAYER__CMS__APP').asString(),
        baseUrl: getEnv('VIDEOPLAYER__CMS__BASE_URL').asString(),
        password: getEnv('VIDEOPLAYER__CMS__PASSWORD', true).asString(),
        username: getEnv('VIDEOPLAYER__CMS__USERNAME', true).asString(),
    },
}

she11sh0cked avatar Oct 13 '21 08:10 she11sh0cked

@she11sh0cked a requiredByDefault seems like a good option to add. I'm thinking the signature of from() can be updated to support an options object instead of a list of args. The function name from() might also be better if it was renamed to config (as you suggested) or build.

import { from, logger } from 'env-var'

const env = from({
  options: { requiredByDefault: true },
  env: process.env,
  extraAccessors: {},
  logger
})

WDYT?

evanshortiss avatar Oct 26 '21 12:10 evanshortiss

Sounds like a good idea! :)

she11sh0cked avatar Oct 26 '21 14:10 she11sh0cked

@evanshortiss Any update on this?

she11sh0cked avatar May 10 '22 12:05 she11sh0cked

@she11sh0cked apologies for the delay. I'm after making some progress on a TypeScript rewrite recently. I will factor this into it too.

evanshortiss avatar Jul 07 '22 22:07 evanshortiss

This is now available in version 8 of the module. Try it using npm install env-var@beta. I'll make an official version 8 release after some more testing.

evanshortiss avatar Dec 25 '22 04:12 evanshortiss