{"id":36419070,"url":"https://github.com/resoluteworks/validk","last_synced_at":"2026-01-11T17:02:04.575Z","repository":{"id":226788687,"uuid":"769642346","full_name":"resoluteworks/validk","owner":"resoluteworks","description":null,"archived":false,"fork":false,"pushed_at":"2025-12-22T20:04:19.000Z","size":418,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-12-24T09:03:21.839Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/resoluteworks.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","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},"funding":{"github":"cosmin-marginean"}},"created_at":"2024-03-09T16:44:03.000Z","updated_at":"2025-12-22T20:04:23.000Z","dependencies_parsed_at":"2024-03-09T18:22:47.487Z","dependency_job_id":"e479c5f1-17c6-4a22-91a5-b56f15eb4dd4","html_url":"https://github.com/resoluteworks/validk","commit_stats":null,"previous_names":["resoluteworks/validk"],"tags_count":16,"template":false,"template_full_name":null,"purl":"pkg:github/resoluteworks/validk","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/resoluteworks%2Fvalidk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/resoluteworks%2Fvalidk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/resoluteworks%2Fvalidk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/resoluteworks%2Fvalidk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/resoluteworks","download_url":"https://codeload.github.com/resoluteworks/validk/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/resoluteworks%2Fvalidk/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28314260,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-11T14:58:17.114Z","status":"ssl_error","status_checked_at":"2026-01-11T14:55:53.580Z","response_time":60,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":[],"created_at":"2026-01-11T17:02:03.887Z","updated_at":"2026-01-11T17:02:04.561Z","avatar_url":"https://github.com/resoluteworks.png","language":"Kotlin","funding_links":["https://github.com/sponsors/cosmin-marginean"],"categories":[],"sub_categories":[],"readme":"# Validk\n\n![GitHub release (latest by date)](https://img.shields.io/github/v/release/resoluteworks/validk)\n![Coveralls](https://img.shields.io/coverallsCoverage/github/resoluteworks/validk)\n\nValidk is a validation framework for Kotlin JVM designed with these goals in mind:\n* Typesafe DSL to defining validation rules\n* No annotations or \"magic\"\n* Value-aware and conditional validation rules (aka dynamic validation)\n* Zero dependencies\n\nDocumentation:\n* [API Docs](https://resoluteworks.github.io/validk/validk/validk/io.validk/index.html)\n* [Built-in constraints](https://resoluteworks.github.io/validk/validk/validk/io.validk.constraints/index.html)\n* [Previous 1.x version](https://github.com/resoluteworks/validk/tree/v1.2.9)\n\n## Dependency\n\n```groovy\nimplementation \"io.resoluteworks:validk:${validkVersion}\"\n```\n\n## Quick start\n\n```kotlin\ndata class Employee(val name: String, val email: String?)\ndata class Organisation(val name: String, val employees: List\u003cEmployee\u003e)\n\nval organisationValidation = Validation {\n    // Organisation name should be at least 5 characters long\n    Organisation::name { minLength(5) }\n\n    Organisation::employees each {\n        // Each employee should have a name that is at least 10 characters long.\n        Employee::name { minLength(10) }\n\n        // An employee can have an email address, but it's not required.\n        // When present, it should be a valid email.\n        Employee::email ifNotNull { email() }\n    }\n}\n\nval org = Organisation(\n    name = \"ACME\",\n    employees = listOf(Employee(\"John\", \"john@test.com\"), Employee(\"Hannah Johnson\", \"hanna\"))\n)\nval result: ValidationResult\u003cOrganisation\u003e = organisationValidation.validate(org)\nwhen (result) {\n    is ValidationResult.Success -\u003e println(\"Validation success\")\n    is ValidationResult.Failure -\u003e result.allErrors.forEach { println(it) }\n}\n```\n\nThe call `organisationValidation.validate(org)` returns a `ValidationResult\u003cOrganisation\u003e` which can be either a\n`ValidationResult.Success` or a `ValidationResult.Failure`. The `ValidationResult.Failure` returns the details\nof the validation errors.\n\nThe code above would print the following:\n\n```text\nValidationError(path=name, message=Must be at least 5 characters long)\nValidationError(path=employees[0].name, message=Must be at least 10 characters long)\nValidationError(path=employees[1].email, message=Must be a valid email)\n```\n\n## Error messages\nError messages can be customised with any of the following constructs.\n```kotlin\n// Dynamic error message\nEmployee::email {\n    email() message { value -\u003e \"Invalid email address: $value\" }\n}\n\n// Static error message\nEmployee::email {\n    email() message \"This emails address is invalid\"\n}\n```\n\n## Custom constraints\nYou can define custom constraints by calling `addConstraint` inside a validation block.\n```kotlin\nEmployee::name{\n    addConstraint(\"Must start with uppercase letter\") {\n        it.first().isUpperCase() == true\n    }\n}\n```\n\n## Dynamic validation\nThere are several options for defining validation rules which apply in a specific context or when\nthe value being validated meets a certain condition.\n\n### withValue\nThe `withValue` lambda receives the object being validated and allows you to define constraints based\non its properties or state.\n```kotlin\ndata class Entity(\n    val type: String,\n    val registeredOffice: String,\n    val proofOfId: String\n)\n\nValidation\u003cEntity\u003e {\n    withValue { entity -\u003e\n        when (entity.type) {\n            \"PERSON\" -\u003e Entity::proofOfId { minLength(10) }\n            \"COMPANY\" -\u003e Entity::registeredOffice { minLength(5) }\n        }\n    }\n}\n```\n\n### whenIs\nThe `whenIs` construct allows you to define constraints based on specific values for a property.\n```kotlin\nValidation {\n    Entity::entityType.whenIs(\"PERSON\") {\n        Entity::proofOfId { minLength(10) }\n    }\n\n    Entity::entityType.whenIs(\"COMPANY\") {\n        Entity::registeredOffice { minLength(5) }\n    }\n}\n```\n\n## Convert validation result\nA `ValidationResult` can be converted to a custom type using the `map` function. This is typically\nuseful when a custom application state is required as the result of a validation. A common example\nwould be a web application that would return a different HTTP response or status code based on the\nvalidation result.\n\n```kotlin\nval httpResponse = validation.validate(personForm).map {\n    success { person -\u003e\n        Response(HttpStatus.OK, person)\n    }\n    error { person, errors -\u003e\n        Response(HttpStatus.BAD_REQUEST, person, errors)\n    }\n}\n```\n\n## Fail-fast validation\n\nIt's often required to only return the first failure message (first failed constraint) when validating a property.\nThis is the case, for example, when displaying user errors in a UI, and when the order of the constraints\nimplies the next ones would fail anyway (and thus don't need checking).\n\nFor example, let's say that we have an `email` field that's both required and needs to be a valid email.\nIn this case, if a `notBlank()` fails, that means that `email()` will fail as well. In this case, we'd like to\nreturn only the first error message, which would be\n```\n\"Email is required\"\n```\nrather than\n```\n[\"Email is required\", \"This is not a valid email\"].\n```\n\nWe call this fail-fast validation and it's enabled by default. Fail-fast validation can be configured when creating\nthe `Validation` object. The example below will check all the constraints and return all the errors.\n\n```kotlin\nValidation {\n    failFast(false)\n    Person::name {\n        notBlank()\n        matches(\"[a-zA-Z]+ [a-zA-Z]+\")\n    }\n}\n```\n\nWhen turning fail-fast off, you can still opt to only select the first error message post-validation, by using\n`ValidationErrors.error(propertyPath)`.  See [ValiationErrors docs](https://resoluteworks.github.io/validk/validk/validk/io.validk/-validation-errors/index.html) for more details.\n\n## ValidObject\n\n`ValidObject` provides a basic mechanism for storing the validation logic within the object itself.\n\n```kotlin\ndata class Person(val name: String, val email: String) : ValidObject\u003cPerson\u003e {\n    override val validation: Validation\u003cPerson\u003e = Validation {\n        Person::name { minLength(10) }\n        Person::email { email() }\n    }\n}\n\nval validationResult = Person(\"John Smith\", \"john@test.com\").validate()\n```\n\n## License\n[Apache 2.0 License](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fresoluteworks%2Fvalidk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fresoluteworks%2Fvalidk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fresoluteworks%2Fvalidk/lists"}