Comparing version 1.0.0 to 1.0.1
85
index.js
'use strict' | ||
const internalsSymbol = Symbol('Lawn config') | ||
const validatorSymbol = Symbol('Lawn validators') | ||
const convertersSymbol = Symbol('Lawn converters') | ||
const createSymbol = Symbol('Lawn create') | ||
const validatorsSymbol = Symbol('Lawn validators') | ||
const transformationsSymbol = Symbol('Lawn transformations') | ||
const cloneSymbol = Symbol('Lawn create') | ||
const Lawn = { | ||
[internalsSymbol]: {}, | ||
[validatorSymbol]: [], | ||
[convertersSymbol]: [], | ||
[validatorsSymbol]: [], | ||
[transformationsSymbol]: [], | ||
[createSymbol] (changes, validator, converter) { | ||
[cloneSymbol] (changes, validator, converter) { | ||
const obj = Object.create(Lawn) | ||
obj[internalsSymbol] = Object.assign({}, this[internalsSymbol], changes) | ||
if (validator) { | ||
obj[validatorSymbol] = [...this[validatorSymbol], validator] | ||
} else { | ||
obj[validatorSymbol] = this[validatorSymbol] | ||
} | ||
if (converter) { | ||
obj[convertersSymbol] = [...this[convertersSymbol], converter] | ||
} else { | ||
obj[convertersSymbol] = this[convertersSymbol] | ||
} | ||
obj[internalsSymbol] = this[internalsSymbol] | ||
obj[validatorsSymbol] = this[validatorsSymbol] | ||
obj[transformationsSymbol] = this[transformationsSymbol] | ||
return obj | ||
}, | ||
props (props) { | ||
const obj = this[cloneSymbol]() | ||
obj[internalsSymbol] = Object.assign({}, this[internalsSymbol], props) | ||
return obj | ||
}, | ||
validation (validation) { | ||
const obj = this[cloneSymbol]() | ||
obj[validatorsSymbol] = [...this[validatorsSymbol], validation] | ||
return obj | ||
}, | ||
transformation (transformation) { | ||
const obj = this[cloneSymbol]() | ||
obj[transformationsSymbol] = [...this[transformationsSymbol], transformation] | ||
return obj | ||
}, | ||
get string () { | ||
return this[createSymbol]({ type: 'string' }) | ||
return this.props({ type: 'string' }) | ||
}, | ||
get number () { | ||
return this[createSymbol]({ type: 'number' }, { message: 'is not a number', fn: v => !Number.isNaN(v) }, v => parseInt(v, 10)) | ||
return this.props({ type: 'number' }) | ||
.transformation(v => parseInt(v, 10)) | ||
.validation({ message: 'is not a number', fn: v => !Number.isNaN(v) }) | ||
}, | ||
get bool () { | ||
return this[createSymbol]({ type: 'bool' }, null, v => { | ||
switch (v.toLowerCase()) { | ||
case 'true': | ||
case 'yes': | ||
case 'y': | ||
case '1': | ||
return true | ||
default: | ||
return false | ||
} | ||
}) | ||
return this.props({ type: 'bool' }) | ||
.transformation(v => { | ||
switch (v.toLowerCase()) { | ||
case 'true': | ||
case 'yes': | ||
case 'y': | ||
case '1': | ||
return true | ||
default: | ||
return false | ||
} | ||
}) | ||
}, | ||
desc (description) { | ||
return this[createSymbol]({ description }) | ||
return this.props({ description }) | ||
}, | ||
example (example) { | ||
return this[createSymbol]({ example }) | ||
return this.props({ example }) | ||
}, | ||
default (def) { | ||
return this[createSymbol]({ default: def }) | ||
return this.props({ default: def }) | ||
}, | ||
@@ -72,4 +85,4 @@ | ||
const cfg = config[key][internalsSymbol] | ||
const converters = config[key][convertersSymbol] | ||
const validators = config[key][validatorSymbol] | ||
const transformations = config[key][transformationsSymbol] | ||
const validators = config[key][validatorsSymbol] | ||
const originalVal = properties[key] | ||
@@ -84,3 +97,3 @@ | ||
} else { | ||
val = converters.reduce((val, converter) => converter(val), originalVal) | ||
val = transformations.reduce((val, transformation) => transformation(val), originalVal) | ||
} | ||
@@ -87,0 +100,0 @@ |
{ | ||
"name": "lawn", | ||
"version": "1.0.0", | ||
"version": "1.0.1", | ||
"description": "The environment is dangerous. Your lawn is nice. Stay in your lawn.", | ||
@@ -10,14 +10,24 @@ "main": "index.js", | ||
"scripts": { | ||
"commit": "git-cz", | ||
"test": "mocha './{,!(node_modules)/**/}*.test.js'", | ||
"posttest": "standard", | ||
"lint": "eslint '**/*.js'", | ||
"coverage": "istanbul cover -x '*.test.js' _mocha -- './{,!(node_modules)/**/}*.test.js'" | ||
"coverage": "istanbul cover -x '*.test.js' _mocha -- './{,!(node_modules)/**/}*.test.js'", | ||
"precommit": "npm test", | ||
"postcommit": "npm test", | ||
"semantic-release": "semantic-release pre && npm publish && semantic-release post" | ||
}, | ||
"devDependencies": { | ||
"chai": "^4.1.2", | ||
"cz-conventional-changelog": "^2.0.0", | ||
"istanbul": "^0.4.5", | ||
"mocha": "^3.5.3", | ||
"standard": "^10.0.3", | ||
"strip-indent": "^2.0.0" | ||
"strip-indent": "^2.0.0", | ||
"semantic-release": "^8.0.3" | ||
}, | ||
"config": { | ||
"commitizen": { | ||
"path": "./node_modules/cz-conventional-changelog" | ||
} | ||
} | ||
} |
117
README.md
@@ -9,3 +9,3 @@ # Lawn | ||
```js | ||
require('lawn') | ||
const lawn = require('lawn') | ||
``` | ||
@@ -34,3 +34,4 @@ | ||
```js | ||
const lawnConfig = { | ||
// lawn-spec.js | ||
module.exports = { | ||
PORT: lawn.number.desc('The port that the server will listen on').default(8000), | ||
@@ -40,3 +41,6 @@ SECRET: lawn.string.desc('The encryption key. Set it very secretly').example('S3CR3T'), | ||
const config = lawn.validate(lawnConfig, process.env) | ||
// index.js | ||
const lawn = require('lawn') | ||
const lawnSpec = require('./lawn-spec') | ||
const config = lawn.validate(lawnSpec, process.env) | ||
``` | ||
@@ -59,3 +63,3 @@ | ||
```js | ||
console.log(lawn.output(lawnConfig)) | ||
console.log(lawn.output(lawnSpec)) | ||
``` | ||
@@ -71,1 +75,106 @@ | ||
``` | ||
## Spec API | ||
### lawn | ||
The root spec object. | ||
### lawn.validate(spec, [props]) | ||
Validate the given spec against the properties given. If no properties are | ||
given, `process.env` is used. | ||
If the validation succeeds, the transformed configuration will be returned. | ||
If the validation fails, an error will be thrown with a reasonable error message. | ||
```js | ||
const lawnSpec = { | ||
PORT: lawn.number.description('The port to listen on').default(8000), | ||
DEBUG: lawn.bool.description('Whether to start in debug mode').default(true), | ||
} | ||
lawn.validate(lawnSpec, {}) | ||
//=> { PORT: 8000, DEBUG: true } | ||
lawn.validate(lawnSpec, { PORT: "3500", DEBUG: "0" } | ||
//=> { PORT: 3500, DEBUG: false } | ||
lawn.validate(lawnSpec, { PORT: "Yes, please" } | ||
//=> throws "PORT is invalid: 'Yes, please' is not a number" | ||
``` | ||
### lawn.output(spec) | ||
Returns a string in [dotenv format][dotenv] format, including descriptions (if | ||
set) and example values. | ||
```js | ||
const lawnSpec = { | ||
PORT: lawn.number | ||
.description('The port to listen on') | ||
.default(8000), | ||
AWS_ACCESS_KEY_ID: lawn.string | ||
.description('The AWS access key for the S3 bucket') | ||
.example('AKIAIOSFODNN7EXAMPLE'), | ||
AWS_SECRET_ACCESS_KEY: lawn.string | ||
.description('The AWS secret key for the S3 bucket') | ||
.example('wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY'), | ||
AWS_REGION: lawn.string | ||
.description('The AWS region where the S3 bucket resides') | ||
.default('us-east-1'), | ||
} | ||
lawn.output(lawnSpec) | ||
=> `# The port to listen on | ||
# PORT=8000 | ||
# The AWS access key for the S3 bucket | ||
AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE | ||
# The AWS secret key for the S3 bucket | ||
AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY | ||
# The AWS region where the S3 bucket resides | ||
# AWS_REGION=us-east-1` | ||
``` | ||
[dotenv]: https://www.npmjs.com/package/dotenv | ||
### .string | ||
Declares that this property is a string. | ||
### .number | ||
Declares this this property is an integer. | ||
### .bool | ||
Declare that this property is a boolean. | ||
Values that resolve to `true` are: | ||
- `"true"` (case-insensitive) | ||
- `"yes"` (case-insensitive) | ||
- `"t"` (case-insensitive) | ||
- `"1"` | ||
All other values resolve to `false`. | ||
### .default(v) | ||
The default value of the property. If no environment variable is set for this | ||
property, then use the default. | ||
### .description(d) | ||
A description of the property. This is used when generating an example | ||
environment string. | ||
### .example(v) | ||
An example value of the property. This is used when generating an example | ||
environment string. |
Sorry, the diff of this file is not supported yet
13665
8
250
176
7