dotenv-extended 2.9.0 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,9 +1,12 @@
1
1
  # dotenv-extended
2
2
 
3
- [![Build Status](https://travis-ci.org/keithmorris/node-dotenv-extended.svg?branch=develop)](https://travis-ci.org/keithmorris/node-dotenv-extended)
4
- [![Coverage Status](https://coveralls.io/repos/github/keithmorris/node-dotenv-extended/badge.svg?branch=develop)](https://coveralls.io/github/keithmorris/node-dotenv-extended?branch=develop)
5
- [![Dependency Status](https://david-dm.org/keithmorris/node-dotenv-extended.svg)](https://david-dm.org/keithmorris/node-dotenv-extended)
3
+ Extended `.env` loading with defaults and schema validation.
6
4
 
5
+ ## Supported Node Versions
6
+
7
+ - Node `20.x`
8
+ - Node `22.x`
9
+ - Node `24.x`
7
10
 
8
11
  I've been a big fan of the [dotenv] for a quite some time (in fact, this library uses [dotenv] under the hood for the `.env` file parsing). However, while working on some bigger projects, we realized that the managing of the `.env` files became a bit of a chore. As the files changed in the development environments, it became a tedious manual process to compare and figure out what needed to be added or removed in the other environments.
9
12
 
@@ -29,7 +32,6 @@ Common configuration defaults across all environments (commited to source contro
29
32
 
30
33
  Defines a schema of what variables _should_ be defined in the combination of `.env` and `.env.defaults`. Optionally, you can have the library throw an error if all values are not configured or if there are extra values that shouldn't be there.
31
34
 
32
-
33
35
  The `.env.schema` file should only have the name of the variable and the `=` without any value:
34
36
 
35
37
  ```
@@ -49,6 +51,24 @@ I have tried to stay as compatible as possible with the [dotenv] library but the
49
51
  npm i --save dotenv-extended
50
52
  ```
51
53
 
54
+ ## Development
55
+
56
+ ```bash
57
+ npm run check
58
+ ```
59
+
60
+ `npm run check` runs linting, formatting checks, and tests.
61
+
62
+ Use individual commands only when needed:
63
+
64
+ ```bash
65
+ npm run build
66
+ npm run lint
67
+ npm run format
68
+ npm run test:unit
69
+ npm test
70
+ ```
71
+
52
72
  ## Usage
53
73
 
54
74
  As early as possible in your main script:
@@ -61,7 +81,7 @@ Or if you prefer import syntax:
61
81
 
62
82
  ```javascript
63
83
  import dotEnvExtended from 'dotenv-extended';
64
- dotEnvExtended.load();
84
+ dotEnvExtended.load();
65
85
  ```
66
86
 
67
87
  Create a `.env` file in the root directory of your project. Add environment-specific variables on new lines in the form of `NAME=VALUE`.
@@ -80,7 +100,7 @@ MONGO_PASS=dbpassword!
80
100
  ```javascript
81
101
  mongoose.connect('mongodb://' + process.env.MONGO_HOST + '/' + process.env.MONGO_DATABASE, {
82
102
  user: process.env.MONGO_USER,
83
- pass: process.env.MONGO_PASS
103
+ pass: process.env.MONGO_PASS,
84
104
  });
85
105
  ```
86
106
 
@@ -98,28 +118,54 @@ Or to specify load options:
98
118
  node -r dotenv-extended/config your_script.js dotenv_config_path=./env/.env dotenv_config_defaults=./env/.env.defaults
99
119
  ```
100
120
 
121
+ `dotenv_config_*` values are normalized to the same option names as `load()`, supporting both snake_case and kebab-case style keys.
122
+
101
123
  ### Load Environment Variables and pass to non-NodeJS script
102
124
 
103
125
  New in 2.0.0, is a feature inspired by [cross-env](https://www.npmjs.com/package/cross-env) to allow you to load environment variables from your `.env` files and then pass them into a non-NodeJS script such as a shell script. This can simplify the process of maintaining variables used in both your Node app and other scripts. To use this command line executable, you will either need to install globally with the `-g` flag, or install `dotenv-extended` in your project and reference it from your npm scripts.
104
126
 
127
+ The package exposes two equivalent CLI commands:
128
+
129
+ - `dotenv-extended` (original)
130
+ - `dee` (short alias)
131
+
105
132
  Install Globally:
106
133
 
107
134
  ```bash
108
135
  npm install -g dotenv-extended
109
136
  ```
110
137
 
111
- Now call your shell scripts through `dotenv-extended` (this uses the defaults):
138
+ Now call your shell scripts through `dee` (this uses the defaults):
139
+
140
+ ```bash
141
+ dee ./myshellscript.sh --whatever-flags-my-script-takes
142
+ ```
143
+
144
+ Configure `dee` (or `dotenv-extended`) by passing any of the dotenv-extended options before your command. Preceed each option with two dashes `--`:
145
+
146
+ ```bash
147
+ dee --path=/path/to/.env --defaults=/path/to/.env.defaults --errorOnMissing=true ./myshellscript.sh --whatever-flags-my-script-takes
148
+ ```
149
+
150
+ `--path` and `--defaults` also support comma-separated layered files:
112
151
 
113
152
  ```bash
114
- dotenv-extended ./myshellscript.sh --whatever-flags-my-script-takes
153
+ dee \
154
+ --defaults=./env/.env.defaults.base,./env/.env.defaults.local \
155
+ --path=./env/.env.base,./env/.env.development \
156
+ ./myshellscript.sh
115
157
  ```
116
158
 
117
- Configure `dotenv-extended` by passing any of the dotenv-extended options before your command. Preceed each option with two dashes `--`:
159
+ You can also print the merged dotenv configuration (without full `process.env`) instead of executing a command:
118
160
 
119
161
  ```bash
120
- dotenv-extended --path=/path/to/.env --defaults=/path/to/.env.defaults --errorOnMissing=true ./myshellscript.sh --whatever-flags-my-script-takes
162
+ dee --print
163
+ dee --print=dotenv
121
164
  ```
122
165
 
166
+ - `--print` outputs JSON
167
+ - `--print=dotenv` outputs `KEY=value` lines
168
+
123
169
  The following are the flags you can pass to the `dotenv-extended` cli with their default values. these options detailed later in this document:
124
170
 
125
171
  ```bash
@@ -142,19 +188,23 @@ Defaults are shown below:
142
188
 
143
189
  ```javascript
144
190
  require('dotenv-extended').load({
145
- encoding: 'utf8',
146
- silent: true,
147
- path: '.env',
148
- defaults: '.env.defaults',
149
- schema: '.env.schema',
150
- errorOnMissing: false,
151
- errorOnExtra: false,
152
- errorOnRegex: false,
153
- includeProcessEnv: false,
154
- assignToProcessEnv: true,
155
- overrideProcessEnv: false
191
+ encoding: 'utf8',
192
+ silent: true,
193
+ path: '.env',
194
+ defaults: '.env.defaults',
195
+ schema: '.env.schema',
196
+ schemaExtends: undefined, // string | string[]
197
+ errorOnMissing: false,
198
+ errorOnExtra: false,
199
+ errorOnRegex: false,
200
+ errorOnMissingFiles: false,
201
+ includeProcessEnv: false,
202
+ returnSchemaOnly: false,
203
+ assignToProcessEnv: true,
204
+ overrideProcessEnv: false,
156
205
  });
157
206
  ```
207
+
158
208
  ### Configure via Environment Variables (New in 2.8.0)
159
209
 
160
210
  You may also set the configuration values via environment variables loaded from `process.env` shown below with defaults:
@@ -165,14 +215,19 @@ DOTENV_CONFIG_SILENT=true
165
215
  DOTENV_CONFIG_PATH=.env
166
216
  DOTENV_CONFIG_DEFAULTS=.env.defaults
167
217
  DOTENV_CONFIG_SCHEMA=.env.schema
218
+ DOTENV_CONFIG_SCHEMA_EXTENDS=
168
219
  DOTENV_CONFIG_ERROR_ON_MISSING=false
169
220
  DOTENV_CONFIG_ERROR_ON_EXTRA=false
170
221
  DOTENV_CONFIG_ERROR_ON_REGEX=false
222
+ DOTENV_CONFIG_ERROR_ON_MISSING_FILES=false
171
223
  DOTENV_CONFIG_INCLUDE_PROCESS_ENV=false
224
+ DOTENV_CONFIG_RETURN_SCHEMA_ONLY=false
172
225
  DOTENV_CONFIG_ASSIGN_TO_PROCESS_ENV=true
173
226
  DOTENV_CONFIG_OVERRIDE_PROCESS_ENV=false
174
227
  ```
175
228
 
229
+ `DOTENV_CONFIG_PATH`, `DOTENV_CONFIG_DEFAULTS`, and `DOTENV_CONFIG_SCHEMA_EXTENDS` can each be set to comma-separated file paths for layered loading.
230
+
176
231
  The `load()` function always returns an object containing the variables loaded from the `.env` and `.env.defaults` files. By default the returned object does not contain the properties held in `process.env` but rather only the ones that are loaded from the `.env` and `.env.defaults` files.
177
232
 
178
233
  ```javascript
@@ -191,14 +246,41 @@ Sets whether a log message is shown when missing the `.env` or `.env.defaults` f
191
246
 
192
247
  The main `.env` file that contains your variables.
193
248
 
249
+ - Accepts `string` or `string[]` in code.
250
+ - Accepts comma-separated paths via environment variable:
251
+ - `DOTENV_CONFIG_PATH=./.env.base,./.env.dev`
252
+ - Merge order is deterministic:
253
+ - load each `path` entry in order
254
+ - later entries override earlier keys
255
+
194
256
  ### defaults (_default: .env.defaults_)
195
257
 
196
258
  The file that default values are loaded from.
197
259
 
260
+ - Accepts `string` or `string[]` in code.
261
+ - Accepts comma-separated paths via environment variable:
262
+ - `DOTENV_CONFIG_DEFAULTS=./.env.defaults.base,./.env.defaults.shared`
263
+ - Merge order is deterministic:
264
+ - load each `defaults` entry in order
265
+ - later entries override earlier keys
266
+ - `path` layers are applied after all `defaults` layers, so `path` still overrides `defaults`
267
+
198
268
  ### schema (_default: .env.schema_)
199
269
 
200
270
  The file that contains the schema of what values should be available from combining `.env` and `.env.defaults`
201
271
 
272
+ ### schemaExtends (_default: undefined_)
273
+
274
+ Optional schema extension file(s) layered on top of `schema`.
275
+
276
+ - Accepts `string` or `string[]` in code.
277
+ - Accepts comma-separated paths via environment variable:
278
+ - `DOTENV_CONFIG_SCHEMA_EXTENDS=./.env.production.schema,./.env.region.schema`
279
+ - Merge order is deterministic:
280
+ - load base `schema` first
281
+ - then apply `schemaExtends` in order
282
+ - later layers override earlier keys
283
+
202
284
  ### errorOnMissing (_default: false_)
203
285
 
204
286
  Causes the library to throw a `MISSING CONFIG VALUES` error listing all of the variables missing the combined `.env` and `.env.defaults` files.
@@ -211,18 +293,51 @@ Causes the library to throw a `EXTRA CONFIG VALUES` error listing all of the ext
211
293
 
212
294
  Causes the library to throw a `REGEX MISMATCH` error listing all of the invalid variables from the combined `.env` and `.env.defaults` files. Also a `SyntaxError` is thrown in case `.env.schema` contains a syntactically invalid regex.
213
295
 
296
+ ### errorOnMissingFiles (_default: false_)
297
+
298
+ Causes the library to throw a `MISSING CONFIG FILE` error when configured dotenv files cannot be found. This applies to `path`, `defaults`, and `schema` when they are loaded.
299
+
214
300
  ### includeProcessEnv (_default: false_)
215
301
 
216
302
  Causes the library add process.env variables to error checking. The variables in process.env overrides the variables in .env and .env.defaults while checking
217
303
 
304
+ ### returnSchemaOnly (_default: false_)
305
+
306
+ Causes the returned object to include only variables present in `.env.schema`. This is useful when using `includeProcessEnv` for validation but you only want schema-defined keys in the final result.
307
+
218
308
  ### assignToProcessEnv (_default: true_)
219
309
 
220
- Sets whether the loaded values are assigned to the `process.env` object. If this is set, you must capture the return value of the call to `.load()` or you will not be able to use your variables.
310
+ Sets whether the loaded values are assigned to the `process.env` object. If this is `false`, values are only available in the returned object from `.load()`.
221
311
 
222
312
  ### overrideProcessEnv (_default: false_)
223
313
 
224
314
  By defaut, `dotenv-entended` will not overwrite any varibles that are already set in the `process.env` object. If you would like to enable overwriting any already existing values, set this value to `true`.
225
315
 
316
+ ### Layered File Precedence
317
+
318
+ When using multiple files, merge precedence is:
319
+
320
+ 1. `defaults` layers in order (last wins)
321
+ 2. `path` layers in order (last wins)
322
+ 3. `process.env` values, if `includeProcessEnv` is true and `overrideProcessEnv` is false
323
+
324
+ Example:
325
+
326
+ ```javascript
327
+ const config = require('dotenv-extended').load({
328
+ defaults: ['./env/.env.defaults.base', './env/.env.defaults.region'],
329
+ path: ['./env/.env.base', './env/.env.production'],
330
+ });
331
+ ```
332
+
333
+ Equivalent via environment variables:
334
+
335
+ ```bash
336
+ DOTENV_CONFIG_DEFAULTS=./env/.env.defaults.base,./env/.env.defaults.region \
337
+ DOTENV_CONFIG_PATH=./env/.env.base,./env/.env.production \
338
+ node app.js
339
+ ```
340
+
226
341
  ## Examples
227
342
 
228
343
  Consider the following three files:
@@ -255,18 +370,18 @@ API_KEY=
255
370
  ```javascript
256
371
  const myConfig = require('dotenv-extended').load();
257
372
 
258
- myConfig.DB_HOST === process.env.DB_HOST === "localhost"
259
- myConfig.DB_USER === process.env.DB_USER === "databaseuser-local"
260
- myConfig.DB_PASS === process.env.DB_PASS === "localhost"
261
- myConfig.DB_DATABASE === process.env.DB_DATABASE === "MyAppDB"
262
- myConfig.SHARE_URL === process.env.SHARE_URL === "http://www.example.com"
373
+ (myConfig.DB_HOST === process.env.DB_HOST) === 'localhost';
374
+ (myConfig.DB_USER === process.env.DB_USER) === 'databaseuser-local';
375
+ (myConfig.DB_PASS === process.env.DB_PASS) === 'localhost';
376
+ (myConfig.DB_DATABASE === process.env.DB_DATABASE) === 'MyAppDB';
377
+ (myConfig.SHARE_URL === process.env.SHARE_URL) === 'http://www.example.com';
263
378
  ```
264
379
 
265
380
  ### Load files with `errorOnMissing`
266
381
 
267
382
  ```javascript
268
383
  const myConfig = require('dotenv-extended').load({
269
- errorOnMissing: true
384
+ errorOnMissing: true,
270
385
  });
271
386
 
272
387
  // Throws ERROR `MISSING CONFIG VALUES: API_KEY`
@@ -276,7 +391,7 @@ const myConfig = require('dotenv-extended').load({
276
391
 
277
392
  ```javascript
278
393
  const myConfig = require('dotenv-extended').load({
279
- errorOnExtra: true
394
+ errorOnExtra: true,
280
395
  });
281
396
 
282
397
  // Throws ERROR `EXTRA CONFIG VALUES: SHARE_URL`
@@ -286,7 +401,7 @@ const myConfig = require('dotenv-extended').load({
286
401
 
287
402
  ```javascript
288
403
  const myConfig = require('dotenv-extended').load({
289
- errorOnRegex: true
404
+ errorOnRegex: true,
290
405
  });
291
406
 
292
407
  // Throws ERROR `REGEX MISMATCH: DB_USER`
@@ -296,6 +411,18 @@ const myConfig = require('dotenv-extended').load({
296
411
 
297
412
  See [CONTRIBUTING.md](CONTRIBUTING.md)
298
413
 
414
+ ## Migration Notes
415
+
416
+ ### Migrating from legacy 2.x tooling
417
+
418
+ - Node `>=20` is now required.
419
+ - Build/test tooling no longer uses `gulp`, Babel, `esm`, or Mocha/NYC.
420
+ - The project now uses:
421
+ - `tsup` for build output in `lib/`
422
+ - `vitest` for tests
423
+ - modern `eslint` config and `prettier`
424
+ - Public API is kept compatible (`load`, `config`, `parse`, CLI behavior, and `dotenv-extended/config` preload entry).
425
+
299
426
  ## Change Log
300
427
 
301
428
  See [CHANGELOG.md](CHANGELOG.md)
@@ -27,17 +27,19 @@ export interface IDotenvExtendedOptions {
27
27
 
28
28
  /**
29
29
  * Path to the main .env file that contains your variables.
30
+ * Can be a string path or layered string[] where later entries override earlier ones.
30
31
  *
31
32
  * @default '.env'
32
33
  */
33
- path?: string;
34
+ path?: string | string[];
34
35
 
35
36
  /**
36
37
  * The path to the file that default values are loaded from.
38
+ * Can be a string path or layered string[] where later entries override earlier ones.
37
39
  *
38
40
  * @default '.env.defaults'
39
41
  */
40
- defaults?: string;
42
+ defaults?: string | string[];
41
43
 
42
44
  /**
43
45
  * The path to the file that contains the schema of what values should be available
@@ -47,6 +49,12 @@ export interface IDotenvExtendedOptions {
47
49
  */
48
50
  schema?: string;
49
51
 
52
+ /**
53
+ * Optional schema extension path(s). These are layered on top of `schema` in order.
54
+ * Later entries override earlier keys (including base schema keys).
55
+ */
56
+ schemaExtends?: string | string[];
57
+
50
58
  /**
51
59
  * Causes the library to throw a MISSING CONFIG VALUES error listing all of the variables
52
60
  * missing the combined .env and .env.defaults files.
@@ -72,17 +80,32 @@ export interface IDotenvExtendedOptions {
72
80
  errorOnRegex?: boolean;
73
81
 
74
82
  /**
75
- * Causes the library add process.env variables to error checking. The variables in process.env overrides the
83
+ * Causes the library to throw when a configured dotenv file path cannot be found.
84
+ * Applies to `path`, `defaults`, and `schema` when they are loaded.
85
+ *
86
+ * @default false
87
+ */
88
+ errorOnMissingFiles?: boolean;
89
+
90
+ /**
91
+ * Causes the library add process.env variables to error checking. The variables in process.env overrides the
76
92
  * variables in .env and .env.defaults while checking
77
93
  *
78
94
  * @default false
79
95
  */
80
96
  includeProcessEnv?: boolean;
81
97
 
98
+ /**
99
+ * Causes the returned object (and any process assignment) to include only variables present in the schema file.
100
+ * This is useful when `includeProcessEnv` is enabled for validation, but you only want schema-defined keys.
101
+ *
102
+ * @default false
103
+ */
104
+ returnSchemaOnly?: boolean;
105
+
82
106
  /**
83
107
  * Sets whether the loaded values are assigned to the process.env object.
84
- * If this is set, you must capture the return value of the call to .load() or you will not be
85
- * able to use your variables.
108
+ * If this is false, values are only available from the returned object.
86
109
  *
87
110
  * @default true
88
111
  */