V8n – Fluent validation library for JavaScript
github.com
github.com
Typical top HN comment.
Yeah, very complicated:
v8n()
.number()
.between(0, 100)
.even()
.not.equal(32)
.test(74); // true // helpers.js
const isNumber = typeof n === "number" && isFinite(n)
const isTestScore = n => isNumber(n) && n >= 0 && n <= 100;
// business-logic.js
const uploadScore = (n, cb) => {
if (!isTestScore(n))
return cb(new Error("invalid test score"));
// super contrived, but let's do it
if (n === 32 || n%2)
return cb(new Error("we don't like oddities and we hate 32"));
// do something with valid test score n
}
IMHO, a validation library should validate types and structure and should know nothing about the specific values of your data. The values are likely relevant to your business logic and should be handled there for finer-grained error handling, logical branching, etc.We don't "need" an abstraction for anything, in the sense that we need oxygen. We _want_ abstractions, and they usually make us more productive, which is something different.
Case in point the above horribly noisy procedural code for something that this library abstracts into neat, purpose specific, calls.
I think the code answers its own question.
Never fear; the devs implement hooks that let you do something when a certain part of the chain fails. Cool -- but now all of our code is tightly coupled to the structure imposed by the hook syntax.
Okay, better solution: how about an array of "reasons" is returned that tells you why your test failed. Now we've got to tell v8n what reason text we want (if any) for each part of the chain that fails, so we're back to having to declare a bunch of messages somewhere, which is what people already do.
Yeah, we want abstraction, but we want the right abstraction. Premature generalization/abstraction is a common pitfall among even the best developers. This library could be useful for some cases, but I'm not convinced it should be used for everything it can be used for.
Is this 32?
You seem confused. You just need to substitute .check() instead of .test() and you get a ValidationException if your value doesn't validate that tells you exactly which rule failed.
And that's just the two two basic result values (true/false on validation or Exception) that the devs implemented.
Nothing in this kind of design prevents returning any kind of detailed error or array of errors etc if one wants too.
>kay, better solution: how about an array of "reasons" is returned that tells you why your test failed. Now we've got to tell v8n what reason text we want (if any) for each part of the chain that fails, so we're back to having to declare a bunch of messages somewhere
Woooosh. The validation library is not about not having to write our own messages for the user. It's about not writing our own tests when the dozens of built-in ones are just as good. Plus they give structure that's better than a bunch of if/elses.
>Yeah, we want abstraction, but we want the right abstraction. Premature generalization/abstraction is a common pitfall among even the best developers.
Premature generalization/abstraction? You might be seeing this pattern for the first time, but this library follows a very standard pattern for validation libraries, that has been with us, and used in tons of production code, for over 2 decades. Apache Commons did that since ages. Even the fluent interface take on such libs is nothing new.
Your validation code is 293 characters and 8 lines, the example code is 95 characters and 6 lines and does more tests.
And that's not even including your helpers which if one uses that lib, they wont have to write.
So, you wrote like 4 times the code, and made it even less flexible (eg. hardcoding the test for 100 in your isTestScore check).
It's more overhead than simple functional approaches combined with conditional statements, but I think it's more approachable. Otherwise I find it doesn't leave too much of a margin for error and it's reasonably fast.
It's a personal preference, but I prefer it far more than a fluent interface. I actually avoid those now despite really loving them in the past.
Best I've found is a few libraries supporting JSON Schema.
const num= 74;
( (typeof num === 'number') && (num > -1 && num < 101) && (num % 2 === 0) && (num !== 32) )
compared to their first example: v8n().number().between(0, 100).even().not.equal(32).test(74);I read the code, and I do not think this library is suitable for real-world use.
Consider `makeTestType` (https://github.com/imbrn/v8n/blob/master/src/v8n.js#L973-L98...):
return () => value => {
return (
typeof value === type ||
(value === null && type === "null") ||
(Array.isArray(value) && type === "array")
);
};
This means that null and "null" (as a string) are now numbers. v8n().number().test("null") // true
It also means that an array of numbers is a number... something that is counterintuitive for the user of the library.In addition to that, most of the time you want to deal with finite numbers. A validation library should have an API that reflects this, but this is not the case for v8n.
`makeTestType("null")()(null)` return true, but `makeTestType("number")()(null)` doesn't. The signature of `makeTestType` is `type: String => () => value: Any => Boolean`.
https://github.com/cross-check/cross-check/tree/master/packa...
It supports 'draft data', which can be used by auto-safe functionality or similar.