{"id":49601172,"url":"https://github.com/entropy-tamer/reynard-validation","last_synced_at":"2026-05-04T09:34:12.518Z","repository":{"id":319551476,"uuid":"1075215564","full_name":"entropy-tamer/reynard-validation","owner":"entropy-tamer","description":"Data validation and schema management for Reynard - comprehensive validation utilities with type safety","archived":false,"fork":false,"pushed_at":"2025-11-16T13:58:14.000Z","size":137,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-11-16T15:22:12.767Z","etag":null,"topics":["data-integrity","data-validation","error-handling","form-validation","frontend","input-validation","javascript","json-schema","reynard","runtime-validation","sanitization","schema","security","solidjs","type-safety","typescript","validation","web-development"],"latest_commit_sha":null,"homepage":"https://github.com/entropy-tamer/reynard-validation","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/entropy-tamer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"docs/security-validators.md","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-10-13T07:43:35.000Z","updated_at":"2025-11-16T13:58:18.000Z","dependencies_parsed_at":null,"dependency_job_id":"4f38a3cc-d555-4b85-a9b8-52f65363a20c","html_url":"https://github.com/entropy-tamer/reynard-validation","commit_stats":null,"previous_names":["entropy-tamer/reynard-validation"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/entropy-tamer/reynard-validation","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/entropy-tamer%2Freynard-validation","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/entropy-tamer%2Freynard-validation/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/entropy-tamer%2Freynard-validation/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/entropy-tamer%2Freynard-validation/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/entropy-tamer","download_url":"https://codeload.github.com/entropy-tamer/reynard-validation/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/entropy-tamer%2Freynard-validation/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32601598,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-03T22:12:39.696Z","status":"online","status_checked_at":"2026-05-04T02:00:06.625Z","response_time":58,"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":["data-integrity","data-validation","error-handling","form-validation","frontend","input-validation","javascript","json-schema","reynard","runtime-validation","sanitization","schema","security","solidjs","type-safety","typescript","validation","web-development"],"created_at":"2026-05-04T09:34:08.339Z","updated_at":"2026-05-04T09:34:12.509Z","avatar_url":"https://github.com/entropy-tamer.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Reynard Validation\n\nValidation utilities for the Reynard framework.\n\n## Overview\n\nThe `reynard-validation` package provides a comprehensive, unified validation system for the entire Reynard ecosystem. It consolidates all validation logic from across the ecosystem into a single, consistent, and powerful validation system with full TypeScript support, comprehensive error handling, and advanced features like JSON remediation.\n\n## Features\n\n- **Unified API**: Single validation system across all Reynard packages\n- **Type Safety**: Full TypeScript support with comprehensive type definitions\n- **Extensible**: Easy to add custom validators and schemas\n- **Performance**: Optimized validation engine with minimal overhead (O(1) for basic validations, O(n) for complex schemas)\n- **Security**: Built-in security validation for URLs, passwords, and file uploads\n  - **Contagious Interview Attack Detection**: Automatically detects base64-encoded JSON storage URLs used for malware delivery\n  - **Config File Security Validation**: Scans config files for malicious patterns\n  - **Known IOC Detection**: Identifies known malicious indicators from threat intelligence\n- **Flexible**: Support for both simple and complex validation scenarios\n- **JSON Remediation**: Advanced JSON syntax fixing and package.json validation\n- **Comprehensive Validators**: 20+ built-in validators for common use cases\n- **Schema System**: Flexible validation schemas with custom rules and error messages\n- **Error Handling**: Detailed validation errors with context information\n\n## Installation\n\n```bash\npnpm add reynard-validation\n```\n\n## Quick Start\n\n### Basic Validation\n\n```typescript\nimport { validateEmail, validatePassword, validateUsername } from \"reynard-validation\";\n\n// Simple validation\nconst emailResult = validateEmail(\"user@example.com\");\nconsole.log(emailResult.isValid); // true\n\nconst passwordResult = validatePassword(\"weak\");\nconsole.log(passwordResult.isValid); // false\nconsole.log(passwordResult.error); // \"Password must be 8-128 characters...\"\n\n// With custom field names\nconst usernameResult = validateUsername(\"john_doe\", \"displayName\");\n```\n\n### Schema-Based Validation\n\n```typescript\nimport { ValidationUtils, CommonSchemas } from \"reynard-validation\";\n\n// Using predefined schemas\nconst result = ValidationUtils.validateValue(\"user@example.com\", CommonSchemas.email, { fieldName: \"email\" });\n\n// Custom schema\nconst customSchema = {\n  type: \"string\" as const,\n  required: true,\n  minLength: 5,\n  maxLength: 50,\n  pattern: /^[a-zA-Z0-9_]+$/,\n  errorMessage: \"Username must be 5-50 alphanumeric characters\",\n};\n\nconst customResult = ValidationUtils.validateValue(\"john_doe\", customSchema, { fieldName: \"username\" });\n```\n\n### Form Validation\n\n```typescript\nimport { ValidationUtils, FormSchemas } from \"reynard-validation\";\n\nconst formData = {\n  email: \"user@example.com\",\n  username: \"john_doe\",\n  password: \"SecurePass123!\",\n};\n\nconst result = ValidationUtils.validateFields(formData, FormSchemas.registration);\n\nconsole.log(result.isValid); // true\nconsole.log(result.results); // { email: {...}, username: {...}, password: {...} }\nconsole.log(result.errors); // [] (empty if all valid)\n```\n\n## JSON Remediation\n\nThe `reynard-validation` package includes powerful JSON remediation tools for fixing common JSON syntax errors, particularly useful for maintaining clean `package.json` files across large monorepos.\n\n### Quick Start - JSON Remediation\n\n```typescript\nimport { JsonRemediatorFinal } from \"reynard-validation\";\n\n// Create a remediator instance\nconst remediator = new JsonRemediatorFinal();\n\n// Fix a malformed JSON string\nconst malformedJson = '{\"name\": \"test\" \"version\": \"1.0.0\"}';\nconst result = remediator.remediate(malformedJson);\n\nconsole.log(result.isValid); // true\nconsole.log(result.fixedJson); // '{\"name\": \"test\", \"version\": \"1.0.0\"}'\nconsole.log(result.errors); // Array of fixed errors\n```\n\n### CLI Usage\n\nThe package provides convenient CLI commands for JSON remediation:\n\n```bash\n# Check JSON files for syntax errors\npnpm json:check\n\n# Fix a specific JSON file\npnpm json:fix path/to/file.json\n\n# Fix all package.json files in the monorepo\npnpm json:fix-all\n```\n\n**See [JSON Remediation Documentation](./docs/json-remediation.md)** for comprehensive documentation including:\n\n- Complete API reference for `JsonRemediator` and `JsonRemediatorFinal` classes\n- Utility functions: `fixJsonSyntax`, `fixPackageJson`\n- All supported error types and fixes\n- CLI usage and integration examples\n- Error handling and troubleshooting\n\n## API Reference\n\n### Core Classes\n\n#### `ValidationUtils`\n\nThe main validation engine class.\n\n```typescript\nclass ValidationUtils {\n  static validateValue(value: unknown, schema: ValidationSchema, options?: FieldValidationOptions): ValidationResult;\n\n  static validateFields(\n    data: Record\u003cstring, unknown\u003e,\n    schemas: Record\u003cstring, ValidationSchema\u003e,\n    options?: { strict?: boolean }\n  ): MultiValidationResult;\n\n  static validateOrThrow(value: unknown, schema: ValidationSchema, options?: FieldValidationOptions): void;\n}\n```\n\n#### `JsonRemediatorFinal`\n\nThe production-ready JSON remediation class for fixing JSON syntax errors.\n\n```typescript\nclass JsonRemediatorFinal {\n  remediate(jsonString: string): JsonRemediationResult;\n  remediatePackageJson(packageJsonContent: string): JsonRemediationResult;\n}\n```\n\n#### `JsonRemediator`\n\nThe comprehensive JSON remediation class with detailed error tracking.\n\n```typescript\nclass JsonRemediator {\n  remediate(jsonString: string): JsonRemediationResult;\n  remediatePackageJson(packageJsonContent: string): JsonRemediationResult;\n}\n```\n\n### Types\n\n#### `ValidationResult`\n\n```typescript\ntype ValidationResult = {\n  isValid: boolean;\n  error?: string;\n  field?: string;\n  value?: unknown;\n  errors?: string[];\n};\n```\n\n#### `ValidationSchema`\n\n```typescript\ntype ValidationSchema = {\n  type: \"string\" | \"number\" | \"email\" | \"url\" | \"password\" | ...;\n  required?: boolean;\n  minLength?: number;\n  maxLength?: number;\n  min?: number;\n  max?: number;\n  pattern?: RegExp;\n  enum?: unknown[];\n  errorMessage?: string;\n  customValidator?: (value: unknown) =\u003e ValidationResult;\n};\n```\n\n#### `JsonRemediationResult`\n\n```typescript\ntype JsonRemediationResult = {\n  isValid: boolean;\n  fixedJson: string;\n  errors: JsonSyntaxError[];\n  unfixableErrors: string[];\n};\n```\n\n#### `JsonSyntaxError`\n\n```typescript\ntype JsonSyntaxError = {\n  type:\n    | \"missing-comma\"\n    | \"trailing-comma\"\n    | \"missing-quote\"\n    | \"invalid-escape\"\n    | \"malformed-object\"\n    | \"malformed-array\";\n  line: number;\n  column: number;\n  description: string;\n  fix: string;\n};\n```\n\n#### `MultiValidationResult`\n\nResult of validating multiple fields with individual and aggregate results.\n\n```typescript\ntype MultiValidationResult = {\n  isValid: boolean;\n  results: Record\u003cstring, ValidationResult\u003e;\n  errors: string[];\n};\n```\n\n### Predefined Schemas\n\n#### `CommonSchemas`\n\nPredefined schemas for common validation patterns:\n\n- `email` - Email address validation\n- `password` - Password strength validation\n- `username` - Username format validation\n- `url` - URL format validation\n- `apiKey` - API key format validation\n- `token` - Authentication token validation\n- `filename` - Filename validation\n- `mimeType` - MIME type validation\n- `port` - Port number validation\n- `timeout` - Timeout value validation\n- `modelName` - AI model name validation\n- `prompt` - AI prompt validation\n- `temperature` - AI temperature parameter validation\n- `maxTokens` - AI max tokens parameter validation\n- `theme` - UI theme validation\n- `language` - Language code validation\n- `color` - Color value validation\n\n#### `FormSchemas`\n\nPredefined form validation schemas:\n\n- `login` - Login form validation\n- `registration` - Registration form validation\n- `profile` - Profile form validation\n- `settings` - Settings form validation\n- `api` - API configuration validation\n- `file` - File upload validation\n- `network` - Network configuration validation\n\n### Validation Functions\n\n#### Basic Validators\n\n```typescript\nvalidateEmail(email: string, fieldName?: string): ValidationResult\nvalidatePassword(password: string, fieldName?: string): ValidationResult\nvalidateUsername(username: string, fieldName?: string): ValidationResult\nvalidateUrl(url: string, fieldName?: string): ValidationResult\n```\n\n#### API Validators\n\n```typescript\nvalidateApiKey(apiKey: string, fieldName?: string): ValidationResult\nvalidateToken(token: string, fieldName?: string): ValidationResult\n```\n\n#### File Validators\n\n```typescript\nvalidateFileName(fileName: string, fieldName?: string): ValidationResult\nvalidateMimeType(mimeType: string, fieldName?: string): ValidationResult\nvalidateFileSize(fileSize: number, fieldName?: string, maxSize?: number): ValidationResult\n```\n\n**Note**: `validateFileSize` accepts file size in bytes, with a default maximum of 100MB.\n\n#### AI/ML Validators\n\n```typescript\nvalidateModelName(modelName: string, fieldName?: string): ValidationResult\nvalidatePrompt(prompt: string, fieldName?: string): ValidationResult\nvalidateTemperature(temperature: number, fieldName?: string): ValidationResult\nvalidateMaxTokens(maxTokens: number, fieldName?: string): ValidationResult\n```\n\n#### UI/UX Validators\n\n```typescript\nvalidateTheme(theme: string, fieldName?: string): ValidationResult\nvalidateLanguage(language: string, fieldName?: string): ValidationResult\nvalidateColor(color: string, fieldName?: string): ValidationResult\n```\n\n#### Utility Validators\n\n```typescript\nvalidateNotEmpty(value: unknown, fieldName?: string): ValidationResult\nvalidatePositive(value: number, fieldName?: string): ValidationResult\nvalidateRange(value: number, min: number, max: number, fieldName?: string): ValidationResult\n```\n\n#### Advanced Validators\n\n```typescript\nvalidatePasswordStrength(\n  password: string,\n  rules?: ValidationRules\n): PasswordStrength\n\nvalidateUrlSecurity(url: string): { isValid: boolean; sanitized?: string }\n```\n\n## Advanced Usage\n\n### Custom Validators\n\n```typescript\nimport { createCustomSchema, ValidationUtils } from \"reynard-validation\";\n\nconst customValidator = createCustomSchema(\n  value =\u003e {\n    if (typeof value !== \"string\") {\n      return { isValid: false, error: \"Must be a string\" };\n    }\n\n    if (value.length \u003c 10) {\n      return { isValid: false, error: \"Must be at least 10 characters\" };\n    }\n\n    return { isValid: true };\n  },\n  { errorMessage: \"Custom validation failed\" }\n);\n\nconst result = ValidationUtils.validateValue(\"short\", customValidator);\n```\n\n### Schema Builders\n\n```typescript\nimport { createStringSchema, createNumberSchema, createEnumSchema } from \"reynard-validation\";\n\nconst stringSchema = createStringSchema({\n  required: true,\n  minLength: 5,\n  maxLength: 50,\n  pattern: /^[a-zA-Z0-9_]+$/,\n  errorMessage: \"Must be 5-50 alphanumeric characters\",\n});\n\nconst numberSchema = createNumberSchema({\n  required: true,\n  min: 0,\n  max: 100,\n  errorMessage: \"Must be between 0 and 100\",\n});\n\nconst enumSchema = createEnumSchema([\"light\", \"dark\", \"auto\"], { errorMessage: \"Must be light, dark, or auto\" });\n```\n\n### Error Handling\n\n```typescript\nimport { ValidationError, ValidationUtils } from \"reynard-validation\";\n\ntry {\n  const result = ValidationUtils.validateValue(\"invalid\", CommonSchemas.email, {\n    fieldName: \"email\",\n    context: { field: \"email\", value: \"invalid\", constraint: \"email\" },\n    strict: true,\n  });\n} catch (error) {\n  if (error instanceof ValidationError) {\n    console.log(error.field); // \"email\"\n    console.log(error.value); // \"invalid\"\n    console.log(error.constraint); // \"email\"\n    console.log(error.context); // Full context object\n  }\n}\n```\n\n## Migration Guide\n\n### From `reynard-core` validation\n\n```typescript\n// Old\nimport { isValidUsername, isValidEmail } from \"reynard-core\";\n\n// New\nimport { validateUsername, validateEmail } from \"reynard-validation\";\n\n// Old usage\nconst isValid = isValidUsername(\"john_doe\");\n\n// New usage\nconst result = validateUsername(\"john_doe\");\nconst isValid = result.isValid;\n```\n\n### From `reynard-connection` validation\n\n```typescript\n// Old\nimport { ValidationUtils as ConnectionValidationUtils } from \"reynard-connection\";\n\n// New\nimport { ValidationUtils } from \"reynard-validation\";\n\n// API is the same, just import from the new package\n```\n\n### From `reynard-auth` validation\n\n```typescript\n// Old\nimport { validatePassword, validateEmail } from \"reynard-auth\";\n\n// New\nimport { validatePassword, validateEmail } from \"reynard-validation\";\n\n// API is compatible, just update imports\n```\n\n## Performance Considerations\n\n- **Lazy Evaluation**: Validation only runs when needed\n- **Early Returns**: Validation stops on first error by default\n- **Optimized Regex**: All patterns are pre-compiled for performance\n- **Minimal Allocations**: Reuses objects where possible\n- **Tree Shaking**: Only imports what you use\n\n## Security Features\n\n- **URL Security**: Validates URLs for security threats\n- **Password Strength**: Comprehensive password strength analysis\n- **File Validation**: Secure filename and MIME type validation\n- **Input Sanitization**: Built-in input sanitization for common attack vectors\n- **XSS Prevention**: Validates against common XSS patterns\n- **Contagious Interview Attack Detection**: Automatically detects base64-encoded JSON storage URLs used for malware delivery\n  - Detects malicious patterns in config files\n  - Identifies known IOCs from threat intelligence\n  - Validates against known malicious JSON storage services\n\n### Security Validators\n\nThe validation package includes specialized security validators to detect the **Contagious Interview** campaign attack vector:\n\n```typescript\nimport { SecurityValidators, ValidationUtils } from 'reynard-validation';\n\n// Automatic detection (enabled by default)\nconst result = ValidationUtils.validateValue(\n  'aHR0cHM6Ly9qc29ua2VlcGVyLmNvbS9iL0dOT1g0',\n  { type: 'string' },\n  { fieldName: 'API_KEY' }\n);\n// Automatically detects base64-encoded JSON storage URL\n\n// Config file validation\nconst configContent = 'API_KEY=aHR0cHM6Ly9qc29ua2VlcGVyLmNvbS9iL0dOT1g0\\n';\nconst securityCheck = ValidationUtils.validateConfigFileSecurity(configContent, {\n  strict: true  // Fail on any threat\n});\n```\n\n**See:** [Security Validators Documentation](./docs/security-validators.md)\n\n## Testing\n\n```typescript\nimport { describe, it, expect } from \"vitest\";\nimport { validateEmail, validatePassword } from \"reynard-validation\";\n\ndescribe(\"Validation\", () =\u003e {\n  it(\"should validate email addresses\", () =\u003e {\n    expect(validateEmail(\"user@example.com\").isValid).toBe(true);\n    expect(validateEmail(\"invalid\").isValid).toBe(false);\n  });\n\n  it(\"should validate passwords\", () =\u003e {\n    expect(validatePassword(\"SecurePass123!\").isValid).toBe(true);\n    expect(validatePassword(\"weak\").isValid).toBe(false);\n  });\n});\n```\n\n## Contributing\n\nWhen adding new validators:\n\n1. Add the validator function to `src/utils.ts`\n2. Add the schema to `src/schemas.ts` if it's a common pattern\n3. Export from `src/index.ts`\n4. Add tests in `src/__tests__/`\n5. Update this README\n\n## Additional Documentation\n\nComprehensive documentation is available in the [`docs/`](./docs/) directory:\n\n### Core Documentation\n\n- **[Core Validation Engine](./docs/core-validation.md)**: The central `ValidationUtils` class and core validation methods\n  - `validateValue()` - Single value validation\n  - `validateFields()` - Multi-field validation\n  - `validateOrThrow()` - Exception-based validation\n  - `validateConfigFileSecurity()` - Security validation\n\n### Validation Tools\n\n- **[Utility Validators](./docs/utility-validators.md)**: Standalone validation functions for common use cases\n  - Basic, API, File, Configuration, AI/ML, UI/UX, and Advanced validators\n  - Complete API reference with examples for all 20+ validators\n\n- **[Validator Classes](./docs/validator-classes.md)**: Internal validator classes for specialized validation\n  - `StringValidators`, `NumberValidators`, `ArrayValidators`\n  - Direct usage examples and integration patterns\n\n### Schema System\n\n- **[Schema System](./docs/schema-system.md)**: Pre-built schemas and schema builders\n  - `CommonSchemas` - 20+ predefined field validation schemas\n  - `FormSchemas` - Complete form validation schemas\n  - Schema builders for creating custom validation schemas\n\n### Specialized Features\n\n- **[JSON Remediation](./docs/json-remediation.md)**: JSON syntax fixing and package.json validation\n  - `JsonRemediator` and `JsonRemediatorFinal` classes\n  - Utility functions: `fixJsonSyntax`, `fixPackageJson`\n  - CLI usage and integration examples\n  - Error types and handling\n\n- **[Security Validators](./docs/security-validators.md)**: Security validation for detecting malicious patterns\n  - Contagious Interview attack detection\n  - Base64-encoded JSON storage URL detection\n  - Config file security validation\n  - Known IOC detection\n\n### Documentation Index\n\n- **[Documentation Index](./docs/README.md)**: Complete documentation index and navigation guide\n\n## Version\n\nCurrent version: **1.0.0**\n\n## Support\n\nFor issues, questions, or contributions, please visit the [Reynard repository](https://github.com/reynard/reynard).\n\n## License\n\nMIT License - see LICENSE file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fentropy-tamer%2Freynard-validation","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fentropy-tamer%2Freynard-validation","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fentropy-tamer%2Freynard-validation/lists"}