antonioru / antonioru/deep-waters
POC - Objectizing and enriching validation responses
- Ngôn ngữ chính
- JavaScript
- Star
- 201
- Fork
- 8
- Chỉ số merge pull request
- Không có pull request nào được merge trong 30 ngày
Mô tả
@antonioru I know your planning to tackle this this weekend. Couldn't get it off my mind and had some free time so heres a proof of concept script.
There's a lot of room for improvement and maybe some optimizations. Hope its helpful. Let me know what you think.
```javascript
/**
* All around functional helpers
*/
const compose = (...funcs) => (...args) => funcs.slice(1).reduce((acc, fn) => fn(acc), funcs[0](...args))
const partial = (fn, ...args) => (...rest) => fn(...args, ...rest)
/**
* Function for converting validator function
* boolean results to an object
*/
const objectize = (doc, fn, value) => ({
...doc,
valid: fn(value),
value
})
/**
* When composing many validator function this will
* aggregate into passed and failed results
*/
const aggregateResults = (results) => ({
passed: results.filter(r => r.valid),
failed: results.filter(r => !r.valid)
})
/**
* Some more helpers for composing and/or validations
*/
const applyDoc = (doc) => (result) => ({ ...result, ...doc })
const applyValue = (value) => (result) => ({ ...result, value })
const runValidators = (validators) => (value) => validators.map(validator => validator(value))
/**
* Determines if a result of composed functions
* is valid or not
*/
const orValid = (result) => ({ ...result, valid: result.passed.length > 0 })
const andValid = (result) => ({ ...result, valid: result.failed.length === 0 })
/**
* HOF used to take simple bool validation functions and
* convert to full object style validators
*/
const validator = (fn) => (doc) => partial(objectize, doc, fn)
// const orValidator = (...validators) => (doc) => value => orValid(applyDoc(doc)(aggregateResults(runValidators(validators)(value))))
const orValidator = (...validators) => (doc) => (value) => compose(
runValidators(validators),
aggregateResults,
applyDoc(doc),
applyValue(value),
orValid)(value)
const andValidator = (...validators) => (doc) => (value) => compose(
runValidators(validators),
aggregateResults,
applyDoc(doc),
applyValue(value),
andValid)(value)
/**
* Same as before - bool validator functions. Some of these
* abbreviated for POC sake. Validators that were previously
* composed at this level would now be composed further
* below as validators
*/
const ofClass = (name, value) => Object.prototype.toString.call(value) === `[object ${name}]`
const isFalse = value => value === false
const isZero = value => value === 0
const isNumber = partial(ofClass, 'Number')
const biggerThan = number => value => value > number
const smallerThan = number => value => value < number
/**
* Object style validators composed with
* the core bool validators and descripting
* objects
*/
const isZeroValidator = validator(isZero)({
name: 'isZero'
})
const isFalseValidator = validator(isFalse)({
name: 'isFalse'
})
const isNumberValidator = validator(isNumber)({
name: 'isNumber'
})
const biggerThanValidator = (min) => validator(biggerThan(min))({
name: 'biggerThan',
expected: `number bigger than ${min}`
})
const smallerThanValidator = (max) => validator(smallerThan(max))({
name: 'smallerThan',
expected: `number smaller than ${max}`
})
const isFalsyValidator = orValidator(isZeroValidator, isFalseValidator)({
name: 'isFalsy'
})
const betweenValidator = (min) => (max) => andValidator(biggerThanValidator(min), smallerThanValidator(max))({
name: 'betweenValidator'
})
/**
*
* Some POC Tests :smile:
*
*/
const assert = (condition) => {
if (!condition) throw 'Assertion failed'
}
const isZeroResult = isZeroValidator(0)
console.log('isZeroResult ===>', isZeroResult)
assert(isZeroResult.name === 'isZero')
assert(isZeroResult.valid === true)
assert(isZeroResult.value === 0)
const isFalseResult = isFalseValidator(true)
console.log('isFalseResult ===>', isFalseResult)
assert(isFalseResult.name === 'isFalse')
assert(isFalseResult.valid === false)
assert(isFalseResult.value === true)
const biggerThanResult = biggerThanValidator(10)(50)
console.log('biggerThanResult ===>', biggerThanResult)
assert(biggerThanResult.name === 'biggerThan')
assert(biggerThanResult.valid === true)
assert(biggerThanResult.value === 50)
assert(biggerThanResult.expected === 'number bigger than 10')
const isFalsyResult = isFalsyValidator(0)
console.log('isFalsyResult ===>', isFalsyResult)
assert(isFalsyResult.name === 'isFalsy')
assert(isFalsyResult.valid === true)
assert(isFalsyResult.value === 0)
assert(isFalsyResult.passed[0].name === 'isZero')
const betweenResult = betweenValidator(10)(20)(9)
console.log('betweenResult ===>', betweenResult)
assert(betweenResult.name === 'betweenValidator')
assert(betweenResult.valid === false)
assert(betweenResult.value === 9)
assert(betweenResult.passed[0].name === 'smallerThan')
```
Also, wasn't sure how to share this with you... hope issue is ok 👍❓
Hướng dẫn đóng góp
Đánh giá
Issue này chưa được đánh giá.