Code Monkey home page Code Monkey logo

dotenv-expand's Introduction

🎉 announcing dotenvx. run anywhere, multi-environment, encrypted envs.

 

dotenv-expand NPM version

dotenv-expand

Dotenv-expand adds variable expansion on top of dotenv. If you find yourself needing to expand environment variables already existing on your machine, then dotenv-expand is your tool.

js-standard-style LICENSE codecov

Install

# Install locally (recommended)
npm install dotenv-expand --save

Or installing with yarn? yarn add dotenv-expand

Usage

Create a .env file in the root of your project:

PASSWORD="s1mpl3"
DB_PASS=$PASSWORD

As early as possible in your application, import and configure dotenv and then expand dotenv:

const dotenv = require('dotenv')
const dotenvExpand = require('dotenv-expand')

dotenvExpand.expand(dotenv.config())

console.log(process.env) // remove this after you've confirmed it is expanding

That's it. process.env now has the expanded keys and values you defined in your .env file.

dotenvExpand.expand(dotenv.config())

...

connectdb(process.env.DB_PASS)

Preload

Note: Consider using dotenvx instead of preloading. I am now doing (and recommending) so.

It serves the same purpose (you do not need to require and load dotenv), has built-in expansion support, adds better debugging, and works with ANY language, framework, or platform. – motdotla

You can use the --require (-r) command line option to preload dotenv & dotenv-expand. By doing this, you do not need to require and load dotenv or dotenv-expand in your application code. This is the preferred approach when using import instead of require.

$ node -r dotenv-expand/config your_script.js

The configuration options below are supported as command line arguments in the format dotenv_config_<option>=value

$ node -r dotenv-expand/config your_script.js dotenv_config_path=/custom/path/to/your/env/vars

Additionally, you can use environment variables to set configuration options. Command line arguments will precede these.

$ DOTENV_CONFIG_<OPTION>=value node -r dotenv-expand/config your_script.js
$ DOTENV_CONFIG_ENCODING=latin1 node -r dotenv-expand/config your_script.js dotenv_config_path=/custom/path/to/.env

Examples

See tests/.env.test for simple and complex examples of variable expansion in your .env file.

Documentation

dotenv-expand exposes one function:

  • expand

Expand

expand will expand your environment variables.

const env = {
  parsed: {
    BASIC: 'basic',
    BASIC_EXPAND: '${BASIC}',
    BASIC_EXPAND_SIMPLE: '$BASIC'
  }
}

console.log(dotenvExpand.expand(env))

Options

processEnv

Default: process.env

Specify an object to write your secrets to. Defaults to process.env environment variables.

const myEnv = {}
const env = {
  processEnv: myEnv,
  parsed: {
    HELLO: 'World'
  }
}
dotenvExpand.expand(env)

console.log(myEnv.HELLO) // World
console.log(process.env.HELLO) // undefined

FAQ

What rules does the expansion engine follow?

The expansion engine roughly has the following rules:

  • $KEY will expand any env with the name KEY
  • ${KEY} will expand any env with the name KEY
  • \$KEY will escape the $KEY rather than expand
  • ${KEY:-default} will first attempt to expand any env with the name KEY. If not one, then it will return default
  • ${KEY-default} will first attempt to expand any env with the name KEY. If not one, then it will return default

You can see a full list of rules here.

How can I avoid expanding pre-existing envs (already in my process.env, for example pas$word)?

Modify your dotenv.config to write to an empty object and pass that to dotenvExpand.processEnv.

const dotenv = require('dotenv')
const dotenvExpand = require('dotenv-expand')

const myEnv = dotenv.config({ processEnv: {} }) // prevent writing to `process.env`

dotenvExpand.expand(myEnv)

Contributing Guide

See CONTRIBUTING.md

CHANGELOG

See CHANGELOG.md

Who's using dotenv-expand?

These npm modules depend on it.

dotenv-expand's People

Contributors

c1moore avatar chatcher avatar dependabot[bot] avatar devule avatar ericrallen avatar felixmosh avatar fezvrasta avatar flamewow avatar guyathomas avatar iansu avatar javiacei avatar legendar avatar lnasc256 avatar logikgate avatar mauriciobraz avatar mfaheemakhtar avatar michaeldeboey avatar mikailbag avatar motdotla avatar mrsteele avatar paramsiddharth avatar tizmagik avatar vantreeseba avatar wormss avatar yeti-or avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

dotenv-expand's Issues

Bring your own `process.env`

ignoreProcessEnv: true is great, though undocumented 🙈, because we can prevent mutating process.env.

