Repository: Aristat/golang-example-app Branch: master Commit: f7be6c387f0e Files: 106 Total size: 354.4 KB Directory structure: gitextract_na8wnxnj/ ├── .circleci/ │ └── config.yml ├── .gitignore ├── Makefile ├── README.md ├── app/ │ ├── auth/ │ │ ├── middleware.go │ │ └── provider.go │ ├── casbin/ │ │ └── provider.go │ ├── common/ │ │ ├── bcrypt.go │ │ ├── constants.go │ │ ├── graphql.go │ │ └── jaeger.go │ ├── config/ │ │ ├── injector.go │ │ ├── provider.go │ │ └── wire_gen.go │ ├── context/ │ │ └── context.go │ ├── dataloader/ │ │ ├── dataloader.go │ │ └── productitemloader_gen.go │ ├── db/ │ │ ├── db.go │ │ ├── domain/ │ │ │ ├── product.go │ │ │ ├── product_item.go │ │ │ └── user.go │ │ ├── injector.go │ │ ├── provider.go │ │ ├── repo/ │ │ │ ├── provider.go │ │ │ ├── users.go │ │ │ └── users_test.go │ │ └── wire_gen.go │ ├── entrypoint/ │ │ ├── entrypoint.go │ │ ├── entrypoint_test.go │ │ └── provider.go │ ├── graphql/ │ │ ├── graphql.go │ │ └── provider.go │ ├── graphql_resolver/ │ │ ├── injector.go │ │ ├── mock.go │ │ ├── product.go │ │ ├── product_test.go │ │ ├── provider.go │ │ ├── resolver.go │ │ ├── resolver_gen.go │ │ ├── user.go │ │ ├── user_test.go │ │ └── wire_gen.go │ ├── grpc/ │ │ ├── connection.go │ │ ├── manager.go │ │ ├── pool.go │ │ └── provider.go │ ├── http/ │ │ ├── http.go │ │ ├── injector.go │ │ ├── logger.go │ │ ├── provider.go │ │ └── wire_gen.go │ ├── http_routers/ │ │ └── products-router/ │ │ ├── injector.go │ │ ├── manager.go │ │ ├── provider.go │ │ ├── router.go │ │ ├── router_test.go │ │ └── wire_gen.go │ ├── logger/ │ │ ├── injector.go │ │ ├── logger.go │ │ ├── middleware.go │ │ ├── mock.go │ │ ├── provider.go │ │ ├── wire_gen.go │ │ └── zap.go │ ├── provider/ │ │ └── provider.go │ └── tracing/ │ ├── jaeger.go │ └── provider.go ├── cmd/ │ ├── daemon/ │ │ └── daemon.go │ ├── health-check-service/ │ │ └── health_check_service.go │ ├── jwt/ │ │ ├── jwt.go │ │ └── token.go │ ├── migrate/ │ │ └── migrate.go │ ├── product-service/ │ │ ├── nats_service.go │ │ └── product_service.go │ └── root.go ├── dbconfig.yml ├── docker/ │ └── app/ │ ├── Dockerfile │ └── files/ │ └── docker/ │ └── bin/ │ └── entrypoint.sh ├── docker-compose.yml ├── generated/ │ ├── graphql/ │ │ ├── generated.go │ │ └── models_gen.go │ └── resources/ │ └── proto/ │ ├── health_checks/ │ │ ├── health_checks.pb.go │ │ └── health_checks_grpc.pb.go │ └── products/ │ ├── products.pb.go │ └── products_grpc.pb.go ├── go.mod ├── go.sum ├── gqlgen.yml ├── main.go ├── prototool.yaml ├── resources/ │ ├── casbin/ │ │ ├── model.conf │ │ └── policy.csv │ ├── configs/ │ │ ├── development.yaml │ │ └── docker_development.yaml │ ├── graphql/ │ │ ├── products.graphql │ │ ├── root.graphql │ │ └── user.graphql │ ├── keys/ │ │ └── local/ │ │ ├── private_key.pem │ │ └── public_key.pem │ ├── migrations/ │ │ ├── 20181215164636-create_users.sql │ │ └── 20181216210607-records.sql │ ├── proto/ │ │ ├── health_checks/ │ │ │ └── health_checks.proto │ │ └── products/ │ │ └── products.proto │ └── templates/ │ └── helpers/ │ └── errors.html └── scripts/ ├── docker-compose-start.sh └── remove_docker_containers.sh ================================================ FILE CONTENTS ================================================ ================================================ FILE: .circleci/config.yml ================================================ version: 2.1 jobs: test: docker: - image: cimg/go:1.17 working_directory: ~/golang-example-app steps: - checkout - run: name: "Setup APP_WD" command: echo 'export APP_WD="$(cd ${CIRCLE_WORKING_DIRECTORY}; pwd)/resources"' >> $BASH_ENV - run: name: Fetch dependencies command: go mod download - run: name: Test command: go test ./... build: docker: - image: cimg/go:1.17 working_directory: ~/golang-example-app steps: - checkout - run: name: Fetch dependencies command: go mod download - run: name: Building command: | VERSION=${CIRCLE_TAG} GOOS=linux GOARCH=amd64 go build -ldflags "-X main.Version=${VERSION}" -o bin/app-${VERSION}-linux-amd64 main.go GOOS=darwin GOARCH=amd64 go build -ldflags "-X main.Version=${VERSION}" -o bin/app-${VERSION}-darwin-amd64 main.go - persist_to_workspace: root: . paths: - bin publish-github-release: docker: - image: cibuilds/github:0.13 steps: - attach_workspace: at: ~/golang-example-app - run: name: "Publish Release on GitHub" command: | VERSION=${CIRCLE_TAG} ghr -t ${GITHUB_TOKEN} -u ${CIRCLE_PROJECT_USERNAME} -r ${CIRCLE_PROJECT_REPONAME} -c ${CIRCLE_SHA1} -delete ${VERSION} ~/golang-example-app/bin workflows: version: 2 main: jobs: - test release: jobs: - build: filters: branches: ignore: /.*/ tags: only: /^v\d+\.\d+\.\d+.*/ - publish-github-release: requires: - build filters: branches: ignore: /.*/ tags: only: /^v\d+\.\d+\.\d+.*/ ================================================ FILE: .gitignore ================================================ # Binaries for programs and plugins *.exe *.dll *.so *.dylib # Test binary, build with `go test -c` *.test # Output of the go coverage tool, specifically when used with LiteIDE *.out # Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736 .glide/ vendor/ .idea/ artifacts/ coverage.out .DS_Store ================================================ FILE: Makefile ================================================ GO_DIR ?= $(shell pwd) GO_PKG ?= $(shell go list -e -f "{{ .ImportPath }}") GOOS ?= $(shell go env GOOS || echo linux) GOARCH ?= $(shell go env GOARCH || echo amd64) CGO_ENABLED ?= 0 DOCKER_IMAGE ?= unknown TAG ?= unknown CACHE_TAG ?= unknown_cache DATABASE_URL ?= golang_example_development REMOVE_CONTAINERS ?= OFF define build_resources find "$(GO_DIR)/resources" -maxdepth 1 -mindepth 1 -exec cp -R -f {} $(GO_DIR)/artifacts/${1} \; endef install: init ## install cli tools go get -v github.com/rubenv/sql-migrate/... ;\ go get -u github.com/google/wire/cmd/wire ;\ go get -u github.com/vektah/dataloaden ; init: ## init packages mkdir -p artifacts ;\ rm -rf artifacts/* start: ## start daemon on development mode ./artifacts/bin daemon -c ./artifacts/configs/development.yaml -d dependencies: ## generate dependencies go mod download gqlgen-generate: ## generate graphql resolver go run github.com/99designs/gqlgen prototool-generate: ## generate proto file protoc --go_out=generated --go_opt=paths=source_relative --go-grpc_out=generated --go-grpc_opt=paths=source_relative resources/proto/products/products.proto protoc --go_out=generated --go_opt=paths=source_relative --go-grpc_out=generated --go-grpc_opt=paths=source_relative resources/proto/health_checks/health_checks.proto build: init ## build binary file $(call build_resources) ;\ GOOS=${GOOS} CGO_ENABLED=${CGO_ENABLED} GOARCH=${GOARCH} \ go build -ldflags "-X $(GO_PKG)/cmd/version.appVersion=$(TAG)-$$(date -u +%Y%m%d%H%M)" -o "$(GO_DIR)/artifacts/bin" main.go docker-image: ## build docker image REMOVE_CONTAINERS=${REMOVE_CONTAINERS} DOCKER_IMAGE=${DOCKER_IMAGE} ./scripts/remove_docker_containers.sh docker rmi ${DOCKER_IMAGE}:${TAG} -f || true ;\ docker build --cache-from ${DOCKER_IMAGE}:${CACHE_TAG} -f "${GO_DIR}/docker/app/Dockerfile" -t ${DOCKER_IMAGE}:${TAG} ${GO_DIR} test: ## test application with race go test -v ./... coverage: ## test coverage go test -coverprofile=coverage.out ./... go tool cover -html coverage.out createdb: ## create database createdb $(DATABASE_URL) dropdb: ## drop database dropdb $(DATABASE_URL) .PHONY: install init dependencies gqlgen-generate prototool-generate help: @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' .DEFAULT_GOAL := help ================================================ FILE: README.md ================================================  # Golang Example Application # Table of Contents - [Overview](#overview) - [Package list](#package-list) - [Installing](#installing) * [Local environment](#local-environment) * [Docker environment](#docker-enviroment) - [Run services](#run-services) * [Start in local](#start-in-local-machine) * [Start in docker](#start-in-docker) - [Getting started](#getting-started) * [Jaeger](#jaeger) * [Http with gRPC](#http-example-with-grpc) * [Graphql with gRPC](#graphql-example-with-grpc) - [Deprecate version](#deprecated-version) - [Testing](#testing) # Overview This is an example golang application. Commands list: 1. Daemon - main service 2. Product service - service that returns Product, an example of gRPC client/server interaction 3. Health check service - this service is needed to show how convenient to understand on which of the services an error occurred in jaeger 4. Migrate - commands for migration 5. JWT - commands for generate JWT token # Package list Packages which use in this example project 1. [sql-migrate](https://github.com/rubenv/sql-migrate) - SQL migrations 2. [wire](https://github.com/google/wire) - dependency Injection 3. [viper](https://github.com/spf13/viper) - environment configuration 4. [cobra](https://github.com/spf13/cobra) - create commands 5. [cast](https://github.com/spf13/cast) - easy casting from one type to another 6. [gorm](https://github.com/jinzhu/gorm) - database ORM 7. [zap](https://github.com/uber-go/zap) - logger 8. [mux](https://github.com/gorilla/mux) - http router 9. [nats-streaming](https://github.com/nats-io/stan.go) - NATS Streaming System 10. [gqlgen](https://github.com/99designs/gqlgen) - graphql server library 11. [protobuf](https://pkg.go.dev/google.golang.org/protobuf) - Google's data interchange format 12. [grpc](google.golang.org/grpc) - RPC framework 13. [opentelemetry](https://github.com/open-telemetry/opentelemetry-go) - OpenTelemetry 14. [jaeger](https://github.com/uber/jaeger-client-go) - Jaeger Bindings for Go OpenTelemetry API 15. [casbin](https://github.com/casbin/casbin) - Supports access control 16. [dataloaden](https://github.com/vektah/dataloaden) - DataLoader for graphql 17. [nats](https://github.com/nats-io/nats.go) - Golang client for NATS, the cloud native messaging system # Installing Install the Golang and GO environment ```$xslt https://golang.org/doc/install ``` Install [Postgresql](https://www.postgresql.org/download) (if you want to run locally) Clone repository ```$xslt git clone git@github.com:Aristat/golang-example-app.git (go get) ``` ## Local environment Install Golang packages without modules ```$xslt make install ``` Install database ```$xslt make createdb ``` Sql migrations ```$xslt sql-migrate up ``` Install Golang dependencies ```$xslt make dependencies ``` Generate artifacts(binary files and configs) ```$xslt make build ``` Packages for proto generator ```$xslt https://grpc.io/docs/languages/go/quickstart/#prerequisites ``` Set APP_WD if you start to use html templates or path to ssh keys or run `make test` ```$xslt export APP_WD=go_path to project_path/resources or project_path/artifacts ``` ## Docker environment Generate docker image ```$xslt DOCKER_IMAGE=golang-example-app TAG=development make docker-image ``` # Run services ## Start in local machine Up jaeger in docker-compose or disable Jaeger(and rebuild binary file) in `resources/configs/*.yaml` ```$xslt docker-compose up jaeger ``` Start daemon (main service) ```$xslt make start ``` or ```$xslt ./artifacts/bin daemon -c ./artifacts/configs/development.yaml -d ``` Start product service ```$xslt ./artifacts/bin product-service -c ./artifacts/configs/development.yaml -d ``` Start health-check service ```$xslt ./artifacts/bin health-check -c ./artifacts/configs/development.yaml -d ``` ## Start in docker #### Run this commands ```$xslt docker-compose rm # Remove previous containers REMOVE_CONTAINERS=on DOCKER_IMAGE=golang-example-app TAG=development make docker-image # Generate new docker image docker-compose up ``` #### or run script ```$xslt ./scripts/docker-compose-start.sh ``` # Getting Started ## Jaeger ```$xslt http://localhost:16686 ``` ## Http example with gRPC ```$xslt http://localhost:9096/products_grpc ``` ## Http example with Nats Streaming ```$xslt http://localhost:9096/products_nats ``` ## Http example with graceful shutdown(long request, you can check the server shutdown) ```$xslt http://localhost:9096/products_slowly ``` ## Graphql example with gRPC Graphql [client](https://github.com/prisma-labs/graphql-playground) for testing. End-point `http://localhost:9096/query`. Generate JWT for Graphql authorization ```$xslt ./artifacts/bin jwt token --key='./artifacts/keys/local/private_key.pem' --fields='{"sub": "owner", "iss": "test-service"}' ``` Set JWT token in headers ```$xslt { "Authorization": "bearer token" } ``` Example query ``` query oneUser { users { one(email: "test@gmail.com") { email id } } } ``` Example query with data loader ``` query allProducts { products { list { products { id productItems { id name } } } } } ``` Example mutation ``` mutation createUser { users { createUser(email: "test1@gmail.com", password: "123456789") { id email } } } ``` # Testing ``` ➜ make test ``` ================================================ FILE: app/auth/middleware.go ================================================ package auth import ( "io/ioutil" "net/http" "strings" "github.com/aristat/golang-example-app/app/common" "github.com/aristat/golang-example-app/app/logger" "github.com/aristat/golang-example-app/app/entrypoint" "github.com/golang-jwt/jwt" appContext "github.com/aristat/golang-example-app/app/context" "github.com/pkg/errors" ) const prefix = "app.auth" const defaultSubject = "anonymous" const defaultServiceName = "unknown" const defaultServiceId = 0 var errPublicNotFound = errors.New("public key not found for issuer") var errAuthJWT = errors.New("Authentication failed, JWT invalid") // CustomClaims type CustomClaims struct { jwt.StandardClaims } // Config type Config struct { Services map[string]uint64 RelativePath string } // Middleware type Middleware struct { keys keys cfg Config log logger.Logger } // keys type keys struct { publicPemKey []byte privatePemKey []byte } // Handler for check Bearer token func (m Middleware) JWTHandler(next http.Handler) http.Handler { fn := func(w http.ResponseWriter, r *http.Request) { var ( token string bearerToken = strings.Split(r.Header.Get("Authorization"), " ") subject = defaultSubject claims *CustomClaims ok bool ) if len(bearerToken) > 1 { token = bearerToken[1] } else { common.SendGraphqlErrorf(w, http.StatusUnauthorized, "Not found authorization token") return } t, err := jwt.ParseWithClaims(token, &CustomClaims{}, func(t *jwt.Token) (interface{}, error) { if _, ok := t.Claims.(*CustomClaims); ok { return jwt.ParseRSAPublicKeyFromPEM(m.keys.publicPemKey) } m.log.Error("Public key not found: %s", logger.Args(errPublicNotFound.Error())) return nil, errPublicNotFound }) if err != nil { m.log.Error("Parse error: %s", logger.Args(err.Error())) common.SendGraphqlErrorf(w, http.StatusUnauthorized, err.Error()) return } if t.Valid { if claims, ok = t.Claims.(*CustomClaims); ok { subject = claims.Subject } } else { m.log.Error("Validation Error: %s", logger.Args(errAuthJWT.Error())) common.SendGraphqlErrorf(w, http.StatusUnauthorized, errAuthJWT.Error()) return } serviceName, serviceID := m.Service(claims) r = r.WithContext(appContext.NewContext(r.Context(), appContext.Mapping{ Subject: subject, ServiceId: serviceID, ServiceName: serviceName, })) next.ServeHTTP(w, r) } return http.HandlerFunc(fn) } // Service returns service data as pair of name and id func (m Middleware) Service(claims *CustomClaims) (string, uint64) { if claims == nil { return defaultServiceName, defaultServiceId } issuer := claims.Issuer if id, ok := m.cfg.Services[issuer]; ok { return claims.Issuer, id } return defaultServiceName, defaultServiceId } func NewMiddleware(cfg Config, log logger.Logger) (*Middleware, func(), error) { rPath := strings.Trim(cfg.RelativePath, "/") log = log.WithFields(logger.Fields{"service": prefix}) m := &Middleware{cfg: cfg, log: log} publicKey, err := ioutil.ReadFile(entrypoint.WorkDir() + "/" + rPath + "/public_key.pem") if err != nil { return nil, func() {}, err } m.keys.publicPemKey = publicKey m.keys.privatePemKey, err = ioutil.ReadFile(entrypoint.WorkDir() + "/" + rPath + "/private_key.pem") if err != nil { return nil, func() {}, err } return m, func() {}, nil } func NewTestMiddleware(log logger.Logger) (*Middleware, func(), error) { log = log.WithFields(logger.Fields{"service": prefix}) private := `` public := `` middleware := &Middleware{ cfg: Config{}, keys: keys{ publicPemKey: []byte(public), privatePemKey: []byte(private), }, log: log, } return middleware, func() {}, nil } ================================================ FILE: app/auth/provider.go ================================================ package auth import ( "github.com/aristat/golang-example-app/app/logger" "github.com/google/wire" "github.com/spf13/viper" ) // ProviderCfg func ProviderCfg(cfg *viper.Viper) (Config, func(), error) { c := Config{} e := cfg.UnmarshalKey("auth", &c) return c, func() {}, e } // Provider func Provider(cfg Config, logger logger.Logger) (*Middleware, func(), error) { return NewMiddleware(cfg, logger) } // ProviderTest func ProviderTest(logger logger.Logger) (*Middleware, func(), error) { return NewTestMiddleware(logger) } var ( ProviderProductionSet = wire.NewSet(Provider, ProviderCfg) ProviderTestSet = wire.NewSet(ProviderTest) ) ================================================ FILE: app/casbin/provider.go ================================================ package casbin import ( "github.com/aristat/golang-example-app/app/entrypoint" "github.com/casbin/casbin" fileadapter "github.com/casbin/casbin/persist/file-adapter" "github.com/google/wire" ) func Provider() (*casbin.Enforcer, func(), error) { wd := entrypoint.WorkDir() enf := casbin.NewEnforcer(wd+"/casbin/model.conf", wd+"/casbin/policy.csv") return enf, func() {}, nil } func ProviderTest() (*casbin.Enforcer, func(), error) { model := ` [request_definition] r = sub, obj, act [policy_definition] p = sub, obj, act [role_definition] g = _, _ [policy_effect] e = some(where (p.eft == allow)) [matchers] m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act ` policy := ` p, reader, users, read p, owner, users, write g, reader, anonymous g, owner, reader ` enf := casbin.NewEnforcer(casbin.NewModel(model), fileadapter.NewAdapter(policy)) return enf, func() {}, nil } var ( ProviderProductionSet = wire.NewSet(Provider) ProviderTestSet = wire.NewSet(ProviderTest) ) ================================================ FILE: app/common/bcrypt.go ================================================ package common import "golang.org/x/crypto/bcrypt" func HashPassword(password string, cost int) (string, error) { bytes, err := bcrypt.GenerateFromPassword([]byte(password), cost) return string(bytes), err } func CheckPasswordHash(password, hash string) bool { err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password)) return err == nil } ================================================ FILE: app/common/constants.go ================================================ package common const ( SrvProducts = "products" ) ================================================ FILE: app/common/graphql.go ================================================ package common import ( "encoding/json" "fmt" "net/http" "github.com/vektah/gqlparser/v2/gqlerror" "github.com/99designs/gqlgen/graphql" ) func SendGraphqlError(w http.ResponseWriter, code int, errors gqlerror.List) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(code) b, err := json.Marshal(&graphql.Response{Errors: errors}) if err != nil { panic(err) } w.Write(b) } func SendGraphqlErrorf(w http.ResponseWriter, code int, format string, args ...interface{}) { SendGraphqlError(w, code, gqlerror.List{{Message: fmt.Sprintf(format, args...)}}) } ================================================ FILE: app/common/jaeger.go ================================================ package common import ( "github.com/aristat/golang-example-app/app/tracing" "go.opentelemetry.io/otel/exporters/jaeger" "go.opentelemetry.io/otel/sdk/resource" tracesdk "go.opentelemetry.io/otel/sdk/trace" semconv "go.opentelemetry.io/otel/semconv/v1.4.0" "github.com/spf13/viper" ) func GenerateTracerForTestClient(serviceName string, cfg *viper.Viper) (*tracesdk.TracerProvider, error) { configuration := tracing.Configuration{} err := cfg.UnmarshalKey("tracing.jaeger", &configuration) if err != nil { return nil, err } exp, err := jaeger.New( jaeger.WithAgentEndpoint( jaeger.WithAgentHost(configuration.AgentHost), jaeger.WithAgentPort(configuration.AgentPort), ), ) if err != nil { return nil, err } tp := tracesdk.NewTracerProvider( tracesdk.WithBatcher(exp), tracesdk.WithResource(resource.NewWithAttributes( semconv.SchemaURL, semconv.ServiceNameKey.String(serviceName), )), ) return tp, nil } ================================================ FILE: app/config/injector.go ================================================ // +build wireinject package config import ( "github.com/google/wire" "github.com/spf13/viper" ) // Build returns spf13/viper instance with resolved dependencies func Build() (*viper.Viper, func(), error) { panic(wire.Build(Provider)) } ================================================ FILE: app/config/provider.go ================================================ package config import ( "github.com/aristat/golang-example-app/app/entrypoint" "github.com/google/wire" "github.com/spf13/viper" ) // Provider returns spf13/viper instance with resolved dependencies func Provider() (*viper.Viper, func(), error) { v := entrypoint.Viper() for _, key := range v.AllKeys() { val := v.Get(key) v.Set(key, val) } return v, func() {}, nil } var ProviderSet = wire.NewSet(Provider) ================================================ FILE: app/config/wire_gen.go ================================================ // Code generated by Wire. DO NOT EDIT. //go:generate go run github.com/google/wire/cmd/wire //go:build !wireinject // +build !wireinject package config import ( "github.com/spf13/viper" ) // Injectors from injector.go: // Build returns spf13/viper instance with resolved dependencies func Build() (*viper.Viper, func(), error) { viperViper, cleanup, err := Provider() if err != nil { return nil, nil, err } return viperViper, func() { cleanup() }, nil } ================================================ FILE: app/context/context.go ================================================ package context import ( "context" "github.com/mitchellh/mapstructure" ) const prefix = "app.context" // Manager type Manager struct { mapping *Mapping ctx context.Context } func (m *Manager) ToMapping() *Mapping { return &Mapping{ Subject: m.mapping.Subject, ServiceId: m.mapping.ServiceId, ServiceName: m.mapping.ServiceName, } } // NewManager func NewManager(ctx context.Context) (*Manager, error) { m := &Manager{ctx: ctx} mapping := &Mapping{} config := &mapstructure.DecoderConfig{TagName: "json", Result: &mapping} decoder, _ := mapstructure.NewDecoder(config) err := decoder.Decode(ctx.Value(prefix)) if err != nil { return nil, err } m.mapping = mapping return m, nil } // Mapping type Mapping struct { Subject string ServiceId uint64 `json:"service_id"` ServiceName string `json:"service_name"` } // NewContext func NewContext(ctx context.Context, m Mapping) context.Context { return context.WithValue(ctx, prefix, map[string]interface{}{ "subject": m.Subject, "service_id": m.ServiceId, "service_name": m.ServiceName, }) } ================================================ FILE: app/dataloader/dataloader.go ================================================ //go:generate go run github.com/vektah/dataloaden ProductItemLoader int []*github.com/aristat/golang-example-app/generated/domain.ProductItem package dataloader import ( "context" "fmt" "math/rand" "net/http" "strconv" "strings" "time" "github.com/aristat/golang-example-app/app/db/domain" ) type ctxKeyType struct{ name string } var ctxKey = ctxKeyType{"userDataLoader"} type loaders struct { ProductItemsByProduct *ProductItemLoader } func LoaderMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ldrs := loaders{} // set this to zero what happens without data loading wait := 250 * time.Microsecond ldrs.ProductItemsByProduct = &ProductItemLoader{ wait: wait, maxBatch: 100, fetch: func(keys []int) ([][]*domain.ProductItem, []error) { fmt.Println("ProductItems Start Fetch") var keySQL []string for _, key := range keys { keySQL = append(keySQL, strconv.Itoa(key)) } fmt.Printf("SELECT * FROM product_items WHERE product_id IN (%s)\n", strings.Join(keySQL, ",")) time.Sleep(5 * time.Millisecond) productItems := make([][]*domain.ProductItem, len(keys)) errors := make([]error, len(keys)) for i := range keys { productItems[i] = []*domain.ProductItem{ {ID: 1, Name: "item " + strconv.Itoa(rand.Int()%20+20)}, {ID: 2, Name: "item " + strconv.Itoa(rand.Int()%20+20)}, } } return productItems, errors }, } dlCtx := context.WithValue(r.Context(), ctxKey, ldrs) next.ServeHTTP(w, r.WithContext(dlCtx)) }) } func CtxLoaders(ctx context.Context) loaders { return ctx.Value(ctxKey).(loaders) } ================================================ FILE: app/dataloader/productitemloader_gen.go ================================================ // Code generated by github.com/vektah/dataloaden, DO NOT EDIT. package dataloader import ( "sync" "time" "github.com/aristat/golang-example-app/app/db/domain" ) // ProductItemLoaderConfig captures the config to create a new ProductItemLoader type ProductItemLoaderConfig struct { // Fetch is a method that provides the data for the loader Fetch func(keys []int) ([][]*domain.ProductItem, []error) // Wait is how long wait before sending a batch Wait time.Duration // MaxBatch will limit the maximum number of keys to send in one batch, 0 = not limit MaxBatch int } // NewProductItemLoader creates a new ProductItemLoader given a fetch, wait, and maxBatch func NewProductItemLoader(config ProductItemLoaderConfig) *ProductItemLoader { return &ProductItemLoader{ fetch: config.Fetch, wait: config.Wait, maxBatch: config.MaxBatch, } } // ProductItemLoader batches and caches requests type ProductItemLoader struct { // this method provides the data for the loader fetch func(keys []int) ([][]*domain.ProductItem, []error) // how long to done before sending a batch wait time.Duration // this will limit the maximum number of keys to send in one batch, 0 = no limit maxBatch int // INTERNAL // lazily created cache cache map[int][]*domain.ProductItem // the current batch. keys will continue to be collected until timeout is hit, // then everything will be sent to the fetch method and out to the listeners batch *productItemLoaderBatch // mutex to prevent races mu sync.Mutex } type productItemLoaderBatch struct { keys []int data [][]*domain.ProductItem error []error closing bool done chan struct{} } // Load a ProductItem by key, batching and caching will be applied automatically func (l *ProductItemLoader) Load(key int) ([]*domain.ProductItem, error) { return l.LoadThunk(key)() } // LoadThunk returns a function that when called will block waiting for a ProductItem. // This method should be used if you want one goroutine to make requests to many // different data loaders without blocking until the thunk is called. func (l *ProductItemLoader) LoadThunk(key int) func() ([]*domain.ProductItem, error) { l.mu.Lock() if it, ok := l.cache[key]; ok { l.mu.Unlock() return func() ([]*domain.ProductItem, error) { return it, nil } } if l.batch == nil { l.batch = &productItemLoaderBatch{done: make(chan struct{})} } batch := l.batch pos := batch.keyIndex(l, key) l.mu.Unlock() return func() ([]*domain.ProductItem, error) { <-batch.done var data []*domain.ProductItem if pos < len(batch.data) { data = batch.data[pos] } var err error // its convenient to be able to return a single error for everything if len(batch.error) == 1 { err = batch.error[0] } else if batch.error != nil { err = batch.error[pos] } if err == nil { l.mu.Lock() l.unsafeSet(key, data) l.mu.Unlock() } return data, err } } // LoadAll fetches many keys at once. It will be broken into appropriate sized // sub batches depending on how the loader is configured func (l *ProductItemLoader) LoadAll(keys []int) ([][]*domain.ProductItem, []error) { results := make([]func() ([]*domain.ProductItem, error), len(keys)) for i, key := range keys { results[i] = l.LoadThunk(key) } productItems := make([][]*domain.ProductItem, len(keys)) errors := make([]error, len(keys)) for i, thunk := range results { productItems[i], errors[i] = thunk() } return productItems, errors } // LoadAllThunk returns a function that when called will block waiting for a ProductItems. // This method should be used if you want one goroutine to make requests to many // different data loaders without blocking until the thunk is called. func (l *ProductItemLoader) LoadAllThunk(keys []int) func() ([][]*domain.ProductItem, []error) { results := make([]func() ([]*domain.ProductItem, error), len(keys)) for i, key := range keys { results[i] = l.LoadThunk(key) } return func() ([][]*domain.ProductItem, []error) { productItems := make([][]*domain.ProductItem, len(keys)) errors := make([]error, len(keys)) for i, thunk := range results { productItems[i], errors[i] = thunk() } return productItems, errors } } // Prime the cache with the provided key and value. If the key already exists, no change is made // and false is returned. // (To forcefully prime the cache, clear the key first with loader.clear(key).prime(key, value).) func (l *ProductItemLoader) Prime(key int, value []*domain.ProductItem) bool { l.mu.Lock() var found bool if _, found = l.cache[key]; !found { // make a copy when writing to the cache, its easy to pass a pointer in from a loop var // and end up with the whole cache pointing to the same value. cpy := make([]*domain.ProductItem, len(value)) copy(cpy, value) l.unsafeSet(key, cpy) } l.mu.Unlock() return !found } // Clear the value at key from the cache, if it exists func (l *ProductItemLoader) Clear(key int) { l.mu.Lock() delete(l.cache, key) l.mu.Unlock() } func (l *ProductItemLoader) unsafeSet(key int, value []*domain.ProductItem) { if l.cache == nil { l.cache = map[int][]*domain.ProductItem{} } l.cache[key] = value } // keyIndex will return the location of the key in the batch, if its not found // it will add the key to the batch func (b *productItemLoaderBatch) keyIndex(l *ProductItemLoader, key int) int { for i, existingKey := range b.keys { if key == existingKey { return i } } pos := len(b.keys) b.keys = append(b.keys, key) if pos == 0 { go b.startTimer(l) } if l.maxBatch != 0 && pos >= l.maxBatch-1 { if !b.closing { b.closing = true l.batch = nil go b.end(l) } } return pos } func (b *productItemLoaderBatch) startTimer(l *ProductItemLoader) { time.Sleep(l.wait) l.mu.Lock() // we must have hit a batch limit and are already finalizing this batch if b.closing { l.mu.Unlock() return } l.batch = nil l.mu.Unlock() b.end(l) } func (b *productItemLoaderBatch) end(l *ProductItemLoader) { b.data, b.error = l.fetch(b.keys) close(b.done) } ================================================ FILE: app/db/db.go ================================================ package db import ( "context" "time" "github.com/jinzhu/gorm" "github.com/aristat/golang-example-app/app/logger" _ "github.com/lib/pq" ) const prefix = "app.db" // Config type Config struct { URL string MaxOpenConns int MaxIdleConns int ConnMaxLifetime time.Duration LogLevel logger.Level } // Http type Manager struct { ctx context.Context cfg Config log logger.Logger DB *gorm.DB } // New func New(ctx context.Context, log logger.Logger, cfg Config, db *gorm.DB) *Manager { return &Manager{ ctx: ctx, cfg: cfg, log: log.WithFields(logger.Fields{"service": prefix}), DB: db, } } ================================================ FILE: app/db/domain/product.go ================================================ package domain type Product struct { ID int Name string productItems []ProductItem } ================================================ FILE: app/db/domain/product_item.go ================================================ package domain type ProductItem struct { ID int Name string } ================================================ FILE: app/db/domain/user.go ================================================ package domain type User struct { ID int `gorm:"column:id"` Email string `gorm:"column:email"` EncryptedPassword string `gorm:"column:encrypted_password"` } // UsersRepo interface type UsersRepo interface { CreateUser(email string, encryptPassword string) (*User, error) FindByEmail(email string) (*User, error) } ================================================ FILE: app/db/injector.go ================================================ // +build wireinject package db import ( "github.com/aristat/golang-example-app/app/provider" "github.com/google/wire" ) func Build() (*Manager, func(), error) { panic(wire.Build(ProviderProductionSet, provider.AwareProductionSet)) } func BuildTest() (*Manager, func(), error) { panic(wire.Build(ProviderTestSet, provider.AwareTestSet)) } ================================================ FILE: app/db/provider.go ================================================ package db import ( "context" "database/sql" "github.com/jinzhu/gorm" "github.com/aristat/golang-example-app/app/logger" "github.com/google/wire" mocket "github.com/selvatico/go-mocket" "github.com/spf13/viper" ) // Cfg func Cfg(cfg *viper.Viper) (Config, func(), error) { c := Config{LogLevel: logger.LevelDebug} e := cfg.UnmarshalKey("db", &c) if e != nil { return c, func() {}, e } return c, func() {}, nil } // CfgTest func CfgTest() (Config, func(), error) { return Config{}, func() {}, nil } // ProviderGORM func ProviderGORM(ctx context.Context, log logger.Logger, cfg Config) (*gorm.DB, func(), error) { log = log.WithFields(logger.Fields{"service": prefix}) db, err := gorm.Open("postgres", cfg.URL) db.DB().SetMaxOpenConns(cfg.MaxOpenConns) db.DB().SetMaxIdleConns(cfg.MaxIdleConns) db.DB().SetConnMaxLifetime(cfg.ConnMaxLifetime) if cfg.LogLevel == logger.LevelDebug { db.LogMode(true) } cleanup := func() { if db != nil { _ = db.Close() } log.Info("Closed db connections") } return db, cleanup, err } // ProviderGORMTest for test, using go-mocket func ProviderGORMTest() (*gorm.DB, func(), error) { var db *gorm.DB cleanup := func() { if db != nil { _ = db.Close() } } mocket.Catcher.Register() mocket.Catcher.Logging = true sqlDB, err := sql.Open(mocket.DriverName, "gorm") if err != nil { return db, cleanup, err } db, err = gorm.Open("postgres", sqlDB) return db, cleanup, err } // Provider func Provider(ctx context.Context, log logger.Logger, cfg Config, db *gorm.DB) (*Manager, func(), error) { g := New(ctx, log, cfg, db) return g, func() {}, nil } var ( ProviderProductionSet = wire.NewSet(Provider, ProviderGORM, Cfg) ProviderTestSet = wire.NewSet(Provider, ProviderGORMTest, CfgTest) ) ================================================ FILE: app/db/repo/provider.go ================================================ package repo import ( "github.com/aristat/golang-example-app/app/db/domain" "github.com/google/wire" ) // Repo for all records type Repo struct { Users domain.UsersRepo } // Provider func Provider(userDomain domain.UsersRepo) (*Repo, func(), error) { repo := &Repo{ Users: userDomain, } return repo, func() {}, nil } var ( ProviderProductionSet = wire.NewSet(Provider, NewUsersRepo) ProviderTestSet = wire.NewSet(Provider, NewUsersRepo) ) ================================================ FILE: app/db/repo/users.go ================================================ package repo import ( "github.com/aristat/golang-example-app/app/db/domain" "github.com/jinzhu/gorm" ) type UsersRepo struct { db *gorm.DB } func (u *UsersRepo) CreateUser(email string, encryptPassword string) (*domain.User, error) { user := &domain.User{Email: email, EncryptedPassword: encryptPassword} if err := u.db.Create(user).Error; err != nil { return nil, err } return user, nil } func (u *UsersRepo) FindByEmail(email string) (*domain.User, error) { user := &domain.User{} err := u.db. Table("users"). Select("id, email, encrypted_password"). Where("users.email = ?", email). Limit(1). Scan(&user).Error return user, err } func NewUsersRepo(db *gorm.DB) (domain.UsersRepo, func(), error) { a := &UsersRepo{db: db} return a, func() {}, nil } ================================================ FILE: app/db/repo/users_test.go ================================================ package repo_test import ( "errors" "testing" "golang.org/x/crypto/bcrypt" "github.com/aristat/golang-example-app/app/db" "github.com/aristat/golang-example-app/app/db/domain" mocket "github.com/selvatico/go-mocket" "github.com/aristat/golang-example-app/app/db/repo" "github.com/stretchr/testify/assert" ) var customInsertError = errors.New("sql: custom insert error") func TestCreateUser(t *testing.T) { mocket.Catcher.Logging = true dbManager, _, e := db.BuildTest() assert.Nil(t, e, "DB manager error should be nil") userRepo, _, e := repo.NewUsersRepo(dbManager.DB) assert.Nil(t, e, "Repo error should be nil") defaultEmail := "test@gmail.com" defaultPassword := "123456789" primaryKey := 333 mockCreateWithError := func() { mocket.Catcher. Reset(). NewMock(). WithQuery("INSERT INTO \"users\" (\"email\",\"encrypted_password\") VALUES ($1,$2)"). WithArgs(defaultEmail, defaultPassword). WithError(customInsertError) } mockCreate := func() { reply := []map[string]interface{}{{"id": primaryKey}} mocket.Catcher. Reset(). NewMock(). WithQuery("INSERT INTO \"users\" (\"email\",\"encrypted_password\") VALUES ($1,$2)"). WithArgs(defaultEmail, defaultPassword). WithReply(reply) } tests := []struct { name string mock func() asserts func(user *domain.User, err error) }{ { name: "USER NOT CREATED", mock: mockCreateWithError, asserts: func(user *domain.User, err error) { assert.Nil(t, user, "user should be nil") assert.NotNil(t, err, "err should not be nil") assert.Equal(t, customInsertError.Error(), err.Error()) }, }, { name: "USER CREATED", mock: mockCreate, asserts: func(user *domain.User, err error) { assert.Equal(t, primaryKey, user.ID) assert.Nil(t, err, "err should be nil") }, }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { test.mock() user, err := userRepo.CreateUser(defaultEmail, defaultPassword) test.asserts(user, err) }) } } func TestFindByEmail(t *testing.T) { mocket.Catcher.Logging = true dbManager, _, e := db.BuildTest() assert.Nil(t, e, "DB manager error should be nil") userRepo, _, e := repo.NewUsersRepo(dbManager.DB) assert.Nil(t, e, "Repo error should be nil") ePassword, e := bcrypt.GenerateFromPassword([]byte("12345"), 8) assert.Nil(t, e, "Password is correct") defaultEmail := "test@gmail.com" mockSelect := func() { reply := []map[string]interface{}{{"id": 1, "email": defaultEmail, "encrypted_password": ePassword}} mocket.Catcher.Reset().NewMock().WithQuery(`WHERE (users.email = $1) LIMIT 1`).WithArgs(defaultEmail).WithReply(reply) } tests := []struct { name string mock func() asserts func(user *domain.User, err error) }{ { name: "USER IS EMPTY", mock: func() {}, asserts: func(user *domain.User, err error) { assert.Equal(t, "", user.Email, "email should be equals") assert.NotNil(t, err, "err should not be nil") assert.Equal(t, err.Error(), "record not found", "error should be corrects") }, }, { name: "USER EXIST", mock: mockSelect, asserts: func(user *domain.User, err error) { assert.Equal(t, defaultEmail, user.Email, "email should be equals") assert.Nil(t, e, "err should be nil") }, }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { mocket.Catcher.Reset() test.mock() user, err := userRepo.FindByEmail(defaultEmail) test.asserts(user, err) }) } } ================================================ FILE: app/db/wire_gen.go ================================================ // Code generated by Wire. DO NOT EDIT. //go:generate go run github.com/google/wire/cmd/wire //go:build !wireinject // +build !wireinject package db import ( "github.com/aristat/golang-example-app/app/config" "github.com/aristat/golang-example-app/app/entrypoint" "github.com/aristat/golang-example-app/app/logger" ) import ( _ "github.com/lib/pq" ) // Injectors from injector.go: func Build() (*Manager, func(), error) { context, cleanup, err := entrypoint.ContextProvider() if err != nil { return nil, nil, err } viper, cleanup2, err := config.Provider() if err != nil { cleanup() return nil, nil, err } loggerConfig, cleanup3, err := logger.ProviderCfg(viper) if err != nil { cleanup2() cleanup() return nil, nil, err } zap, cleanup4, err := logger.Provider(context, loggerConfig) if err != nil { cleanup3() cleanup2() cleanup() return nil, nil, err } dbConfig, cleanup5, err := Cfg(viper) if err != nil { cleanup4() cleanup3() cleanup2() cleanup() return nil, nil, err } db, cleanup6, err := ProviderGORM(context, zap, dbConfig) if err != nil { cleanup5() cleanup4() cleanup3() cleanup2() cleanup() return nil, nil, err } manager, cleanup7, err := Provider(context, zap, dbConfig, db) if err != nil { cleanup6() cleanup5() cleanup4() cleanup3() cleanup2() cleanup() return nil, nil, err } return manager, func() { cleanup7() cleanup6() cleanup5() cleanup4() cleanup3() cleanup2() cleanup() }, nil } func BuildTest() (*Manager, func(), error) { context, cleanup, err := entrypoint.ContextProviderTest() if err != nil { return nil, nil, err } loggerConfig, cleanup2, err := logger.ProviderCfgTest() if err != nil { cleanup() return nil, nil, err } mock, cleanup3, err := logger.ProviderTest(context, loggerConfig) if err != nil { cleanup2() cleanup() return nil, nil, err } dbConfig, cleanup4, err := CfgTest() if err != nil { cleanup3() cleanup2() cleanup() return nil, nil, err } db, cleanup5, err := ProviderGORMTest() if err != nil { cleanup4() cleanup3() cleanup2() cleanup() return nil, nil, err } manager, cleanup6, err := Provider(context, mock, dbConfig, db) if err != nil { cleanup5() cleanup4() cleanup3() cleanup2() cleanup() return nil, nil, err } return manager, func() { cleanup6() cleanup5() cleanup4() cleanup3() cleanup2() cleanup() }, nil } ================================================ FILE: app/entrypoint/entrypoint.go ================================================ package entrypoint import ( "context" "os" "sync" "github.com/spf13/viper" ) var ( vi *viper.Viper mu sync.Mutex reloadCh = make(chan struct{}) shutdownCtx context.Context cancelFn context.CancelFunc ep *EntryPoint wd string ) const prefix = "app.entrypoint" func init() { shutdownCtx, cancelFn = context.WithCancel(context.Background()) } // Viper returns instance of Viper func Viper() *viper.Viper { mu.Lock() defer mu.Unlock() if vi != nil { return vi } vi = viper.GetViper() return vi } // Initialize returns instance of entry point singleton manager, workDir uses to attach templates func Initialize(workDir string, v *viper.Viper) (*EntryPoint, error) { mu.Lock() defer mu.Unlock() if ep != nil { return ep, nil } if len(workDir) > 0 { wd = workDir } else { wd, _ = os.Getwd() } vi, ep = v, &EntryPoint{} return ep, nil } // OnShutdown subscribe on shutdown event for gracefully exit via context. func OnShutdown() context.Context { return shutdownCtx } // OnReload subscribe on reload event. func OnReload() <-chan struct{} { return reloadCh } // EntryPoint manager of single point of application type EntryPoint struct { } // Shutdown raise shutdown event. func Shutdown(ctx context.Context, code int) { mu.Lock() defer mu.Unlock() cancelFn() if _, ok := ctx.Deadline(); ok { <-ctx.Done() } } // Reload raise reload event. func (e *EntryPoint) Reload() { mu.Lock() defer mu.Unlock() ch := reloadCh reloadCh = make(chan struct{}) close(ch) } // WorkDir returns current work directory func WorkDir() string { return wd } ================================================ FILE: app/entrypoint/entrypoint_test.go ================================================ package entrypoint_test import ( "os" "path/filepath" "testing" "github.com/aristat/golang-example-app/app/entrypoint" "github.com/stretchr/testify/assert" ) func TestInitialize(t *testing.T) { wd, _ := filepath.Abs(os.Getenv("APP_WD")) entryPoint, err := entrypoint.Initialize(wd, nil) assert.Nil(t, err, "err should be nil") assert.NotNil(t, entryPoint, "entryPoint should not be nil") } ================================================ FILE: app/entrypoint/provider.go ================================================ package entrypoint import ( "context" "os" "path/filepath" "github.com/google/wire" ) // ContextProvider func ContextProvider() (context.Context, func(), error) { c := OnShutdown() return c, func() {}, nil } // ContextProviderTest func ContextProviderTest() (context.Context, func(), error) { // initializing wd, _ := filepath.Abs(os.Getenv("APP_WD")) _, err := Initialize(wd, nil) c := context.Background() return c, func() {}, err } var ( ProviderProductionSet = wire.NewSet(ContextProvider) ProviderTestSet = wire.NewSet(ContextProviderTest) ) ================================================ FILE: app/graphql/graphql.go ================================================ package graphql import ( "context" "errors" "net/http" "strings" "time" "github.com/99designs/gqlgen/graphql/handler" "github.com/99designs/gqlgen/graphql/handler/extension" "github.com/99designs/gqlgen/graphql/handler/lru" "github.com/99designs/gqlgen/graphql/handler/transport" gqlgen "github.com/99designs/gqlgen/graphql" "github.com/aristat/golang-example-app/app/logger" "github.com/aristat/golang-example-app/generated/graphql" "github.com/go-chi/chi/v5" "github.com/vektah/gqlparser/v2/gqlerror" ) const ( prefix = "app.graphql" ) var errInternalServer = errors.New("internal server error") // GraphQL type GraphQL struct { ctx context.Context resolver *graphql.Config log logger.Logger cfg Config } // Use func (g *GraphQL) Use(router *chi.Mux) { router.Use(g.cfg.Middleware...) } // Routers func (g *GraphQL) Routers(router chi.Router) { srv := handler.New(graphql.NewExecutableSchema(*g.resolver)) srv.AddTransport(transport.Websocket{ KeepAlivePingInterval: 10 * time.Second, }) srv.AddTransport(transport.Options{}) srv.AddTransport(transport.GET{}) srv.AddTransport(transport.POST{}) srv.AddTransport(transport.MultipartForm{}) srv.SetQueryCache(lru.New(1000)) if g.cfg.Introspection { srv.Use(extension.Introspection{}) } srv.Use(extension.AutomaticPersistedQuery{ Cache: lru.New(100), }) srv.SetRecoverFunc(func(ctx context.Context, err interface{}) error { g.log.Alert("unhandled panic, err: %v", logger.Args(err)) return nil }) srv.SetErrorPresenter(func(ctx context.Context, e error) *gqlerror.Error { if e != nil { g.log.Alert("recover on middleware, err: %v", logger.Args(e)) goto done } e = errInternalServer done: return gqlgen.DefaultErrorPresenter(ctx, e) }) if g.cfg.Debug { srv.AroundResponses(func(ctx context.Context, next gqlgen.ResponseHandler) *gqlgen.Response { startTime := time.Now() rc := gqlgen.GetOperationContext(ctx) resp := next(ctx) g.log.Debug("\nVARS:\n%+v\nQUERY:\n%v\nRESPONSE:\n%v\nERROR:\n%v\n", logger.Args(rc.Variables, strings.TrimRight(rc.RawQuery, "\n"), string(resp.Data), resp.Errors), logger.WithFields(logger.Fields{ "time": time.Since(startTime).String(), }), ) return resp }) } router.Handle("/query", srv) } // Config type Config struct { Debug bool Introspection bool Name string Middleware []func(http.Handler) http.Handler } // New func New(ctx context.Context, resolver graphql.Config, log logger.Logger, cfg Config) *GraphQL { log = log.WithFields(logger.Fields{"service": prefix}) return &GraphQL{ ctx: ctx, resolver: &resolver, cfg: cfg, log: log, } } ================================================ FILE: app/graphql/provider.go ================================================ package graphql import ( "context" "github.com/aristat/golang-example-app/app/graphql_resolver" "github.com/aristat/golang-example-app/app/logger" "github.com/aristat/golang-example-app/generated/graphql" "github.com/google/wire" "github.com/spf13/viper" ) // Cfg func Cfg(cfg *viper.Viper) (Config, func(), error) { c := Config{} e := cfg.UnmarshalKey("graphql", &c) if e != nil { return c, func() {}, e } if cfg.IsSet("debug") && !c.Debug { c.Debug = cfg.GetBool("debug") } return c, func() {}, nil } // CfgTest func CfgTest() (Config, func(), error) { return Config{}, func() {}, nil } // Provider func Provider(ctx context.Context, resolver graphql.Config, log logger.Logger, cfg Config) (*GraphQL, func(), error) { g := New(ctx, resolver, log, cfg) return g, func() {}, nil } var ( ProviderProductionSet = wire.NewSet(Provider, Cfg, graphql_resolver.ProviderProductionSet) ProviderTestSet = wire.NewSet(Provider, CfgTest, graphql_resolver.ProviderTestSet) ) ================================================ FILE: app/graphql_resolver/injector.go ================================================ // +build wireinject package graphql_resolver import ( "github.com/aristat/golang-example-app/app/db" "github.com/aristat/golang-example-app/app/db/repo" "github.com/aristat/golang-example-app/app/provider" "github.com/aristat/golang-example-app/generated/graphql" "github.com/google/wire" ) // Build func Build() (graphql.Config, func(), error) { panic(wire.Build(ProviderProductionSet, repo.ProviderProductionSet, db.ProviderProductionSet, provider.AwareProductionSet)) } func BuildTest() (graphql.Config, func(), error) { panic(wire.Build(ProviderTestSet, repo.ProviderTestSet, db.ProviderTestSet, provider.AwareTestSet)) } ================================================ FILE: app/graphql_resolver/mock.go ================================================ package graphql_resolver import ( "context" "fmt" "github.com/aristat/golang-example-app/generated/resources/proto/products" ) type ProductServerMock struct { products.UnimplementedProductsServer } func (s *ProductServerMock) ListProduct(ctx context.Context, in *products.ListProductIn) (*products.ListProductOut, error) { productIds := []int64{1, 2, 3, 4, 5} out := &products.ListProductOut{Status: products.ListProductOut_OK, Products: []*products.Product{}} for _, id := range productIds { out.Products = append(out.Products, &products.Product{Id: id, Name: fmt.Sprintf("product_%d", id)}) } return out, nil } ================================================ FILE: app/graphql_resolver/product.go ================================================ package graphql_resolver import ( "context" "time" "github.com/aristat/golang-example-app/app/dataloader" "github.com/aristat/golang-example-app/app/db/domain" "github.com/aristat/golang-example-app/app/common" "github.com/aristat/golang-example-app/app/grpc" "github.com/aristat/golang-example-app/generated/graphql" "github.com/aristat/golang-example-app/generated/resources/proto/products" "github.com/spf13/cast" ) type productsQueryResolver struct{ *Resolver } type productResolver struct{ *Resolver } func (r *Resolver) ProductsQuery() graphql.ProductsQueryResolver { return &productsQueryResolver{r} } // QUERY func (r *queryResolver) Products(ctx context.Context) (*graphql.ProductsQuery, error) { return &graphql.ProductsQuery{}, nil } func (r *productsQueryResolver) List(ctx context.Context, obj *graphql.ProductsQuery) (*graphql.ProductsListOut, error) { conn, d, err := grpc.GetConnGRPC(r.pollManager, common.SrvProducts) defer d() if err != nil { return nil, err } c := products.NewProductsClient(conn) ctx, cancel := context.WithTimeout(ctx, time.Second*time.Duration(r.cfg.ProductTimeout)) defer cancel() productOut, err := c.ListProduct(ctx, &products.ListProductIn{Id: 1}) if err != nil { return nil, err } list := make([]*domain.Product, len(productOut.Products)) for i, product := range productOut.Products { list[i] = &domain.Product{ ID: cast.ToInt(&product.Id), Name: product.Name, } } return &graphql.ProductsListOut{Products: list}, nil } func (r *queryResolver) ProductsRoot(ctx context.Context) ([]*domain.Product, error) { return []*domain.Product{{ID: 1, Name: "test1"}, {ID: 2, Name: "test2"}}, nil } func (r *Resolver) Product() graphql.ProductResolver { return &productResolver{r} } func (r *productResolver) ProductItems(ctx context.Context, obj *domain.Product) ([]*domain.ProductItem, error) { r.log.Info("ProductItems Start Request") return dataloader.CtxLoaders(ctx).ProductItemsByProduct.Load(obj.ID) } ================================================ FILE: app/graphql_resolver/product_test.go ================================================ package graphql_resolver_test import ( "context" "encoding/json" "log" "net" "os" "strconv" "testing" "github.com/aristat/golang-example-app/app/common" "github.com/aristat/golang-example-app/generated/resources/proto/products" "google.golang.org/grpc" "github.com/stretchr/testify/assert" "github.com/aristat/golang-example-app/app/graphql_resolver" grpc1 "github.com/aristat/golang-example-app/app/grpc" graphql1 "github.com/aristat/golang-example-app/generated/graphql" ) var ( productServerHost = "localhost" grpcPort string ) func TestMain(m *testing.M) { lis, err := net.Listen("tcp", ":0") if err != nil { log.Fatalf(err.Error()) } defer lis.Close() grpcPort = ":" + strconv.Itoa(lis.Addr().(*net.TCPAddr).Port) s := grpc.NewServer() products.RegisterProductsServer(s, &graphql_resolver.ProductServerMock{}) go func() { if err := s.Serve(lis); err != nil { log.Fatalf("Server exited with error: %v", err) } }() code := m.Run() os.Exit(code) } func TestList(t *testing.T) { var opts []grpc.DialOption ctx := context.Background() opts = append(opts, grpc.WithInsecure()) pool, _ := grpc1.NewPool(ctx, common.SrvProducts, productServerHost+grpcPort, grpc1.ConnOptions(opts...)) grpc1.SetPool(pool, common.SrvProducts) cfg, _, err := graphql_resolver.BuildTest() if err != nil { assert.Failf(t, "graphql_resolver instance failed, err: %v", err.Error()) return } obj := graphql1.ProductsQuery{} out, err := cfg.Resolvers.ProductsQuery().List(ctx, &obj) if err != nil { assert.Failf(t, "request failed, err: %v", err.Error()) return } jsonProducts, _ := json.Marshal(out.Products) t.Log(string(jsonProducts)) assert.Equal(t, len(out.Products), 5) } ================================================ FILE: app/graphql_resolver/provider.go ================================================ package graphql_resolver import ( "context" "github.com/casbin/casbin" "github.com/aristat/golang-example-app/app/logger" "github.com/aristat/golang-example-app/generated/graphql" "github.com/google/wire" "github.com/spf13/viper" ) // Cfg func Cfg(cfg *viper.Viper) (Config, func(), error) { c := Config{} e := cfg.UnmarshalKey("graphql_resolver", &c) return c, func() {}, e } // CfgTest func CfgTest() (Config, func(), error) { return Config{ProductTimeout: 5}, func() {}, nil } var ProviderManagers = wire.NewSet( wire.Struct(new(Managers), "*"), ) // Provider func Provider(ctx context.Context, log logger.Logger, cfg Config, enforcer *casbin.Enforcer, managers Managers) (graphql.Config, func(), error) { c := New(ctx, log, cfg, enforcer, managers) return c, func() {}, nil } var ( ProviderProductionSet = wire.NewSet(Provider, Cfg, ProviderManagers) ProviderTestSet = wire.NewSet(Provider, CfgTest, ProviderManagers) ) ================================================ FILE: app/graphql_resolver/resolver.go ================================================ package graphql_resolver import ( "context" "strings" "github.com/pkg/errors" "github.com/99designs/gqlgen/graphql" "github.com/casbin/casbin" "github.com/aristat/golang-example-app/app/grpc" "github.com/aristat/golang-example-app/app/db/repo" appContext "github.com/aristat/golang-example-app/app/context" "github.com/aristat/golang-example-app/app/logger" graphql1 "github.com/aristat/golang-example-app/generated/graphql" ) var prefix = "app.graphql_resolver" var errPermission = errors.WithMessage(errors.New("No have permission"), prefix) // Config type Config struct { ProductTimeout int } // Managers type Managers struct { Repo *repo.Repo PollManager *grpc.PoolManager } type queryResolver struct{ *Resolver } type mutationResolver struct{ *Resolver } // Resolver config graphql resolvers type Resolver struct { ctx context.Context log logger.Logger cfg Config repo *repo.Repo pollManager *grpc.PoolManager } // Mutation returns root graphql mutation graphql_resolver func (r *Resolver) Mutation() graphql1.MutationResolver { return &mutationResolver{r} } // Query returns root graphql query graphql_resolver func (r *Resolver) Query() graphql1.QueryResolver { return &queryResolver{r} } // New func New(ctx context.Context, log logger.Logger, cfg Config, enforcer *casbin.Enforcer, managers Managers) graphql1.Config { log = log.WithFields(logger.Fields{"service": prefix}) c := graphql1.Config{ Resolvers: &Resolver{ ctx: ctx, log: log, cfg: cfg, repo: managers.Repo, pollManager: managers.PollManager, }, } c.Directives.HasUsersPermission = func(ctx context.Context, obj interface{}, next graphql.Resolver, role graphql1.UsersPermissionEnum) (res interface{}, err error) { m, err := appContext.NewManager(ctx) if err != nil { return nil, err } mapping := m.ToMapping() if !enforcer.Enforce(mapping.Subject, "users", strings.ToLower(string(role))) { return nil, errPermission } return next(ctx) } return c } ================================================ FILE: app/graphql_resolver/resolver_gen.go ================================================ package graphql_resolver ================================================ FILE: app/graphql_resolver/user.go ================================================ package graphql_resolver import ( "context" "github.com/aristat/golang-example-app/app/common" graphql1 "github.com/aristat/golang-example-app/generated/graphql" "github.com/spf13/cast" ) type usersQueryResolver struct{ *Resolver } type usersMutationResolver struct{ *Resolver } func (r *Resolver) UsersMutation() graphql1.UsersMutationResolver { return &usersMutationResolver{r} } func (r *Resolver) UsersQuery() graphql1.UsersQueryResolver { return &usersQueryResolver{r} } // QUERY func (r *queryResolver) Users(ctx context.Context) (*graphql1.UsersQuery, error) { return &graphql1.UsersQuery{}, nil } func (r *usersQueryResolver) One(ctx context.Context, obj *graphql1.UsersQuery, email string) (*graphql1.UsersOneOut, error) { user, err := r.repo.Users.FindByEmail(email) if err != nil { return nil, err } userData := &graphql1.UsersOneOut{ ID: cast.ToString(&user.ID), Email: user.Email, } return userData, nil } // MUTATIONS func (r *mutationResolver) Users(ctx context.Context) (*graphql1.UsersMutation, error) { return &graphql1.UsersMutation{}, nil } func (r *usersMutationResolver) CreateUser(ctx context.Context, obj *graphql1.UsersMutation, email string, password string) (*graphql1.UsersCreateOut, error) { encryptPassword, err := common.HashPassword(password, 8) if err != nil { return nil, err } user, err := r.repo.Users.CreateUser(email, encryptPassword) if err != nil { return nil, err } userData := &graphql1.UsersCreateOut{ ID: cast.ToString(user.ID), Email: user.Email, Status: graphql1.UsersCreateOutStatusOk, } return userData, nil } ================================================ FILE: app/graphql_resolver/user_test.go ================================================ package graphql_resolver_test import ( "context" "testing" "github.com/spf13/cast" "golang.org/x/crypto/bcrypt" "github.com/stretchr/testify/assert" "github.com/aristat/golang-example-app/app/graphql_resolver" graphql1 "github.com/aristat/golang-example-app/generated/graphql" mocket "github.com/selvatico/go-mocket" ) type UserParams struct { testName string id int email string } func TestOne(t *testing.T) { ctx := context.Background() cfg, _, err := graphql_resolver.BuildTest() if err != nil { assert.Failf(t, "graphql_resolver instance failed, err: %v", err.Error()) return } ePassword, e := bcrypt.GenerateFromPassword([]byte("12345"), 8) assert.Nil(t, e, "Password is correct") obj := graphql1.UsersQuery{} defaultEmail := "test@gmail.com" id := 1 mockDefaultResult := func() { reply := []map[string]interface{}{{"id": id, "email": defaultEmail, "encrypted_password": ePassword}} mocket.Catcher.Reset().NewMock().WithQuery(`WHERE (users.email = $1) LIMIT 1`).WithArgs(defaultEmail).WithReply(reply) } tests := []struct { userParams UserParams mock func() asserts func(userParams UserParams, out *graphql1.UsersOneOut, err error) }{ { userParams: UserParams{id: 2, email: "test1@gmail.com", testName: "USER NOT EXIST"}, mock: mockDefaultResult, asserts: func(userParams UserParams, out *graphql1.UsersOneOut, err error) { assert.NotNil(t, err, "err should not be nil") assert.Nil(t, out, "out should be nil") }, }, { userParams: UserParams{id: id, email: defaultEmail, testName: "USER EXIST"}, mock: mockDefaultResult, asserts: func(userParams UserParams, out *graphql1.UsersOneOut, err error) { assert.Nil(t, err, "err should be nil") assert.Equal(t, cast.ToString(userParams.id), out.ID, "id should be equals") assert.Equal(t, userParams.email, out.Email, "email should be equals") }, }, } for _, test := range tests { t.Run(test.userParams.testName, func(t *testing.T) { mocket.Catcher.Reset() test.mock() out, err := cfg.Resolvers.UsersQuery().One(ctx, &obj, test.userParams.email) test.asserts(test.userParams, out, err) }) } } ================================================ FILE: app/graphql_resolver/wire_gen.go ================================================ // Code generated by Wire. DO NOT EDIT. //go:generate go run github.com/google/wire/cmd/wire //go:build !wireinject // +build !wireinject package graphql_resolver import ( "github.com/aristat/golang-example-app/app/casbin" "github.com/aristat/golang-example-app/app/config" "github.com/aristat/golang-example-app/app/db" "github.com/aristat/golang-example-app/app/db/repo" "github.com/aristat/golang-example-app/app/entrypoint" "github.com/aristat/golang-example-app/app/grpc" "github.com/aristat/golang-example-app/app/logger" "github.com/aristat/golang-example-app/app/tracing" "github.com/aristat/golang-example-app/generated/graphql" ) // Injectors from injector.go: // Build func Build() (graphql.Config, func(), error) { context, cleanup, err := entrypoint.ContextProvider() if err != nil { return graphql.Config{}, nil, err } viper, cleanup2, err := config.Provider() if err != nil { cleanup() return graphql.Config{}, nil, err } loggerConfig, cleanup3, err := logger.ProviderCfg(viper) if err != nil { cleanup2() cleanup() return graphql.Config{}, nil, err } zap, cleanup4, err := logger.Provider(context, loggerConfig) if err != nil { cleanup3() cleanup2() cleanup() return graphql.Config{}, nil, err } graphql_resolverConfig, cleanup5, err := Cfg(viper) if err != nil { cleanup4() cleanup3() cleanup2() cleanup() return graphql.Config{}, nil, err } enforcer, cleanup6, err := casbin.Provider() if err != nil { cleanup5() cleanup4() cleanup3() cleanup2() cleanup() return graphql.Config{}, nil, err } dbConfig, cleanup7, err := db.Cfg(viper) if err != nil { cleanup6() cleanup5() cleanup4() cleanup3() cleanup2() cleanup() return graphql.Config{}, nil, err } gormDB, cleanup8, err := db.ProviderGORM(context, zap, dbConfig) if err != nil { cleanup7() cleanup6() cleanup5() cleanup4() cleanup3() cleanup2() cleanup() return graphql.Config{}, nil, err } usersRepo, cleanup9, err := repo.NewUsersRepo(gormDB) if err != nil { cleanup8() cleanup7() cleanup6() cleanup5() cleanup4() cleanup3() cleanup2() cleanup() return graphql.Config{}, nil, err } repoRepo, cleanup10, err := repo.Provider(usersRepo) if err != nil { cleanup9() cleanup8() cleanup7() cleanup6() cleanup5() cleanup4() cleanup3() cleanup2() cleanup() return graphql.Config{}, nil, err } configuration, cleanup11, err := tracing.Cfg(viper) if err != nil { cleanup10() cleanup9() cleanup8() cleanup7() cleanup6() cleanup5() cleanup4() cleanup3() cleanup2() cleanup() return graphql.Config{}, nil, err } tracerProvider, cleanup12, err := tracing.Provider(context, configuration, zap) if err != nil { cleanup11() cleanup10() cleanup9() cleanup8() cleanup7() cleanup6() cleanup5() cleanup4() cleanup3() cleanup2() cleanup() return graphql.Config{}, nil, err } grpcConfig, cleanup13, err := grpc.Cfg(viper) if err != nil { cleanup12() cleanup11() cleanup10() cleanup9() cleanup8() cleanup7() cleanup6() cleanup5() cleanup4() cleanup3() cleanup2() cleanup() return graphql.Config{}, nil, err } poolManager, cleanup14, err := grpc.Provider(context, tracerProvider, zap, grpcConfig) if err != nil { cleanup13() cleanup12() cleanup11() cleanup10() cleanup9() cleanup8() cleanup7() cleanup6() cleanup5() cleanup4() cleanup3() cleanup2() cleanup() return graphql.Config{}, nil, err } managers := Managers{ Repo: repoRepo, PollManager: poolManager, } graphqlConfig, cleanup15, err := Provider(context, zap, graphql_resolverConfig, enforcer, managers) if err != nil { cleanup14() cleanup13() cleanup12() cleanup11() cleanup10() cleanup9() cleanup8() cleanup7() cleanup6() cleanup5() cleanup4() cleanup3() cleanup2() cleanup() return graphql.Config{}, nil, err } return graphqlConfig, func() { cleanup15() cleanup14() cleanup13() cleanup12() cleanup11() cleanup10() cleanup9() cleanup8() cleanup7() cleanup6() cleanup5() cleanup4() cleanup3() cleanup2() cleanup() }, nil } func BuildTest() (graphql.Config, func(), error) { context, cleanup, err := entrypoint.ContextProviderTest() if err != nil { return graphql.Config{}, nil, err } loggerConfig, cleanup2, err := logger.ProviderCfgTest() if err != nil { cleanup() return graphql.Config{}, nil, err } mock, cleanup3, err := logger.ProviderTest(context, loggerConfig) if err != nil { cleanup2() cleanup() return graphql.Config{}, nil, err } graphql_resolverConfig, cleanup4, err := CfgTest() if err != nil { cleanup3() cleanup2() cleanup() return graphql.Config{}, nil, err } enforcer, cleanup5, err := casbin.ProviderTest() if err != nil { cleanup4() cleanup3() cleanup2() cleanup() return graphql.Config{}, nil, err } gormDB, cleanup6, err := db.ProviderGORMTest() if err != nil { cleanup5() cleanup4() cleanup3() cleanup2() cleanup() return graphql.Config{}, nil, err } usersRepo, cleanup7, err := repo.NewUsersRepo(gormDB) if err != nil { cleanup6() cleanup5() cleanup4() cleanup3() cleanup2() cleanup() return graphql.Config{}, nil, err } repoRepo, cleanup8, err := repo.Provider(usersRepo) if err != nil { cleanup7() cleanup6() cleanup5() cleanup4() cleanup3() cleanup2() cleanup() return graphql.Config{}, nil, err } tracerProvider, cleanup9, err := tracing.ProviderTest() if err != nil { cleanup8() cleanup7() cleanup6() cleanup5() cleanup4() cleanup3() cleanup2() cleanup() return graphql.Config{}, nil, err } grpcConfig, cleanup10, err := grpc.CfgTest() if err != nil { cleanup9() cleanup8() cleanup7() cleanup6() cleanup5() cleanup4() cleanup3() cleanup2() cleanup() return graphql.Config{}, nil, err } poolManager, cleanup11, err := grpc.Provider(context, tracerProvider, mock, grpcConfig) if err != nil { cleanup10() cleanup9() cleanup8() cleanup7() cleanup6() cleanup5() cleanup4() cleanup3() cleanup2() cleanup() return graphql.Config{}, nil, err } managers := Managers{ Repo: repoRepo, PollManager: poolManager, } graphqlConfig, cleanup12, err := Provider(context, mock, graphql_resolverConfig, enforcer, managers) if err != nil { cleanup11() cleanup10() cleanup9() cleanup8() cleanup7() cleanup6() cleanup5() cleanup4() cleanup3() cleanup2() cleanup() return graphql.Config{}, nil, err } return graphqlConfig, func() { cleanup12() cleanup11() cleanup10() cleanup9() cleanup8() cleanup7() cleanup6() cleanup5() cleanup4() cleanup3() cleanup2() cleanup() }, nil } ================================================ FILE: app/grpc/connection.go ================================================ package grpc import ( "sync" "google.golang.org/grpc" ) var ( srvMu sync.Mutex poolSrv = map[string]*Pool{} ) // Set pool connections func SetPool(p *Pool, srv string) { if _, ok := poolSrv[srv]; !ok { srvMu.Lock() defer srvMu.Unlock() poolSrv[srv] = p } } // Get client connection func GetConnGRPC(poolManager *PoolManager, srv string) (*grpc.ClientConn, Done, error) { if _, ok := poolSrv[srv]; !ok { srvMu.Lock() defer srvMu.Unlock() if _, ok := poolSrv[srv]; !ok { p, _, e := poolManager.NewPool(srv) if e != nil { return nil, func() {}, e } poolSrv[srv] = p } } return poolSrv[srv].Get() } ================================================ FILE: app/grpc/manager.go ================================================ package grpc import ( "context" "errors" "go.opentelemetry.io/otel/propagation" "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" tracesdk "go.opentelemetry.io/otel/sdk/trace" "google.golang.org/grpc/credentials/insecure" "github.com/aristat/golang-example-app/app/logger" "google.golang.org/grpc" "google.golang.org/grpc/keepalive" ) const prefix = "app.grpc" var errCfgInvalid = errors.New("cfg is not present or invalid") // PoolManager type PoolManager struct { ctx context.Context tracing *tracesdk.TracerProvider cfg *Config logger logger.Logger } // New func (p *PoolManager) NewPool(service string) (_ *Pool, loaded bool, _ error) { s, ok := p.cfg.Services[service] if !ok { return nil, false, errCfgInvalid } var opts []grpc.DialOption opts = append(opts, grpc.WithTransportCredentials(insecure.NewCredentials())) cl := s.ClientParameters if cl == nil { if p.cfg.ClientParameters != nil { cl = p.cfg.ClientParameters } else { cl = &keepalive.ClientParameters{} } } opts = append(opts, grpc.WithKeepaliveParams(*cl)) opts = append(opts, grpc.WithChainUnaryInterceptor( logger.UnaryClientInterceptor(p.logger, true), otelgrpc.UnaryClientInterceptor(otelgrpc.WithTracerProvider(p.tracing), otelgrpc.WithPropagators(propagation.TraceContext{})), ), ) opts = append(opts, grpc.WithChainStreamInterceptor( logger.StreamClientInterceptor(p.logger, true), otelgrpc.StreamClientInterceptor(otelgrpc.WithTracerProvider(p.tracing), otelgrpc.WithPropagators(propagation.TraceContext{})), ), ) pool, l := NewPool(p.ctx, service, s.Target, MaxConn(s.MaxConn), InitConn(s.InitConn), MaxLifeDuration(s.MaxLifeDuration), IdleTimeout(s.IdleTimeout), ConnOptions(opts...), ) return pool, l, nil } // NewPoolManager func NewPoolManager(ctx context.Context, tracing *tracesdk.TracerProvider, logger logger.Logger, cfg *Config) *PoolManager { return &PoolManager{ctx: ctx, tracing: tracing, cfg: cfg, logger: logger} } ================================================ FILE: app/grpc/pool.go ================================================ package grpc import ( "context" "sync" "time" "github.com/pkg/errors" grpcpool "github.com/processout/grpc-go-pool" "google.golang.org/grpc" ) var ( poolList map[string]*Pool mu sync.Mutex ) // Done type Done func() type conn struct { conn *grpc.ClientConn pool *Pool err error } func (c *conn) init() { c.conn, c.err = grpc.Dial(c.pool.target, c.pool.opts.dialOptions...) } // Pool type Pool struct { id string ctx context.Context service string pool *grpcpool.Pool target string opts *opts } // Get func (p *Pool) Get() (*grpc.ClientConn, Done, error) { c, e := p.pool.Get(p.ctx) return c.ClientConn, func() { _ = c.Close() }, errors.WithMessage(e, prefix) } type opts struct { dialOptions []grpc.DialOption initConn int maxConn int idleTimeout time.Duration maxLifeDuration time.Duration } // Option type Option func(*opts) error // ConnOptions func ConnOptions(o ...grpc.DialOption) Option { return func(f *opts) error { f.dialOptions = o return nil } } // MaxConn func MaxConn(value int) Option { return func(f *opts) error { f.maxConn = value return nil } } // InitConn func InitConn(value int) Option { return func(f *opts) error { f.initConn = value return nil } } // MaxLifeDuration func MaxLifeDuration(value time.Duration) Option { return func(f *opts) error { f.maxLifeDuration = value return nil } } // IdleTimeout func IdleTimeout(value time.Duration) Option { return func(f *opts) error { f.idleTimeout = value return nil } } // NewPool func NewPool(ctx context.Context, service, target string, o ...Option) (_ *Pool, loaded bool) { mu.Lock() defer mu.Unlock() if p := poolList[service]; p != nil { return p, true } p := &Pool{ id: time.Now().String(), ctx: ctx, service: service, opts: &opts{}, target: target, } for _, option := range o { _ = option(p.opts) } factory := func() (*grpc.ClientConn, error) { c := &conn{pool: p} c.init() return c.conn, c.err } p.pool, _ = grpcpool.New(factory, p.opts.initConn, p.opts.maxConn, p.opts.idleTimeout, p.opts.maxLifeDuration) return p, false } ================================================ FILE: app/grpc/provider.go ================================================ package grpc import ( "context" "sync" "time" tracesdk "go.opentelemetry.io/otel/sdk/trace" "github.com/aristat/golang-example-app/app/logger" "github.com/google/wire" "github.com/spf13/viper" "google.golang.org/grpc/keepalive" ) var ( pm *PoolManager mutexPM sync.Mutex ) // Cfg func Cfg(cfg *viper.Viper) (*Config, func(), error) { c := &Config{} e := cfg.UnmarshalKey("grpc", c) if e != nil { return c, func() {}, e } return c, func() {}, e } // CfgTest func CfgTest() (*Config, func(), error) { return &Config{}, func() {}, nil } // Service type Service struct { Target string MaxConn int InitConn int MaxLifeDuration time.Duration IdleTimeout time.Duration ClientParameters *keepalive.ClientParameters } // Config type Config struct { Services map[string]*Service ClientParameters *keepalive.ClientParameters } // Provider func Provider(ctx context.Context, tracing *tracesdk.TracerProvider, logger logger.Logger, cfg *Config) (*PoolManager, func(), error) { mutexPM.Lock() defer mutexPM.Unlock() if pm != nil { return pm, func() {}, nil } pm = NewPoolManager(ctx, tracing, logger, cfg) return pm, func() {}, nil } var ( ProviderProductionSet = wire.NewSet(Provider, Cfg) ProviderTestSet = wire.NewSet(Provider, CfgTest) ) ================================================ FILE: app/http/http.go ================================================ package http import ( "context" "net/http" "sync" "github.com/go-chi/chi/v5" "github.com/go-session/session" "github.com/aristat/golang-example-app/app/logger" ) const prefix = "app.http" // Config type Config struct { Debug bool Bind string } // Http type Http struct { ctx context.Context cfg Config session *session.Manager log logger.Logger mux *chi.Mux } // ListenAndServe func (m *Http) ListenAndServe(wg *sync.WaitGroup, bind ...string) (server *http.Server) { bindAddress := m.cfg.Bind if len(bind) > 0 && len(bind[0]) > 0 { bindAddress = bind[0] } server = &http.Server{ Addr: bindAddress, Handler: m.mux, } go func() { defer wg.Done() if err := server.ListenAndServe(); err != nil { if err != http.ErrServerClosed { m.log.Emergency("Server is shutdown with error, %v", logger.Args(err)) } else { err = nil } } m.log.Info("HTTP Server stopped successfully") }() return server } // New func New(ctx context.Context, mux *chi.Mux, log logger.Logger, cfg Config) *Http { return &Http{ ctx: ctx, cfg: cfg, mux: mux, log: log.WithFields(logger.Fields{"service": prefix}), } } ================================================ FILE: app/http/injector.go ================================================ // +build wireinject package http import ( "github.com/aristat/golang-example-app/app/auth" "github.com/aristat/golang-example-app/app/db" "github.com/aristat/golang-example-app/app/db/repo" "github.com/aristat/golang-example-app/app/graphql" products_router "github.com/aristat/golang-example-app/app/http_routers/products-router" "github.com/aristat/golang-example-app/app/provider" "github.com/google/wire" ) // Build func Build() (*Http, func(), error) { panic(wire.Build( ProviderProductionSet, auth.ProviderProductionSet, graphql.ProviderProductionSet, products_router.ProviderProductionSet, repo.ProviderProductionSet, db.ProviderProductionSet, provider.AwareProductionSet, )) } ================================================ FILE: app/http/logger.go ================================================ package http import ( "net/http" "time" "github.com/aristat/golang-example-app/app/logger" "github.com/go-chi/chi/v5/middleware" ) func Logger(l logger.Logger) func(next http.Handler) http.Handler { return func(next http.Handler) http.Handler { fn := func(w http.ResponseWriter, r *http.Request) { ww := middleware.NewWrapResponseWriter(w, r.ProtoMajor) t1 := time.Now() defer func() { l.Info("proto %s, path %s, lat %d, status %d, size %d, reqId %s", logger.Args( r.Proto, r.URL.Path, time.Since(t1), ww.Status(), ww.BytesWritten(), middleware.GetReqID(r.Context()), )) }() next.ServeHTTP(ww, r) } return http.HandlerFunc(fn) } } ================================================ FILE: app/http/provider.go ================================================ package http import ( "context" "github.com/riandyrn/otelchi" "github.com/aristat/golang-example-app/app/dataloader" products_router "github.com/aristat/golang-example-app/app/http_routers/products-router" "github.com/aristat/golang-example-app/app/auth" "github.com/aristat/golang-example-app/app/graphql" "github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5/middleware" "github.com/aristat/golang-example-app/app/logger" "github.com/google/wire" "github.com/spf13/viper" ) var muxRouter *chi.Mux // Cfg func Cfg(cfg *viper.Viper) (Config, func(), error) { c := Config{} e := cfg.UnmarshalKey("http", &c) if e != nil { return c, func() {}, e } c.Debug = cfg.GetBool("debug") return c, func() {}, nil } // CfgTest func CfgTest() (Config, func(), error) { return Config{}, func() {}, nil } // Mux func Mux(managers Managers, log logger.Logger) (*chi.Mux, func(), error) { if muxRouter != nil { return muxRouter, func() {}, nil } muxRouter = chi.NewRouter() muxRouter.Use(middleware.RequestID) muxRouter.Use(Logger(log)) muxRouter.Use(otelchi.Middleware("http-server", otelchi.WithChiRoutes(muxRouter))) muxRouter.Use(dataloader.LoaderMiddleware) managers.products.Router.Run(muxRouter) managers.graphql.Routers(muxRouter.With(managers.authMiddleware.JWTHandler)) return muxRouter, func() {}, nil } // ServiceManagers type Managers struct { products *products_router.Manager authMiddleware *auth.Middleware graphql *graphql.GraphQL } var ProviderManagers = wire.NewSet( wire.Struct(new(Managers), "*"), ) // Provider func Provider(ctx context.Context, mux *chi.Mux, log logger.Logger, cfg Config) (*Http, func(), error) { g := New(ctx, mux, log, cfg) return g, func() {}, nil } var ( ProviderProductionSet = wire.NewSet(Provider, Cfg, Mux, ProviderManagers) ProviderTestSet = wire.NewSet(Provider, CfgTest) ) ================================================ FILE: app/http/wire_gen.go ================================================ // Code generated by Wire. DO NOT EDIT. //go:generate go run github.com/google/wire/cmd/wire //go:build !wireinject // +build !wireinject package http import ( "github.com/aristat/golang-example-app/app/auth" "github.com/aristat/golang-example-app/app/casbin" "github.com/aristat/golang-example-app/app/config" "github.com/aristat/golang-example-app/app/db" "github.com/aristat/golang-example-app/app/db/repo" "github.com/aristat/golang-example-app/app/entrypoint" "github.com/aristat/golang-example-app/app/graphql" "github.com/aristat/golang-example-app/app/graphql_resolver" "github.com/aristat/golang-example-app/app/grpc" "github.com/aristat/golang-example-app/app/http_routers/products-router" "github.com/aristat/golang-example-app/app/logger" "github.com/aristat/golang-example-app/app/tracing" ) // Injectors from injector.go: // Build func Build() (*Http, func(), error) { context, cleanup, err := entrypoint.ContextProvider() if err != nil { return nil, nil, err } viper, cleanup2, err := config.Provider() if err != nil { cleanup() return nil, nil, err } loggerConfig, cleanup3, err := logger.ProviderCfg(viper) if err != nil { cleanup2() cleanup() return nil, nil, err } zap, cleanup4, err := logger.Provider(context, loggerConfig) if err != nil { cleanup3() cleanup2() cleanup() return nil, nil, err } configuration, cleanup5, err := tracing.Cfg(viper) if err != nil { cleanup4() cleanup3() cleanup2() cleanup() return nil, nil, err } tracerProvider, cleanup6, err := tracing.Provider(context, configuration, zap) if err != nil { cleanup5() cleanup4() cleanup3() cleanup2() cleanup() return nil, nil, err } grpcConfig, cleanup7, err := grpc.Cfg(viper) if err != nil { cleanup6() cleanup5() cleanup4() cleanup3() cleanup2() cleanup() return nil, nil, err } poolManager, cleanup8, err := grpc.Provider(context, tracerProvider, zap, grpcConfig) if err != nil { cleanup7() cleanup6() cleanup5() cleanup4() cleanup3() cleanup2() cleanup() return nil, nil, err } serviceManagers := products_router.ServiceManagers{ PoolManager: poolManager, } products_routerConfig, cleanup9, err := products_router.Cfg(viper) if err != nil { cleanup8() cleanup7() cleanup6() cleanup5() cleanup4() cleanup3() cleanup2() cleanup() return nil, nil, err } manager, cleanup10, err := products_router.Provider(context, zap, serviceManagers, products_routerConfig) if err != nil { cleanup9() cleanup8() cleanup7() cleanup6() cleanup5() cleanup4() cleanup3() cleanup2() cleanup() return nil, nil, err } authConfig, cleanup11, err := auth.ProviderCfg(viper) if err != nil { cleanup10() cleanup9() cleanup8() cleanup7() cleanup6() cleanup5() cleanup4() cleanup3() cleanup2() cleanup() return nil, nil, err } middleware, cleanup12, err := auth.Provider(authConfig, zap) if err != nil { cleanup11() cleanup10() cleanup9() cleanup8() cleanup7() cleanup6() cleanup5() cleanup4() cleanup3() cleanup2() cleanup() return nil, nil, err } graphql_resolverConfig, cleanup13, err := graphql_resolver.Cfg(viper) if err != nil { cleanup12() cleanup11() cleanup10() cleanup9() cleanup8() cleanup7() cleanup6() cleanup5() cleanup4() cleanup3() cleanup2() cleanup() return nil, nil, err } enforcer, cleanup14, err := casbin.Provider() if err != nil { cleanup13() cleanup12() cleanup11() cleanup10() cleanup9() cleanup8() cleanup7() cleanup6() cleanup5() cleanup4() cleanup3() cleanup2() cleanup() return nil, nil, err } dbConfig, cleanup15, err := db.Cfg(viper) if err != nil { cleanup14() cleanup13() cleanup12() cleanup11() cleanup10() cleanup9() cleanup8() cleanup7() cleanup6() cleanup5() cleanup4() cleanup3() cleanup2() cleanup() return nil, nil, err } gormDB, cleanup16, err := db.ProviderGORM(context, zap, dbConfig) if err != nil { cleanup15() cleanup14() cleanup13() cleanup12() cleanup11() cleanup10() cleanup9() cleanup8() cleanup7() cleanup6() cleanup5() cleanup4() cleanup3() cleanup2() cleanup() return nil, nil, err } usersRepo, cleanup17, err := repo.NewUsersRepo(gormDB) if err != nil { cleanup16() cleanup15() cleanup14() cleanup13() cleanup12() cleanup11() cleanup10() cleanup9() cleanup8() cleanup7() cleanup6() cleanup5() cleanup4() cleanup3() cleanup2() cleanup() return nil, nil, err } repoRepo, cleanup18, err := repo.Provider(usersRepo) if err != nil { cleanup17() cleanup16() cleanup15() cleanup14() cleanup13() cleanup12() cleanup11() cleanup10() cleanup9() cleanup8() cleanup7() cleanup6() cleanup5() cleanup4() cleanup3() cleanup2() cleanup() return nil, nil, err } managers := graphql_resolver.Managers{ Repo: repoRepo, PollManager: poolManager, } graphqlConfig, cleanup19, err := graphql_resolver.Provider(context, zap, graphql_resolverConfig, enforcer, managers) if err != nil { cleanup18() cleanup17() cleanup16() cleanup15() cleanup14() cleanup13() cleanup12() cleanup11() cleanup10() cleanup9() cleanup8() cleanup7() cleanup6() cleanup5() cleanup4() cleanup3() cleanup2() cleanup() return nil, nil, err } config2, cleanup20, err := graphql.Cfg(viper) if err != nil { cleanup19() cleanup18() cleanup17() cleanup16() cleanup15() cleanup14() cleanup13() cleanup12() cleanup11() cleanup10() cleanup9() cleanup8() cleanup7() cleanup6() cleanup5() cleanup4() cleanup3() cleanup2() cleanup() return nil, nil, err } graphQL, cleanup21, err := graphql.Provider(context, graphqlConfig, zap, config2) if err != nil { cleanup20() cleanup19() cleanup18() cleanup17() cleanup16() cleanup15() cleanup14() cleanup13() cleanup12() cleanup11() cleanup10() cleanup9() cleanup8() cleanup7() cleanup6() cleanup5() cleanup4() cleanup3() cleanup2() cleanup() return nil, nil, err } httpManagers := Managers{ products: manager, authMiddleware: middleware, graphql: graphQL, } mux, cleanup22, err := Mux(httpManagers, zap) if err != nil { cleanup21() cleanup20() cleanup19() cleanup18() cleanup17() cleanup16() cleanup15() cleanup14() cleanup13() cleanup12() cleanup11() cleanup10() cleanup9() cleanup8() cleanup7() cleanup6() cleanup5() cleanup4() cleanup3() cleanup2() cleanup() return nil, nil, err } httpConfig, cleanup23, err := Cfg(viper) if err != nil { cleanup22() cleanup21() cleanup20() cleanup19() cleanup18() cleanup17() cleanup16() cleanup15() cleanup14() cleanup13() cleanup12() cleanup11() cleanup10() cleanup9() cleanup8() cleanup7() cleanup6() cleanup5() cleanup4() cleanup3() cleanup2() cleanup() return nil, nil, err } http, cleanup24, err := Provider(context, mux, zap, httpConfig) if err != nil { cleanup23() cleanup22() cleanup21() cleanup20() cleanup19() cleanup18() cleanup17() cleanup16() cleanup15() cleanup14() cleanup13() cleanup12() cleanup11() cleanup10() cleanup9() cleanup8() cleanup7() cleanup6() cleanup5() cleanup4() cleanup3() cleanup2() cleanup() return nil, nil, err } return http, func() { cleanup24() cleanup23() cleanup22() cleanup21() cleanup20() cleanup19() cleanup18() cleanup17() cleanup16() cleanup15() cleanup14() cleanup13() cleanup12() cleanup11() cleanup10() cleanup9() cleanup8() cleanup7() cleanup6() cleanup5() cleanup4() cleanup3() cleanup2() cleanup() }, nil } ================================================ FILE: app/http_routers/products-router/injector.go ================================================ // +build wireinject package products_router import ( "github.com/aristat/golang-example-app/app/provider" "github.com/google/wire" ) // Build func Build() (*Manager, func(), error) { panic(wire.Build(ProviderProductionSet, provider.AwareProductionSet)) } func BuildTest() (*Manager, func(), error) { panic(wire.Build(ProviderTestSet, provider.AwareTestSet)) } ================================================ FILE: app/http_routers/products-router/manager.go ================================================ package products_router import ( "context" "github.com/aristat/golang-example-app/app/grpc" "github.com/aristat/golang-example-app/app/logger" ) const prefix = "app.products-router" // Product Manager type Manager struct { ctx context.Context logger logger.Logger Router *Router } // ServiceManagers type ServiceManagers struct { PoolManager *grpc.PoolManager } func New(ctx context.Context, log logger.Logger, managers ServiceManagers, cfg *Config) *Manager { log = log.WithFields(logger.Fields{"service": prefix}) router := &Router{ ctx: ctx, cfg: cfg, logger: log, poolManager: managers.PoolManager, } return &Manager{ ctx: ctx, logger: log, Router: router, } } ================================================ FILE: app/http_routers/products-router/provider.go ================================================ package products_router import ( "context" "github.com/aristat/golang-example-app/app/logger" "github.com/google/wire" "github.com/spf13/viper" ) // Cfg func Cfg(cfg *viper.Viper) (*Config, func(), error) { c := &Config{} e := cfg.UnmarshalKey("products", c) if e != nil { return c, func() {}, e } return c, func() {}, e } // CfgTest func CfgTest() (*Config, func(), error) { return &Config{}, func() {}, nil } // Config type Config struct { NatsURL string Subject string } var ProviderManagers = wire.NewSet( wire.Struct(new(ServiceManagers), "*"), ) // Provider func Provider(ctx context.Context, log logger.Logger, managers ServiceManagers, cfg *Config) (*Manager, func(), error) { g := New(ctx, log, managers, cfg) return g, func() {}, nil } var ( ProviderProductionSet = wire.NewSet(Provider, ProviderManagers, Cfg) ProviderTestSet = wire.NewSet(Provider, ProviderManagers, CfgTest) ) ================================================ FILE: app/http_routers/products-router/router.go ================================================ package products_router import ( "context" "encoding/json" "net/http" "time" "github.com/nats-io/stan.go" "github.com/aristat/golang-example-app/app/common" "github.com/go-chi/chi/v5" "github.com/nats-io/nats.go" "github.com/aristat/golang-example-app/app/grpc" "github.com/aristat/golang-example-app/app/logger" "github.com/aristat/golang-example-app/generated/resources/proto/products" ) type Router struct { ctx context.Context cfg *Config logger logger.Logger poolManager *grpc.PoolManager } func (router *Router) Run(chiRouter chi.Router) { chiRouter.Get("/products_grpc", router.GetProductsGrpc) chiRouter.Get("/products_nats", router.GetProductsNats) chiRouter.Get("/products_slowly", router.GetProductsSlowly) } func (router *Router) GetProductsGrpc(w http.ResponseWriter, r *http.Request) { conn, d, err := grpc.GetConnGRPC(router.poolManager, common.SrvProducts) defer d() defer r.Body.Close() if err != nil { router.logger.Printf("[ERROR] %s", err.Error()) http.Error(w, err.Error(), http.StatusInternalServerError) return } c := products.NewProductsClient(conn) ctx, cancel := context.WithTimeout(r.Context(), time.Second) defer cancel() e := json.NewEncoder(w) productOut, err := c.ListProduct(ctx, &products.ListProductIn{Id: 1}) if err != nil { w.WriteHeader(http.StatusBadGateway) e.Encode("{}") return } e.Encode(productOut) } func (router *Router) GetProductsNats(w http.ResponseWriter, r *http.Request) { // Connect to NATS nc, err := nats.Connect(router.cfg.NatsURL) if err != nil { router.logger.Error(err.Error()) http.Error(w, err.Error(), http.StatusInternalServerError) return } defer nc.Close() sc, err := stan.Connect("test-cluster", "stan-pub", stan.NatsConn(nc)) if err != nil { router.logger.Error(err.Error()) http.Error(w, err.Error(), http.StatusInternalServerError) return } // Close connection defer sc.Close() message := "Hello" router.logger.Printf("[NATS] send %s", message) err = sc.Publish(router.cfg.Subject, []byte(message)) if err != nil { router.logger.Printf("[ERROR] %s", err.Error()) http.Error(w, err.Error(), http.StatusInternalServerError) return } e := json.NewEncoder(w) e.Encode("done") } func (router *Router) GetProductsSlowly(w http.ResponseWriter, r *http.Request) { router.logger.Info("Start sleep") time.Sleep(time.Second * 10) router.logger.Info("Stop sleep") e := json.NewEncoder(w) e.Encode("") } ================================================ FILE: app/http_routers/products-router/router_test.go ================================================ package products_router_test import ( "context" "log" "net" "net/http" "net/http/httptest" "os" "strconv" "strings" "testing" products_router "github.com/aristat/golang-example-app/app/http_routers/products-router" "github.com/stretchr/testify/assert" "github.com/aristat/golang-example-app/app/common" grpc1 "github.com/aristat/golang-example-app/app/grpc" "github.com/aristat/golang-example-app/app/graphql_resolver" "github.com/aristat/golang-example-app/generated/resources/proto/products" "google.golang.org/grpc" ) var ( productServerHost = "localhost" grpcPort string ) func TestMain(m *testing.M) { lis, err := net.Listen("tcp", ":0") if err != nil { log.Fatalf(err.Error()) } defer lis.Close() grpcPort = ":" + strconv.Itoa(lis.Addr().(*net.TCPAddr).Port) s := grpc.NewServer() products.RegisterProductsServer(s, &graphql_resolver.ProductServerMock{}) go func() { if err := s.Serve(lis); err != nil { log.Fatalf("Server exited with error: %v", err) } }() code := m.Run() os.Exit(code) } func TestGetProductsGrpc(t *testing.T) { var opts []grpc.DialOption ctx := context.Background() opts = append(opts, grpc.WithInsecure()) pool, _ := grpc1.NewPool(ctx, common.SrvProducts, productServerHost+grpcPort, grpc1.ConnOptions(opts...)) grpc1.SetPool(pool, common.SrvProducts) tests := []struct { name string expectedCode int }{ { name: "successful", expectedCode: http.StatusOK, }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { provider, _, e := products_router.BuildTest() assert.Nil(t, e, "err should be nil") rec := httptest.NewRecorder() req, _ := http.NewRequest(http.MethodGet, "/products_grpc", strings.NewReader("")) provider.Router.GetProductsGrpc(rec, req) assert.Equal(t, test.expectedCode, rec.Code) assert.NotNil(t, rec.Body) }) } } ================================================ FILE: app/http_routers/products-router/wire_gen.go ================================================ // Code generated by Wire. DO NOT EDIT. //go:generate go run github.com/google/wire/cmd/wire //go:build !wireinject // +build !wireinject package products_router import ( "github.com/aristat/golang-example-app/app/config" "github.com/aristat/golang-example-app/app/entrypoint" "github.com/aristat/golang-example-app/app/grpc" "github.com/aristat/golang-example-app/app/logger" "github.com/aristat/golang-example-app/app/tracing" ) // Injectors from injector.go: // Build func Build() (*Manager, func(), error) { context, cleanup, err := entrypoint.ContextProvider() if err != nil { return nil, nil, err } viper, cleanup2, err := config.Provider() if err != nil { cleanup() return nil, nil, err } loggerConfig, cleanup3, err := logger.ProviderCfg(viper) if err != nil { cleanup2() cleanup() return nil, nil, err } zap, cleanup4, err := logger.Provider(context, loggerConfig) if err != nil { cleanup3() cleanup2() cleanup() return nil, nil, err } configuration, cleanup5, err := tracing.Cfg(viper) if err != nil { cleanup4() cleanup3() cleanup2() cleanup() return nil, nil, err } tracerProvider, cleanup6, err := tracing.Provider(context, configuration, zap) if err != nil { cleanup5() cleanup4() cleanup3() cleanup2() cleanup() return nil, nil, err } grpcConfig, cleanup7, err := grpc.Cfg(viper) if err != nil { cleanup6() cleanup5() cleanup4() cleanup3() cleanup2() cleanup() return nil, nil, err } poolManager, cleanup8, err := grpc.Provider(context, tracerProvider, zap, grpcConfig) if err != nil { cleanup7() cleanup6() cleanup5() cleanup4() cleanup3() cleanup2() cleanup() return nil, nil, err } serviceManagers := ServiceManagers{ PoolManager: poolManager, } products_routerConfig, cleanup9, err := Cfg(viper) if err != nil { cleanup8() cleanup7() cleanup6() cleanup5() cleanup4() cleanup3() cleanup2() cleanup() return nil, nil, err } manager, cleanup10, err := Provider(context, zap, serviceManagers, products_routerConfig) if err != nil { cleanup9() cleanup8() cleanup7() cleanup6() cleanup5() cleanup4() cleanup3() cleanup2() cleanup() return nil, nil, err } return manager, func() { cleanup10() cleanup9() cleanup8() cleanup7() cleanup6() cleanup5() cleanup4() cleanup3() cleanup2() cleanup() }, nil } func BuildTest() (*Manager, func(), error) { context, cleanup, err := entrypoint.ContextProviderTest() if err != nil { return nil, nil, err } loggerConfig, cleanup2, err := logger.ProviderCfgTest() if err != nil { cleanup() return nil, nil, err } mock, cleanup3, err := logger.ProviderTest(context, loggerConfig) if err != nil { cleanup2() cleanup() return nil, nil, err } tracerProvider, cleanup4, err := tracing.ProviderTest() if err != nil { cleanup3() cleanup2() cleanup() return nil, nil, err } grpcConfig, cleanup5, err := grpc.CfgTest() if err != nil { cleanup4() cleanup3() cleanup2() cleanup() return nil, nil, err } poolManager, cleanup6, err := grpc.Provider(context, tracerProvider, mock, grpcConfig) if err != nil { cleanup5() cleanup4() cleanup3() cleanup2() cleanup() return nil, nil, err } serviceManagers := ServiceManagers{ PoolManager: poolManager, } products_routerConfig, cleanup7, err := CfgTest() if err != nil { cleanup6() cleanup5() cleanup4() cleanup3() cleanup2() cleanup() return nil, nil, err } manager, cleanup8, err := Provider(context, mock, serviceManagers, products_routerConfig) if err != nil { cleanup7() cleanup6() cleanup5() cleanup4() cleanup3() cleanup2() cleanup() return nil, nil, err } return manager, func() { cleanup8() cleanup7() cleanup6() cleanup5() cleanup4() cleanup3() cleanup2() cleanup() }, nil } ================================================ FILE: app/logger/injector.go ================================================ // +build wireinject package logger import ( "github.com/aristat/golang-example-app/app/config" "github.com/aristat/golang-example-app/app/entrypoint" "github.com/google/wire" ) // Build returns logger instance implemented of Logger interface with resolved dependencies func Build() (Logger, func(), error) { panic(wire.Build(ProviderProductionSet, entrypoint.ProviderProductionSet, config.ProviderSet)) } func BuildTest() (Logger, func(), error) { panic(wire.Build(ProviderTestSet, entrypoint.ProviderTestSet)) } ================================================ FILE: app/logger/logger.go ================================================ package logger type ( Fields map[string]interface{} ) // Level represent RFC5424 logger severity type Level int8 // String implements interface Stringer func (l Level) String() string { switch l { case LevelDebug: return "debug" case LevelInfo: return "info" case LevelNotice: return "notice" case LevelWarning: return "warning" case LevelError: return "error" case LevelCritical: return "critical" case LevelAlert: return "alert" case LevelEmergency: return "emergency" } return "unknown" } // FromString set logger level from string representation func (l *Level) FromString(level string) Level { switch level { case "debug": *l = LevelDebug case "info": *l = LevelInfo case "notice": *l = LevelNotice case "warning": *l = LevelWarning case "error": *l = LevelError case "critical": *l = LevelCritical case "alert": *l = LevelAlert case "emergency": *l = LevelEmergency } return *l } const ( // Debug: debug-level messages LevelDebug Level = 7 // Informational: informational messages LevelInfo Level = 6 // Notice: normal but significant condition LevelNotice Level = 5 // Warning: warning conditions LevelWarning Level = 4 // Error: error conditions LevelError Level = 3 // Critical: critical conditions LevelCritical Level = 2 // Alert: action must be taken immediately LevelAlert Level = 1 // Emergency: system is unusable LevelEmergency Level = 0 ) type opts struct { args []interface{} fields Fields } // Option is func hook for underling logic call type Option func(*opts) error // Args returns func hook a logger for replace fmt placeholders on represent values func Args(a ...interface{}) Option { return func(f *opts) error { f.args = a return nil } } // WithFields returns func hook a logger for adding fields for call func WithFields(fields Fields) Option { return func(f *opts) error { f.fields = fields return nil } } // Config is a general logger config settings type Config struct { Debug bool } // Logger is the interface for logger client type Logger interface { // Printf is like fmt.Printf, push to log entry with debug level Printf(format string, a ...interface{}) // Emergency push to log entry with emergency level & throw panic Emergency(format string, opts ...Option) // Alert push to log entry with alert level Alert(format string, opts ...Option) // Critical push to log entry with critical level Critical(format string, opts ...Option) // Error push to log entry with error level Error(format string, opts ...Option) // Warning push to log entry with warning level Warning(format string, opts ...Option) // Notice push to log entry with notice level Notice(format string, opts ...Option) // Info push to log entry with info level Info(format string, opts ...Option) // Debug push to log entry with debug level Debug(format string, opts ...Option) // Write push to log entry with debug level Write(p []byte) (n int, err error) // Log push to log with specified level Log(level Level, format string, opts ...Option) // WithFields create new instance with fields WithFields(fields Fields) Logger } ================================================ FILE: app/logger/middleware.go ================================================ package logger import ( "context" "strings" "time" "google.golang.org/grpc" ) // UnaryClientInterceptor wrapper to logging query func UnaryClientInterceptor(log Logger, enable bool) grpc.UnaryClientInterceptor { return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { if !enable { return invoker(ctx, method, req, reply, cc, opts...) } startTime := time.Now() err := invoker(ctx, method, req, reply, cc, opts...) var e string if err != nil { e = strings.ReplaceAll(err.Error(), "\n", "") } log.Debug("\nQUERY UnaryClient:\n\nData: %v\n\nERROR:\n%v\n\n", Args(req, e), WithFields(Fields{ "time": time.Since(startTime).String(), })) return err } } // StreamClientInterceptor returns a new streaming client interceptor func StreamClientInterceptor(log Logger, enable bool) grpc.StreamClientInterceptor { return func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) { if !enable { return streamer(ctx, desc, cc, method, opts...) } startTime := time.Now() clientStream, err := streamer(ctx, desc, cc, method, opts...) var e string if err != nil { e = strings.ReplaceAll(err.Error(), "\n", "") } log.Debug("\nQUERY StreamClient:\n\nMethod: %v\n\nERROR:\n%v\n\n", Args(method, e), WithFields(Fields{ "time": time.Since(startTime).String(), })) return clientStream, err } } // UnaryServerInterceptor wrapper to logging query func UnaryServerInterceptor(log Logger, enable bool) grpc.UnaryServerInterceptor { return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { if !enable { return handler(ctx, req) } startTime := time.Now() res, err := handler(ctx, req) var e string if err != nil { e = strings.ReplaceAll(err.Error(), "\n", "") } log.Debug("\nQUERY UnaryServer:\n\nFullMethod: %v\nData: %v\nRESPONSE:\n\nData: %v\nERROR:\n%v\n", Args(info.FullMethod, req, res, e), WithFields(Fields{ "time": time.Since(startTime).String(), })) return res, err } } // StreamServerInterceptor returns a new streaming server interceptor func StreamServerInterceptor(log Logger, enable bool) grpc.StreamServerInterceptor { return func(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { if !enable { return handler(srv, stream) } startTime := time.Now() err := handler(srv, stream) var e string if err != nil { e = strings.ReplaceAll(err.Error(), "\n", "") } log.Debug("\nQUERY StreamServer:\n\nFullMethod: %v\n\nERROR:\n%v\n", Args(info.FullMethod, e), WithFields(Fields{ "time": time.Since(startTime).String(), })) return err } } ================================================ FILE: app/logger/mock.go ================================================ package logger import ( "context" ) // Entity represent log struct with all assets type Entity struct { Level Level Fields Fields Args []interface{} Format string } // Mock is the logger with stubbed methods type Mock struct { ctx context.Context ch chan Entity discard bool cfg Config fields map[string]interface{} } // Printf is like fmt.Printf, push to log entry with debug level func (m *Mock) Printf(format string, a ...interface{}) { m.Debug(format, Args(a...)) } // Emergency push to log entry with emergency level & throw panic func (m *Mock) Emergency(format string, opts ...Option) { m.Log(LevelEmergency, format, opts...) } // Alert push to log entry with alert level func (m *Mock) Alert(format string, opts ...Option) { m.Log(LevelAlert, format, opts...) } // Critical push to log entry with critical level func (m *Mock) Critical(format string, opts ...Option) { m.Log(LevelCritical, format, opts...) } // Error push to log entry with error level func (m *Mock) Error(format string, opts ...Option) { m.Log(LevelError, format, opts...) } // Warning push to log entry with warning level func (m *Mock) Warning(format string, opts ...Option) { m.Log(LevelWarning, format, opts...) } // Notice push to log entry with notice level func (m *Mock) Notice(format string, opts ...Option) { m.Log(LevelNotice, format, opts...) } // Info push to log entry with info level func (m *Mock) Info(format string, opts ...Option) { m.Log(LevelInfo, format, opts...) } // Debug push to log entry with debug level func (m *Mock) Debug(format string, opts ...Option) { m.Log(LevelDebug, format, opts...) } // Write push to log entry with debug level func (m *Mock) Write(p []byte) (n int, err error) { m.Debug(string(p)) return len(p), nil } // Log push to log with specified level func (m *Mock) Log(level Level, format string, o ...Option) { if !m.discard { return } opts := &opts{} for _, option := range o { _ = option(opts) } var ( fields = map[string]interface{}{} ) // fields for k, v := range m.fields { fields[k] = v } for k, v := range opts.fields { fields[k] = v } go func() { m.ch <- Entity{ Level: level, Format: format, Args: opts.args, Fields: fields, } }() } // WithFields create new instance with fields func (m *Mock) WithFields(fields Fields) Logger { nm := &Mock{} copyMock(nm, m, fields) return nm } func copyMock(dst, src *Mock, fields map[string]interface{}) { var cFields = map[string]interface{}{} // fields for k, v := range src.fields { cFields[k] = v } dst.fields = cFields if fields != nil { for k, v := range fields { dst.fields[k] = v } } dst.discard = src.discard dst.ch = src.ch } // Catch returns channel of entity structure for testing event content func (m *Mock) Catch() <-chan Entity { return m.ch } // NewMock returns mock instance implemented of Logger interface func newMock(ctx context.Context, cfg Config, discard bool) *Mock { return &Mock{ ctx: ctx, cfg: cfg, ch: make(chan Entity), discard: discard, } } ================================================ FILE: app/logger/provider.go ================================================ package logger import ( "context" "github.com/google/wire" "github.com/spf13/viper" ) // ProviderCfg returns configuration for production logger func ProviderCfg(cfg *viper.Viper) (Config, func(), error) { c := Config{} e := cfg.UnmarshalKey("logger", &c) if e != nil { return c, func() {}, e } if cfg.IsSet("debug") && !c.Debug { c.Debug = cfg.GetBool("debug") } return c, func() {}, nil } // ProviderCfgTest returns configuration for stub/mock logger func ProviderCfgTest() (Config, func(), error) { return Config{}, func() {}, nil } // Provider returns logger instance implemented of Logger interface with resolved dependencies func Provider(ctx context.Context, cfg Config) (*Zap, func(), error) { return newZap(ctx, cfg), func() {}, nil } // ProviderTest returns stub/mock logger instance implemented of Logger interface with resolved dependencies func ProviderTest(ctx context.Context, cfg Config) (*Mock, func(), error) { mock := newMock(ctx, cfg, true) cleanup := func() { if mock.ch != nil { close(mock.ch) } } return mock, cleanup, nil } var ( ProviderProductionSet = wire.NewSet(Provider, ProviderCfg, wire.Bind(new(Logger), new(*Zap))) ProviderTestSet = wire.NewSet(ProviderTest, ProviderCfgTest, wire.Bind(new(Logger), new(*Mock))) ) ================================================ FILE: app/logger/wire_gen.go ================================================ // Code generated by Wire. DO NOT EDIT. //go:generate go run github.com/google/wire/cmd/wire //go:build !wireinject // +build !wireinject package logger import ( "github.com/aristat/golang-example-app/app/config" "github.com/aristat/golang-example-app/app/entrypoint" ) // Injectors from injector.go: // Build returns logger instance implemented of Logger interface with resolved dependencies func Build() (Logger, func(), error) { context, cleanup, err := entrypoint.ContextProvider() if err != nil { return nil, nil, err } viper, cleanup2, err := config.Provider() if err != nil { cleanup() return nil, nil, err } loggerConfig, cleanup3, err := ProviderCfg(viper) if err != nil { cleanup2() cleanup() return nil, nil, err } zap, cleanup4, err := Provider(context, loggerConfig) if err != nil { cleanup3() cleanup2() cleanup() return nil, nil, err } return zap, func() { cleanup4() cleanup3() cleanup2() cleanup() }, nil } func BuildTest() (Logger, func(), error) { context, cleanup, err := entrypoint.ContextProviderTest() if err != nil { return nil, nil, err } loggerConfig, cleanup2, err := ProviderCfgTest() if err != nil { cleanup() return nil, nil, err } mock, cleanup3, err := ProviderTest(context, loggerConfig) if err != nil { cleanup2() cleanup() return nil, nil, err } return mock, func() { cleanup3() cleanup2() cleanup() }, nil } ================================================ FILE: app/logger/zap.go ================================================ package logger import ( "context" "go.uber.org/zap/zapcore" "go.uber.org/zap" ) // Zap is uber/zap logger implemented of Logger interface type Zap struct { ctx context.Context cfg Config logger *zap.SugaredLogger fields map[string]interface{} } // Printf is like fmt.Printf, push to log entry with debug level func (z *Zap) Printf(format string, a ...interface{}) { z.Debug(format, Args(a...)) } // Emergency push to log entry with emergency level & throw panic func (z *Zap) Emergency(format string, opts ...Option) { z.Log(LevelEmergency, format, opts...) } // Alert push to log entry with alert level func (z *Zap) Alert(format string, opts ...Option) { z.Log(LevelAlert, format, opts...) } // Critical push to log entry with critical level func (z *Zap) Critical(format string, opts ...Option) { z.Log(LevelCritical, format, opts...) } // Error push to log entry with error level func (z *Zap) Error(format string, opts ...Option) { z.Log(LevelError, format, opts...) } // Warning push to log entry with warning level func (z *Zap) Warning(format string, opts ...Option) { z.Log(LevelWarning, format, opts...) } // Notice push to log entry with notice level func (z *Zap) Notice(format string, opts ...Option) { z.Log(LevelNotice, format, opts...) } // Info push to log entry with info level func (z *Zap) Info(format string, opts ...Option) { z.Log(LevelInfo, format, opts...) } // Debug push to log entry with debug level func (z *Zap) Debug(format string, opts ...Option) { z.Log(LevelDebug, format, opts...) } // Write push to log entry with debug level func (z *Zap) Write(p []byte) (n int, err error) { z.Debug(string(p)) return len(p), nil } // Log push to log with specified level func (z *Zap) Log(level Level, format string, o ...Option) { opts := &opts{} for _, option := range o { _ = option(opts) } var ( wargs = []interface{}{"level", level.String()} ) // fields for k, v := range z.fields { wargs = append(wargs, k, v) } for k, v := range opts.fields { wargs = append(wargs, k, v) } var logger = z.logger if len(wargs) > 0 { logger = logger.With(wargs...) } if len(opts.args) == 0 { var fn func(args ...interface{}) switch level { default: fn = logger.Debug case LevelInfo, LevelNotice: fn = logger.Info case LevelWarning: fn = logger.Warn case LevelError, LevelCritical, LevelAlert: fn = logger.Error case LevelEmergency: fn = logger.Panic } fn(format) } else { var fn func(format string, args ...interface{}) switch level { default: fn = logger.Debugf case LevelInfo, LevelNotice: fn = logger.Infof case LevelWarning: fn = logger.Warnf case LevelError, LevelCritical, LevelAlert: fn = logger.Errorf case LevelEmergency: fn = logger.Panicf } fn(format, opts.args...) } } // WithFields create new instance with fields func (z *Zap) WithFields(fields Fields) Logger { nz := &Zap{} copyZap(nz, z, fields) return nz } func copyZap(dst, src *Zap, fields map[string]interface{}) { var cFields = map[string]interface{}{} // fields for k, v := range src.fields { cFields[k] = v } dst.fields = cFields if fields != nil { for k, v := range fields { dst.fields[k] = v } } dst.logger = src.logger } // NewZap returns zap logger func newZap(ctx context.Context, cfg Config) *Zap { var logger *zap.Logger if !cfg.Debug { cfg := zap.NewProductionConfig() logger, _ = cfg.Build(zap.AddCallerSkip(3), zap.AddStacktrace(zap.WarnLevel)) } else { cfg := zap.NewDevelopmentConfig() cfg.EncoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder logger, _ = cfg.Build(zap.AddCallerSkip(3), zap.AddStacktrace(zap.WarnLevel)) } go func(logger *zap.Logger) { <-ctx.Done() _ = logger.Sync() }(logger) return &Zap{ctx: ctx, cfg: cfg, logger: logger.Sugar()} } ================================================ FILE: app/provider/provider.go ================================================ package provider import ( "github.com/aristat/golang-example-app/app/casbin" "github.com/aristat/golang-example-app/app/config" "github.com/aristat/golang-example-app/app/entrypoint" "github.com/aristat/golang-example-app/app/grpc" "github.com/aristat/golang-example-app/app/logger" "github.com/aristat/golang-example-app/app/tracing" "github.com/google/wire" ) var AwareProductionSet = wire.NewSet( entrypoint.ProviderProductionSet, logger.ProviderProductionSet, config.ProviderSet, tracing.ProviderProductionSet, grpc.ProviderProductionSet, casbin.ProviderProductionSet, ) var AwareTestSet = wire.NewSet( entrypoint.ProviderTestSet, logger.ProviderTestSet, tracing.ProviderTestSet, grpc.ProviderTestSet, casbin.ProviderTestSet, ) ================================================ FILE: app/tracing/jaeger.go ================================================ package tracing import ( "context" "go.opentelemetry.io/otel/exporters/jaeger" "go.opentelemetry.io/otel/sdk/resource" tracesdk "go.opentelemetry.io/otel/sdk/trace" semconv "go.opentelemetry.io/otel/semconv/v1.4.0" "github.com/aristat/golang-example-app/app/logger" "github.com/pkg/errors" ) type Configuration struct { AgentHost string AgentPort string ServiceName string } const prefix = "app.tracer" func newJaegerTracer(ctx context.Context, configuration *Configuration, log logger.Logger) (*tracesdk.TracerProvider, error) { log = log.WithFields(logger.Fields{"service": prefix}) exp, err := jaeger.New( jaeger.WithAgentEndpoint( jaeger.WithAgentHost(configuration.AgentHost), jaeger.WithAgentPort(configuration.AgentPort), ), ) if err != nil { return nil, errors.WithMessage(err, prefix) } tracer := tracesdk.NewTracerProvider( tracesdk.WithBatcher(exp), tracesdk.WithResource(resource.NewWithAttributes( semconv.SchemaURL, semconv.ServiceNameKey.String(configuration.ServiceName), )), ) go func() { <-ctx.Done() if err := tracer.Shutdown(ctx); err != nil { log.Printf("Error shutting down tracer provider: %v", err) } }() return tracer, errors.WithMessage(err, prefix) } ================================================ FILE: app/tracing/provider.go ================================================ package tracing import ( "context" "go.opentelemetry.io/otel/propagation" "github.com/google/wire" "github.com/spf13/viper" tracesdk "go.opentelemetry.io/otel/sdk/trace" "go.opentelemetry.io/otel" "github.com/aristat/golang-example-app/app/logger" ) // Cfg func Cfg(cfg *viper.Viper) (*Configuration, func(), error) { c := Configuration{} e := cfg.UnmarshalKey("tracing.jaeger", &c) if e != nil { return nil, func() {}, e } return &c, func() {}, nil } // Provider func Provider(ctx context.Context, configuration *Configuration, log logger.Logger) (*tracesdk.TracerProvider, func(), error) { t, e := newJaegerTracer(ctx, configuration, log) otel.SetTracerProvider(t) otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{})) return t, func() {}, e } // ProviderTest func ProviderTest() (*tracesdk.TracerProvider, func(), error) { m := tracesdk.NewTracerProvider() return m, func() {}, nil } var ( ProviderProductionSet = wire.NewSet(Provider, Cfg) ProviderTestSet = wire.NewSet(ProviderTest) ) ================================================ FILE: cmd/daemon/daemon.go ================================================ package daemon import ( "context" "os" "os/signal" "sync" "syscall" "time" "github.com/aristat/golang-example-app/app/entrypoint" "github.com/aristat/golang-example-app/app/http" "github.com/aristat/golang-example-app/app/logger" "github.com/spf13/cobra" ) var ( bind string gracefulDelay time.Duration Cmd = &cobra.Command{ Use: "daemon", Short: "Gateway API daemon", SilenceUsage: true, SilenceErrors: true, Run: func(_ *cobra.Command, _ []string) { var ( e error s *http.Http c func() ) log, c, e := logger.Build() if e != nil { panic(e) } defer c() defer func() { if r := recover(); r != nil { if re, _ := r.(error); re != nil { log.Error(re.Error()) } else { log.Alert("unhandled panic, err: %v", logger.Args(r)) } } }() s, c, e = http.Build() if e != nil { log.Error(e.Error()) return } defer c() wg := &sync.WaitGroup{} wg.Add(1) server := s.ListenAndServe(wg, bind) shutdownSignal := make(chan os.Signal) signal.Notify(shutdownSignal, syscall.SIGTERM, syscall.SIGINT) sig := <-shutdownSignal log.Printf("OS signaled `%v`\n", sig.String()) log.Info("Server shutdown is raised") if e := server.Shutdown(context.Background()); e != nil { log.Emergency("Graceful shutdown error, %v", logger.Args(e)) } wg.Wait() log.Printf("Graceful shutdown in %s\n", gracefulDelay) ctx, _ := context.WithTimeout(context.Background(), gracefulDelay) entrypoint.Shutdown(ctx, 0) }, } ) func init() { Cmd.PersistentFlags().StringVarP(&bind, "bind", "b", ":9096", "bind address") Cmd.PersistentFlags().DurationVar(&gracefulDelay, "graceful.delay", 50*time.Millisecond, "graceful delay") } ================================================ FILE: cmd/health-check-service/health_check_service.go ================================================ package health_check_service import ( "context" "log" "math/rand" "net" "time" "go.opentelemetry.io/otel/propagation" "go.opentelemetry.io/otel" "github.com/aristat/golang-example-app/app/config" "github.com/aristat/golang-example-app/app/logger" "github.com/aristat/golang-example-app/app/common" "github.com/aristat/golang-example-app/generated/resources/proto/health_checks" "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" emptypb "google.golang.org/protobuf/types/known/emptypb" "github.com/spf13/cobra" "google.golang.org/grpc" ) // Config type Config struct { Port string RandomDisable bool } type server struct { cfg Config health_checks.UnimplementedHealthChecksServer } func (s *server) IsAlive(ctx context.Context, empty *emptypb.Empty) (*health_checks.IsAliveOut, error) { if s.cfg.RandomDisable { return &health_checks.IsAliveOut{Status: health_checks.IsAliveOut_OK}, nil } var status health_checks.IsAliveOut_Status rand.Seed(time.Now().UTC().UnixNano()) number := rand.Intn(2-0) + 0 if number == 1 { status = health_checks.IsAliveOut_OK } else { status = health_checks.IsAliveOut_NOT_OK } return &health_checks.IsAliveOut{Status: status}, nil } // Example service, which need for testing jaeger and grpc pool var ( //bind string Cmd = &cobra.Command{ Use: "health-check", Short: "Health check", SilenceUsage: true, SilenceErrors: true, Run: func(_ *cobra.Command, _ []string) { conf, c, e := config.Build() if e != nil { panic(e) } defer c() clientConfig := Config{} e = conf.UnmarshalKey("services.healthCheckService", &clientConfig) if e != nil { log.Fatal("Config initialize error") } log, c, e := logger.Build() if e != nil { panic(e) } defer c() defer func() { if r := recover(); r != nil { if re, _ := r.(error); re != nil { log.Error(re.Error()) } else { log.Alert("unhandled panic, err: %v", logger.Args(r)) } } }() tracer, e := common.GenerateTracerForTestClient("golang-example-app-health-check-service", conf) otel.SetTracerProvider(tracer) if e != nil { panic(e) } defer func() { if err := tracer.Shutdown(context.Background()); err != nil { log.Printf("Error shutting down tracer provider: %v", err) } }() lis, err := net.Listen("tcp", ":"+clientConfig.Port) if err != nil { panic(err) } s := grpc.NewServer( grpc.ChainUnaryInterceptor( logger.UnaryServerInterceptor(log, true), otelgrpc.UnaryServerInterceptor(otelgrpc.WithTracerProvider(tracer), otelgrpc.WithPropagators(propagation.TraceContext{})), ), grpc.ChainStreamInterceptor( logger.StreamServerInterceptor(log, true), otelgrpc.StreamServerInterceptor(otelgrpc.WithTracerProvider(tracer), otelgrpc.WithPropagators(propagation.TraceContext{})), ), ) health_checks.RegisterHealthChecksServer(s, &server{cfg: clientConfig}) if err := s.Serve(lis); err != nil { panic(err) } }, } ) func init() { } ================================================ FILE: cmd/jwt/jwt.go ================================================ package jwt import "github.com/spf13/cobra" var Cmd = &cobra.Command{ Use: "jwt", Short: "Tools for generate JWT", SilenceUsage: true, SilenceErrors: true, } func init() { Cmd.AddCommand(tokenCmd) } ================================================ FILE: cmd/jwt/token.go ================================================ package jwt import ( "encoding/json" "fmt" "io/ioutil" "os" "time" "github.com/spf13/cast" "github.com/golang-jwt/jwt" "github.com/spf13/cobra" ) var ( jwtFlagPrivateKey string jwtFlagFields string ) func init() { tokenCmd.PersistentFlags().StringVar(&jwtFlagPrivateKey, "key", "", "private key") tokenCmd.PersistentFlags().StringVar(&jwtFlagFields, "fields", "", "JWT fields in JSON format") } var tokenCmd = &cobra.Command{ Use: "token", Short: "Generate JWT token with sign", Example: `jwt --key='{path to private key}' --fields='{in json format {"key":"value"} }'`, SilenceUsage: true, SilenceErrors: true, Run: func(cmd *cobra.Command, args []string) { if jwtFlagPrivateKey == "" { fmt.Printf("Flag `key` is required\n") os.Exit(1) } privatePemKey, err := ioutil.ReadFile(jwtFlagPrivateKey) if err != nil { fmt.Printf("Error occurred: %v\n", err.Error()) os.Exit(1) } fields := make(map[string]interface{}) if jwtFlagFields != "" { if err = json.Unmarshal([]byte(jwtFlagFields), &fields); err != nil { fmt.Printf("Parse fields error %v\n", err.Error()) os.Exit(1) } } jwtEncoded, err := GenerateJWT(privatePemKey, fields) if err != nil { fmt.Printf("Error occurred: %v\n", err.Error()) os.Exit(1) } fmt.Println(jwtEncoded) }, } // GenerateJWT returns token signed by private key with filled fields func GenerateJWT(privateKey []byte, fields map[string]interface{}) (string, error) { type CustomClaims struct { UserId int64 `json:"user_id,omitempty"` jwt.StandardClaims } claims := &CustomClaims{} for k, v := range fields { switch k { case "aud": claims.Audience = cast.ToString(v) case "sub": claims.Subject = cast.ToString(v) case "iss": claims.Issuer = cast.ToString(v) case "id": claims.Id = cast.ToString(v) case "exp": claims.ExpiresAt = cast.ToInt64(v) case "user_id": claims.UserId = cast.ToInt64(v) case "nbf": claims.NotBefore = cast.ToInt64(v) case "iat": claims.IssuedAt = time.Now().Unix() } } var ( sPrivateKey interface{} err error ) sPrivateKey, err = jwt.ParseRSAPrivateKeyFromPEM(privateKey) if err != nil { return "", err } token := jwt.NewWithClaims(jwt.SigningMethodRS256, claims) ss, err := token.SignedString(sPrivateKey) if err != nil { return "", err } return ss, nil } ================================================ FILE: cmd/migrate/migrate.go ================================================ package migrate import ( "database/sql" "fmt" "os" "github.com/aristat/golang-example-app/app/entrypoint" _ "github.com/lib/pq" migrate "github.com/rubenv/sql-migrate" "github.com/spf13/cobra" ) var ( argDsn, argTable string argLimit int db *sql.DB ms *migrate.FileMigrationSource initCmdFn = func(cmd *cobra.Command, _ []string) (re error) { var e error defer func() { recover() re = e }() ms = &migrate.FileMigrationSource{ Dir: entrypoint.WorkDir() + "/migrations", } migrate.SetTable(argTable) db, e = sql.Open("postgres", argDsn) if e != nil { return e } return nil } cmdUp = &cobra.Command{ Use: "up", Short: "Migrates the database to the most recent version available", SilenceUsage: true, SilenceErrors: true, Run: func(_ *cobra.Command, _ []string) { if e := initCmdFn(nil, nil); e != nil { fmt.Printf("Failed: %v\n", e.Error()) os.Exit(1) } n, err := migrate.ExecMax(db, "postgres", ms, migrate.Up, argLimit) if err != nil { fmt.Printf("Failed: %v\n", err.Error()) os.Exit(1) } fmt.Printf("Applied %d migrations!\n", n) }, } cmdDown = &cobra.Command{ Use: "down", Short: "Rollback a database migration", SilenceUsage: true, SilenceErrors: true, Run: func(_ *cobra.Command, _ []string) { if e := initCmdFn(nil, nil); e != nil { fmt.Printf("Failed: %v\n", e.Error()) os.Exit(1) } n, err := migrate.ExecMax(db, "postgres", ms, migrate.Down, argLimit) if err != nil { fmt.Printf("Failed: %v\n", err.Error()) os.Exit(1) } fmt.Printf("Applied %d migrations!\n", n) }, } Cmd = &cobra.Command{ Use: "migrate", Short: "SQL migration tool", SilenceUsage: true, SilenceErrors: true, } ) func init() { Cmd.PersistentFlags().StringVar(&argTable, "table", "migrations", "Table for migration history") Cmd.PersistentFlags().IntVar(&argLimit, "limit", 1, "Limit the number of migrations (0 = unlimited)") Cmd.PersistentFlags().StringVar(&argDsn, "dsn", "postgres://localhost:5432/golang_example_development?sslmode=disable", "DSN connection string") Cmd.AddCommand(cmdUp, cmdDown) } ================================================ FILE: cmd/product-service/nats_service.go ================================================ package product_service import ( "github.com/aristat/golang-example-app/app/logger" "github.com/nats-io/stan.go" ) type natsService struct { logger logger.Logger } func (s *natsService) workerHanlder(m *stan.Msg) { s.logger.Info("[NATS] Received a message: %s\n", logger.Args(string(m.Data))) m.Ack() } ================================================ FILE: cmd/product-service/product_service.go ================================================ package product_service import ( "context" "errors" "log" "net" "time" "go.opentelemetry.io/otel/propagation" "google.golang.org/grpc/credentials/insecure" "go.opentelemetry.io/otel" "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" "github.com/nats-io/nats.go" "github.com/nats-io/stan.go" "github.com/aristat/golang-example-app/app/config" "github.com/aristat/golang-example-app/app/common" "github.com/aristat/golang-example-app/app/logger" "github.com/aristat/golang-example-app/generated/resources/proto/health_checks" "github.com/aristat/golang-example-app/generated/resources/proto/products" emptypb "google.golang.org/protobuf/types/known/emptypb" "github.com/spf13/cobra" "google.golang.org/grpc" ) // Config type Config struct { Port string HealthCheckUrl string NatsURL string Subject string } type server struct { logger logger.Logger cfg Config products.UnimplementedProductsServer } func (s *server) ListProduct(ctx context.Context, in *products.ListProductIn) (*products.ListProductOut, error) { tracer := otel.GetTracerProvider() conn, err := grpc.Dial(s.cfg.HealthCheckUrl, grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithChainUnaryInterceptor( logger.UnaryClientInterceptor(s.logger, true), otelgrpc.UnaryClientInterceptor(otelgrpc.WithTracerProvider(tracer), otelgrpc.WithPropagators(propagation.TraceContext{})), ), grpc.WithChainStreamInterceptor( logger.StreamClientInterceptor(s.logger, true), otelgrpc.StreamClientInterceptor(otelgrpc.WithTracerProvider(tracer), otelgrpc.WithPropagators(propagation.TraceContext{})), ), ) if err != nil { return nil, err } defer conn.Close() c := health_checks.NewHealthChecksClient(conn) ctx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() isAliveOut, err := c.IsAlive(ctx, &emptypb.Empty{}) if err != nil { return nil, err } if isAliveOut.Status != health_checks.IsAliveOut_OK { return nil, errors.New("Heal checks not working") } // test result out := &products.ListProductOut{Status: products.ListProductOut_OK, Products: []*products.Product{}} out.Products = append(out.Products, &products.Product{Id: 1, Name: "first_product"}) out.Products = append(out.Products, &products.Product{Id: 2, Name: "second_product"}) return out, nil } // Example service, which gives some data var ( //bind string Cmd = &cobra.Command{ Use: "product-service", Short: "Product service", SilenceUsage: true, SilenceErrors: true, Run: func(_ *cobra.Command, _ []string) { conf, c, e := config.Build() if e != nil { panic(e) } defer c() clientConfig := Config{} e = conf.UnmarshalKey("services.productService", &clientConfig) if e != nil { log.Fatal("Config initialize error") } log, c, e := logger.Build() if e != nil { panic(e) } defer c() defer func() { if r := recover(); r != nil { if re, _ := r.(error); re != nil { log.Error(re.Error()) } else { log.Alert("unhandled panic, err: %v", logger.Args(r)) } } }() tracer, e := common.GenerateTracerForTestClient("golang-example-app-product-service", conf) otel.SetTracerProvider(tracer) if e != nil { panic(e) } defer func() { if err := tracer.Shutdown(context.Background()); err != nil { log.Printf("Error shutting down tracer provider: %v", err) } }() log.Info("Start product service %s", logger.Args(clientConfig.Port)) lis, err := net.Listen("tcp", ":"+clientConfig.Port) if err != nil { panic(err) } nc, err := nats.Connect(clientConfig.NatsURL) if err != nil { log.Error(err.Error()) panic(err) } defer nc.Close() sc, _ := stan.Connect("test-cluster", "example-subscriber", stan.NatsConn(nc)) natsService := natsService{logger: log} _, err = sc.QueueSubscribe(clientConfig.Subject, "worker", natsService.workerHanlder, stan.DurableName("i-will-remember"), stan.MaxInflight(1), stan.SetManualAckMode()) if err != nil { sc.Close() log.Error(err.Error()) panic(err) } s := grpc.NewServer( grpc.ChainUnaryInterceptor( logger.UnaryServerInterceptor(log, true), otelgrpc.UnaryServerInterceptor(otelgrpc.WithTracerProvider(tracer), otelgrpc.WithPropagators(propagation.TraceContext{})), ), grpc.ChainStreamInterceptor( logger.StreamServerInterceptor(log, true), otelgrpc.StreamServerInterceptor(otelgrpc.WithTracerProvider(tracer), otelgrpc.WithPropagators(propagation.TraceContext{})), ), ) products.RegisterProductsServer(s, &server{logger: log, cfg: clientConfig}) if err := s.Serve(lis); err != nil { panic(err) } }, } ) func init() { } ================================================ FILE: cmd/root.go ================================================ package cmd import ( "bytes" "encoding/json" "fmt" "os" "os/signal" "path/filepath" "strings" "syscall" "github.com/aristat/golang-example-app/cmd/jwt" "github.com/aristat/golang-example-app/cmd/migrate" health_check_service "github.com/aristat/golang-example-app/cmd/health-check-service" product_service "github.com/aristat/golang-example-app/cmd/product-service" "github.com/aristat/golang-example-app/app/entrypoint" "github.com/aristat/golang-example-app/app/logger" "go.uber.org/automaxprocs/maxprocs" "github.com/aristat/golang-example-app/cmd/daemon" "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/spf13/viper" ) var ( configPath string debug bool v *viper.Viper log logger.Logger ) const prefix = "cmd.root" // Root command var rootCmd = &cobra.Command{ Use: "bin [command]", Long: "", SilenceUsage: true, SilenceErrors: true, PersistentPreRun: func(cmd *cobra.Command, _ []string) { l, c, e := logger.Build() defer c() if e != nil { panic(e) } log = l.WithFields(logger.Fields{"service": prefix}) v.SetConfigFile(configPath) if configPath != "" { e := v.ReadInConfig() if e != nil { log.Error("can't read config, %v", logger.Args(errors.WithMessage(e, prefix))) os.Exit(1) } } if debug { b, _ := json.Marshal(v.AllSettings()) var out bytes.Buffer e := json.Indent(&out, b, "", " ") if e != nil { log.Error("can't prettify config") os.Exit(1) } fmt.Println(string(out.Bytes())) } _, _ = maxprocs.Set(maxprocs.Logger(log.Printf)) }, } func init() { v = viper.New() v.SetConfigType("yaml") v.SetEnvPrefix("APP") v.SetEnvKeyReplacer(strings.NewReplacer("-", "_", ".", "_")) v.AutomaticEnv() // pflags rootCmd.PersistentFlags().StringVarP(&configPath, "config", "c", "", "config file") rootCmd.PersistentFlags().BoolVarP(&debug, "debug", "d", false, "debug mode") // initializing wd := os.Getenv("APP_WD") if len(wd) == 0 { wd, _ = filepath.Abs(filepath.Dir(os.Args[0])) } wd, _ = filepath.Abs(wd) ep, _ := entrypoint.Initialize(wd, v) // bin pflags to viper _ = v.BindPFlags(rootCmd.PersistentFlags()) go func() { reloadSignal := make(chan os.Signal) signal.Notify(reloadSignal, syscall.SIGHUP) for { sig := <-reloadSignal ep.Reload() fmt.Printf("OS signaled `%v`, reload", sig.String()) } }() } func Execute() { rootCmd.AddCommand(daemon.Cmd, product_service.Cmd, health_check_service.Cmd, migrate.Cmd, jwt.Cmd) if e := rootCmd.Execute(); e != nil { _, _ = fmt.Fprintf(os.Stderr, "%v\n", e.Error()) os.Exit(1) } } ================================================ FILE: dbconfig.yml ================================================ development: dialect: postgres datasource: dbname=golang_example_development sslmode=disable dir: resources/migrations table: migrations ================================================ FILE: docker/app/Dockerfile ================================================ FROM golang:1.17.9-alpine3.15 as builder RUN apk add --update make \ && rm -rf /tmp/* \ && rm -rf /var/cache/apk/* RUN mkdir /build WORKDIR /build COPY . . RUN GOOS=linux GOARCH=amd64 make build FROM alpine:3.9 COPY --from=builder /build/docker/app/files / COPY --from=builder /build/artifacts /app/ WORKDIR /app RUN apk --no-cache add tzdata bash \ && chmod +x /docker/bin/* \ && chmod +x bin \ && rm -rf /tmp/* \ && rm -rf /var/cache/apk/* ENTRYPOINT ["/docker/bin/entrypoint.sh"] ================================================ FILE: docker/app/files/docker/bin/entrypoint.sh ================================================ #!/usr/bin/env sh exec ./bin "$@" ================================================ FILE: docker-compose.yml ================================================ version: '3.7' services: jaeger: image: jaegertracing/all-in-one:latest networks: - intranet ports: - "5775:5775/udp" - "6831:6831/udp" - "6832:6832/udp" - "5778:5778" - "16686:16686" - "14268:14268" - "9411:9411" #=============================# # check migration before start daemon-migrate: image: golang-example-app:development depends_on: - postgres networks: - intranet command: migrate up --dsn=postgres://postgres@postgres:5432/golang_example_development?sslmode=disable --limit=0 daemon: image: golang-example-app:development command: daemon -c ./configs/docker_development.yaml -d depends_on: - product_service - health_check_service - daemon-migrate - postgres - redis - nats-streaming networks: - intranet ports: - "9096:9096" #=============================# product_service: image: golang-example-app:development command: product-service -c ./configs/docker_development.yaml -d depends_on: - postgres networks: - intranet ports: - "50051:50051" #=============================# health_check_service: image: golang-example-app:development command: health-check -c ./configs/docker_development.yaml -d networks: - intranet ports: - "50052:50052" #=============================# postgres: image: postgres:9.6 environment: - POSTGRES_USER=postgres - POSTGRES_DB=golang_example_development - POSTGRES_HOST_AUTH_METHOD=trust volumes: - postgres_data:/var/lib/postgresql/data ports: - "5532:5432" networks: - intranet redis: image: redis:latest volumes: - redis_data:/data networks: - intranet nats-streaming: image: nats-streaming ports: - "8222:8222" - "4222:4222" networks: - intranet networks: intranet: driver: bridge volumes: postgres_data: redis_data: ================================================ FILE: generated/graphql/generated.go ================================================ // Code generated by github.com/99designs/gqlgen, DO NOT EDIT. package graphql import ( "bytes" "context" "errors" "fmt" "strconv" "sync" "sync/atomic" "github.com/99designs/gqlgen/graphql" "github.com/99designs/gqlgen/graphql/introspection" "github.com/aristat/golang-example-app/app/db/domain" gqlparser "github.com/vektah/gqlparser/v2" "github.com/vektah/gqlparser/v2/ast" ) // region ************************** generated!.gotpl ************************** // NewExecutableSchema creates an ExecutableSchema from the ResolverRoot interface. func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { return &executableSchema{ resolvers: cfg.Resolvers, directives: cfg.Directives, complexity: cfg.Complexity, } } type Config struct { Resolvers ResolverRoot Directives DirectiveRoot Complexity ComplexityRoot } type ResolverRoot interface { Mutation() MutationResolver Product() ProductResolver ProductsQuery() ProductsQueryResolver Query() QueryResolver UsersMutation() UsersMutationResolver UsersQuery() UsersQueryResolver } type DirectiveRoot struct { HasUsersPermission func(ctx context.Context, obj interface{}, next graphql.Resolver, permission UsersPermissionEnum) (res interface{}, err error) } type ComplexityRoot struct { Mutation struct { Users func(childComplexity int) int } Product struct { ID func(childComplexity int) int Name func(childComplexity int) int ProductItems func(childComplexity int) int } ProductItem struct { ID func(childComplexity int) int Name func(childComplexity int) int } ProductsListOut struct { Products func(childComplexity int) int } ProductsQuery struct { List func(childComplexity int) int } Query struct { Products func(childComplexity int) int Users func(childComplexity int) int } UsersCreateOut struct { Email func(childComplexity int) int ID func(childComplexity int) int Status func(childComplexity int) int } UsersMutation struct { CreateUser func(childComplexity int, email string, password string) int } UsersOneOut struct { Email func(childComplexity int) int ID func(childComplexity int) int } UsersQuery struct { One func(childComplexity int, email string) int } } type MutationResolver interface { Users(ctx context.Context) (*UsersMutation, error) } type ProductResolver interface { ProductItems(ctx context.Context, obj *domain.Product) ([]*domain.ProductItem, error) } type ProductsQueryResolver interface { List(ctx context.Context, obj *ProductsQuery) (*ProductsListOut, error) } type QueryResolver interface { Users(ctx context.Context) (*UsersQuery, error) Products(ctx context.Context) (*ProductsQuery, error) } type UsersMutationResolver interface { CreateUser(ctx context.Context, obj *UsersMutation, email string, password string) (*UsersCreateOut, error) } type UsersQueryResolver interface { One(ctx context.Context, obj *UsersQuery, email string) (*UsersOneOut, error) } type executableSchema struct { resolvers ResolverRoot directives DirectiveRoot complexity ComplexityRoot } func (e *executableSchema) Schema() *ast.Schema { return parsedSchema } func (e *executableSchema) Complexity(typeName, field string, childComplexity int, rawArgs map[string]interface{}) (int, bool) { ec := executionContext{nil, e} _ = ec switch typeName + "." + field { case "Mutation.users": if e.complexity.Mutation.Users == nil { break } return e.complexity.Mutation.Users(childComplexity), true case "Product.id": if e.complexity.Product.ID == nil { break } return e.complexity.Product.ID(childComplexity), true case "Product.name": if e.complexity.Product.Name == nil { break } return e.complexity.Product.Name(childComplexity), true case "Product.productItems": if e.complexity.Product.ProductItems == nil { break } return e.complexity.Product.ProductItems(childComplexity), true case "ProductItem.id": if e.complexity.ProductItem.ID == nil { break } return e.complexity.ProductItem.ID(childComplexity), true case "ProductItem.name": if e.complexity.ProductItem.Name == nil { break } return e.complexity.ProductItem.Name(childComplexity), true case "ProductsListOut.products": if e.complexity.ProductsListOut.Products == nil { break } return e.complexity.ProductsListOut.Products(childComplexity), true case "ProductsQuery.list": if e.complexity.ProductsQuery.List == nil { break } return e.complexity.ProductsQuery.List(childComplexity), true case "Query.products": if e.complexity.Query.Products == nil { break } return e.complexity.Query.Products(childComplexity), true case "Query.users": if e.complexity.Query.Users == nil { break } return e.complexity.Query.Users(childComplexity), true case "UsersCreateOut.email": if e.complexity.UsersCreateOut.Email == nil { break } return e.complexity.UsersCreateOut.Email(childComplexity), true case "UsersCreateOut.id": if e.complexity.UsersCreateOut.ID == nil { break } return e.complexity.UsersCreateOut.ID(childComplexity), true case "UsersCreateOut.status": if e.complexity.UsersCreateOut.Status == nil { break } return e.complexity.UsersCreateOut.Status(childComplexity), true case "UsersMutation.createUser": if e.complexity.UsersMutation.CreateUser == nil { break } args, err := ec.field_UsersMutation_createUser_args(context.TODO(), rawArgs) if err != nil { return 0, false } return e.complexity.UsersMutation.CreateUser(childComplexity, args["email"].(string), args["password"].(string)), true case "UsersOneOut.email": if e.complexity.UsersOneOut.Email == nil { break } return e.complexity.UsersOneOut.Email(childComplexity), true case "UsersOneOut.id": if e.complexity.UsersOneOut.ID == nil { break } return e.complexity.UsersOneOut.ID(childComplexity), true case "UsersQuery.one": if e.complexity.UsersQuery.One == nil { break } args, err := ec.field_UsersQuery_one_args(context.TODO(), rawArgs) if err != nil { return 0, false } return e.complexity.UsersQuery.One(childComplexity, args["email"].(string)), true } return 0, false } func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler { rc := graphql.GetOperationContext(ctx) ec := executionContext{rc, e} first := true switch rc.Operation.Operation { case ast.Query: return func(ctx context.Context) *graphql.Response { if !first { return nil } first = false data := ec._Query(ctx, rc.Operation.SelectionSet) var buf bytes.Buffer data.MarshalGQL(&buf) return &graphql.Response{ Data: buf.Bytes(), } } case ast.Mutation: return func(ctx context.Context) *graphql.Response { if !first { return nil } first = false data := ec._Mutation(ctx, rc.Operation.SelectionSet) var buf bytes.Buffer data.MarshalGQL(&buf) return &graphql.Response{ Data: buf.Bytes(), } } default: return graphql.OneShot(graphql.ErrorResponse(ctx, "unsupported GraphQL operation")) } } type executionContext struct { *graphql.OperationContext *executableSchema } func (ec *executionContext) introspectSchema() (*introspection.Schema, error) { if ec.DisableIntrospection { return nil, errors.New("introspection disabled") } return introspection.WrapSchema(parsedSchema), nil } func (ec *executionContext) introspectType(name string) (*introspection.Type, error) { if ec.DisableIntrospection { return nil, errors.New("introspection disabled") } return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]), nil } var sources = []*ast.Source{ {Name: "resources/graphql/products.graphql", Input: `type ProductsQuery { list: ProductsListOut! } type Product { id: ID! name: String! productItems: [ProductItem!]! } type ProductItem { id: ID! name: String! } type ProductsListOut { products: [Product!]! } `, BuiltIn: false}, {Name: "resources/graphql/root.graphql", Input: `type Query { users: UsersQuery products: ProductsQuery } type Mutation { users: UsersMutation } `, BuiltIn: false}, {Name: "resources/graphql/user.graphql", Input: `type UsersOneOut { id: ID! email: String! } type UsersQuery { one(email: String!): UsersOneOut! @hasUsersPermission(permission: READ) } type UsersMutation { createUser(email: String!, password: String!): UsersCreateOut! @hasUsersPermission(permission: WRITE) } type UsersCreateOut { status: UsersCreateOutStatus! id: ID! email: String! } enum UsersCreateOutStatus { OK BAD_REQUEST SERVER_INTERNAL_ERROR } directive @hasUsersPermission(permission: UsersPermissionEnum!) on FIELD_DEFINITION enum UsersPermissionEnum { READ WRITE } `, BuiltIn: false}, } var parsedSchema = gqlparser.MustLoadSchema(sources...) // endregion ************************** generated!.gotpl ************************** // region ***************************** args.gotpl ***************************** func (ec *executionContext) dir_hasUsersPermission_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} var arg0 UsersPermissionEnum if tmp, ok := rawArgs["permission"]; ok { ctx := graphql.WithFieldInputContext(ctx, graphql.NewFieldInputWithField("permission")) arg0, err = ec.unmarshalNUsersPermissionEnum2githubᚗcomᚋaristatᚋgolangᚑexampleᚑappᚋgeneratedᚋgraphqlᚐUsersPermissionEnum(ctx, tmp) if err != nil { return nil, err } } args["permission"] = arg0 return args, nil } func (ec *executionContext) field_Query___type_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} var arg0 string if tmp, ok := rawArgs["name"]; ok { ctx := graphql.WithFieldInputContext(ctx, graphql.NewFieldInputWithField("name")) arg0, err = ec.unmarshalNString2string(ctx, tmp) if err != nil { return nil, err } } args["name"] = arg0 return args, nil } func (ec *executionContext) field_UsersMutation_createUser_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} var arg0 string if tmp, ok := rawArgs["email"]; ok { ctx := graphql.WithFieldInputContext(ctx, graphql.NewFieldInputWithField("email")) arg0, err = ec.unmarshalNString2string(ctx, tmp) if err != nil { return nil, err } } args["email"] = arg0 var arg1 string if tmp, ok := rawArgs["password"]; ok { ctx := graphql.WithFieldInputContext(ctx, graphql.NewFieldInputWithField("password")) arg1, err = ec.unmarshalNString2string(ctx, tmp) if err != nil { return nil, err } } args["password"] = arg1 return args, nil } func (ec *executionContext) field_UsersQuery_one_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} var arg0 string if tmp, ok := rawArgs["email"]; ok { ctx := graphql.WithFieldInputContext(ctx, graphql.NewFieldInputWithField("email")) arg0, err = ec.unmarshalNString2string(ctx, tmp) if err != nil { return nil, err } } args["email"] = arg0 return args, nil } func (ec *executionContext) field___Type_enumValues_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} var arg0 bool if tmp, ok := rawArgs["includeDeprecated"]; ok { ctx := graphql.WithFieldInputContext(ctx, graphql.NewFieldInputWithField("includeDeprecated")) arg0, err = ec.unmarshalOBoolean2bool(ctx, tmp) if err != nil { return nil, err } } args["includeDeprecated"] = arg0 return args, nil } func (ec *executionContext) field___Type_fields_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} var arg0 bool if tmp, ok := rawArgs["includeDeprecated"]; ok { ctx := graphql.WithFieldInputContext(ctx, graphql.NewFieldInputWithField("includeDeprecated")) arg0, err = ec.unmarshalOBoolean2bool(ctx, tmp) if err != nil { return nil, err } } args["includeDeprecated"] = arg0 return args, nil } // endregion ***************************** args.gotpl ***************************** // region ************************** directives.gotpl ************************** // endregion ************************** directives.gotpl ************************** // region **************************** field.gotpl ***************************** func (ec *executionContext) _Mutation_users(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "Mutation", Field: field, Args: nil, IsMethod: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Mutation().Users(rctx) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { return graphql.Null } res := resTmp.(*UsersMutation) fc.Result = res return ec.marshalOUsersMutation2ᚖgithubᚗcomᚋaristatᚋgolangᚑexampleᚑappᚋgeneratedᚋgraphqlᚐUsersMutation(ctx, field.Selections, res) } func (ec *executionContext) _Product_id(ctx context.Context, field graphql.CollectedField, obj *domain.Product) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "Product", Field: field, Args: nil, IsMethod: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.ID, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(int) fc.Result = res return ec.marshalNID2int(ctx, field.Selections, res) } func (ec *executionContext) _Product_name(ctx context.Context, field graphql.CollectedField, obj *domain.Product) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "Product", Field: field, Args: nil, IsMethod: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Name, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(string) fc.Result = res return ec.marshalNString2string(ctx, field.Selections, res) } func (ec *executionContext) _Product_productItems(ctx context.Context, field graphql.CollectedField, obj *domain.Product) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "Product", Field: field, Args: nil, IsMethod: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Product().ProductItems(rctx, obj) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.([]*domain.ProductItem) fc.Result = res return ec.marshalNProductItem2ᚕᚖgithubᚗcomᚋaristatᚋgolangᚑexampleᚑappᚋappᚋdbᚋdomainᚐProductItemᚄ(ctx, field.Selections, res) } func (ec *executionContext) _ProductItem_id(ctx context.Context, field graphql.CollectedField, obj *domain.ProductItem) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "ProductItem", Field: field, Args: nil, IsMethod: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.ID, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(int) fc.Result = res return ec.marshalNID2int(ctx, field.Selections, res) } func (ec *executionContext) _ProductItem_name(ctx context.Context, field graphql.CollectedField, obj *domain.ProductItem) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "ProductItem", Field: field, Args: nil, IsMethod: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Name, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(string) fc.Result = res return ec.marshalNString2string(ctx, field.Selections, res) } func (ec *executionContext) _ProductsListOut_products(ctx context.Context, field graphql.CollectedField, obj *ProductsListOut) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "ProductsListOut", Field: field, Args: nil, IsMethod: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Products, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.([]*domain.Product) fc.Result = res return ec.marshalNProduct2ᚕᚖgithubᚗcomᚋaristatᚋgolangᚑexampleᚑappᚋappᚋdbᚋdomainᚐProductᚄ(ctx, field.Selections, res) } func (ec *executionContext) _ProductsQuery_list(ctx context.Context, field graphql.CollectedField, obj *ProductsQuery) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "ProductsQuery", Field: field, Args: nil, IsMethod: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.ProductsQuery().List(rctx, obj) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(*ProductsListOut) fc.Result = res return ec.marshalNProductsListOut2ᚖgithubᚗcomᚋaristatᚋgolangᚑexampleᚑappᚋgeneratedᚋgraphqlᚐProductsListOut(ctx, field.Selections, res) } func (ec *executionContext) _Query_users(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "Query", Field: field, Args: nil, IsMethod: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Query().Users(rctx) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { return graphql.Null } res := resTmp.(*UsersQuery) fc.Result = res return ec.marshalOUsersQuery2ᚖgithubᚗcomᚋaristatᚋgolangᚑexampleᚑappᚋgeneratedᚋgraphqlᚐUsersQuery(ctx, field.Selections, res) } func (ec *executionContext) _Query_products(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "Query", Field: field, Args: nil, IsMethod: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Query().Products(rctx) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { return graphql.Null } res := resTmp.(*ProductsQuery) fc.Result = res return ec.marshalOProductsQuery2ᚖgithubᚗcomᚋaristatᚋgolangᚑexampleᚑappᚋgeneratedᚋgraphqlᚐProductsQuery(ctx, field.Selections, res) } func (ec *executionContext) _Query___type(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "Query", Field: field, Args: nil, IsMethod: true, } ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field_Query___type_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.introspectType(args["name"].(string)) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { return graphql.Null } res := resTmp.(*introspection.Type) fc.Result = res return ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) } func (ec *executionContext) _Query___schema(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "Query", Field: field, Args: nil, IsMethod: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.introspectSchema() }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { return graphql.Null } res := resTmp.(*introspection.Schema) fc.Result = res return ec.marshalO__Schema2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐSchema(ctx, field.Selections, res) } func (ec *executionContext) _UsersCreateOut_status(ctx context.Context, field graphql.CollectedField, obj *UsersCreateOut) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "UsersCreateOut", Field: field, Args: nil, IsMethod: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Status, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(UsersCreateOutStatus) fc.Result = res return ec.marshalNUsersCreateOutStatus2githubᚗcomᚋaristatᚋgolangᚑexampleᚑappᚋgeneratedᚋgraphqlᚐUsersCreateOutStatus(ctx, field.Selections, res) } func (ec *executionContext) _UsersCreateOut_id(ctx context.Context, field graphql.CollectedField, obj *UsersCreateOut) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "UsersCreateOut", Field: field, Args: nil, IsMethod: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.ID, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(string) fc.Result = res return ec.marshalNID2string(ctx, field.Selections, res) } func (ec *executionContext) _UsersCreateOut_email(ctx context.Context, field graphql.CollectedField, obj *UsersCreateOut) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "UsersCreateOut", Field: field, Args: nil, IsMethod: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Email, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(string) fc.Result = res return ec.marshalNString2string(ctx, field.Selections, res) } func (ec *executionContext) _UsersMutation_createUser(ctx context.Context, field graphql.CollectedField, obj *UsersMutation) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "UsersMutation", Field: field, Args: nil, IsMethod: true, } ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field_UsersMutation_createUser_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { directive0 := func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.UsersMutation().CreateUser(rctx, obj, args["email"].(string), args["password"].(string)) } directive1 := func(ctx context.Context) (interface{}, error) { permission, err := ec.unmarshalNUsersPermissionEnum2githubᚗcomᚋaristatᚋgolangᚑexampleᚑappᚋgeneratedᚋgraphqlᚐUsersPermissionEnum(ctx, "WRITE") if err != nil { return nil, err } if ec.directives.HasUsersPermission == nil { return nil, errors.New("directive hasUsersPermission is not implemented") } return ec.directives.HasUsersPermission(ctx, obj, directive0, permission) } tmp, err := directive1(rctx) if err != nil { return nil, err } if tmp == nil { return nil, nil } if data, ok := tmp.(*UsersCreateOut); ok { return data, nil } return nil, fmt.Errorf(`unexpected type %T from directive, should be *github.com/aristat/golang-example-app/generated/graphql.UsersCreateOut`, tmp) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(*UsersCreateOut) fc.Result = res return ec.marshalNUsersCreateOut2ᚖgithubᚗcomᚋaristatᚋgolangᚑexampleᚑappᚋgeneratedᚋgraphqlᚐUsersCreateOut(ctx, field.Selections, res) } func (ec *executionContext) _UsersOneOut_id(ctx context.Context, field graphql.CollectedField, obj *UsersOneOut) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "UsersOneOut", Field: field, Args: nil, IsMethod: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.ID, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(string) fc.Result = res return ec.marshalNID2string(ctx, field.Selections, res) } func (ec *executionContext) _UsersOneOut_email(ctx context.Context, field graphql.CollectedField, obj *UsersOneOut) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "UsersOneOut", Field: field, Args: nil, IsMethod: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Email, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(string) fc.Result = res return ec.marshalNString2string(ctx, field.Selections, res) } func (ec *executionContext) _UsersQuery_one(ctx context.Context, field graphql.CollectedField, obj *UsersQuery) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "UsersQuery", Field: field, Args: nil, IsMethod: true, } ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field_UsersQuery_one_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { directive0 := func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.UsersQuery().One(rctx, obj, args["email"].(string)) } directive1 := func(ctx context.Context) (interface{}, error) { permission, err := ec.unmarshalNUsersPermissionEnum2githubᚗcomᚋaristatᚋgolangᚑexampleᚑappᚋgeneratedᚋgraphqlᚐUsersPermissionEnum(ctx, "READ") if err != nil { return nil, err } if ec.directives.HasUsersPermission == nil { return nil, errors.New("directive hasUsersPermission is not implemented") } return ec.directives.HasUsersPermission(ctx, obj, directive0, permission) } tmp, err := directive1(rctx) if err != nil { return nil, err } if tmp == nil { return nil, nil } if data, ok := tmp.(*UsersOneOut); ok { return data, nil } return nil, fmt.Errorf(`unexpected type %T from directive, should be *github.com/aristat/golang-example-app/generated/graphql.UsersOneOut`, tmp) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(*UsersOneOut) fc.Result = res return ec.marshalNUsersOneOut2ᚖgithubᚗcomᚋaristatᚋgolangᚑexampleᚑappᚋgeneratedᚋgraphqlᚐUsersOneOut(ctx, field.Selections, res) } func (ec *executionContext) ___Directive_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "__Directive", Field: field, Args: nil, IsMethod: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Name, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(string) fc.Result = res return ec.marshalNString2string(ctx, field.Selections, res) } func (ec *executionContext) ___Directive_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "__Directive", Field: field, Args: nil, IsMethod: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Description, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { return graphql.Null } res := resTmp.(string) fc.Result = res return ec.marshalOString2string(ctx, field.Selections, res) } func (ec *executionContext) ___Directive_locations(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "__Directive", Field: field, Args: nil, IsMethod: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Locations, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.([]string) fc.Result = res return ec.marshalN__DirectiveLocation2ᚕstringᚄ(ctx, field.Selections, res) } func (ec *executionContext) ___Directive_args(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "__Directive", Field: field, Args: nil, IsMethod: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Args, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.([]introspection.InputValue) fc.Result = res return ec.marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx, field.Selections, res) } func (ec *executionContext) ___EnumValue_name(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "__EnumValue", Field: field, Args: nil, IsMethod: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Name, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(string) fc.Result = res return ec.marshalNString2string(ctx, field.Selections, res) } func (ec *executionContext) ___EnumValue_description(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "__EnumValue", Field: field, Args: nil, IsMethod: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Description, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { return graphql.Null } res := resTmp.(string) fc.Result = res return ec.marshalOString2string(ctx, field.Selections, res) } func (ec *executionContext) ___EnumValue_isDeprecated(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "__EnumValue", Field: field, Args: nil, IsMethod: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.IsDeprecated(), nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(bool) fc.Result = res return ec.marshalNBoolean2bool(ctx, field.Selections, res) } func (ec *executionContext) ___EnumValue_deprecationReason(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "__EnumValue", Field: field, Args: nil, IsMethod: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.DeprecationReason(), nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { return graphql.Null } res := resTmp.(*string) fc.Result = res return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } func (ec *executionContext) ___Field_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "__Field", Field: field, Args: nil, IsMethod: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Name, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(string) fc.Result = res return ec.marshalNString2string(ctx, field.Selections, res) } func (ec *executionContext) ___Field_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "__Field", Field: field, Args: nil, IsMethod: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Description, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { return graphql.Null } res := resTmp.(string) fc.Result = res return ec.marshalOString2string(ctx, field.Selections, res) } func (ec *executionContext) ___Field_args(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "__Field", Field: field, Args: nil, IsMethod: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Args, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.([]introspection.InputValue) fc.Result = res return ec.marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx, field.Selections, res) } func (ec *executionContext) ___Field_type(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "__Field", Field: field, Args: nil, IsMethod: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Type, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(*introspection.Type) fc.Result = res return ec.marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) } func (ec *executionContext) ___Field_isDeprecated(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "__Field", Field: field, Args: nil, IsMethod: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.IsDeprecated(), nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(bool) fc.Result = res return ec.marshalNBoolean2bool(ctx, field.Selections, res) } func (ec *executionContext) ___Field_deprecationReason(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "__Field", Field: field, Args: nil, IsMethod: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.DeprecationReason(), nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { return graphql.Null } res := resTmp.(*string) fc.Result = res return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } func (ec *executionContext) ___InputValue_name(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "__InputValue", Field: field, Args: nil, IsMethod: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Name, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(string) fc.Result = res return ec.marshalNString2string(ctx, field.Selections, res) } func (ec *executionContext) ___InputValue_description(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "__InputValue", Field: field, Args: nil, IsMethod: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Description, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { return graphql.Null } res := resTmp.(string) fc.Result = res return ec.marshalOString2string(ctx, field.Selections, res) } func (ec *executionContext) ___InputValue_type(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "__InputValue", Field: field, Args: nil, IsMethod: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Type, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(*introspection.Type) fc.Result = res return ec.marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) } func (ec *executionContext) ___InputValue_defaultValue(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "__InputValue", Field: field, Args: nil, IsMethod: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.DefaultValue, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { return graphql.Null } res := resTmp.(*string) fc.Result = res return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } func (ec *executionContext) ___Schema_types(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "__Schema", Field: field, Args: nil, IsMethod: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Types(), nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.([]introspection.Type) fc.Result = res return ec.marshalN__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx, field.Selections, res) } func (ec *executionContext) ___Schema_queryType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "__Schema", Field: field, Args: nil, IsMethod: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.QueryType(), nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(*introspection.Type) fc.Result = res return ec.marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) } func (ec *executionContext) ___Schema_mutationType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "__Schema", Field: field, Args: nil, IsMethod: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.MutationType(), nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { return graphql.Null } res := resTmp.(*introspection.Type) fc.Result = res return ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) } func (ec *executionContext) ___Schema_subscriptionType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "__Schema", Field: field, Args: nil, IsMethod: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.SubscriptionType(), nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { return graphql.Null } res := resTmp.(*introspection.Type) fc.Result = res return ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) } func (ec *executionContext) ___Schema_directives(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "__Schema", Field: field, Args: nil, IsMethod: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Directives(), nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.([]introspection.Directive) fc.Result = res return ec.marshalN__Directive2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirectiveᚄ(ctx, field.Selections, res) } func (ec *executionContext) ___Type_kind(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "__Type", Field: field, Args: nil, IsMethod: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Kind(), nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(string) fc.Result = res return ec.marshalN__TypeKind2string(ctx, field.Selections, res) } func (ec *executionContext) ___Type_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "__Type", Field: field, Args: nil, IsMethod: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Name(), nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { return graphql.Null } res := resTmp.(*string) fc.Result = res return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } func (ec *executionContext) ___Type_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "__Type", Field: field, Args: nil, IsMethod: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Description(), nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { return graphql.Null } res := resTmp.(string) fc.Result = res return ec.marshalOString2string(ctx, field.Selections, res) } func (ec *executionContext) ___Type_fields(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "__Type", Field: field, Args: nil, IsMethod: true, } ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field___Type_fields_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Fields(args["includeDeprecated"].(bool)), nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { return graphql.Null } res := resTmp.([]introspection.Field) fc.Result = res return ec.marshalO__Field2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐFieldᚄ(ctx, field.Selections, res) } func (ec *executionContext) ___Type_interfaces(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "__Type", Field: field, Args: nil, IsMethod: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Interfaces(), nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { return graphql.Null } res := resTmp.([]introspection.Type) fc.Result = res return ec.marshalO__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx, field.Selections, res) } func (ec *executionContext) ___Type_possibleTypes(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "__Type", Field: field, Args: nil, IsMethod: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.PossibleTypes(), nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { return graphql.Null } res := resTmp.([]introspection.Type) fc.Result = res return ec.marshalO__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx, field.Selections, res) } func (ec *executionContext) ___Type_enumValues(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "__Type", Field: field, Args: nil, IsMethod: true, } ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field___Type_enumValues_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.EnumValues(args["includeDeprecated"].(bool)), nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { return graphql.Null } res := resTmp.([]introspection.EnumValue) fc.Result = res return ec.marshalO__EnumValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValueᚄ(ctx, field.Selections, res) } func (ec *executionContext) ___Type_inputFields(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "__Type", Field: field, Args: nil, IsMethod: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.InputFields(), nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { return graphql.Null } res := resTmp.([]introspection.InputValue) fc.Result = res return ec.marshalO__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx, field.Selections, res) } func (ec *executionContext) ___Type_ofType(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } }() fc := &graphql.FieldContext{ Object: "__Type", Field: field, Args: nil, IsMethod: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.OfType(), nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { return graphql.Null } res := resTmp.(*introspection.Type) fc.Result = res return ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) } // endregion **************************** field.gotpl ***************************** // region **************************** input.gotpl ***************************** // endregion **************************** input.gotpl ***************************** // region ************************** interface.gotpl *************************** // endregion ************************** interface.gotpl *************************** // region **************************** object.gotpl **************************** var mutationImplementors = []string{"Mutation"} func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler { fields := graphql.CollectFields(ec.OperationContext, sel, mutationImplementors) ctx = graphql.WithFieldContext(ctx, &graphql.FieldContext{ Object: "Mutation", }) out := graphql.NewFieldSet(fields) var invalids uint32 for i, field := range fields { switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("Mutation") case "users": out.Values[i] = ec._Mutation_users(ctx, field) default: panic("unknown field " + strconv.Quote(field.Name)) } } out.Dispatch() if invalids > 0 { return graphql.Null } return out } var productImplementors = []string{"Product"} func (ec *executionContext) _Product(ctx context.Context, sel ast.SelectionSet, obj *domain.Product) graphql.Marshaler { fields := graphql.CollectFields(ec.OperationContext, sel, productImplementors) out := graphql.NewFieldSet(fields) var invalids uint32 for i, field := range fields { switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("Product") case "id": out.Values[i] = ec._Product_id(ctx, field, obj) if out.Values[i] == graphql.Null { atomic.AddUint32(&invalids, 1) } case "name": out.Values[i] = ec._Product_name(ctx, field, obj) if out.Values[i] == graphql.Null { atomic.AddUint32(&invalids, 1) } case "productItems": field := field out.Concurrently(i, func() (res graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) } }() res = ec._Product_productItems(ctx, field, obj) if res == graphql.Null { atomic.AddUint32(&invalids, 1) } return res }) default: panic("unknown field " + strconv.Quote(field.Name)) } } out.Dispatch() if invalids > 0 { return graphql.Null } return out } var productItemImplementors = []string{"ProductItem"} func (ec *executionContext) _ProductItem(ctx context.Context, sel ast.SelectionSet, obj *domain.ProductItem) graphql.Marshaler { fields := graphql.CollectFields(ec.OperationContext, sel, productItemImplementors) out := graphql.NewFieldSet(fields) var invalids uint32 for i, field := range fields { switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("ProductItem") case "id": out.Values[i] = ec._ProductItem_id(ctx, field, obj) if out.Values[i] == graphql.Null { invalids++ } case "name": out.Values[i] = ec._ProductItem_name(ctx, field, obj) if out.Values[i] == graphql.Null { invalids++ } default: panic("unknown field " + strconv.Quote(field.Name)) } } out.Dispatch() if invalids > 0 { return graphql.Null } return out } var productsListOutImplementors = []string{"ProductsListOut"} func (ec *executionContext) _ProductsListOut(ctx context.Context, sel ast.SelectionSet, obj *ProductsListOut) graphql.Marshaler { fields := graphql.CollectFields(ec.OperationContext, sel, productsListOutImplementors) out := graphql.NewFieldSet(fields) var invalids uint32 for i, field := range fields { switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("ProductsListOut") case "products": out.Values[i] = ec._ProductsListOut_products(ctx, field, obj) if out.Values[i] == graphql.Null { invalids++ } default: panic("unknown field " + strconv.Quote(field.Name)) } } out.Dispatch() if invalids > 0 { return graphql.Null } return out } var productsQueryImplementors = []string{"ProductsQuery"} func (ec *executionContext) _ProductsQuery(ctx context.Context, sel ast.SelectionSet, obj *ProductsQuery) graphql.Marshaler { fields := graphql.CollectFields(ec.OperationContext, sel, productsQueryImplementors) out := graphql.NewFieldSet(fields) var invalids uint32 for i, field := range fields { switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("ProductsQuery") case "list": field := field out.Concurrently(i, func() (res graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) } }() res = ec._ProductsQuery_list(ctx, field, obj) if res == graphql.Null { atomic.AddUint32(&invalids, 1) } return res }) default: panic("unknown field " + strconv.Quote(field.Name)) } } out.Dispatch() if invalids > 0 { return graphql.Null } return out } var queryImplementors = []string{"Query"} func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler { fields := graphql.CollectFields(ec.OperationContext, sel, queryImplementors) ctx = graphql.WithFieldContext(ctx, &graphql.FieldContext{ Object: "Query", }) out := graphql.NewFieldSet(fields) var invalids uint32 for i, field := range fields { switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("Query") case "users": field := field out.Concurrently(i, func() (res graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) } }() res = ec._Query_users(ctx, field) return res }) case "products": field := field out.Concurrently(i, func() (res graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) } }() res = ec._Query_products(ctx, field) return res }) case "__type": out.Values[i] = ec._Query___type(ctx, field) case "__schema": out.Values[i] = ec._Query___schema(ctx, field) default: panic("unknown field " + strconv.Quote(field.Name)) } } out.Dispatch() if invalids > 0 { return graphql.Null } return out } var usersCreateOutImplementors = []string{"UsersCreateOut"} func (ec *executionContext) _UsersCreateOut(ctx context.Context, sel ast.SelectionSet, obj *UsersCreateOut) graphql.Marshaler { fields := graphql.CollectFields(ec.OperationContext, sel, usersCreateOutImplementors) out := graphql.NewFieldSet(fields) var invalids uint32 for i, field := range fields { switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("UsersCreateOut") case "status": out.Values[i] = ec._UsersCreateOut_status(ctx, field, obj) if out.Values[i] == graphql.Null { invalids++ } case "id": out.Values[i] = ec._UsersCreateOut_id(ctx, field, obj) if out.Values[i] == graphql.Null { invalids++ } case "email": out.Values[i] = ec._UsersCreateOut_email(ctx, field, obj) if out.Values[i] == graphql.Null { invalids++ } default: panic("unknown field " + strconv.Quote(field.Name)) } } out.Dispatch() if invalids > 0 { return graphql.Null } return out } var usersMutationImplementors = []string{"UsersMutation"} func (ec *executionContext) _UsersMutation(ctx context.Context, sel ast.SelectionSet, obj *UsersMutation) graphql.Marshaler { fields := graphql.CollectFields(ec.OperationContext, sel, usersMutationImplementors) out := graphql.NewFieldSet(fields) var invalids uint32 for i, field := range fields { switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("UsersMutation") case "createUser": field := field out.Concurrently(i, func() (res graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) } }() res = ec._UsersMutation_createUser(ctx, field, obj) if res == graphql.Null { atomic.AddUint32(&invalids, 1) } return res }) default: panic("unknown field " + strconv.Quote(field.Name)) } } out.Dispatch() if invalids > 0 { return graphql.Null } return out } var usersOneOutImplementors = []string{"UsersOneOut"} func (ec *executionContext) _UsersOneOut(ctx context.Context, sel ast.SelectionSet, obj *UsersOneOut) graphql.Marshaler { fields := graphql.CollectFields(ec.OperationContext, sel, usersOneOutImplementors) out := graphql.NewFieldSet(fields) var invalids uint32 for i, field := range fields { switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("UsersOneOut") case "id": out.Values[i] = ec._UsersOneOut_id(ctx, field, obj) if out.Values[i] == graphql.Null { invalids++ } case "email": out.Values[i] = ec._UsersOneOut_email(ctx, field, obj) if out.Values[i] == graphql.Null { invalids++ } default: panic("unknown field " + strconv.Quote(field.Name)) } } out.Dispatch() if invalids > 0 { return graphql.Null } return out } var usersQueryImplementors = []string{"UsersQuery"} func (ec *executionContext) _UsersQuery(ctx context.Context, sel ast.SelectionSet, obj *UsersQuery) graphql.Marshaler { fields := graphql.CollectFields(ec.OperationContext, sel, usersQueryImplementors) out := graphql.NewFieldSet(fields) var invalids uint32 for i, field := range fields { switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("UsersQuery") case "one": field := field out.Concurrently(i, func() (res graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) } }() res = ec._UsersQuery_one(ctx, field, obj) if res == graphql.Null { atomic.AddUint32(&invalids, 1) } return res }) default: panic("unknown field " + strconv.Quote(field.Name)) } } out.Dispatch() if invalids > 0 { return graphql.Null } return out } var __DirectiveImplementors = []string{"__Directive"} func (ec *executionContext) ___Directive(ctx context.Context, sel ast.SelectionSet, obj *introspection.Directive) graphql.Marshaler { fields := graphql.CollectFields(ec.OperationContext, sel, __DirectiveImplementors) out := graphql.NewFieldSet(fields) var invalids uint32 for i, field := range fields { switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__Directive") case "name": out.Values[i] = ec.___Directive_name(ctx, field, obj) if out.Values[i] == graphql.Null { invalids++ } case "description": out.Values[i] = ec.___Directive_description(ctx, field, obj) case "locations": out.Values[i] = ec.___Directive_locations(ctx, field, obj) if out.Values[i] == graphql.Null { invalids++ } case "args": out.Values[i] = ec.___Directive_args(ctx, field, obj) if out.Values[i] == graphql.Null { invalids++ } default: panic("unknown field " + strconv.Quote(field.Name)) } } out.Dispatch() if invalids > 0 { return graphql.Null } return out } var __EnumValueImplementors = []string{"__EnumValue"} func (ec *executionContext) ___EnumValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.EnumValue) graphql.Marshaler { fields := graphql.CollectFields(ec.OperationContext, sel, __EnumValueImplementors) out := graphql.NewFieldSet(fields) var invalids uint32 for i, field := range fields { switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__EnumValue") case "name": out.Values[i] = ec.___EnumValue_name(ctx, field, obj) if out.Values[i] == graphql.Null { invalids++ } case "description": out.Values[i] = ec.___EnumValue_description(ctx, field, obj) case "isDeprecated": out.Values[i] = ec.___EnumValue_isDeprecated(ctx, field, obj) if out.Values[i] == graphql.Null { invalids++ } case "deprecationReason": out.Values[i] = ec.___EnumValue_deprecationReason(ctx, field, obj) default: panic("unknown field " + strconv.Quote(field.Name)) } } out.Dispatch() if invalids > 0 { return graphql.Null } return out } var __FieldImplementors = []string{"__Field"} func (ec *executionContext) ___Field(ctx context.Context, sel ast.SelectionSet, obj *introspection.Field) graphql.Marshaler { fields := graphql.CollectFields(ec.OperationContext, sel, __FieldImplementors) out := graphql.NewFieldSet(fields) var invalids uint32 for i, field := range fields { switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__Field") case "name": out.Values[i] = ec.___Field_name(ctx, field, obj) if out.Values[i] == graphql.Null { invalids++ } case "description": out.Values[i] = ec.___Field_description(ctx, field, obj) case "args": out.Values[i] = ec.___Field_args(ctx, field, obj) if out.Values[i] == graphql.Null { invalids++ } case "type": out.Values[i] = ec.___Field_type(ctx, field, obj) if out.Values[i] == graphql.Null { invalids++ } case "isDeprecated": out.Values[i] = ec.___Field_isDeprecated(ctx, field, obj) if out.Values[i] == graphql.Null { invalids++ } case "deprecationReason": out.Values[i] = ec.___Field_deprecationReason(ctx, field, obj) default: panic("unknown field " + strconv.Quote(field.Name)) } } out.Dispatch() if invalids > 0 { return graphql.Null } return out } var __InputValueImplementors = []string{"__InputValue"} func (ec *executionContext) ___InputValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.InputValue) graphql.Marshaler { fields := graphql.CollectFields(ec.OperationContext, sel, __InputValueImplementors) out := graphql.NewFieldSet(fields) var invalids uint32 for i, field := range fields { switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__InputValue") case "name": out.Values[i] = ec.___InputValue_name(ctx, field, obj) if out.Values[i] == graphql.Null { invalids++ } case "description": out.Values[i] = ec.___InputValue_description(ctx, field, obj) case "type": out.Values[i] = ec.___InputValue_type(ctx, field, obj) if out.Values[i] == graphql.Null { invalids++ } case "defaultValue": out.Values[i] = ec.___InputValue_defaultValue(ctx, field, obj) default: panic("unknown field " + strconv.Quote(field.Name)) } } out.Dispatch() if invalids > 0 { return graphql.Null } return out } var __SchemaImplementors = []string{"__Schema"} func (ec *executionContext) ___Schema(ctx context.Context, sel ast.SelectionSet, obj *introspection.Schema) graphql.Marshaler { fields := graphql.CollectFields(ec.OperationContext, sel, __SchemaImplementors) out := graphql.NewFieldSet(fields) var invalids uint32 for i, field := range fields { switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__Schema") case "types": out.Values[i] = ec.___Schema_types(ctx, field, obj) if out.Values[i] == graphql.Null { invalids++ } case "queryType": out.Values[i] = ec.___Schema_queryType(ctx, field, obj) if out.Values[i] == graphql.Null { invalids++ } case "mutationType": out.Values[i] = ec.___Schema_mutationType(ctx, field, obj) case "subscriptionType": out.Values[i] = ec.___Schema_subscriptionType(ctx, field, obj) case "directives": out.Values[i] = ec.___Schema_directives(ctx, field, obj) if out.Values[i] == graphql.Null { invalids++ } default: panic("unknown field " + strconv.Quote(field.Name)) } } out.Dispatch() if invalids > 0 { return graphql.Null } return out } var __TypeImplementors = []string{"__Type"} func (ec *executionContext) ___Type(ctx context.Context, sel ast.SelectionSet, obj *introspection.Type) graphql.Marshaler { fields := graphql.CollectFields(ec.OperationContext, sel, __TypeImplementors) out := graphql.NewFieldSet(fields) var invalids uint32 for i, field := range fields { switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__Type") case "kind": out.Values[i] = ec.___Type_kind(ctx, field, obj) if out.Values[i] == graphql.Null { invalids++ } case "name": out.Values[i] = ec.___Type_name(ctx, field, obj) case "description": out.Values[i] = ec.___Type_description(ctx, field, obj) case "fields": out.Values[i] = ec.___Type_fields(ctx, field, obj) case "interfaces": out.Values[i] = ec.___Type_interfaces(ctx, field, obj) case "possibleTypes": out.Values[i] = ec.___Type_possibleTypes(ctx, field, obj) case "enumValues": out.Values[i] = ec.___Type_enumValues(ctx, field, obj) case "inputFields": out.Values[i] = ec.___Type_inputFields(ctx, field, obj) case "ofType": out.Values[i] = ec.___Type_ofType(ctx, field, obj) default: panic("unknown field " + strconv.Quote(field.Name)) } } out.Dispatch() if invalids > 0 { return graphql.Null } return out } // endregion **************************** object.gotpl **************************** // region ***************************** type.gotpl ***************************** func (ec *executionContext) unmarshalNBoolean2bool(ctx context.Context, v interface{}) (bool, error) { res, err := graphql.UnmarshalBoolean(v) return res, graphql.WrapErrorWithInputPath(ctx, err) } func (ec *executionContext) marshalNBoolean2bool(ctx context.Context, sel ast.SelectionSet, v bool) graphql.Marshaler { res := graphql.MarshalBoolean(v) if res == graphql.Null { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "must not be null") } } return res } func (ec *executionContext) unmarshalNID2int(ctx context.Context, v interface{}) (int, error) { res, err := graphql.UnmarshalIntID(v) return res, graphql.WrapErrorWithInputPath(ctx, err) } func (ec *executionContext) marshalNID2int(ctx context.Context, sel ast.SelectionSet, v int) graphql.Marshaler { res := graphql.MarshalIntID(v) if res == graphql.Null { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "must not be null") } } return res } func (ec *executionContext) unmarshalNID2string(ctx context.Context, v interface{}) (string, error) { res, err := graphql.UnmarshalID(v) return res, graphql.WrapErrorWithInputPath(ctx, err) } func (ec *executionContext) marshalNID2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler { res := graphql.MarshalID(v) if res == graphql.Null { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "must not be null") } } return res } func (ec *executionContext) marshalNProduct2ᚕᚖgithubᚗcomᚋaristatᚋgolangᚑexampleᚑappᚋappᚋdbᚋdomainᚐProductᚄ(ctx context.Context, sel ast.SelectionSet, v []*domain.Product) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 if !isLen1 { wg.Add(len(v)) } for i := range v { i := i fc := &graphql.FieldContext{ Index: &i, Result: &v[i], } ctx := graphql.WithFieldContext(ctx, fc) f := func(i int) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = nil } }() if !isLen1 { defer wg.Done() } ret[i] = ec.marshalNProduct2ᚖgithubᚗcomᚋaristatᚋgolangᚑexampleᚑappᚋappᚋdbᚋdomainᚐProduct(ctx, sel, v[i]) } if isLen1 { f(i) } else { go f(i) } } wg.Wait() return ret } func (ec *executionContext) marshalNProduct2ᚖgithubᚗcomᚋaristatᚋgolangᚑexampleᚑappᚋappᚋdbᚋdomainᚐProduct(ctx context.Context, sel ast.SelectionSet, v *domain.Product) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "must not be null") } return graphql.Null } return ec._Product(ctx, sel, v) } func (ec *executionContext) marshalNProductItem2ᚕᚖgithubᚗcomᚋaristatᚋgolangᚑexampleᚑappᚋappᚋdbᚋdomainᚐProductItemᚄ(ctx context.Context, sel ast.SelectionSet, v []*domain.ProductItem) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 if !isLen1 { wg.Add(len(v)) } for i := range v { i := i fc := &graphql.FieldContext{ Index: &i, Result: &v[i], } ctx := graphql.WithFieldContext(ctx, fc) f := func(i int) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = nil } }() if !isLen1 { defer wg.Done() } ret[i] = ec.marshalNProductItem2ᚖgithubᚗcomᚋaristatᚋgolangᚑexampleᚑappᚋappᚋdbᚋdomainᚐProductItem(ctx, sel, v[i]) } if isLen1 { f(i) } else { go f(i) } } wg.Wait() return ret } func (ec *executionContext) marshalNProductItem2ᚖgithubᚗcomᚋaristatᚋgolangᚑexampleᚑappᚋappᚋdbᚋdomainᚐProductItem(ctx context.Context, sel ast.SelectionSet, v *domain.ProductItem) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "must not be null") } return graphql.Null } return ec._ProductItem(ctx, sel, v) } func (ec *executionContext) marshalNProductsListOut2githubᚗcomᚋaristatᚋgolangᚑexampleᚑappᚋgeneratedᚋgraphqlᚐProductsListOut(ctx context.Context, sel ast.SelectionSet, v ProductsListOut) graphql.Marshaler { return ec._ProductsListOut(ctx, sel, &v) } func (ec *executionContext) marshalNProductsListOut2ᚖgithubᚗcomᚋaristatᚋgolangᚑexampleᚑappᚋgeneratedᚋgraphqlᚐProductsListOut(ctx context.Context, sel ast.SelectionSet, v *ProductsListOut) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "must not be null") } return graphql.Null } return ec._ProductsListOut(ctx, sel, v) } func (ec *executionContext) unmarshalNString2string(ctx context.Context, v interface{}) (string, error) { res, err := graphql.UnmarshalString(v) return res, graphql.WrapErrorWithInputPath(ctx, err) } func (ec *executionContext) marshalNString2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler { res := graphql.MarshalString(v) if res == graphql.Null { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "must not be null") } } return res } func (ec *executionContext) marshalNUsersCreateOut2githubᚗcomᚋaristatᚋgolangᚑexampleᚑappᚋgeneratedᚋgraphqlᚐUsersCreateOut(ctx context.Context, sel ast.SelectionSet, v UsersCreateOut) graphql.Marshaler { return ec._UsersCreateOut(ctx, sel, &v) } func (ec *executionContext) marshalNUsersCreateOut2ᚖgithubᚗcomᚋaristatᚋgolangᚑexampleᚑappᚋgeneratedᚋgraphqlᚐUsersCreateOut(ctx context.Context, sel ast.SelectionSet, v *UsersCreateOut) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "must not be null") } return graphql.Null } return ec._UsersCreateOut(ctx, sel, v) } func (ec *executionContext) unmarshalNUsersCreateOutStatus2githubᚗcomᚋaristatᚋgolangᚑexampleᚑappᚋgeneratedᚋgraphqlᚐUsersCreateOutStatus(ctx context.Context, v interface{}) (UsersCreateOutStatus, error) { var res UsersCreateOutStatus err := res.UnmarshalGQL(v) return res, graphql.WrapErrorWithInputPath(ctx, err) } func (ec *executionContext) marshalNUsersCreateOutStatus2githubᚗcomᚋaristatᚋgolangᚑexampleᚑappᚋgeneratedᚋgraphqlᚐUsersCreateOutStatus(ctx context.Context, sel ast.SelectionSet, v UsersCreateOutStatus) graphql.Marshaler { return v } func (ec *executionContext) marshalNUsersOneOut2githubᚗcomᚋaristatᚋgolangᚑexampleᚑappᚋgeneratedᚋgraphqlᚐUsersOneOut(ctx context.Context, sel ast.SelectionSet, v UsersOneOut) graphql.Marshaler { return ec._UsersOneOut(ctx, sel, &v) } func (ec *executionContext) marshalNUsersOneOut2ᚖgithubᚗcomᚋaristatᚋgolangᚑexampleᚑappᚋgeneratedᚋgraphqlᚐUsersOneOut(ctx context.Context, sel ast.SelectionSet, v *UsersOneOut) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "must not be null") } return graphql.Null } return ec._UsersOneOut(ctx, sel, v) } func (ec *executionContext) unmarshalNUsersPermissionEnum2githubᚗcomᚋaristatᚋgolangᚑexampleᚑappᚋgeneratedᚋgraphqlᚐUsersPermissionEnum(ctx context.Context, v interface{}) (UsersPermissionEnum, error) { var res UsersPermissionEnum err := res.UnmarshalGQL(v) return res, graphql.WrapErrorWithInputPath(ctx, err) } func (ec *executionContext) marshalNUsersPermissionEnum2githubᚗcomᚋaristatᚋgolangᚑexampleᚑappᚋgeneratedᚋgraphqlᚐUsersPermissionEnum(ctx context.Context, sel ast.SelectionSet, v UsersPermissionEnum) graphql.Marshaler { return v } func (ec *executionContext) marshalN__Directive2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirective(ctx context.Context, sel ast.SelectionSet, v introspection.Directive) graphql.Marshaler { return ec.___Directive(ctx, sel, &v) } func (ec *executionContext) marshalN__Directive2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirectiveᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Directive) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 if !isLen1 { wg.Add(len(v)) } for i := range v { i := i fc := &graphql.FieldContext{ Index: &i, Result: &v[i], } ctx := graphql.WithFieldContext(ctx, fc) f := func(i int) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = nil } }() if !isLen1 { defer wg.Done() } ret[i] = ec.marshalN__Directive2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirective(ctx, sel, v[i]) } if isLen1 { f(i) } else { go f(i) } } wg.Wait() return ret } func (ec *executionContext) unmarshalN__DirectiveLocation2string(ctx context.Context, v interface{}) (string, error) { res, err := graphql.UnmarshalString(v) return res, graphql.WrapErrorWithInputPath(ctx, err) } func (ec *executionContext) marshalN__DirectiveLocation2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler { res := graphql.MarshalString(v) if res == graphql.Null { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "must not be null") } } return res } func (ec *executionContext) unmarshalN__DirectiveLocation2ᚕstringᚄ(ctx context.Context, v interface{}) ([]string, error) { var vSlice []interface{} if v != nil { if tmp1, ok := v.([]interface{}); ok { vSlice = tmp1 } else { vSlice = []interface{}{v} } } var err error res := make([]string, len(vSlice)) for i := range vSlice { ctx := graphql.WithFieldInputContext(ctx, graphql.NewFieldInputWithIndex(i)) res[i], err = ec.unmarshalN__DirectiveLocation2string(ctx, vSlice[i]) if err != nil { return nil, graphql.WrapErrorWithInputPath(ctx, err) } } return res, nil } func (ec *executionContext) marshalN__DirectiveLocation2ᚕstringᚄ(ctx context.Context, sel ast.SelectionSet, v []string) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 if !isLen1 { wg.Add(len(v)) } for i := range v { i := i fc := &graphql.FieldContext{ Index: &i, Result: &v[i], } ctx := graphql.WithFieldContext(ctx, fc) f := func(i int) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = nil } }() if !isLen1 { defer wg.Done() } ret[i] = ec.marshalN__DirectiveLocation2string(ctx, sel, v[i]) } if isLen1 { f(i) } else { go f(i) } } wg.Wait() return ret } func (ec *executionContext) marshalN__EnumValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValue(ctx context.Context, sel ast.SelectionSet, v introspection.EnumValue) graphql.Marshaler { return ec.___EnumValue(ctx, sel, &v) } func (ec *executionContext) marshalN__Field2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐField(ctx context.Context, sel ast.SelectionSet, v introspection.Field) graphql.Marshaler { return ec.___Field(ctx, sel, &v) } func (ec *executionContext) marshalN__InputValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx context.Context, sel ast.SelectionSet, v introspection.InputValue) graphql.Marshaler { return ec.___InputValue(ctx, sel, &v) } func (ec *executionContext) marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.InputValue) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 if !isLen1 { wg.Add(len(v)) } for i := range v { i := i fc := &graphql.FieldContext{ Index: &i, Result: &v[i], } ctx := graphql.WithFieldContext(ctx, fc) f := func(i int) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = nil } }() if !isLen1 { defer wg.Done() } ret[i] = ec.marshalN__InputValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx, sel, v[i]) } if isLen1 { f(i) } else { go f(i) } } wg.Wait() return ret } func (ec *executionContext) marshalN__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v introspection.Type) graphql.Marshaler { return ec.___Type(ctx, sel, &v) } func (ec *executionContext) marshalN__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Type) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 if !isLen1 { wg.Add(len(v)) } for i := range v { i := i fc := &graphql.FieldContext{ Index: &i, Result: &v[i], } ctx := graphql.WithFieldContext(ctx, fc) f := func(i int) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = nil } }() if !isLen1 { defer wg.Done() } ret[i] = ec.marshalN__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, sel, v[i]) } if isLen1 { f(i) } else { go f(i) } } wg.Wait() return ret } func (ec *executionContext) marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v *introspection.Type) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "must not be null") } return graphql.Null } return ec.___Type(ctx, sel, v) } func (ec *executionContext) unmarshalN__TypeKind2string(ctx context.Context, v interface{}) (string, error) { res, err := graphql.UnmarshalString(v) return res, graphql.WrapErrorWithInputPath(ctx, err) } func (ec *executionContext) marshalN__TypeKind2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler { res := graphql.MarshalString(v) if res == graphql.Null { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "must not be null") } } return res } func (ec *executionContext) unmarshalOBoolean2bool(ctx context.Context, v interface{}) (bool, error) { res, err := graphql.UnmarshalBoolean(v) return res, graphql.WrapErrorWithInputPath(ctx, err) } func (ec *executionContext) marshalOBoolean2bool(ctx context.Context, sel ast.SelectionSet, v bool) graphql.Marshaler { return graphql.MarshalBoolean(v) } func (ec *executionContext) unmarshalOBoolean2ᚖbool(ctx context.Context, v interface{}) (*bool, error) { if v == nil { return nil, nil } res, err := graphql.UnmarshalBoolean(v) return &res, graphql.WrapErrorWithInputPath(ctx, err) } func (ec *executionContext) marshalOBoolean2ᚖbool(ctx context.Context, sel ast.SelectionSet, v *bool) graphql.Marshaler { if v == nil { return graphql.Null } return graphql.MarshalBoolean(*v) } func (ec *executionContext) marshalOProductsQuery2ᚖgithubᚗcomᚋaristatᚋgolangᚑexampleᚑappᚋgeneratedᚋgraphqlᚐProductsQuery(ctx context.Context, sel ast.SelectionSet, v *ProductsQuery) graphql.Marshaler { if v == nil { return graphql.Null } return ec._ProductsQuery(ctx, sel, v) } func (ec *executionContext) unmarshalOString2string(ctx context.Context, v interface{}) (string, error) { res, err := graphql.UnmarshalString(v) return res, graphql.WrapErrorWithInputPath(ctx, err) } func (ec *executionContext) marshalOString2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler { return graphql.MarshalString(v) } func (ec *executionContext) unmarshalOString2ᚖstring(ctx context.Context, v interface{}) (*string, error) { if v == nil { return nil, nil } res, err := graphql.UnmarshalString(v) return &res, graphql.WrapErrorWithInputPath(ctx, err) } func (ec *executionContext) marshalOString2ᚖstring(ctx context.Context, sel ast.SelectionSet, v *string) graphql.Marshaler { if v == nil { return graphql.Null } return graphql.MarshalString(*v) } func (ec *executionContext) marshalOUsersMutation2ᚖgithubᚗcomᚋaristatᚋgolangᚑexampleᚑappᚋgeneratedᚋgraphqlᚐUsersMutation(ctx context.Context, sel ast.SelectionSet, v *UsersMutation) graphql.Marshaler { if v == nil { return graphql.Null } return ec._UsersMutation(ctx, sel, v) } func (ec *executionContext) marshalOUsersQuery2ᚖgithubᚗcomᚋaristatᚋgolangᚑexampleᚑappᚋgeneratedᚋgraphqlᚐUsersQuery(ctx context.Context, sel ast.SelectionSet, v *UsersQuery) graphql.Marshaler { if v == nil { return graphql.Null } return ec._UsersQuery(ctx, sel, v) } func (ec *executionContext) marshalO__EnumValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValueᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.EnumValue) graphql.Marshaler { if v == nil { return graphql.Null } ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 if !isLen1 { wg.Add(len(v)) } for i := range v { i := i fc := &graphql.FieldContext{ Index: &i, Result: &v[i], } ctx := graphql.WithFieldContext(ctx, fc) f := func(i int) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = nil } }() if !isLen1 { defer wg.Done() } ret[i] = ec.marshalN__EnumValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValue(ctx, sel, v[i]) } if isLen1 { f(i) } else { go f(i) } } wg.Wait() return ret } func (ec *executionContext) marshalO__Field2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐFieldᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Field) graphql.Marshaler { if v == nil { return graphql.Null } ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 if !isLen1 { wg.Add(len(v)) } for i := range v { i := i fc := &graphql.FieldContext{ Index: &i, Result: &v[i], } ctx := graphql.WithFieldContext(ctx, fc) f := func(i int) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = nil } }() if !isLen1 { defer wg.Done() } ret[i] = ec.marshalN__Field2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐField(ctx, sel, v[i]) } if isLen1 { f(i) } else { go f(i) } } wg.Wait() return ret } func (ec *executionContext) marshalO__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.InputValue) graphql.Marshaler { if v == nil { return graphql.Null } ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 if !isLen1 { wg.Add(len(v)) } for i := range v { i := i fc := &graphql.FieldContext{ Index: &i, Result: &v[i], } ctx := graphql.WithFieldContext(ctx, fc) f := func(i int) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = nil } }() if !isLen1 { defer wg.Done() } ret[i] = ec.marshalN__InputValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx, sel, v[i]) } if isLen1 { f(i) } else { go f(i) } } wg.Wait() return ret } func (ec *executionContext) marshalO__Schema2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐSchema(ctx context.Context, sel ast.SelectionSet, v *introspection.Schema) graphql.Marshaler { if v == nil { return graphql.Null } return ec.___Schema(ctx, sel, v) } func (ec *executionContext) marshalO__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Type) graphql.Marshaler { if v == nil { return graphql.Null } ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 if !isLen1 { wg.Add(len(v)) } for i := range v { i := i fc := &graphql.FieldContext{ Index: &i, Result: &v[i], } ctx := graphql.WithFieldContext(ctx, fc) f := func(i int) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = nil } }() if !isLen1 { defer wg.Done() } ret[i] = ec.marshalN__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, sel, v[i]) } if isLen1 { f(i) } else { go f(i) } } wg.Wait() return ret } func (ec *executionContext) marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v *introspection.Type) graphql.Marshaler { if v == nil { return graphql.Null } return ec.___Type(ctx, sel, v) } // endregion ***************************** type.gotpl ***************************** ================================================ FILE: generated/graphql/models_gen.go ================================================ // Code generated by github.com/99designs/gqlgen, DO NOT EDIT. package graphql import ( "fmt" "io" "strconv" "github.com/aristat/golang-example-app/app/db/domain" ) type ProductsListOut struct { Products []*domain.Product `json:"products"` } type ProductsQuery struct { List *ProductsListOut `json:"list"` } type UsersCreateOut struct { Status UsersCreateOutStatus `json:"status"` ID string `json:"id"` Email string `json:"email"` } type UsersMutation struct { CreateUser *UsersCreateOut `json:"createUser"` } type UsersOneOut struct { ID string `json:"id"` Email string `json:"email"` } type UsersQuery struct { One *UsersOneOut `json:"one"` } type UsersCreateOutStatus string const ( UsersCreateOutStatusOk UsersCreateOutStatus = "OK" UsersCreateOutStatusBadRequest UsersCreateOutStatus = "BAD_REQUEST" UsersCreateOutStatusServerInternalError UsersCreateOutStatus = "SERVER_INTERNAL_ERROR" ) var AllUsersCreateOutStatus = []UsersCreateOutStatus{ UsersCreateOutStatusOk, UsersCreateOutStatusBadRequest, UsersCreateOutStatusServerInternalError, } func (e UsersCreateOutStatus) IsValid() bool { switch e { case UsersCreateOutStatusOk, UsersCreateOutStatusBadRequest, UsersCreateOutStatusServerInternalError: return true } return false } func (e UsersCreateOutStatus) String() string { return string(e) } func (e *UsersCreateOutStatus) UnmarshalGQL(v interface{}) error { str, ok := v.(string) if !ok { return fmt.Errorf("enums must be strings") } *e = UsersCreateOutStatus(str) if !e.IsValid() { return fmt.Errorf("%s is not a valid UsersCreateOutStatus", str) } return nil } func (e UsersCreateOutStatus) MarshalGQL(w io.Writer) { fmt.Fprint(w, strconv.Quote(e.String())) } type UsersPermissionEnum string const ( UsersPermissionEnumRead UsersPermissionEnum = "READ" UsersPermissionEnumWrite UsersPermissionEnum = "WRITE" ) var AllUsersPermissionEnum = []UsersPermissionEnum{ UsersPermissionEnumRead, UsersPermissionEnumWrite, } func (e UsersPermissionEnum) IsValid() bool { switch e { case UsersPermissionEnumRead, UsersPermissionEnumWrite: return true } return false } func (e UsersPermissionEnum) String() string { return string(e) } func (e *UsersPermissionEnum) UnmarshalGQL(v interface{}) error { str, ok := v.(string) if !ok { return fmt.Errorf("enums must be strings") } *e = UsersPermissionEnum(str) if !e.IsValid() { return fmt.Errorf("%s is not a valid UsersPermissionEnum", str) } return nil } func (e UsersPermissionEnum) MarshalGQL(w io.Writer) { fmt.Fprint(w, strconv.Quote(e.String())) } ================================================ FILE: generated/resources/proto/health_checks/health_checks.pb.go ================================================ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.1 // protoc v3.17.3 // source: resources/proto/health_checks/health_checks.proto package health_checks import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" emptypb "google.golang.org/protobuf/types/known/emptypb" reflect "reflect" sync "sync" ) 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) ) type IsAliveOut_Status int32 const ( IsAliveOut_OK IsAliveOut_Status = 0 IsAliveOut_NOT_OK IsAliveOut_Status = 2 ) // Enum value maps for IsAliveOut_Status. var ( IsAliveOut_Status_name = map[int32]string{ 0: "OK", 2: "NOT_OK", } IsAliveOut_Status_value = map[string]int32{ "OK": 0, "NOT_OK": 2, } ) func (x IsAliveOut_Status) Enum() *IsAliveOut_Status { p := new(IsAliveOut_Status) *p = x return p } func (x IsAliveOut_Status) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (IsAliveOut_Status) Descriptor() protoreflect.EnumDescriptor { return file_resources_proto_health_checks_health_checks_proto_enumTypes[0].Descriptor() } func (IsAliveOut_Status) Type() protoreflect.EnumType { return &file_resources_proto_health_checks_health_checks_proto_enumTypes[0] } func (x IsAliveOut_Status) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Use IsAliveOut_Status.Descriptor instead. func (IsAliveOut_Status) EnumDescriptor() ([]byte, []int) { return file_resources_proto_health_checks_health_checks_proto_rawDescGZIP(), []int{0, 0} } type IsAliveOut struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Status IsAliveOut_Status `protobuf:"varint,1,opt,name=status,proto3,enum=health_checks.IsAliveOut_Status" json:"status,omitempty"` } func (x *IsAliveOut) Reset() { *x = IsAliveOut{} if protoimpl.UnsafeEnabled { mi := &file_resources_proto_health_checks_health_checks_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *IsAliveOut) String() string { return protoimpl.X.MessageStringOf(x) } func (*IsAliveOut) ProtoMessage() {} func (x *IsAliveOut) ProtoReflect() protoreflect.Message { mi := &file_resources_proto_health_checks_health_checks_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use IsAliveOut.ProtoReflect.Descriptor instead. func (*IsAliveOut) Descriptor() ([]byte, []int) { return file_resources_proto_health_checks_health_checks_proto_rawDescGZIP(), []int{0} } func (x *IsAliveOut) GetStatus() IsAliveOut_Status { if x != nil { return x.Status } return IsAliveOut_OK } var File_resources_proto_health_checks_health_checks_proto protoreflect.FileDescriptor var file_resources_proto_health_checks_health_checks_proto_rawDesc = []byte{ 0x0a, 0x31, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x2f, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0d, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x64, 0x0a, 0x0a, 0x49, 0x73, 0x41, 0x6c, 0x69, 0x76, 0x65, 0x4f, 0x75, 0x74, 0x12, 0x38, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x2e, 0x49, 0x73, 0x41, 0x6c, 0x69, 0x76, 0x65, 0x4f, 0x75, 0x74, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x1c, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x06, 0x0a, 0x02, 0x4f, 0x4b, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x4e, 0x4f, 0x54, 0x5f, 0x4f, 0x4b, 0x10, 0x02, 0x32, 0x4e, 0x0a, 0x0c, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x12, 0x3e, 0x0a, 0x07, 0x49, 0x73, 0x41, 0x6c, 0x69, 0x76, 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x19, 0x2e, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x2e, 0x49, 0x73, 0x41, 0x6c, 0x69, 0x76, 0x65, 0x4f, 0x75, 0x74, 0x22, 0x00, 0x42, 0x35, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x72, 0x69, 0x73, 0x74, 0x61, 0x74, 0x2f, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2d, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2d, 0x61, 0x70, 0x70, 0x2f, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_resources_proto_health_checks_health_checks_proto_rawDescOnce sync.Once file_resources_proto_health_checks_health_checks_proto_rawDescData = file_resources_proto_health_checks_health_checks_proto_rawDesc ) func file_resources_proto_health_checks_health_checks_proto_rawDescGZIP() []byte { file_resources_proto_health_checks_health_checks_proto_rawDescOnce.Do(func() { file_resources_proto_health_checks_health_checks_proto_rawDescData = protoimpl.X.CompressGZIP(file_resources_proto_health_checks_health_checks_proto_rawDescData) }) return file_resources_proto_health_checks_health_checks_proto_rawDescData } var file_resources_proto_health_checks_health_checks_proto_enumTypes = make([]protoimpl.EnumInfo, 1) var file_resources_proto_health_checks_health_checks_proto_msgTypes = make([]protoimpl.MessageInfo, 1) var file_resources_proto_health_checks_health_checks_proto_goTypes = []interface{}{ (IsAliveOut_Status)(0), // 0: health_checks.IsAliveOut.Status (*IsAliveOut)(nil), // 1: health_checks.IsAliveOut (*emptypb.Empty)(nil), // 2: google.protobuf.Empty } var file_resources_proto_health_checks_health_checks_proto_depIdxs = []int32{ 0, // 0: health_checks.IsAliveOut.status:type_name -> health_checks.IsAliveOut.Status 2, // 1: health_checks.HealthChecks.IsAlive:input_type -> google.protobuf.Empty 1, // 2: health_checks.HealthChecks.IsAlive:output_type -> health_checks.IsAliveOut 2, // [2:3] is the sub-list for method output_type 1, // [1:2] is the sub-list for method input_type 1, // [1:1] is the sub-list for extension type_name 1, // [1:1] is the sub-list for extension extendee 0, // [0:1] is the sub-list for field type_name } func init() { file_resources_proto_health_checks_health_checks_proto_init() } func file_resources_proto_health_checks_health_checks_proto_init() { if File_resources_proto_health_checks_health_checks_proto != nil { return } if !protoimpl.UnsafeEnabled { file_resources_proto_health_checks_health_checks_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*IsAliveOut); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_resources_proto_health_checks_health_checks_proto_rawDesc, NumEnums: 1, NumMessages: 1, NumExtensions: 0, NumServices: 1, }, GoTypes: file_resources_proto_health_checks_health_checks_proto_goTypes, DependencyIndexes: file_resources_proto_health_checks_health_checks_proto_depIdxs, EnumInfos: file_resources_proto_health_checks_health_checks_proto_enumTypes, MessageInfos: file_resources_proto_health_checks_health_checks_proto_msgTypes, }.Build() File_resources_proto_health_checks_health_checks_proto = out.File file_resources_proto_health_checks_health_checks_proto_rawDesc = nil file_resources_proto_health_checks_health_checks_proto_goTypes = nil file_resources_proto_health_checks_health_checks_proto_depIdxs = nil } ================================================ FILE: generated/resources/proto/health_checks/health_checks_grpc.pb.go ================================================ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. package health_checks import ( context "context" grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" emptypb "google.golang.org/protobuf/types/known/emptypb" ) // 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.32.0 or later. const _ = grpc.SupportPackageIsVersion7 // HealthChecksClient is the client API for HealthChecks 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. type HealthChecksClient interface { IsAlive(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*IsAliveOut, error) } type healthChecksClient struct { cc grpc.ClientConnInterface } func NewHealthChecksClient(cc grpc.ClientConnInterface) HealthChecksClient { return &healthChecksClient{cc} } func (c *healthChecksClient) IsAlive(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*IsAliveOut, error) { out := new(IsAliveOut) err := c.cc.Invoke(ctx, "/health_checks.HealthChecks/IsAlive", in, out, opts...) if err != nil { return nil, err } return out, nil } // HealthChecksServer is the server API for HealthChecks service. // All implementations must embed UnimplementedHealthChecksServer // for forward compatibility type HealthChecksServer interface { IsAlive(context.Context, *emptypb.Empty) (*IsAliveOut, error) mustEmbedUnimplementedHealthChecksServer() } // UnimplementedHealthChecksServer must be embedded to have forward compatible implementations. type UnimplementedHealthChecksServer struct { } func (UnimplementedHealthChecksServer) IsAlive(context.Context, *emptypb.Empty) (*IsAliveOut, error) { return nil, status.Errorf(codes.Unimplemented, "method IsAlive not implemented") } func (UnimplementedHealthChecksServer) mustEmbedUnimplementedHealthChecksServer() {} // UnsafeHealthChecksServer may be embedded to opt out of forward compatibility for this service. // Use of this interface is not recommended, as added methods to HealthChecksServer will // result in compilation errors. type UnsafeHealthChecksServer interface { mustEmbedUnimplementedHealthChecksServer() } func RegisterHealthChecksServer(s grpc.ServiceRegistrar, srv HealthChecksServer) { s.RegisterService(&HealthChecks_ServiceDesc, srv) } func _HealthChecks_IsAlive_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(emptypb.Empty) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(HealthChecksServer).IsAlive(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: "/health_checks.HealthChecks/IsAlive", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(HealthChecksServer).IsAlive(ctx, req.(*emptypb.Empty)) } return interceptor(ctx, in, info, handler) } // HealthChecks_ServiceDesc is the grpc.ServiceDesc for HealthChecks service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) var HealthChecks_ServiceDesc = grpc.ServiceDesc{ ServiceName: "health_checks.HealthChecks", HandlerType: (*HealthChecksServer)(nil), Methods: []grpc.MethodDesc{ { MethodName: "IsAlive", Handler: _HealthChecks_IsAlive_Handler, }, }, Streams: []grpc.StreamDesc{}, Metadata: "resources/proto/health_checks/health_checks.proto", } ================================================ FILE: generated/resources/proto/products/products.pb.go ================================================ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.1 // protoc v3.17.3 // source: resources/proto/products/products.proto package products import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" ) 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) ) type ListProductOut_Status int32 const ( ListProductOut_OK ListProductOut_Status = 0 ListProductOut_NOT_FOUND ListProductOut_Status = 2 ) // Enum value maps for ListProductOut_Status. var ( ListProductOut_Status_name = map[int32]string{ 0: "OK", 2: "NOT_FOUND", } ListProductOut_Status_value = map[string]int32{ "OK": 0, "NOT_FOUND": 2, } ) func (x ListProductOut_Status) Enum() *ListProductOut_Status { p := new(ListProductOut_Status) *p = x return p } func (x ListProductOut_Status) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (ListProductOut_Status) Descriptor() protoreflect.EnumDescriptor { return file_resources_proto_products_products_proto_enumTypes[0].Descriptor() } func (ListProductOut_Status) Type() protoreflect.EnumType { return &file_resources_proto_products_products_proto_enumTypes[0] } func (x ListProductOut_Status) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Use ListProductOut_Status.Descriptor instead. func (ListProductOut_Status) EnumDescriptor() ([]byte, []int) { return file_resources_proto_products_products_proto_rawDescGZIP(), []int{2, 0} } type Product struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` } func (x *Product) Reset() { *x = Product{} if protoimpl.UnsafeEnabled { mi := &file_resources_proto_products_products_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *Product) String() string { return protoimpl.X.MessageStringOf(x) } func (*Product) ProtoMessage() {} func (x *Product) ProtoReflect() protoreflect.Message { mi := &file_resources_proto_products_products_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use Product.ProtoReflect.Descriptor instead. func (*Product) Descriptor() ([]byte, []int) { return file_resources_proto_products_products_proto_rawDescGZIP(), []int{0} } func (x *Product) GetId() int64 { if x != nil { return x.Id } return 0 } func (x *Product) GetName() string { if x != nil { return x.Name } return "" } type ListProductIn struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` } func (x *ListProductIn) Reset() { *x = ListProductIn{} if protoimpl.UnsafeEnabled { mi := &file_resources_proto_products_products_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *ListProductIn) String() string { return protoimpl.X.MessageStringOf(x) } func (*ListProductIn) ProtoMessage() {} func (x *ListProductIn) ProtoReflect() protoreflect.Message { mi := &file_resources_proto_products_products_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use ListProductIn.ProtoReflect.Descriptor instead. func (*ListProductIn) Descriptor() ([]byte, []int) { return file_resources_proto_products_products_proto_rawDescGZIP(), []int{1} } func (x *ListProductIn) GetId() int64 { if x != nil { return x.Id } return 0 } type ListProductOut struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Status ListProductOut_Status `protobuf:"varint,1,opt,name=status,proto3,enum=products.ListProductOut_Status" json:"status,omitempty"` Products []*Product `protobuf:"bytes,2,rep,name=products,proto3" json:"products,omitempty"` } func (x *ListProductOut) Reset() { *x = ListProductOut{} if protoimpl.UnsafeEnabled { mi := &file_resources_proto_products_products_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *ListProductOut) String() string { return protoimpl.X.MessageStringOf(x) } func (*ListProductOut) ProtoMessage() {} func (x *ListProductOut) ProtoReflect() protoreflect.Message { mi := &file_resources_proto_products_products_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) } return ms } return mi.MessageOf(x) } // Deprecated: Use ListProductOut.ProtoReflect.Descriptor instead. func (*ListProductOut) Descriptor() ([]byte, []int) { return file_resources_proto_products_products_proto_rawDescGZIP(), []int{2} } func (x *ListProductOut) GetStatus() ListProductOut_Status { if x != nil { return x.Status } return ListProductOut_OK } func (x *ListProductOut) GetProducts() []*Product { if x != nil { return x.Products } return nil } var File_resources_proto_products_products_proto protoreflect.FileDescriptor var file_resources_proto_products_products_proto_rawDesc = []byte{ 0x0a, 0x27, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x73, 0x2f, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x08, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x73, 0x22, 0x2d, 0x0a, 0x07, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x1f, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x22, 0x99, 0x01, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x4f, 0x75, 0x74, 0x12, 0x37, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x73, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x4f, 0x75, 0x74, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2d, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x73, 0x2e, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x73, 0x22, 0x1f, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x06, 0x0a, 0x02, 0x4f, 0x4b, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x4f, 0x54, 0x5f, 0x46, 0x4f, 0x55, 0x4e, 0x44, 0x10, 0x02, 0x32, 0x4e, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x73, 0x12, 0x42, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x12, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x73, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x6e, 0x1a, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x73, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x4f, 0x75, 0x74, 0x22, 0x00, 0x42, 0x30, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x72, 0x69, 0x73, 0x74, 0x61, 0x74, 0x2f, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2d, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2d, 0x61, 0x70, 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_resources_proto_products_products_proto_rawDescOnce sync.Once file_resources_proto_products_products_proto_rawDescData = file_resources_proto_products_products_proto_rawDesc ) func file_resources_proto_products_products_proto_rawDescGZIP() []byte { file_resources_proto_products_products_proto_rawDescOnce.Do(func() { file_resources_proto_products_products_proto_rawDescData = protoimpl.X.CompressGZIP(file_resources_proto_products_products_proto_rawDescData) }) return file_resources_proto_products_products_proto_rawDescData } var file_resources_proto_products_products_proto_enumTypes = make([]protoimpl.EnumInfo, 1) var file_resources_proto_products_products_proto_msgTypes = make([]protoimpl.MessageInfo, 3) var file_resources_proto_products_products_proto_goTypes = []interface{}{ (ListProductOut_Status)(0), // 0: products.ListProductOut.Status (*Product)(nil), // 1: products.Product (*ListProductIn)(nil), // 2: products.ListProductIn (*ListProductOut)(nil), // 3: products.ListProductOut } var file_resources_proto_products_products_proto_depIdxs = []int32{ 0, // 0: products.ListProductOut.status:type_name -> products.ListProductOut.Status 1, // 1: products.ListProductOut.products:type_name -> products.Product 2, // 2: products.Products.ListProduct:input_type -> products.ListProductIn 3, // 3: products.Products.ListProduct:output_type -> products.ListProductOut 3, // [3:4] is the sub-list for method output_type 2, // [2:3] is the sub-list for method input_type 2, // [2:2] is the sub-list for extension type_name 2, // [2:2] is the sub-list for extension extendee 0, // [0:2] is the sub-list for field type_name } func init() { file_resources_proto_products_products_proto_init() } func file_resources_proto_products_products_proto_init() { if File_resources_proto_products_products_proto != nil { return } if !protoimpl.UnsafeEnabled { file_resources_proto_products_products_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Product); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_resources_proto_products_products_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ListProductIn); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_resources_proto_products_products_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ListProductOut); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_resources_proto_products_products_proto_rawDesc, NumEnums: 1, NumMessages: 3, NumExtensions: 0, NumServices: 1, }, GoTypes: file_resources_proto_products_products_proto_goTypes, DependencyIndexes: file_resources_proto_products_products_proto_depIdxs, EnumInfos: file_resources_proto_products_products_proto_enumTypes, MessageInfos: file_resources_proto_products_products_proto_msgTypes, }.Build() File_resources_proto_products_products_proto = out.File file_resources_proto_products_products_proto_rawDesc = nil file_resources_proto_products_products_proto_goTypes = nil file_resources_proto_products_products_proto_depIdxs = nil } ================================================ FILE: generated/resources/proto/products/products_grpc.pb.go ================================================ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. package products 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.32.0 or later. const _ = grpc.SupportPackageIsVersion7 // ProductsClient is the client API for Products 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. type ProductsClient interface { ListProduct(ctx context.Context, in *ListProductIn, opts ...grpc.CallOption) (*ListProductOut, error) } type productsClient struct { cc grpc.ClientConnInterface } func NewProductsClient(cc grpc.ClientConnInterface) ProductsClient { return &productsClient{cc} } func (c *productsClient) ListProduct(ctx context.Context, in *ListProductIn, opts ...grpc.CallOption) (*ListProductOut, error) { out := new(ListProductOut) err := c.cc.Invoke(ctx, "/products.Products/ListProduct", in, out, opts...) if err != nil { return nil, err } return out, nil } // ProductsServer is the server API for Products service. // All implementations must embed UnimplementedProductsServer // for forward compatibility type ProductsServer interface { ListProduct(context.Context, *ListProductIn) (*ListProductOut, error) mustEmbedUnimplementedProductsServer() } // UnimplementedProductsServer must be embedded to have forward compatible implementations. type UnimplementedProductsServer struct { } func (UnimplementedProductsServer) ListProduct(context.Context, *ListProductIn) (*ListProductOut, error) { return nil, status.Errorf(codes.Unimplemented, "method ListProduct not implemented") } func (UnimplementedProductsServer) mustEmbedUnimplementedProductsServer() {} // UnsafeProductsServer may be embedded to opt out of forward compatibility for this service. // Use of this interface is not recommended, as added methods to ProductsServer will // result in compilation errors. type UnsafeProductsServer interface { mustEmbedUnimplementedProductsServer() } func RegisterProductsServer(s grpc.ServiceRegistrar, srv ProductsServer) { s.RegisterService(&Products_ServiceDesc, srv) } func _Products_ListProduct_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(ListProductIn) if err := dec(in); err != nil { return nil, err } if interceptor == nil { return srv.(ProductsServer).ListProduct(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, FullMethod: "/products.Products/ListProduct", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(ProductsServer).ListProduct(ctx, req.(*ListProductIn)) } return interceptor(ctx, in, info, handler) } // Products_ServiceDesc is the grpc.ServiceDesc for Products service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) var Products_ServiceDesc = grpc.ServiceDesc{ ServiceName: "products.Products", HandlerType: (*ProductsServer)(nil), Methods: []grpc.MethodDesc{ { MethodName: "ListProduct", Handler: _Products_ListProduct_Handler, }, }, Streams: []grpc.StreamDesc{}, Metadata: "resources/proto/products/products.proto", } ================================================ FILE: go.mod ================================================ module github.com/aristat/golang-example-app require ( github.com/99designs/gqlgen v0.12.2 github.com/agnivade/levenshtein v1.1.0 // indirect github.com/casbin/casbin v1.9.1 github.com/go-chi/chi/v5 v5.0.7 github.com/go-session/session v3.1.2+incompatible github.com/golang-jwt/jwt v3.2.2+incompatible github.com/google/wire v0.5.0 github.com/hashicorp/golang-lru v0.5.4 // indirect github.com/jinzhu/gorm v1.9.10 github.com/kr/text v0.2.0 // indirect github.com/lib/pq v1.10.4 github.com/mitchellh/mapstructure v1.4.1 github.com/nats-io/nats-streaming-server v0.24.5 // indirect github.com/nats-io/nats.go v1.14.0 github.com/nats-io/stan.go v0.10.2 github.com/pkg/errors v0.9.1 github.com/processout/grpc-go-pool v1.2.1 github.com/riandyrn/otelchi v0.4.0 github.com/rubenv/sql-migrate v1.1.1 github.com/selvatico/go-mocket v1.0.7 github.com/spf13/cast v1.3.1 github.com/spf13/cobra v1.2.1 github.com/spf13/viper v1.8.1 github.com/stretchr/testify v1.7.1 github.com/vektah/gqlparser/v2 v2.0.1 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.32.0 go.opentelemetry.io/otel v1.7.0 go.opentelemetry.io/otel/exporters/jaeger v1.7.0 go.opentelemetry.io/otel/sdk v1.7.0 go.uber.org/atomic v1.9.0 // indirect go.uber.org/automaxprocs v1.2.0 go.uber.org/zap v1.17.0 golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd golang.org/x/sys v0.0.0-20220429233432-b5fbb4746d32 // indirect golang.org/x/text v0.3.7 // indirect golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f // indirect google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8 // indirect google.golang.org/grpc v1.46.0 google.golang.org/protobuf v1.27.1 ) go 1.13 ================================================ FILE: go.sum ================================================ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7hw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= cloud.google.com/go v0.81.0 h1:at8Tk2zUz63cLPR0JPWm5vp77pEZmzxEQBEfRKn1VV8= cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/99designs/gqlgen v0.12.2 h1:aOdpsiCycFtCnAv8CAI1exnKrIDHMqtMzQoXeTziY4o= github.com/99designs/gqlgen v0.12.2/go.mod h1:7zdGo6ry9u1YBp/qlb2uxSU5Mt2jQKLcBETQiKk+Bxo= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible h1:1G1pk05UrOh0NlF1oeaaix1x8XzrfjIDK47TY0Zehcw= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= github.com/agnivade/levenshtein v1.0.3/go.mod h1:4SFRZbbXWLF4MU1T9Qg0pGgH3Pjs+t6ie5efyrwRJXs= github.com/agnivade/levenshtein v1.1.0 h1:n6qGwyHG61v3ABce1rPVZklEYRT8NFpCMrpZdBUbYGM= github.com/agnivade/levenshtein v1.1.0/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q= github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878 h1:EFSB7Zo9Eg91v7MJPVsifUysc/wPdN+NOnVe6bWbdBM= github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878/go.mod h1:3AMJUQhVx52RsWOnlkpikZr01T/yAVN2gn0861vByNg= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/casbin/casbin v1.9.1 h1:ucjbS5zTrmSLtH4XogqOG920Poe6QatdXtz1FEbApeM= github.com/casbin/casbin v1.9.1/go.mod h1:z8uPsfBJGUsnkagrt3G8QvjgTKFMBJ32UP8HpZllfog= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/denisenkom/go-mssqldb v0.0.0-20190515213511-eb9f6a1743f3/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM= github.com/denisenkom/go-mssqldb v0.9.0 h1:RSohk2RsiZqLZ0zCjtfn3S4Gp4exhpBWHyQ7D0yGjAk= github.com/denisenkom/go-mssqldb v0.9.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/dgryski/trifles v0.0.0-20190318185328-a8d75aae118c/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48 h1:fRzb/w+pyskVMQ+UbP35JkH8yB7MYb4q/qhBarqZE6g= github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y= github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0= github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/felixge/httpsnoop v1.0.2 h1:+nS9g82KMXccJ/wp0zyRW9ZBHFETmMGtkk+2CTTrW4o= github.com/felixge/httpsnoop v1.0.2/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-chi/chi v3.3.2+incompatible h1:uQNcQN3NsV1j4ANsPh42P4ew4t6rnRbJb8frvpp31qQ= github.com/go-chi/chi v3.3.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= github.com/go-chi/chi/v5 v5.0.7 h1:rDTPXLDHGATaeHvVlLcR4Qe0zftYethFucbjVQ1PxU8= github.com/go-chi/chi/v5 v5.0.7/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gorp/gorp/v3 v3.0.2 h1:ULqJXIekoqMx29FI5ekXXFoH1dT2Vc8UhnRzBg+Emz4= github.com/go-gorp/gorp/v3 v3.0.2/go.mod h1:BJ3q1ejpV8cVALtcXvXaXyTOlMmJhWDxTmncaR6rwBY= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.1/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/stdr v1.2.0/go.mod h1:YkVgnZu1ZjjL7xTxrfm/LLZBfkhTqSR1ydtm6jTKKwI= 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/go-session/session v3.1.2+incompatible h1:yStchEObKg4nk2F7JGE7KoFIrA/1Y078peagMWcrncg= github.com/go-session/session v3.1.2+incompatible/go.mod h1:8B3iivBQjrz/JtC68Np2T1yBBLxTan3mn/3OM0CyRt0= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gobuffalo/logger v1.0.6 h1:nnZNpxYo0zx+Aj9RfMPBm+x9zAU2OayFh/xrAWi34HU= github.com/gobuffalo/logger v1.0.6/go.mod h1:J31TBEHR1QLV2683OXTAItYIg8pv2JMHnF/quuAbMjs= github.com/gobuffalo/packd v1.0.1 h1:U2wXfRr4E9DH8IdsDLlRFwTZTK7hLfq9qT/QHXGVe/0= github.com/gobuffalo/packd v1.0.1/go.mod h1:PP2POP3p3RXGz7Jh6eYEf93S7vA2za6xM7QT85L4+VY= github.com/gobuffalo/packr/v2 v2.8.3 h1:xE1yzvnO56cUC0sTpKR3DIbxZgB54AftTFMhB2XEWlY= github.com/gobuffalo/packr/v2 v2.8.3/go.mod h1:0SahksCVcx4IMnigTjiFuyldmTrdTctXsOdiU5KwbKc= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godror/godror v0.24.2/go.mod h1:wZv/9vPiUib6tkoDl+AZ/QLf5YZgMravZ7jxH2eQWAE= github.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/wire v0.5.0 h1:I7ELFeVBr3yfPIcc8+MWvrjk+3VjbcSzoXm3JVa+jD8= github.com/google/wire v0.5.0/go.mod h1:ngWDr9Qvq3yZA10YrxfyGELY/AFWGVpy9c1LTRi1EoU= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/mux v1.6.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-hclog v0.9.1/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= github.com/hashicorp/go-hclog v1.1.0 h1:QsGcniKx5/LuX2eYoeL+Np3UKYPNaN7YKpTh29h8rbw= github.com/hashicorp/go-hclog v1.1.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxBjXVn/J/3+z5/0= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-msgpack v1.1.5 h1:9byZdVjKTe5mce63pRVNP1L7UAmdHOTEMGehn6KvJWs= github.com/hashicorp/go-msgpack v1.1.5/go.mod h1:gWVc3sv/wbDmR3rQsj1CAktEZzoz1YNK9NfGLXJ69/4= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/raft v1.3.7 h1:mnuQAuSMNRjAvFc9IYxnGxZJ9LBBZyheMR8Kv8Ve71M= github.com/hashicorp/raft v1.3.7/go.mod h1:4Ak7FSPnuvmb0GV6vgIAJ4vYT4bek9bb6Q+7HVbyzqM= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jinzhu/gorm v1.9.10 h1:HvrsqdhCW78xpJF67g1hMxS6eCToo9PZH4LDB8WKPac= github.com/jinzhu/gorm v1.9.10/go.mod h1:Kh6hTsSGffh4ui079FHrR5Gg+5D0hgihqDcsDN2BBJY= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.0.1 h1:HjfetcXq097iXP0uoPCdnM4Efp5/9MsM0/M+XOTeR3M= github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/karrick/godirwalk v1.16.1 h1:DynhcF+bztK8gooS0+NDJFrdNZjJ3gzVzC545UNA9iw= github.com/karrick/godirwalk v1.16.1/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.14.4 h1:eijASRJcobkVtSt81Olfh7JX43osYLwy5krOJo6YEu4= github.com/klauspost/compress v1.14.4/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kortschak/utter v1.0.1/go.mod h1:vSmSjbyrlKjjsL71193LmzBOKgwePk9DH6uFaWHIInc= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.10.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.4 h1:SO9z7FRPzA03QhHKJrH5BXA6HU1rS4V2nIVrrNC1iYk= github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/markbates/errx v1.1.0 h1:QDFeR+UP95dO12JgW+tgi2UVfo0V8YBHiUIOaeBPiEI= github.com/markbates/errx v1.1.0/go.mod h1:PLa46Oex9KNbVDZhKel8v1OT7hD5JZ2eI7AHhA0wswc= github.com/markbates/oncer v1.0.0 h1:E83IaVAHygyndzPimgUYJjbshhDTALZyXxvk9FOlQRY= github.com/markbates/oncer v1.0.0/go.mod h1:Z59JA581E9GP6w96jai+TGqafHPW+cPfRxz2aSZ0mcI= github.com/markbates/safe v1.0.1 h1:yjZkbvRM6IzKj9tlu/zMJLS0n/V351OZWRnF3QfaUxI= github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= github.com/matryer/moq v0.0.0-20200106131100-75d0ddfc0007/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-oci8 v0.1.1/go.mod h1:wjDx6Xm9q7dFtHJvIlrI99JytznLw5wQ4R+9mNXJwGI= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg= github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g= github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/cli v1.1.2/go.mod h1:6iaV0fGdElS6dPBx0EApTxHrcWvmJphyh2n8YBLPPZ4= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v0.0.0-20180203102830-a4e142e9c047/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nats-io/jwt/v2 v2.2.1-0.20220330180145-442af02fd36a h1:lem6QCvxR0Y28gth9P+wV2K/zYUUAkJ+55U8cpS0p5I= github.com/nats-io/jwt/v2 v2.2.1-0.20220330180145-442af02fd36a/go.mod h1:0tqz9Hlu6bCBFLWAASKhE5vUA4c24L9KPUUgvwumE/k= github.com/nats-io/nats-server/v2 v2.8.1 h1:WZ9m/d8rklkWo6opo3X927vXnuaE00VEEl5zXcpL6qw= github.com/nats-io/nats-server/v2 v2.8.1/go.mod h1:vIdpKz3OG+DCg4q/xVPdXHoztEyKDWRtykQ4N7hd7C4= github.com/nats-io/nats-streaming-server v0.24.5 h1:jB+GvMRqH6tTJIjmWEgcy7kaHtk081bc26u78U+JAqI= github.com/nats-io/nats-streaming-server v0.24.5/go.mod h1:wY5y2xJQxrYdSmKJplQk1zPjBiu7p2f/+p58/VokW1o= github.com/nats-io/nats.go v1.13.0/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w= github.com/nats-io/nats.go v1.14.0 h1:/QLCss4vQ6wvDpbqXucsVRDi13tFIR6kTdau+nXzKJw= github.com/nats-io/nats.go v1.14.0/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w= github.com/nats-io/nkeys v0.3.0 h1:cgM5tL53EvYRU+2YLXIK0G2mJtK12Ft9oeooSZMA2G8= github.com/nats-io/nkeys v0.3.0/go.mod h1:gvUNGjVcM2IPr5rCsRsC6Wb3Hr2CQAm08dsxtV6A5y4= github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/nats-io/stan.go v0.10.2 h1:gQLd05LhzmhFkHm3/qP/klYHfM/hys45GyHa1Uly/kI= github.com/nats-io/stan.go v0.10.2/go.mod h1:vo2ax8K2IxaR3JtEMLZRFKIdoK/3o1/PKueapB7ezX0= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml v1.9.3 h1:zeC5b1GviRUyKYd6OJPvBU/mcVDVoL1OhT17FCt5dSQ= github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/poy/onpar v0.0.0-20190519213022-ee068f8ea4d1 h1:oL4IBbcqwhhNWh31bjOX8C/OCy0zs9906d/VUru+bqg= github.com/poy/onpar v0.0.0-20190519213022-ee068f8ea4d1/go.mod h1:nSbFQvMj97ZyhFRSJYtut+msi4sOY6zJDGCdSc+/rZU= github.com/processout/grpc-go-pool v1.2.1 h1:hbp1BOA02CIxEAoRLHGpUhhPFv77nwfBLBeO3Ya9P7I= github.com/processout/grpc-go-pool v1.2.1/go.mod h1:F4hiNj96O6VQ87jv4rdz8R9tkHdelQQJ/J2B1a5VSt4= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/riandyrn/otelchi v0.4.0 h1:btWguNWE2NluzNqRNaqAdJ809GKP1CjZEi8UP4AdYGw= github.com/riandyrn/otelchi v0.4.0/go.mod h1:gYlFYJYyLUmgxgJFKE/NFno7ljcu2lCd8+aOlD8oLTw= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rubenv/sql-migrate v1.1.1 h1:haR5Hn8hbW9/SpAICrXoZqXnywS7Q5WijwkQENPeNWY= github.com/rubenv/sql-migrate v1.1.1/go.mod h1:/7TZymwxN8VWumcIxw1jjHEcR1djpdkMHQPT4FWdnbQ= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/selvatico/go-mocket v1.0.7 h1:jbVa7RkoOCzBanQYiYF+VWgySHZogg25fOIKkM38q5k= github.com/selvatico/go-mocket v1.0.7/go.mod h1:7bSWzuNieCdUlanCVu3w0ppS0LvDtPAZmKBIlhoTcp8= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/shurcooL/vfsgen v0.0.0-20180121065927-ffb13db8def0/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v1.2.1 h1:+KmjbUw1hriSNMF55oPrkZcb27aECyrj8V2ytv7kWDw= github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.8.1 h1:Kq1fyeebqsBfbjZj4EL7gj2IO0mMaiyjYUWcUsl2O44= github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= github.com/vektah/dataloaden v0.2.1-0.20190515034641-a19b9a6e7c9e/go.mod h1:/HUdMve7rvxZma+2ZELQeNh88+003LL7Pf/CZ089j8U= github.com/vektah/gqlparser v1.3.1 h1:8b0IcD3qZKWJQHSzynbDlrtP3IxVydZ2DZepCGofqfU= github.com/vektah/gqlparser v1.3.1/go.mod h1:bkVf0FX+Stjg/MHnm8mEyubuaArhNEqfQhF+OTiAL74= github.com/vektah/gqlparser/v2 v2.0.1 h1:xgl5abVnsd4hkN9rk65OJID9bfcLSMuTaTcZj777q1o= github.com/vektah/gqlparser/v2 v2.0.1/go.mod h1:SyUiHgLATUR8BiYURfTirrTcGpcE+4XkV2se04Px1Ms= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs= github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0= go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opentelemetry.io/contrib v1.0.0 h1:khwDCxdSspjOLmFnvMuSHd/5rPzbTx0+l6aURwtQdfE= go.opentelemetry.io/contrib v1.0.0/go.mod h1:EH4yDYeNoaTqn/8yCWQmfNB78VHfGX2Jt2bvnvzBlGM= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.32.0 h1:WenoaOMNP71oq3KkMZ/jnxI9xU/JSCLw8yZILSI2lfU= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.32.0/go.mod h1:J0dBVrt7dPS/lKJyQoW0xzQiUr4r2Ik1VwPjAUWnofI= go.opentelemetry.io/otel v1.3.0/go.mod h1:PWIKzi6JCp7sM0k9yZ43VX+T345uNbAkDKwHVjb2PTs= go.opentelemetry.io/otel v1.7.0 h1:Z2lA3Tdch0iDcrhJXDIlC94XE+bxok1F9B+4Lz/lGsM= go.opentelemetry.io/otel v1.7.0/go.mod h1:5BdUoMIz5WEs0vt0CUEMtSSaTSHBBVwrhnz7+nrD5xk= go.opentelemetry.io/otel/exporters/jaeger v1.7.0 h1:wXgjiRldljksZkZrldGVe6XrG9u3kYDyQmkZwmm5dI0= go.opentelemetry.io/otel/exporters/jaeger v1.7.0/go.mod h1:PwQAOqBgqbLQRKlj466DuD2qyMjbtcPpfPfj+AqbSBs= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.3.0/go.mod h1:PQLM+xJ3EMSZU9rMevmw+4nH1efyp23CW/nD9BlB3sg= go.opentelemetry.io/otel/sdk v1.3.0/go.mod h1:rIo4suHNhQwBIPg9axF8V9CA72Wz2mKF1teNrup8yzs= go.opentelemetry.io/otel/sdk v1.7.0 h1:4OmStpcKVOfvDOgCt7UriAPtKolwIhxpnSNI/yK+1B0= go.opentelemetry.io/otel/sdk v1.7.0/go.mod h1:uTEOTwaqIVuTGiJN7ii13Ibp75wJmYUDe374q6cZwUU= go.opentelemetry.io/otel/trace v1.3.0/go.mod h1:c/VDhno8888bvQYmbYLqe41/Ldmr/KKunbvWM4/fEjk= go.opentelemetry.io/otel/trace v1.7.0 h1:O37Iogk1lEkMRXewVtZ1BBTVn5JEp8GrJvP92bJqC6o= go.opentelemetry.io/otel/trace v1.7.0/go.mod h1:fzLSB9nqR2eXzxPXb2JW9IKE+ScyXA48yyE4TNvoHqU= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/automaxprocs v1.2.0 h1:+RUihKM+nmYUoB9w0D0Ov5TJ2PpFO2FgenTxMJiZBZA= go.uber.org/automaxprocs v1.2.0/go.mod h1:YfO3fm683kQpzETxlTGZhGIVmXAhaw3gxeBADbpZtnU= go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd h1:XcWmESyNjXJMLahc3mqVQJcgSTDxFxhETVlfk9uGc38= golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602 h1:0Ja1LBD+yisY6RWM/BH7TJVXWsSjs2VwBSmvSX4HdBc= golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220429233432-b5fbb4746d32 h1:Js08h5hqB5xyWR789+QqueR6sDE8mk+YvpETZ+F6X9Y= golang.org/x/sys v0.0.0-20220429233432-b5fbb4746d32/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11 h1:GZokNIeuVkl3aZHJchRrr13WCsols02MLUcz1U9is6M= golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190422233926-fe54fb35175b/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190424220101-1e8e1cfdf96b/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190515012406-7d7faa4812bd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200114235610-7ae403b6b589/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f h1:GGU+dLjvlC3qDwqYgL6UgRmHXhOOgns0bZu2Ty5mm6U= golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8 h1:XosVttQUxX8erNhEruTu053/VchgYuksoS9Bj/OITjU= google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.46.0 h1:oCjezcn6g6A75TGoKYBPgKmVBLexhYLM6MebdrPApP8= google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU= gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sourcegraph.com/sourcegraph/appdash v0.0.0-20180110180208-2cc67fd64755/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= sourcegraph.com/sourcegraph/appdash-data v0.0.0-20151005221446-73f23eafcf67/go.mod h1:L5q+DGLGOQFpo1snNEkLOJT2d1YTW66rWNzatr3He1k= ================================================ FILE: gqlgen.yml ================================================ schema: - "resources/graphql/*.graphql" exec: filename: generated/graphql/generated.go model: filename: generated/graphql/models_gen.go resolver: filename: app/graphql_resolver/resolver_gen.go type: Resolver models: Product: model: github.com/aristat/golang-example-app/app/db/domain.Product ProductItem: model: github.com/aristat/golang-example-app/app/db/domain.ProductItem UsersQuery: fields: one: resolver: true ProductsQuery: fields: list: resolver: true UsersMutation: fields: createUser: resolver: true ================================================ FILE: main.go ================================================ package main import "github.com/aristat/golang-example-app/cmd" func main() { cmd.Execute() } ================================================ FILE: prototool.yaml ================================================ protoc: version: 3.8.0 generate: go_options: import_path: github.com/aristat/golang-example-app plugins: - name: go-grpc type: go flags: paths=source_relative output: generated ================================================ FILE: resources/casbin/model.conf ================================================ [request_definition] r = sub, obj, act [policy_definition] p = sub, obj, act [role_definition] g = _, _ [policy_effect] e = some(where (p.eft == allow)) [matchers] m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act ================================================ FILE: resources/casbin/policy.csv ================================================ p, reader, users, read p, owner, users, write g, reader, anonymous g, owner, reader ================================================ FILE: resources/configs/development.yaml ================================================ session: redisUrl: localhost:6379 redisDB: 10 db: url: postgresql://localhost:5432/golang_example_development?sslmode=disable maxOpenConns: 5 maxIdleConns: 3 connMaxLifetime: 15m logLevel: 7 grpc: services: products: target: localhost:50051 maxConn: 10 initConn: 1 maxLifeDuration: 5m idleTimeout: 1s clientParameters: time: 5m timeout: 10s permitWithoutStream: false auth: services: test-service: 1 relativePath: keys/local logger: debug: true graphql: introspection: true graphql_resolver: productTimeout: 5 tracing: jaeger: agentHost: localhost agentPort: 6831 serviceName: golang-example-app-server products: natsUrl: http://localhost:4222 subject: products services: productService: port: 50051 healthCheckUrl: localhost:50052 natsUrl: http://localhost:4222 subject: products healthCheckService: port: 50052 randomDisable: true ================================================ FILE: resources/configs/docker_development.yaml ================================================ session: redisUrl: redis:6379 redisDB: 10 db: url: postgres://postgres@postgres:5432/golang_example_development?sslmode=disable maxOpenConns: 5 maxIdleConns: 3 connMaxLifetime: 15m logLevel: 7 grpc: services: products: target: product_service:50051 maxConn: 10 initConn: 1 maxLifeDuration: 5m idleTimeout: 1s clientParameters: time: 5m timeout: 10s permitWithoutStream: false auth: services: test-service: 1 relativePath: keys/local logger: debug: true graphql: introspection: true graphql_resolver: productTimeout: 5 tracing: jaeger: agentHost: jaeger agentPort: 6831 serviceName: golang-example-app-server products: natsUrl: nats-streaming:4222 subject: products services: productService: port: 50051 healthCheckUrl: health_check_service:50052 natsUrl: nats-streaming:4222 subject: products healthCheckService: port: 50052 randomDisable: true ================================================ FILE: resources/graphql/products.graphql ================================================ type ProductsQuery { list: ProductsListOut! } type Product { id: ID! name: String! productItems: [ProductItem!]! } type ProductItem { id: ID! name: String! } type ProductsListOut { products: [Product!]! } ================================================ FILE: resources/graphql/root.graphql ================================================ type Query { users: UsersQuery products: ProductsQuery } type Mutation { users: UsersMutation } ================================================ FILE: resources/graphql/user.graphql ================================================ type UsersOneOut { id: ID! email: String! } type UsersQuery { one(email: String!): UsersOneOut! @hasUsersPermission(permission: READ) } type UsersMutation { createUser(email: String!, password: String!): UsersCreateOut! @hasUsersPermission(permission: WRITE) } type UsersCreateOut { status: UsersCreateOutStatus! id: ID! email: String! } enum UsersCreateOutStatus { OK BAD_REQUEST SERVER_INTERNAL_ERROR } directive @hasUsersPermission(permission: UsersPermissionEnum!) on FIELD_DEFINITION enum UsersPermissionEnum { READ WRITE } ================================================ FILE: resources/keys/local/private_key.pem ================================================ -----BEGIN RSA PRIVATE KEY----- MIIEpQIBAAKCAQEA0yucnZD57YJ5bPjdZfltW1sObqjT89R6fiHJRkwtA29COZro H+I2ZNtXJ6Y5zOuE4DVgeCRIt5/Dk3XO24VClIewK30+hhKxEAHrVYivKiB7AXLg vL/CbQp0SSIu/qtJE0NkhEQEVPXRFsQzi1nv/uYOjWOcS66YzYyCV+V/Q885f9vY bnJ+pRoulvjTZIneeiGG58l68cRE3Cky3WnXP5q/BsMucPz52uSnaaMHybTKGVG1 zbDIvRogOg/FHatA04K1fLlq3YKo2gDTRpMNuVWk4D3PGXqf3TTM6XmJdlulgbzn Me2p/EUuOaM1B3g6XyeTT8/3eBzgUjK9x0HALwIDAQABAoIBABGeZebPncqvRCpP aUmE0hb5Ne8NrwF9DOtRLlXrLSZINiJQRmXCnf80PcVVHSV30RJT4cSkYlzPu6Wm AqhWKgPyfkRiosDU9mj7gAMW8GZ3Z0vrpcyZw0MNyD4B2CHvcJ1m1hAjDKl6CQP5 QsOxsVB3KWeqk/PMkXs06fsjbsbdcHIflDxstAdHxh1Jjt+R/eOPGKRjkjr+XyIR 5LLp6eg4D0i2fuh1uo08q3Ok654kAJmKQaDyD9FYqFcYw2jYkJPtwSehoTtfDv2L 14MwDAJ3vfNHy7zV6PM80sw3lKH7752wK83FmPW2Irkt/UuDxOjs4g/g4uQnRP3w 8o61J8ECgYEA984X1FLMQ7/iljd3eas1wOxky86Q/7NOBJy61NhYVWhrwswIoHVQ xyRVZBMAez0HQL4/YFkRpe/BQD9ABXIRUkauzOdNMs1F8GPE1Y50g8EkjtUwJ5Ke rn9T6UBxitjfe8mgCSVWRl4tlmNLaYetY3PPJsLkxinBg/F7NHnePgcCgYEA2ide 91+Vup2AYOQb14R6QCBTGbHWOoPpUsRYg5+h2uHEE5onYIZpM4K4zheBz6L7IDlq k9qy83M/U7mW410iwrSbfTZYg9yJZClSCh/jZhU6/e5Rrg0+LT1lwbcnCrbtYyKu HsEOLbc6l66bqJimTT4JEYA7xuMi8EP5PsjQYpkCgYEA7ILBb57O4mLECodJ+tAT 79wvn+25qrMh5XkJQJh0Rp/xKey+1xbhUBA3h9oy/WyT/ZEWwAiCtZONKJq1qfzi 11oq/9pLbg9Jj1RJy2G5hv7Su5hx63MfDIDuP5OISvMO6gDYQ6JlI6hDbmO62C/s px0jO2WMIC4+SoYyBzXBjgUCgYEAvZp6b4YkHI3Hhm67xBTgK9vsXeiyySjdIZKF W+DiS9rtEBxrHPm1dY+oD3de25hLqzY760WpQu5nm90xx2qrS46tlaYmSHTk9Kj1 JNeSTKcnHoyDcUMRR0CVsEf/JtDWgdMigphIOnOF+U9I+r+xynCgcRWC3tmLBEgP 2QGwHAECgYEA9nTzfqm9Vjdyn6zjbkp9zr/j+r9KLPeEiXQKlAuPyg+zXrYzneIE Fyqi2WMep+Q8oY1kCwPmHz72WrP/NCXPwjBVYZsGA4vCDLVm/g6A8yoTQV/Cb89s pKNKfj4Tj1K1QIxO6yLbBb1SynOCxkLFyg9Xdt/jgW0cxpREQM6XMTE= -----END RSA PRIVATE KEY----- ================================================ FILE: resources/keys/local/public_key.pem ================================================ -----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0yucnZD57YJ5bPjdZflt W1sObqjT89R6fiHJRkwtA29COZroH+I2ZNtXJ6Y5zOuE4DVgeCRIt5/Dk3XO24VC lIewK30+hhKxEAHrVYivKiB7AXLgvL/CbQp0SSIu/qtJE0NkhEQEVPXRFsQzi1nv /uYOjWOcS66YzYyCV+V/Q885f9vYbnJ+pRoulvjTZIneeiGG58l68cRE3Cky3WnX P5q/BsMucPz52uSnaaMHybTKGVG1zbDIvRogOg/FHatA04K1fLlq3YKo2gDTRpMN uVWk4D3PGXqf3TTM6XmJdlulgbznMe2p/EUuOaM1B3g6XyeTT8/3eBzgUjK9x0HA LwIDAQAB -----END PUBLIC KEY----- ================================================ FILE: resources/migrations/20181215164636-create_users.sql ================================================ -- +migrate Up CREATE TABLE users( id SERIAL PRIMARY KEY, email VARCHAR(255) NOT NULL DEFAULT '', encrypted_password VARCHAR(255) NOT NULL DEFAULT '' ); CREATE UNIQUE INDEX users_email ON users USING btree (email); -- +migrate Down ================================================ FILE: resources/migrations/20181216210607-records.sql ================================================ -- +migrate Up -- password: 123456789 INSERT INTO users (email, encrypted_password) VALUES ('test@gmail.com', '$2a$10$bRGA2ckqEhydPBjA8jpDzehoAAhlmc95nGEB5WaZmxOz/EyUnE9l6'); -- +migrate Down DELETE FROM users WHERE email = 'test@gmail.com'; ================================================ FILE: resources/proto/health_checks/health_checks.proto ================================================ syntax = "proto3"; package health_checks; import "google/protobuf/empty.proto"; option go_package="github.com/aristat/golang-example-app/health_checks"; service HealthChecks { rpc IsAlive (google.protobuf.Empty) returns (IsAliveOut) { } } message IsAliveOut { enum Status { OK = 0; NOT_OK = 2; } Status status = 1; } ================================================ FILE: resources/proto/products/products.proto ================================================ syntax = "proto3"; package products; option go_package="github.com/aristat/golang-example-app/products"; message Product { int64 id = 1; string name = 2; } service Products { rpc ListProduct (ListProductIn) returns (ListProductOut) { } } message ListProductIn { int64 id = 1; } message ListProductOut { enum Status { OK = 0; NOT_FOUND = 2; } Status status = 1; repeated Product products = 2; } ================================================ FILE: resources/templates/helpers/errors.html ================================================ {{ define "errors" }} {{if .errors }} {{range .errors}}