Created
August 28, 2018 00:22
-
-
Save jaidetree/dc49e2328b3d9ed25f8712e3f89c03f3 to your computer and use it in GitHub Desktop.
An example of a functional-programming inspired validator
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { of } from "rxjs/observable"; | |
| import { filter, map } from "rxjs/operators"; | |
| import validate, * as v from "libs/validate"; | |
| const validateForm = validate([ | |
| v.field("name", "Full Name", [ | |
| v.isRequired, | |
| "A full name is required.", | |
| name => name.split(" ").length, | |
| wordCount => wordCount < 2, | |
| "Please provide a first name and last name." | |
| wordCount => wordCount > 2, | |
| "Only a first name and last name is required." | |
| ]), | |
| v.field("email", "Email", [ | |
| v.isRequired, | |
| "An email address is required", | |
| v.isEmail, | |
| "Please provide a valid email address.", | |
| ]), | |
| v.field("age", "Your Age", [ | |
| v.isNumeric, | |
| "Age must be a numeric value", | |
| // naive, custom isInteger | |
| age => String(age) === String(parseInt(age, 10)), | |
| "Age must be a positive, whole number.", | |
| Number, | |
| age => age >= 62, | |
| "Sorry you are too young to collect social security.", | |
| ]), | |
| v.field("favorite_color", "Your Favorite Color", [ | |
| v.isRequired, | |
| "A favorite color is required", | |
| color => color === "blue", | |
| "Sorry but your favorite color must be blue.", | |
| ]), | |
| ]); | |
| const data = { | |
| name: "Amadaeus F. Blundershvlt", | |
| email: "amadaeus@example", | |
| age: 15, | |
| }; | |
| of(data) | |
| .pipe( | |
| map(validateForm), | |
| // optional | |
| // filter(form => form.isValid === true) | |
| ) | |
| .subscribe(console.log); | |
| // => | |
| // { | |
| // data: { | |
| // name: "Amadaeus F. Blundershvlt", | |
| // email: "amadaeus@example", | |
| // age: 15, | |
| // }, | |
| // isValid: false, | |
| // errors: [ | |
| // { | |
| // name: "name", | |
| // label: "Full Name", | |
| // message: "Only a first name and last name is required.", | |
| // }, | |
| // { | |
| // name: "email", | |
| // label: "Email", | |
| // message: "Please provide a valid email address.", | |
| // }, | |
| // { | |
| // name: "age", | |
| // label: "Your Age", | |
| // message: "You are too young to collect social security.", | |
| // }, | |
| // { | |
| // name: "favorite_color", | |
| // label: "Favorite Color", | |
| // message: "A favorite color is required.", | |
| // }, | |
| // ] | |
| // } | |
| Promise.resolve(data) | |
| // this is what v.toPromise does but since validateForm is just a function | |
| // you can wrap it so it can be coerced into whatever shape or structure | |
| // you need | |
| .then(data => { | |
| const form = validateForm(data); | |
| return form.isValid | |
| ? Promise.resolve(form.data) | |
| : Promise.reject(form.errors); | |
| }) | |
| .then(console.log) | |
| .catch(console.error) | |
| // Pass Case | |
| // => | |
| // { | |
| // name: "Amadaeus Blundershvlt", | |
| // email: "[email protected]", | |
| // age: 63, | |
| // favorite_color: "blue", | |
| // } | |
| // Fail Case | |
| // => | |
| // [ | |
| // { | |
| // name: "name", | |
| // label: "Full Name", | |
| // message: "Only a first name and last name is required.", | |
| // }, | |
| // { | |
| // name: "email", | |
| // label: "Email", | |
| // message: "Please provide a valid email address.", | |
| // }, | |
| // { | |
| // name: "age", | |
| // label: "Your Age", | |
| // message: "You are too young to collect social security.", | |
| // }, | |
| // { | |
| // name: "favorite_color", | |
| // label: "Favorite Color", | |
| // message: "A favorite color is required.", | |
| // }, | |
| // ] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment