@trenskow/config 2.1.12 → 3.0.2
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/.eslintrc.cjs +50 -0
- package/README.md +9 -42
- package/index.js +20 -49
- package/package.json +7 -5
- package/test/index.js +46 -64
- package/.eslintrc.js +0 -49
package/.eslintrc.cjs
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
'env': {
|
|
3
|
+
'es6': true,
|
|
4
|
+
'node': true,
|
|
5
|
+
'mocha': true
|
|
6
|
+
},
|
|
7
|
+
'parserOptions': {
|
|
8
|
+
'ecmaVersion': 2017,
|
|
9
|
+
'sourceType': 'module'
|
|
10
|
+
},
|
|
11
|
+
'extends': 'eslint:recommended',
|
|
12
|
+
'rules': {
|
|
13
|
+
'indent': [
|
|
14
|
+
'error',
|
|
15
|
+
'tab'
|
|
16
|
+
],
|
|
17
|
+
'linebreak-style': [
|
|
18
|
+
'error',
|
|
19
|
+
'unix'
|
|
20
|
+
],
|
|
21
|
+
'quotes': [
|
|
22
|
+
'error',
|
|
23
|
+
'single'
|
|
24
|
+
],
|
|
25
|
+
'semi': [
|
|
26
|
+
'error',
|
|
27
|
+
'always'
|
|
28
|
+
],
|
|
29
|
+
'no-console': [
|
|
30
|
+
'error', {
|
|
31
|
+
'allow': [
|
|
32
|
+
'warn',
|
|
33
|
+
'error',
|
|
34
|
+
'info'
|
|
35
|
+
]
|
|
36
|
+
}
|
|
37
|
+
],
|
|
38
|
+
'no-unused-vars': [
|
|
39
|
+
'error', {
|
|
40
|
+
'argsIgnorePattern': '^_'
|
|
41
|
+
}
|
|
42
|
+
],
|
|
43
|
+
'no-empty': [
|
|
44
|
+
'error', {
|
|
45
|
+
'allowEmptyCatch': true
|
|
46
|
+
}
|
|
47
|
+
],
|
|
48
|
+
'require-atomic-updates': 'off'
|
|
49
|
+
}
|
|
50
|
+
};
|
package/README.md
CHANGED
|
@@ -6,12 +6,14 @@ Converts `process.env` into a neatly packed object.
|
|
|
6
6
|
# Usage
|
|
7
7
|
|
|
8
8
|
````javascript
|
|
9
|
-
|
|
9
|
+
import config from '@trenskow/config';
|
|
10
|
+
|
|
11
|
+
const myConfig = await config();
|
|
10
12
|
````
|
|
11
13
|
|
|
12
14
|
# What it does
|
|
13
15
|
|
|
14
|
-
|
|
16
|
+
It turns the environment variables below...
|
|
15
17
|
|
|
16
18
|
````bash
|
|
17
19
|
API_PORT=3000
|
|
@@ -22,7 +24,7 @@ API_USER_KEYS_1="key2"
|
|
|
22
24
|
API_USER_KEYS_2="key3"
|
|
23
25
|
````
|
|
24
26
|
|
|
25
|
-
into
|
|
27
|
+
...into the data below.
|
|
26
28
|
|
|
27
29
|
```javascript
|
|
28
30
|
{
|
|
@@ -41,14 +43,14 @@ into this
|
|
|
41
43
|
|
|
42
44
|
# Validation
|
|
43
45
|
|
|
44
|
-
The [isvalid](https://npmjs.org/
|
|
46
|
+
The [isvalid](https://npmjs.org/package/isvalid) package is build into the library and can be used to validate the configuration.
|
|
45
47
|
|
|
46
48
|
> See the documentation for `isvalid` on how to format the schema.
|
|
47
49
|
|
|
48
50
|
Example
|
|
49
51
|
|
|
50
52
|
````javascript
|
|
51
|
-
const
|
|
53
|
+
const myConfig = await config({
|
|
52
54
|
'port': {
|
|
53
55
|
type: Number,
|
|
54
56
|
required: true,
|
|
@@ -63,42 +65,7 @@ The above example will throw an error if the data cannot be validated. It will,
|
|
|
63
65
|
|
|
64
66
|
> The comment in the example is there to show what options *config* uses per default.
|
|
65
67
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
Validating replaces the exported data of the module – so you only have to validate once. An example of this is provided below.
|
|
69
|
-
|
|
70
|
-
````javascript
|
|
71
|
-
require('@trenskow/config')
|
|
72
|
-
|
|
73
|
-
.validate({
|
|
74
|
-
'port': {
|
|
75
|
-
type: Number,
|
|
76
|
-
required: true,
|
|
77
|
-
range: '-65535'
|
|
78
|
-
}
|
|
79
|
-
})
|
|
80
|
-
|
|
81
|
-
.then(myApp) // <-- start if successful
|
|
82
|
-
|
|
83
|
-
.catch((error) => {
|
|
84
|
-
|
|
85
|
-
console.error(`Invalid environment variable ${error.keyPath}: ${error.message}`);
|
|
86
|
-
|
|
87
|
-
// `error.keyPath` contains the failed environment variable - in this example `PORT`.
|
|
88
|
-
|
|
89
|
-
process.exit(1);
|
|
90
|
-
|
|
91
|
-
})
|
|
92
|
-
|
|
93
|
-
const myApp = function() {
|
|
94
|
-
|
|
95
|
-
const config = require('@trenskow/config');
|
|
96
|
-
|
|
97
|
-
// `config` now contains the validated data.
|
|
98
|
-
|
|
99
|
-
};
|
|
100
|
-
````
|
|
68
|
+
# License
|
|
101
69
|
|
|
102
|
-
|
|
70
|
+
See license in LICENSE.
|
|
103
71
|
|
|
104
|
-
MIT (See license)
|
package/index.js
CHANGED
|
@@ -1,37 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
keyd = require('keyd');
|
|
8
|
-
|
|
9
|
-
let config = {};
|
|
10
|
-
|
|
11
|
-
// We first split the env names at `_` and put them into objects.
|
|
12
|
-
Object.keys(process.env).filter((key) => process.env[key])
|
|
13
|
-
.forEach((key) => {
|
|
14
|
-
|
|
15
|
-
// Split and filter.
|
|
16
|
-
const parts = key
|
|
17
|
-
.split('_')
|
|
18
|
-
.filter((part) => part)
|
|
19
|
-
.map((part) => part.toLowerCase());
|
|
20
|
-
|
|
21
|
-
let obj = config;
|
|
22
|
-
|
|
23
|
-
parts
|
|
24
|
-
.forEach((part, idx) => {
|
|
25
|
-
// If we're at the end of the name assign { $: value }.
|
|
26
|
-
if (idx === parts.length - 1) {
|
|
27
|
-
obj[part] = { $: process.env[key] };
|
|
28
|
-
}
|
|
29
|
-
// - else just assign an empty object to store the children.
|
|
30
|
-
else {
|
|
31
|
-
obj = obj[part] = obj[part] || {};
|
|
32
|
-
}
|
|
33
|
-
});
|
|
34
|
-
});
|
|
3
|
+
import caseit from '@trenskow/caseit';
|
|
4
|
+
import merge from 'merge';
|
|
5
|
+
import isvalid, { formalize, keyPaths } from 'isvalid';
|
|
6
|
+
import keyd from 'keyd';
|
|
35
7
|
|
|
36
8
|
const fillArray = (value, length) => {
|
|
37
9
|
let result = [];
|
|
@@ -97,16 +69,20 @@ const cleanIt = (obj, expanded = [], keyPath = []) => {
|
|
|
97
69
|
|
|
98
70
|
};
|
|
99
71
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
72
|
+
const camelCased = (schema) => {
|
|
73
|
+
const result = {};
|
|
74
|
+
Object.keys(process.env)
|
|
75
|
+
.filter((key) => process.env[key])
|
|
76
|
+
.forEach((key) => {
|
|
77
|
+
keyd(result).set(`${caseit(key.toLowerCase(), 'domain')}.$`, process.env[key]);
|
|
78
|
+
});
|
|
79
|
+
return cleanIt(result, keyPaths(schema).all(Object).filter((keyPath) => keyPath));
|
|
80
|
+
};
|
|
104
81
|
|
|
105
|
-
|
|
82
|
+
// Give it back.
|
|
83
|
+
export default async (schema = {}, options = {}) => {
|
|
106
84
|
|
|
107
|
-
|
|
108
|
-
validate: module.exports.validate
|
|
109
|
-
});
|
|
85
|
+
schema = formalize(schema);
|
|
110
86
|
|
|
111
87
|
options = merge({
|
|
112
88
|
defaults: {
|
|
@@ -115,15 +91,10 @@ module.exports.validate = async (schema, options = {}) => {
|
|
|
115
91
|
}, options);
|
|
116
92
|
|
|
117
93
|
try {
|
|
118
|
-
return
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
type: 'AsyncFunction',
|
|
123
|
-
required: true
|
|
124
|
-
}
|
|
125
|
-
}),
|
|
126
|
-
options));
|
|
94
|
+
return await isvalid(
|
|
95
|
+
camelCased(schema),
|
|
96
|
+
schema,
|
|
97
|
+
options);
|
|
127
98
|
} catch (error) {
|
|
128
99
|
if (error.keyPath) {
|
|
129
100
|
error.keyPath = caseit(error.keyPath
|
package/package.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trenskow/config",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.2",
|
|
4
4
|
"description": "Converts `process.env` into a neatly packed object.",
|
|
5
5
|
"main": "index.js",
|
|
6
|
+
"type": "module",
|
|
6
7
|
"scripts": {
|
|
7
|
-
"test": "./node_modules/mocha/bin/mocha test/index.js"
|
|
8
|
+
"test": "./node_modules/mocha/bin/mocha.js test/index.js"
|
|
8
9
|
},
|
|
9
10
|
"repository": {
|
|
10
11
|
"type": "git",
|
|
@@ -26,12 +27,13 @@
|
|
|
26
27
|
"homepage": "https://github.com/trenskow/config#readme",
|
|
27
28
|
"dependencies": {
|
|
28
29
|
"@trenskow/caseit": "^1.3.0",
|
|
29
|
-
"isvalid": "^
|
|
30
|
-
"keyd": "^1.5.
|
|
30
|
+
"isvalid": "^4.0.1",
|
|
31
|
+
"keyd": "^1.5.9",
|
|
31
32
|
"merge": "^2.1.1"
|
|
32
33
|
},
|
|
33
34
|
"devDependencies": {
|
|
34
35
|
"chai": "^4.3.6",
|
|
35
|
-
"
|
|
36
|
+
"chai-as-promised": "^7.1.1",
|
|
37
|
+
"mocha": "^10.0.0"
|
|
36
38
|
}
|
|
37
39
|
}
|
package/test/index.js
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
import { use, expect } from 'chai';
|
|
4
|
+
import merge from 'merge';
|
|
5
|
+
import chaiAsPromised from 'chai-as-promised';
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
use(chaiAsPromised);
|
|
8
|
+
|
|
9
|
+
import config from '../index.js';
|
|
10
|
+
|
|
11
|
+
process.env = merge(process.env, {
|
|
7
12
|
CONFIG_TEST: 'true',
|
|
8
13
|
CONFIG_TEST_OBJ_STRING: 'string',
|
|
9
14
|
CONFIG_TEST_OBJ_NUMBER: '200',
|
|
@@ -15,35 +20,32 @@ process.env = {
|
|
|
15
20
|
CONFIG_TEST_ARRAY_3: '3',
|
|
16
21
|
CONFIG_TEST_THIS_IS_A_DEEPLY_NESTED_KEY: 'true',
|
|
17
22
|
config_test_small_array_0: '0'
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
const config = require('../');
|
|
23
|
+
});
|
|
21
24
|
|
|
22
25
|
describe('config', () => {
|
|
23
26
|
it ('must come back with the process.env proper converted.', () => {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
return config().then((result) => {
|
|
28
|
+
expect(result).to.have.property('configTest'),
|
|
29
|
+
expect(result).to.have.property('configTest').to.have.property('$').equal('true'),
|
|
30
|
+
expect(result).to.have.property('configTest').to.have.property('obj'),
|
|
31
|
+
expect(result).to.have.property('configTest').to.have.property('obj').to.have.property('string').equal('string'),
|
|
32
|
+
expect(result).to.have.property('configTest').to.have.property('obj').to.have.property('number').equal('200');
|
|
33
|
+
});
|
|
29
34
|
});
|
|
30
|
-
it ('must come back with the original environment name on error.', (
|
|
31
|
-
config
|
|
35
|
+
it ('must come back with the original environment name on error.', () => {
|
|
36
|
+
return config({
|
|
32
37
|
'configTest': {
|
|
33
38
|
'obj': {
|
|
34
39
|
'string': { type: Number, required: true }
|
|
35
40
|
}
|
|
36
41
|
}
|
|
37
|
-
}).then(() => {
|
|
38
|
-
done(new Error('Data was validated.'));
|
|
39
42
|
}).catch((error) => {
|
|
40
|
-
expect(error.message).to.equal('Is not of type
|
|
43
|
+
expect(error.message).to.equal('Is not of type number.');
|
|
41
44
|
expect(error.keyPath).to.equal('CONFIG_TEST_OBJ_STRING');
|
|
42
|
-
|
|
43
|
-
}).catch(done);
|
|
45
|
+
});
|
|
44
46
|
});
|
|
45
|
-
it ('must validate', (
|
|
46
|
-
config
|
|
47
|
+
it ('must validate', () => {
|
|
48
|
+
return config({
|
|
47
49
|
'configTest': {
|
|
48
50
|
'$': { type: Boolean, required: true},
|
|
49
51
|
'obj': {
|
|
@@ -51,51 +53,33 @@ describe('config', () => {
|
|
|
51
53
|
'number': { type: Number, required: true }
|
|
52
54
|
}
|
|
53
55
|
}
|
|
54
|
-
}).then((
|
|
55
|
-
expect(
|
|
56
|
-
expect(
|
|
57
|
-
expect(
|
|
58
|
-
expect(
|
|
59
|
-
expect(
|
|
60
|
-
expect(
|
|
61
|
-
|
|
62
|
-
done();
|
|
63
|
-
}).catch(done);
|
|
56
|
+
}).then((result) => {
|
|
57
|
+
expect(result).to.have.property('configTest');
|
|
58
|
+
expect(result.configTest).to.have.property('$').equal(true);
|
|
59
|
+
expect(result.configTest).to.have.property('obj');
|
|
60
|
+
expect(result.configTest.obj).to.have.property('string').equal('string');
|
|
61
|
+
expect(result.configTest.obj).to.have.property('number').equal(200);
|
|
62
|
+
expect(result.configTest.obj).to.have.property('number').equal(200);
|
|
63
|
+
});
|
|
64
64
|
});
|
|
65
65
|
it ('should convert arrays into arrays.', () => {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
66
|
+
return config().then((result) => {
|
|
67
|
+
expect(result)
|
|
68
|
+
.to.have.property('configTest')
|
|
69
|
+
.to.have.property('array')
|
|
70
|
+
.to.eql(['0', '1', '2', '3']);
|
|
71
|
+
});
|
|
71
72
|
});
|
|
72
73
|
it ('should convert even small arrays.', () => {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
it ('not remove validate method when unknown keys are set to be removed', (done) => {
|
|
80
|
-
config.validate({
|
|
81
|
-
'configTest': {
|
|
82
|
-
'$': { type: Boolean, required: true},
|
|
83
|
-
'obj': {
|
|
84
|
-
'string': { type: String, required: true }
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}, {
|
|
88
|
-
defaults: {
|
|
89
|
-
unknownKeys: 'remove'
|
|
90
|
-
}
|
|
91
|
-
}).then(() => {
|
|
92
|
-
const result = require('../');
|
|
93
|
-
expect(result.validate).to.be.a('Function');
|
|
94
|
-
done();
|
|
95
|
-
}).catch(done);
|
|
74
|
+
return config().then((result) => {
|
|
75
|
+
expect(result)
|
|
76
|
+
.to.have.property('configTest')
|
|
77
|
+
.to.have.property('smallArray')
|
|
78
|
+
.to.eql(['0']);
|
|
79
|
+
});
|
|
96
80
|
});
|
|
97
|
-
it ('must validate a deeply nested key.', (
|
|
98
|
-
config
|
|
81
|
+
it ('must validate a deeply nested key.', () => {
|
|
82
|
+
return config({
|
|
99
83
|
'configTest': {
|
|
100
84
|
'this': {
|
|
101
85
|
'is': {
|
|
@@ -109,10 +93,8 @@ describe('config', () => {
|
|
|
109
93
|
}
|
|
110
94
|
}
|
|
111
95
|
}
|
|
112
|
-
}).then(() => {
|
|
113
|
-
const result = require('../');
|
|
96
|
+
}).then((result) => {
|
|
114
97
|
expect(result.configTest.this.is.a.deeply.nested.key).to.equal(true);
|
|
115
|
-
|
|
116
|
-
}).catch(done);
|
|
98
|
+
});
|
|
117
99
|
});
|
|
118
100
|
});
|
package/.eslintrc.js
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
module.exports = {
|
|
2
|
-
"env": {
|
|
3
|
-
"es6": true,
|
|
4
|
-
"node": true,
|
|
5
|
-
"mocha": true
|
|
6
|
-
},
|
|
7
|
-
"parserOptions": {
|
|
8
|
-
"ecmaVersion": 2017
|
|
9
|
-
},
|
|
10
|
-
"extends": "eslint:recommended",
|
|
11
|
-
"rules": {
|
|
12
|
-
"indent": [
|
|
13
|
-
"error",
|
|
14
|
-
"tab"
|
|
15
|
-
],
|
|
16
|
-
"linebreak-style": [
|
|
17
|
-
"error",
|
|
18
|
-
"unix"
|
|
19
|
-
],
|
|
20
|
-
"quotes": [
|
|
21
|
-
"error",
|
|
22
|
-
"single"
|
|
23
|
-
],
|
|
24
|
-
"semi": [
|
|
25
|
-
"error",
|
|
26
|
-
"always"
|
|
27
|
-
],
|
|
28
|
-
"no-console": [
|
|
29
|
-
"error", {
|
|
30
|
-
"allow": [
|
|
31
|
-
"warn",
|
|
32
|
-
"error",
|
|
33
|
-
"info"
|
|
34
|
-
]
|
|
35
|
-
}
|
|
36
|
-
],
|
|
37
|
-
"no-unused-vars": [
|
|
38
|
-
"error", {
|
|
39
|
-
"argsIgnorePattern": "^_"
|
|
40
|
-
}
|
|
41
|
-
],
|
|
42
|
-
"no-empty": [
|
|
43
|
-
"error", {
|
|
44
|
-
"allowEmptyCatch": true
|
|
45
|
-
}
|
|
46
|
-
],
|
|
47
|
-
"require-atomic-updates": "off"
|
|
48
|
-
}
|
|
49
|
-
};
|