🚀 DAY 5 OF LAUNCH WEEK:Introducing Webhook Events for Alert Changes.Learn more
Socket
Book a DemoInstallSign in
Socket

zee-light-validate

Package Overview
Dependencies
Maintainers
1
Versions
2
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

zee-light-validate

A lightweight TypeScript object validation library with zero dependencies

latest
Source
npmnpm
Version
1.0.1
Version published
Weekly downloads
0
-100%
Maintainers
1
Weekly downloads
 
Created
Source

Light Validate

A comprehensive, lightweight validation library for TypeScript/JavaScript with zero dependencies. Tree-shakeable, type-safe, and designed for modern applications with support for file validation, cross-field validation, async validation, and internationalization.

Features

  • 🪶 Lightweight: Zero dependencies, minimal bundle size
  • 🌳 Tree-shakeable: Import only what you need
  • 📘 TypeScript: Full TypeScript support with excellent IntelliSense
  • 🔧 Flexible: Extensible with custom validators
  • 🎯 Simple: Clean and intuitive API
  • 📦 Universal: Works in Node.js (CommonJS) and modern JavaScript (ESM)
  • 🌍 Internationalization: Multi-language error messages
  • Async Support: Database/API validation
  • 🔗 Cross-field: Compare fields within schemas
  • 📊 Schema Reusability: Create and reuse validation schemas

🔤 Advanced String Validations

  • ✅ Email, URL, IP address validation
  • ✅ UUID, Time (HH:mm) validation
  • ✅ Slug, Credit Card (Luhn algorithm)
  • ✅ IBAN, Postal Code (190+ countries)
  • ✅ XSS/SQL injection protection
  • ✅ Custom regex patterns
  • ✅ Username, Domain, MAC address
  • ✅ Hex colors, Base64, JWT tokens
  • ✅ Country codes, API keys, OTP
  • ✅ Hash validation, Currency codes
  • ✅ Language codes, Timezones
  • ✅ Latitude/Longitude, Port numbers
  • ✅ Cron expressions, Environment variables

📁 File Validation

  • ✅ File size limits (bytes, KB, MB)
  • ✅ MIME type validation
  • ✅ File extension validation
  • ✅ Multiple file type categories
  • ✅ Custom file validation rules

📦 Data Structure Validations

  • ✅ Array unique items validation
  • ✅ Array of objects validation
  • ✅ Array sorted validation (ascending/descending)
  • ✅ Array type consistency validation
  • ✅ Array exact length validation
  • ✅ Array contains/not contains validation
  • ✅ Object required keys validation
  • ✅ Object strict keys validation (no unexpected keys)
  • ✅ Object deep nested validation (dot notation)
  • ✅ Object array contains validation
  • ✅ Object plain object validation (reject Date/RegExp)
  • ✅ Date range validation (ISO/US/EU formats)
  • ✅ Enum validation (string/number/mixed)
  • ✅ Nested object validation
  • ✅ Cross-field comparisons
  • ✅ Schema composition and reusability

🚀 Advanced Features

  • ✅ Async validation (DB/API checks)
  • ✅ Cross-field validation (greater, lessThan, equalTo)
  • ✅ Localization/i18n support
  • ✅ Schema reusability and composition
  • ✅ Custom validation functions
  • ✅ Complex nested validations

Installation

npm install light-validate

Quick Start

Basic Usage

import { string, number, boolean, object, array, schema } from "light-validate";

// Simple validation
const nameValidator = string().min(2).max(50).required();
const result = nameValidator.validate("Zohaib Irshad");
console.log(result); // { success: true }

// Object validation
const userSchema = object({
  name: string().required().min(3),
  email: string().email().required(),
  age: number().min(18).max(120),
  isActive: boolean(),
});

const user = {
  name: "Zohaib Irshad",
  email: "zohaib@example.com",
  age: 25,
  isActive: true,
};

const validation = userSchema.validate(user);
console.log(validation); // { success: true }

Advanced Schema Validation

import {
  schema,
  field,
  greater,
  equalTo,
  string,
  number,
} from "light-validate";

// Cross-field validation
const eventSchema = schema({
  title: string().required(),
  startDate: string().required(),
  endDate: field(string().required(), greater("startDate")),
  originalPrice: number().min(0).required(),
  salePrice: field(number().min(0), lessThan("originalPrice")),
});

// Password confirmation
const passwordSchema = schema({
  password: string().min(8).required(),
  confirmPassword: field(string().required(), equalTo("password")),
});

Async Validation

import { schema, string, asyncEmail, asyncUsername } from "light-validate";

// Database/API validation
const registrationSchema = schema({
  username: string().username().required(),
  email: string().email().required(),
})
  .asyncValidate(
    "email",
    asyncEmail(async (email) => {
      // Check if email exists in database
      const exists = await checkEmailInDatabase(email);
      return !exists; // Return true if unique
    })
  )
  .asyncValidate(
    "username",
    asyncUsername(async (username) => {
      // Check username availability
      const available = await checkUsernameAvailability(username);
      return available;
    })
  );

// Use async validation
const result = await registrationSchema.validateAsync({
  username: "zohaib_irshad",
  email: "zohaib@example.com",
});

Localization/i18n

import { schema, string } from "light-validate";

const userSchema = schema({
  name: string().required(),
  email: string().email().required(),
}).locale({
  locale: "ur", // Urdu
  messages: {
    ur: {
      required: "یہ فیلڈ ضروری ہے",
      email: "درست ای میل ایڈریس درج کریں",
      type: "یہ فیلڈ ایک آبجیکٹ ہونا چاہیے",
    },
    es: {
      required: "Este campo es requerido",
      email: "Ingrese una dirección de correo válida",
    },
  },
});

Array of Objects Validation

import { array, string, number } from "light-validate";

// Array of user objects
const usersValidator = array()
  .min(1, "At least one user required")
  .max(10, "Maximum 10 users allowed")
  .arrayOf({
    name: string().required(),
    email: string().email().required(),
    age: number().min(0).max(120),
  })
  .unique("All users must be unique");

