{"id":15482792,"url":"https://github.com/markwoodhall/clova","last_synced_at":"2025-04-14T00:41:30.113Z","repository":{"id":29509328,"uuid":"33047572","full_name":"markwoodhall/clova","owner":"markwoodhall","description":"A simple validation library for Clojure and ClojureScript","archived":false,"fork":false,"pushed_at":"2024-09-22T20:51:25.000Z","size":255,"stargazers_count":16,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-06T23:45:39.627Z","etag":null,"topics":["clojure","clojurescript","validation"],"latest_commit_sha":null,"homepage":null,"language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/markwoodhall.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":null,"support":null}},"created_at":"2015-03-28T19:42:29.000Z","updated_at":"2024-09-22T20:51:28.000Z","dependencies_parsed_at":"2022-08-26T07:22:51.272Z","dependency_job_id":null,"html_url":"https://github.com/markwoodhall/clova","commit_stats":null,"previous_names":[],"tags_count":44,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/markwoodhall%2Fclova","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/markwoodhall%2Fclova/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/markwoodhall%2Fclova/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/markwoodhall%2Fclova/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/markwoodhall","download_url":"https://codeload.github.com/markwoodhall/clova/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248530609,"owners_count":21119601,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["clojure","clojurescript","validation"],"created_at":"2024-10-02T05:10:00.891Z","updated_at":"2025-04-14T00:41:30.079Z","avatar_url":"https://github.com/markwoodhall.png","language":"Clojure","funding_links":[],"categories":["Data Validation"],"sub_categories":[],"readme":"# clova\n\nA \"minimal\" validation library for Clojure and ClojureScript.\n\n- [API Docs](https://cljdoc.xyz/d/clova/clova/0.49.0/api/clova)\n- [Change Log](https://github.com/markwoodhall/clova/blob/master/doc/CHANGES.md)\n\n## Status\n\n[![CircleCI](https://circleci.com/gh/markwoodhall/clova.svg?style=svg)](https://circleci.com/gh/markwoodhall/clova)\n[![Clojars Project](https://img.shields.io/clojars/v/clova.svg)](http://clojars.org/clova)\n\n\n## Installation\n\n`clova` is available from [Clojars](https://clojars.org/clova)\n\n## Usage\n\nValidation sets are pairs of keys to validate and the functions used to validate them. When a map conforms\nto the validation set then the `validate` function returns the original map.\n\n```clojure\n(validate\n  [:email email?\n   :age [between? 18 40]\n   [:nested :value] [between? 0 10]] \n   {:email \"test@email.com\" :age 20 :nested {:value 9}})\n\n;; {:email \"test@email.com\", :age 20, :nested {:value 9}}\n\n```\n\nWhen a map does not conform to the validation set then the `validate` function returns the original map\nwith a sequence of validation errors transposed onto the applicable keys. All validation errors are available\nusing the `:clova.core/results` key and the validation status is available using the `:clova.core/invalid?` key.\n\n```clojure\n(validate\n  [:email email?\n   :age [between? 18 40]\n   [:nested :value] [between? 0 10]] \n   {:email \"testemail.com\" :age 10 :nested {:value 19}})\n\n;; {:clova.core/results (\"email should be a valid email address.\" \"age is 10 but it must be between 18 and 40.\" \"nested value is 19 but it must be between 0 and 10.\") \n;;  :clova.core/invalid? true \n;;  :email (\"email should be a valid email address.\") \n;;  :age (\"age is 10 but it must be between 18 and 40.\"), \n;;  :nested {:value (\"nested value is 19 but it must be between 0 and 10.\")}}\n\n```\n\nYou don't have to use pre-defined validator functions exposed by clova, you can also use arbitrary functions. \n\nArbitrary functions will not generate scenario specific failure messages but a generic message format of `\"%s has value %s, which is invalid.\"` will be used.\n\n```clojure\n(validate [:age [\u003e 18]] {:age 21})\n\n;; {:age 21}\n```\n\nIf you want to compose multiple validators you can.\n\n```clojure\n(validate [:age required? [greater? 18] [lesser? 30]] {:age 29})\n\n;; {:age 29}\n```\n\nMost of the time it is useful to only apply and fail validation if a given key is present in the map under validation, this is\nthe default behaviour in clova. However if this is not the case and you wish to make a validator fail if the key is not present you can do so\nby using a `required?` validator.\n\n\n```clojure\n(validate [:email required? email?] {:email \"email@somedomain.com\"})\n\n;; {:email \"email@somedomain.com\"}\n\n(validate [:age required? [between? 18 30]] {:age 29})\n\n;; {:age 29}\n```\n\nGet the validation status:\n\n```clojure\n(:clova.core/invalid? (validate [:email required? email?] {:email \"notanemail\"}))\n\n;; true\n\n(:clova.core/invalid? (validate [:email required? email?] {:email \"email@somedomain.com\"}))\n\n;; nil\n```\n\nor\n```clojure\n(valid? [:email required? email?] {:email \"email@somedomain.com\"})\n\n;; true\n\n(valid? [:email required? email?] {:email \"notanemail\"})\n\n;; false\n\n```\n\nGet the validation results (error messages):\n\n```clojure\n(:clova.core/results (validate [:email required? email?] {:email \"email@somedomain.com\"}))\n\n;; nil\n(:clova.core/results (validate [:email required? email?] {:email \"notanemail\"}))\n\n;; (\"email should be a valid email address.\")\n```\n\nor\n```clojure\n(results [:email required? email?] {:email \"email@somedomain.com\"})\n\n;; nil\n\n(results [:email required? email?] {:email \"notanemail\"})\n\n;; (\"email should be a valid email address.\")\n```\n\nYou can also specify a custom function for providing validation error messages. This function will\nbe called with the validator type, the target value and any arguments passed to the validator specified as arguments,\nif the custom function returns nil then the default validation message will be used.\n\nFor example, we can use the `between?` validator with a custom error message, like so:\n\n```clojure\n(let [message-func (fn [v-type value args]\n                    (case v-type\n                      :between (str \"Age is \" value \" but it must be between \" (first args) \" and \" (second args))\n                       nil))]\n    (validate v-set {:age 9} {:default-message-fn message-func}))\n```\n\nBy default clova will execute all validators and provide validation messages for all failures. You\ncan override this behaviour using the `:short-circuit?` option. This will stop execution of subsequent\nvalidators after the first validation failure and will therefore only return one validation failure\nmessage.\n\n```clojure\n(validate v-set {:email \"\"} {:short-circuit? true })\n```\n\n[See more usage examples.](https://github.com/markwoodhall/clova/blob/master/doc/EXAMPLES.md)\n\n## Validators\n\nclova has the following built in validators\n\n1. [between?](https://cljdoc.org/d/clova/clova/0.40.2/api/clova.core#between?)\n2. [email?](https://cljdoc.org/d/clova/clova/0.40.2/api/clova.core#email?)\n3. [greater?](https://cljdoc.org/d/clova/clova/0.40.2/api/clova.core#greater?)\n4. [lesser?](https://cljdoc.org/d/clova/clova/0.40.2/api/clova.core#lesser?)\n5. [matches?](https://cljdoc.org/d/clova/clova/0.40.2/api/clova.core#matches?)\n6. [negative?](https://cljdoc.org/d/clova/clova/0.40.2/api/clova.core#negative?)\n7. [positive?](https://cljdoc.org/d/clova/clova/0.40.2/api/clova.core#positive?)\n8. [post-code?](https://cljdoc.org/d/clova/clova/0.40.2/api/clova.core#post-code?)\n9. [not-nil?](https://cljdoc.org/d/clova/clova/0.40.2/api/clova.core#not-nil?)\n10. [required?](https://cljdoc.org/d/clova/clova/0.40.2/api/clova.core#required?)\n11. [url?](https://cljdoc.org/d/clova/clova/0.40.2/api/clova.core#url?)\n12. [zip-code?](https://cljdoc.org/d/clova/clova/0.40.2/api/clova.core#zip-code?)\n13. [length?](https://cljdoc.org/d/clova/clova/0.40.2/api/clova.core#length?)\n14. [longer?](https://cljdoc.org/d/clova/clova/0.40.2/api/clova.core#longer?)\n15. [shorter?](https://cljdoc.org/d/clova/clova/0.40.2/api/clova.core#shorter?)\n16. [one-of?](https://cljdoc.org/d/clova/clova/0.40.2/api/clova.core#one-of?)\n17. [all?](https://cljdoc.org/d/clova/clova/0.40.2/api/clova.core#all?)\n18. [credit-card?](https://cljdoc.org/d/clova/clova/0.40.2/api/clova.core#credit-card?)\n19. [numeric?](https://cljdoc.org/d/clova/clova/0.40.2/api/clova.core#numeric?)\n20. [stringy?](https://cljdoc.org/d/clova/clova/0.40.2/api/clova.core#stringy?)\n21. [date?](https://cljdoc.org/d/clova/clova/0.40.2/api/clova.core#date?)\n22. [before?](https://cljdoc.org/d/clova/clova/0.40.2/api/clova.core#before?)\n23. [after?](https://cljdoc.org/d/clova/clova/0.40.2/api/clova.core#after?)\n24. [=date?](https://cljdoc.org/d/clova/clova/0.40.2/api/clova.core#=date?)\n25. [=?](https://cljdoc.org/d/clova/clova/0.40.2/api/clova.core#=?)\n26. [alphanumeric?](https://cljdoc.org/d/clova/clova/0.40.2/api/clova.core#alphanumeric?)\n27. [not-exists?](https://cljdoc.org/d/clova/clova/0.40.2/api/clova.core#not-exists?)\n27. [exists?](https://cljdoc.org/d/clova/clova/0.40.2/api/clova.core#exists?)\n\n## License\n\nCopyright © 2015-2024 Mark Woodhall\n\nReleased under the MIT License: http://www.opensource.org/licenses/mit-license.php\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarkwoodhall%2Fclova","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmarkwoodhall%2Fclova","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarkwoodhall%2Fclova/lists"}