@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 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
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.33.1",
2
+ "version": "0.35.0",
3
3
  "name": "@dotenvx/dotenvx",
4
4
  "description": "a better dotenv–from the creator of `dotenv`",
5
5
  "author": "@motdotla",
@@ -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
@@ -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')
@@ -0,0 +1,11 @@
1
+ const path = require('path')
2
+
3
+ function forgivingDirectory (pathString) {
4
+ if (pathString.endsWith('.env.keys')) {
5
+ return path.dirname(pathString)
6
+ }
7
+
8
+ return pathString
9
+ }
10
+
11
+ module.exports = forgivingDirectory
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