{"id":26040256,"url":"https://github.com/alok5953/isovalid","last_synced_at":"2026-04-06T02:33:12.696Z","repository":{"id":281039177,"uuid":"944003468","full_name":"alok5953/isovalid","owner":"alok5953","description":"A lightweight, isomorphic data validation library for TypeScript/JavaScript","archived":false,"fork":false,"pushed_at":"2025-03-10T14:21:34.000Z","size":69,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-01-03T14:30:39.947Z","etag":null,"topics":["backend","data-validation","express","form-validation","frontend","isomorphic","javascript","nextjs","nodejs","react","schema-validation","type-safety","typescript","validation","vue"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alok5953.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-03-06T16:14:10.000Z","updated_at":"2025-03-17T14:35:31.000Z","dependencies_parsed_at":"2025-03-06T17:33:49.577Z","dependency_job_id":"e0acaf61-a3e1-43f1-97f7-d8a825de83bb","html_url":"https://github.com/alok5953/isovalid","commit_stats":null,"previous_names":["alok5953/isovalid"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/alok5953/isovalid","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alok5953%2Fisovalid","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alok5953%2Fisovalid/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alok5953%2Fisovalid/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alok5953%2Fisovalid/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alok5953","download_url":"https://codeload.github.com/alok5953/isovalid/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alok5953%2Fisovalid/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31457703,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-05T21:22:52.476Z","status":"online","status_checked_at":"2026-04-06T02:00:07.287Z","response_time":112,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["backend","data-validation","express","form-validation","frontend","isomorphic","javascript","nextjs","nodejs","react","schema-validation","type-safety","typescript","validation","vue"],"created_at":"2025-03-07T12:08:50.406Z","updated_at":"2026-04-06T02:33:12.665Z","avatar_url":"https://github.com/alok5953.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# IsoValid\n\n[![npm version](https://badge.fury.io/js/%40alok5953%2Fisovalid.svg)](https://badge.fury.io/js/%40alok5953%2Fisovalid)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/)\n[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/alok5953/isovalid/blob/main/CONTRIBUTING.md)\n\nA lightweight, isomorphic data validation library for TypeScript and JavaScript that works seamlessly in both browser and Node.js environments. IsoValid is designed to provide a unified validation experience across your entire application stack.\n\n\u003e Created and maintained by [Alok Kaushik](https://github.com/alok5953) | [alokkaushik5953@gmail.com](mailto:alokkaushik5953@gmail.com)\n\n## Why IsoValid?\n\nIn modern web applications, data validation is crucial at multiple layers:\n- Client-side form validation for immediate user feedback\n- API request/response validation for data integrity\n- Server-side validation for security\n\nTraditionally, developers had to:\n1. Write separate validation logic for frontend and backend\n2. Maintain multiple validation libraries\n3. Deal with inconsistencies between environments\n\nIsoValid solves these problems by providing:\n- 🌐 **True Isomorphic Support** - The exact same validation code runs in both browser and Node.js\n- 🎯 **TypeScript-First Design** - Built from the ground up with TypeScript for excellent type inference\n- 🪶 **Minimal Bundle Size** - Core validation features without unnecessary bloat\n- 🔄 **Developer-Friendly API** - Intuitive, chainable interface for building schemas\n- ⚡ **High Performance** - Optimized validation with minimal overhead\n- 🎨 **Extensible Design** - Easy to add custom validators and error messages\n\n## Installation\n\n```bash\nnpm install isovalid\n```\n\n## Architecture\n\nIsoValid is built on a flexible, extensible architecture:\n\n### Core Components\n\n1. **Base Schema Class**\n   - Abstract foundation for all schema types\n   - Handles common validation logic\n   - Manages optional/nullable states\n\n2. **Type-Specific Schemas**\n   - StringSchema: String validation with length, pattern, format checks\n   - NumberSchema: Numeric validation with range, integer, sign checks\n   - More types coming soon (Boolean, Array, Object)\n\n3. **Validation Pipeline**\n   - Multi-stage validation process\n   - Custom validator support\n   - Detailed error reporting\n\n## API Reference\n\n### String Validation\n\n```typescript\nconst stringSchema = v.string()\n  .min(2)           // Minimum length\n  .max(50)          // Maximum length\n  .email()          // Email format\n  .matches(/regex/) // Custom regex pattern\n  .trimmed()        // Auto-trim whitespace\n  .setOptional()    // Allow undefined\n  .setNullable()    // Allow null\n  .custom(value =\u003e value.includes('@') ? null : 'Must include @'); // Custom validation\n```\n\n### Number Validation\n\n```typescript\nconst numberSchema = v.number()\n  .min(0)         // Minimum value\n  .max(100)       // Maximum value\n  .integer()      // Must be an integer\n  .positive()     // Must be \u003e 0\n  .setOptional()  // Allow undefined\n  .setNullable(); // Allow null\n```\n\n### Validation Results\n\nAll validations return a structured result:\n\n```typescript\ninterface ValidationResult {\n  valid: boolean;\n  errors: Array\u003c{\n    path: string[];\n    message: string;\n  }\u003e;\n}\n```\n\n## Real-World Examples\n\n### 1. React Form Validation\n\n```typescript\nimport { v } from 'isovalid';\nimport { useState, FormEvent } from 'react';\n\nconst userSchema = {\n  username: v.string().min(3).max(20),\n  email: v.string().email(),\n  age: v.number().integer().min(18)\n};\n\nfunction RegistrationForm() {\n  const [formData, setFormData] = useState({\n    username: '',\n    email: '',\n    age: ''\n  });\n  const [errors, setErrors] = useState\u003cRecord\u003cstring, string\u003e\u003e({});\n\n  const validateField = (field: keyof typeof userSchema, value: any) =\u003e {\n    const result = userSchema[field].validate(value);\n    return result.valid ? null : result.errors[0].message;\n  };\n\n  const handleSubmit = (e: FormEvent) =\u003e {\n    e.preventDefault();\n    const newErrors: Record\u003cstring, string\u003e = {};\n    \n    // Validate all fields\n    Object.entries(formData).forEach(([field, value]) =\u003e {\n      const error = validateField(field as keyof typeof userSchema, value);\n      if (error) newErrors[field] = error;\n    });\n\n    if (Object.keys(newErrors).length === 0) {\n      // Form is valid, submit data\n      console.log('Submitting:', formData);\n    } else {\n      setErrors(newErrors);\n    }\n  };\n\n  return (\n    \u003cform onSubmit={handleSubmit}\u003e\n      \u003cdiv\u003e\n        \u003cinput\n          type=\"text\"\n          value={formData.username}\n          onChange={e =\u003e setFormData(prev =\u003e ({ ...prev, username: e.target.value }))}\n          placeholder=\"Username\"\n        /\u003e\n        {errors.username \u0026\u0026 \u003cspan className=\"error\"\u003e{errors.username}\u003c/span\u003e}\n      \u003c/div\u003e\n      {/* Similar fields for email and age */}\n      \u003cbutton type=\"submit\"\u003eRegister\u003c/button\u003e\n    \u003c/form\u003e\n  );\n}\n```\n\n### 2. Express API Validation\n\n```typescript\nimport express from 'express';\nimport { v } from 'isovalid';\n\nconst app = express();\napp.use(express.json());\n\nconst productSchema = {\n  name: v.string().min(3).max(100),\n  price: v.number().min(0),\n  category: v.string().custom(value =\u003e\n    ['electronics', 'books', 'clothing'].includes(value)\n      ? null\n      : 'Invalid category'\n  )\n};\n\napp.post('/api/products', (req, res) =\u003e {\n  const errors = Object.entries(productSchema)\n    .map(([field, schema]) =\u003e ({\n      field,\n      result: schema.validate(req.body[field])\n    }))\n    .filter(({ result }) =\u003e !result.valid)\n    .map(({ field, result }) =\u003e ({\n      field,\n      message: result.errors[0].message\n    }));\n\n  if (errors.length \u003e 0) {\n    return res.status(400).json({ errors });\n  }\n\n  // Process valid product data\n  const product = req.body;\n  // Save to database, etc.\n  res.status(201).json(product);\n});\n```\n\n## Best Practices\n\n1. **Schema Reuse**\n   - Define schemas once and share between frontend and backend\n   - Keep schemas in a shared directory accessible to both environments\n\n2. **Type Safety**\n   - Leverage TypeScript's type inference with IsoValid\n   - Define interfaces that match your schemas\n\n3. **Performance**\n   - Create schemas outside request handlers\n   - Reuse schema instances when possible\n\n4. **Error Handling**\n   - Always check the `valid` property before accessing data\n   - Provide user-friendly error messages in custom validators\n\n## Contributing\n\nWe welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.\n\n1. Fork the repository\n2. Create your feature branch\n3. Write tests for your changes\n4. Submit a pull request\n\n## Testing\n\nIsoValid uses Jest for testing. Run the test suite:\n\n```bash\nnpm test\n```\n\nCurrent test coverage: \u003e88%\n\n## Roadmap\n\n- [ ] Array schema type\n- [ ] Object schema type with nested validation\n- [ ] Custom error message templates\n- [ ] Async validation support\n- [ ] Integration with popular form libraries\n- [ ] Schema composition and inheritance\n\n## License\n\nMIT © [IsoValid](LICENSE)\n\n## Support\n\n- GitHub Issues: Report bugs and feature requests\n- Documentation: Check our [Wiki](https://github.com/isovalid/isovalid/wiki)\n- Stack Overflow: Tag your questions with `isovalid`\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falok5953%2Fisovalid","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falok5953%2Fisovalid","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falok5953%2Fisovalid/lists"}