const users = [
  { name: "Zohaib Irshad", email: "zohaib@example.com", age: 25 },
  { name: "John Doe", email: "john@example.com", age: 30 },
];

const result = usersValidator.validate(users);

Schema Reusability

import { schema, string, number } from "light-validate";

// Reusable address schema
const addressSchema = schema({
  street: string().required(),
  city: string().required(),
  zipCode: string().postalCode("US").required(),
  country: string().countryCode().required(),
});

// User schema using address
const userSchema = schema({
  name: string().required(),
  email: string().email().required(),
  address: addressSchema, // Nested schema
  billingAddress: addressSchema, // Reuse same schema
});

// Company schema
const companySchema = schema({
  name: string().required(),
  email: string().email().required(),
  employees: number().min(1).required(),
  headquarters: addressSchema, // Reuse address schema
});

Validation Types

String Validators

Basic String Validation

import { string } from "light-validate";

const validator = string()
  .required("Name is required")
  .min(2, "Minimum 2 characters")
  .max(50, "Maximum 50 characters");

// Custom regex
const codeValidator = string().regex(/^[A-Z]{2,3}-\d{3,6}$/, "Invalid format");

Email & Communication

// Email validation
const emailValidator = string().email("Invalid email address");

// URL validation
const urlValidator = string().url("Must be a valid URL");

// Domain validation (without protocol)
const domainValidator = string().domain("Invalid domain name");

Geographic & Location

// IP address (IPv4 & IPv6)
const ipValidator = string().ip("Invalid IP address");

// Latitude/Longitude coordinates
const coordsValidator = string().latLng("Invalid coordinates (lat,lng)");

// Postal codes (190+ countries supported)
const zipValidator = string().postalCode("US", "Invalid US zip code");
const pkZipValidator = string().postalCode(
  "PK",
  "Invalid Pakistan postal code"
);

// Country codes (ISO 2 or 3 letter)
const countryValidator = string().countryCode("Invalid country code");

// Language codes (ISO 639)
const langValidator = string().languageCode("Invalid language code");

// Timezone validation
const timezoneValidator = string().timezone("Invalid timezone");

Technical & Development

// Username validation (no spaces, only _ or . allowed)
const usernameValidator = string().username("Invalid username format");

// Environment variable names
const envVarValidator = string().envVar("Invalid environment variable");

// MAC address validation
const macValidator = string().mac("Invalid MAC address");

// Hexadecimal validation
const hexValidator = string().hex("Invalid hex value");

// Base64 validation
const base64Validator = string().base64("Invalid Base64 string");

// JWT token validation
const jwtValidator = string().jwt("Invalid JWT token");

// Port number validation (1-65535)
const portValidator = string().port("Invalid port number");

// Cron expression validation
const cronValidator = string().cron("Invalid cron expression");

Identification & Security

// UUID validation
const uuidValidator = string().uuid("Invalid UUID format");

// API key validation (32+ characters)
const apiKeyValidator = string().apiKey("Invalid API key format");

// OTP validation (customizable length)
const otpValidator = string().otp(6, "Invalid 6-digit OTP");

// Hash validation (MD5, SHA1, SHA256, SHA512)
const hashValidator = string().hash("sha256", "Invalid SHA256 hash");

// Credit card validation (with Luhn algorithm)
const cardValidator = string().creditCard("Invalid credit card number");

// IBAN validation
const ibanValidator = string().iban("Invalid IBAN");

Time & Format

// Time validation (HH:mm format)
const timeValidator = string().time("Invalid time format");

// Slug validation (URL-friendly strings)
const slugValidator = string().slug("Invalid slug format");

// Currency codes (ISO 4217)
const currencyValidator = string().currency("Invalid currency code");

Security & Safety

// Safe string validation (XSS/SQL injection protection)
const safeValidator = string().safeString("Contains unsafe content");

Number Validators

import { number } from "light-validate";

const ageValidator = number()
  .required("Age is required")
  .min(0, "Age cannot be negative")
  .max(120, "Age cannot exceed 120");

const priceValidator = number()
  .min(0, "Price must be positive")
  .custom((val) =>
    val % 0.01 === 0 ? null : "Price must have max 2 decimal places"
  );

Boolean Validators

import { boolean } from "light-validate";

const termsValidator = boolean()
  .required("Must accept terms")
  .custom((val) => (val === true ? null : "Terms must be accepted"));

Array Validators

import { array, string, number } from "light-validate";

// Basic array validation
const tagsValidator = array()
  .min(1, "At least one tag required")
  .max(10, "Maximum 10 tags allowed")
  .of(string().min(2))
  .unique("Tags must be unique");

// Array of numbers
const scoresValidator = array()
  .of(number().min(0).max(100))
  .min(3, "Minimum 3 scores required");

// Array of objects
const productsValidator = array().arrayOf({
  name: string().required(),
  price: number().min(0).required(),
  category: string().required(),
});

File Validators

import { file } from "light-validate";

// Image validation
const avatarValidator = file()
  .images("Only image files allowed")
  .maxSizeMB(5, "File too large")
  .required("Avatar is required");

// Document validation
const docValidator = file()
  .documents("Only document files allowed")
  .maxSizeKB(500, "Document too large");

// Custom file validation
const customValidator = file()
  .mimeTypes(["application/pdf", "text/plain"])
  .extensions([".pdf", ".txt"])
  .maxSizeBytes(1024 * 1024); // 1MB

Enum Validators

import { enum as enumValidator } from "light-validate";

// String enum
const statusValidator = enumValidator(["active", "inactive", "pending"]);

// Number enum
const priorityValidator = enumValidator([1, 2, 3, 4, 5]);

// Mixed enum
const mixedValidator = enumValidator(["low", "medium", "high", 1, 2, 3]);

Date Range Validators

import { dateRange } from "light-validate";

// ISO date format (YYYY-MM-DD)
const isoRangeValidator = dateRange({
  dateFormat: "ISO",
  allowSameDate: false,
});

// US date format (MM/DD/YYYY)
const usRangeValidator = dateRange({
  dateFormat: "US",
  allowSameDate: true,
});

// EU date format (DD/MM/YYYY)
const euRangeValidator = dateRange({
  dateFormat: "EU",
});

const result = isoRangeValidator.validate({
  start: "2025-01-01",
  end: "2025-12-31",
});

name: "User Name", email: "test@test.com", age: 22, status: "active", });

console.log(result); // { success: true }


### Node.js/CommonJS

```javascript
const {
  object,
  string,
  number,
  enum: enumValidator,
} = require("light-validate");

const schema = object({
  name: string().required().min(3),
  email: string().email(),
  age: number().min(18),
  status: enumValidator(["active", "inactive"]).required(),
});

const result = schema.validate({
  name: "User Name",
  email: "test@test.com",
  age: 22,
  status: "active",
});

console.log(result);
// { success: true }

API Reference

Basic Types

string()

Creates a string validator with comprehensive validation options.

import { string } from "light-validate";

const validator = string()
  .required() // Field is required
  .min(3) // Minimum length
  .max(50) // Maximum length
  .email() // Valid email format
  .url() // Valid URL (http/https)
  .ip() // Valid IP address (IPv4/IPv6)
  .uuid() // Valid UUID v4 format
  .time() // Valid time format (HH:mm)
  .slug() // Valid slug (alphanumeric, dash, underscore)
  .creditCard() // Valid credit card (Luhn algorithm)
  .iban() // Valid IBAN format
  .safeString() // XSS/SQL injection protection
  .regex(/^[A-Z0-9]+$/) // Custom regex pattern
  .postalCode("PK") // Postal code for specific country
  .custom((value) => {
    // Custom validation
    return value.includes("@") ? null : "Must contain @";
  });

// Advanced string validations examples:

// URL validation
string().url().validate("https://example.com"); // ✅
string().url().validate("invalid-url"); // ❌

// IP address validation
string().ip().validate("192.168.0.1"); // ✅ IPv4
string().ip().validate("2001:db8::1"); // ✅ IPv6

// UUID validation
string().uuid().validate("550e8400-e29b-41d4-a716-446655440000"); // ✅

// Time validation
string().time().validate("14:30"); // ✅
string().time().validate("25:30"); // ❌

// Slug validation
string().slug().validate("zohaib_irshad"); // ✅
string().slug().validate("invalid slug"); // ❌

// Credit card validation (Luhn algorithm)
string().creditCard().validate("4111111111111111"); // ✅ Visa test card

// IBAN validation
string().iban().validate("PK36SCBL0000001123456702"); // ✅

// Safe string (XSS/SQL injection protection)
string().safeString().validate("Safe user input"); // ✅
string().safeString().validate("<script>alert(1)</script>"); // ❌

// Custom regex
string()
  .regex(/^[A-Z0-9]+$/)
  .validate("ABC123"); // ✅

// Postal codes for different countries
string().postalCode("US").validate("12345"); // ✅ US ZIP
string().postalCode("PK").validate("54000"); // ✅ Pakistan
string().postalCode("UK").validate("SW1A 1AA"); // ✅ UK postcode
string().postalCode("CA").validate("K1A 0A6"); // ✅ Canada

number()

Creates a number validator.

import { number } from "light-validate";

const validator = number()
  .required() // Field is required
  .min(0) // Minimum value
  .max(100) // Maximum value
  .custom((value) => {
    // Custom validation
    return value % 2 === 0 ? null : "Must be even";
  });

boolean()

Creates a boolean validator.

import { boolean } from "light-validate";

const validator = boolean()
  .required() // Field is required
  .custom((value) => {
    // Custom validation
    return value === true ? null : "Must be true";
  });

object(schema)

Creates an object validator with a schema.

import { object, string, number, array } from "light-validate";

const validator = object({
  name: string().required(),
  age: number().min(0),
})
  .required() // Object itself is required
  .custom((obj) => {
    // Custom validation on entire object
    return obj.name && obj.age ? null : "Invalid user";
  });

// Advanced Object Validations

// Non-empty object validation
object({
  name: string(),
  email: string()
})
  .notEmpty() // Object cannot be empty
  .validate({ name: 'John' }); // ✅

// Required keys validation
object({
  name: string(),
  email: string(),
  age: number()
})
  .hasKeys(['name', 'email']) // These keys must exist
  .validate({ name: 'John', email: 'john@test.com', age: 30 }); // ✅

// Strict keys validation (no unexpected keys)
object({
  name: string(),
  age: number()
})
  .strictKeys() // Only defined keys allowed
  .validate({ name: 'John', age: 30 }); // ✅
  .validate({ name: 'John', age: 30, email: 'extra' }); // ❌ (unexpected key)

// Deep nested validation using dot notation
object({
  user: object({
    profile: object({
      name: string()
    })
  })
})
  .deepKey('user.profile.name', string().min(2))
  .validate({
    user: {
      profile: {
        name: 'John'
      }
    }
  }); // ✅

// Array contains validation (validate arrays inside objects)
object({
  tags: array(),
  categories: array()
})
  .arrayContains('tags', 'javascript') // tags array must contain 'javascript'
  .validate({
    tags: ['javascript', 'typescript'],
    categories: ['frontend']
  }); // ✅

// Plain object validation (reject Date, RegExp, etc.)
object({
  data: string()
})
  .plainObject() // Must be a plain object, not Date/RegExp/etc
  .validate({ data: 'value' }); // ✅
  .validate(new Date()); // ❌ (not a plain object)

// Combined advanced validations
object({
  name: string().required(),
  email: string().email().required(),
  age: number().min(18),
  tags: array()
})
  .notEmpty()
  .hasKeys(['name', 'email'])
  .strictKeys()
  .plainObject()
  .arrayContains('tags', 'verified')
  .validate({
    name: 'John',
    email: 'john@test.com',
    age: 25,
    tags: ['verified', 'user']
  }); // ✅ (passes all validations)

array()

Creates an array validator with advanced validation options.

import { array, string, number } from "light-validate";

const validator = array()
  .required() // Array is required
  .min(1) // Minimum number of items
  .max(10) // Maximum number of items
  .unique() // All items must be unique
  .of(string()) // Validate each item as string
  .custom((arr) => {
    // Custom validation
    return arr.length > 0 ? null : "Cannot be empty";
  });

// Array validation examples:

// Basic array with length constraints
array().min(1).max(5).validate([1, 2, 3]); // ✅

// Unique items validation
array().unique().validate([1, 2, 3, 4]); // ✅
array().unique().validate([1, 2, 2, 3]); // ❌ (duplicate items)

// Array of validated items
array().of(string().email()).validate(["test@test.com", "user@example.org"]); // ✅

// Complex array validation
array()
  .min(2, "At least 2 items required")
  .max(5, "Maximum 5 items allowed")
  .unique("All items must be unique")
  .of(
    string()
      .min(3, "Each item must be at least 3 characters")
      .slug("Each item must be a valid slug")
  )
  .validate(["user_1", "admin_2", "guest_3"]); // ✅

// Advanced Array Validations

// Sorted array validation
array()
  .of(number())
  .sorted() // Must be sorted in ascending order
  .validate([1, 2, 3, 4]); // ✅

array()
  .of(number())
  .sorted("desc") // Must be sorted in descending order
  .validate([4, 3, 2, 1]); // ✅

// Type consistency validation
array()
  .ofType("string") // All items must be strings
  .validate(["a", "b", "c"]); // ✅

array()
  .ofType("number") // All items must be numbers
  .validate([1, 2, 3]); // ✅

// Exact length validation
array()
  .length(3) // Must have exactly 3 items
  .validate([1, 2, 3]); // ✅

// Non-empty validation
array()
  .notEmpty() // Cannot be empty
  .validate([1]); // ✅

// Contains specific value
array()
  .contains("required-item") // Must contain this value
  .validate(["a", "required-item", "c"]); // ✅

// Does not contain specific value
array()
  .notContains("forbidden") // Must not contain this value
  .validate(["a", "b", "c"]); // ✅

// Combined advanced validations
array()
  .of(number())
  .notEmpty()
  .length(3)
  .sorted()
  .contains(2)
  .validate([1, 2, 3]); // ✅ (exactly 3 numbers, sorted, contains 2)

enum(allowedValues)

Creates an enum validator for predefined values.

import { enum as enumValidator } from "light-validate";

// String enum validation
const statusValidator = enumValidator([
  "active",
  "inactive",
  "pending",
] as const)
  .required() // Enum value is required
  .custom((value) => {
    // Custom validation
    return value === "inactive" ? "Inactive status not allowed" : null;
  });

// Number enum validation
const priorityValidator = enumValidator([1, 2, 3, 4, 5] as const);

// TypeScript enum support
enum UserRole {
  ADMIN = "admin",
  USER = "user",
  GUEST = "guest",
}
const roleValidator = enumValidator(Object.values(UserRole));

// Mixed enum (string + number)
const mixedValidator = enumValidator([
  "low",
  1,
  "medium",
  2,
  "high",
  3,
] as const);

dateRange(options)

Creates a date range validator to ensure start date is before end date.

import { dateRange } from "light-validate";

// Basic date range validation (ISO format: YYYY-MM-DD)
const basicRange = dateRange().required().validate({
  start: "2025-01-01",
  end: "2025-12-31",
}); // ✅

// Date range with options
const flexibleRange = dateRange({
  allowSameDate: true, // Allow start = end
  dateFormat: "US", // MM/DD/YYYY format
});

// Different date formats supported:
const isoRange = dateRange({ dateFormat: "ISO" }); // YYYY-MM-DD
const usRange = dateRange({ dateFormat: "US" }); // MM/DD/YYYY
const euRange = dateRange({ dateFormat: "EU" }); // DD/MM/YYYY

// Usage examples:
dateRange().validate({
  start: "2025-01-01",
  end: "2025-12-31",
}); // ✅ Valid range

dateRange().validate({
  start: "2025-12-31",
  end: "2025-01-01",
}); // ❌ Start after end

dateRange({ allowSameDate: true }).validate({
  start: "2025-06-15",
  end: "2025-06-15",
}); // ✅ Same date allowed

// Custom validation on date ranges
dateRange()
  .custom((range) => {
    const start = new Date(range.start);
    const end = new Date(range.end);
    const diffDays = (end.getTime() - start.getTime()) / (1000 * 60 * 60 * 24);
    return diffDays <= 365 ? null : "Date range cannot exceed 1 year";
  })
  .validate({ start: "2025-01-01", end: "2025-12-31" }); // ✅

file()

Creates a file validator for validating File objects or file-like data.

import { file } from "light-validate";

const validator = file()
  .required() // File is required
  .images() // Accept only image files
  .maxSizeMB(5) // Maximum 5MB
  .minSizeKB(10) // Minimum 10KB
  .extensions(["jpg", "png"]) // Specific extensions
  .types("IMAGE", "DOCUMENT") // File type categories
  .mimeTypes(["image/jpeg", "image/png"]) // Specific MIME types
  .custom((fileData) => {
    // Custom validation (e.g., filename patterns)
    return fileData.name.includes("profile") ? null : "Must be a profile image";
  });

// File type categories available:
// IMAGE, AUDIO, VIDEO, DOCUMENT, TEXT, ARCHIVE, CODE

// File size methods:
file().maxSize(1024); // Maximum size in bytes
file().minSize(512); // Minimum size in bytes
file().maxSizeKB(500); // Maximum in kilobytes
file().minSizeKB(10); // Minimum in kilobytes
file().maxSizeMB(5); // Maximum in megabytes
file().minSizeMB(1); // Minimum in megabytes

// Multiple file type validation:
file().types("IMAGE", "DOCUMENT"); // Accept images and documents
file().extensions(["pdf", "jpg", "png"]); // Specific extensions
file().mimeTypes(["application/pdf", "image/jpeg"]); // MIME types

// Convenience methods for common file types:
file().images(); // Accept images only
file().audio(); // Accept audio files only
file().video(); // Accept video files only
file().documents(); // Accept documents only
file().textFiles(); // Accept text files only
file().archives(); // Accept archive files only
file().codeFiles(); // Accept code files only

// Note: Image dimension validation (width/height) can be implemented
// using custom validation with image processing libraries

Custom Error Messages

All validators support custom error messages for internationalization and better UX:

import { string, number, object } from "light-validate";

// Individual custom messages
const nameValidator = string()
  .required("نام ضروری ہے") // Name is required (Urdu)
  .min(3, "کم از کم 3 حروف") // At least 3 characters (Urdu)
  .email("صحیح ای میل درج کریں"); // Enter valid email (Urdu)

// Bulk custom messages using messages() method
const ageValidator = number()
  .messages({
    required: "Age is mandatory",
    type: "Must be a valid number",
    min: "Too young for this service",
    max: "Age limit exceeded",
  })
  .required()
  .min(18)
  .max(65);

// Custom validation with custom error message
const passwordValidator = string().custom(
  (password) =>
    /^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])/.test(password) ? null : "Invalid",
  "پاس ورڈ میں کم از کم ایک بڑا حرف، چھوٹا حرف اور نمبر ہونا چاہیے"
);

Validation Methods

All validators support these methods:

  • .required() - Makes the field required (fails on null/undefined)
  • .custom(validator) - Adds a custom validation function

Type-specific methods:

  • String: .min(length), .max(length), .email(), .url(), .ip(), .uuid(), .time(), .slug(), .creditCard(), .iban(), .safeString(), .regex(pattern), .postalCode(country)
  • Number: .min(value), .max(value)
  • Boolean: No additional methods beyond base methods
  • Array: .min(length), .max(length), .of(validator), .unique()
  • Enum: Validates against predefined allowed values
  • File: .maxSizeMB(), .extensions(), .mimeTypes(), .images(), .types(), etc.
  • DateRange: Date format options (ISO, US, EU), .allowSameDate option

Validation Result

All validators return a ValidationResult:

interface ValidationResult {
  success: boolean;
  errors?: string[];
}

Example:

// Success
{ success: true }

// Failure
{
  success: false,
  errors: ["This field is required", "Must be at least 3 characters"]
}

Examples

File Upload Validation

import { object, string, file, array } from "light-validate";

// Single file validation with comprehensive checks
const profileSchema = object({
  name: string().required("نام ضروری ہے").min(2), // Urdu error message
  avatar: file()
    .required("تصویر اپ لوڈ کریں") // Upload image (Urdu)
    .images() // Only image files
    .maxSizeMB(5) // Maximum 5MB
    .minSizeKB(10) // Minimum 10KB
    .extensions(["jpg", "jpeg", "png"]) // Specific extensions
    .mimeTypes(["image/jpeg", "image/png"]) // MIME type validation
    .custom((fileData) => {
      return fileData.name.includes("profile")
        ? null
        : 'Filename must contain "profile"';
    }),
});

// Multiple files validation with different types
const documentSchema = object({
  title: string().required().min(5),
  attachments: array()
    .required()
    .min(1, "At least one document required")
    .max(5, "Maximum 5 documents allowed")
    .of(
      file()
        .types("DOCUMENT", "TEXT") // PDF, DOC, CSV, etc.
        .maxSizeMB(10) // Each file max 10MB
        .mimeTypes([
          "application/pdf",
          "text/csv",
          "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
        ])
    ),

  // Mixed media files
  mediaFiles: array()
    .of(
      file()
        .types("IMAGE", "VIDEO", "AUDIO") // Multiple categories
        .maxSizeMB(50) // Larger limit for media
        .custom((fileData) => {
          // Custom business rule
          if (
            fileData.size > 20 * 1024 * 1024 &&
            fileData.name.includes("preview")
          ) {
            return "Preview files should be under 20MB";
          }
          return null;
        })
    )
    .max(10, "Maximum 10 media files"),
});

// Advanced file validation with size and type checks
const advancedFileSchema = object({
  documents: array().of(
    file()
      .documents() // Document files only
      .maxSizeMB(25)
      .extensions(["pdf", "docx", "xlsx"])
  ),

  images: array().of(
    file()
      .images() // Image files only
      .maxSizeMB(5)
      .minSizeKB(50) // Prevent tiny/corrupt images
      .mimeTypes(["image/jpeg", "image/png", "image/webp"])
  ),

  archives: array().of(
    file()
      .archives() // ZIP, RAR, etc.
      .maxSizeMB(100)
      .extensions(["zip", "rar", "7z"])
  ),
});

// Usage with File objects from input[type="file"]
const fileInput = document.getElementById("upload") as HTMLInputElement;
const files = fileInput.files;

if (files && files.length > 0) {
  const result = profileSchema.validate({
    name: "احمد علی", // Urdu name
    avatar: files[0], // File object
  });

  console.log(result);
}

Multi-language Error Messages

import { object, string, number } from "light-validate";

// English version
const englishSchema = object({
  email: string()
    .required("Email is required")
    .email("Please enter a valid email address"),
  age: number()
    .required("Age is required")
    .min(18, "You must be at least 18 years old"),
});

// Urdu version with same validation logic
const urduSchema = object({
  email: string()
    .required("ای میل ایڈریس ضروری ہے")
    .email("صحیح ای میل ایڈریس درج کریں"),
  age: number()
    .required("عمر ضروری ہے")
    .min(18, "آپ کی عمر کم از کم 18 سال ہونی چاہیے"),
});

// Test data
const userData = { email: "invalid", age: 16 };

console.log("English:", englishSchema.validate(userData));
// English: { success: false, errors: ['email: Please enter a valid email address', 'age: You must be at least 18 years old'] }

console.log("Urdu:", urduSchema.validate(userData));
// Urdu: { success: false, errors: ['email: صحیح ای میل ایڈریس درج کریں', 'age: آپ کی عمر کم از کم 18 سال ہونی چاہیے'] }

Custom Business Rules

import { object, string, number, file } from "light-validate";

// E-commerce product validation with business rules
const productSchema = object({
  title: string()
    .required("Product name is required")
    .min(5, "Product name too short")
    .custom((title) => {
      // Business rule: No spam words allowed
      const spamWords = ["free", "urgent", "limited"];
      const hasSpam = spamWords.some((word) =>
        title.toLowerCase().includes(word)
      );
      return hasSpam ? "Product name contains prohibited words" : null;
    }),

  price: number()
    .required("Price is required")
    .min(1, "Price must be positive")
    .custom((price) => {
      // Business rule: Price should be reasonable
      if (price > 10000 && price % 1000 === 0) {
        return "Price seems too rounded - please set market rate";
      }
      return null;
    }),

  images: array()
    .required("Product images required")
    .min(1, "At least one image required")
    .max(10, "Maximum 10 images allowed")
    .of(
      file()
        .images()
        .maxSizeMB(5)
        .custom((fileData) => {
          // Business rule: Images must follow naming convention
          return fileData.name.includes("product_")
            ? null
            : 'Image filename must start with "product_"';
        })
    ),
});

Advanced String & Array Validations

import { object, string, array, dateRange } from "light-validate";

// Comprehensive user profile validation
const userProfileSchema = object({
  // Personal Information
  username: string()
    .required("صارف نام ضروری ہے") // Username required (Urdu)
    .slug("صرف حروف، نمبرز، ڈیش اور انڈر سکور") // Only letters, numbers, dash, underscore (Urdu)
    .min(3, "کم از کم 3 حروف")
    .max(20, "زیادہ سے زیادہ 20 حروف"),

  email: string().required("ای میل ضروری ہے").email("صحیح ای میل درج کریں"),

  website: string()
    .url("صحیح ویب سائٹ کا لنک درج کریں")
    .custom((url) => {
      // Business rule: Only allow HTTPS
      return url.startsWith("https://") ? null : "صرف HTTPS لنکس کی اجازت ہے";
    }),

  phone: string().regex(
    /^\+92[0-9]{10}$/,
    "پاکستانی فون نمبر درج کریں (+92xxxxxxxxxx)"
  ),

  // Security
  ipAddress: string().ip("صحیح IP ایڈریس درج کریں"),

  userId: string().uuid("صحیح UUID فارمیٹ درج کریں"),

  // Financial
  creditCard: string().creditCard("صحیح کریڈٹ کارڈ نمبر درج کریں"),

  iban: string().iban("صحیح IBAN نمبر درج کریں"),

  // Address
  postalCode: string().postalCode("PK", "پاکستان کا صحیح پوسٹل کوڈ درج کریں"),

  // Content Security
  bio: string()
    .safeString("غیر محفوظ مواد کی اجازت نہیں")
    .max(500, "تعارف 500 حروف سے زیادہ نہیں ہو سکتا"),

  // Time & Schedule
  workingHours: object({
    start: string().time("صحیح وقت فارمیٹ (HH:mm)"),
    end: string().time("صحیح وقت فارمیٹ (HH:mm)"),
  }),

  // Project dates
  projectDuration: dateRange({
    dateFormat: "ISO",
    allowSameDate: false,
  })
    .required("منصوبے کی تاریخ ضروری ہے")
    .custom((range) => {
      const start = new Date(range.start);
      const end = new Date(range.end);
      const diffMonths =
        (end.getFullYear() - start.getFullYear()) * 12 +
        (end.getMonth() - start.getMonth());
      return diffMonths <= 24 ? null : "منصوبہ 2 سال سے زیادہ نہیں ہو سکتا";
    }),

  // Skills array with unique validation
  skills: array()
    .required("کم از کم ایک مہارت ضروری ہے")
    .min(1, "کم از کم ایک مہارت")
    .max(10, "زیادہ سے زیادہ 10 مہارتیں")
    .unique("تمام مہارتیں منفرد ہونی چاہیے")
    .of(
      string()
        .min(2, "مہارت کم از کم 2 حروف")
        .slug("مہارت میں صرف حروف، نمبرز، ڈیش")
        .custom((skill) => {
          const forbiddenSkills = ["hacking", "spam", "fraud"];
          return forbiddenSkills.includes(skill.toLowerCase())
            ? "یہ مہارت قابل قبول نہیں"
            : null;
        })
    ),

  // Languages with proficiency
  languages: array()
    .min(1, "کم از کم ایک زبان")
    .of(
      object({
        language: enumValidator([
          "en",
          "ur",
          "ar",
          "es",
          "fr",
          "de",
        ] as const).required("زبان کا انتخاب ضروری"),
        proficiency: enumValidator([
          "beginner",
          "intermediate",
          "advanced",
          "native",
        ] as const).required("مہارت کی سطح"),
      })
    )
    .unique("ہر زبان صرف ایک بار"),
});

// API validation example
const apiRequestSchema = object({
  // Request validation
  apiKey: string()
    .required("API کلید ضروری")
    .regex(/^[A-Za-z0-9]{32}$/, "API کلید 32 حروف کی ہونی چاہیے"),

  callback: string()
    .url("صحیح callback URL")
    .custom((url) => {
      // Security: Only allow HTTPS callbacks
      return url.startsWith("https://") ? null : "Callback URL must use HTTPS";
    }),

  serverIp: string().required("سرور IP ضروری").ip("صحیح IP address"),

  requestId: string().uuid("صحیح request UUID"),

  // Data validation
  payload: object({
    data: string()
      .safeString("غیر محفوظ ڈیٹا کی اجازت نہیں")
      .max(10000, "ڈیٹا 10KB سے زیادہ نہیں"),

    checksum: string().regex(/^[a-f0-9]{64}$/, "صحیح SHA-256 checksum"),
  }),
});

// E-commerce validation
const productSchema = object({
  sku: string()
    .required("SKU ضروری")
    .regex(/^[A-Z0-9-]{6,20}$/, "SKU: 6-20 حروف، بڑے حروف، نمبرز، ڈیش"),

  pricing: object({
    currency: enumValidator(["PKR", "USD", "EUR", "GBP"] as const).required(
      "کرنسی کا انتخاب"
    ),
    amount: number()
      .min(0.01, "کم از کم 0.01")
      .max(999999.99, "زیادہ سے زیادہ 999999.99"),
  }),

  availability: dateRange({
    dateFormat: "ISO",
  }).required("دستیابی کی تاریخ"),

  tags: array()
    .max(20, "زیادہ سے زیادہ 20 ٹیگز")
    .unique("تمام ٹیگز منفرد")
    .of(
      string()
        .slug("ٹیگ میں صرف حروف، نمبرز، ڈیش")
        .min(2, "کم از کم 2 حروف")
        .max(30, "زیادہ سے زیادہ 30 حروف")
    ),
});

// Usage examples
const profileResult = userProfileSchema.validate({
  username: "zohaib_dev",
  email: "zohaib@example.com",
  website: "https://zohaib.dev",
  phone: "+923001234567",
  skills: ["javascript", "typescript", "react", "node"],
  languages: [
    { language: "en", proficiency: "native" },
    { language: "ur", proficiency: "native" },
  ],
  projectDuration: {
    start: "2025-01-01",
    end: "2025-06-30",
  },
});

Enum Validation Examples

import { object, string, enum as enumValidator } from "light-validate";

// Basic enum validation
const orderSchema = object({
  status: enumValidator([
    "pending",
    "processing",
    "shipped",
    "delivered",
  ] as const).required("Order status is required"),

  priority: enumValidator([1, 2, 3, 4, 5] as const).required(
    "Priority level is required"
  ),
});

// TypeScript enum support
enum PaymentMethod {
  CREDIT_CARD = "credit_card",
  DEBIT_CARD = "debit_card",
  PAYPAL = "paypal",
  BANK_TRANSFER = "bank_transfer",
}

enum SubscriptionTier {
  FREE = 0,
  BASIC = 1,
  PREMIUM = 2,
  ENTERPRISE = 3,
}

const subscriptionSchema = object({
  paymentMethod: enumValidator(Object.values(PaymentMethod)).required(
    "Payment method is required"
  ),

  tier: enumValidator([
    SubscriptionTier.FREE,
    SubscriptionTier.BASIC,
    SubscriptionTier.PREMIUM,
    SubscriptionTier.ENTERPRISE,
  ])
    .required("Subscription tier is required")
    .custom((tier) => {
      // Business rule: Free tier has limitations
      if (tier === SubscriptionTier.FREE) {
        return "Free tier signup is temporarily disabled";
      }
      return null;
    }),
});

// Multi-language enum with custom messages
const languageSchema = object({
  language: enumValidator(["en", "ur", "ar", "es", "fr"] as const)
    .required("زبان کا انتخاب ضروری ہے") // Language selection required (Urdu)
    .messages({
      enum: "صرف مدد شدہ زبانیں منتخب کریں: انگریزی، اردو، عربی، ہسپانوی، فرانسیسی", // Only supported languages (Urdu)
    }),

  region: enumValidator(["US", "UK", "PK", "IN", "CA"] as const)
    .required()
    .custom((region) => {
      return region === "PK"
        ? null
        : "Service currently available in Pakistan only";
    }),
});

// Usage examples
const result1 = orderSchema.validate({
  status: "shipped",
  priority: 3,
});

const result2 = subscriptionSchema.validate({
  paymentMethod: PaymentMethod.CREDIT_CARD,
  tier: SubscriptionTier.PREMIUM,
});

const result3 = languageSchema.validate({
  language: "ur",
  region: "PK",
});

Advanced Array and Object Validations

The library provides sophisticated validation capabilities for complex data structures with chainable APIs.

Advanced Array Validations

import { array, string, number } from "light-validate";

// Sorted array validation
const sortedNumbers = array()
  .of(number())
  .sorted() // Ascending order
  .notEmpty()
  .validate([1, 2, 3, 4, 5]); // ✅

const sortedDescending = array()
  .of(number())
  .sorted("desc") // Descending order
  .validate([5, 4, 3, 2, 1]); // ✅

// Type consistency validation
const stringArray = array()
  .ofType("string") // All items must be strings
  .notEmpty()
  .validate(["apple", "banana", "cherry"]); // ✅

const numberArray = array()
  .ofType("number") // All items must be numbers
  .min(3) // At least 3 items
  .max(10) // At most 10 items
  .validate([1, 2, 3, 4, 5]); // ✅

// Exact length and content validation
const exactArray = array()
  .length(3) // Exactly 3 items
  .contains("required") // Must contain 'required'
  .notContains("forbidden") // Must not contain 'forbidden'
  .validate(["item1", "required", "item3"]); // ✅

// Complex array validation combining multiple rules
const advancedArray = array()
  .of(string().min(2).max(20))
  .notEmpty()
  .length(5)
  .sorted()
  .ofType("string")
  .contains("admin")
  .unique()
  .validate(["admin", "guest", "moderator", "user", "visitor"]); // ✅

Advanced Object Validations

import { object, string, number, array } from "light-validate";

// Non-empty and required keys validation
const userProfile = object({
  name: string().required(),
  email: string().email(),
  age: number(),
  skills: array(),
})
  .notEmpty() // Object cannot be empty
  .hasKeys(["name", "email"]) // These keys must exist
  .validate({
    name: "John Doe",
    email: "john@example.com",
    age: 30,
    skills: ["JavaScript", "TypeScript"],
  }); // ✅

// Strict keys validation (no unexpected properties)
const strictUser = object({
  username: string().required(),
  password: string().required(),
})
  .hasKeys(["username", "password"])
  .strictKeys() // Only defined keys allowed
  .validate({
    username: "johndoe",
    password: "secret123",
    // email: 'extra@example.com' // ❌ Would fail - unexpected key
  }); // ✅

// Deep nested property validation using dot notation
const nestedValidation = object({
  user: object({
    profile: object({
      personal: object({
        name: string(),
        contact: object({
          email: string(),
          phone: string(),
        }),
      }),
    }),
    settings: object({
      preferences: array(),
    }),
  }),
})
  .deepKey("user.profile.personal.name", string().min(2).required())
  .deepKey("user.profile.personal.contact.email", string().email())
  .deepKey("user.settings.preferences", array().notEmpty())
  .validate({
    user: {
      profile: {
        personal: {
          name: "John",
          contact: {
            email: "john@test.com",
            phone: "+1234567890",
          },
        },
      },
      settings: {
        preferences: ["dark-mode", "notifications"],
      },
    },
  }); // ✅

// Array contains validation within objects
const projectValidation = object({
  name: string().required(),
  technologies: array(),
  categories: array(),
  team: array(),
})
  .arrayContains("technologies", "javascript") // Must use JavaScript
  .arrayContains("categories", "web") // Must be web category
  .arrayContains("team", "developer") // Must have a developer
  .validate({
    name: "My Web App",
    technologies: ["javascript", "typescript", "react"],
    categories: ["web", "frontend"],
    team: ["developer", "designer", "manager"],
  }); // ✅

// Plain object validation (reject special objects)
const plainObjectValidation = object({
  data: string(),
  metadata: object({}),
})
  .plainObject() // Must be plain object, not Date/RegExp/etc
  .validate({
    data: "sample",
    metadata: { version: "1.0" },
  }); // ✅
// .validate(new Date()); // ❌ Would fail - not a plain object

// Enterprise-level validation combining all features
const enterpriseUserSchema = object({
  profile: object({
    personalInfo: object({
      firstName: string().required(),
      lastName: string().required(),
      email: string().email().required(),
    }),
    professionalInfo: object({
      skills: array(),
      experience: number(),
      certifications: array(),
    }),
  }),
  account: object({
    permissions: array(),
    roles: array(),
    status: string(),
  }),
  preferences: object({
    notifications: array(),
    privacy: object({}),
  }),
})
  .notEmpty()
  .hasKeys(["profile", "account"])
  .strictKeys()
  .plainObject()
  .deepKey("profile.personalInfo.firstName", string().min(2))
  .deepKey("profile.personalInfo.lastName", string().min(2))
  .deepKey(
    "profile.professionalInfo.skills",
    array().notEmpty().ofType("string")
  )
  .deepKey("account.permissions", array().notEmpty())
  .arrayContains("account.roles", "user")
  .arrayContains("preferences.notifications", "email")
  .validate({
    profile: {
      personalInfo: {
        firstName: "John",
        lastName: "Doe",
        email: "john.doe@company.com",
      },
      professionalInfo: {
        skills: ["JavaScript", "TypeScript", "React"],
        experience: 5,
        certifications: ["AWS", "Google Cloud"],
      },
    },
    account: {
      permissions: ["read", "write", "delete"],
      roles: ["user", "admin"],
      status: "active",
    },
    preferences: {
      notifications: ["email", "push", "sms"],
      privacy: { shareProfile: false },
    },
  }); // ✅ Passes all validations

User Registration Validation

import { object, string, number, boolean } from "light-validate";

const userSchema = object({
  username: string().required().min(3).max(20),
  email: string().required().email(),
  password: string()
    .required()
    .min(8)
    .custom((value) => {
      if (!/[A-Z]/.test(value)) return "Must contain uppercase letter";
      if (!/[a-z]/.test(value)) return "Must contain lowercase letter";
      if (!/[0-9]/.test(value)) return "Must contain number";
      return null;
    }),
  age: number().required().min(13),
  acceptTerms: boolean()
    .required()
    .custom((value) => {
      return value === true ? null : "Must accept terms";
    }),
});

const result = userSchema.validate({
  username: "john_doe",
  email: "john@example.com",
  password: "SecurePass123",
  age: 25,
  acceptTerms: true,
});

Nested Object Validation

import { object, string, array } from "light-validate";

const companySchema = object({
  name: string().required(),
  employees: array()
    .of(
      object({
        name: string().required(),
        email: string().email(),
        department: string().required(),
      })
    )
    .min(1),
  address: object({
    street: string().required(),
    city: string().required(),
    zipCode: string().min(5).max(10),
  }).required(),
});

Tree-Shaking (Import Individual Validators)

// Import only what you need for smaller bundle size
import { string as createStringValidator } from "light-validate";
import { number as createNumberValidator } from "light-validate";

const nameValidator = createStringValidator().required().min(2);
const ageValidator = createNumberValidator().min(0).max(120);

TypeScript Support

The library is written in TypeScript and provides excellent type inference:

import { object, string, number } from "light-validate";

// TypeScript will infer the correct types
const schema = object({
  name: string().required(),
  age: number(),
});

// result is typed as ValidationResult
const result = schema.validate(someData);

if (result.success) {
  // No errors
  console.log("Validation passed!");
} else {
  // result.errors is string[]
  console.log("Errors:", result.errors);
}

Error Messages

The library provides clear, descriptive error messages:

const schema = object({
  name: string().required().min(3),
  age: number().min(18),
});

const result = schema.validate({ name: "Jo", age: 15 });

console.log(result.errors);
// [
//   "name: Must be at least 3 characters long",
//   "age: Must be at least 18"
// ]

Bundle Size

Light Validate is designed to be minimal:

  • Core library: ~3KB minified
  • Tree-shakeable: Import only what you use
  • Zero dependencies: No external libraries

Comparison with Other Libraries

FeatureLight ValidateYupJoiZod
Bundle Size~3KB~65KB~145KB~30KB
Dependencies0SeveralSeveral0
Tree Shaking
TypeScript
Learning CurveEasyMediumMediumMedium

License

MIT

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Keywords

validation

FAQs

Package last updated on 05 Sep 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts