@dotenvx/dotenvx 0.2.23

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 ADDED
@@ -0,0 +1,274 @@
1
+ ![dotenvx](https://dotenv.org/better-banner.png)
2
+
3
+ *a better dotenv*–from the creator of [`dotenv`](https://github.com/motdotla/dotenv).
4
+
5
+ * run anywhere (cross-platform)
6
+ * multi-environment
7
+ * encrypted envs
8
+
9
+  
10
+
11
+
12
+ ### Quickstart
13
+
14
+ ```sh
15
+ brew install dotenvx/brew/dotenvx
16
+ ```
17
+ > * [other ways to install](#other-ways-to-install)
18
+
19
+  
20
+
21
+ ## Run Anywhere
22
+
23
+ ```sh
24
+ $ echo "HELLO=World" > .env && echo "console.log('Hello ' + process.env.HELLO)" > index.js
25
+
26
+ $ node index.js
27
+ Hello undefined
28
+
29
+ $ dotenv run -- node index.js
30
+ Hello World
31
+ > :-D
32
+ ```
33
+
34
+ More examples
35
+
36
+ * <details><summary>Python 🐍</summary><br>
37
+
38
+ ```sh
39
+ $ echo 'import os;print("Hello " + os.getenv("HELLO", ""))' > index.py
40
+
41
+ $ dotenv run -- python3 index.py
42
+ Hello World
43
+ ```
44
+
45
+ </details>
46
+ * <details><summary>PHP 🐘</summary><br>
47
+
48
+ ```sh
49
+ $ echo '<?php echo "Hello {$_SERVER["HELLO"]}\n";' > index.php
50
+
51
+ $ dotenv run -- php index.php
52
+ Hello World
53
+ ```
54
+
55
+ </details>
56
+ * <details><summary>Ruby 💎</summary><br>
57
+
58
+ ```sh
59
+ $ echo 'puts "Hello #{ENV["HELLO"]}"' > index.rb
60
+
61
+ $ dotenv run -- ruby index.rb
62
+ Hello World
63
+ ```
64
+
65
+ </details>
66
+ * <details><summary>Rust 🦀</summary><br>
67
+
68
+ ```sh
69
+ $ echo 'fn main() {let hello = std::env::var("HELLO").unwrap_or("".to_string());println!("Hello {hello}");}' > src/main.rs
70
+
71
+ $ dotenv run -- cargo run
72
+ Hello World
73
+ ```
74
+
75
+ </details>
76
+ * <details><summary>Frameworks ▲</summary><br>
77
+
78
+ ```sh
79
+ $ dotenv run -- next dev
80
+ $ dotenv run -- npm start
81
+ $ dotenv run -- bin/rails s
82
+ $ dotenv run -- php artisan serve
83
+ ```
84
+
85
+ </details>
86
+ * <details><summary>Docker 🐳</summary><br>
87
+
88
+ ```sh
89
+ # run as a command-line tool
90
+ docker run -it --rm -v $(pwd):/app dotenv/dotenv run -- node index.js
91
+ ```
92
+
93
+ ```sh
94
+ # include in a Dockerfile
95
+ # example coming soon
96
+ ```
97
+
98
+ </details>
99
+
100
+ * <details><summary>CI/CDs 🐙</summary><br>
101
+
102
+ ```sh
103
+ examples coming soon
104
+ ```
105
+
106
+ </details>
107
+ * <details><summary>Platforms</summary><br>
108
+
109
+ ```sh
110
+ examples coming soon
111
+ ```
112
+
113
+ </details>
114
+ * <details><summary>npx</summary><br>
115
+
116
+ ```sh
117
+ # alternatively use npx
118
+ $ npx @dotenv/dotenv run -- node index.js
119
+ $ npx @dotenv/dotenv run -- next dev
120
+ $ npx @dotenv/dotenv run -- npm start
121
+ ```
122
+
123
+ </details>
124
+ * <details><summary>Git</summary><br>
125
+
126
+ ```sh
127
+ # use as a git submodule
128
+ $ git dotenv run -- node index.js
129
+ $ git dotenv run -- next dev
130
+ $ git dotenv run -- npm start
131
+ ```
132
+
133
+ </details>
134
+
135
+ &nbsp;
136
+
137
+ ## Multiple Environments
138
+
139
+ Pass the `--env-file` flag (shorthand `-f`) to run any environment from a `.env.environment` file.
140
+
141
+ ```sh
142
+ $ dotenv run --env-file=.env.production -- node index.js
143
+ [dotenv][INFO] Injecting 12 production environment variables into your application process
144
+ ```
145
+
146
+ Combine multiple `.env` files if you like.
147
+
148
+ ```
149
+ $ dotenv run --env-file=.env.local --env-file=.env -- node index.js
150
+ [dotenv][INFO] Injecting 12 local, 1 development environment variables into your application process
151
+ ```
152
+
153
+ &nbsp;
154
+
155
+ ## Encrypt Your Env Files
156
+
157
+ WIP
158
+
159
+ &nbsp;
160
+
161
+ ## Usage
162
+
163
+ ### Guide
164
+
165
+ Begin by creating a simple 'hello world' program.
166
+
167
+ ```js
168
+ // index.js
169
+ console.log(`Hello ${process.env.HELLO}`)
170
+ ```
171
+
172
+ Run it.
173
+
174
+ ```js
175
+ $ node index.js
176
+ Hello undefined
177
+ ```
178
+
179
+ Run it with `dotenv`.
180
+
181
+ ```sh
182
+ $ dotenv run -- node index.js
183
+ [dotenv@x.x.x][WARN] ENOENT: no such file or directory, open '/../../.env'
184
+ Hello undefined
185
+ ```
186
+
187
+ It warns you when there is no `.env` file (pass the `--quiet` flag to suppress these warnings).
188
+
189
+ Create the `.env` file.
190
+
191
+ ```ini
192
+ # env
193
+ JELLO="World"
194
+ ```
195
+
196
+ Run it again.
197
+
198
+ ```sh
199
+ $ dotenv run -- node index.js
200
+ [dotenv@x.x.x][INFO] Injecting 0 environment variables into your application process
201
+ Hello undefined
202
+ ```
203
+
204
+ Hrm, still undefined. Pass the `--debug` flag to debug the issue. I'll give you a hint: 🍮
205
+
206
+ ```sh
207
+ $ dotenv run --debug -- node index.js
208
+ [dotenv@x.x.x][VERBOSE] Loading env from /../../.env
209
+ [dotenv@x.x.x][DEBUG] Reading env from /../../.env
210
+ [dotenv@x.x.x][DEBUG] Parsing env from /../../.env
211
+ [dotenv@x.x.x][DEBUG] {"JELLO":"World"}
212
+
213
+ # Oops, HELLO not JELLO ^^
214
+ ```
215
+
216
+ Fix your `.env` file.
217
+
218
+ ```ini
219
+ # .env
220
+ HELLO="World"
221
+ ```
222
+
223
+ One last time. [Le tired](https://youtu.be/kCpjgl2baLs?t=45).
224
+
225
+ ```sh
226
+ $ dotenv run -- node index.js
227
+ [dotenv@x.x.x][INFO] Injecting 0 environment variables into your application process
228
+ Hello undefined
229
+ ```
230
+
231
+ &nbsp;
232
+
233
+
234
+ ## Install
235
+
236
+ Installing with [`brew`](https://brew.sh) is most straight forward:
237
+
238
+ ```sh
239
+ brew install dotenvx/brew/dotenvx
240
+ ```
241
+
242
+ ### Other Ways to Install
243
+
244
+ 1. After `brew`, installing globally using [`npm`](https://www.npmjs.com/package/@dotenvx/dotenvx) is easiest:
245
+
246
+ ```sh
247
+ npm install @dotenvx/dotenvx --global
248
+ ```
249
+
250
+ 2. Or use with [`npx`](https://www.npmjs.com/package/npx):
251
+
252
+ ```sh
253
+ npx @dotenvx/dotenvx help
254
+ ```
255
+
256
+ 3. dotenvx is a standalone binary, so (if you want) you can just download it directly:
257
+
258
+ ```sh
259
+ # download it to `./dotenvx`
260
+ curl -Lo ./dotenvx --compressed -f --proto '=https' https://github.com/dotenvx/dotenvx/releases/latest/download/dotenvx-$(uname)-$(uname -m).tar.gz
261
+
262
+ # install it to `/usr/local/bin/dotenvx`
263
+ sudo install -m 755 dotenvx /usr/local/bin
264
+
265
+ # check it works
266
+ dotenvx --help
267
+ ```
268
+
269
+ ## Contributing
270
+
271
+ If you have questions or feedback:
272
+
273
+ * [github.com/dotenvx/dotenvx](https://github.com/dotenvx/dotenvx) - bugs and discussions
274
+ * [@dotenvx 𝕏](https://x.com/dotenvx) (DMs are open)
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "version": "0.2.23",
3
+ "name": "@dotenvx/dotenvx",
4
+ "description": "a better dotenv–from the creator of `dotenv`",
5
+ "author": "@motdotla",
6
+ "keywords": [
7
+ "dotenv",
8
+ "env"
9
+ ],
10
+ "homepage": "https://github.com/dotenvx/dotenvx",
11
+ "repository": "dotenvx/dotenvx",
12
+ "license": "MIT",
13
+ "files": [
14
+ "src/**/*"
15
+ ],
16
+ "main": "src/lib/main.js",
17
+ "bin": {
18
+ "dotenvx": "./src/cli/dotenvx.js",
19
+ "git-dotenvx": "./src/cli/dotenvx.js"
20
+ },
21
+ "scripts": {
22
+ "standard": "standard",
23
+ "standard:fix": "standard --fix",
24
+ "test": "jest"
25
+ },
26
+ "dependencies": {
27
+ "commander": "^11.1.0",
28
+ "dotenv": "^16.3.1",
29
+ "winston": "^3.11.0"
30
+ },
31
+ "devDependencies": {
32
+ "jest": "^29.7.0",
33
+ "jest-mock-process": "^2.0.0",
34
+ "pkg": "^5.8.1",
35
+ "standard": "^17.1.0"
36
+ },
37
+ "standard": {
38
+ "env": [
39
+ "jest"
40
+ ]
41
+ },
42
+ "publishConfig": {
43
+ "access": "public"
44
+ }
45
+ }
@@ -0,0 +1,116 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs')
4
+ const { Command } = require('commander')
5
+ const program = new Command()
6
+
7
+ // constants
8
+ const ENCODING = 'utf8'
9
+
10
+ const logger = require('./../shared/logger')
11
+ const helpers = require('./helpers')
12
+ const packageJson = require('./../shared/packageJson')
13
+ const main = require('./../lib/main')
14
+
15
+ // global log levels
16
+ program
17
+ .option('-l, --log-level <level>', 'set log level', 'info')
18
+ .option('-q, --quiet', 'sets log level to error')
19
+ .option('-v, --verbose', 'sets log level to verbose')
20
+ .option('-d, --debug', 'sets log level to debug')
21
+ .hook('preAction', (thisCommand, actionCommand) => {
22
+ const options = thisCommand.opts()
23
+
24
+ if (options.logLevel) {
25
+ logger.level = options.logLevel
26
+ logger.debug(`Setting log level to ${options.logLevel}`)
27
+ }
28
+
29
+ // --quiet overides --log-level. only errors will be shown
30
+ if (options.quiet) {
31
+ logger.level = 'error'
32
+ }
33
+
34
+ // --verbose overrides --quiet
35
+ if (options.verbose) {
36
+ logger.level = 'verbose'
37
+ }
38
+
39
+ // --debug overrides --verbose
40
+ if (options.debug) {
41
+ logger.level = 'debug'
42
+ }
43
+ })
44
+
45
+ // cli
46
+ program
47
+ .name(packageJson.name)
48
+ .description(packageJson.description)
49
+ .version(packageJson.version)
50
+
51
+ // commands
52
+ program.command('encrypt')
53
+ .description('encrypt something')
54
+ .action((_str, _options) => {
55
+ console.log('encrypted!')
56
+ })
57
+
58
+ program.command('decrypt')
59
+ .description('decrypt something')
60
+ .action((_str, _options) => {
61
+ console.log('decrypted!')
62
+ })
63
+
64
+ program.command('run')
65
+ .description('Inject env variables into your application process')
66
+ .option('-f, --env-file <paths...>', 'path to your env file', '.env')
67
+ .option('-o, --overload', 'override existing env variables')
68
+ .action(function () {
69
+ // injecting 1 environment variable from ${options.envFile}
70
+ const options = this.opts()
71
+ logger.debug('Configuring options')
72
+ logger.debug(options)
73
+
74
+ // convert to array if needed
75
+ let optionEnvFile = options.envFile
76
+ if (!Array.isArray(optionEnvFile)) {
77
+ optionEnvFile = [optionEnvFile]
78
+ }
79
+
80
+ const env = {}
81
+
82
+ for (const envFilepath of optionEnvFile) {
83
+ const filepath = helpers.resolvePath(envFilepath)
84
+
85
+ logger.verbose(`Loading env from ${filepath}`)
86
+
87
+ try {
88
+ logger.debug(`Reading env from ${filepath}`)
89
+ const src = fs.readFileSync(filepath, { encoding: ENCODING })
90
+
91
+ logger.debug(`Parsing env from ${filepath}`)
92
+ const parsed = main.parse(src)
93
+
94
+ logger.debug(`Populating env from ${filepath}`)
95
+ main.populate(process.env, parsed, { debug: (logger.level === 'debug'), override: options.overload })
96
+ } catch (e) {
97
+ logger.warn(e)
98
+ }
99
+ }
100
+
101
+ logger.info('Injecting X environment variables into your application process')
102
+
103
+ // Extract command and arguments after '--'
104
+ const commandIndex = process.argv.indexOf('--')
105
+ if (commandIndex === -1 || commandIndex === process.argv.length - 1) {
106
+ logger.error('At least one argument is required after the run command, received 0.')
107
+ logger.error('Exiting')
108
+ process.exit(1)
109
+ } else {
110
+ const subCommand = process.argv.slice(commandIndex + 1)
111
+
112
+ helpers.executeCommand(subCommand, env)
113
+ }
114
+ })
115
+
116
+ program.parse(process.argv)
@@ -0,0 +1,28 @@
1
+ const path = require('path')
2
+ const { spawn } = require('child_process')
3
+
4
+ // resolve path based on current running process location
5
+ const resolvePath = function (filepath) {
6
+ return path.resolve(process.cwd(), filepath)
7
+ }
8
+
9
+ const executeCommand = function (subCommand, env) {
10
+ const subprocess = spawn(subCommand[0], subCommand.slice(1), {
11
+ stdio: 'inherit',
12
+ shell: true,
13
+ env: { ...process.env, ...env }
14
+ })
15
+
16
+ subprocess.on('close', (code) => {
17
+ process.exit(code)
18
+ })
19
+
20
+ subprocess.on('error', (_err) => {
21
+ process.exit(1)
22
+ })
23
+ }
24
+
25
+ module.exports = {
26
+ resolvePath,
27
+ executeCommand
28
+ }
@@ -0,0 +1,28 @@
1
+ const logger = require('./../shared/logger')
2
+ const dotenv = require('dotenv')
3
+
4
+ const config = function (options) {
5
+ return dotenv.config(options)
6
+ }
7
+
8
+ const parse = function (src) {
9
+ const result = dotenv.parse(src)
10
+
11
+ logger.debug(result)
12
+
13
+ return result
14
+ }
15
+
16
+ const populate = function (processEnv, parsed, options = {}) {
17
+ const result = dotenv.populate(processEnv, parsed, options = {})
18
+
19
+ logger.debug(process.env)
20
+
21
+ return result
22
+ }
23
+
24
+ module.exports = {
25
+ config,
26
+ parse,
27
+ populate
28
+ }
@@ -0,0 +1,26 @@
1
+ const winston = require('winston')
2
+
3
+ const printf = winston.format.printf
4
+ const combine = winston.format.combine
5
+ const createLogger = winston.createLogger
6
+ const transports = winston.transports
7
+
8
+ const packageJson = require('./packageJson')
9
+
10
+ const dotenvxFormat = printf(({ level, message, label, timestamp }) => {
11
+ const formattedMessage = typeof message === 'object' ? JSON.stringify(message) : message
12
+
13
+ return `[dotenvx@${packageJson.version}][${level.toUpperCase()}] ${formattedMessage}`
14
+ })
15
+
16
+ const logger = createLogger({
17
+ level: 'info',
18
+ format: combine(
19
+ dotenvxFormat
20
+ ),
21
+ transports: [
22
+ new transports.Console()
23
+ ]
24
+ })
25
+
26
+ module.exports = logger
@@ -0,0 +1,8 @@
1
+ const fs = require('fs')
2
+ const path = require('path')
3
+
4
+ const packageJsonPath = path.join(__dirname, '../../package.json')
5
+
6
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'))
7
+
8
+ module.exports = packageJson