Custom Software Development

Introducing IsoValid: A Lightweight Isomorphic Data Validation Library

processor with isovalid written on it.
Isovalid architecture image
Isovalid architecture image

🚀 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 inferenceMinimal 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

🔹 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

Number Validation

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

Validation Results

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

🎯 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> ); }

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); });

🎯 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:

-

📌 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! 🚀