@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 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
- const config = require('@/trenskow/config');
9
+ import config from '@trenskow/config';
10
+
11
+ const myConfig = await config();
10
12
  ````
11
13
 
12
14
  # What it does
13
15
 
14
- Turn this
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 this
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/packages/isvalid) package is build into the library and can be used to validate the configuration.
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 config = await require('@trenskow/config').validate({
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
- ## Validate Once and Require
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
- # LICENSE
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
- const
4
- caseit = require('@trenskow/caseit'),
5
- merge = require('merge'),
6
- isvalid = require('isvalid'),
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
- // Give it back.
101
- module.exports = cleanIt(config);
102
-
103
- module.exports.validate = async (schema, options = {}) => {
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
- schema = isvalid.formalize(schema);
82
+ // Give it back.
83
+ export default async (schema = {}, options = {}) => {
106
84
 
107
- module.exports = merge(module.exports, cleanIt(config, isvalid.keyPaths(schema).all(Object).filter((keyPath) => keyPath)), {
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 module.exports = merge(module.exports, await isvalid(
119
- module.exports,
120
- isvalid.merge(schema).with({
121
- 'validate': {
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": "2.1.12",
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": "^3.2.4",
30
- "keyd": "^1.5.7",
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
- "mocha": "^9.2.2"
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
- const
4
- { expect } = require('chai');
3
+ import { use, expect } from 'chai';
4
+ import merge from 'merge';
5
+ import chaiAsPromised from 'chai-as-promised';
5
6
 
6
- process.env = {
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
- expect(config).to.have.property('configTest');
25
- expect(config.configTest).to.have.property('$').equal('true');
26
- expect(config.configTest).to.have.property('obj');
27
- expect(config.configTest.obj).to.have.property('string').equal('string');
28
- expect(config.configTest.obj).to.have.property('number').equal('200');
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.', (done) => {
31
- config.validate({
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 Number.');
43
+ expect(error.message).to.equal('Is not of type number.');
41
44
  expect(error.keyPath).to.equal('CONFIG_TEST_OBJ_STRING');
42
- done();
43
- }).catch(done);
45
+ });
44
46
  });
45
- it ('must validate', (done) => {
46
- config.validate({
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((returned) => {
55
- expect(config).to.have.property('configTest');
56
- expect(config.configTest).to.have.property('$').equal(true);
57
- expect(config.configTest).to.have.property('obj');
58
- expect(config.configTest.obj).to.have.property('string').equal('string');
59
- expect(config.configTest.obj).to.have.property('number').equal(200);
60
- expect(config.validate).to.be.a('Function');
61
- expect(returned.configTest.obj).to.have.property('number').equal(200);
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
- const result = require('../');
67
- expect(result)
68
- .to.have.property('configTest')
69
- .to.have.property('array')
70
- .to.eql(['0', '1', '2', '3']);
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
- const result = require('../');
74
- expect(result)
75
- .to.have.property('configTest')
76
- .to.have.property('smallArray')
77
- .to.eql(['0']);
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.', (done) => {
98
- config.validate({
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
- done();
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
- };