{"id":21500711,"url":"https://github.com/lost22git/validate","last_synced_at":"2025-10-15T19:07:11.484Z","repository":{"id":218701600,"uuid":"746699344","full_name":"lost22git/validate","owner":"lost22git","description":"A simple, not flexible, mediocre performance Object Fields Validator","archived":false,"fork":false,"pushed_at":"2024-04-13T19:41:44.000Z","size":34,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-17T13:18:31.836Z","etag":null,"topics":["nim","validate"],"latest_commit_sha":null,"homepage":"","language":"Nim","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/lost22git.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,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2024-01-22T13:56:13.000Z","updated_at":"2025-01-24T23:06:38.000Z","dependencies_parsed_at":"2024-01-30T12:01:11.118Z","dependency_job_id":"667c3791-ccb6-45f5-97fa-144348a2f977","html_url":"https://github.com/lost22git/validate","commit_stats":null,"previous_names":["lost22git/validate"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/lost22git/validate","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lost22git%2Fvalidate","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lost22git%2Fvalidate/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lost22git%2Fvalidate/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lost22git%2Fvalidate/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lost22git","download_url":"https://codeload.github.com/lost22git/validate/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lost22git%2Fvalidate/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279104006,"owners_count":26104411,"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","status":"online","status_checked_at":"2025-10-15T02:00:07.814Z","response_time":56,"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":["nim","validate"],"created_at":"2024-11-23T17:43:39.330Z","updated_at":"2025-10-15T19:07:11.454Z","avatar_url":"https://github.com/lost22git.png","language":"Nim","readme":"\nA simple, not flexible, mediocre performance Object Fields Validator\n\n## Features\n\n* based on pragma and macro\n* tags to group/filter validation rules\n    *  compile-time: tagsFilter expr\n    *  runtime: filterTags params\n* custom validation function\n* custom validation error message \n* nested validation\n\n## TODO\n\n* i18n validation error message\n\n## pragmas\n\n`{.valid: @[built-in rules].}` for built-in validation rules\n\n`{.validFn(fn=\"function name\").}` for custom validation function\n\n`{.validate: \"tag filter expr\".}` for marking a proc as validation proc\n\n## built-in validation rules\n\n|rules|for types|usage|description|\n|:----|:----|:----|:----|\n|nonNil|ref \\| ptr \\| pointer \\| cstring|`a {.valid: @[nonNil()].}: ptr int`|not nil|\n|nonEmpty|string \\| array \\| set \\| seq|`a {.valid: nonEmpty().}: string`|len \u003e 0|\n|nonBlank|string|`a {.valid: @[nonBlank()].}: string`|not isEmptyOrWhiteSpace, use `std/strutils`|\n|range|int|`a {.valid: @[range(min=1, max=10)].}: int`|int range|\n|frange|float|`a {.valid: @[frange(min=1,max=10)].}: float`|float range|\n|length|string \\| array \\| set \\| seq|`a {.valid: @[length(min=1,max=10)].}: string`|length range|\n\n\n## usage\n\n\u003e [!NOTE]\n\u003e Due to use `std/strutils`, `std/sequtils` in generated code, you should import them where you use `{.validate.}`\n\n* code:\n```nim\nimport validate\nimport std/[sequtils, strutils]\n\ntype Category = ref object\n  name {.valid: @[length(min = 2)].}: string\n\ntype Status = enum\n  onsale\n  sold\n\nproc isHttpUrl(v: string): bool =\n    v.startswith(\"http://\")\n\ntype Book = object\n  # {.validFn.} use custom validate function\n  url {.validFn(fn = \"isHttpUrl\", tags = [\"show\"], msg = \"the url is not http url\").}: string\n  # nested validation\n  category {.valid: @[nonNil()].}: Category\n  tags {.valid: @[length(min = 2, max = 4, tags = [\"show\"])].}: seq[string]\n  # msg template interpolation: $min and $max\n  price {.valid: @[frange(min = 5, max = 50, tags = [\"hide\"], msg = \"the price requires from $min to $max\")].}: float\n  # support object variants\n  case status: Status\n  of onsale, sold:\n    count {.valid: @[range(min = 100, tags = [\"hide\"])].}: int\n\n# validate book with filterTags\nproc validate(book: Book, filterTags: varargs[string]): ValidateResult {.validate: \"\".}\n\n# validate book with tagFilterExpr\nproc validateWithTagFilterExpr(book: Book): ValidateResult {.validate: \"\"\" it in [\"default\",\"show\",\"hide\"] \"\"\".}\n\n\nlet category = Category(name: \"T\")\nlet book = Book(\n    url: \"ftp://127.0.0.1/books/1.pdf\",\n    category: category,\n    tags: @[\"nim\"],\n    price: 52'd,\n    status: onsale,\n    count: 10,\n)\n\n# let validateResult = book.validate(\"default\", \"show\", \"hide\")\nlet validateResult = book.validateWithTagFilterExpr()\nfor error in validateResult.errors:\n    echo error\n```\n\n* output:\n```\nthe url is not http url\nBook.category.name: require match range `2 .. 9223372036854775807`\nBook.tags: require match range `2 .. 4`\nthe price requires from 5.0 to 50.0\nBook.count: require match range `100 .. 9223372036854775807`\n```\n\n## benchmark\n\n[bench.nim](bench/bench.nim)\n\n```\nroot in validate/bench on  main [✘?] via 👑 v2.0.2\n❯ ./bench filterTags\nlen: 1000000\ntag filter method: filterTags\nresult: 1.203444μs/op\n\nroot in validate/bench on  main [✘?] via 👑 v2.0.2\n❯ ./bench tagFilterExpr\nlen: 1000000\ntag filter method: tagFilterExpr\nresult: 1.186805μs/op\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flost22git%2Fvalidate","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flost22git%2Fvalidate","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flost22git%2Fvalidate/lists"}