DEV Community

Cover image for Introducing IsoValid: A Lightweight Isomorphic Data Validation Library
alok5953
alok5953

Posted on

Introducing IsoValid: A Lightweight Isomorphic Data Validation Library

Image description

πŸš€ Why Data Validation Matters

Data validation is a crucial part of modern web applications, ensuring data integrity, security, and a smooth user experience. However, developers often struggle with:

  • Writing separate validation logic for frontend and backend
  • Managing multiple validation libraries across environments
  • Keeping validation consistent between client and server

Introducing IsoValidβ€”a powerful, isomorphic validation library that allows you to use the same validation logic across both browser and Node.js environments.


πŸ”₯ What is IsoValid?

IsoValid is a lightweight, TypeScript-first validation library designed to unify validation across your entire application stack. Whether you're validating user input in a React form or ensuring API request integrity in an Express server, IsoValid makes it seamless.

🌟 Key Features

βœ… True Isomorphic Support – The same validation code runs in both frontend and backend

βœ… TypeScript-First – Fully typed API for strong type inference

βœ… Minimal Bundle Size – No unnecessary dependencies or bloat

βœ… Intuitive API – Developer-friendly, chainable syntax

βœ… High Performance – Optimized validation with minimal overhead

βœ… Extensible – Easily add custom validators and error messages


πŸ“¦ Installation

Get started with IsoValid in seconds:

npm install isovalid
Enter fullscreen mode Exit fullscreen mode

πŸ”Ή Core Architecture

IsoValid is built on a flexible, extensible architecture that includes:

Base Schema Class

  • Foundation for all validation schemas
  • Handles optional/nullable states
  • Common validation logic across types

Type-Specific Schemas

  • StringSchema – Length, regex, email, trimming, etc.
  • NumberSchema – Min/max, integer, positive/negative checks
  • More types coming soon (Boolean, Array, Object)

Validation Pipeline

  • Multi-stage validation process
  • Supports custom validation functions
  • Returns detailed error reporting

⚑ Usage Examples

String Validation

import { v } from 'isovalid';

const stringSchema = v.string()
  .min(2)  // Minimum length
  .max(50) // Maximum length
  .email() // Must be a valid email
  .matches(/regex/) // Custom pattern
  .trimmed() // Remove extra whitespace
  .setOptional() // Allow undefined
  .setNullable(); // Allow null
Enter fullscreen mode Exit fullscreen mode

Number Validation

const numberSchema = v.number()
  .min(0) // Minimum value
  .max(100) // Maximum value
  .integer() // Must be an integer
  .positive(); // Must be > 0
Enter fullscreen mode Exit fullscreen mode

Validation Results

interface ValidationResult {
  valid: boolean;
  errors: Array<{ path: string[]; message: string; }>;
}
Enter fullscreen mode Exit fullscreen mode

🎯 Real-World Examples

1. React Form Validation

import { v } from 'isovalid';
import { useState, FormEvent } from 'react';

const userSchema = {
  username: v.string().min(3).max(20),
  email: v.string().email(),
  age: v.number().integer().min(18)
};

function RegistrationForm() {
  const [formData, setFormData] = useState({ username: '', email: '', age: '' });
  const [errors, setErrors] = useState<Record<string, string>>({});

  const validateField = (field: keyof typeof userSchema, value: any) => {
    const result = userSchema[field].validate(value);
    return result.valid ? null : result.errors[0].message;
  };

  const handleSubmit = (e: FormEvent) => {
    e.preventDefault();
    const newErrors: Record<string, string> = {};

    Object.entries(formData).forEach(([field, value]) => {
      const error = validateField(field as keyof typeof userSchema, value);
      if (error) newErrors[field] = error;
    });

    if (Object.keys(newErrors).length === 0) {
      console.log('Submitting:', formData);
    } else {
      setErrors(newErrors);
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <input type="text" placeholder="Username" onChange={e => setFormData(prev => ({ ...prev, username: e.target.value }))} />
      {errors.username && <span>{errors.username}</span>}
      <button type="submit">Register</button>
    </form>
  );
}
Enter fullscreen mode Exit fullscreen mode

2. Express API Validation

import express from 'express';
import { v } from 'isovalid';

const app = express();
app.use(express.json());

const productSchema = {
  name: v.string().min(3).max(100),
  price: v.number().min(0),
  category: v.string().custom(value =>
    ['electronics', 'books', 'clothing'].includes(value) ? null : 'Invalid category'
  )
};

app.post('/api/products', (req, res) => {
  const errors = Object.entries(productSchema)
    .map(([field, schema]) => ({ field, result: schema.validate(req.body[field]) }))
    .filter(({ result }) => !result.valid)
    .map(({ field, result }) => ({ field, message: result.errors[0].message }));

  if (errors.length > 0) {
    return res.status(400).json({ errors });
  }

  res.status(201).json(req.body);
});
Enter fullscreen mode Exit fullscreen mode

🎯 Best Practices

βœ… Schema Reuse – Define schemas once & share across frontend/backend

βœ… Type Safety – Leverage TypeScript’s inference capabilities

βœ… Performance Optimization – Cache schema instances for reuse

βœ… Error Handling – Always check .valid before using data


πŸ› οΈ Roadmap

πŸš€ Upcoming Features:

  • [ ] Array & Object Schema Support
  • [ ] Custom Error Message Templates
  • [ ] Async Validation
  • [ ] Integration with Popular Form Libraries
  • [ ] Schema Composition & Inheritance

πŸ“Œ Get Started with IsoValid

IsoValid is open-source and welcomes contributions! Try it today and share your feedback.

πŸ”— NPM Package: IsoValid on NPM

πŸ”— GitHub Repository: GitHub Repo

Let’s make data validation simpler together! πŸš€

TypeScript #NodeJS #Validation #Isomorphic #WebDevelopment #DataIntegrity

Top comments (0)