Commit efc4800
Changed files (7)
docs/v7/api.md
@@ -204,3 +204,17 @@ The [yaml](https://www.npmjs.com/package/yaml) package.
```js
console.log(YAML.parse('foo: bar').foo)
```
+
+
+## loadDotenv
+
+Read env files and collects it into environment variables.
+
+```js
+const env = loadDotenv(env1, env2)
+console.log((await $({ env })`echo $FOO`).stdout)
+---
+const env = loadDotenv(env1)
+$.env = env
+console.log((await $`echo $FOO`).stdout)
+```
\ No newline at end of file
src/goods.ts
@@ -21,6 +21,7 @@ import {
isStringLiteral,
parseBool,
parseDuration,
+ readEnvFromFile,
toCamelCase,
} from './util.js'
import {
@@ -217,3 +218,10 @@ export async function spinner<T>(
}
})
}
+
+/**
+ *
+ * Read env files and collects it into environment variables
+ */
+export const loadDotenv = (...files: string[]): NodeJS.ProcessEnv =>
+ files.reduce<NodeJS.ProcessEnv>((m, f) => readEnvFromFile(f, m), {})
test/cli.test.js
@@ -17,21 +17,8 @@ import { test, describe, before, after } from 'node:test'
import { fileURLToPath } from 'node:url'
import net from 'node:net'
import getPort from 'get-port'
-import {
- argv,
- importPath,
- injectGlobalRequire,
- isMain,
- main,
- normalizeExt,
- runScript,
- printUsage,
- scriptFromStdin,
- scriptFromHttp,
- transformMarkdown,
- writeAndImport,
-} from '../build/cli.js'
-import { $, path, fs, tmpfile, tmpdir } from '../build/index.js'
+import { $, path, tmpfile, tmpdir, fs } from '../build/index.js'
+import { isMain, normalizeExt, transformMarkdown } from '../build/cli.js'
const __filename = fileURLToPath(import.meta.url)
const spawn = $.spawn
test/core.test.js
@@ -26,24 +26,20 @@ import {
resolveDefaults,
cd,
syncProcessCwd,
- log,
- kill,
- defaults,
within,
usePowerShell,
usePwsh,
useBash,
} from '../build/core.js'
import {
+ tempfile,
fs,
- nothrow,
- quiet,
+ quote,
+ quotePowerShell,
sleep,
- tempfile,
- tempdir,
+ quiet,
which,
} from '../build/index.js'
-import { quote, quotePowerShell } from '../build/util.js'
describe('core', () => {
describe('resolveDefaults()', () => {
test/export.test.js
@@ -331,6 +331,7 @@ describe('index', () => {
assert.equal(typeof index.globby.isGitIgnored, 'function', 'index.globby.isGitIgnored')
assert.equal(typeof index.globby.isGitIgnoredSync, 'function', 'index.globby.isGitIgnoredSync')
assert.equal(typeof index.kill, 'function', 'index.kill')
+ assert.equal(typeof index.loadDotenv, 'function', 'index.loadDotenv')
assert.equal(typeof index.log, 'function', 'index.log')
assert.equal(typeof index.minimist, 'function', 'index.minimist')
assert.equal(typeof index.nothrow, 'function', 'index.nothrow')
test/goods.test.js
@@ -13,9 +13,9 @@
// limitations under the License.
import assert from 'node:assert'
-import { test, describe } from 'node:test'
-import { $, chalk } from '../build/index.js'
-import { echo, sleep, parseArgv } from '../build/goods.js'
+import { test, describe, after } from 'node:test'
+import { $, chalk, fs, tempfile } from '../build/index.js'
+import { echo, sleep, parseArgv, loadDotenv } from '../build/goods.js'
describe('goods', () => {
function zx(script) {
@@ -173,4 +173,45 @@ describe('goods', () => {
}
)
})
+
+ describe('loadDotenv()', () => {
+ const env1 = tempfile(
+ '.env',
+ `FOO=BAR
+ BAR=FOO+`
+ )
+ const env2 = tempfile('.env.default', `BAR2=FOO2`)
+
+ after(() => {
+ fs.remove(env1)
+ fs.remove(env2)
+ })
+
+ test('handles multiple dotenv files', async () => {
+ const env = loadDotenv(env1, env2)
+
+ assert.equal((await $({ env })`echo $FOO`).stdout, 'BAR\n')
+ assert.equal((await $({ env })`echo $BAR`).stdout, 'FOO+\n')
+ assert.equal((await $({ env })`echo $BAR2`).stdout, 'FOO2\n')
+ })
+
+ test('handles replace evn', async () => {
+ const env = loadDotenv(env1)
+ $.env = env
+ assert.equal((await $`echo $FOO`).stdout, 'BAR\n')
+ assert.equal((await $`echo $BAR`).stdout, 'FOO+\n')
+ $.env = process.env
+ })
+
+ test('handle error', async () => {
+ try {
+ loadDotenv('./.env')
+
+ assert.throw()
+ } catch (e) {
+ assert.equal(e.code, 'ENOENT')
+ assert.equal(e.errno, -2)
+ }
+ })
+ })
})
test/util.test.js
@@ -14,7 +14,8 @@
import assert from 'node:assert'
import fs from 'node:fs'
-import { test, describe } from 'node:test'
+import { test, describe, after } from 'node:test'
+import { fs as fsCore } from '../build/index.js'
import {
formatCmd,
isString,
@@ -164,8 +165,10 @@ e.g. a private SSH key
})
describe('readEnvFromFile()', () => {
+ const file = tempfile('.env', 'ENV=value1\nENV2=value24')
+ after(() => fsCore.remove(file))
+
test('handles correct proccess.env', () => {
- const file = tempfile('.env', 'ENV=value1\nENV2=value24')
const env = readEnvFromFile(file)
assert.equal(env.ENV, 'value1')
assert.equal(env.ENV2, 'value24')
@@ -173,7 +176,6 @@ describe('readEnvFromFile()', () => {
})
test('handles correct some env', () => {
- const file = tempfile('.env', 'ENV=value1\nENV2=value24')
const env = readEnvFromFile(file, { version: '1.0.0', name: 'zx' })
assert.equal(env.ENV, 'value1')
assert.equal(env.ENV2, 'value24')