snap-validate
TypeScript icon, indicating that this package has built-in type declarations

0.3.3 • Public • Published

Snap Validate ⚡

npm version Build Status License: MIT install size npm bundle size npm downloads

A lightning-fast, lightweight validation library for common patterns without heavy dependencies. Perfect for client-side and server-side validation with zero external dependencies and built-in protection against ReDoS (Regular Expression Denial of Service) attacks.

Features

  • Lightning Fast: Optimized for speed and performance
  • 🚀 Lightweight: No external dependencies, minimal footprint
  • 🔧 Flexible: Chainable validation rules and custom validators
  • 📧 Common Patterns: Email, phone, credit card, URL, password validation
  • 🌍 International: Support for different formats (US/International phone, postal codes)
  • 🔄 Async Support: Full async validation support for database checks and API calls
  • 🎯 Conditional: Advanced conditional validation with when() and optional()
  • 🛠️ Custom Validators: Add your own sync and async validation logic
  • 🔒 Security First: Built-in protection against ReDoS attacks and unsafe regex patterns
  • 🛡️ Timeout Protection: Configurable timeout for regex operations to prevent DoS attacks
  • 🧪 Well Tested: Comprehensive test suite with high coverage
  • 📦 Easy Integration: Works in Node.js and browsers
  • 🔗 Chainable API: Intuitive fluent interface
  • 📘 TypeScript Support: Complete TypeScript definitions with full IntelliSense support

Installation

npm install snap-validate

TypeScript

For TypeScript projects, types are included automatically:

npm install snap-validate
# Types are included - no need for @types/snap-validate

Quick Start

const { validators, validate } = require('snap-validate');

// Single field validation
const emailResult = validators.email('user@example.com').validate();
console.log(emailResult.isValid); // true

// Schema validation
const schema = {
  email: validators.email,
  phone: (value) => validators.phone(value, 'us'),
  password: validators.password
};

const data = {
  email: 'user@example.com',
  phone: '(555) 123-4567',
  password: 'SecurePass123'
};

const result = validate(schema, data);
console.log(result.isValid); // true

TypeScript Support

Snap Validate includes comprehensive TypeScript definitions for enhanced developer experience:

import { BaseValidator, validators, validate, ValidationResult } from 'snap-validate';

// Full type safety and auto-completion
const validator = new BaseValidator('test-value')
  .required('This field is required')
  .min(5, 'Must be at least 5 characters')
  .pattern(/^[a-zA-Z]+$/, 'Only letters allowed');

// Type-safe result handling
const result: ValidationResult = validator.validate();

// Schema validation with types
interface UserData {
  email: string;
  phone: string;
  password: string;
}

const userData: UserData = {
  email: 'john@example.com',
  phone: '1234567890',
  password: 'StrongPass123'
};

const schema = {
  email: validators.email,
  phone: (value: string) => validators.phone(value, 'us'),
  password: validators.password
};

const result = validate(schema, userData);

Features:

  • Complete type definitions for all classes and functions
  • IntelliSense support in VS Code, WebStorm, and other editors
  • Compile-time validation prevents common usage errors
  • Generic support for flexible validation workflows
  • Rich JSDoc comments for comprehensive documentation

Security Features

ReDoS Protection

Snap Validate includes built-in protection against Regular Expression Denial of Service (ReDoS) attacks:

  • Regex Safety Detection: Automatically detects and prevents potentially dangerous regex patterns
  • Input Length Limits: Protects against extremely long input strings (10,000 character limit)
  • Timeout Protection: Configurable timeout for regex operations (default: 1 second)
  • Safe Defaults: All predefined validators use safe, optimized regex patterns
// Set custom timeout for regex operations
const validator = new BaseValidator(value)
  .setRegexTimeout(2000) // 2 second timeout
  .pattern(/your-pattern/, 'Error message');

// Use async pattern validation for complex patterns with timeout protection
const validator = new BaseValidator(value)
  .patternAsync(/complex-pattern/, 'Error message');

const result = await validator.validateAsync();

Available Validators

Email Validation

validators.email('user@example.com').validate();

Phone Number Validation

// US format (default)
validators.phone('(555) 123-4567').validate();

// International format
validators.phone('+1234567890', 'international').validate();

// Simple numeric
validators.phone('1234567890', 'simple').validate();

Credit Card Validation

// Uses Luhn algorithm
validators.creditCard('4532015112830366').validate();

URL Validation

