@adonisjs/env 4.0.3-0 → 4.1.0-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
@@ -78,7 +78,7 @@ Once you have the parsed objects, you can optionally validate them against a pre
78
78
  ```ts
79
79
  import { Env } from '@adonisjs/env'
80
80
 
81
- const validate = Env.rules({
81
+ const validator = Env.rules({
82
82
  PORT: Env.schema.number(),
83
83
  HOST: Env.schema.string({ format: 'host' })
84
84
  })
@@ -86,61 +86,29 @@ const validate = Env.rules({
86
86
 
87
87
  The `Env.schema` is a reference to the [@poppinss/validator-lite](https://github.com/poppinss/validator-lite) `schema` object. Make sure to go through the package README to view all the available methods and options.
88
88
 
89
- The `Env.rules` method returns a function to validate the environment variables. The return value is the validated object with type information inferred from the schema.
89
+ The `Env.rules` method returns an instance of the validator to validate the environment variables. The return value is the validated object with type information inferred from the schema.
90
90
 
91
91
  ```ts
92
- validate(process.env)
92
+ validator.validate(process.env)
93
93
  ```
94
94
 
95
- Following is a complete example of using the `EnvLoader`, `EnvParser`, and the validator to set up environment variables.
95
+ Following is a complete example of loading dot-env files and validating them in one go.
96
96
 
97
97
  > **Note**: Existing `process.env` variables have the top most priority over the variables defined in any of the files.
98
98
 
99
99
  ```ts
100
- import { EnvLoader, EnvParser, Env } from '@adonisjs/env'
101
-
102
- const lookupPath = new URL('./', import.meta.url)
103
- const loader = new EnvLoader(lookupPath)
104
- const envFiles = await loader.load()
105
-
106
- let envValues = {}
107
-
108
- envFiles.forEach(({ contents }) => {
109
- if (!contents.trim()) {
110
- return
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
- })
126
- })
100
+ import { Env } from '@adonisjs/env'
127
101
 
