You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@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.
/*** All around functional helpers*/constcompose=(...funcs)=>(...args)=>funcs.slice(1).reduce((acc,fn)=>fn(acc),funcs[0](...args))constpartial=(fn, ...args)=>(...rest)=>fn(...args, ...rest)/*** Function for converting validator function* boolean results to an object*/constobjectize=(doc,fn,value)=>({
...doc,valid: fn(value),
value
})/*** When composing many validator function this will* aggregate into passed and failed results*/constaggregateResults=(results)=>({passed: results.filter(r=>r.valid),failed: results.filter(r=>!r.valid)})/*** Some more helpers for composing and/or validations*/constapplyDoc=(doc)=>(result)=>({ ...result, ...doc})constapplyValue=(value)=>(result)=>({ ...result, value })construnValidators=(validators)=>(value)=>validators.map(validator=>validator(value))/*** Determines if a result of composed functions* is valid or not*/constorValid=(result)=>({ ...result,valid: result.passed.length>0})constandValid=(result)=>({ ...result,valid: result.failed.length===0})/*** HOF used to take simple bool validation functions and* convert to full object style validators*/constvalidator=(fn)=>(doc)=>partial(objectize,doc,fn)// const orValidator = (...validators) => (doc) => value => orValid(applyDoc(doc)(aggregateResults(runValidators(validators)(value))))constorValidator=(...validators)=>(doc)=>(value)=>compose(runValidators(validators),aggregateResults,applyDoc(doc),applyValue(value),orValid)(value)constandValidator=(...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*/constofClass=(name,value)=>Object.prototype.toString.call(value)===`[object ${name}]`constisFalse=value=>value===falseconstisZero=value=>value===0constisNumber=partial(ofClass,'Number')constbiggerThan=number=>value=>value>numberconstsmallerThan=number=>value=>value<number/*** Object style validators composed with* the core bool validators and descripting* objects*/constisZeroValidator=validator(isZero)({name: 'isZero'})constisFalseValidator=validator(isFalse)({name: 'isFalse'})constisNumberValidator=validator(isNumber)({name: 'isNumber'})constbiggerThanValidator=(min)=>validator(biggerThan(min))({name: 'biggerThan',expected: `number bigger than ${min}`})constsmallerThanValidator=(max)=>validator(smallerThan(max))({name: 'smallerThan',expected: `number smaller than ${max}`})constisFalsyValidator=orValidator(isZeroValidator,isFalseValidator)({name: 'isFalsy'})constbetweenValidator=(min)=>(max)=>andValidator(biggerThanValidator(min),smallerThanValidator(max))({name: 'betweenValidator'})/**** Some POC Tests :smile:**/constassert=(condition)=>{if(!condition)throw'Assertion failed'}constisZeroResult=isZeroValidator(0)console.log('isZeroResult ===>',isZeroResult)assert(isZeroResult.name==='isZero')assert(isZeroResult.valid===true)assert(isZeroResult.value===0)constisFalseResult=isFalseValidator(true)console.log('isFalseResult ===>',isFalseResult)assert(isFalseResult.name==='isFalse')assert(isFalseResult.valid===false)assert(isFalseResult.value===true)constbiggerThanResult=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')constisFalsyResult=isFalsyValidator(0)console.log('isFalsyResult ===>',isFalsyResult)assert(isFalsyResult.name==='isFalsy')assert(isFalsyResult.valid===true)assert(isFalsyResult.value===0)assert(isFalsyResult.passed[0].name==='isZero')constbetweenResult=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 👍❓
The text was updated successfully, but these errors were encountered:
first let me tell you, your code is absolutely brilliant, you must be a very talented developer!
I've developed something similar by using a monad to compose the responses, you can find my solution in the branch feature/monadic-response (of course it's way worse than this)
If you don't mind, I'll respond you properly in the #1 issue, so we'll keep the discussion there 😉
PS: in case you need to share anything with me in future, and I would be glad of it, my email address is:
my own name (antonio) AT my own company name (beautifulinteractions) .com ))
@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.
Also, wasn't sure how to share this with you... hope issue is ok 👍❓
The text was updated successfully, but these errors were encountered: