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
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,validateManyandcombineValidateare 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,validateshouldn'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
intlpackage in our internal project, this package should just be removed.Predicates should always be factories, meaning that even a simple
isRequiredpredicate needs to be "initialized":This allows validations (or validators, however we want to call this concept) to be created dynamically. Here's a sketch:
and
This allows the following usage:
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-intlandredux-form. We could provide one in this library as a separate package, although a simple recipe would probably do.Signatures: