{"_id":"@c-a-f/validation","_rev":"2-39f130a0eaf7799e0675a5183a1c8d84","name":"@c-a-f/validation","dist-tags":{"latest":"1.0.4"},"versions":{"1.0.3":{"name":"@c-a-f/validation","version":"1.0.3","keywords":["clean-architecture-frontend","clean-architecture","caf","validation","schema","zod","yup","joi","class-validator"],"author":{"name":"ali aslani","email":"aliaslani.mm@gmail.com"},"license":"MIT","_id":"@c-a-f/validation@1.0.3","maintainers":[{"name":"ialiaslani","email":"aliaslani.mm@gmail.com"}],"homepage":"https://github.com/ialiaslani/caf#readme","bugs":{"url":"https://github.com/ialiaslani/caf/issues"},"dist":{"shasum":"ad66c7eb3d8d25e3e470e3137406a5dd19f9a7cc","tarball":"https://registry.npmjs.org/@c-a-f/validation/-/validation-1.0.3.tgz","fileCount":28,"integrity":"sha512-GWv/8N9JgvFLp/3oe1SREQywYigp9o9Fb8lEolRdaBnOH9CYhZbGrBLsCk50rZp5aluniHIa/kPdQfcsDC/64Q==","signatures":[{"sig":"MEUCIQCoGKxrOiXwAeXZyRkeXrWEETArZnyM5EYCl7OMtraYRgIgOfngRUprHhjrFVae9PcpEFDkNN2/z5ic/ETyOYsmVUs=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":34106},"main":"./.build/src/index.js","type":"module","types":"./.build/src/index.d.ts","module":"./.build/src/index.js","exports":{".":{"node":"./.build/src/index.js","types":"./.build/src/index.d.ts","import":"./.build/src/index.js","default":"./.build/src/index.js"},"./joi":{"node":"./.build/src/adapters/JoiAdapter.js","types":"./.build/src/adapters/JoiAdapter.d.ts","import":"./.build/src/adapters/JoiAdapter.js","default":"./.build/src/adapters/JoiAdapter.js"},"./yup":{"node":"./.build/src/adapters/yup.js","types":"./.build/src/adapters/yup.d.ts","import":"./.build/src/adapters/yup.js","default":"./.build/src/adapters/yup.js"},"./zod":{"node":"./.build/src/adapters/zod.js","types":"./.build/src/adapters/zod.d.ts","import":"./.build/src/adapters/zod.js","default":"./.build/src/adapters/zod.js"},"./class-validator":{"node":"./.build/src/adapters/ClassValidatorAdapter.js","types":"./.build/src/adapters/ClassValidatorAdapter.d.ts","import":"./.build/src/adapters/ClassValidatorAdapter.js","default":"./.build/src/adapters/ClassValidatorAdapter.js"}},"gitHead":"ca2feba4757534a4a130717ea50c4df2e2ff01e6","scripts":{"test":"vitest run","build":"tsc --build","start":"tsc --watch","test:watch":"vitest","prepublishOnly":"npm run build"},"_npmUser":{"name":"ialiaslani","email":"aliaslani.mm@gmail.com"},"repository":{"url":"git+https://github.com/ialiaslani/caf.git","type":"git"},"_npmVersion":"10.9.2","description":"Schema-agnostic validation interfaces and runner for CAF. Works with Zod, Yup, Joi, class-validator, or any validation library.","directories":{},"_nodeVersion":"22.13.0","dependencies":{"@c-a-f/core":"^1.0.3"},"_hasShrinkwrap":false,"devDependencies":{"joi":"^17.13.0","yup":"^1.4.0","zod":"^3.22.4","vitest":"^2.1.0","class-validator":"^0.14.1","reflect-metadata":"^0.2.2"},"peerDependencies":{"joi":"*","yup":"*","zod":"*","class-validator":"*"},"peerDependenciesMeta":{"joi":{"optional":true},"yup":{"optional":true},"zod":{"optional":true},"class-validator":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/validation_1.0.3_1771671235065_0.1813585338805348","host":"s3://npm-registry-packages-npm-production"}},"1.0.4":{"name":"@c-a-f/validation","type":"module","version":"1.0.4","description":"Schema-agnostic validation interfaces and runner for CAF. Works with Zod, Yup, Joi, class-validator, or any validation library.","keywords":["clean-architecture-frontend","clean-architecture","caf","validation","schema","zod","yup","joi","class-validator"],"author":{"name":"ali aslani","email":"aliaslani.mm@gmail.com"},"license":"MIT","homepage":"https://docs-caf.vercel.app/docs/packages/validation","repository":{"type":"git","url":"git+https://github.com/ialiaslani/caf.git"},"main":"./.build/src/index.js","module":"./.build/src/index.js","types":"./.build/src/index.d.ts","exports":{".":{"types":"./.build/src/index.d.ts","import":"./.build/src/index.js","node":"./.build/src/index.js","default":"./.build/src/index.js"},"./zod":{"types":"./.build/src/adapters/zod.d.ts","import":"./.build/src/adapters/zod.js","node":"./.build/src/adapters/zod.js","default":"./.build/src/adapters/zod.js"},"./yup":{"types":"./.build/src/adapters/yup.d.ts","import":"./.build/src/adapters/yup.js","node":"./.build/src/adapters/yup.js","default":"./.build/src/adapters/yup.js"},"./joi":{"types":"./.build/src/adapters/JoiAdapter.d.ts","import":"./.build/src/adapters/JoiAdapter.js","node":"./.build/src/adapters/JoiAdapter.js","default":"./.build/src/adapters/JoiAdapter.js"},"./class-validator":{"types":"./.build/src/adapters/ClassValidatorAdapter.d.ts","import":"./.build/src/adapters/ClassValidatorAdapter.js","node":"./.build/src/adapters/ClassValidatorAdapter.js","default":"./.build/src/adapters/ClassValidatorAdapter.js"}},"scripts":{"build":"tsc --build","start":"tsc --watch","prepublishOnly":"npm run build","test":"vitest run","test:watch":"vitest"},"dependencies":{"@c-a-f/core":"^1.0.3"},"devDependencies":{"vitest":"^2.1.0","zod":"^3.22.4","yup":"^1.4.0","joi":"^17.13.0","class-validator":"^0.14.1","reflect-metadata":"^0.2.2"},"peerDependencies":{"zod":"*","yup":"*","joi":"*","class-validator":"*"},"peerDependenciesMeta":{"zod":{"optional":true},"yup":{"optional":true},"joi":{"optional":true},"class-validator":{"optional":true}},"_id":"@c-a-f/validation@1.0.4","gitHead":"c754b6d68b1a5b1196bb202e70c962ea7c3de87e","bugs":{"url":"https://github.com/ialiaslani/caf/issues"},"_nodeVersion":"22.13.0","_npmVersion":"10.9.2","dist":{"integrity":"sha512-yIqQGfYsfykecPHd6vFU1osm4ChWzONAUkrTAiGE5l1xO1uuL0ye4zYJkW2UWHVTdU1Ngx2bAv1DQFy8510wpQ==","shasum":"8fee64e18f1a9778d248d1a3a013b6ded8912bdd","tarball":"https://registry.npmjs.org/@c-a-f/validation/-/validation-1.0.4.tgz","fileCount":28,"unpackedSize":34278,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIG50gzEtOA/yVCNgKHcwIyYhE9c5m6mjiKlBKJnd15AcAiEAlJx6Ul3fO2/ZVGQkPalETT4k691AZ1L595oX3Fqvemk="}]},"_npmUser":{"name":"ialiaslani","email":"aliaslani.mm@gmail.com"},"directories":{},"maintainers":[{"name":"ialiaslani","email":"aliaslani.mm@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/validation_1.0.4_1771680075054_0.16549418153272932"},"_hasShrinkwrap":false}},"time":{"created":"2026-02-21T10:53:54.968Z","modified":"2026-02-21T13:21:15.319Z","1.0.3":"2026-02-21T10:53:55.223Z","1.0.4":"2026-02-21T13:21:15.194Z"},"bugs":{"url":"https://github.com/ialiaslani/caf/issues"},"author":{"name":"ali aslani","email":"aliaslani.mm@gmail.com"},"license":"MIT","homepage":"https://docs-caf.vercel.app/docs/packages/validation","keywords":["clean-architecture-frontend","clean-architecture","caf","validation","schema","zod","yup","joi","class-validator"],"repository":{"type":"git","url":"git+https://github.com/ialiaslani/caf.git"},"description":"Schema-agnostic validation interfaces and runner for CAF. Works with Zod, Yup, Joi, class-validator, or any validation library.","maintainers":[{"name":"ialiaslani","email":"aliaslani.mm@gmail.com"}],"readme":"# @c-a-f/validation\r\n\r\nSchema-agnostic validation interfaces and runner for CAF. Works with Zod, Yup, Joi, class-validator, or any validation library.\r\n\r\n**Documentation:** [@c-a-f/validation docs](https://docs-caf.vercel.app/docs/packages/validation)\r\n\r\n## Installation\r\n\r\n```bash\r\nnpm install @c-a-f/validation\r\n```\r\n\r\nFor Zod integration:\r\n```bash\r\nnpm install @c-a-f/validation zod\r\n```\r\n\r\nFor Yup integration:\r\n```bash\r\nnpm install @c-a-f/validation yup\r\n```\r\n\r\nFor Joi integration:\r\n```bash\r\nnpm install @c-a-f/validation joi\r\n```\r\n\r\nFor class-validator integration:\r\n```bash\r\nnpm install @c-a-f/validation class-validator\r\n```\r\n\r\n## Usage\r\n\r\n### Core Interfaces\r\n\r\nThe package provides schema-agnostic interfaces that work with any validation library:\r\n\r\n```typescript\r\nimport { IValidator, ValidationResult, ValidationError } from '@c-a-f/validation';\r\n\r\n// IValidator interface can be implemented by any validation library adapter\r\ninterface IValidator<T> {\r\n  validate(data: unknown): ValidationResult | Promise<ValidationResult>;\r\n  parse(data: unknown): T | Promise<T>;\r\n  isValid(data: unknown): boolean | Promise<boolean>;\r\n}\r\n```\r\n\r\n### Validation Runner\r\n\r\nUse `ValidationRunner` to execute validations and format errors:\r\n\r\n```typescript\r\nimport { ValidationRunner, IValidator } from '@c-a-f/validation';\r\n\r\n// Run a single validation\r\nconst result = await ValidationRunner.run(validator, data);\r\n\r\n// Run multiple validations and aggregate results\r\nconst results = await ValidationRunner.runAll([\r\n  { validator: emailValidator, data: email },\r\n  { validator: passwordValidator, data: password },\r\n]);\r\n\r\n// Run and throw on failure\r\nconst validatedData = await ValidationRunner.runOrThrow(validator, data);\r\n\r\n// Format errors\r\nconst errorMessages = ValidationRunner.formatErrors(result.errors);\r\nconst errorRecord = ValidationRunner.formatErrorsAsRecord(result.errors);\r\n```\r\n\r\n## Integration with Zod\r\n\r\n```typescript\r\nimport { z } from 'zod';\r\nimport { ZodValidator } from '@c-a-f/validation/zod';\r\nimport { ValidationRunner } from '@c-a-f/validation';\r\n\r\n// Define Zod schema\r\nconst userSchema = z.object({\r\n  email: z.string().email(),\r\n  age: z.number().min(18),\r\n  name: z.string().min(1),\r\n});\r\n\r\n// Create validator\r\nconst validator = new ZodValidator(userSchema);\r\n\r\n// Validate data\r\nconst result = await validator.validate({\r\n  email: 'user@example.com',\r\n  age: 25,\r\n  name: 'John',\r\n});\r\n\r\nif (result.success) {\r\n  console.log('Valid data:', result.data);\r\n} else {\r\n  console.log('Errors:', ValidationRunner.formatErrors(result.errors));\r\n}\r\n\r\n// Or use parse to throw on error\r\ntry {\r\n  const validated = await validator.parse(data);\r\n  console.log('Validated:', validated);\r\n} catch (error) {\r\n  console.error('Validation failed:', error);\r\n}\r\n```\r\n\r\n## Integration with Yup\r\n\r\n```typescript\r\nimport * as yup from 'yup';\r\nimport { YupValidator } from '@c-a-f/validation/yup';\r\nimport { ValidationRunner } from '@c-a-f/validation';\r\n\r\n// Define Yup schema\r\nconst userSchema = yup.object({\r\n  email: yup.string().email().required(),\r\n  age: yup.number().min(18).required(),\r\n  name: yup.string().min(1).required(),\r\n});\r\n\r\n// Create validator\r\nconst validator = new YupValidator(userSchema);\r\n\r\n// Validate data\r\nconst result = await validator.validate({\r\n  email: 'user@example.com',\r\n  age: 25,\r\n  name: 'John',\r\n});\r\n\r\nif (result.success) {\r\n  console.log('Valid data:', result.data);\r\n} else {\r\n  console.log('Errors:', ValidationRunner.formatErrors(result.errors));\r\n}\r\n```\r\n\r\n## Integration with Joi\r\n\r\n```typescript\r\nimport Joi from 'joi';\r\nimport { JoiValidator } from '@c-a-f/validation/joi';\r\nimport { ValidationRunner } from '@c-a-f/validation';\r\n\r\n// Define Joi schema\r\nconst userSchema = Joi.object({\r\n  email: Joi.string().email().required(),\r\n  age: Joi.number().min(18).required(),\r\n  name: Joi.string().min(1).required(),\r\n});\r\n\r\n// Create validator\r\nconst validator = new JoiValidator(userSchema);\r\n\r\n// Validate data\r\nconst result = await validator.validate({\r\n  email: 'user@example.com',\r\n  age: 25,\r\n  name: 'John',\r\n});\r\n\r\nif (result.success) {\r\n  console.log('Valid data:', result.data);\r\n} else {\r\n  console.log('Errors:', ValidationRunner.formatErrors(result.errors));\r\n}\r\n\r\n// Or use parse to throw on error\r\ntry {\r\n  const validated = await validator.parse(data);\r\n  console.log('Validated:', validated);\r\n} catch (error) {\r\n  console.error('Validation failed:', error);\r\n}\r\n```\r\n\r\n## Integration with class-validator\r\n\r\n```typescript\r\nimport { validate, IsString, IsEmail, IsNumber, Min } from 'class-validator';\r\nimport { ClassValidatorAdapter, createClassValidator } from '@c-a-f/validation/class-validator';\r\nimport { ValidationRunner } from '@c-a-f/validation';\r\n\r\n// Define DTO class with decorators\r\nclass UserDto {\r\n  @IsString()\r\n  @IsEmail()\r\n  email!: string;\r\n\r\n  @IsNumber()\r\n  @Min(18)\r\n  age!: number;\r\n\r\n  @IsString()\r\n  name!: string;\r\n}\r\n\r\n// Create validator using factory function (recommended)\r\nconst validator = createClassValidator(UserDto, validate);\r\n\r\n// Or create directly\r\n// const validator = new ClassValidatorAdapter(UserDto, validate);\r\n\r\n// Validate data\r\nconst result = await validator.validate({\r\n  email: 'user@example.com',\r\n  age: 25,\r\n  name: 'John',\r\n});\r\n\r\nif (result.success) {\r\n  console.log('Valid data:', result.data);\r\n} else {\r\n  console.log('Errors:', ValidationRunner.formatErrors(result.errors));\r\n}\r\n\r\n// Or use parse to throw on error\r\ntry {\r\n  const validated = await validator.parse(data);\r\n  console.log('Validated:', validated);\r\n} catch (error) {\r\n  console.error('Validation failed:', error);\r\n}\r\n```\r\n\r\n## Custom Validator Implementation\r\n\r\nYou can implement `IValidator` for any validation library:\r\n\r\n```typescript\r\nimport { IValidator, ValidationResult, ValidationError } from '@c-a-f/validation';\r\n\r\nclass CustomValidator<T> implements IValidator<T> {\r\n  constructor(private validateFn: (data: unknown) => boolean) {}\r\n\r\n  async validate(data: unknown): Promise<ValidationResult> {\r\n    const isValid = this.validateFn(data);\r\n    return {\r\n      success: isValid,\r\n      errors: isValid ? [] : [{ path: '', message: 'Validation failed' }],\r\n      data: isValid ? (data as T) : undefined,\r\n    };\r\n  }\r\n\r\n  async parse(data: unknown): Promise<T> {\r\n    const result = await this.validate(data);\r\n    if (!result.success) {\r\n      throw new Error('Validation failed');\r\n    }\r\n    return result.data as T;\r\n  }\r\n\r\n  async isValid(data: unknown): Promise<boolean> {\r\n    return this.validateFn(data);\r\n  }\r\n}\r\n```\r\n\r\n## Exports\r\n\r\n- `IValidator` — Interface for validation implementations\r\n- `ValidationResult` — Result type with success status and errors\r\n- `ValidationError` — Error type with path and message\r\n- `ValidationRunner` — Utility class for running validations\r\n- `ValidationErrorException` — Exception thrown on validation failure\r\n- `ZodValidator` — Adapter for Zod schemas (from `@c-a-f/validation/zod`)\r\n- `YupValidator` — Adapter for Yup schemas (from `@c-a-f/validation/yup`)\r\n- `JoiValidator` — Adapter for Joi schemas (from `@c-a-f/validation/joi`)\r\n- `ClassValidatorAdapter` — Adapter for class-validator (from `@c-a-f/validation/class-validator`)\r\n- `createClassValidator` — Factory function for creating class-validator adapters\r\n\r\n## Dependencies\r\n\r\n- `@c-a-f/core` — Core primitives\r\n\r\n## Peer Dependencies (Optional)\r\n\r\n- `zod` — For Zod integration\r\n- `yup` — For Yup integration\r\n- `joi` — For Joi integration\r\n- `class-validator` — For class-validator integration\r\n\r\n## Development\r\n\r\n### Testing\r\n\r\nThe validation package includes comprehensive test coverage for all adapters and the validation runner. Tests use the actual validation libraries (Zod, Yup, Joi, class-validator) to ensure proper integration.\r\n\r\n```bash\r\n# Run tests\r\nyarn workspace @c-a-f/validation test\r\n\r\n# Run tests in watch mode\r\nyarn workspace @c-a-f/validation test:watch\r\n```\r\n\r\nOr from the root directory:\r\n\r\n```bash\r\n# Run all tests (including validation)\r\nyarn test\r\n\r\n# Run only validation tests\r\nyarn workspace @c-a-f/validation test\r\n```\r\n\r\n### Test Coverage\r\n\r\nThe test suite covers:\r\n- **ValidationRunner** — All methods (run, runAll, runOrThrow, formatErrors, formatErrorsAsRecord)\r\n- **ZodAdapter** — Validation, parsing, error handling, nested objects, arrays, transformations\r\n- **YupAdapter** — Validation, parsing, error handling, nested objects, arrays, constraints\r\n- **JoiAdapter** — Validation, parsing, error handling, error codes, transformations\r\n- **ClassValidatorAdapter** — Validation, parsing, multiple constraints, optional fields, arrays\r\n\r\n## License\r\n\r\nMIT\r\n","readmeFilename":"README.md"}