Sadly this option has the effect that we cannot interpolate variables across different files. Something that is quite convenient in a dotenv setup like .env.local, …, .env.

Ideally this option would be useProcessEnv: boolean | object instead of ignoreProcessEnv: boolean so we can loop over the seperate dotenv files without modifying process.env and without loosing the ability to refer variables across the files.

# .env.local
NAME="Dieter"
# .env
ADMIN="${NAME}"
const dotenv = require('dotenv');
const expand = require('dotenv-expand');

const env = {};
expand(dotenv.config({ path: '.env.local' }), { ignoreProcessEnv: true, useProcessEnv: env });
expand(dotenv.config({ path: '.env' }), { ignoreProcessEnv: true, useProcessEnv: env });

// Expected
// assert.ok(env.ADMIN === 'Dieter');

Document breaking changes of v10

Changelog just mentions that "Support special characters in default expansion" was added, which doesn't look as breaking change.

If there were breaking changes. Ideally if there's a BREAKING CHANGES section explaining what's breaking exactly

Allow disabling `$xxx` expansion

This feature would be very useful for me.

In CapRover the environment variables don't need a \ to mark dollar signs that aren't expansions, so whenever I have to move environment variables from CapRover to local I need to find all $ and add a \ before them, which is annoying and error-prone.

Also, this would allow variable expansion to be aligned with the usage of backticks in Javascript:

const MY_VAR = 123;

console.log(`hello$world`); // hello$world
console.log(`hello${MY_VAR}world`); // hello123world
console.log(`hello\${MY_VAR}world`); // hello${MY_VAR}world

While if I try the same in dotenv-expand:

MY_VAR=123

TEST1=hello$world # hello
TEST2=hello${MY_VAR}world # hello123world
TEST3=hello\${MY_VAR}world # hello${MY_VAR}world

empty environment variables cause error

Got the following error:

ERROR TypeError: Cannot read property 'match' of undefined
TypeError: Cannot read property 'match' of undefined
at interpolate (D:\EnviDat\Frontend\envidat_frontend\node_modules\dotenv-expand\lib\main.js:10:28)
at dotenvExpand (D:\EnviDat\Frontend\envidat_frontend\node_modules\dotenv-expand\lib\main.js:54:32)
at load (D:\EnviDat\Frontend\envidat_frontend\node_modules@vue\cli-service\lib\Service.js:102:9)
at Service.loadEnv (D:\EnviDat\Frontend\envidat_frontend\node_modules@vue\cli-service\lib\Service.js:114:5)
at Service.init (D:\EnviDat\Frontend\envidat_frontend\node_modules@vue\cli-service\lib\Service.js:70:10)
at Service.run (D:\EnviDat\Frontend\envidat_frontend\node_modules@vue\cli-service\lib\Service.js:209:10)
at Object. (D:\EnviDat\Frontend\envidat_frontend\node_modules@vue\cli-service\bin\vue-cli-service.js:36:9)
at Module._compile (module.js:643:30)
at Object.Module._extensions..js (module.js:654:10)
at Module.load (module.js:556:32)
at tryModuleLoad (module.js:499:12)
at Function.Module._load (module.js:491:3)
at Function.Module.runMain (module.js:684:10)
at startup (bootstrap_node.js:187:16)
at bootstrap_node.js:608:3

I've tested it with the current version like so:

  1. cloned the repo
  2. npm install
  3. npm run test
  4. Added additional empty variable in test/.env like so:
    BASIC=basic
    BASIC_EMPTY=
    BASIC_EXPAND=$BASIC
  5. npm run test again: 8 of 19 Tests failed.

Possible recursive expansion regression

After upgrading from 10.0 to latest 11.0.3

the following .env

BACKEND_API_HEALTH_CHECK_URL=${MOCK_SERVER_HOST}/ci-health-check
...
MOCK_SERVER_HOST=http://localhost:${MOCK_SERVER_PORT}
MOCK_SERVER_PORT=8090

parsed by this script

expand(dotenv.config({ path: path.resolve(root, '.env') }))

console.log('env', process.env)

is not recursively expanded anymore. Now it produces the following result:

BACKEND_API_HEALTH_CHECK_URL: 'http://localhost:${MOCK_SERVER_PORT}/ci-health-check',
...
MOCK_SERVER_HOST: 'http://localhost:8090',
MOCK_SERVER_PORT: '8090',

Possible recursive expansion regression (3)

Sorry to bother you again

While upgrading from 10.0 to latest 11.0.6

the following .env

FIRST_PAGE_URL=${PROJECT_PUBLIC_HOST}/first-page