128
- // Now perform the validation
129
- const validate = Env.rules({
102
+ const env = await Env.create(new URL('./', import.meta.url), {
130
103
  PORT: Env.schema.number(),
131
104
  HOST: Env.schema.string({ format: 'host' })
132
105
  })
133
106
 
134
- const validated = validate(envValues)
135
- const env = new Env(validated)
136
-
137
107
  env.get('PORT') // is a number
138
108
  env.get('HOST') // is a string
139
109
  env.get('NODE_ENV') // is unknown, hence a string or undefined
140
110
  ```
141
111
 
142
- The above code may seem like a lot of work to set up environment variables. However, you have fine-grained control over each step. In the case of AdonisJS, all this boilerplate is hidden inside the framework's application bootstrapping logic.
143
-
144
112
  ## Known Exceptions
145
113
 
146
114
  ### E_INVALID_ENV_VARIABLES
package/build/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export { Env } from './src/env.js';
2
2
  export { EnvParser } from './src/parser.js';
3
3
  export { EnvLoader } from './src/loader.js';
4
+ export { EnvProcessor } from './src/processor.js';
4
5
  export { InvalidEnvVariablesException } from './src/exceptions/invalid_env_variables.js';
package/build/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  export { Env } from './src/env.js';
2
2
  export { EnvParser } from './src/parser.js';
3
3
  export { EnvLoader } from './src/loader.js';
4
+ export { EnvProcessor } from './src/processor.js';
4
5
  export { InvalidEnvVariablesException } from './src/exceptions/invalid_env_variables.js';
@@ -0,0 +1,3 @@
1
+ /// <reference types="node" resolution-mode="require"/>
2
+ declare const _default: import("util").DebugLogger;
3
+ export default _default;
@@ -0,0 +1,2 @@
1
+ import { debuglog } from 'node:util';
2
+ export default debuglog('adonisjs:env');
@@ -1,8 +1,14 @@
1
- import { EnvValidator } from './validator.js';
1
+ /// <reference types="node" resolution-mode="require"/>
2
2
  import { type ValidateFn } from '@poppinss/validator-lite';
3
+ import { EnvValidator } from './validator.js';
3
4
  export declare class Env<EnvValues extends Record<string, any>> {
4
5
  #private;
5
6
  constructor(values: EnvValues);
7
+ static create<Schema extends {
8
+ [key: string]: ValidateFn<unknown>;
9
+ }>(appRoot: URL, schema: Schema): Promise<Env<{
10
+ [K in keyof Schema]: ReturnType<Schema[K]>;
11
+ }>>;
6
12
  static schema: {
7
13
  number: typeof import("@poppinss/validator-lite/build/src/schema/number.js").number;
8
14
  string: typeof import("@poppinss/validator-lite/build/src/schema/string.js").string;
@@ -11,7 +17,7 @@ export declare class Env<EnvValues extends Record<string, any>> {
11
17
  };
12
18
  static rules<T extends {
13
19
  [key: string]: ValidateFn<unknown>;
14
- }>(schema: T): EnvValidator<T>['validate'];
20
+ }>(schema: T): EnvValidator<T>;
15
21
  get<K extends keyof EnvValues>(key: K): EnvValues[K];
16
22
  get<K extends keyof EnvValues>(key: K, defaultValue: Exclude<EnvValues[K], undefined>): Exclude<EnvValues[K], undefined>;
17
23
  get(key: string): string | undefined;
package/build/src/env.js CHANGED
@@ -1,14 +1,20 @@
1
- import { EnvValidator } from './validator.js';
2
1
  import { schema as envSchema } from '@poppinss/validator-lite';
2
+ import { EnvValidator } from './validator.js';
3
+ import { EnvProcessor } from './processor.js';
3
4
  export class Env {
4
5
  #values;
5
6
  constructor(values) {
6
7
  this.#values = values;
7
8
  }
9
+ static async create(appRoot, schema) {
10
+ const values = await new EnvProcessor(appRoot).process();
11
+ const validator = this.rules(schema);
12
+ return new Env(validator.validate(values));
13
+ }
8
14
  static schema = envSchema;
9
15
  static rules(schema) {
10
16
  const validator = new EnvValidator(schema);
11
- return validator.validate.bind(validator);
17
+ return validator;
12
18
  }
13
19
  get(key, defaultValue) {
14
20
  if (this.#values[key] !== undefined) {
@@ -1,6 +1,7 @@
1
1
  import { fileURLToPath } from 'node:url';
2
2
  import { readFile } from 'node:fs/promises';
3
3
  import { isAbsolute, join } from 'node:path';
4
+ import debug from './debug.js';
4
5
  export class EnvLoader {
5
6
  #appRoot;
6
7
  constructor(appRoot) {
@@ -21,11 +22,18 @@ export class EnvLoader {
21
22
  const ENV_PATH = process.env.ENV_PATH;
22
23
  const NODE_ENV = process.env.NODE_ENV;
23
24
  const envFiles = [];
25
+ if (debug.enabled) {
26
+ debug('ENV_PATH variable is %s', ENV_PATH ? 'set' : 'not set');
27
+ debug('NODE_ENV variable is %s', NODE_ENV ? 'set' : 'not set');
28
+ }
24
29
  const baseEnvPath = ENV_PATH
25
30
  ? isAbsolute(ENV_PATH)
26
31
  ? ENV_PATH
27
32
  : join(this.#appRoot, ENV_PATH)
28
33
  : this.#appRoot;
34
+ if (debug.enabled) {
35
+ debug('dot-env files base path "%s"', baseEnvPath);
36
+ }
29
37
  if (NODE_ENV) {
30
38
  const nodeEnvLocalFile = join(baseEnvPath, `.env.${process.env.NODE_ENV}.local`);
31
39
  envFiles.push({
@@ -0,0 +1,6 @@
1
+ /// <reference types="node" resolution-mode="require"/>
2
+ export declare class EnvProcessor {
3
+ #private;
4
+ constructor(appRoot: URL);
5
+ process(): Promise<Record<string, any>>;
6
+ }
@@ -0,0 +1,39 @@
1
+ import debug from './debug.js';
2
+ import { EnvParser } from './parser.js';
3
+ import { EnvLoader } from './loader.js';
4
+ export class EnvProcessor {
5
+ #appRoot;
6
+ constructor(appRoot) {
7
+ this.#appRoot = appRoot;
8
+ }
9
+ #processContents(envContents, store) {
10
+ if (!envContents.trim()) {
11
+ return store;
12
+ }
13
+ const values = new EnvParser(envContents).parse();
14
+ Object.keys(values).forEach((key) => {
15
+ let value = process.env[key];
16
+ if (!value) {
17
+ value = values[key];
18
+ process.env[key] = values[key];
19
+ }
20
+ if (!store[key]) {
21
+ store[key] = value;
22
+ }
23
+ });
24
+ return store;
25
+ }
26
+ async #loadAndProcessDotFiles() {
27
+ const loader = new EnvLoader(this.#appRoot);
28
+ const envFiles = await loader.load();
29
+ if (debug.enabled) {
30
+ debug('processing .env files (priority from top to bottom) %O', envFiles.map((file) => file.path));
31
+ }
32
+ const envValues = {};
33
+ envFiles.forEach(({ contents }) => this.#processContents(contents, envValues));
34
+ return envValues;
35
+ }
36
+ async process() {
37
+ return this.#loadAndProcessDotFiles();
38
+ }
39
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adonisjs/env",
3
- "version": "4.0.3-0",
3
+ "version": "4.1.0-0",
4
4
  "description": "Environment variable manager for Node.js",
5
5
  "main": "build/index.js",
6
6
  "type": "module",
@@ -14,7 +14,7 @@
14
14
  },
15
15
  "scripts": {
16
16
  "pretest": "npm run lint",
17
- "test": "c8 npm run vscode:test",
17
+ "test": "cross-env NODE_DEBUG=adonisjs:env c8 npm run vscode:test",
18
18
  "clean": "del-cli build",
19
19
  "compile": "npm run lint && npm run clean && tsc",
20
20
  "build": "npm run compile",
@@ -41,12 +41,13 @@
41
41
  "@japa/runner": "^2.2.2",
42
42
  "@japa/spec-reporter": "^1.3.2",
43
43
  "@poppinss/dev-utils": "^2.0.3",
44
- "@swc/core": "^1.3.21",
44
+ "@swc/core": "^1.3.22",
45
45
  "@types/fs-extra": "^9.0.13",
46
- "@types/node": "^18.11.10",
46
+ "@types/node": "^18.11.13",
47
47
  "c8": "^7.12.0",
48
+ "cross-env": "^7.0.3",
48
49
  "del-cli": "^5.0.0",
49
- "eslint": "^8.28.0",
50
+ "eslint": "^8.29.0",
50
51
  "eslint-config-prettier": "^8.5.0",
51
52
  "eslint-plugin-adonis": "^3.0.3",
52
53
  "eslint-plugin-prettier": "^4.2.1",
@@ -54,9 +55,9 @@
54
55
  "github-label-sync": "^2.2.0",
55
56
  "husky": "^8.0.2",
56
57
  "np": "^7.6.2",
57
- "prettier": "^2.8.0",
58
+ "prettier": "^2.8.1",
58
59
  "ts-node": "^10.9.1",
59
- "typescript": "^4.9.3"
60
+ "typescript": "^4.9.4"
60
61
  },
61
62
  "dependencies": {
62
63
  "@poppinss/utils": "^6.1.0-0",