dotenv-extended 2.9.0 → 3.0.1
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 +60 -25
- package/dotenv-extended.d.ts +1 -1
- package/lib/bin/cli.js +224 -0
- package/lib/bin/index.js +222 -46
- package/lib/config.js +176 -30
- package/lib/index.js +155 -66
- package/package.json +56 -57
- package/CHANGELOG.md +0 -72
- package/CONTRIBUTING.md +0 -33
- package/lib/utils/config-from-env.js +0 -28
- package/lib/utils/load-environment-file.js +0 -30
- package/lib/utils/parse-command.js +0 -49
package/README.md
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
# dotenv-extended
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
[](https://coveralls.io/github/keithmorris/node-dotenv-extended?branch=develop)
|
|
5
|
-
[](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,6 +118,8 @@ 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.
|
|
@@ -142,19 +164,20 @@ Defaults are shown below:
|
|
|
142
164
|
|
|
143
165
|
```javascript
|
|
144
166
|
require('dotenv-extended').load({
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
167
|
+
encoding: 'utf8',
|
|
168
|
+
silent: true,
|
|
169
|
+
path: '.env',
|
|
170
|
+
defaults: '.env.defaults',
|
|
171
|
+
schema: '.env.schema',
|
|
172
|
+
errorOnMissing: false,
|
|
173
|
+
errorOnExtra: false,
|
|
174
|
+
errorOnRegex: false,
|
|
175
|
+
includeProcessEnv: false,
|
|
176
|
+
assignToProcessEnv: true,
|
|
177
|
+
overrideProcessEnv: false,
|
|
156
178
|
});
|
|
157
179
|
```
|
|
180
|
+
|
|
158
181
|
### Configure via Environment Variables (New in 2.8.0)
|
|
159
182
|
|
|
160
183
|
You may also set the configuration values via environment variables loaded from `process.env` shown below with defaults:
|
|
@@ -255,18 +278,18 @@ API_KEY=
|
|
|
255
278
|
```javascript
|
|
256
279
|
const myConfig = require('dotenv-extended').load();
|
|
257
280
|
|
|
258
|
-
myConfig.DB_HOST === process.env.DB_HOST ===
|
|
259
|
-
myConfig.DB_USER === process.env.DB_USER ===
|
|
260
|
-
myConfig.DB_PASS === process.env.DB_PASS ===
|
|
261
|
-
myConfig.DB_DATABASE === process.env.DB_DATABASE ===
|
|
262
|
-
myConfig.SHARE_URL === process.env.SHARE_URL ===
|
|
281
|
+
(myConfig.DB_HOST === process.env.DB_HOST) === 'localhost';
|
|
282
|
+
(myConfig.DB_USER === process.env.DB_USER) === 'databaseuser-local';
|
|
283
|
+
(myConfig.DB_PASS === process.env.DB_PASS) === 'localhost';
|
|
284
|
+
(myConfig.DB_DATABASE === process.env.DB_DATABASE) === 'MyAppDB';
|
|
285
|
+
(myConfig.SHARE_URL === process.env.SHARE_URL) === 'http://www.example.com';
|
|
263
286
|
```
|
|
264
287
|
|
|
265
288
|
### Load files with `errorOnMissing`
|
|
266
289
|
|
|
267
290
|
```javascript
|
|
268
291
|
const myConfig = require('dotenv-extended').load({
|
|
269
|
-
errorOnMissing: true
|
|
292
|
+
errorOnMissing: true,
|
|
270
293
|
});
|
|
271
294
|
|
|
272
295
|
// Throws ERROR `MISSING CONFIG VALUES: API_KEY`
|
|
@@ -276,7 +299,7 @@ const myConfig = require('dotenv-extended').load({
|
|
|
276
299
|
|
|
277
300
|
```javascript
|
|
278
301
|
const myConfig = require('dotenv-extended').load({
|
|
279
|
-
errorOnExtra: true
|
|
302
|
+
errorOnExtra: true,
|
|
280
303
|
});
|
|
281
304
|
|
|
282
305
|
// Throws ERROR `EXTRA CONFIG VALUES: SHARE_URL`
|
|
@@ -286,7 +309,7 @@ const myConfig = require('dotenv-extended').load({
|
|
|
286
309
|
|
|
287
310
|
```javascript
|
|
288
311
|
const myConfig = require('dotenv-extended').load({
|
|
289
|
-
errorOnRegex: true
|
|
312
|
+
errorOnRegex: true,
|
|
290
313
|
});
|
|
291
314
|
|
|
292
315
|
// Throws ERROR `REGEX MISMATCH: DB_USER`
|
|
@@ -296,6 +319,18 @@ const myConfig = require('dotenv-extended').load({
|
|
|
296
319
|
|
|
297
320
|
See [CONTRIBUTING.md](CONTRIBUTING.md)
|
|
298
321
|
|
|
322
|
+
## Migration Notes
|
|
323
|
+
|
|
324
|
+
### Migrating from legacy 2.x tooling
|
|
325
|
+
|
|
326
|
+
- Node `>=20` is now required.
|
|
327
|
+
- Build/test tooling no longer uses `gulp`, Babel, `esm`, or Mocha/NYC.
|
|
328
|
+
- The project now uses:
|
|
329
|
+
- `tsup` for build output in `lib/`
|
|
330
|
+
- `vitest` for tests
|
|
331
|
+
- modern `eslint` config and `prettier`
|
|
332
|
+
- Public API is kept compatible (`load`, `config`, `parse`, CLI behavior, and `dotenv-extended/config` preload entry).
|
|
333
|
+
|
|
299
334
|
## Change Log
|
|
300
335
|
|
|
301
336
|
See [CHANGELOG.md](CHANGELOG.md)
|
package/dotenv-extended.d.ts
CHANGED
|
@@ -72,7 +72,7 @@ export interface IDotenvExtendedOptions {
|
|
|
72
72
|
errorOnRegex?: boolean;
|
|
73
73
|
|
|
74
74
|
/**
|
|
75
|
-
* Causes the library add process.env variables to error checking. The variables in process.env overrides the
|
|
75
|
+
* Causes the library add process.env variables to error checking. The variables in process.env overrides the
|
|
76
76
|
* variables in .env and .env.defaults while checking
|
|
77
77
|
*
|
|
78
78
|
* @default false
|
package/lib/bin/cli.js
ADDED
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __copyProps = (to, from, except, desc) => {
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
10
|
+
for (let key of __getOwnPropNames(from))
|
|
11
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
12
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
13
|
+
}
|
|
14
|
+
return to;
|
|
15
|
+
};
|
|
16
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
17
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
18
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
19
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
20
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
21
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
22
|
+
mod
|
|
23
|
+
));
|
|
24
|
+
|
|
25
|
+
// src/index.js
|
|
26
|
+
var import_dotenv2 = __toESM(require("dotenv"));
|
|
27
|
+
|
|
28
|
+
// src/utils/parse-primitive.js
|
|
29
|
+
var parsePrimitive = (value) => {
|
|
30
|
+
if (value === null || typeof value === "undefined") {
|
|
31
|
+
return value;
|
|
32
|
+
}
|
|
33
|
+
if (typeof value === "number" || typeof value === "boolean") {
|
|
34
|
+
return value;
|
|
35
|
+
}
|
|
36
|
+
if (typeof value !== "string") {
|
|
37
|
+
return value;
|
|
38
|
+
}
|
|
39
|
+
let normalized = value.trim().replace(/(^"|"$)|(^'|'$)/g, "").toLowerCase();
|
|
40
|
+
if (normalized === "" || normalized === "undefined") {
|
|
41
|
+
return void 0;
|
|
42
|
+
}
|
|
43
|
+
if (normalized === "null") {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
if (normalized === "nan") {
|
|
47
|
+
return NaN;
|
|
48
|
+
}
|
|
49
|
+
if (normalized === "true" || normalized === "1") {
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
if (normalized === "false" || normalized === "0") {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
const numeric = Number(normalized);
|
|
56
|
+
if (!Number.isNaN(numeric)) {
|
|
57
|
+
return numeric;
|
|
58
|
+
}
|
|
59
|
+
return value;
|
|
60
|
+
};
|
|
61
|
+
var parse_primitive_default = parsePrimitive;
|
|
62
|
+
|
|
63
|
+
// src/utils/normalize-option-key.js
|
|
64
|
+
var normalizedWithSeparators = (key) => key.toLowerCase().replace(/[_-\s]+([a-z0-9])/g, (_, next) => next.toUpperCase());
|
|
65
|
+
var normalizeOptionKey = (key) => {
|
|
66
|
+
const trimmed = key.trim();
|
|
67
|
+
if (!trimmed) {
|
|
68
|
+
return "";
|
|
69
|
+
}
|
|
70
|
+
if (/[_-\s]/.test(trimmed)) {
|
|
71
|
+
return normalizedWithSeparators(trimmed);
|
|
72
|
+
}
|
|
73
|
+
if (trimmed === trimmed.toUpperCase()) {
|
|
74
|
+
return trimmed.toLowerCase();
|
|
75
|
+
}
|
|
76
|
+
return trimmed.charAt(0).toLowerCase() + trimmed.slice(1);
|
|
77
|
+
};
|
|
78
|
+
var normalize_option_key_default = normalizeOptionKey;
|
|
79
|
+
|
|
80
|
+
// src/utils/config-from-env.js
|
|
81
|
+
var getConfigFromEnv = (env) => {
|
|
82
|
+
let config2 = {};
|
|
83
|
+
Object.keys(env).forEach((key) => {
|
|
84
|
+
const curr = key.split("DOTENV_CONFIG_");
|
|
85
|
+
if (curr.length === 2 && curr[0] === "" && curr[1].length) {
|
|
86
|
+
config2[normalize_option_key_default(curr[1])] = parse_primitive_default(env[key]);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
return config2;
|
|
90
|
+
};
|
|
91
|
+
var config_from_env_default = getConfigFromEnv;
|
|
92
|
+
|
|
93
|
+
// src/utils/load-environment-file.js
|
|
94
|
+
var import_fs = __toESM(require("fs"));
|
|
95
|
+
var import_dotenv = __toESM(require("dotenv"));
|
|
96
|
+
var loadEnvironmentFile = (path, encoding, silent) => {
|
|
97
|
+
try {
|
|
98
|
+
const data = import_fs.default.readFileSync(path, encoding);
|
|
99
|
+
return import_dotenv.default.parse(data);
|
|
100
|
+
} catch (err) {
|
|
101
|
+
if (!silent) {
|
|
102
|
+
console.error(err.message);
|
|
103
|
+
}
|
|
104
|
+
return {};
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
var load_environment_file_default = loadEnvironmentFile;
|
|
108
|
+
|
|
109
|
+
// src/index.js
|
|
110
|
+
var parse = import_dotenv2.default.parse.bind(import_dotenv2.default);
|
|
111
|
+
var config = (options) => {
|
|
112
|
+
let defaultsData, environmentData, defaultOptions = {
|
|
113
|
+
encoding: "utf8",
|
|
114
|
+
silent: true,
|
|
115
|
+
path: ".env",
|
|
116
|
+
defaults: ".env.defaults",
|
|
117
|
+
schema: ".env.schema",
|
|
118
|
+
errorOnMissing: false,
|
|
119
|
+
errorOnExtra: false,
|
|
120
|
+
errorOnRegex: false,
|
|
121
|
+
includeProcessEnv: false,
|
|
122
|
+
assignToProcessEnv: true,
|
|
123
|
+
overrideProcessEnv: false
|
|
124
|
+
}, processEnvOptions = config_from_env_default(process.env);
|
|
125
|
+
options = Object.assign({}, defaultOptions, processEnvOptions, options);
|
|
126
|
+
defaultsData = load_environment_file_default(options.defaults, options.encoding, options.silent);
|
|
127
|
+
environmentData = load_environment_file_default(options.path, options.encoding, options.silent);
|
|
128
|
+
let configData = Object.assign({}, defaultsData, environmentData);
|
|
129
|
+
const config2 = options.includeProcessEnv ? Object.assign({}, configData, process.env) : configData;
|
|
130
|
+
const configOnlyKeys = Object.keys(configData);
|
|
131
|
+
const configKeys = Object.keys(config2);
|
|
132
|
+
if (options.errorOnMissing || options.errorOnExtra || options.errorOnRegex) {
|
|
133
|
+
const schema = load_environment_file_default(options.schema, options.encoding, options.silent);
|
|
134
|
+
const schemaKeys = Object.keys(schema);
|
|
135
|
+
let missingKeys = schemaKeys.filter(function(key) {
|
|
136
|
+
return configKeys.indexOf(key) < 0;
|
|
137
|
+
});
|
|
138
|
+
let extraKeys = configOnlyKeys.filter(function(key) {
|
|
139
|
+
return schemaKeys.indexOf(key) < 0;
|
|
140
|
+
});
|
|
141
|
+
if (options.errorOnMissing && missingKeys.length) {
|
|
142
|
+
throw new Error("MISSING CONFIG VALUES: " + missingKeys.join(", "));
|
|
143
|
+
}
|
|
144
|
+
if (options.errorOnExtra && extraKeys.length) {
|
|
145
|
+
throw new Error("EXTRA CONFIG VALUES: " + extraKeys.join(", "));
|
|
146
|
+
}
|
|
147
|
+
if (options.errorOnRegex) {
|
|
148
|
+
const regexMismatchKeys = schemaKeys.filter(function(key) {
|
|
149
|
+
if (schema[key]) {
|
|
150
|
+
return !new RegExp(schema[key]).test(
|
|
151
|
+
typeof config2[key] === "string" ? config2[key] : ""
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
if (regexMismatchKeys.length) {
|
|
156
|
+
throw new Error("REGEX MISMATCH: " + regexMismatchKeys.join(", "));
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
if (options.includeProcessEnv && !options.overrideProcessEnv) {
|
|
161
|
+
for (let i = 0; i < configKeys.length; i++) {
|
|
162
|
+
if (typeof process.env[configKeys[i]] !== "undefined")
|
|
163
|
+
configData[configKeys[i]] = process.env[configKeys[i]];
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
if (options.assignToProcessEnv) {
|
|
167
|
+
if (options.overrideProcessEnv) {
|
|
168
|
+
Object.assign(process.env, configData);
|
|
169
|
+
} else {
|
|
170
|
+
const tmp = Object.assign({}, configData, process.env);
|
|
171
|
+
Object.assign(process.env, tmp);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return configData;
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
// src/utils/parse-command.js
|
|
178
|
+
var dotEnvFlagRegex = /^--(.+)=(.+)/;
|
|
179
|
+
var parseCommand = (args) => {
|
|
180
|
+
const config2 = {};
|
|
181
|
+
let command = null;
|
|
182
|
+
let commandArgs = [];
|
|
183
|
+
for (let i = 0; i < args.length; i++) {
|
|
184
|
+
const match = dotEnvFlagRegex.exec(args[i]);
|
|
185
|
+
if (match) {
|
|
186
|
+
config2[normalize_option_key_default(match[1])] = parse_primitive_default(match[2]);
|
|
187
|
+
} else {
|
|
188
|
+
command = args[i];
|
|
189
|
+
commandArgs = args.slice(i + 1);
|
|
190
|
+
break;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return [config2, command, commandArgs];
|
|
194
|
+
};
|
|
195
|
+
var parse_command_default = parseCommand;
|
|
196
|
+
|
|
197
|
+
// src/bin/index.js
|
|
198
|
+
var import_node_child_process = require("child_process");
|
|
199
|
+
var spawnCommand = (command, commandArgs, options) => (0, import_node_child_process.spawn)(command, commandArgs, options);
|
|
200
|
+
function loadAndExecute(args, dependencies = {}) {
|
|
201
|
+
const {
|
|
202
|
+
spawnCommandFn = spawnCommand,
|
|
203
|
+
processOn = process.on.bind(process),
|
|
204
|
+
processExit = process.exit
|
|
205
|
+
} = dependencies;
|
|
206
|
+
const [dotEnvConfig, command, commandArgs] = parse_command_default(args);
|
|
207
|
+
if (command) {
|
|
208
|
+
config(dotEnvConfig);
|
|
209
|
+
const proc = spawnCommandFn(command, commandArgs, {
|
|
210
|
+
stdio: "inherit",
|
|
211
|
+
shell: true,
|
|
212
|
+
env: process.env
|
|
213
|
+
});
|
|
214
|
+
processOn("SIGTERM", () => proc.kill("SIGTERM"));
|
|
215
|
+
processOn("SIGINT", () => proc.kill("SIGINT"));
|
|
216
|
+
processOn("SIGBREAK", () => proc.kill("SIGBREAK"));
|
|
217
|
+
processOn("SIGHUP", () => proc.kill("SIGHUP"));
|
|
218
|
+
proc.on("exit", processExit);
|
|
219
|
+
return proc;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// src/bin/cli.js
|
|
224
|
+
loadAndExecute(process.argv.slice(2));
|
package/lib/bin/index.js
CHANGED
|
@@ -1,63 +1,239 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
2
29
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
var _ = require("..");
|
|
12
|
-
|
|
13
|
-
var _parseCommand3 = _interopRequireDefault(require("../utils/parse-command"));
|
|
14
|
-
|
|
15
|
-
var _crossSpawn = require("cross-spawn");
|
|
16
|
-
|
|
17
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
|
|
30
|
+
// src/bin/index.js
|
|
31
|
+
var bin_exports = {};
|
|
32
|
+
__export(bin_exports, {
|
|
33
|
+
loadAndExecute: () => loadAndExecute,
|
|
34
|
+
spawnCommand: () => spawnCommand
|
|
35
|
+
});
|
|
36
|
+
module.exports = __toCommonJS(bin_exports);
|
|
18
37
|
|
|
19
|
-
|
|
38
|
+
// src/index.js
|
|
39
|
+
var import_dotenv2 = __toESM(require("dotenv"));
|
|
20
40
|
|
|
21
|
-
|
|
41
|
+
// src/utils/parse-primitive.js
|
|
42
|
+
var parsePrimitive = (value) => {
|
|
43
|
+
if (value === null || typeof value === "undefined") {
|
|
44
|
+
return value;
|
|
45
|
+
}
|
|
46
|
+
if (typeof value === "number" || typeof value === "boolean") {
|
|
47
|
+
return value;
|
|
48
|
+
}
|
|
49
|
+
if (typeof value !== "string") {
|
|
50
|
+
return value;
|
|
51
|
+
}
|
|
52
|
+
let normalized = value.trim().replace(/(^"|"$)|(^'|'$)/g, "").toLowerCase();
|
|
53
|
+
if (normalized === "" || normalized === "undefined") {
|
|
54
|
+
return void 0;
|
|
55
|
+
}
|
|
56
|
+
if (normalized === "null") {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
if (normalized === "nan") {
|
|
60
|
+
return NaN;
|
|
61
|
+
}
|
|
62
|
+
if (normalized === "true" || normalized === "1") {
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
if (normalized === "false" || normalized === "0") {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
const numeric = Number(normalized);
|
|
69
|
+
if (!Number.isNaN(numeric)) {
|
|
70
|
+
return numeric;
|
|
71
|
+
}
|
|
72
|
+
return value;
|
|
73
|
+
};
|
|
74
|
+
var parse_primitive_default = parsePrimitive;
|
|
22
75
|
|
|
23
|
-
|
|
76
|
+
// src/utils/normalize-option-key.js
|
|
77
|
+
var normalizedWithSeparators = (key) => key.toLowerCase().replace(/[_-\s]+([a-z0-9])/g, (_, next) => next.toUpperCase());
|
|
78
|
+
var normalizeOptionKey = (key) => {
|
|
79
|
+
const trimmed = key.trim();
|
|
80
|
+
if (!trimmed) {
|
|
81
|
+
return "";
|
|
82
|
+
}
|
|
83
|
+
if (/[_-\s]/.test(trimmed)) {
|
|
84
|
+
return normalizedWithSeparators(trimmed);
|
|
85
|
+
}
|
|
86
|
+
if (trimmed === trimmed.toUpperCase()) {
|
|
87
|
+
return trimmed.toLowerCase();
|
|
88
|
+
}
|
|
89
|
+
return trimmed.charAt(0).toLowerCase() + trimmed.slice(1);
|
|
90
|
+
};
|
|
91
|
+
var normalize_option_key_default = normalizeOptionKey;
|
|
24
92
|
|
|
25
|
-
|
|
93
|
+
// src/utils/config-from-env.js
|
|
94
|
+
var getConfigFromEnv = (env) => {
|
|
95
|
+
let config2 = {};
|
|
96
|
+
Object.keys(env).forEach((key) => {
|
|
97
|
+
const curr = key.split("DOTENV_CONFIG_");
|
|
98
|
+
if (curr.length === 2 && curr[0] === "" && curr[1].length) {
|
|
99
|
+
config2[normalize_option_key_default(curr[1])] = parse_primitive_default(env[key]);
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
return config2;
|
|
103
|
+
};
|
|
104
|
+
var config_from_env_default = getConfigFromEnv;
|
|
26
105
|
|
|
27
|
-
|
|
106
|
+
// src/utils/load-environment-file.js
|
|
107
|
+
var import_fs = __toESM(require("fs"));
|
|
108
|
+
var import_dotenv = __toESM(require("dotenv"));
|
|
109
|
+
var loadEnvironmentFile = (path, encoding, silent) => {
|
|
110
|
+
try {
|
|
111
|
+
const data = import_fs.default.readFileSync(path, encoding);
|
|
112
|
+
return import_dotenv.default.parse(data);
|
|
113
|
+
} catch (err) {
|
|
114
|
+
if (!silent) {
|
|
115
|
+
console.error(err.message);
|
|
116
|
+
}
|
|
117
|
+
return {};
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
var load_environment_file_default = loadEnvironmentFile;
|
|
28
121
|
|
|
29
|
-
|
|
122
|
+
// src/index.js
|
|
123
|
+
var parse = import_dotenv2.default.parse.bind(import_dotenv2.default);
|
|
124
|
+
var config = (options) => {
|
|
125
|
+
let defaultsData, environmentData, defaultOptions = {
|
|
126
|
+
encoding: "utf8",
|
|
127
|
+
silent: true,
|
|
128
|
+
path: ".env",
|
|
129
|
+
defaults: ".env.defaults",
|
|
130
|
+
schema: ".env.schema",
|
|
131
|
+
errorOnMissing: false,
|
|
132
|
+
errorOnExtra: false,
|
|
133
|
+
errorOnRegex: false,
|
|
134
|
+
includeProcessEnv: false,
|
|
135
|
+
assignToProcessEnv: true,
|
|
136
|
+
overrideProcessEnv: false
|
|
137
|
+
}, processEnvOptions = config_from_env_default(process.env);
|
|
138
|
+
options = Object.assign({}, defaultOptions, processEnvOptions, options);
|
|
139
|
+
defaultsData = load_environment_file_default(options.defaults, options.encoding, options.silent);
|
|
140
|
+
environmentData = load_environment_file_default(options.path, options.encoding, options.silent);
|
|
141
|
+
let configData = Object.assign({}, defaultsData, environmentData);
|
|
142
|
+
const config2 = options.includeProcessEnv ? Object.assign({}, configData, process.env) : configData;
|
|
143
|
+
const configOnlyKeys = Object.keys(configData);
|
|
144
|
+
const configKeys = Object.keys(config2);
|
|
145
|
+
if (options.errorOnMissing || options.errorOnExtra || options.errorOnRegex) {
|
|
146
|
+
const schema = load_environment_file_default(options.schema, options.encoding, options.silent);
|
|
147
|
+
const schemaKeys = Object.keys(schema);
|
|
148
|
+
let missingKeys = schemaKeys.filter(function(key) {
|
|
149
|
+
return configKeys.indexOf(key) < 0;
|
|
150
|
+
});
|
|
151
|
+
let extraKeys = configOnlyKeys.filter(function(key) {
|
|
152
|
+
return schemaKeys.indexOf(key) < 0;
|
|
153
|
+
});
|
|
154
|
+
if (options.errorOnMissing && missingKeys.length) {
|
|
155
|
+
throw new Error("MISSING CONFIG VALUES: " + missingKeys.join(", "));
|
|
156
|
+
}
|
|
157
|
+
if (options.errorOnExtra && extraKeys.length) {
|
|
158
|
+
throw new Error("EXTRA CONFIG VALUES: " + extraKeys.join(", "));
|
|
159
|
+
}
|
|
160
|
+
if (options.errorOnRegex) {
|
|
161
|
+
const regexMismatchKeys = schemaKeys.filter(function(key) {
|
|
162
|
+
if (schema[key]) {
|
|
163
|
+
return !new RegExp(schema[key]).test(
|
|
164
|
+
typeof config2[key] === "string" ? config2[key] : ""
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
if (regexMismatchKeys.length) {
|
|
169
|
+
throw new Error("REGEX MISMATCH: " + regexMismatchKeys.join(", "));
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
if (options.includeProcessEnv && !options.overrideProcessEnv) {
|
|
174
|
+
for (let i = 0; i < configKeys.length; i++) {
|
|
175
|
+
if (typeof process.env[configKeys[i]] !== "undefined")
|
|
176
|
+
configData[configKeys[i]] = process.env[configKeys[i]];
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
if (options.assignToProcessEnv) {
|
|
180
|
+
if (options.overrideProcessEnv) {
|
|
181
|
+
Object.assign(process.env, configData);
|
|
182
|
+
} else {
|
|
183
|
+
const tmp = Object.assign({}, configData, process.env);
|
|
184
|
+
Object.assign(process.env, tmp);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return configData;
|
|
188
|
+
};
|
|
30
189
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
190
|
+
// src/utils/parse-command.js
|
|
191
|
+
var dotEnvFlagRegex = /^--(.+)=(.+)/;
|
|
192
|
+
var parseCommand = (args) => {
|
|
193
|
+
const config2 = {};
|
|
194
|
+
let command = null;
|
|
195
|
+
let commandArgs = [];
|
|
196
|
+
for (let i = 0; i < args.length; i++) {
|
|
197
|
+
const match = dotEnvFlagRegex.exec(args[i]);
|
|
198
|
+
if (match) {
|
|
199
|
+
config2[normalize_option_key_default(match[1])] = parse_primitive_default(match[2]);
|
|
200
|
+
} else {
|
|
201
|
+
command = args[i];
|
|
202
|
+
commandArgs = args.slice(i + 1);
|
|
203
|
+
break;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
return [config2, command, commandArgs];
|
|
207
|
+
};
|
|
208
|
+
var parse_command_default = parseCommand;
|
|
37
209
|
|
|
210
|
+
// src/bin/index.js
|
|
211
|
+
var import_node_child_process = require("child_process");
|
|
212
|
+
var spawnCommand = (command, commandArgs, options) => (0, import_node_child_process.spawn)(command, commandArgs, options);
|
|
213
|
+
function loadAndExecute(args, dependencies = {}) {
|
|
214
|
+
const {
|
|
215
|
+
spawnCommandFn = spawnCommand,
|
|
216
|
+
processOn = process.on.bind(process),
|
|
217
|
+
processExit = process.exit
|
|
218
|
+
} = dependencies;
|
|
219
|
+
const [dotEnvConfig, command, commandArgs] = parse_command_default(args);
|
|
38
220
|
if (command) {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
stdio: 'inherit',
|
|
221
|
+
config(dotEnvConfig);
|
|
222
|
+
const proc = spawnCommandFn(command, commandArgs, {
|
|
223
|
+
stdio: "inherit",
|
|
43
224
|
shell: true,
|
|
44
225
|
env: process.env
|
|
45
226
|
});
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
});
|
|
52
|
-
process.on('SIGBREAK', function () {
|
|
53
|
-
return proc.kill('SIGBREAK');
|
|
54
|
-
});
|
|
55
|
-
process.on('SIGHUP', function () {
|
|
56
|
-
return proc.kill('SIGHUP');
|
|
57
|
-
});
|
|
58
|
-
proc.on('exit', process.exit);
|
|
227
|
+
processOn("SIGTERM", () => proc.kill("SIGTERM"));
|
|
228
|
+
processOn("SIGINT", () => proc.kill("SIGINT"));
|
|
229
|
+
processOn("SIGBREAK", () => proc.kill("SIGBREAK"));
|
|
230
|
+
processOn("SIGHUP", () => proc.kill("SIGHUP"));
|
|
231
|
+
proc.on("exit", processExit);
|
|
59
232
|
return proc;
|
|
60
233
|
}
|
|
61
234
|
}
|
|
62
|
-
|
|
63
|
-
|
|
235
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
236
|
+
0 && (module.exports = {
|
|
237
|
+
loadAndExecute,
|
|
238
|
+
spawnCommand
|
|
239
|
+
});
|