...
MOCK_SERVER_HOST=http://localhost:${MOCK_SERVER_PORT}
MOCK_SERVER_PORT=8090

PROJECT_PUBLIC_HOST=${MOCK_SERVER_HOST}

parsed by this script

expand(dotenv.config({ path: path.resolve(root, '.env') }))

console.log('env', process.env)

is not recursively expanded anymore. Now it produces the following result:

FIRST_PAGE_URL: '${MOCK_SERVER_HOST}/first-page',
...
MOCK_SERVER_HOST: 'http://localhost:8090',
MOCK_SERVER_PORT: '8090',

PROJECT_PUBLIC_HOST='http://localhost:8090'


Can't handle bcrypt password structure

Hi,

I've encountered with a weird bug, I've a bcrypt pass that looks like that $2b$10$OMZ69gxxsmRgwAt945WHSujpr/u8ZMx.xwtxWOCMkeMW7p3XqKYca (it is not a real pass 😁), I've escaped the $ sign \$2b\$10\$OMZ69gxxsmRgwAt945WHSujpr/u8ZMx.xwtxWOCMkeMW7p3XqKYca it falls to the first condition, and therefore it returns $2b\$10\$OMZ69gxxsmRgwAt945WHSujpr/u8ZMx.xwtxWOCMkeMW7p3XqKYca that is wrong.

I don't think that it is a good solution to escape only the first $, which will work till it won't.

So, I will make a PR for more robust solution.

Incorrectly expands `$` instead of `${}`

Package tries to erroneously expand any $ while it should only expand variables ${}

Input:

DATABASE_URL="postgres://user:[email protected]:5432/database?ssl=1&schema=schema$1234"

Expected:

DATABASE_URL => postgres://user:[email protected]:5432/database?ssl=1&schema=schema$1234

Actual result:

DATABASE_URL => postgres://user:[email protected]:5432/database?ssl=1&schema=schema

Fix: https://github.com/prisma/prisma/blob/acbd91a6c517d08f4850b4d2f6794d3773710a29/src/packages/sdk/src/dotenvExpand.ts

Last change broke something

RPS_SCRIPT=${PEXEC} \${REMOTE_SERVER_IP} -u ${REMOTE_SERVER_USER} -P ${REMOTE_SERVER_PASSWORD} -i cmd /c ${RPS_SCRIPT_PATH}

RPS_SCRIPT does not get resolved. Seems \\ is affecting dotenv-expand and is preventing interpolation

It is not working for angle bracket substition

I tried your code but it is not working

MONGOLAB_URI=mongodb://${MONGOLAB_USER}:${MONGOLAB_PASSWORD}@${MONGOLAB_DOMAIN}:${MONGOLAB_PORT}/${MONGOLAB_DATABASE}

still shows

MONGOLAB_URI=mongodb://${MONGOLAB_USER}:${MONGOLAB_PASSWORD}@${MONGOLAB_DOMAIN}:${MONGOLAB_PORT}/${MONGOLAB_DATABASE}

ONLY BASIC_EXPAND=$BASIC can be converted.

Possible double-recursive expansion regression

In addition to #117, there is also a breaking change when referencing a "real" env variable from a .env file.

For example:

Variable (set in docker environment):
APP_DOMAIN=example.com

Variable (set in .env):
BASE_URL=https://${APP_DOMAIN}/api/

Results in https://${APP_DOMAIN}/api/.
In v10 it was correct: https://example.com/api/

Why use two loops?

for (var configKey in config.parsed) {

for (var processKey in config.parsed) {

Why use two loops? I think one can be used.

  for (var configKey in config.parsed) {
    var value = environment.hasOwnProperty(configKey) ? environment[configKey] : config.parsed[configKey]

    config.parsed[configKey] = interpolate(value)
  }

  for (var processKey in config.parsed) {
    environment[processKey] = config.parsed[processKey]
  }

supporting expansion while simultaneously supporting passwords with `$` in them (common in generated passwords like postgres)

Hi! I reported an issue to serverless but then found that dotenv-expand is actually causing the problem.

The problem is:

  • if database password contains $ inside - piece of password disappears after dotenv-expand is applied
  • if process.env.POSTGRESQL_PASSWORD is ab$defghijk
    • as a result I have POSTGRESQL_PASSWORD=ab ($defghijk disappeared)
  • if process.env.POSTGRESQL_PASSWORD is ab$defgh@jk
    • as a result I have POSTGRESQL_PASSWORD=ab@jk ($defgh disappeared)

How to reproduce

Create an .env file with this content:

POSTGRESQL_DATABASE=some_db
POSTGRESQL_HOST=some_host
POSTGRESQL_PASSWORD="ab$defgh@jk"
POSTGRESQL_USERNAME=some_user

And create test.js file with this content:

const dotenv = require('dotenv');
const dotenvExpand = require('dotenv-expand');

const config = dotenv.config({ path: './.env' });
console.log(dotenvExpand.expand(config));

Run node test.js and you'll see that POSTGRESQL_PASSWORD="ab@jk" ($defgh disappeared)

Possible solutions

Is it possible to provide some option to 'dotenv-expand' so that it does nothing if variable $defgh does not exist?
Currently it replaces it by empty string.

Variables names bug

I have a bug when i create .env file like this:

DB=mydb
DB_HOST=localhost
DB_URL=postgres://postgres:myPass@$DB_HOST:5432/$DB

i have a output, like this:

postgres://postgres:myPass@mydb_HOST:5432/mydb

expand see "DB" case and use it in all places where start is "DB", when i change this to "DB_SOMETHING" that's working good, that's issue with regex IMO.

Can we use only `${}` instead of `$xxx`?

Some sensitive data like Database password might be possible to contain the special char like $. It transformed to white-space instead of the original characters. So, Is it possible to enforce and use only one replacement pattern like ${xx}?

Strange handling $ONE$TWO

Consider the following env file:

NO_NO="NO_NO: $NO$NO"
YES_NO="YES_NO: $YES$NO"
YES_YES="YES_YES: $YES$YES"
NO_YES="NO_YES: $NO$YES"
YES_YESS="YES_YESS: $YES$YESS"

When NO is not defined and YES and YESS are defined, this results in:

NO_NO: 
YES_NO: yes
YES_YES: yesyes
NO_YES: 
YES_YESS:

In other words, if ONE and TWO are both defined, $ONE$TWO evaluates to undefined.
This is highly unintuitive.
I expect both variables to be expanded in this case.

As a workaround, ${ONE}${TWO} works as expected.

Version: 10.0.0

This used to work with 5.1.0.

Error when declaring a variable referencing itself: X="$X"

Apologies if this is a known issue or I've missed something here.

I'm on macOS Monterey 12.2.1, node v17.1.9, and dotenv-expand 8.0.1 and was trying to convert a Bash script to dotenv's format.

I ran into an issue with:

DIST="${DIST:-$PWD/dist/lib}"

Unfortunately, this doesn't seem to work either:

TEMP="${DIST:-$PWD/dist/lib}"
DIST="$TEMP"

I was expecting for the variable DIST to be defined to "./dist/lib" if it wasn't already defined.

I was surprised to discover something as simple as DIST="$DIST" produces the same error:

"RangeError: Maximum call stack size exceeded" on "dotenv-expand/lib/main.js:7:53"

How to escape `${}`

I would like to use a variable that contains literally ${id}. Is there a way to escape it so that it does not try to expand it?

So if I have in .env URL=https://devices/${id}/users when I read URL in code I get https://devices//users due to the expansion (and no id variable present).

How could I get literally https://devices/${id}/users from URL using this library?

Usage produces fatal error when .env file defines a variable with same name as expanded variable.

When I have a .env file like this, everything works fine:

MY_VAR_1=$MY_VAR

But this breaks:

MY_VAR_1=$MY_VAR
MY_VAR_2=$MY_VAR_2

This line causes the breakage:

MY_VAR_2=$MY_VAR_2

Somehow the library cannot handle this situation.

Error produced:

/Users/<REDACTED>/flourish-node-api/node_modules/dotenv-expand/lib/main.js:6
  return matches.reduce(function (newEnv, match, index) {
                 ^
RangeError: Maximum call stack size exceeded
    at RegExp.exec (<anonymous>)
    at /Users/<REDACTED>/flourish-node-api/node_modules/dotenv-expand/lib/main.js:7:54
    at Array.reduce (<anonymous>)
    at _interpolate (/Users/<REDACTED>/flourish-node-api/node_modules/dotenv-expand/lib/main.js:6:18)
    at /Users/<REDACTED>/flourish-node-api/node_modules/dotenv-expand/lib/main.js:36:15
    at Array.reduce (<anonymous>)
    at _interpolate (/Users/<REDACTED>/flourish-node-api/node_modules/dotenv-expand/lib/main.js:6:18)
    at /Users/<REDACTED>/flourish-node-api/node_modules/dotenv-expand/lib/main.js:36:15
    at Array.reduce (<anonymous>)
    at _interpolate (/Users/<REDACTED>/flourish-node-api/node_modules/dotenv-expand/lib/main.js:6:18)

Someone has already faced this issue and documented it somewhat:
https://stackoverflow.com/questions/49287598/maximum-call-stack-size-exceeded-from-dotenv-expand-on-circleci-using-react

You might ask the question: Why?

  • To that I would respond: Why not? Why does it matter how people use it?
  • And I would add: It is a form of documentation, in case other developers use different variable names to expand than me.
  • Pretty please, fix this.
  • It took so long to stumble onto why this is happening.
  • I was using this lib to save time, and pain.... :/

Using these versions:

    "dotenv": "14.1.0",
    "dotenv-expand": "^9.0.0", <--- And tried v10 (latest), same outcome.

TypeError: Cannot read properties of undefined (reading 'split')

[0] D:\dev\REDACTED\node_modules\dotenv-expand\lib\main.js:20
[0]       const keyParts = parts[2].split(':-')
[0]                                 ^
[0] 
[0] TypeError: Cannot read properties of undefined (reading 'split')
[0]     at D:\dev\REDACTED\node_modules\dotenv-expand\lib\main.js:20:33
[0]     at Array.reduce (<anonymous>)
[0]     at _interpolate (D:\dev\script\publiek\node_modules\dotenv-expand\lib\main.js:6:18)
[0]     at Object.expand (D:\dev\script\publiek\node_modules\dotenv-expand\lib\main.js:50:32)
[0]     at Object.<anonymous> (D:\dev\script\publiek\bs-config.js:1:26)    
[0]     at Module._compile (node:internal/modules/cjs/loader:1120:14)      
[0]     at Module._extensions..js (node:internal/modules/cjs/loader:1174:10)
[0]     at Module.load (node:internal/modules/cjs/loader:998:32)
[0]     at Module._load (node:internal/modules/cjs/loader:839:12)
[0]     at Module.require (node:internal/modules/cjs/loader:1022:19)       
[0]
[0] Node.js v18.7.0

If I remove the following environment variables, it doesn't throw the error:

AUTH_KEY='.kZh`>4[,[DDU-*Jt+[;8-,@K=,9%;F9KsoXqOE)gpG^X!{)Q+/9Fc(QF}i[NEi!'
SECURE_AUTH_KEY='=;+=CNy3)-D=zI6gRP2w$B@0K;Y]e^EFnCmx$Dx?;.9wf-rgk1BcTR0]JtY<S:b_'
LOGGED_IN_KEY='MUcKSGSY@HCON<1S_siWTP`DgS*Ug],mu]SkqI|7V2eOk9:>&fw;>HEwms`D8E2H'
NONCE_KEY='m]zjzfRItw2gs[2:{p{ugENyFw9m)tH6_VCQzer`*noVaI<vqa3?FZ9+6U;K#Bfd'
AUTH_SALT='#la__nK?IxNlQ%`5q&DpcZ>Munx=[1-AMgAcwmPkToxTaB?kgdF5y`A8m=Oa-B!)'
SECURE_AUTH_SALT='xlC&*<j4J<d._<JKH0RBJV!4(ZQEN-+&!0p137<g*hdY2H4xk?/;KO1$(W{:Wc}Q'
LOGGED_IN_SALT='?$6)m*xhTVewc#NVVgxX%eBhJjoHYzpXFg=gzn[rWXPLj5UWj@z$/UDm8o79n/p%'
NONCE_SALT='@}:[4#g%[R-CFR});bY(Z[KcDQDsVn2_y4cSdU<Mjy!c^F`G<!Ks7]kbS]N1:bP:'

require from command line does not work

#31 seems to have introduced a bug.

When I try to use node -r dotenv-expand/config, it throws following error

❯ node -r dotenv-expand/config
Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: Package subpath './lib/env-options' is not defined by "exports" in /home/projects/node-bdyl5f/node_modules/dotenv/package.json
    at throwExportsNotFound (https://node-bdyl5f.w.staticblitz.com/blitz.d64d45524a435df425e7813603b52872ecfbe08e.js:6:488525)
    at packageExportsResolve (https://node-bdyl5f.w.staticblitz.com/blitz.d64d45524a435df425e7813603b52872ecfbe08e.js:6:491222)
    at resolveExports (https://node-bdyl5f.w.staticblitz.com/blitz.d64d45524a435df425e7813603b52872ecfbe08e.js:6:182519)
    at Function.Module._findPath (https://node-bdyl5f.w.staticblitz.com/blitz.d64d45524a435df425e7813603b52872ecfbe08e.js:6:183031)
    at Function.Module._resolveFilename (https://node-bdyl5f.w.staticblitz.com/blitz.d64d45524a435df425e7813603b52872ecfbe08e.js:6:188095)
    at Function.Module._load (https://node-bdyl5f.w.staticblitz.com/blitz.d64d45524a435df425e7813603b52872ecfbe08e.js:6:185865)
    at Module.require (https://node-bdyl5f.w.staticblitz.com/blitz.d64d45524a435df425e7813603b52872ecfbe08e.js:6:189078)
    at i (https://node-bdyl5f.w.staticblitz.com/blitz.d64d45524a435df425e7813603b52872ecfbe08e.js:6:443011)
    at _0x4248b4 (https://node-bdyl5f.w.staticblitz.com/blitz.d64d45524a435df425e7813603b52872ecfbe08e.js:15:95063)
    at eval (/home/projects/node-bdyl5f/node_modules/dotenv-expand/config.js:6:7) {
  code: 'ERR_PACKAGE_PATH_NOT_EXPORTED'
}

This is due to lib/cli-options and lib/env-options are not exported from dotenv.

After monkey patching the exports under node_modules/dotenv/package.json with exports: {"./lib/*": "./lib/*.js"} I get another error

❯ node -r dotenv-expand/config
Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: Package subpath './lib/env-options' is not defined by "exports" in /home/projects/node-bdyl5f/node_modules/dotenv/package.json
    at throwExportsNotFound (https://node-bdyl5f.w.staticblitz.com/blitz.d64d45524a435df425e7813603b52872ecfbe08e.js:6:488525)
    at packageExportsResolve (https://node-bdyl5f.w.staticblitz.com/blitz.d64d45524a435df425e7813603b52872ecfbe08e.js:6:491222)
    at resolveExports (https://node-bdyl5f.w.staticblitz.com/blitz.d64d45524a435df425e7813603b52872ecfbe08e.js:6:182519)
    at Function.Module._findPath (https://node-bdyl5f.w.staticblitz.com/blitz.d64d45524a435df425e7813603b52872ecfbe08e.js:6:183031)
    at Function.Module._resolveFilename (https://node-bdyl5f.w.staticblitz.com/blitz.d64d45524a435df425e7813603b52872ecfbe08e.js:6:188095)
    at Function.Module._load (https://node-bdyl5f.w.staticblitz.com/blitz.d64d45524a435df425e7813603b52872ecfbe08e.js:6:185865)
    at Module.require (https://node-bdyl5f.w.staticblitz.com/blitz.d64d45524a435df425e7813603b52872ecfbe08e.js:6:189078)
    at i (https://node-bdyl5f.w.staticblitz.com/blitz.d64d45524a435df425e7813603b52872ecfbe08e.js:6:443011)
    at _0x4248b4 (https://node-bdyl5f.w.staticblitz.com/blitz.d64d45524a435df425e7813603b52872ecfbe08e.js:15:95063)
    at eval (/home/projects/node-bdyl5f/node_modules/dotenv-expand/config.js:6:7) {
  code: 'ERR_PACKAGE_PATH_NOT_EXPORTED'
}

This requires changes in the following line of config.js

return dotenvExpand(env) => return dotenvExpand.expand(env).

After this, the command works out fine.

The issue can be reproduced here

Expansion issues

Using your test .env file

var dotenv = require('dotenv')
var dotenvExpand = require('dotenv-expand')
var config = dotenv.config();
dotenvExpand(config);
console.log(process.env.MONGOLAB_URI)

--
mongodb://${MONGOLAB_USER}:${MONGOLAB_PASSWORD}@${MONGOLAB_DOMAIN}:${MONGOLAB_PORT}/${MONGOLAB_DATABASE}

Win 8.1
Node: 6.10.0
dotenv: 2.0.0
dotenv-expand: 4.0.1

Bracket notation with default does not work with /

For example:

DIST=${APP:-/dist}

Currently, DIST will evaluate to "/dist}" instead of the expected "/dist".

Since there is just a one character difference, this could be a pretty easily missed error. Perhaps this notation should be discouraged?

Not using the bracket notation works fine:

DIST=$APP:-/dist

Can this be used on existing env variables on the system (not via .env)

The project description mentions "If you find yourself needing to expand environment variables already existing on your machine, then dotenv-expand is your tool."

And after my exploration it seems like it's not for already existing environment variables. Raising this issue for confirmation on the same, is the description supposed to be "If you find yourself needing to expand environment variables already existing on your machine, then dotenv-expand is NOT your tool."?

Or is there a way to use this for already existing environment variables.

default value not working if value includes colon (or other special chars)

The following configuration:

const dotenv = {
  parsed: {
    BASIC: 'basic',
    BASIC_EXPAND: '${BASIC:-foo:bar}',
    MISSING_EXPAND: '${MISSING:-foo:bar}',
  }
};

console.log(dotenvExpand.expand(dotenv));

Results in:

{
  parsed: {
    BASIC: "basic",
    BASIC_EXPAND: "basic:bar}",
    MISSING_EXPAND: "foo:bar}"
  }
} 

As you can see there's a problem where $BASIC is defined and its default value includes a colon in it.

Escaping the colon with \: doesn't have any effect.

[HELP] Variables names

Hello!, I'm seeking for help while i'm doing something useless but having fun. It is possible to actually name a variable coming from another? something like this:

## Database Variables
HOST=${DB_HOST}
PORT=${DB_PORT}
USER=${DB_USER}
PASS=${DB_PASS}
DB=${DB_DB}

## Generate variables using Database Variables
${HOST} = localhost

Dosn't work with node -r

../
./
lib/
CHANGELOG.md
LICENSE
README.md
package.json
~

"node_modules/dotenv-expand/"

there is no config.js file in tar

  "version": "6.0.1"

Allow to use env variables with '.' in it's name (i.e. REDIS.PUBSUB.PORT)

currently, if I want to use a variable whose name contains "." (e.g. REDIS.PUBSUB.PORT) the lib is not working.

Should be as simple as changing regex to allow "."

  const matches = envValue.match(/(.?\${*[\w\.]*(?::-[\w/]*)?}*)/g) || []

  return matches.reduce(function (newEnv, match, index) {
    const parts = /(.?)\${*([\w\.]*(?::-[\w/]*)?)?}*/g.exec(match)
    if (!parts || parts.length === 0) {
      return newEnv
    }

Env var expansion breaking change in versions 11.0.3 - 11.0.6 affecting Vite

Hello dear maintainers,

we were using env expansion references without braces for a kebab-cased values, which are now broken.

This breaking change were brought with [email protected] patch published recently, as the dotenv-expand dependency got updated ^10.0.0 to ^11.0.3.

The breaking change seems to be made intentionally to allow default values in substitutions without braces, which stops me from opening a PR.

In any case, it brakes any content in kebab case, as everything after the substitution is dropped.

Reproduction

Here's the lightweight reproduction you can try:
https://stackblitz.com/edit/stackblitz-starters-p3yqwk?file=.env

Given following .env file as example:

# .env
SOURCE=12345
EXPANDED=ab-$SOURCE-cd-ef-gh

Expected behaviour, as of dotenv-expand@<=11.0.2 and Vite@<=5.1.1:

console.log(import.meta.env.EXPANDED) // ab-12345-cd-ef-gh

Actual result for dotenv-expand@>=11.0.3 Vite@>=5.1.2:

console.log(import.meta.env.EXPANDED) //ab-12345

the -cd-ef-gh parts is missing now

Possibly related issues

I was able to find issues #117 (fixed with 11.0.4), #120 (fixed in (11.0.5) and #123.
Meanwhile, none of them mentioned the case with trailing content after the env variable reference.

Affected versions

All mentions versions is affected:

  • 11.0.3
  • 11.0.4
  • 11.0.5
  • 11.0.6

This particular case was working fine for 11.0.0 - 11.0.3 and for ^10.0.0

Syntax collision with 'default values'

This breaking change seems to be an intentional feature, as I can see via tests

Although, I can't agree with such a behaviour because:

  • That breaking change could be easily avoided
  • It doesn't seems to be a standard syntax, example with bash:
    sh-5.2$ echo "$SHELL-extra"
    /bin/bash-extra
    
  • For me it sounds that default variables have to be always go within braces, to make it bullet-proof for both, the users and the implementation, as the implementation should be easy to avoid ReDoS

TypeError: Cannot read property 'split' of undefined

A simple .env file containing:

SERVER_HOST=localhost:8080
CORS_ALLOWED_ORIGINS=/${SERVER_HOST}(:[0-9]+)?$/

will throw this error when configured:
TypeError: Cannot read property 'split' of undefined

This issue wasn't happening in version 5.1.0 but I noticed it in 8.0.1

Add Changelog

Adding a CHANGELOG.md to document changes to the package (especially for major releases that may contain breaking changes) makes life much easier for consumers of this package when trying to keep their dependencies up to date.

fs.readFileSync is not a function

i get an error about fs.readFileSync is not a function while import the two packages specified in the doc !
Anyone have the same issue !

import dotenv from "dotenv";
import dotenvExpand from "dotenv-expand";

const env = dotenv.config();
dotenvExpand(env);

Possible to modify expand command?

I understand that you can use $ to escape a $, but that is annoying to deal with when you end up needing to put it in passwords. Is it possible to change the $ to some other thing?

Type 'typeof import(".../node_modules/dotenv-expand/lib/main")' has no call signatures.

I tried to use dotenv-expand with typescript, but raise the error TS2349 (This expression is not callable). I don't know what that means yet. Someone had this error before?

I created a repository to reproduce the problem here: https://github.com/lvfxbr/lab/commits/dotenv-expand-1

I post here a possible output of this problem:

$ ts-node index.ts
C:\myprojectpath\node_modules\ts-node\src\index.ts:820
    return new TSError(diagnosticText, diagnosticCodes);
           ^
TSError: ⨯ Unable to compile TypeScript:
index.ts:6:1 - error TS2349: This expression is not callable.
  Type 'typeof import("C:/myprojectpath/node_modules/dotenv-expand/lib/main")' has no call signatures.

6 dotenvExpand(dotenvConfig);
  ~~~~~~~~~~~~

    at createTSError (C:\myprojectpath\node_modules\ts-node\src\index.ts:820:12)
    at reportTSError (C:\myprojectpath\node_modules\ts-node\src\index.ts:824:19)
    at getOutput (C:\myprojectpath\node_modules\ts-node\src\index.ts:1014:36)
    at Object.compile (C:\myprojectpath\node_modules\ts-node\src\index.ts:1322:43)
    at Module.m._compile (C:\myprojectpath\node_modules\ts-node\src\index.ts:1454:30)
    at Module._extensions..js (node:internal/modules/cjs/loader:1159:10)
    at Object.require.extensions.<computed> [as .ts] (C:\myprojectpath\node_modules\ts-node\src\index.ts:1458:12)      
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:77:12) {
  diagnosticCodes: [ 2349 ]
}
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

Note: personally I use ts-node to execute typescript directly but I tested the compiled version of typescript and triggers the same error. I believe this error is something related to dotenv-expand. So, I am creating this issue to investigate.

[QUESTION]: How to use with import?

I have previously used dotenv with import. How would I used expand?

Excerpt from .env file:

MY_ENV_VAR=test
MY_OTHER_VAR=${MY_ENV_VAR}

Then, in index.js:

import * as dotenv from 'dotenv/config';
import dotenvExpand from 'dotenv-expand';
dotenvExpand(dotenv);

console.log(process.env.MY_OTHER_VAR);

This produces: "${MY_ENV_VAR}".

Package subpath './lib/env-options' is not defined by "exports"

@motdotla
@lnasc256

node:internal/modules/cjs/loader:499ig:load:flatten Completed in 1ms
      throw e;
      ^

Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: Package subpath './lib/env-options' is not defined by "exports" in /Users/xxx/projects/xxx/node_modules/.pnpm/node_modules/dotenv/package.json
    at new NodeError (node:internal/errors:387:5)

dotenv doesn't export env-options, check the exports options

{
  "name": "dotenv",
  "version": "10.0.0",
  "description": "Loads environment variables from .env file",
  "main": "lib/main.js",
  "exports": {
    ".": "./lib/main.js",
    "./config": "./config.js",
    "./config.js": "./config.js",
    "./package.json": "./package.json"
  },
  "types": "types/index.d.ts",
  "scripts": {
    "flow": "flow",
    "dtslint": "dtslint types",
    "lint": "standard",
    "postlint": "standard-markdown",
    "pretest": "npm run lint && npm run dtslint",
    "test": "tap tests/*.js --100",
    "prerelease": "npm test",
    "release": "standard-version"
  },
  "repository": {
    "type": "git",
    "url": "git://github.com/motdotla/dotenv.git"
  },
  "keywords": [
    "dotenv",
    "env",
    ".env",
    "environment",
    "variables",
    "config",
    "settings"
  ],
  "readmeFilename": "README.md",
  "license": "BSD-2-Clause",
  "devDependencies": {
    "decache": "^4.5.1",
    "dtslint": "^0.9.8",
    "flow-bin": "^0.109.0",
    "sinon": "^7.5.0",
    "standard": "^13.1.0",
    "standard-markdown": "^5.1.0",
    "standard-version": "^7.0.0",
    "tap": "^14.7.0"
  },
  "dependencies": {},
  "engines": {
    "node": ">=10"
  },
  "standard": {
    "ignore": [
      "flow-typed/"
    ]
  }
}

Preload dotenv-expand

Is it possible to preload dotenv-expand like dotenv does it?

$ node -r dotenv/config your_script.js

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.