lundegaard / lundegaard/validarium
Suggested structure
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 28
- Forks
- 9
- PR merge metrics
- No merged PRs in 30d
Description
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
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
No implementation file or test is named in the issue. Start by reviewing the existing validate, validateMany, combineValidate, predicates, and intl integration, then compare them with the proposed factory signatures and null-or-object result shape. Done means the project has agreed on the API direction and documented the chosen validation and message integration.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, react
- Domain
- frontend, tooling
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 20/100