@adonisjs/env 4.0.0-2 → 4.0.1-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 +42 -44
- package/build/src/loader.d.ts +3 -3
- package/build/src/loader.js +36 -7
- package/build/src/parser.d.ts +1 -1
- package/build/src/parser.js +3 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -25,21 +25,22 @@ import { EnvLoader } from '@adonisjs/env'
|
|
|
25
25
|
const lookupPath = new URL('./', import.meta.url)
|
|
26
26
|
const loader = new EnvLoader(lookupPath)
|
|
27
27
|
|
|
28
|
-
const
|
|
28
|
+
const envFiles = await loader.load()
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
The return value is an array of objects with following properties.
|
|
32
32
|
|
|
33
|
-
-
|
|
34
|
-
-
|
|
35
|
-
- If the `ENV_PATH` environment variable is set, the loader will use that instead of the `.env` file. This allows overwriting the location of the dot-env file.
|
|
33
|
+
- `path`: The path to the loaded dot-env file.
|
|
34
|
+
- `contents`: The contents of the file.
|
|
36
35
|
|
|
36
|
+
Following is the list of loaded files. The array is ordered by the priority of the files. The first file has the highest priority and must override the variables from the last file.
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
38
|
+
| Priority | File name | Environment | Should I `.gitignore` it | Notes |
|
|
39
|
+
|----------|-----------|-------------|--------------------------|-------|
|
|
40
|
+
| 1st | `.env.[NODE_ENV].local` | Current environment | Yes | Loaded when `NODE_ENV` is set |
|
|
41
|
+
| 2nd | `.env.local` | All | Yes | Loaded in all the environments except `test` or `testing` environments |
|
|
42
|
+
| 3rd | `.env.[NODE_ENV]` | Current environment | No | Loaded when `NODE_ENV` is set |
|
|
43
|
+
| 4th | `.env` | All | Depends | Loaded in all the environments. You should `.gitignore` it when storing secrets in this file |
|
|
43
44
|
|
|
44
45
|
## EnvParser
|
|
45
46
|
The `EnvParser` class is responsible for parsing the contents of the `.env` file(s) and converting them into an object.
|
|
@@ -49,21 +50,22 @@ import { EnvLoader, EnvParser } from '@adonisjs/env'
|
|
|
49
50
|
|
|
50
51
|
const lookupPath = new URL('./', import.meta.url)
|
|
51
52
|
const loader = new EnvLoader(lookupPath)
|
|
52
|
-
const
|
|
53
|
+
const envFiles = await loader.load()
|
|
53
54
|
|
|
54
|
-
const envParser = new EnvParser(
|
|
55
|
-
|
|
55
|
+
const envParser = new EnvParser(`
|
|
56
|
+
PORT=3000
|
|
57
|
+
HOST=localhost
|
|
58
|
+
`)
|
|
56
59
|
|
|
57
|
-
console.log(envParser.parse()) // {
|
|
58
|
-
console.log(currentEnvParser.parse()) // { key: value }
|
|
60
|
+
console.log(envParser.parse()) // { PORT: '3000', HOST: 'localhost' }
|
|
59
61
|
```
|
|
60
62
|
|
|
61
63
|
The return value of `parser.parse` is an object with key-value pair. The parser also has support for interpolation.
|
|
62
64
|
|
|
63
|
-
|
|
65
|
+
By default, the parser prefers existing `process.env` values when they exist. However, you can instruct the parser to ignore existing `process.env` files as follows.
|
|
64
66
|
|
|
65
67
|
```ts
|
|
66
|
-
new EnvParser(envContents, {
|
|
68
|
+
new EnvParser(envContents, { ignoreProcessEnv: true })
|
|
67
69
|
```
|
|
68
70
|
|
|
69
71
|
## Validating environment variables
|
|
@@ -92,39 +94,35 @@ validate(process.env)
|
|
|
92
94
|
|
|
93
95
|
Following is a complete example of using the `EnvLoader`, `EnvParser`, and the validator to set up environment variables.
|
|
94
96
|
|
|
97
|
+
> **Note**: Existing `process.env` variables have the top most priority over the variables defined in any of the files.
|
|
98
|
+
|
|
95
99
|
```ts
|
|
96
100
|
import { EnvLoader, EnvParser, Env } from '@adonisjs/env'
|
|
97
101
|
|
|
98
102
|
const lookupPath = new URL('./', import.meta.url)
|
|
99
103
|
const loader = new EnvLoader(lookupPath)
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
* Loop over all the current env parsed values and let
|
|
104
|
-
* them take precedence over the existing process.env
|
|
105
|
-
* values.
|
|
106
|
-
*/
|
|
107
|
-
const currentEnvValues = new EnvParser(currentEnvContents).parse()
|
|
108
|
-
Object.keys(currentEnvValues).forEach((key) => {
|
|
109
|
-
process.env[key] = currentEnvValues[key]
|
|
110
|
-
})
|
|
104
|
+
const envFiles = await loader.load()
|
|
105
|
+
|
|
106
|
+
let envValues = {}
|
|
111
107
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
* Loop over all the parsed env values and set
|
|
116
|
-
* them on "process.env"
|
|
117
|
-
*
|
|
118
|
-
* However, if the value already exists on "process.env", then
|
|
119
|
-
* do not overwrite it, instead update the envValues
|
|
120
|
-
* object.
|
|
121
|
-
*/
|
|
122
|
-
Object.keys(envValues).forEach((key) => {
|
|
123
|
-
if (process.env[key]) {
|
|
124
|
-
envValues[key] = process.env[key]
|
|
125
|
-
} else {
|
|
126
|
-
process.env[key] = envValues[key]
|
|
108
|
+
envFiles.forEach(({ contents }) => {
|
|
109
|
+
if (!contents.trim()) {
|
|
110
|
+
return
|
|
127
111
|
}
|
|
112
|
+
|
|
113
|
+
const values = new EnvParser(contents).parse()
|
|
114
|
+
Object.keys(values).forEach((key) => {
|
|
115
|
+
let value = process.env[key]
|
|
116
|
+
|
|
117
|
+
if (!value) {
|
|
118
|
+
value = values[key]
|
|
119
|
+
process.env[key] = values[key]
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (!envValues[key]) {
|
|
123
|
+
envValues[key] = value
|
|
124
|
+
}
|
|
125
|
+
})
|
|
128
126
|
})
|
|
129
127
|
|
|
130
128
|
// Now perform the validation
|
|
@@ -133,7 +131,7 @@ const validate = Env.rules({
|
|
|
133
131
|
HOST: Env.schema.string({ format: 'host' })
|
|
134
132
|
})
|
|
135
133
|
|
|
136
|
-
const validated = validate(
|
|
134
|
+
const validated = validate(envValues)
|
|
137
135
|
const env = new Env(validated)
|
|
138
136
|
|
|
139
137
|
env.get('PORT') // is a number
|
package/build/src/loader.d.ts
CHANGED
package/build/src/loader.js
CHANGED
|
@@ -7,7 +7,7 @@ export class EnvLoader {
|
|
|
7
7
|
constructor(appRoot) {
|
|
8
8
|
this.#appRoot = typeof appRoot === 'string' ? appRoot : fileURLToPath(appRoot);
|
|
9
9
|
}
|
|
10
|
-
async #loadFile(filePath, optional =
|
|
10
|
+
async #loadFile(filePath, optional = true) {
|
|
11
11
|
try {
|
|
12
12
|
return await readFile(filePath, 'utf-8');
|
|
13
13
|
}
|
|
@@ -24,11 +24,40 @@ export class EnvLoader {
|
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
async load() {
|
|
27
|
-
const
|
|
28
|
-
const
|
|
29
|
-
const
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
27
|
+
const ENV_PATH = process.env.ENV_PATH;
|
|
28
|
+
const NODE_ENV = process.env.NODE_ENV;
|
|
29
|
+
const envFiles = [];
|
|
30
|
+
const baseEnvPath = ENV_PATH
|
|
31
|
+
? isAbsolute(ENV_PATH)
|
|
32
|
+
? ENV_PATH
|
|
33
|
+
: join(this.#appRoot, ENV_PATH)
|
|
34
|
+
: this.#appRoot;
|
|
35
|
+
if (NODE_ENV) {
|
|
36
|
+
const nodeEnvLocalFile = join(baseEnvPath, `.env.${process.env.NODE_ENV}.local`);
|
|
37
|
+
envFiles.push({
|
|
38
|
+
path: nodeEnvLocalFile,
|
|
39
|
+
contents: await this.#loadFile(nodeEnvLocalFile),
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
if (!NODE_ENV || !['test', 'testing'].includes(NODE_ENV)) {
|
|
43
|
+
const envLocalFile = join(baseEnvPath, '.env.local');
|
|
44
|
+
envFiles.push({
|
|
45
|
+
path: envLocalFile,
|
|
46
|
+
contents: await this.#loadFile(envLocalFile),
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
if (NODE_ENV) {
|
|
50
|
+
const nodeEnvFile = join(baseEnvPath, `.env.${process.env.NODE_ENV}`);
|
|
51
|
+
envFiles.push({
|
|
52
|
+
path: nodeEnvFile,
|
|
53
|
+
contents: await this.#loadFile(nodeEnvFile),
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
const envFile = join(baseEnvPath, '.env');
|
|
57
|
+
envFiles.push({
|
|
58
|
+
path: envFile,
|
|
59
|
+
contents: await this.#loadFile(envFile),
|
|
60
|
+
});
|
|
61
|
+
return envFiles;
|
|
33
62
|
}
|
|
34
63
|
}
|
package/build/src/parser.d.ts
CHANGED
package/build/src/parser.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import dotenv from 'dotenv';
|
|
2
2
|
export class EnvParser {
|
|
3
3
|
#envContents;
|
|
4
|
-
#preferProcessEnv =
|
|
4
|
+
#preferProcessEnv = true;
|
|
5
5
|
constructor(envContents, options) {
|
|
6
|
-
if (options?.
|
|
7
|
-
this.#preferProcessEnv =
|
|
6
|
+
if (options?.ignoreProcessEnv) {
|
|
7
|
+
this.#preferProcessEnv = false;
|
|
8
8
|
}
|
|
9
9
|
this.#envContents = envContents;
|
|
10
10
|
}
|