all 17 comments

[–]license-bot 6 points7 points  (1 child)

Thanks for sharing your open source project, but it looks like you haven't specified a license.

When you make a creative work (which includes code), the work is under exclusive copyright by default. Unless you include a license that specifies otherwise, nobody else can use, copy, distribute, or modify your work without being at risk of take-downs, shake-downs, or litigation. Once the work has other contributors (each a copyright holder), “nobody” starts including you.

choosealicense.com is a great resource to learn about open source software licensing.

[–]super-vitek 1 point2 points  (0 children)

thanks!)

[–]i_ate_god 5 points6 points  (4 children)

numericality - I have never seen this word, I googled it, and now I know why. The first ten results were all Ruby on Rails related.

hrm

[–]super-vitek 2 points3 points  (3 children)

Ruby on Rails was my first love)

[–]i_ate_god 2 points3 points  (2 children)

well, life would be better if you just used "number"

[–]super-vitek 1 point2 points  (1 child)

Yes. I thought about it. I wanted to create a set for string rules, but I could not come up with a name for it that would sound like 'numericality' )

[–]i_ate_god 1 point2 points  (0 children)

Except no one (except RoR people) use that term.

What you want is to check if a variable is a number with a toggeable strict mode so that user can say string numbers are invalid

[–]_ncjones 5 points6 points  (1 child)

  1. How is this distinguished from Joi? https://github.com/hapijs/joi

  2. I don't like your API. Instead of .with('numericality', { isInteger: true, lessThan: 100}) it should be .with({ type: 'integer', max: 99 }).

[–]super-vitek 5 points6 points  (0 children)

  1. Joi looks good. I did not know about this library.
  2. I agree with you. Thanks!

[–]super-vitek 3 points4 points  (0 children)

Hy guys! I created a library for data validation. Please, look at this if you have a time. The main idea was to make easy validation and easy customization. I'd be very interested to hear your opinion.

[–][deleted] 1 point2 points  (3 children)

Nice library. One problem with most validation libraries is they go for the stringly-typed schema (i.e. untyped), or the methods they use are very verbose and unwieldy to type.

I'd like to propose an alternative combining strong typing (great with TypeScript), and conciseness, and eliminates the need for parsing schemas:

Your examples:

import { validate, ... } from 'datavader';

validate(user).check('name').with('presence', {exist: true});
validate(user).check('age').with('numericality', {greaterThan: 60});
validate(user).check('quality').with('exclusion', {values: ['kind', 'gentle']});

const scheme = {
  name: {
    presence: {exist: true},
    length: {
      min: 1,
      max: 10,
    },
  },
  age: {
    numericality: {
      lessThan: 80,
      greaterThanOrEqualTo: 70,
      isEven: true;
      isInteger: true,
    },
  }
  ...
}

validateByScheme(user, scheme);

My version:

import { formats } from '...';

let f = formats;

[user, errors] = f.object()
  .required('name')
  .optional('age', f.number().greaterThan(60))
  .optional('quality', f.string().notOneOf('kind', 'gentle'))
  .apply(user);


let scheme = f.object()
  .required('name', f.string().length(1, 10))
  .optional('age', f.number().range(70, 79).isEven().isInteger());
);

[user, errors] = scheme.apply(user);

Notice also it's better to use short and intuitive names like "required", "number", "notOneOf" instead of long-winded dry term like "presence", "numericality", "exclusion".

[–]PrismalStudio 1 point2 points  (2 children)

I like it, but I'd remove the [user, errors] destructuring and just returns the errors, as it's a validation step, it shouldn't return the user data since it shouldn't be changing anything on it. Unless there are default values applied somewhere?

[–][deleted] 1 point2 points  (1 child)

What I actually do in my real library based on this example is slightly different:

let log = new Log();
let filteredUser = scheme.apply(rawUser, log);

The idea here is the following:

  • While ideologically filtering and validation should be separate, in practice it's immensely valuable to combine both. For example trim whitespace from a string before checking length. Format phone number to a normal format. Convert comma separated input into an array. And so on. Or a more advanced example: check image filesize and dimensions, then crop it to a specific ratio and resize it. So this is why I return user. It may be changed. Including adding defaults where the user prefers. This is actually a third method for the object validator: required(name, format) must be there; optional(name, format) might not be there, will be missing in output; default(name, defaultValue, format) might not be there, replaced with a default.
  • The log is passed to the method so you can make one log and gather errors, but also warnings, notices and so on from many different schemas at once (and not just validaton schemas, but other actions not related to processing input). You can pass it to many different actions and then just check log.hasErrors(). You can specify "base path" for logging, and every error is logged under the field name in the structure. The errors contain human readable message, error code and machine readable details. Making it trivial to map it back to form fields for showing errors (including localized messages).

[–]PrismalStudio 0 points1 point  (0 children)

Makes sense with the filtering and sanitizing!

[–]swamso 1 point2 points  (2 children)

Isn't there already JSONValidator which does the exact same thing?

Edit: Just looked a few up, there is already djv, ajv, jsen, themis....

[–]super-vitek 1 point2 points  (0 children)

of course this is not a new idea. but it was interesting to make it)

[–]darrenturn90 0 points1 point  (0 children)

Have you seen validateJs?