diff --git a/.gitignore b/.gitignore index 9ec0e71..3decea7 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,4 @@ node_modules /shared/api/bundles/ /coverage/ +/contracts/ diff --git a/Taskfile.yml b/Taskfile.yml index aa0bc20..35c077f 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -6,23 +6,23 @@ vars: GOLANGCI_LINT_VERSION: 'v2.8.0' GCI_VERSION: 'v0.13.7' GOFUMPT_VERSION: 'v0.9.2' + BUF_VERSION: '1.64.0' + PROTOC_GEN_GO_VERSION: 'v1.36.11' + PROTOC_GEN_GO_GRPC_VERSION: 'v1.6.0' BIN_DIR: '{{.ROOT_DIR}}/bin' GOLANGCI_LINT: '{{.BIN_DIR}}/golangci-lint' GCI: '{{.BIN_DIR}}/gci' GOFUMPT: '{{.BIN_DIR}}/gofumpt' + BUF: '{{.BIN_DIR}}/buf' + PROTOC_GEN_GO: '{{.BIN_DIR}}/protoc-gen-go' + PROTOC_GEN_GO_GRPC: '{{.BIN_DIR}}/protoc-gen-go-grpc' + MODULES: inventory order payment shared tasks: install-formatters: desc: "Устанавливает форматтеры gci и gofumpt в ./bin" - summary: | - Эта задача проверяет наличие инструментов форматирования кода gofumpt и gci в директории bin. - Если инструменты не найдены, они будут автоматически установлены с указанными версиями. - - Используется: - - gofumpt: для форматирования кода Go - - gci: для сортировки импортов Go cmds: - | [ -f {{.GOFUMPT}} ] || { @@ -39,13 +39,6 @@ tasks: format: desc: "Форматирует весь проект gofumpt + gci, исключая mocks" - summary: | - Форматирует все Go-файлы проекта с использованием gofumpt для стандартизации кода - и gci для сортировки импортов, исключая файлы в директориях mocks. - - Использует инструменты: - - gofumpt: для стандартизации форматирования - - gci: для сортировки импортов по стандартным группам deps: [ install-formatters ] cmds: - | @@ -69,11 +62,6 @@ tasks: install-golangci-lint: desc: "Устанавливает golangci-lint в каталог bin" - summary: | - Проверяет наличие golangci-lint в директории bin. - Если инструмент не найден, автоматически устанавливает его через go install. - - Устанавливаемая версия: {{.GOLANGCI_LINT_VERSION}} cmds: - | [ -f {{.GOLANGCI_LINT}} ] || { @@ -86,14 +74,6 @@ tasks: lint: desc: "Запускает golangci-lint для всех модулей" - summary: | - Запускает линтер golangci-lint для всех модулей проекта. - Линтер проверяет код на соответствие стандартам качества и лучшим практикам. - Проверка включает проверку безопасности через gosec (встроенный в golangci-lint). - - Зависимости: - - install-golangci-lint: автоматически устанавливает линтер - - format: форматирует код перед проверкой deps: [ install-golangci-lint ] vars: MODULES: '{{.MODULES}}' @@ -110,3 +90,89 @@ tasks: fi done exit $ERR + + lint:fix: + desc: "Запускает golangci-lint для всех модулей" + deps: [ install-golangci-lint ] + vars: + MODULES: '{{.MODULES}}' + GOLANGCI_LINT: '{{.GOLANGCI_LINT}}' + cmds: + - | + set -e + ERR=0 + echo "🔍 Линтим все модули ..." + for mod in {{.MODULES}}; do + if [ -d "$mod" ]; then + echo "🔍 Линтим $mod module" + {{.GOLANGCI_LINT}} run $mod/... --fix --config=.golangci.yml || ERR=1 + fi + done + exit $ERR + + deps:update: + desc: "Обновление зависимостей в go.mod во всех модулях" + cmds: + - | + echo "🔄 Обновление зависимостей в go.work" + go work sync + echo "🔄 Обновление зависимостей в go.mod во всех модулях" + for mod in {{.MODULES}}; do + if [ -d "$mod" ]; then + echo "🔄 Обновление зависимостей в $mod" + (cd "$mod" && go mod tidy -compat={{.GO_VERSION}}) || exit 1 + fi + done + + install-buf: + desc: "Устанавливает Buf в каталог bin" + cmds: + - | + mkdir -p {{.BIN_DIR}} + [ -f {{.BUF}} ] || { + echo '📦 Устанавливаем buf {{.BUF_VERSION}}...' + GOBIN={{.BIN_DIR}} go install github.com/bufbuild/buf/cmd/buf@v{{.BUF_VERSION}} + } + status: + - test -x {{.BUF}} + + proto:install-plugins: + desc: "Устанавливает protoc плагины в каталог bin" + dir: shared/proto + cmds: + - | + [ -f {{.PROTOC_GEN_GO}} ] || { + echo '📦 Installing protoc-gen-go...' + GOBIN={{.BIN_DIR}} go install google.golang.org/protobuf/cmd/protoc-gen-go@{{.PROTOC_GEN_GO_VERSION}} + } + [ -f {{.PROTOC_GEN_GO_GRPC}} ] || { + echo '📦 Installing protoc-gen-go-grpc...' + GOBIN={{.BIN_DIR}} go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@{{.PROTOC_GEN_GO_GRPC_VERSION}} + } + + proto:update-deps: + deps: [ install-buf ] + desc: Обновляет зависимости protobuf из удаленных репозиториев (googleapis и т.д.) + dir: shared/proto + cmds: + - | + echo "🔄 Обновляем зависимости buf..." + {{.BUF}} dep update + + proto:lint: + deps: [ proto:install-plugins, proto:update-deps ] + desc: Проверка .proto-файлов на соответствие стилю + dir: shared/proto + cmds: + - | + echo "🔍 Проверяем .proto файлы..." + {{.BUF}} lint + + proto:gen: + deps: [ install-buf, proto:install-plugins, proto:update-deps, proto:lint ] + desc: Генерация Go-кода из .proto + dir: shared/proto + cmds: + - | + echo "🏗️ Генерируем Go код из .proto..." + {{.BUF}} generate diff --git a/go.work.sum b/go.work.sum new file mode 100644 index 0000000..f881c84 --- /dev/null +++ b/go.work.sum @@ -0,0 +1,139 @@ +cel.dev/expr v0.24.0/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw= +cloud.google.com/go/accessapproval v1.8.8/go.mod h1:RFwPY9JDKseP4gJrX1BlAVsP5O6kI8NdGlTmaeDefmk= +cloud.google.com/go/accesscontextmanager v1.9.7/go.mod h1:i6e0nd5CPcrh7+YwGq4bKvju5YB9sgoAip+mXU73aMM= +cloud.google.com/go/aiplatform v1.113.0/go.mod h1:B8fcWtC2vSadapIQqweJrTATJe/odNDjk2uIA5kmXog= +cloud.google.com/go/analytics v0.30.1/go.mod h1:V/FnINU5kMOsttZnKPnXfKi6clJUHTEXUKQjHxcNK8A= +cloud.google.com/go/apigateway v1.7.7/go.mod h1:j1bCmrUK1BzVHpiIyTApxB7cRyhivKzltqLmp6j6i7U= +cloud.google.com/go/apigeeconnect v1.7.7/go.mod h1:ftGK3nca0JePiVLl0A6alaMjKdOc5C+sAkFMyH2RH8U= +cloud.google.com/go/apigeeregistry v0.10.0/go.mod h1:SAlF5OhKvyLDuwWAaFAIVJjrEqKRrGTPkJs+TWNnSqg= +cloud.google.com/go/appengine v1.9.7/go.mod h1:y1XpGVeAhbsNzHida79cHbr3pFRsym0ob8xnC8yphbo= +cloud.google.com/go/area120 v0.9.7/go.mod h1:5nJ0yksmjOMfc4Zpk+okWfJ3A1004FvB82rfia+ZLaY= +cloud.google.com/go/artifactregistry v1.19.0/go.mod h1:UEAPCgHDFC1q+A8nnVxXHPEy9KCVOeavFBF1fEChQvU= +cloud.google.com/go/asset v1.22.0/go.mod h1:q80JP2TeWWzMCazYnrAfDf36aQKf1QiKzzpNLflJwf8= +cloud.google.com/go/assuredworkloads v1.13.0/go.mod h1:o/oHEOnUlribR+uJWTKQo8A5RhSl9K9FNeMOew4TJ3M= +cloud.google.com/go/automl v1.15.0/go.mod h1:U9zOtQb8zVrFNGTuW3BfxeqmLyeleLgT9B12EaXfODg= +cloud.google.com/go/baremetalsolution v1.4.0/go.mod h1:K6C6g4aS8LW95I0fEHZiBsBlh0UxwDLGf+S/vyfXbvg= +cloud.google.com/go/batch v1.14.0/go.mod h1:oeQveyG6NDS/ks2ilOP4LzKRmuIaI7GLe0CkR7WF6pk= +cloud.google.com/go/beyondcorp v1.2.0/go.mod h1:sszcgxpPPBEfLzbI0aYCTg6tT1tyt3CmKav3NZIUcvI= +cloud.google.com/go/bigquery v1.72.0/go.mod h1:GUbRtmeCckOE85endLherHD9RsujY+gS7i++c1CqssQ= +cloud.google.com/go/bigtable v1.41.0/go.mod h1:JlaltP06LEFXaxQdZiarGR9tKsX/II0IkNAKMDrWspI= +cloud.google.com/go/billing v1.21.0/go.mod h1:ZGairB3EVnb3i09E2SxFxo50p5unPaMTuo1jh6jW9js= +cloud.google.com/go/binaryauthorization v1.10.0/go.mod h1:WOuiaQkI4PU/okwrcREjSAr2AUtjQgVe+PlrXKOmKKw= +cloud.google.com/go/certificatemanager v1.9.6/go.mod h1:vWogV874jKZkSRDFCMM3r7wqybv8WXs3XhyNff6o/Zo= +cloud.google.com/go/channel v1.21.0/go.mod h1:8v3TwHtgLmFxTpL2U+e10CLFOQN8u/Vr9RhYcJUS3y8= +cloud.google.com/go/cloudbuild v1.25.0/go.mod h1:lCu+T6IPkobPo2Nw+vCE7wuaAl9HbXLzdPx/tcF+oWo= +cloud.google.com/go/clouddms v1.8.8/go.mod h1:QtCyw+a73dlkDb2q20aTAPvfaTZCepDDi6Gb1AKq0a4= +cloud.google.com/go/cloudtasks v1.13.7/go.mod h1:H0TThOUG+Ml34e2+ZtW6k6nt4i9KuH3nYAJ5mxh7OM4= +cloud.google.com/go/compute v1.53.0/go.mod h1:zdogTa7daHhEtEX92+S5IARtQmi/RNVPUfoI8Jhl8Do= +cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= +cloud.google.com/go/contactcenterinsights v1.17.4/go.mod h1:kZe6yOnKDfpPz2GphDHynxk/Spx+53UX/pGf+SmWAKM= +cloud.google.com/go/container v1.45.0/go.mod h1:eB6jUfJLjne9VsTDGcH7mnj6JyZK+KOUIA6KZnYE/ds= +cloud.google.com/go/containeranalysis v0.14.2/go.mod h1:FjppROiUtP9cyMegdWdY/TsBSGc6kqh1GjA2NOJXXL8= +cloud.google.com/go/datacatalog v1.26.1/go.mod h1:2Qcq8vsHNxMDgjgadRFmFG47Y+uuIVsyEGUrlrKEdrg= +cloud.google.com/go/dataflow v0.11.1/go.mod h1:3s6y/h5Qz7uuxTmKJKBifkYZ3zs63jS+6VGtSu8Cf7Y= +cloud.google.com/go/dataform v0.12.1/go.mod h1:atGS8ReRjfNDUQib0X/o/7Gi2bqHI2G7/J86LKiGimE= +cloud.google.com/go/datafusion v1.8.7/go.mod h1:4dkFb1la41qCEXh1AzYtFwl842bu2ikTUXyKhjvFCb0= +cloud.google.com/go/datalabeling v0.9.7/go.mod h1:EEUVn+wNn3jl19P2S13FqE1s9LsKzRsPuuMRq2CMsOk= +cloud.google.com/go/dataplex v1.28.0/go.mod h1:VB+xlYJiJ5kreonXsa2cHPj0A3CfPh/mgiHG4JFhbUA= +cloud.google.com/go/dataproc/v2 v2.15.0/go.mod h1:tSdkodShfzrrUNPDVEL6MdH9/mIEvp/Z9s9PBdbsZg8= +cloud.google.com/go/dataqna v0.9.8/go.mod h1:2lHKmGPOqzzuqCc5NI0+Xrd5om4ulxGwPpLB4AnFgpA= +cloud.google.com/go/datastore v1.21.0/go.mod h1:9l+KyAHO+YVVcdBbNQZJu8svF17Nw5sMKuFR0LYf1nY= +cloud.google.com/go/datastream v1.15.1/go.mod h1:aV1Grr9LFon0YvqryE5/gF1XAhcau2uxN2OvQJPpqRw= +cloud.google.com/go/deploy v1.27.3/go.mod h1:7LFIYYTSSdljYRqY3n+JSmIFdD4lv6aMD5xg0crB5iw= +cloud.google.com/go/dialogflow v1.73.0/go.mod h1:vFkeDO7ishnfakWVLlbgIynQGTFJ/YaVMlYmSn5M+1o= +cloud.google.com/go/dlp v1.28.0/go.mod h1:C3od1fIK8lf7Kr62aU1Uh0z4OL5Z8s3do3znAiEupAw= +cloud.google.com/go/documentai v1.39.0/go.mod h1:KmlLO93F7GRU8dENXRxvt+7V8o7eCG6Y6WDitKbcYJs= +cloud.google.com/go/domains v0.10.7/go.mod h1:T3WG/QUAO/52z4tUPooKS8AY7yXaFxPYn1V3F0/JbNQ= +cloud.google.com/go/edgecontainer v1.4.4/go.mod h1:yyNVHsCKtsX/0mqFdbljQw0Uo660q2dlMPaiqYiC2Tg= +cloud.google.com/go/errorreporting v0.4.0/go.mod h1:dZGEhqzdHZSRxxWLVjC3Ue5CVaROzvP58D9rU6zbBfw= +cloud.google.com/go/essentialcontacts v1.7.7/go.mod h1:ytycWAEn/aKUMRKQPMVgMrAtphEMgjbzL8vFwM3tqXs= +cloud.google.com/go/eventarc v1.18.0/go.mod h1:/6SDoqh5+9QNUqCX4/oQcJVK16fG/snHBSXu7lrJtO8= +cloud.google.com/go/filestore v1.10.3/go.mod h1:94ZGyLTx9j+aWKozPQ6Wbq1DuImie/L/HIdGMshtwac= +cloud.google.com/go/firestore v1.21.0/go.mod h1:1xH6HNcnkf/gGyR8udd6pFO4Z7GWJSwLKQMx/u6UrP4= +cloud.google.com/go/functions v1.19.7/go.mod h1:xbcKfS7GoIcaXr2FSwmtn9NXal1JR4TV6iYZlgXffwA= +cloud.google.com/go/gkebackup v1.8.1/go.mod h1:GAaAl+O5D9uISH5MnClUop2esQW4pDa2qe/95A4l7YQ= +cloud.google.com/go/gkeconnect v0.12.5/go.mod h1:wMD2RXcsAWlkREZWJDVeDV70PYka1iEb9stFmgpw+5o= +cloud.google.com/go/gkehub v0.16.0/go.mod h1:ADp27Ucor8v81wY+x/5pOxTorxkPj/xswH3AUpN62GU= +cloud.google.com/go/gkemulticloud v1.6.0/go.mod h1:bGpd4o/Z5Z/XFlaojkgdVisHRwb+fLJvUPzsmV0I9ok= +cloud.google.com/go/gsuiteaddons v1.7.8/go.mod h1:DBKNHH4YXAdd/rd6zVvtOGAJNGo0ekOh+nIjTUDEJ5U= +cloud.google.com/go/iam v1.5.3/go.mod h1:MR3v9oLkZCTlaqljW6Eb2d3HGDGK5/bDv93jhfISFvU= +cloud.google.com/go/iap v1.11.3/go.mod h1:+gXO0ClH62k2LVlfhHzrpiHQNyINlEVmGAE3+DB4ShU= +cloud.google.com/go/ids v1.5.7/go.mod h1:N3ZQOIgIBwwOu2tzyhmh3JDT+kt8PcoKkn2BRT9Qe4A= +cloud.google.com/go/iot v1.8.7/go.mod h1:HvVcypV8LPv1yTXSLCNK+YCtqGHhq+p0F3BXETfpN+U= +cloud.google.com/go/kms v1.24.0/go.mod h1:QDH3z2SJ50lfNOE8EokKC1G40i7I0f8xTMCoiptcb5g= +cloud.google.com/go/language v1.14.6/go.mod h1:7y3J9OexQsfkWNGCxhT+7lb64pa60e12ZCoWDOHxJ1M= +cloud.google.com/go/lifesciences v0.10.7/go.mod h1:v3AbTki9iWttEls/Wf4ag3EqeLRHofploOcpsLnu7iY= +cloud.google.com/go/logging v1.13.1/go.mod h1:XAQkfkMBxQRjQek96WLPNze7vsOmay9H5PqfsNYDqvw= +cloud.google.com/go/longrunning v0.8.0/go.mod h1:UmErU2Onzi+fKDg2gR7dusz11Pe26aknR4kHmJJqIfk= +cloud.google.com/go/managedidentities v1.7.7/go.mod h1:nwNlMxtBo2YJMvsKXRtAD1bL41qiCI9npS7cbqrsJUs= +cloud.google.com/go/maps v1.26.0/go.mod h1:+auempdONAP8emtm48aCfNo1ZC+3CJniRA1h8J4u7bY= +cloud.google.com/go/mediatranslation v0.9.7/go.mod h1:mz3v6PR7+Fd/1bYrRxNFGnd+p4wqdc/fyutqC5QHctw= +cloud.google.com/go/memcache v1.11.7/go.mod h1:AU1jYlUqCihxapcJ1GGMtlMWDVhzjbfUWBXqsXa4rBg= +cloud.google.com/go/metastore v1.14.8/go.mod h1:h1XI2LpD4ohJhQYn9TwXqKb5sVt6KSo47ft96SiFF1s= +cloud.google.com/go/monitoring v1.24.3/go.mod h1:nYP6W0tm3N9H/bOw8am7t62YTzZY+zUeQ+Bi6+2eonI= +cloud.google.com/go/networkconnectivity v1.19.1/go.mod h1:Q5v6uNNNz8BP232uuXM66XgWML9m379xhwv58Y+8Kb0= +cloud.google.com/go/networkmanagement v1.21.0/go.mod h1:clG/5Yt0wQ57qSH6Yh7oehQYlobHw3F6nb3Pn4ig5hU= +cloud.google.com/go/networksecurity v0.11.0/go.mod h1:JLgDsg4tOyJ3eMO8lypjqMftbfd60SJ+P7T+DUmWBsM= +cloud.google.com/go/notebooks v1.12.7/go.mod h1:uR9pxAkKmlNloibMr9Q1t8WhIu4P2JeqJs7c064/0Mo= +cloud.google.com/go/optimization v1.7.7/go.mod h1:OY2IAlX23o52qwMAZ0w65wibKuV12a4x6IHDTCq6kcU= +cloud.google.com/go/orchestration v1.11.10/go.mod h1:tz7m1s4wNEvhNNIM3JOMH0lYxBssu9+7si5MCPw/4/0= +cloud.google.com/go/orgpolicy v1.15.1/go.mod h1:bpvi9YIyU7wCW9WiXL/ZKT7pd2Ovegyr2xENIeRX5q0= +cloud.google.com/go/osconfig v1.15.1/go.mod h1:NegylQQl0+5m+I+4Ey/g3HGeQxKkncQ1q+Il4DZ8PME= +cloud.google.com/go/oslogin v1.14.7/go.mod h1:NB6NqBHfDMwznePdBVX+ILllc1oPCdNSGp5u/WIyndY= +cloud.google.com/go/phishingprotection v0.9.7/go.mod h1:JTI4HNGyAbWolBoNOoCyCF0e3cqPNrYnlievHU49EwE= +cloud.google.com/go/policytroubleshooter v1.11.7/go.mod h1:JP/aQ+bUkt4Gz6lQXBi/+A/6nyNRZ0Pvxui5Xl9ieyk= +cloud.google.com/go/privatecatalog v0.10.8/go.mod h1:BkLHi+rtAGYBt5DocXLytHhF0n6F03Tegxgty40Y7aA= +cloud.google.com/go/pubsub v1.50.1/go.mod h1:6YVJv3MzWJUVdvQXG081sFvS0dWQOdnV+oTo++q/xFk= +cloud.google.com/go/pubsub/v2 v2.0.0/go.mod h1:0aztFxNzVQIRSZ8vUr79uH2bS3jwLebwK6q1sgEub+E= +cloud.google.com/go/pubsublite v1.8.2/go.mod h1:4r8GSa9NznExjuLPEJlF1VjOPOpgf3IT6k8x/YgaOPI= +cloud.google.com/go/recaptchaenterprise/v2 v2.21.0/go.mod h1:HxQYqZC2/zl2CvKN7jJEv71vEdDi1GMGNUiZxnpiuVI= +cloud.google.com/go/recommendationengine v0.9.7/go.mod h1:snZ/FL147u86Jqpv1j95R+CyU5NvL/UzYiyDo6UByTM= +cloud.google.com/go/recommender v1.13.6/go.mod h1:y5/5womtdOaIM3xx+76vbsiA+8EBTIVfWnxHDFHBGJM= +cloud.google.com/go/redis v1.18.3/go.mod h1:x8HtXZbvMBDNT6hMHaQ022Pos5d7SP7YsUH8fCJ2Wm4= +cloud.google.com/go/resourcemanager v1.10.7/go.mod h1:rScGkr6j2eFwxAjctvOP/8sqnEpDbQ9r5CKwKfomqjs= +cloud.google.com/go/resourcesettings v1.8.3/go.mod h1:BzgfXFHIWOOmHe6ZV9+r3OWfpHJgnqXy8jqwx4zTMLw= +cloud.google.com/go/retail v1.25.1/go.mod h1:J75G8pd+DH0SHueL9IJw7Y5d2VhTsjFsk+F1t9f8jXc= +cloud.google.com/go/run v1.14.0/go.mod h1:KStBOpjX7m47Yi1xStWSkvJcCqLr+PMUkz6p3po5/VA= +cloud.google.com/go/scheduler v1.11.8/go.mod h1:bNKU7/f04eoM6iKQpwVLvFNBgGyJNS87RiFN73mIPik= +cloud.google.com/go/secretmanager v1.16.0/go.mod h1://C/e4I8D26SDTz1f3TQcddhcmiC3rMEl0S1Cakvs3Q= +cloud.google.com/go/security v1.19.2/go.mod h1:KXmf64mnOsLVKe8mk/bZpU1Rsvxqc0Ej0A6tgCeN93w= +cloud.google.com/go/securitycenter v1.38.1/go.mod h1:Ge2D/SlG2lP1FrQD7wXHy8qyeloRenvKXeB4e7zO6z0= +cloud.google.com/go/servicedirectory v1.12.7/go.mod h1:gOtN+qbuCMH6tj2dqlDY3qQL7w3V0+nkWaZElnJK8Ps= +cloud.google.com/go/shell v1.8.7/go.mod h1:OTke7qc3laNEW5Jr5OV9VR3IwU5x5VqGOE6705zFex4= +cloud.google.com/go/spanner v1.87.0/go.mod h1:tcj735Y2aqphB6/l+X5MmwG4NnV+X1NJIbFSZGaHYXw= +cloud.google.com/go/speech v1.29.0/go.mod h1:wtUmIS/h0ZYU6cPA9klcyST3f6i2FdnvNDqENjrRDds= +cloud.google.com/go/storagetransfer v1.13.1/go.mod h1:S858w5l383ffkdqAqrAA+BC7KlhCqeNieK3sFf5Bj4Y= +cloud.google.com/go/talent v1.8.4/go.mod h1:3yukBXUTVFNyKcJpUExW/k5gqEy8qW6OCNj7WdN0MWo= +cloud.google.com/go/texttospeech v1.16.0/go.mod h1:AeSkoH3ziPvapsuyI07TWY4oGxluAjntX+pF4PJ2jy0= +cloud.google.com/go/tpu v1.8.4/go.mod h1:ul0cyWSHr6jHGZYElZe6HvQn35VY93RAlwpDiSBRnPA= +cloud.google.com/go/trace v1.11.7/go.mod h1:TNn9d5V3fQVf6s4SCveVMIBS2LJUqo73GACmq/Tky0s= +cloud.google.com/go/translate v1.12.7/go.mod h1:wwJp14NZyWvcrFANhIXutXj0pOBkYciBHwSlUOykcjI= +cloud.google.com/go/video v1.27.1/go.mod h1:xzfAC77B4vtnbi/TT3UUxEjCa/+Ehy5EA8w470ytOig= +cloud.google.com/go/videointelligence v1.12.7/go.mod h1:XAk5hCMY+GihxJ55jNoMdwdXSNZnCl3wGs2+94gK7MA= +cloud.google.com/go/vision/v2 v2.9.6/go.mod h1:lJC+vP15D5znJvHQYjEoTKnpToX1L93BUlvBmzM0gyg= +cloud.google.com/go/vmmigration v1.10.0/go.mod h1:LDztCWEb+RwS1bPg4Xzt0fcJS9kVrFxa3ejhH7OW9vg= +cloud.google.com/go/vmwareengine v1.3.6/go.mod h1:ps0rb+Skgpt9ppHYC0o5DqtJ5ld2FyS8sAqtbHH8t9s= +cloud.google.com/go/vpcaccess v1.8.7/go.mod h1:9RYw5bVvk4Z51Rc8vwXT63yjEiMD/l7XyEaDyrNHgmk= +cloud.google.com/go/webrisk v1.11.2/go.mod h1:yH44GeXz5iz4HFsIlGeoVvnjwnmfbni7Lwj1SelV4f0= +cloud.google.com/go/websecurityscanner v1.7.7/go.mod h1:ng/PzARaus3Bj4Os4LpUnyYHsbtJky1HbBDmz148v1o= +cloud.google.com/go/workflows v1.14.3/go.mod h1:CC9+YdVI2Kvp0L58WajHpEfKJxhrtRh3uQ0SYWcmAk4= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.30.0/go.mod h1:P4WPRUkOhJC13W//jWpyfJNDAIpvRbAUIYLX/4jtlE0= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cncf/xds/go v0.0.0-20251022180443-0feb69152e9f/go.mod h1:HlzOvOjVBOfTGSRXRyY0OiCS/3J1akRGQQpRO/7zyF4= +github.com/envoyproxy/go-control-plane v0.13.5-0.20251024222203-75eaa193e329/go.mod h1:Alz8LEClvR7xKsrq3qzoc4N0guvVNSS8KmSChGYr9hs= +github.com/envoyproxy/go-control-plane/envoy v1.35.0/go.mod h1:09qwbGVuSWWAyN5t/b3iyVfz5+z8QWGrzkoqm/8SbEs= +github.com/envoyproxy/go-control-plane/ratelimit v0.1.0/go.mod h1:Wk+tMFAFbCXaJPzVVHnPgRKdUdwW/KdbRt94AzgRee4= +github.com/envoyproxy/protoc-gen-validate v1.2.1/go.mod h1:d/C80l/jxXLdfEIhX1W2TmLfsJ31lvEjwamM4DxlWXU= +github.com/go-jose/go-jose/v4 v4.1.3/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= +github.com/golang/glog v1.2.5/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= +github.com/spiffe/go-spiffe/v2 v2.6.0/go.mod h1:gm2SeUoMZEtpnzPNs2Csc0D/gX33k1xIx7lEzqblHEs= +go.opentelemetry.io/contrib/detectors/gcp v1.38.0/go.mod h1:SU+iU7nu5ud4oCb3LQOhIZ3nRLj6FNVrKgtflbaf2ts= +golang.org/x/crypto v0.44.0/go.mod h1:013i+Nw79BMiQiMsOPcVCB5ZIJbYkerPrGnOa00tvmc= +golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w= +golang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= +golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254= +golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs= +google.golang.org/genproto/googleapis/api v0.0.0-20251029180050-ab9386a59fda/go.mod h1:fDMmzKV90WSg1NbozdqrE64fkuTv6mlq2zxo9ad+3yo= +google.golang.org/genproto/googleapis/api v0.0.0-20260120174246-409b4a993575/go.mod h1:dd646eSK+Dk9kxVBl1nChEOhJPtMXriCcVb4x3o6J+E= diff --git a/inventory/cmd/main.go b/inventory/cmd/main.go new file mode 100644 index 0000000..dccded2 --- /dev/null +++ b/inventory/cmd/main.go @@ -0,0 +1,183 @@ +package main + +import ( + "context" + "fmt" + "log" + "net" + "os" + "os/signal" + "slices" + "sync" + "syscall" + + "github.com/brianvoe/gofakeit/v7" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/reflection" + "google.golang.org/grpc/status" + "google.golang.org/protobuf/types/known/timestamppb" + + inventoryv1 "github.com/qyrlabs/test-backend/shared/pkg/proto/inventory/v1" +) + +const grpcPort = 50061 + +type inventoryService struct { + inventoryv1.UnimplementedInventoryServiceServer + + mu sync.RWMutex + parts map[string]*inventoryv1.Part +} + +// Get part info by its UUID. +func (s *inventoryService) GetPart(ctx context.Context, req *inventoryv1.GetPartRequest) (*inventoryv1.GetPartResponse, error) { + s.mu.RLock() + defer s.mu.RUnlock() + part, ok := s.parts[req.GetUuid()] + if !ok { + return nil, status.Errorf(codes.NotFound, "part with uuid %s is not found", req.GetUuid()) + } + + return &inventoryv1.GetPartResponse{ + Part: part, + }, nil +} + +// Returns List of Parts by filter. +func (s *inventoryService) ListParts(ctx context.Context, req *inventoryv1.ListPartsRequest) (*inventoryv1.ListPartsResponse, error) { + s.mu.RLock() + defer s.mu.RUnlock() + + filter := req.GetFilter() + uuids := filter.GetUuids() + names := filter.GetNames() + categories := filter.GetCategories() + countries := filter.GetManufacturerCountries() + tags := filter.GetTags() + + filteredParts := make([]*inventoryv1.Part, 0) + for uuid, part := range s.parts { + if (uuids == nil || slices.Contains(uuids, uuid)) && + (names == nil || slices.Contains(names, part.GetName())) && + (categories == nil || slices.Contains(categories, part.GetCategory())) && + (countries == nil || slices.Contains(countries, part.GetManufacturer().GetCountry())) && + (tags == nil || slices.Equal(tags, part.GetTags())) { + + filteredParts = append(filteredParts, part) + } + } + + if len(filteredParts) == 0 { + return nil, status.Errorf(codes.NotFound, "parts not found") + } + + return &inventoryv1.ListPartsResponse{ + Parts: filteredParts, + }, nil +} + +func main() { + lis, err := net.Listen("tcp", fmt.Sprintf("localhost:%d", grpcPort)) + if err != nil { + log.Printf("failed to listen: %v\n", err) + return + } + + defer func() { + if cerr := lis.Close(); cerr != nil { + log.Printf("failed to close listener: %v\n", cerr) + } + }() + + grpcServer := grpc.NewServer() + reflection.Register(grpcServer) + + service := &inventoryService{ + parts: initParts(100), + } + + inventoryv1.RegisterInventoryServiceServer(grpcServer, service) + + go func() { + log.Printf("gRPC server listening on %s\n", lis.Addr().String()) + err := grpcServer.Serve(lis) + if err != nil { + log.Printf("Failed to serve: %v\n", err) + return + } + }() + + // Graceful shutdown + quit := make(chan os.Signal, 1) + signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) + <-quit + log.Println("Shutting down gRPC server...") + grpcServer.GracefulStop() + log.Println("gRPC server stopped") +} + +func initParts(count int) map[string]*inventoryv1.Part { + parts := createParts(count) + partsMap := make(map[string]*inventoryv1.Part, count) + for _, part := range parts { + partsMap[part.GetUuid()] = part + } + return partsMap +} + +func fakeDimensions() *inventoryv1.Dimensions { + return &inventoryv1.Dimensions{ + Length: gofakeit.Float64Range(1.0, 300.0), + Width: gofakeit.Float64Range(1.0, 300.0), + Height: gofakeit.Float64Range(0.5, 150.0), + Weight: gofakeit.Float64Range(0.1, 500.0), + } +} + +func fakeManufacturer() *inventoryv1.Manufacturer { + return &inventoryv1.Manufacturer{ + Name: gofakeit.Company(), + Country: gofakeit.Country(), + Website: gofakeit.URL(), + } +} + +func fakeTags() []string { + tags := make([]string, 0, 5) + for range gofakeit.IntRange(1, 5) { + tags = append(tags, gofakeit.Word()) + } + return tags +} + +func randomCategory() inventoryv1.Category { + // Ignore any, but not UNSPECIFIED + vals := []inventoryv1.Category{ + inventoryv1.Category_CATEGORY_ENGINE, + inventoryv1.Category_CATEGORY_FUEL, + inventoryv1.Category_CATEGORY_PORTHOLE, + inventoryv1.Category_CATEGORY_WING, + } + return vals[gofakeit.IntRange(0, len(vals)-1)] +} + +func createParts(count int) []*inventoryv1.Part { + parts := make([]*inventoryv1.Part, 0, count) + for range count { + parts = append(parts, &inventoryv1.Part{ + Uuid: gofakeit.UUID(), + Name: gofakeit.Name(), + Description: gofakeit.Sentence(10), + Price: int64(gofakeit.IntRange(1, 100000)), + StockQuantity: int64(gofakeit.IntRange(1, 100)), + Category: randomCategory(), + Dimensions: fakeDimensions(), + Manufacturer: fakeManufacturer(), + Tags: fakeTags(), + CreatedAt: timestamppb.New(gofakeit.Date()), + UpdatedAt: timestamppb.New(gofakeit.Date()), + }) + } + return parts +} diff --git a/inventory/go.mod b/inventory/go.mod index 89c7d5d..c80abd6 100644 --- a/inventory/go.mod +++ b/inventory/go.mod @@ -1,3 +1,19 @@ module github.com/qyrlabs/test-backend/inventory go 1.25.6 + +replace github.com/qyrlabs/test-backend/shared => ../shared + +require ( + github.com/brianvoe/gofakeit/v7 v7.14.0 + github.com/qyrlabs/test-backend/shared v0.0.0-00010101000000-000000000000 + google.golang.org/grpc v1.78.0 + google.golang.org/protobuf v1.36.11 +) + +require ( + golang.org/x/net v0.47.0 // indirect + golang.org/x/sys v0.38.0 // indirect + golang.org/x/text v0.31.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260120174246-409b4a993575 // indirect +) diff --git a/inventory/go.sum b/inventory/go.sum new file mode 100644 index 0000000..8a01d65 --- /dev/null +++ b/inventory/go.sum @@ -0,0 +1,38 @@ +github.com/brianvoe/gofakeit/v7 v7.14.0 h1:R8tmT/rTDJmD2ngpqBL9rAKydiL7Qr2u3CXPqRt59pk= +github.com/brianvoe/gofakeit/v7 v7.14.0/go.mod h1:QXuPeBw164PJCzCUZVmgpgHJ3Llj49jSLVkKPMtxtxA= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= +go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= +go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8= +go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM= +go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA= +go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI= +go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E= +go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg= +go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM= +go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA= +go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE= +go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs= +golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY= +golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= +golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= +golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= +golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= +gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= +gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260120174246-409b4a993575 h1:vzOYHDZEHIsPYYnaSYo60AqHkJronSu0rzTz/s4quL0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260120174246-409b4a993575/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= +google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc= +google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= diff --git a/inventory/main.go b/inventory/main.go deleted file mode 100644 index 3b2e8d2..0000000 --- a/inventory/main.go +++ /dev/null @@ -1,9 +0,0 @@ -package main - -import ( - "log" -) - -func main() { - log.Println("inventory up") -} diff --git a/shared/go.mod b/shared/go.mod index 43dcdf3..a048230 100644 --- a/shared/go.mod +++ b/shared/go.mod @@ -1,3 +1,15 @@ module github.com/qyrlabs/test-backend/shared go 1.25.6 + +require ( + google.golang.org/grpc v1.78.0 + google.golang.org/protobuf v1.36.11 +) + +require ( + golang.org/x/net v0.47.0 // indirect + golang.org/x/sys v0.38.0 // indirect + golang.org/x/text v0.31.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260120174246-409b4a993575 // indirect +) diff --git a/shared/go.sum b/shared/go.sum new file mode 100644 index 0000000..ae87d8a --- /dev/null +++ b/shared/go.sum @@ -0,0 +1,36 @@ +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= +go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= +go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8= +go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM= +go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA= +go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI= +go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E= +go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg= +go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM= +go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA= +go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE= +go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs= +golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY= +golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= +golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= +golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= +golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= +gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= +gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260120174246-409b4a993575 h1:vzOYHDZEHIsPYYnaSYo60AqHkJronSu0rzTz/s4quL0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260120174246-409b4a993575/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= +google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc= +google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= diff --git a/shared/pkg/proto/inventory/v1/inventory.pb.go b/shared/pkg/proto/inventory/v1/inventory.pb.go new file mode 100644 index 0000000..ef7dd61 --- /dev/null +++ b/shared/pkg/proto/inventory/v1/inventory.pb.go @@ -0,0 +1,879 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11 +// protoc (unknown) +// source: inventory/v1/inventory.proto + +package inventoryv1 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// Category of the Part. +type Category int32 + +const ( + Category_CATEGORY_UNSPECIFIED Category = 0 + Category_CATEGORY_ENGINE Category = 1 + Category_CATEGORY_FUEL Category = 2 + Category_CATEGORY_PORTHOLE Category = 3 + Category_CATEGORY_WING Category = 4 +) + +// Enum value maps for Category. +var ( + Category_name = map[int32]string{ + 0: "CATEGORY_UNSPECIFIED", + 1: "CATEGORY_ENGINE", + 2: "CATEGORY_FUEL", + 3: "CATEGORY_PORTHOLE", + 4: "CATEGORY_WING", + } + Category_value = map[string]int32{ + "CATEGORY_UNSPECIFIED": 0, + "CATEGORY_ENGINE": 1, + "CATEGORY_FUEL": 2, + "CATEGORY_PORTHOLE": 3, + "CATEGORY_WING": 4, + } +) + +func (x Category) Enum() *Category { + p := new(Category) + *p = x + return p +} + +func (x Category) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Category) Descriptor() protoreflect.EnumDescriptor { + return file_inventory_v1_inventory_proto_enumTypes[0].Descriptor() +} + +func (Category) Type() protoreflect.EnumType { + return &file_inventory_v1_inventory_proto_enumTypes[0] +} + +func (x Category) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use Category.Descriptor instead. +func (Category) EnumDescriptor() ([]byte, []int) { + return file_inventory_v1_inventory_proto_rawDescGZIP(), []int{0} +} + +// Request to Get parts. +type GetPartRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Uuid string `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetPartRequest) Reset() { + *x = GetPartRequest{} + mi := &file_inventory_v1_inventory_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetPartRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetPartRequest) ProtoMessage() {} + +func (x *GetPartRequest) ProtoReflect() protoreflect.Message { + mi := &file_inventory_v1_inventory_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetPartRequest.ProtoReflect.Descriptor instead. +func (*GetPartRequest) Descriptor() ([]byte, []int) { + return file_inventory_v1_inventory_proto_rawDescGZIP(), []int{0} +} + +func (x *GetPartRequest) GetUuid() string { + if x != nil { + return x.Uuid + } + return "" +} + +// Response to Get parts. +type GetPartResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Part *Part `protobuf:"bytes,1,opt,name=part,proto3" json:"part,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetPartResponse) Reset() { + *x = GetPartResponse{} + mi := &file_inventory_v1_inventory_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetPartResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetPartResponse) ProtoMessage() {} + +func (x *GetPartResponse) ProtoReflect() protoreflect.Message { + mi := &file_inventory_v1_inventory_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetPartResponse.ProtoReflect.Descriptor instead. +func (*GetPartResponse) Descriptor() ([]byte, []int) { + return file_inventory_v1_inventory_proto_rawDescGZIP(), []int{1} +} + +func (x *GetPartResponse) GetPart() *Part { + if x != nil { + return x.Part + } + return nil +} + +// Request to List parts by filter. +type ListPartsRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Filter *PartsFilter `protobuf:"bytes,1,opt,name=filter,proto3" json:"filter,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListPartsRequest) Reset() { + *x = ListPartsRequest{} + mi := &file_inventory_v1_inventory_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListPartsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListPartsRequest) ProtoMessage() {} + +func (x *ListPartsRequest) ProtoReflect() protoreflect.Message { + mi := &file_inventory_v1_inventory_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListPartsRequest.ProtoReflect.Descriptor instead. +func (*ListPartsRequest) Descriptor() ([]byte, []int) { + return file_inventory_v1_inventory_proto_rawDescGZIP(), []int{2} +} + +func (x *ListPartsRequest) GetFilter() *PartsFilter { + if x != nil { + return x.Filter + } + return nil +} + +// List of found Parts by filter. +type ListPartsResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Parts []*Part `protobuf:"bytes,1,rep,name=parts,proto3" json:"parts,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListPartsResponse) Reset() { + *x = ListPartsResponse{} + mi := &file_inventory_v1_inventory_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListPartsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListPartsResponse) ProtoMessage() {} + +func (x *ListPartsResponse) ProtoReflect() protoreflect.Message { + mi := &file_inventory_v1_inventory_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListPartsResponse.ProtoReflect.Descriptor instead. +func (*ListPartsResponse) Descriptor() ([]byte, []int) { + return file_inventory_v1_inventory_proto_rawDescGZIP(), []int{3} +} + +func (x *ListPartsResponse) GetParts() []*Part { + if x != nil { + return x.Parts + } + return nil +} + +// Part contains all general information. +type Part struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Unique identifier of the part. + Uuid string `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"` + // Name of the part. + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + // Description of the part. + Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` + // Unit price. + Price int64 `protobuf:"varint,4,opt,name=price,proto3" json:"price,omitempty"` + // Quantity available in stock. + StockQuantity int64 `protobuf:"varint,5,opt,name=stock_quantity,json=stockQuantity,proto3" json:"stock_quantity,omitempty"` + // Part category. + Category Category `protobuf:"varint,6,opt,name=category,proto3,enum=inventory.v1.Category" json:"category,omitempty"` + // Part dimensions. + Dimensions *Dimensions `protobuf:"bytes,7,opt,name=dimensions,proto3" json:"dimensions,omitempty"` + // Manufacturer information. + Manufacturer *Manufacturer `protobuf:"bytes,8,opt,name=manufacturer,proto3" json:"manufacturer,omitempty"` + // Tags for quick search. + Tags []string `protobuf:"bytes,9,rep,name=tags,proto3" json:"tags,omitempty"` + // Flexible metadata. + Metadata map[string]*Value `protobuf:"bytes,10,rep,name=metadata,proto3" json:"metadata,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + // Creation timestamp. + CreatedAt *timestamppb.Timestamp `protobuf:"bytes,11,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` + // Last update timestamp. + UpdatedAt *timestamppb.Timestamp `protobuf:"bytes,12,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Part) Reset() { + *x = Part{} + mi := &file_inventory_v1_inventory_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Part) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Part) ProtoMessage() {} + +func (x *Part) ProtoReflect() protoreflect.Message { + mi := &file_inventory_v1_inventory_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Part.ProtoReflect.Descriptor instead. +func (*Part) Descriptor() ([]byte, []int) { + return file_inventory_v1_inventory_proto_rawDescGZIP(), []int{4} +} + +func (x *Part) GetUuid() string { + if x != nil { + return x.Uuid + } + return "" +} + +func (x *Part) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Part) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +func (x *Part) GetPrice() int64 { + if x != nil { + return x.Price + } + return 0 +} + +func (x *Part) GetStockQuantity() int64 { + if x != nil { + return x.StockQuantity + } + return 0 +} + +func (x *Part) GetCategory() Category { + if x != nil { + return x.Category + } + return Category_CATEGORY_UNSPECIFIED +} + +func (x *Part) GetDimensions() *Dimensions { + if x != nil { + return x.Dimensions + } + return nil +} + +func (x *Part) GetManufacturer() *Manufacturer { + if x != nil { + return x.Manufacturer + } + return nil +} + +func (x *Part) GetTags() []string { + if x != nil { + return x.Tags + } + return nil +} + +func (x *Part) GetMetadata() map[string]*Value { + if x != nil { + return x.Metadata + } + return nil +} + +func (x *Part) GetCreatedAt() *timestamppb.Timestamp { + if x != nil { + return x.CreatedAt + } + return nil +} + +func (x *Part) GetUpdatedAt() *timestamppb.Timestamp { + if x != nil { + return x.UpdatedAt + } + return nil +} + +// Filter for details. +// If field is empty - do not filter by this field. +type PartsFilter struct { + state protoimpl.MessageState `protogen:"open.v1"` + Uuids []string `protobuf:"bytes,1,rep,name=uuids,proto3" json:"uuids,omitempty"` + Names []string `protobuf:"bytes,2,rep,name=names,proto3" json:"names,omitempty"` + Categories []Category `protobuf:"varint,3,rep,packed,name=categories,proto3,enum=inventory.v1.Category" json:"categories,omitempty"` + ManufacturerCountries []string `protobuf:"bytes,4,rep,name=manufacturer_countries,json=manufacturerCountries,proto3" json:"manufacturer_countries,omitempty"` + Tags []string `protobuf:"bytes,5,rep,name=tags,proto3" json:"tags,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *PartsFilter) Reset() { + *x = PartsFilter{} + mi := &file_inventory_v1_inventory_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PartsFilter) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PartsFilter) ProtoMessage() {} + +func (x *PartsFilter) ProtoReflect() protoreflect.Message { + mi := &file_inventory_v1_inventory_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PartsFilter.ProtoReflect.Descriptor instead. +func (*PartsFilter) Descriptor() ([]byte, []int) { + return file_inventory_v1_inventory_proto_rawDescGZIP(), []int{5} +} + +func (x *PartsFilter) GetUuids() []string { + if x != nil { + return x.Uuids + } + return nil +} + +func (x *PartsFilter) GetNames() []string { + if x != nil { + return x.Names + } + return nil +} + +func (x *PartsFilter) GetCategories() []Category { + if x != nil { + return x.Categories + } + return nil +} + +func (x *PartsFilter) GetManufacturerCountries() []string { + if x != nil { + return x.ManufacturerCountries + } + return nil +} + +func (x *PartsFilter) GetTags() []string { + if x != nil { + return x.Tags + } + return nil +} + +// Dimenstions of the Part. +type Dimensions struct { + state protoimpl.MessageState `protogen:"open.v1"` + Length float64 `protobuf:"fixed64,1,opt,name=length,proto3" json:"length,omitempty"` + Width float64 `protobuf:"fixed64,2,opt,name=width,proto3" json:"width,omitempty"` + Height float64 `protobuf:"fixed64,3,opt,name=height,proto3" json:"height,omitempty"` + Weight float64 `protobuf:"fixed64,4,opt,name=weight,proto3" json:"weight,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Dimensions) Reset() { + *x = Dimensions{} + mi := &file_inventory_v1_inventory_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Dimensions) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Dimensions) ProtoMessage() {} + +func (x *Dimensions) ProtoReflect() protoreflect.Message { + mi := &file_inventory_v1_inventory_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Dimensions.ProtoReflect.Descriptor instead. +func (*Dimensions) Descriptor() ([]byte, []int) { + return file_inventory_v1_inventory_proto_rawDescGZIP(), []int{6} +} + +func (x *Dimensions) GetLength() float64 { + if x != nil { + return x.Length + } + return 0 +} + +func (x *Dimensions) GetWidth() float64 { + if x != nil { + return x.Width + } + return 0 +} + +func (x *Dimensions) GetHeight() float64 { + if x != nil { + return x.Height + } + return 0 +} + +func (x *Dimensions) GetWeight() float64 { + if x != nil { + return x.Weight + } + return 0 +} + +// Manufacturer of the Part. +type Manufacturer struct { + state protoimpl.MessageState `protogen:"open.v1"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Country string `protobuf:"bytes,2,opt,name=country,proto3" json:"country,omitempty"` + Website string `protobuf:"bytes,3,opt,name=website,proto3" json:"website,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Manufacturer) Reset() { + *x = Manufacturer{} + mi := &file_inventory_v1_inventory_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Manufacturer) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Manufacturer) ProtoMessage() {} + +func (x *Manufacturer) ProtoReflect() protoreflect.Message { + mi := &file_inventory_v1_inventory_proto_msgTypes[7] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Manufacturer.ProtoReflect.Descriptor instead. +func (*Manufacturer) Descriptor() ([]byte, []int) { + return file_inventory_v1_inventory_proto_rawDescGZIP(), []int{7} +} + +func (x *Manufacturer) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Manufacturer) GetCountry() string { + if x != nil { + return x.Country + } + return "" +} + +func (x *Manufacturer) GetWebsite() string { + if x != nil { + return x.Website + } + return "" +} + +// Value represents a typed metadata value. +type Value struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Types that are valid to be assigned to Kind: + // + // *Value_StringValue + // *Value_Int64Value + // *Value_DoubleValue + // *Value_BoolValue + Kind isValue_Kind `protobuf_oneof:"kind"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Value) Reset() { + *x = Value{} + mi := &file_inventory_v1_inventory_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Value) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Value) ProtoMessage() {} + +func (x *Value) ProtoReflect() protoreflect.Message { + mi := &file_inventory_v1_inventory_proto_msgTypes[8] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Value.ProtoReflect.Descriptor instead. +func (*Value) Descriptor() ([]byte, []int) { + return file_inventory_v1_inventory_proto_rawDescGZIP(), []int{8} +} + +func (x *Value) GetKind() isValue_Kind { + if x != nil { + return x.Kind + } + return nil +} + +func (x *Value) GetStringValue() string { + if x != nil { + if x, ok := x.Kind.(*Value_StringValue); ok { + return x.StringValue + } + } + return "" +} + +func (x *Value) GetInt64Value() int64 { + if x != nil { + if x, ok := x.Kind.(*Value_Int64Value); ok { + return x.Int64Value + } + } + return 0 +} + +func (x *Value) GetDoubleValue() float64 { + if x != nil { + if x, ok := x.Kind.(*Value_DoubleValue); ok { + return x.DoubleValue + } + } + return 0 +} + +func (x *Value) GetBoolValue() bool { + if x != nil { + if x, ok := x.Kind.(*Value_BoolValue); ok { + return x.BoolValue + } + } + return false +} + +type isValue_Kind interface { + isValue_Kind() +} + +type Value_StringValue struct { + StringValue string `protobuf:"bytes,1,opt,name=string_value,json=stringValue,proto3,oneof"` +} + +type Value_Int64Value struct { + Int64Value int64 `protobuf:"varint,2,opt,name=int64_value,json=int64Value,proto3,oneof"` +} + +type Value_DoubleValue struct { + DoubleValue float64 `protobuf:"fixed64,3,opt,name=double_value,json=doubleValue,proto3,oneof"` +} + +type Value_BoolValue struct { + BoolValue bool `protobuf:"varint,4,opt,name=bool_value,json=boolValue,proto3,oneof"` +} + +func (*Value_StringValue) isValue_Kind() {} + +func (*Value_Int64Value) isValue_Kind() {} + +func (*Value_DoubleValue) isValue_Kind() {} + +func (*Value_BoolValue) isValue_Kind() {} + +var File_inventory_v1_inventory_proto protoreflect.FileDescriptor + +const file_inventory_v1_inventory_proto_rawDesc = "" + + "\n" + + "\x1cinventory/v1/inventory.proto\x12\finventory.v1\x1a\x1fgoogle/protobuf/timestamp.proto\"$\n" + + "\x0eGetPartRequest\x12\x12\n" + + "\x04uuid\x18\x01 \x01(\tR\x04uuid\"9\n" + + "\x0fGetPartResponse\x12&\n" + + "\x04part\x18\x01 \x01(\v2\x12.inventory.v1.PartR\x04part\"E\n" + + "\x10ListPartsRequest\x121\n" + + "\x06filter\x18\x01 \x01(\v2\x19.inventory.v1.PartsFilterR\x06filter\"=\n" + + "\x11ListPartsResponse\x12(\n" + + "\x05parts\x18\x01 \x03(\v2\x12.inventory.v1.PartR\x05parts\"\xd5\x04\n" + + "\x04Part\x12\x12\n" + + "\x04uuid\x18\x01 \x01(\tR\x04uuid\x12\x12\n" + + "\x04name\x18\x02 \x01(\tR\x04name\x12 \n" + + "\vdescription\x18\x03 \x01(\tR\vdescription\x12\x14\n" + + "\x05price\x18\x04 \x01(\x03R\x05price\x12%\n" + + "\x0estock_quantity\x18\x05 \x01(\x03R\rstockQuantity\x122\n" + + "\bcategory\x18\x06 \x01(\x0e2\x16.inventory.v1.CategoryR\bcategory\x128\n" + + "\n" + + "dimensions\x18\a \x01(\v2\x18.inventory.v1.DimensionsR\n" + + "dimensions\x12>\n" + + "\fmanufacturer\x18\b \x01(\v2\x1a.inventory.v1.ManufacturerR\fmanufacturer\x12\x12\n" + + "\x04tags\x18\t \x03(\tR\x04tags\x12<\n" + + "\bmetadata\x18\n" + + " \x03(\v2 .inventory.v1.Part.MetadataEntryR\bmetadata\x129\n" + + "\n" + + "created_at\x18\v \x01(\v2\x1a.google.protobuf.TimestampR\tcreatedAt\x129\n" + + "\n" + + "updated_at\x18\f \x01(\v2\x1a.google.protobuf.TimestampR\tupdatedAt\x1aP\n" + + "\rMetadataEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12)\n" + + "\x05value\x18\x02 \x01(\v2\x13.inventory.v1.ValueR\x05value:\x028\x01\"\xbc\x01\n" + + "\vPartsFilter\x12\x14\n" + + "\x05uuids\x18\x01 \x03(\tR\x05uuids\x12\x14\n" + + "\x05names\x18\x02 \x03(\tR\x05names\x126\n" + + "\n" + + "categories\x18\x03 \x03(\x0e2\x16.inventory.v1.CategoryR\n" + + "categories\x125\n" + + "\x16manufacturer_countries\x18\x04 \x03(\tR\x15manufacturerCountries\x12\x12\n" + + "\x04tags\x18\x05 \x03(\tR\x04tags\"j\n" + + "\n" + + "Dimensions\x12\x16\n" + + "\x06length\x18\x01 \x01(\x01R\x06length\x12\x14\n" + + "\x05width\x18\x02 \x01(\x01R\x05width\x12\x16\n" + + "\x06height\x18\x03 \x01(\x01R\x06height\x12\x16\n" + + "\x06weight\x18\x04 \x01(\x01R\x06weight\"V\n" + + "\fManufacturer\x12\x12\n" + + "\x04name\x18\x01 \x01(\tR\x04name\x12\x18\n" + + "\acountry\x18\x02 \x01(\tR\acountry\x12\x18\n" + + "\awebsite\x18\x03 \x01(\tR\awebsite\"\x9d\x01\n" + + "\x05Value\x12#\n" + + "\fstring_value\x18\x01 \x01(\tH\x00R\vstringValue\x12!\n" + + "\vint64_value\x18\x02 \x01(\x03H\x00R\n" + + "int64Value\x12#\n" + + "\fdouble_value\x18\x03 \x01(\x01H\x00R\vdoubleValue\x12\x1f\n" + + "\n" + + "bool_value\x18\x04 \x01(\bH\x00R\tboolValueB\x06\n" + + "\x04kind*v\n" + + "\bCategory\x12\x18\n" + + "\x14CATEGORY_UNSPECIFIED\x10\x00\x12\x13\n" + + "\x0fCATEGORY_ENGINE\x10\x01\x12\x11\n" + + "\rCATEGORY_FUEL\x10\x02\x12\x15\n" + + "\x11CATEGORY_PORTHOLE\x10\x03\x12\x11\n" + + "\rCATEGORY_WING\x10\x042\xa8\x01\n" + + "\x10InventoryService\x12F\n" + + "\aGetPart\x12\x1c.inventory.v1.GetPartRequest\x1a\x1d.inventory.v1.GetPartResponse\x12L\n" + + "\tListParts\x12\x1e.inventory.v1.ListPartsRequest\x1a\x1f.inventory.v1.ListPartsResponseBKZIgithub.com/qyrlabs/test-backend/shared/pkg/proto/inventory/v1;inventoryv1b\x06proto3" + +var ( + file_inventory_v1_inventory_proto_rawDescOnce sync.Once + file_inventory_v1_inventory_proto_rawDescData []byte +) + +func file_inventory_v1_inventory_proto_rawDescGZIP() []byte { + file_inventory_v1_inventory_proto_rawDescOnce.Do(func() { + file_inventory_v1_inventory_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_inventory_v1_inventory_proto_rawDesc), len(file_inventory_v1_inventory_proto_rawDesc))) + }) + return file_inventory_v1_inventory_proto_rawDescData +} + +var file_inventory_v1_inventory_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_inventory_v1_inventory_proto_msgTypes = make([]protoimpl.MessageInfo, 10) +var file_inventory_v1_inventory_proto_goTypes = []any{ + (Category)(0), // 0: inventory.v1.Category + (*GetPartRequest)(nil), // 1: inventory.v1.GetPartRequest + (*GetPartResponse)(nil), // 2: inventory.v1.GetPartResponse + (*ListPartsRequest)(nil), // 3: inventory.v1.ListPartsRequest + (*ListPartsResponse)(nil), // 4: inventory.v1.ListPartsResponse + (*Part)(nil), // 5: inventory.v1.Part + (*PartsFilter)(nil), // 6: inventory.v1.PartsFilter + (*Dimensions)(nil), // 7: inventory.v1.Dimensions + (*Manufacturer)(nil), // 8: inventory.v1.Manufacturer + (*Value)(nil), // 9: inventory.v1.Value + nil, // 10: inventory.v1.Part.MetadataEntry + (*timestamppb.Timestamp)(nil), // 11: google.protobuf.Timestamp +} +var file_inventory_v1_inventory_proto_depIdxs = []int32{ + 5, // 0: inventory.v1.GetPartResponse.part:type_name -> inventory.v1.Part + 6, // 1: inventory.v1.ListPartsRequest.filter:type_name -> inventory.v1.PartsFilter + 5, // 2: inventory.v1.ListPartsResponse.parts:type_name -> inventory.v1.Part + 0, // 3: inventory.v1.Part.category:type_name -> inventory.v1.Category + 7, // 4: inventory.v1.Part.dimensions:type_name -> inventory.v1.Dimensions + 8, // 5: inventory.v1.Part.manufacturer:type_name -> inventory.v1.Manufacturer + 10, // 6: inventory.v1.Part.metadata:type_name -> inventory.v1.Part.MetadataEntry + 11, // 7: inventory.v1.Part.created_at:type_name -> google.protobuf.Timestamp + 11, // 8: inventory.v1.Part.updated_at:type_name -> google.protobuf.Timestamp + 0, // 9: inventory.v1.PartsFilter.categories:type_name -> inventory.v1.Category + 9, // 10: inventory.v1.Part.MetadataEntry.value:type_name -> inventory.v1.Value + 1, // 11: inventory.v1.InventoryService.GetPart:input_type -> inventory.v1.GetPartRequest + 3, // 12: inventory.v1.InventoryService.ListParts:input_type -> inventory.v1.ListPartsRequest + 2, // 13: inventory.v1.InventoryService.GetPart:output_type -> inventory.v1.GetPartResponse + 4, // 14: inventory.v1.InventoryService.ListParts:output_type -> inventory.v1.ListPartsResponse + 13, // [13:15] is the sub-list for method output_type + 11, // [11:13] is the sub-list for method input_type + 11, // [11:11] is the sub-list for extension type_name + 11, // [11:11] is the sub-list for extension extendee + 0, // [0:11] is the sub-list for field type_name +} + +func init() { file_inventory_v1_inventory_proto_init() } +func file_inventory_v1_inventory_proto_init() { + if File_inventory_v1_inventory_proto != nil { + return + } + file_inventory_v1_inventory_proto_msgTypes[8].OneofWrappers = []any{ + (*Value_StringValue)(nil), + (*Value_Int64Value)(nil), + (*Value_DoubleValue)(nil), + (*Value_BoolValue)(nil), + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_inventory_v1_inventory_proto_rawDesc), len(file_inventory_v1_inventory_proto_rawDesc)), + NumEnums: 1, + NumMessages: 10, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_inventory_v1_inventory_proto_goTypes, + DependencyIndexes: file_inventory_v1_inventory_proto_depIdxs, + EnumInfos: file_inventory_v1_inventory_proto_enumTypes, + MessageInfos: file_inventory_v1_inventory_proto_msgTypes, + }.Build() + File_inventory_v1_inventory_proto = out.File + file_inventory_v1_inventory_proto_goTypes = nil + file_inventory_v1_inventory_proto_depIdxs = nil +} diff --git a/shared/pkg/proto/inventory/v1/inventory_grpc.pb.go b/shared/pkg/proto/inventory/v1/inventory_grpc.pb.go new file mode 100644 index 0000000..c6a8c63 --- /dev/null +++ b/shared/pkg/proto/inventory/v1/inventory_grpc.pb.go @@ -0,0 +1,167 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.6.0 +// - protoc (unknown) +// source: inventory/v1/inventory.proto + +package inventoryv1 + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.64.0 or later. +const _ = grpc.SupportPackageIsVersion9 + +const ( + InventoryService_GetPart_FullMethodName = "/inventory.v1.InventoryService/GetPart" + InventoryService_ListParts_FullMethodName = "/inventory.v1.InventoryService/ListParts" +) + +// InventoryServiceClient is the client API for InventoryService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +// +// Inventory Service stores and provides info about Parts(details). +type InventoryServiceClient interface { + // Get part info by its UUID. + GetPart(ctx context.Context, in *GetPartRequest, opts ...grpc.CallOption) (*GetPartResponse, error) + // Returns List of Parts by filter. + ListParts(ctx context.Context, in *ListPartsRequest, opts ...grpc.CallOption) (*ListPartsResponse, error) +} + +type inventoryServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewInventoryServiceClient(cc grpc.ClientConnInterface) InventoryServiceClient { + return &inventoryServiceClient{cc} +} + +func (c *inventoryServiceClient) GetPart(ctx context.Context, in *GetPartRequest, opts ...grpc.CallOption) (*GetPartResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetPartResponse) + err := c.cc.Invoke(ctx, InventoryService_GetPart_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *inventoryServiceClient) ListParts(ctx context.Context, in *ListPartsRequest, opts ...grpc.CallOption) (*ListPartsResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ListPartsResponse) + err := c.cc.Invoke(ctx, InventoryService_ListParts_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// InventoryServiceServer is the server API for InventoryService service. +// All implementations must embed UnimplementedInventoryServiceServer +// for forward compatibility. +// +// Inventory Service stores and provides info about Parts(details). +type InventoryServiceServer interface { + // Get part info by its UUID. + GetPart(context.Context, *GetPartRequest) (*GetPartResponse, error) + // Returns List of Parts by filter. + ListParts(context.Context, *ListPartsRequest) (*ListPartsResponse, error) + mustEmbedUnimplementedInventoryServiceServer() +} + +// UnimplementedInventoryServiceServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedInventoryServiceServer struct{} + +func (UnimplementedInventoryServiceServer) GetPart(context.Context, *GetPartRequest) (*GetPartResponse, error) { + return nil, status.Error(codes.Unimplemented, "method GetPart not implemented") +} +func (UnimplementedInventoryServiceServer) ListParts(context.Context, *ListPartsRequest) (*ListPartsResponse, error) { + return nil, status.Error(codes.Unimplemented, "method ListParts not implemented") +} +func (UnimplementedInventoryServiceServer) mustEmbedUnimplementedInventoryServiceServer() {} +func (UnimplementedInventoryServiceServer) testEmbeddedByValue() {} + +// UnsafeInventoryServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to InventoryServiceServer will +// result in compilation errors. +type UnsafeInventoryServiceServer interface { + mustEmbedUnimplementedInventoryServiceServer() +} + +func RegisterInventoryServiceServer(s grpc.ServiceRegistrar, srv InventoryServiceServer) { + // If the following call panics, it indicates UnimplementedInventoryServiceServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&InventoryService_ServiceDesc, srv) +} + +func _InventoryService_GetPart_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetPartRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(InventoryServiceServer).GetPart(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: InventoryService_GetPart_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(InventoryServiceServer).GetPart(ctx, req.(*GetPartRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _InventoryService_ListParts_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListPartsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(InventoryServiceServer).ListParts(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: InventoryService_ListParts_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(InventoryServiceServer).ListParts(ctx, req.(*ListPartsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// InventoryService_ServiceDesc is the grpc.ServiceDesc for InventoryService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var InventoryService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "inventory.v1.InventoryService", + HandlerType: (*InventoryServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetPart", + Handler: _InventoryService_GetPart_Handler, + }, + { + MethodName: "ListParts", + Handler: _InventoryService_ListParts_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "inventory/v1/inventory.proto", +} diff --git a/shared/proto/buf.gen.yaml b/shared/proto/buf.gen.yaml new file mode 100644 index 0000000..c92b75b --- /dev/null +++ b/shared/proto/buf.gen.yaml @@ -0,0 +1,13 @@ +version: v2 +# Удаляет сгенеренное ранее, то что находится в out каждого плагина. +clean: true + +plugins: + - local: ../../bin/protoc-gen-go + out: ../pkg/proto + opt: + - paths=source_relative + - local: ../../bin/protoc-gen-go-grpc + out: ../pkg/proto + opt: + - paths=source_relative \ No newline at end of file diff --git a/shared/proto/buf.lock b/shared/proto/buf.lock new file mode 100644 index 0000000..4f98143 --- /dev/null +++ b/shared/proto/buf.lock @@ -0,0 +1,2 @@ +# Generated by buf. DO NOT EDIT. +version: v2 diff --git a/shared/proto/buf.yaml b/shared/proto/buf.yaml new file mode 100644 index 0000000..551fdf7 --- /dev/null +++ b/shared/proto/buf.yaml @@ -0,0 +1,9 @@ +# For details on buf.yaml configuration, visit https://buf.build/docs/configuration/v2/buf-yaml +version: v2 +lint: + use: + - STANDARD + - COMMENT_ENUM + - COMMENT_MESSAGE + rpc_allow_google_protobuf_empty_requests: true + rpc_allow_google_protobuf_empty_responses: true diff --git a/shared/proto/inventory/v1/inventory.proto b/shared/proto/inventory/v1/inventory.proto new file mode 100644 index 0000000..5b39225 --- /dev/null +++ b/shared/proto/inventory/v1/inventory.proto @@ -0,0 +1,119 @@ +syntax = "proto3"; + +package inventory.v1; + +import "google/protobuf/timestamp.proto"; + +option go_package = "github.com/qyrlabs/test-backend/shared/pkg/proto/inventory/v1;inventoryv1"; + +// Inventory Service stores and provides info about Parts(details). +service InventoryService { + // Get part info by its UUID. + rpc GetPart(GetPartRequest) returns (GetPartResponse); + + // Returns List of Parts by filter. + rpc ListParts(ListPartsRequest) returns (ListPartsResponse); +} + +// Request to Get parts. +message GetPartRequest { + string uuid = 1; +} + +// Response to Get parts. +message GetPartResponse { + Part part = 1; +} + +// Request to List parts by filter. +message ListPartsRequest { + PartsFilter filter = 1; +} + +// List of found Parts by filter. +message ListPartsResponse { + repeated Part parts = 1; +} + +// Part contains all general information. +message Part { + // Unique identifier of the part. + string uuid = 1; + + // Name of the part. + string name = 2; + + // Description of the part. + string description = 3; + + // Unit price. + int64 price = 4; + + // Quantity available in stock. + int64 stock_quantity = 5; + + // Part category. + Category category = 6; + + // Part dimensions. + Dimensions dimensions = 7; + + // Manufacturer information. + Manufacturer manufacturer = 8; + + // Tags for quick search. + repeated string tags = 9; + + // Flexible metadata. + map metadata = 10; + + // Creation timestamp. + google.protobuf.Timestamp created_at = 11; + + // Last update timestamp. + google.protobuf.Timestamp updated_at = 12; +} + +// Filter for details. +// If field is empty - do not filter by this field. +message PartsFilter { + repeated string uuids = 1; + repeated string names = 2; + repeated Category categories = 3; + repeated string manufacturer_countries = 4; + repeated string tags = 5; +} + +// Category of the Part. +enum Category { + CATEGORY_UNSPECIFIED = 0; + CATEGORY_ENGINE = 1; + CATEGORY_FUEL = 2; + CATEGORY_PORTHOLE = 3; + CATEGORY_WING = 4; +} + +// Dimenstions of the Part. +message Dimensions { + double length = 1; + double width = 2; + double height = 3; + double weight = 4; +} + +// Manufacturer of the Part. +message Manufacturer { + string name = 1; + string country = 2; + string website = 3; +} + +// Value represents a typed metadata value. +message Value { + oneof kind { + string string_value = 1; + int64 int64_value = 2; + double double_value = 3; + bool bool_value = 4; + } +}