@dotenvx/dotenvx 0.33.1 → 0.35.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 +26 -0
- package/package.json +1 -1
- package/src/cli/actions/hub/push.js +3 -0
- package/src/cli/actions/set.js +43 -0
- package/src/cli/dotenvx.js +8 -0
- package/src/lib/helpers/forgivingDirectory.js +11 -0
- package/src/lib/main.js +6 -0
- package/src/lib/services/genexample.js +1 -1
- package/src/lib/services/sets.js +87 -0
package/README.md
CHANGED
|
@@ -84,6 +84,32 @@ More examples
|
|
|
84
84
|
|
|
85
85
|
</details>
|
|
86
86
|
|
|
87
|
+
* <details><summary>Deno 🦕</summary><br>
|
|
88
|
+
|
|
89
|
+
```sh
|
|
90
|
+
$ echo "HELLO=World" > .env
|
|
91
|
+
$ echo "console.log('Hello ' + Deno.env.get('HELLO'))" > index.ts
|
|
92
|
+
|
|
93
|
+
$ deno run --allow-env index.ts
|
|
94
|
+
Hello undefined
|
|
95
|
+
|
|
96
|
+
$ dotenvx run -- deno run --allow-env index.ts
|
|
97
|
+
Hello World
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
* <details><summary>Bun 🥟</summary><br>
|
|
101
|
+
|
|
102
|
+
```sh
|
|
103
|
+
$ echo "HELLO=Test" > .env.test
|
|
104
|
+
$ echo "console.log('Hello ' + process.env.HELLO)" > index.js
|
|
105
|
+
|
|
106
|
+
$ bun index.js
|
|
107
|
+
Hello undefined
|
|
108
|
+
|
|
109
|
+
$ dotenvx run -f .env.test -- bun index.js
|
|
110
|
+
Hello Test
|
|
111
|
+
```
|
|
112
|
+
|
|
87
113
|
* <details><summary>Python 🐍</summary><br>
|
|
88
114
|
|
|
89
115
|
```sh
|
package/package.json
CHANGED
|
@@ -12,6 +12,7 @@ const gitUrl = require('./../../../lib/helpers/gitUrl')
|
|
|
12
12
|
const gitRoot = require('./../../../lib/helpers/gitRoot')
|
|
13
13
|
const extractUsernameName = require('./../../../lib/helpers/extractUsernameName')
|
|
14
14
|
const sleep = require('./../../../lib/helpers/sleep')
|
|
15
|
+
const forgivingDirectory = require('./../../../lib/helpers/forgivingDirectory')
|
|
15
16
|
|
|
16
17
|
const spinner = createSpinner('pushing')
|
|
17
18
|
|
|
@@ -23,6 +24,8 @@ async function push (directory) {
|
|
|
23
24
|
spinner.start()
|
|
24
25
|
await sleep(500) // better dx
|
|
25
26
|
|
|
27
|
+
directory = forgivingDirectory(directory)
|
|
28
|
+
|
|
26
29
|
// debug args
|
|
27
30
|
logger.debug(`directory: ${directory}`)
|
|
28
31
|
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
const logger = require('./../../shared/logger')
|
|
2
|
+
|
|
3
|
+
const main = require('./../../lib/main')
|
|
4
|
+
|
|
5
|
+
function set (key, value) {
|
|
6
|
+
logger.debug(`key: ${key}`)
|
|
7
|
+
logger.debug(`value: ${value}`)
|
|
8
|
+
|
|
9
|
+
const options = this.opts()
|
|
10
|
+
logger.debug(`options: ${JSON.stringify(options)}`)
|
|
11
|
+
|
|
12
|
+
try {
|
|
13
|
+
const {
|
|
14
|
+
processedEnvFiles,
|
|
15
|
+
settableFilepaths
|
|
16
|
+
} = main.set(key, value, options.envFile)
|
|
17
|
+
|
|
18
|
+
for (const processedEnvFile of processedEnvFiles) {
|
|
19
|
+
logger.verbose(`setting for ${processedEnvFile.filepath}`)
|
|
20
|
+
|
|
21
|
+
if (processedEnvFile.error) {
|
|
22
|
+
if (processedEnvFile.error.code === 'MISSING_ENV_FILE') {
|
|
23
|
+
logger.warn(processedEnvFile.error)
|
|
24
|
+
logger.help(`? add one with [echo "HELLO=World" > ${processedEnvFile.filepath}] and re-run [dotenvx set]`)
|
|
25
|
+
} else {
|
|
26
|
+
logger.warn(processedEnvFile.error)
|
|
27
|
+
}
|
|
28
|
+
} else {
|
|
29
|
+
logger.verbose(`${processedEnvFile.key} set`)
|
|
30
|
+
logger.debug(`${processedEnvFile.key} set to ${processedEnvFile.value}`)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
logger.success(`set ${key} (${settableFilepaths.join(', ')})`)
|
|
35
|
+
} catch (error) {
|
|
36
|
+
logger.error(error.message)
|
|
37
|
+
if (error.help) {
|
|
38
|
+
logger.help(error.help)
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
module.exports = set
|
package/src/cli/dotenvx.js
CHANGED
|
@@ -92,6 +92,14 @@ program.command('get')
|
|
|
92
92
|
getAction.apply(this, args)
|
|
93
93
|
})
|
|
94
94
|
|
|
95
|
+
// dotenvx set
|
|
96
|
+
program.command('set')
|
|
97
|
+
.description('set a single environment variable')
|
|
98
|
+
.argument('KEY', 'KEY')
|
|
99
|
+
.argument('value', 'value')
|
|
100
|
+
.option('-f, --env-file <paths...>', 'path(s) to your env file(s)', '.env')
|
|
101
|
+
.action(require('./actions/set'))
|
|
102
|
+
|
|
95
103
|
// dotenvx encrypt
|
|
96
104
|
program.command('encrypt')
|
|
97
105
|
.description('encrypt .env.* to .env.vault')
|
package/src/lib/main.js
CHANGED
|
@@ -6,6 +6,7 @@ const dotenvExpand = require('dotenv-expand')
|
|
|
6
6
|
const Encrypt = require('./services/encrypt')
|
|
7
7
|
const Ls = require('./services/ls')
|
|
8
8
|
const Get = require('./services/get')
|
|
9
|
+
const Sets = require('./services/sets')
|
|
9
10
|
const Genexample = require('./services/genexample')
|
|
10
11
|
const Settings = require('./services/settings')
|
|
11
12
|
|
|
@@ -56,6 +57,10 @@ const get = function (key, envs = [], overload = false, DOTENV_KEY = '', all = f
|
|
|
56
57
|
return new Get(key, envs, overload, DOTENV_KEY, all).run()
|
|
57
58
|
}
|
|
58
59
|
|
|
60
|
+
const set = function (key, value, envFile) {
|
|
61
|
+
return new Sets(key, value, envFile).run()
|
|
62
|
+
}
|
|
63
|
+
|
|
59
64
|
const settings = function (key = null) {
|
|
60
65
|
return new Settings(key).run()
|
|
61
66
|
}
|
|
@@ -88,6 +93,7 @@ module.exports = {
|
|
|
88
93
|
encrypt,
|
|
89
94
|
ls,
|
|
90
95
|
get,
|
|
96
|
+
set,
|
|
91
97
|
genexample,
|
|
92
98
|
// settings
|
|
93
99
|
settings,
|
|
@@ -51,7 +51,7 @@ class Genexample {
|
|
|
51
51
|
const exampleFilename = '.env.example'
|
|
52
52
|
const exampleFilepath = path.resolve(this.directory, exampleFilename)
|
|
53
53
|
if (!fs.existsSync(exampleFilepath)) {
|
|
54
|
-
envExampleFile += `# ${exampleFilename}\n`
|
|
54
|
+
envExampleFile += `# ${exampleFilename} - generated with dotenvx\n`
|
|
55
55
|
} else {
|
|
56
56
|
envExampleFile = fs.readFileSync(exampleFilepath, ENCODING)
|
|
57
57
|
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
const fs = require('fs')
|
|
2
|
+
const path = require('path')
|
|
3
|
+
const dotenv = require('dotenv')
|
|
4
|
+
|
|
5
|
+
const ENCODING = 'utf8'
|
|
6
|
+
|
|
7
|
+
class Sets {
|
|
8
|
+
constructor (key, value, envFile = '.env') {
|
|
9
|
+
this.key = key
|
|
10
|
+
this.value = value
|
|
11
|
+
this.envFile = envFile
|
|
12
|
+
|
|
13
|
+
this.processedEnvFiles = []
|
|
14
|
+
this.settableFilepaths = new Set()
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
run () {
|
|
18
|
+
const envFilepaths = this._envFilepaths()
|
|
19
|
+
for (const envFilepath of envFilepaths) {
|
|
20
|
+
const row = {}
|
|
21
|
+
row.key = this.key
|
|
22
|
+
row.value = this.value
|
|
23
|
+
row.filepath = envFilepath
|
|
24
|
+
|
|
25
|
+
const filepath = path.resolve(envFilepath)
|
|
26
|
+
try {
|
|
27
|
+
const src = fs.readFileSync(filepath, { encoding: ENCODING })
|
|
28
|
+
const parsed = dotenv.parse(src)
|
|
29
|
+
|
|
30
|
+
let newSrc
|
|
31
|
+
if (Object.prototype.hasOwnProperty.call(parsed, this.key)) {
|
|
32
|
+
newSrc = this._srcReplaced(src)
|
|
33
|
+
} else {
|
|
34
|
+
newSrc = this._srcAppended(src)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
fs.writeFileSync(filepath, newSrc)
|
|
38
|
+
|
|
39
|
+
this.settableFilepaths.add(envFilepath)
|
|
40
|
+
} catch (e) {
|
|
41
|
+
if (e.code === 'ENOENT') {
|
|
42
|
+
const error = new Error(`missing ${envFilepath} file (${filepath})`)
|
|
43
|
+
error.code = 'MISSING_ENV_FILE'
|
|
44
|
+
|
|
45
|
+
row.error = error
|
|
46
|
+
} else {
|
|
47
|
+
row.error = e
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
this.processedEnvFiles.push(row)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
processedEnvFiles: this.processedEnvFiles,
|
|
56
|
+
settableFilepaths: [...this.settableFilepaths]
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
_envFilepaths () {
|
|
61
|
+
if (!Array.isArray(this.envFile)) {
|
|
62
|
+
return [this.envFile]
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return this.envFile
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
_srcReplaced (src) {
|
|
69
|
+
// Regular expression to find the key and replace its value
|
|
70
|
+
const regex = new RegExp(`^${this.key}=.*$`, 'm')
|
|
71
|
+
|
|
72
|
+
return src.replace(regex, `${this.key}="${this.value}"`)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
_srcAppended (src) {
|
|
76
|
+
let formatted = `${this.key}="${this.value}"`
|
|
77
|
+
if (src.endsWith('\n')) {
|
|
78
|
+
formatted = formatted + '\n'
|
|
79
|
+
} else {
|
|
80
|
+
formatted = '\n' + formatted
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return src + formatted
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
module.exports = Sets
|