validators.url('https://example.com').validate();

Password Validation

// Default: min 8 chars, requires upper, lower, numbers
validators.password('SecurePass123').validate();

// Custom options
validators.password('MyPass123!', {
  minLength: 10,
  requireUppercase: true,
  requireLowercase: true,
  requireNumbers: true,
  requireSpecialChars: true
}).validate();

Alphanumeric Validation

validators.alphanumeric('ABC123').validate();

Numeric Validation

validators.numeric('12345').validate();

Zip Code Validation

// US zip code
validators.zipCode('12345').validate();
validators.zipCode('12345-6789').validate();

// Canadian postal code
validators.zipCode('K1A 0A6', 'ca').validate();

// UK postal code
validators.zipCode('SW1A 1AA', 'uk').validate();

Advanced Validation Features

Conditional Validation

const { BaseValidator } = require('snap-validate');

// Validate only when condition is met
const validator = new BaseValidator(value)
  .when(user.isAdmin, validators.required('Admin field required'))
  .min(5, 'Must be at least 5 characters');

// Optional validation - skip if empty/null/undefined
const optionalValidator = new BaseValidator(value)
  .optional()
  .email('Must be a valid email if provided');

// Function-based conditions
const conditionalValidator = new BaseValidator(value)
  .when(() => user.role === 'admin', validators.required())
  .max(100);

Custom Validators

const { BaseValidator } = require('snap-validate');

// Synchronous custom validation
const customValidator = new BaseValidator(value)
  .custom((val) => val !== 'forbidden', 'Value cannot be forbidden')
  .custom((val) => {
    if (val.includes('admin') && !user.isAdmin) {
      return 'Only admins can use this value';
    }
    return true;
  });

// Asynchronous custom validation
const asyncValidator = new BaseValidator(email)
  .email()
  .customAsync(async (email) => {
    const exists = await checkEmailExists(email);
    return !exists || 'Email already exists';
  }, 'Email validation failed');

// Use async validation
const result = await asyncValidator.validateAsync();

Async Validation

// Async validation for single field
const validator = new BaseValidator(username)
  .required()
  .min(3)
  .customAsync(async (username) => {
    const available = await checkUsernameAvailable(username);
    return available || 'Username is already taken';
  });

const result = await validator.validateAsync();

// Async schema validation
const asyncSchema = {
  username: (value) => new BaseValidator(value)
    .required()
    .customAsync(async (val) => {
      const available = await checkUsernameAvailable(val);
      return available || 'Username taken';
    }),
  
  email: (value) => validators.email(value)
    .customAsync(async (val) => {
      const exists = await checkEmailExists(val);
      return !exists || 'Email already registered';
    })
};

const asyncResult = await validate.async(asyncSchema, userData);

Security and Pattern Validation

Safe Pattern Validation

const { BaseValidator } = require('snap-validate');

// Synchronous pattern validation with built-in safety checks
const validator = new BaseValidator(value)
  .pattern(/^[a-zA-Z0-9]+$/, 'Only alphanumeric characters allowed');

// Asynchronous pattern validation with timeout protection
const asyncValidator = new BaseValidator(value)
  .patternAsync(/^[a-zA-Z0-9]+$/, 'Only alphanumeric characters allowed')
  .setRegexTimeout(5000); // 5 second timeout

const result = await asyncValidator.validateAsync();

Configurable Security Settings

const validator = new BaseValidator(value)
  .setRegexTimeout(3000) // Set custom timeout (3 seconds)
  .pattern(/your-pattern/, 'Error message');

// The library automatically:
// - Detects unsafe regex patterns
// - Limits input length to prevent ReDoS
// - Applies timeout protection for complex patterns
// - Provides clear error messages for security violations

Custom Validation

Using BaseValidator

const { BaseValidator } = require('snap-validate');

const customValidator = new BaseValidator('test-value')
  .required('This field is required')
  .min(5, 'Must be at least 5 characters')
  .max(20, 'Must be no more than 20 characters')
  .pattern(/^[a-zA-Z]+$/, 'Only letters allowed');

const result = customValidator.validate();

Schema Validation with Custom Rules

const schema = {
  username: (value) => new BaseValidator(value)
    .required()
    .min(3)
    .max(20)
    .pattern(/^[a-zA-Z0-9_]+$/, 'Username can only contain letters, numbers, and underscores'),
  
  email: validators.email,
  
  age: (value) => new BaseValidator(value)
    .required()
    .pattern(/^\d+$/, 'Age must be a number')
    .custom((val) => parseInt(val) >= 18, 'Must be 18 or older')
};

