Execution environment separation
Execution environment separation here is a way of running particular predicate functions and state callbacks only in the specified environment and is implemented with the aid of the following properties:
State callbacks separation
For example, asuming you use the same validation logic on both sides, on the client side you might need to perform UI effects connected to validations’ states, whereas on the server side logging on “invalid” to detect attempts to get around your client side validations. If the client side validations passed, the server side validations cannont fail.
import { disableElement, enableElement } from 'your-ui-effects-file.js';import { log } from 'your-logging-tools-file.js';// import predicate functions from your-predicates-file.js// ...
const loginV = Validation();const passwordV = Validation();
// adding constraints to loginV and passwordV// loginV.constraint() ...// passwordV.constraint() ...// ...
// creating a validation profileconst [signinForm, signinV] = Validation.profile( '[name=signinForm]', ['login', 'password'], [loginV, passwordV],);
signinV .client .started(disableElement(signinForm.submitBtn)) // ignored on the server side .invalid(disableElement(signinForm.submitBtn)) // ignored on the server side .valid(enableElement(signinForm.submitBtn)) // ignored on the server side .server .invalid(log); // ignored on the client side
// export validation to use on the server side as a middleware functionexport default signinV;
Constraints separation
In some cases it may be useful to split a predicate function in two parts and execute one on the client and the other one on the server side.
import { isEmailNotTemp, isEmailVacantC, // makes a request to the server isEmailVacantS, // makes a request to a database // other predicate functions // ...} from 'your-predicates-file.js';
const emailV = Validation();const passwordV = Validation();const pwdconfirmV = Validation();
// adding shared constraints to emailV, passwordV and pwdconfirmV// loginV.constraint() ...// passwordV.constraint() ...// pwdconfirmV.constraint() ...// ...
// creating a validation profileconst [signupForm, signupV] = Validation.profile( '#signup_form', ['email', 'password', 'pwdconfirm'], [emailV, passwordV, pwdconfirmV]);
// adding form-specific constraintssignupV.email .constraint(isEmailNotTemp) // will be added on both sides .client.constraint(isEmailVacantC) // will be added only on the client side .server.constraint(isEmailVacantS); // will be added only on the server side
// export validation to use on the server side as a middleware functionexport default signupV;
Now assuming isEmailVacantC
makes a request to the '/chkemail'
url, the server code may look as following:
import express from 'express';import bodyParser from 'body-parser';import signinV from 'your-signin-validation-file-name.js';import signupV from 'your-signup-validation-file-name.js';import { signinRequestHandler, signupRequestHandler, checkemailRequestHandler,} from 'your-file-name.js';
const app = express();const urlencodeParser = bodyParser.urlencoded({extended: false});
// validations are added as middleware functionsapp.post('/signin', urlencodeParser, signinV, signinRequestHandler);app.post('/signup', urlencodeParser, signupV, signupRequestHandler);app.post('/chkemail', urlencodeParser, signupV.email, checkemailRequestHandler);