Coder Social home page Coder Social logo

lundegaard / validarium Goto Github PK

View Code? Open in Web Editor NEW
29.0 5.0 9.0 2.79 MB

🛡Agnostic validation library for JavaScript applications.

Home Page: https://validarium.js.org

License: MIT License

JavaScript 98.60% HTML 1.40%
validations formik redux-form react ramda intl

validarium's People

Contributors

aizerin avatar dependabot[bot] avatar macem8 avatar tommmyy avatar vwerne avatar wafflepie avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

validarium's Issues

Duplicate id: 'validarium.hasAgeInInterval' in messages.js

in messages keys hasAgeInInterval and matches has same message id.
hasAgeInInterval: { id: 'validarium.hasAgeInInterval', defaultMessage: 'You must be between {minAge} and {maxAge} years old', }, matches: { id: 'validarium.hasAgeInInterval', defaultMessage: 'Value has a wrong format', },

Create `@validarium/domain-cs` package

  • create @validarium/domain-cs package
  • add the iban, phone number and birth number validation to @validarium/domain-cs
  • phone number can also be validation in @validarium/validations configurable for specific country: isPhoneNumber({ prefix: ‘420’, minLength, maxLength })

`validateMany` should return `null` when all validations pass

validateMany currently returns an array of results ([null]), even if all subvalidations successfully pass. null should be returned directly to be consistent with validate and allow nesting of validate and validateMany calls.

validate({ 
  foo: [isRequired] 
})({ 
  foo: 'bar' 
}); // === null

validateMany({ 
  foo: [isRequired] 
})([{ 
  foo: 'bar' 
}]) // === [null], expected to be null

validate({
  arr: [
    validateMany({ 
      foo: [isRequired] 
    })
  ]
})({
  arr: [{ 
    foo: 'bar' 
  }]
}) // === {arr: [null]}, expected to be null

Of course when at least one validation fails, the structure should be kept as is to know which index is wrong.

Proposed fix:

const fixedValidateMany = validations => o(when(all(isNil), always(null)), validateMany(validations));

Make all validations optional and null safe

All validations should be optional and null safe. Required fields should be explicitly marked with isRequired validations. Otherwise, we have no other choice than duplicate every validation and make it optional.

New feature - conditional validations

I think it would be useful to have conditional validations. Like

validate({
     firstName: { validations: [isRequired, ...], conditions: [isUserPresent, ...]},
})

conditions should get all form values.

Or we can make condition part of validation itself if we extend the API.

New feature - nested arrays validations

I think that it would be useful to have something like that:

validate({
    users: [{
        email: [isRequired, isEmail, hasLengthMax(200)],
        age: [isRequired, isNumber, hasValueMin(18)],
    }]
});

or

validate({
    users: validateMany({
        email: [isRequired, isEmail, hasLengthMax(200)],
        age: [isRequired, isNumber, hasValueMin(18)],
    })
});

but it should be also possible to validate array itself. Like users: [isGreatenThan10, isRequired, ...]

New feature - nested objects

I think it would be useful to have nested objects validations. Like

validate({
    user: {
        email: [isRequired, isEmail, hasLengthMax(200)],
        age: [isRequired, isNumber, hasValueMin(18)],
    }
})

We can already translate this type of validation results by intl translator. But we are not able to validate them.

Simplify @validarium/validations

IMO this package should really just be 2 files: messages and something that loops over all predicates and connects them with the message. This should be possible if we choose a convention for the values passed to messages, e.g. $1, $2 or so (or by always passing objects).

`isRequired` validation doesn't allow "falsy" values

The documentation for isRequired states

Checks if the value is present

The current implementation however does not only check if the value is present, but also checks if the value is truthy

export default ifElse(isTruthy, alwaysNull, always({ message: m.isRequired }));

This is confusing, because valid values, such as 0, are resolved as invalid. I think 0 is a perfectly reasonable value for a "required" numerical input or select box. The same applies to boolean values - the validation should force the user to "make a choice", not to "pick true"

Missing READMEs

  • Main README should contain sections:
    • Features - what the lib is for
    • Installation
    • Getting started
    • Guides
      • How to implement own validations
      • Integration to redux-form
      • Integration to formik
    • Contribution
    • Link to API
  • Every package should contain link to main page to our repo.

Fill in the @validarium/predicates

@validarium/predicates should contain all predicate functions that are used by validations in @validarium/intl packages. Right now they are hard-coded within validation itself.

Suggested structure

Hi @tommmyy, in our internal project, I sketched a draft of what validarium could look like in terms of predicates, validations and integration with intl. I'm creating this issue so that the suggestion is written down somewhere and not just forgotten in the git history.

First of all, validate, validateMany and combineValidate are fine and I don't think any changes are necessary in this regard. However, what users of validarium often don't realise is that if you need to do validations using multiple fields, validate shouldn't/cannot be used.

Although the library should technically be agnostic (which should be possible). I think the APIs should suit the libraries that we use in our stack: redux-form and react-intl. There do not have to be any dependencies on these libraries I think.

Because we don't use the intl package in our internal project, this package should just be removed.

Predicates should always be factories, meaning that even a simple isRequired predicate needs to be "initialized":

validate({ name: [isRequired()] })

This allows validations (or validators, however we want to call this concept) to be created dynamically. Here's a sketch:

import { o, pick, keys, mapObjIndexed } from 'ramda';
import createValidation from './createValidation';
import * as predicates from './predicates';
import messages from './messages';

const validations = o(
	mapObjIndexed((predicate, key) => (options, message = messages[key]) =>
		createValidation(predicate, message, options)
	),
	pick(keys(predicates)) // NOTE: To only select enumerable properties.
)(predicates);

export default validations;

and

import { cond, T } from 'ramda';
import { alwaysNull } from 'ramda-extension';

const createValidation = (predicate, message, options) =>
	cond([
		// TODO: Add null safety?
		[predicate(options), alwaysNull],
		[T, value => ({ value, message, options })],
	]);

export default createValidation;

This allows the following usage:

import v from '@validarium/validations'

v.isRequired()
v.hasLengthMax({ max: 100 })
v.hasLengthMax({ max: 100 }, { id: 'sth', defaultMessage: 'Max length is {max}' })

Meaning that we can easily override validation messages and the creation process of validations is also simplified.

It is possible to further optimize this by creating the validations as a build script (allowing for code completion and better imports), but the predicate structure should stay consistent.

Validations either return null (if validation passed) or they return { value, message, options } object. With redux-form, this object should be stored as the field error (storing the translated value doesn't make much sense).

When visualising the error, this should be handled by a decorator/hook aware of both react-intl and redux-form. We could provide one in this library as a separate package, although a simple recipe would probably do.

Signatures:

Predicate
  (options?: Object) => (value: any) => bool

Validation
  (options?: Object, message?: Message) =>
  (value: any) =>
  ({ message: Message, options?: Object, value: any }) || null

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.