const userData = {
  username: 'john_doe',
  email: 'john@example.com',
  age: '25'
};

const result = validate(schema, userData);

Error Handling

const result = validators.email('invalid-email').validate();

if (!result.isValid) {
  console.log('Validation errors:', result.errors);
  // Output: ['Invalid email format']
}

// For schema validation
const schemaResult = validate(schema, data);
if (!schemaResult.isValid) {
  const errors = schemaResult.getErrors();
  console.log('Field errors:', errors);
  // Output: { email: ['Invalid email format'], password: ['Password too weak'] }
}

// Async error handling
try {
  const asyncResult = await validator.validateAsync();
  if (!asyncResult.isValid) {
    console.log('Async validation errors:', asyncResult.errors);
  }
} catch (error) {
  console.log('Validation exception:', error.message);
}

// Security-related errors
const unsafeResult = validator.pattern(/potentially-dangerous-pattern/, 'Error').validate();
if (!unsafeResult.isValid) {
  console.log('Security errors:', unsafeResult.errors);
  // Output: ['Potentially unsafe regex pattern detected']
}

Browser Usage

<script src="https://unpkg.com/snap-validate/src/index.js"></script>
<script>
  const { validators } = SnapValidate;
  
  const result = validators.email('user@example.com').validate();
  console.log(result.isValid);
</script>

API Reference

ValidationResult

  • isValid: boolean - Whether validation passed
  • errors: string[] - Array of error messages

BaseValidator Methods

  • required(message?) - Field is required
  • min(length, message?) - Minimum length validation
  • max(length, message?) - Maximum length validation
  • pattern(regex, message?) - Pattern matching validation with safety checks
  • patternAsync(regex, message?) - Async pattern validation with timeout protection
  • setRegexTimeout(timeoutMs) - Set custom timeout for regex operations
  • when(condition, validator) - Conditional validation
  • optional() - Skip validation if empty/null/undefined
  • custom(fn, message?) - Custom synchronous validation
  • customAsync(fn, message?) - Custom asynchronous validation
  • validate() - Execute synchronous validation
  • validateAsync() - Execute asynchronous validation

Available Validators

  • validators.email(value)
  • validators.phone(value, format?)
  • validators.creditCard(value)
  • validators.url(value)
  • validators.password(value, options?)
  • validators.alphanumeric(value)
  • validators.numeric(value)
  • validators.zipCode(value, country?)

TypeScript Types

  • ValidationResult - Interface for validation results
  • ValidatorFunction - Type for validator functions used in schemas
  • ValidationSchema - Type for validation schema objects
  • PasswordOptions - Interface for password validation configuration
  • BaseValidator<T> - Generic base validator class

Validation Functions

  • validate(schema, data) - Synchronous schema validation
  • validate.async(schema, data) - Asynchronous schema validation

Security Functions

  • isRegexSafe(regex) - Check if a regex pattern is safe to use
  • safeRegexText(regex, str, timeoutMs) - Execute regex with timeout protection

Security Best Practices

  1. Use Built-in Validators: The predefined validators are optimized for security and performance
  2. Validate Input Length: Large inputs are automatically limited to prevent ReDoS attacks
  3. Set Appropriate Timeouts: Configure regex timeouts based on your application's needs
  4. Test Custom Patterns: Use isRegexSafe() to check custom regex patterns before deployment
  5. Handle Async Errors: Always use try-catch blocks with async validation

Contributing

We welcome contributions! Please see our Contributing Guide for details.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Development

# Install dependencies
npm install

# Run tests
npm test

# Run tests in watch mode
npm run test:watch

# Run tests with coverage
npm run test:coverage

# Lint code
npm run lint

# Format code
npm run format

# Security audit
npm audit

# Type checking (for TypeScript users)
npm run type-check

# Validate TypeScript definitions
npm run validate-types

License

This project is licensed under the MIT License - see the LICENSE file for details.

Changelog

See CHANGELOG.md for a detailed history of changes.


Made with ⚡ by Ramachandra Anirudh Vemulapalli

Package Sidebar

Install

npm i snap-validate

Weekly Downloads

7

Version

0.3.3

License

MIT

Unpacked Size

44.4 kB

Total Files

6

Last publish

Collaborators

  • aniru_dh21