Skip to content

ralenjor/js-validator

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 

Repository files navigation

validator.js

A lightweight, chainable, reusable input validation and sanitization utility for JavaScript projects. Drop it into any project and import it wherever you need to validate user input.


Table of Contents


Setup

Place the file in your project at:

your-project/
└── src/
    └── utils/
        └── validator.js

Your HTML script tag must use type="module":

<script src="main.js" type="module"></script>

Note: Modules require an HTTP server to run. Open your project with VS Code Live Server, or run python3 -m http.server 8000 in your project folder and navigate to http://localhost:8000.


Quick Start

import { Validator, sanitize } from './src/utils/validator.js';

// Sanitize raw input first, then validate
const raw = document.getElementById('email').value;
const clean = sanitize(raw);

const result = new Validator(clean, "Email")
  .required()
  .isEmail()
  .validate();

if (!result.valid) {
  console.log(result.errors); // ["Email must be a valid email address."]
}

Chain as many rules as you need. Call .validate() at the end to get the result object:

{ valid: true | false, errors: [] }

Sanitization

Always sanitize raw user input before validating or storing it.

sanitize(str)

Strips characters used in XSS attacks (<, >, ", ', /, &) and trims whitespace.

import { sanitize } from './src/utils/validator.js';

const clean = sanitize(userInput);

safeParseJSON(str)

Safely parses a JSON string. Returns null instead of throwing if the input is invalid or not an object. Use this any time you parse data from an API or external source.

import { safeParseJSON } from './src/utils/validator.js';

const data = safeParseJSON(responseText);
if (!data) {
  console.error("Invalid JSON received.");
}

Validator Methods

All methods return this, so they can be chained. Call .validate() at the end to finalize.


Presence

.required()

Fails if the value is empty, null, or undefined. If this fails, all further checks are skipped automatically.

new Validator("", "Username").required().validate();
// { valid: false, errors: ["Username is required."] }

.optional()

Use instead of .required() for non-mandatory fields. If the value is empty, all further checks are silently skipped.

new Validator("", "Nickname").optional().minLength(3).validate();
// { valid: true, errors: [] }  ← skipped because field is empty and optional

String Checks

.minLength(n)

Value must be at least n characters long.

.maxLength(n)

Value must be no more than n characters long.

.exactLength(n)

Value must be exactly n characters long. Useful for codes, PINs, etc.

.noSpaces()

Value must contain no whitespace. Useful for usernames and identifiers.

.noScript()

Fails if value contains <, >, ", ', or backticks. A second layer of XSS defense on top of sanitize().

new Validator("<script>alert(1)</script>", "Comment")
  .required()
  .noScript()
  .validate();
// { valid: false, errors: ["Comment contains invalid characters."] }

Format Checks

.isEmail()

Must match standard email format ([email protected]).

.isUrl()

Must be a valid http:// or https:// URL. Rejects javascript: and data: URIs.

.isPhone()

Must be a valid phone number. Allows digits, spaces, dashes, parentheses, and a leading + for international format.

.isZip()

Must be a US ZIP code — either 5-digit (12345) or ZIP+4 (12345-6789).

.isDate()

Must be a valid date in YYYY-MM-DD format.

.isStrongPassword()

Enforces strong password requirements:

  • At least 8 characters
  • At least one uppercase letter
  • At least one lowercase letter
  • At least one number
  • At least one special character
new Validator("weakpass", "Password").required().isStrongPassword().validate();
// { valid: false, errors: ["Password must contain one uppercase letter, one number, one special character."] }

Number Checks

.isNumber()

Value must be numeric (integers and decimals both pass).

.isInteger()

Value must be a whole number. Decimals fail.

.inRange(min, max)

Value must be between min and max (inclusive).

.min(n)

Value must be greater than or equal to n.

.max(n)

Value must be less than or equal to n.

new Validator("150", "Age").required().isInteger().inRange(0, 120).validate();
// { valid: false, errors: ["Age must be between 0 and 120."] }

Whitelist and Pattern

.isOneOf(array)

Value must be one of the items in the provided array. Use this for dropdowns, selects, and any field with a fixed set of valid options.

new Validator("purple", "Color")
  .required()
  .isOneOf(["red", "green", "blue"])
  .validate();
// { valid: false, errors: ["Color must be one of: red, green, blue."] }

.matches(regex, message)

Value must match the provided regular expression. Supply a custom error message as the second argument.

new Validator("ABC-123", "Product Code")
  .required()
  .matches(/^[A-Z]{3}-\d{3}$/, "Product Code must follow the format ABC-123.")
  .validate();

Comparison

.equals(otherValue, otherFieldName)

Value must strictly equal another value. Designed for confirm password fields.

const password = "Secure@99";
const confirm = "Secure@88";

new Validator(confirm, "Confirm Password")
  .required()
  .equals(password, "Password")
  .validate();
// { valid: false, errors: ["Confirm Password must match Password."] }

Custom Rules

.custom(fn)

Pass any function that receives the value and returns either true (pass) or a string (error message). Use this for any validation logic that does not fit a built-in method.

new Validator("42", "Lucky Number")
  .required()
  .isInteger()
  .custom((val) => val === "42" || "Lucky Number must be exactly 42.")
  .validate();

Validating Entire Forms

Use validateForm() to validate all fields in a form at once against a schema you define. It returns a single result object with errors grouped by field name.

import { Validator, sanitize, validateForm } from './src/utils/validator.js';

const schema = {
  username: (val) => new Validator(val, "Username").required().minLength(3).maxLength(20).noSpaces().validate(),
  email:    (val) => new Validator(val, "Email").required().isEmail().validate(),
  age:      (val) => new Validator(val, "Age").required().isInteger().inRange(18, 99).validate(),
  password: (val) => new Validator(val, "Password").required().isStrongPassword().validate(),
};

const formData = {
  username: sanitize(document.getElementById('username').value),
  email:    sanitize(document.getElementById('email').value),
  age:      sanitize(document.getElementById('age').value),
  password: document.getElementById('password').value, // don't sanitize passwords
};

const result = validateForm(formData, schema);

if (!result.valid) {
  console.log(result.errors);
  // {
  //   email: ["Email must be a valid email address."],
  //   age:   ["Age must be between 18 and 99."]
  // }
}

Note: Do not run sanitize() on password fields. Sanitization replaces characters like < and > which may be intentional parts of a strong password. Passwords should be hashed server-side and never stored or rendered as plain text.


Security: What This Prevents

Cross-Site Scripting (XSS)

What it is: An attacker injects malicious script tags or event handlers into your page through input fields. If the value is later rendered in the DOM, the script executes in other users' browsers, potentially stealing session cookies or credentials.

How this helps: sanitize() encodes <, >, ", ', /, and & before the value ever reaches your logic. .noScript() adds a second validation layer that rejects any input still containing those characters.


Injection Attacks (SQL, Command, Template)

What it is: An attacker crafts input containing characters like quotes, semicolons, or backticks that break out of their context and execute unintended commands in a database or shell.

How this helps: sanitize() strips the characters most commonly used to break out of string contexts. .noScript() and .matches() let you enforce a strict allowlist of valid characters, so only expected input ever reaches your backend.


Mass Assignment / Prototype Pollution

What it is: An attacker passes unexpected keys like __proto__ or constructor in a JSON payload, potentially overwriting built-in JavaScript object properties across your entire application.

How this helps: safeParseJSON() validates that parsed input is a plain object before returning it. .isOneOf() ensures that only whitelisted keys and values are accepted for fields with a fixed set of options.


Brute Force and Abuse

What it is: Automated scripts submitting thousands of requests to a login or form endpoint, either to guess credentials or to overwhelm the server.

How this helps: .isStrongPassword() enforces complexity requirements that significantly raise the cost of brute-force attacks. Client-side validation also catches bad input immediately, reducing the volume of requests that ever reach your server.


Business Logic Abuse

What it is: A user submits values that are technically valid (a real number, a real email) but violate the rules of your application — such as a negative price, an age of 999, or selecting an option that does not exist.

How this helps: .inRange(), .min(), .max(), .isOneOf(), and .custom() let you enforce the rules of your specific application, not just generic format checks.


What This Does Not Replace

Client-side validation improves user experience and adds a layer of defense, but it is not a security boundary on its own. A determined attacker can bypass JavaScript entirely using browser DevTools or tools like Burp Suite.

Always enforce the same rules server-side. This library is designed to be ported to or mirrored by your backend validation layer. Never trust input solely because it passed client-side checks.

Additional server-side measures this library does not cover:

  • Parameterized queries / prepared statements (SQL injection prevention)
  • httpOnly and Secure cookie flags (session protection)
  • Rate limiting and account lockout (brute force prevention)
  • CSRF tokens (cross-site request forgery prevention)
  • Content Security Policy headers (XSS containment)
  • Server-side authentication and authorization

About

A lightweight, chainable, reusable input validation and sanitization utility for JavaScript projects. Drop it into any project and import it wherever you need to validate user input.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors