{"id":19251044,"url":"https://github.com/onesignal/go-proto-validators","last_synced_at":"2025-02-23T16:38:54.093Z","repository":{"id":204025099,"uuid":"337520153","full_name":"OneSignal/go-proto-validators","owner":"OneSignal","description":"Generate message validators from .proto annotations. ","archived":false,"fork":false,"pushed_at":"2023-04-19T18:36:19.000Z","size":245,"stargazers_count":0,"open_issues_count":0,"forks_count":1,"subscribers_count":31,"default_branch":"main","last_synced_at":"2025-02-16T16:56:13.822Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","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/OneSignal.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2021-02-09T19:56:48.000Z","updated_at":"2023-10-27T18:27:38.000Z","dependencies_parsed_at":null,"dependency_job_id":"90edb870-79d6-48be-831c-dda684b4cba5","html_url":"https://github.com/OneSignal/go-proto-validators","commit_stats":null,"previous_names":["onesignal/go-proto-validators"],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OneSignal%2Fgo-proto-validators","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OneSignal%2Fgo-proto-validators/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OneSignal%2Fgo-proto-validators/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OneSignal%2Fgo-proto-validators/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/OneSignal","download_url":"https://codeload.github.com/OneSignal/go-proto-validators/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240347762,"owners_count":19787230,"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":[],"created_at":"2024-11-09T18:19:44.103Z","updated_at":"2025-02-23T16:38:54.073Z","avatar_url":"https://github.com/OneSignal.png","language":"Go","readme":"# Golang ProtoBuf Validator Compiler\n\n[![Apache 2.0 License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE)\n\nA `protoc` plugin that generates `Validate() error` functions on Go proto `struct`s based on field options inside `.proto`\nfiles. The validation functions are code-generated and thus don't suffer on performance from tag-based reflection on\ndeeply-nested messages.\n\n## Requirements\n\nUsing Protobuf validators is currently verified to work with:\n\n- Go 1.11, 1.12, 1.13, 1.15\n- [Protobuf](https://github.com/protocolbuffers/protobuf) @ `v3.13.0`\n- [Go Protobuf](https://github.com/golang/protobuf) @ `v1.3.2`\n- [Gogo Protobuf](https://github.com/gogo/protobuf) @ `v1.3.0`\n\nIt _should_ still be possible to use it in project using earlier Go versions. However if you want to contribute to this\nrepository you'll need at least 1.11 for Go module support.\n\n## Paint me a code picture\n\nLet's take the following `proto3` snippet:\n\n```proto\nsyntax = \"proto3\";\npackage validator.examples;\nimport \"github.com/OneSignal/go-proto-validators/validator.proto\";\n\nmessage InnerMessage {\n  // some_integer can only be in range (0, 100).\n  int32 some_integer = 1 [(validator.field) = {int_gt: 0, int_lt: 100}];\n  // some_float can only be in range (0;1).\n  double some_float = 2 [(validator.field) = {float_gte: 0, float_lte: 1}];\n}\n\nmessage OuterMessage {\n  // important_string must be a lowercase alpha-numeric of 5 to 30 characters (RE2 syntax).\n  string important_string = 1 [(validator.field) = {regex: \"^[a-z0-9]{5,30}$\"}];\n  // proto3 doesn't have `required`, the `msg_exist` enforces presence of InnerMessage.\n  InnerMessage inner = 2 [(validator.field) = {msg_exists : true}];\n}\n```\n\nFirst, the **`required` keyword is back** for `proto3`, under the guise of `msg_exists`. The painful `if-nil` checks are taken care of!\n\nSecond, the expected values in fields are now part of the contract `.proto` file. No more hunting down conditions in code!\n\nThird, the generated code is understandable and has clear understandable error messages. Take a look:\n\n```go\nfunc (this *InnerMessage) Validate() error {\n\tif !(this.SomeInteger \u003e 0) {\n\t\treturn fmt.Errorf(\"validation error: InnerMessage.SomeInteger must be greater than '0'\")\n\t}\n\tif !(this.SomeInteger \u003c 100) {\n\t\treturn fmt.Errorf(\"validation error: InnerMessage.SomeInteger must be less than '100'\")\n\t}\n\tif !(this.SomeFloat \u003e= 0) {\n\t\treturn fmt.Errorf(\"validation error: InnerMessage.SomeFloat must be greater than or equal to '0'\")\n\t}\n\tif !(this.SomeFloat \u003c= 1) {\n\t\treturn fmt.Errorf(\"validation error: InnerMessage.SomeFloat must be less than or equal to '1'\")\n\t}\n\treturn nil\n}\n\nvar _regex_OuterMessage_ImportantString = regexp.MustCompile(\"^[a-z0-9]{5,30}$\")\n\nfunc (this *OuterMessage) Validate() error {\n\tif !_regex_OuterMessage_ImportantString.MatchString(this.ImportantString) {\n\t\treturn fmt.Errorf(\"validation error: OuterMessage.ImportantString must conform to regex '^[a-z0-9]{5,30}$'\")\n\t}\n\tif nil == this.Inner {\n\t\treturn fmt.Errorf(\"validation error: OuterMessage.Inner message must exist\")\n\t}\n\tif this.Inner != nil {\n\t\tif err := validators.CallValidatorIfExists(this.Inner); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n```\n\n## Installing and using\n\nThe `protoc` compiler expects to find plugins named `proto-gen-XYZ` on the execution `$PATH`. So first:\n\n```sh\nexport PATH=${PATH}:${GOPATH}/bin\n```\n\nThen, do the usual\n\n```sh\ngo get github.com/OneSignal/go-proto-validators/protoc-gen-govalidators\n```\n\nYour `protoc` builds probably look very simple like:\n\n```sh\nprotoc  \\\n  --proto_path=. \\\n  --go_out=. \\\n  *.proto\n```\n\nThat's fine, until you encounter `.proto` includes. Because `go-proto-validators` uses field options inside the `.proto` \nfiles themselves, it's `.proto` definition (and the Google `descriptor.proto` itself) need to on the `protoc` include\npath. Hence the above becomes:\n\n```sh\nprotoc  \\\n  --proto_path=${GOPATH}/src \\\n  --proto_path=${GOPATH}/src/github.com/google/protobuf/src \\\n  --proto_path=. \\\n  --go_out=. \\\n  --govalidators_out=. \\\n  *.proto\n```\n\nOr with gogo protobufs:\n\n```sh\nprotoc  \\\n  --proto_path=${GOPATH}/src \\\n  --proto_path=${GOPATH}/src/github.com/gogo/protobuf/protobuf \\\n  --proto_path=. \\\n  --gogo_out=. \\\n  --govalidators_out=gogoimport=true:. \\\n  *.proto\n```\n\nBasically the magical incantation (apart from includes) is the `--govalidators_out`. That triggers the \n`protoc-gen-govalidators` plugin to generate `mymessage.validator.pb.go`. That's it :)\n\n## License\n\n`go-proto-validators` is released under the Apache 2.0 license. See the [LICENSE](LICENSE) file for details.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fonesignal%2Fgo-proto-validators","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fonesignal%2Fgo-proto-validators","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fonesignal%2Fgo-proto-validators/lists"}