dynenv 1.3.2 → 1.4.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 +2 -2
- package/index.js +6 -77
- package/lib/listDirectory.js +11 -0
- package/lib/parseArgs.js +32 -0
- package/lib/requireFiles.js +18 -0
- package/lib/safeRequire.js +14 -0
- package/lib/spawnNextCommand.js +8 -0
- package/package.json +27 -20
package/README.md
CHANGED
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
Dynamically loads environment variables from modules and then spawns a child process with them
|
|
4
4
|
|
|
5
|
-
It's like
|
|
5
|
+
It's like [dotenv](https://github.com/motdotla/dotenv), but instead of .env files, you require modules!
|
|
6
6
|
|
|
7
7
|
## Usage
|
|
8
8
|
|
|
9
9
|
Add `dynenv` as a dev dependency using your particular package manager:
|
|
10
|
-
```
|
|
10
|
+
```sh
|
|
11
11
|
npm install dynenv --save-dev
|
|
12
12
|
yarn add dynenv --dev
|
|
13
13
|
```
|
package/index.js
CHANGED
|
@@ -1,80 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
import { parseArgs } from './lib/parseArgs.js';
|
|
3
|
+
import { requireFiles } from './lib/requireFiles.js';
|
|
4
|
+
import { spawnNextCommand } from './lib/spawnNextCommand.js';
|
|
5
5
|
|
|
6
|
-
parseArgs()
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
parseArgs(process.argv.slice(2))
|
|
7
|
+
.then(state => requireFiles(state, process.env))
|
|
8
|
+
.then(state => process.exitCode = spawnNextCommand(state).status)
|
|
9
9
|
;
|
|
10
|
-
|
|
11
|
-
async function parseArgs() {
|
|
12
|
-
const args = process.argv.slice(2);
|
|
13
|
-
const barrier = args.indexOf('--');
|
|
14
|
-
if (-1 === barrier) {
|
|
15
|
-
const modules = await listDirectory('./node_modules/');
|
|
16
|
-
for (const parentDirectory of modules.filter(m => m.indexOf(`${sep}@`) >= 0)) {
|
|
17
|
-
modules.push(...await listDirectory(parentDirectory));
|
|
18
|
-
}
|
|
19
|
-
const filesToRequire = [];
|
|
20
|
-
for (const module of modules) {
|
|
21
|
-
const packageJSON = safeRequire(resolve(module, 'package.json'));
|
|
22
|
-
if (packageJSON && packageJSON.dynenv) {
|
|
23
|
-
filesToRequire.push(resolve(module, packageJSON.dynenv));
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
return {
|
|
27
|
-
filesToRequire,
|
|
28
|
-
nextCommand: args[0],
|
|
29
|
-
nextCommandArgs: args.slice(1),
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
else {
|
|
33
|
-
return {
|
|
34
|
-
filesToRequire: args.slice(0, barrier),
|
|
35
|
-
nextCommand: args[barrier + 1],
|
|
36
|
-
nextCommandArgs: args.slice(barrier + 2),
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function listDirectory(ref) {
|
|
42
|
-
return new Promise((resolve, reject) => {
|
|
43
|
-
readdir(ref, (err, results) => err
|
|
44
|
-
? reject(err)
|
|
45
|
-
: resolve(results.map(result => join(ref, result))),
|
|
46
|
-
);
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
async function requireFiles(state) {
|
|
51
|
-
state.env = Object.assign({}, process.env);
|
|
52
|
-
for (const fileToRequire of state.filesToRequire) {
|
|
53
|
-
const exports = safeRequire(fileToRequire.startsWith('./')
|
|
54
|
-
? resolve(fileToRequire)
|
|
55
|
-
: fileToRequire);
|
|
56
|
-
const newEnv = typeof exports === 'function'
|
|
57
|
-
? await exports()
|
|
58
|
-
: exports;
|
|
59
|
-
if (newEnv) {
|
|
60
|
-
Object.assign(state.env, newEnv);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
return state;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
function safeRequire(ref) {
|
|
67
|
-
try {
|
|
68
|
-
return require(ref);
|
|
69
|
-
}
|
|
70
|
-
catch (err) {
|
|
71
|
-
return null;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
function spawnNextCommand({ nextCommand, nextCommandArgs, env }) {
|
|
76
|
-
return spawn.sync(nextCommand, nextCommandArgs, {
|
|
77
|
-
stdio: 'inherit',
|
|
78
|
-
env,
|
|
79
|
-
});
|
|
80
|
-
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { readdir } from 'fs';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
|
|
4
|
+
export function listDirectory(ref) {
|
|
5
|
+
return new Promise((resolve, reject) => {
|
|
6
|
+
readdir(ref, (err, results) => err
|
|
7
|
+
? reject(err)
|
|
8
|
+
: resolve(results.map(result => join(ref, result))),
|
|
9
|
+
);
|
|
10
|
+
});
|
|
11
|
+
}
|
package/lib/parseArgs.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { resolve, sep } from 'path';
|
|
2
|
+
import { listDirectory } from './listDirectory.js';
|
|
3
|
+
import { safeRequire } from './safeRequire.js';
|
|
4
|
+
|
|
5
|
+
export async function parseArgs(args) {
|
|
6
|
+
const barrier = args.indexOf('--');
|
|
7
|
+
if (-1 === barrier) {
|
|
8
|
+
const modules = await listDirectory('./node_modules/');
|
|
9
|
+
for (const parentDirectory of modules.filter(m => m.indexOf(`${sep}@`) >= 0)) {
|
|
10
|
+
modules.push(...await listDirectory(parentDirectory));
|
|
11
|
+
}
|
|
12
|
+
const filesToRequire = [];
|
|
13
|
+
for (const module of modules) {
|
|
14
|
+
const packageJSON = safeRequire(resolve(module, 'package.json'));
|
|
15
|
+
if (packageJSON && packageJSON.dynenv) {
|
|
16
|
+
filesToRequire.push(resolve(module, packageJSON.dynenv));
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return {
|
|
20
|
+
filesToRequire,
|
|
21
|
+
nextCommand: args[0],
|
|
22
|
+
nextCommandArgs: args.slice(1),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
return {
|
|
27
|
+
filesToRequire: args.slice(0, barrier),
|
|
28
|
+
nextCommand: args[barrier + 1],
|
|
29
|
+
nextCommandArgs: args.slice(barrier + 2),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { resolve } from 'path';
|
|
2
|
+
import { safeRequire } from './safeRequire.js';
|
|
3
|
+
|
|
4
|
+
export async function requireFiles(state, initialEnv) {
|
|
5
|
+
state.env = Object.assign({}, initialEnv);
|
|
6
|
+
for (const fileToRequire of state.filesToRequire) {
|
|
7
|
+
const exports = safeRequire(fileToRequire.startsWith('./')
|
|
8
|
+
? resolve(fileToRequire)
|
|
9
|
+
: fileToRequire);
|
|
10
|
+
const newEnv = typeof exports === 'function'
|
|
11
|
+
? await exports()
|
|
12
|
+
: exports;
|
|
13
|
+
if (newEnv) {
|
|
14
|
+
Object.assign(state.env, newEnv);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return state;
|
|
18
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { createRequire } from 'module';
|
|
2
|
+
|
|
3
|
+
// Create a CommonJS-compatible require that works from ESM context
|
|
4
|
+
const requireCompat = createRequire(import.meta.url);
|
|
5
|
+
|
|
6
|
+
export function safeRequire(ref) {
|
|
7
|
+
try {
|
|
8
|
+
return requireCompat(ref);
|
|
9
|
+
}
|
|
10
|
+
catch (err) {
|
|
11
|
+
console.error(err);
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
}
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.
|
|
2
|
+
"version": "1.4.0",
|
|
3
3
|
"name": "dynenv",
|
|
4
4
|
"description": "Dynamically loads environment variables from modules and then spawns a child process with them",
|
|
5
5
|
"author": "Dawson Toth",
|
|
@@ -7,33 +7,40 @@
|
|
|
7
7
|
"dotenv"
|
|
8
8
|
],
|
|
9
9
|
"homepage": ".",
|
|
10
|
-
"
|
|
10
|
+
"type": "module",
|
|
11
|
+
"license": "ISC",
|
|
12
|
+
"publishConfig": {
|
|
13
|
+
"registry": "https://registry.npmjs.org/",
|
|
14
|
+
"tag": "latest",
|
|
15
|
+
"provenance": true
|
|
16
|
+
},
|
|
11
17
|
"repository": "github:dawsontoth/dynenv",
|
|
12
18
|
"main": "index.js",
|
|
13
19
|
"bin": {
|
|
14
20
|
"dynenv": "./index.js"
|
|
15
21
|
},
|
|
16
|
-
"scripts": {
|
|
22
|
+
"scripts": {
|
|
23
|
+
"test": "vitest",
|
|
24
|
+
"test:ci": "vitest run",
|
|
25
|
+
"test:coverage": "vitest run --coverage",
|
|
26
|
+
"lint": "eslint .",
|
|
27
|
+
"lint:fix": "eslint . --fix"
|
|
28
|
+
},
|
|
17
29
|
"dependencies": {
|
|
18
30
|
"cross-spawn": "^7.0.3"
|
|
19
31
|
},
|
|
20
32
|
"devDependencies": {
|
|
33
|
+
"@eslint/js": "^9.39.1",
|
|
34
|
+
"@semantic-release/commit-analyzer": "^13.0.1",
|
|
21
35
|
"@semantic-release/git": "^10.0.1",
|
|
22
|
-
"semantic-release": "^
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
"@
|
|
26
|
-
"
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
"docs",
|
|
33
|
-
"package.json"
|
|
34
|
-
],
|
|
35
|
-
"message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
|
|
36
|
-
}
|
|
37
|
-
]
|
|
38
|
-
]
|
|
36
|
+
"@semantic-release/github": "^12.0.2",
|
|
37
|
+
"@semantic-release/npm": "^13.1.1",
|
|
38
|
+
"@semantic-release/release-notes-generator": "^14.1.0",
|
|
39
|
+
"@vitest/coverage-v8": "^4.0.8",
|
|
40
|
+
"conventional-changelog-conventionalcommits": "^9.1.0",
|
|
41
|
+
"eslint": "^9.39.1",
|
|
42
|
+
"globals": "^16.5.0",
|
|
43
|
+
"semantic-release": "^25.0.2",
|
|
44
|
+
"vitest": "^4.0.8"
|
|
45
|
+
}
|
|
39
46
|
}
|