├── .editorconfig ├── .gitignore ├── Dockerfile ├── LICENSE ├── README.md ├── docker-compose.yaml ├── frontend ├── .gitignore ├── .prettierrc ├── babel.config.js ├── package-lock.json ├── package.json ├── public │ ├── favicon.ico │ └── index.html ├── src │ ├── App.vue │ ├── auth.js │ ├── components │ │ ├── Home.vue │ │ ├── Login.vue │ │ ├── Message.vue │ │ ├── MessageForm.vue │ │ ├── MessageList.vue │ │ └── UserList.vue │ ├── main.js │ └── router.js └── vue.config.js ├── go.mod ├── go.sum ├── main.go ├── server ├── generated.go ├── graphql.go ├── models_gen.go └── schema.graphql └── vendor ├── github.com ├── 99designs │ └── gqlgen │ │ ├── LICENSE │ │ ├── complexity │ │ └── complexity.go │ │ ├── graphql │ │ ├── any.go │ │ ├── bool.go │ │ ├── context.go │ │ ├── error.go │ │ ├── exec.go │ │ ├── fieldset.go │ │ ├── float.go │ │ ├── id.go │ │ ├── int.go │ │ ├── introspection │ │ │ ├── introspection.go │ │ │ ├── query.go │ │ │ ├── schema.go │ │ │ └── type.go │ │ ├── jsonw.go │ │ ├── map.go │ │ ├── oneshot.go │ │ ├── recovery.go │ │ ├── response.go │ │ ├── root.go │ │ ├── string.go │ │ ├── time.go │ │ ├── tracer.go │ │ ├── upload.go │ │ └── version.go │ │ └── handler │ │ ├── context.go │ │ ├── graphql.go │ │ ├── mock.go │ │ ├── playground.go │ │ ├── stub.go │ │ └── websocket.go ├── agnivade │ └── levenshtein │ │ ├── .gitignore │ │ ├── .travis.yml │ │ ├── License.txt │ │ ├── Makefile │ │ ├── README.md │ │ ├── go.mod │ │ └── levenshtein.go ├── go-redis │ └── redis │ │ ├── .gitignore │ │ ├── .travis.yml │ │ ├── CHANGELOG.md │ │ ├── LICENSE │ │ ├── Makefile │ │ ├── README.md │ │ ├── cluster.go │ │ ├── cluster_commands.go │ │ ├── command.go │ │ ├── commands.go │ │ ├── doc.go │ │ ├── internal │ │ ├── consistenthash │ │ │ └── consistenthash.go │ │ ├── error.go │ │ ├── hashtag │ │ │ └── hashtag.go │ │ ├── internal.go │ │ ├── log.go │ │ ├── once.go │ │ ├── pool │ │ │ ├── conn.go │ │ │ ├── pool.go │ │ │ ├── pool_single.go │ │ │ └── pool_sticky.go │ │ ├── proto │ │ │ ├── reader.go │ │ │ ├── scan.go │ │ │ └── writer.go │ │ ├── util.go │ │ └── util │ │ │ ├── safe.go │ │ │ ├── strconv.go │ │ │ └── unsafe.go │ │ ├── iterator.go │ │ ├── options.go │ │ ├── pipeline.go │ │ ├── pubsub.go │ │ ├── redis.go │ │ ├── result.go │ │ ├── ring.go │ │ ├── script.go │ │ ├── sentinel.go │ │ ├── tx.go │ │ └── universal.go ├── gorilla │ └── websocket │ │ ├── .gitignore │ │ ├── AUTHORS │ │ ├── LICENSE │ │ ├── README.md │ │ ├── client.go │ │ ├── client_clone.go │ │ ├── client_clone_legacy.go │ │ ├── compression.go │ │ ├── conn.go │ │ ├── conn_write.go │ │ ├── conn_write_legacy.go │ │ ├── doc.go │ │ ├── go.mod │ │ ├── go.sum │ │ ├── join.go │ │ ├── json.go │ │ ├── mask.go │ │ ├── mask_safe.go │ │ ├── prepared.go │ │ ├── proxy.go │ │ ├── server.go │ │ ├── trace.go │ │ ├── trace_17.go │ │ ├── util.go │ │ └── x_net_proxy.go ├── hashicorp │ └── golang-lru │ │ ├── .gitignore │ │ ├── 2q.go │ │ ├── LICENSE │ │ ├── README.md │ │ ├── arc.go │ │ ├── doc.go │ │ ├── go.mod │ │ ├── lru.go │ │ └── simplelru │ │ ├── lru.go │ │ └── lru_interface.go ├── kelseyhightower │ └── envconfig │ │ ├── .travis.yml │ │ ├── LICENSE │ │ ├── MAINTAINERS │ │ ├── README.md │ │ ├── doc.go │ │ ├── env_os.go │ │ ├── env_syscall.go │ │ ├── envconfig.go │ │ ├── go.mod │ │ └── usage.go ├── rs │ └── cors │ │ ├── .travis.yml │ │ ├── LICENSE │ │ ├── README.md │ │ ├── cors.go │ │ ├── go.mod │ │ └── utils.go ├── segmentio │ └── ksuid │ │ ├── .gitignore │ │ ├── LICENSE.md │ │ ├── README.md │ │ ├── base62.go │ │ ├── ksuid.go │ │ ├── rand.go │ │ ├── sequence.go │ │ ├── set.go │ │ └── uint128.go ├── tinrab │ └── retry │ │ ├── .editorconfig │ │ ├── .gitignore │ │ ├── LICENSE │ │ ├── README.md │ │ └── retry.go └── vektah │ └── gqlparser │ ├── .gitignore │ ├── LICENSE │ ├── ast │ ├── argmap.go │ ├── collections.go │ ├── definition.go │ ├── directive.go │ ├── document.go │ ├── dumper.go │ ├── fragment.go │ ├── operation.go │ ├── selection.go │ ├── source.go │ ├── type.go │ └── value.go │ ├── go.mod │ ├── go.sum │ ├── gqlerror │ └── error.go │ ├── gqlparser.go │ ├── lexer │ ├── blockstring.go │ ├── lexer.go │ ├── lexer_test.yml │ └── token.go │ ├── parser │ ├── parser.go │ ├── query.go │ ├── query_test.yml │ ├── schema.go │ └── schema_test.yml │ ├── readme.md │ └── validator │ ├── error.go │ ├── messaging.go │ ├── prelude.go │ ├── prelude.graphql │ ├── rules │ ├── fields_on_correct_type.go │ ├── fragments_on_composite_types.go │ ├── known_argument_names.go │ ├── known_directives.go │ ├── known_fragment_names.go │ ├── known_type_names.go │ ├── lone_anonymous_operation.go │ ├── no_fragment_cycles.go │ ├── no_undefined_variables.go │ ├── no_unused_fragments.go │ ├── no_unused_variables.go │ ├── overlapping_fields_can_be_merged.go │ ├── possible_fragment_spreads.go │ ├── provided_required_arguments.go │ ├── scalar_leafs.go │ ├── single_field_subscriptions.go │ ├── unique_argument_names.go │ ├── unique_directives_per_location.go │ ├── unique_fragment_names.go │ ├── unique_input_field_names.go │ ├── unique_operation_names.go │ ├── unique_variable_names.go │ ├── values_of_correct_type.go │ ├── variables_are_input_types.go │ └── variables_in_allowed_position.go │ ├── schema.go │ ├── schema_test.yml │ ├── suggestionList.go │ ├── validator.go │ ├── vars.go │ └── walk.go └── modules.txt /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.go] 12 | indent_style = tab 13 | indent_size = 4 14 | 15 | [*.md] 16 | trim_trailing_whitespace = false 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.13-alpine3.11 AS build 2 | RUN apk --no-cache add clang gcc g++ make git ca-certificates 3 | 4 | WORKDIR /go/src/github.com/tinrab/graphql-realtime-chat 5 | COPY go.mod go.sum vendor main.go ./ 6 | COPY server server 7 | RUN go build -o /go/bin/app . 8 | 9 | FROM alpine:3.11 10 | WORKDIR /usr/bin 11 | COPY --from=build /go/bin . 12 | EXPOSE 8080 13 | CMD ["app"] 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Tin Rabzelj 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Real-time Chat with GraphQL Subscriptions in Go 2 | 3 | Underlying source code for the article [Real-time Chat with GraphQL Subscriptions in Go](https://outcrawl.com/go-graphql-realtime-chat). 4 | 5 | ## Running 6 | 7 | Run server: 8 | 9 | ``` 10 | $ docker-compose up -d --build 11 | ``` 12 | 13 | Run Vue app: 14 | 15 | ``` 16 | $ cd frontend 17 | $ npm run start 18 | ``` 19 | -------------------------------------------------------------------------------- /docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: "3.7" 2 | 3 | services: 4 | app: 5 | build: . 6 | environment: 7 | REDIS_URL: redis:6379 8 | ports: 9 | - 8080:8080 10 | redis: 11 | image: redis:5.0.7 12 | -------------------------------------------------------------------------------- /frontend/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | # local env files 6 | .env.local 7 | .env.*.local 8 | 9 | # Log files 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | 14 | # Editor directories and files 15 | .idea 16 | .vscode 17 | *.suo 18 | *.ntvs* 19 | *.njsproj 20 | *.sln 21 | *.sw* 22 | -------------------------------------------------------------------------------- /frontend/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 120, 3 | "arrowParens": "always", 4 | "trailingComma": "all", 5 | "singleQuote": true, 6 | "overrides": [ 7 | { 8 | "files": ["*.scss", "*.css"], 9 | "options": { 10 | "singleQuote": false 11 | } 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /frontend/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['@vue/app'], 3 | }; 4 | -------------------------------------------------------------------------------- /frontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "frontend", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "vue-cli-service serve", 7 | "build": "vue-cli-service build" 8 | }, 9 | "dependencies": { 10 | "apollo-cache-inmemory": "^1.6.5", 11 | "apollo-client": "^2.6.8", 12 | "apollo-link": "^1.2.13", 13 | "apollo-link-http": "^1.5.16", 14 | "apollo-link-ws": "^1.0.19", 15 | "apollo-utilities": "^1.3.3", 16 | "axios": "^1.6.0", 17 | "bootstrap": "^4.4.1", 18 | "graphql": "^14.5.8", 19 | "graphql-tag": "^2.10.1", 20 | "subscriptions-transport-ws": "^0.9.16", 21 | "vue": "^2.6.11", 22 | "vue-apollo": "^3.1.0", 23 | "vue-router": "^3.1.5", 24 | "vuex": "^3.1.2" 25 | }, 26 | "devDependencies": { 27 | "@vue/cli-plugin-babel": "^5.0.8", 28 | "@vue/cli-service": "^5.0.8", 29 | "node-sass": "^9.0.0", 30 | "sass-loader": "^8.0.2", 31 | "vue-template-compiler": "^2.6.11" 32 | }, 33 | "postcss": { 34 | "plugins": { 35 | "autoprefixer": {} 36 | } 37 | }, 38 | "browserslist": [ 39 | "> 1%", 40 | "last 2 versions", 41 | "not ie <= 8" 42 | ] 43 | } 44 | -------------------------------------------------------------------------------- /frontend/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinrab/graphql-realtime-chat/78b4d841d9ab8bdf3045b0439e21c187982f2c2c/frontend/public/favicon.ico -------------------------------------------------------------------------------- /frontend/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | frontend 9 | 10 | 11 | 15 |
16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /frontend/src/App.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 11 | -------------------------------------------------------------------------------- /frontend/src/auth.js: -------------------------------------------------------------------------------- 1 | const AuthPlugin = { 2 | install(Vue, options) { 3 | Vue.prototype.$setCurrentUser = function (user) { 4 | Vue.prototype.user = user; 5 | }; 6 | Vue.prototype.$currentUser = function () { 7 | return Vue.prototype.user; 8 | }; 9 | }, 10 | }; 11 | 12 | export { AuthPlugin }; 13 | -------------------------------------------------------------------------------- /frontend/src/components/Home.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 38 | -------------------------------------------------------------------------------- /frontend/src/components/Login.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 45 | 46 | 52 | -------------------------------------------------------------------------------- /frontend/src/components/Message.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 16 | -------------------------------------------------------------------------------- /frontend/src/components/MessageForm.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 57 | -------------------------------------------------------------------------------- /frontend/src/components/MessageList.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 67 | -------------------------------------------------------------------------------- /frontend/src/components/UserList.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 54 | -------------------------------------------------------------------------------- /frontend/src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import { ApolloClient } from 'apollo-client'; 3 | import { HttpLink } from 'apollo-link-http'; 4 | import { InMemoryCache } from 'apollo-cache-inmemory'; 5 | import VueApollo from 'vue-apollo'; 6 | import { split } from 'apollo-link'; 7 | import { WebSocketLink } from 'apollo-link-ws'; 8 | import { getMainDefinition } from 'apollo-utilities'; 9 | import 'bootstrap/scss/bootstrap.scss'; 10 | 11 | import router from './router'; 12 | import App from './App.vue'; 13 | import { AuthPlugin } from './auth'; 14 | 15 | Vue.config.productionTip = false; 16 | 17 | const httpLink = new HttpLink({ 18 | uri: 'http://localhost:8080/graphql', 19 | }); 20 | const wsLink = new WebSocketLink({ 21 | uri: 'ws://localhost:8080/graphql', 22 | options: { 23 | reconnect: true, 24 | }, 25 | }); 26 | const link = split( 27 | ({ query }) => { 28 | const { kind, operation } = getMainDefinition(query); 29 | return kind === 'OperationDefinition' && operation === 'subscription'; 30 | }, 31 | wsLink, 32 | httpLink, 33 | ); 34 | const apolloClient = new ApolloClient({ 35 | link: link, 36 | cache: new InMemoryCache(), 37 | }); 38 | const apolloProvider = new VueApollo({ 39 | defaultClient: apolloClient, 40 | }); 41 | 42 | Vue.use(VueApollo); 43 | Vue.use(AuthPlugin); 44 | 45 | const vm = new Vue({ 46 | router, 47 | provide: apolloProvider.provide(), 48 | render: (h) => h(App), 49 | }); 50 | vm.$mount('#app'); 51 | -------------------------------------------------------------------------------- /frontend/src/router.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import Router from 'vue-router'; 3 | 4 | import Home from '@/components/Home.vue'; 5 | import Login from '@/components/Login.vue'; 6 | 7 | Vue.use(Router); 8 | 9 | export default new Router({ 10 | routes: [ 11 | { 12 | path: '/', 13 | name: 'home', 14 | component: Home, 15 | }, 16 | { 17 | path: '/login', 18 | name: 'login', 19 | component: Login, 20 | }, 21 | ], 22 | }); 23 | -------------------------------------------------------------------------------- /frontend/vue.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | devServer: { 3 | port: 3000, 4 | }, 5 | }; 6 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/tinrab/graphql-realtime-chat 2 | 3 | go 1.13 4 | 5 | require ( 6 | github.com/99designs/gqlgen v0.10.2 7 | github.com/go-redis/redis v6.15.6+incompatible 8 | github.com/gorilla/websocket v1.4.1 9 | github.com/kelseyhightower/envconfig v1.4.0 10 | github.com/onsi/ginkgo v1.11.0 // indirect 11 | github.com/onsi/gomega v1.8.1 // indirect 12 | github.com/rs/cors v1.7.0 13 | github.com/segmentio/ksuid v1.0.2 14 | github.com/tinrab/retry v1.0.0 15 | github.com/vektah/gqlparser v1.2.0 16 | ) 17 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | 6 | "github.com/kelseyhightower/envconfig" 7 | "github.com/tinrab/graphql-realtime-chat/server" 8 | ) 9 | 10 | type config struct { 11 | RedisURL string `envconfig:"REDIS_URL"` 12 | } 13 | 14 | func main() { 15 | var cfg config 16 | err := envconfig.Process("", &cfg) 17 | if err != nil { 18 | log.Fatal(err) 19 | } 20 | 21 | s, err := server.NewGraphQLServer(cfg.RedisURL) 22 | if err != nil { 23 | log.Fatal(err) 24 | } 25 | 26 | err = s.Serve("/graphql", 8080) 27 | if err != nil { 28 | log.Fatal(err) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /server/models_gen.go: -------------------------------------------------------------------------------- 1 | // Code generated by github.com/99designs/gqlgen, DO NOT EDIT. 2 | 3 | package server 4 | 5 | import ( 6 | "time" 7 | ) 8 | 9 | type Message struct { 10 | ID string `json:"id"` 11 | User string `json:"user"` 12 | CreatedAt time.Time `json:"createdAt"` 13 | Text string `json:"text"` 14 | } 15 | -------------------------------------------------------------------------------- /server/schema.graphql: -------------------------------------------------------------------------------- 1 | scalar Time 2 | 3 | type Message { 4 | id: String! 5 | user: String! 6 | createdAt: Time! 7 | text: String! 8 | } 9 | 10 | type Mutation { 11 | postMessage(user: String!, text: String!): Message 12 | } 13 | 14 | type Query { 15 | messages: [Message!]! 16 | users: [String!]! 17 | } 18 | 19 | type Subscription { 20 | messagePosted(user: String!): Message! 21 | userJoined(user: String!): String! 22 | } 23 | -------------------------------------------------------------------------------- /vendor/github.com/99designs/gqlgen/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 Adam Scarr 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /vendor/github.com/99designs/gqlgen/complexity/complexity.go: -------------------------------------------------------------------------------- 1 | package complexity 2 | 3 | import ( 4 | "github.com/99designs/gqlgen/graphql" 5 | "github.com/vektah/gqlparser/ast" 6 | ) 7 | 8 | func Calculate(es graphql.ExecutableSchema, op *ast.OperationDefinition, vars map[string]interface{}) int { 9 | walker := complexityWalker{ 10 | es: es, 11 | schema: es.Schema(), 12 | vars: vars, 13 | } 14 | return walker.selectionSetComplexity(op.SelectionSet) 15 | } 16 | 17 | type complexityWalker struct { 18 | es graphql.ExecutableSchema 19 | schema *ast.Schema 20 | vars map[string]interface{} 21 | } 22 | 23 | func (cw complexityWalker) selectionSetComplexity(selectionSet ast.SelectionSet) int { 24 | var complexity int 25 | for _, selection := range selectionSet { 26 | switch s := selection.(type) { 27 | case *ast.Field: 28 | fieldDefinition := cw.schema.Types[s.Definition.Type.Name()] 29 | var childComplexity int 30 | switch fieldDefinition.Kind { 31 | case ast.Object, ast.Interface, ast.Union: 32 | childComplexity = cw.selectionSetComplexity(s.SelectionSet) 33 | } 34 | 35 | args := s.ArgumentMap(cw.vars) 36 | var fieldComplexity int 37 | if s.ObjectDefinition.Kind == ast.Interface { 38 | fieldComplexity = cw.interfaceFieldComplexity(s.ObjectDefinition, s.Name, childComplexity, args) 39 | } else { 40 | fieldComplexity = cw.fieldComplexity(s.ObjectDefinition.Name, s.Name, childComplexity, args) 41 | } 42 | complexity = safeAdd(complexity, fieldComplexity) 43 | 44 | case *ast.FragmentSpread: 45 | complexity = safeAdd(complexity, cw.selectionSetComplexity(s.Definition.SelectionSet)) 46 | 47 | case *ast.InlineFragment: 48 | complexity = safeAdd(complexity, cw.selectionSetComplexity(s.SelectionSet)) 49 | } 50 | } 51 | return complexity 52 | } 53 | 54 | func (cw complexityWalker) interfaceFieldComplexity(def *ast.Definition, field string, childComplexity int, args map[string]interface{}) int { 55 | // Interfaces don't have their own separate field costs, so they have to assume the worst case. 56 | // We iterate over all implementors and choose the most expensive one. 57 | maxComplexity := 0 58 | implementors := cw.schema.GetPossibleTypes(def) 59 | for _, t := range implementors { 60 | fieldComplexity := cw.fieldComplexity(t.Name, field, childComplexity, args) 61 | if fieldComplexity > maxComplexity { 62 | maxComplexity = fieldComplexity 63 | } 64 | } 65 | return maxComplexity 66 | } 67 | 68 | func (cw complexityWalker) fieldComplexity(object, field string, childComplexity int, args map[string]interface{}) int { 69 | if customComplexity, ok := cw.es.Complexity(object, field, childComplexity, args); ok && customComplexity >= childComplexity { 70 | return customComplexity 71 | } 72 | // default complexity calculation 73 | return safeAdd(1, childComplexity) 74 | } 75 | 76 | const maxInt = int(^uint(0) >> 1) 77 | 78 | // safeAdd is a saturating add of a and b that ignores negative operands. 79 | // If a + b would overflow through normal Go addition, 80 | // it returns the maximum integer value instead. 81 | // 82 | // Adding complexities with this function prevents attackers from intentionally 83 | // overflowing the complexity calculation to allow overly-complex queries. 84 | // 85 | // It also helps mitigate the impact of custom complexities that accidentally 86 | // return negative values. 87 | func safeAdd(a, b int) int { 88 | // Ignore negative operands. 89 | if a < 0 { 90 | if b < 0 { 91 | return 1 92 | } 93 | return b 94 | } else if b < 0 { 95 | return a 96 | } 97 | 98 | c := a + b 99 | if c < a { 100 | // Set c to maximum integer instead of overflowing. 101 | c = maxInt 102 | } 103 | return c 104 | } 105 | -------------------------------------------------------------------------------- /vendor/github.com/99designs/gqlgen/graphql/any.go: -------------------------------------------------------------------------------- 1 | package graphql 2 | 3 | import ( 4 | "encoding/json" 5 | "io" 6 | ) 7 | 8 | func MarshalAny(v interface{}) Marshaler { 9 | return WriterFunc(func(w io.Writer) { 10 | err := json.NewEncoder(w).Encode(v) 11 | if err != nil { 12 | panic(err) 13 | } 14 | }) 15 | } 16 | 17 | func UnmarshalAny(v interface{}) (interface{}, error) { 18 | return v, nil 19 | } 20 | -------------------------------------------------------------------------------- /vendor/github.com/99designs/gqlgen/graphql/bool.go: -------------------------------------------------------------------------------- 1 | package graphql 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "strings" 7 | ) 8 | 9 | func MarshalBoolean(b bool) Marshaler { 10 | return WriterFunc(func(w io.Writer) { 11 | if b { 12 | w.Write(trueLit) 13 | } else { 14 | w.Write(falseLit) 15 | } 16 | }) 17 | } 18 | 19 | func UnmarshalBoolean(v interface{}) (bool, error) { 20 | switch v := v.(type) { 21 | case string: 22 | return strings.ToLower(v) == "true", nil 23 | case int: 24 | return v != 0, nil 25 | case bool: 26 | return v, nil 27 | default: 28 | return false, fmt.Errorf("%T is not a bool", v) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /vendor/github.com/99designs/gqlgen/graphql/error.go: -------------------------------------------------------------------------------- 1 | package graphql 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/vektah/gqlparser/gqlerror" 7 | ) 8 | 9 | type ErrorPresenterFunc func(context.Context, error) *gqlerror.Error 10 | 11 | type ExtendedError interface { 12 | Extensions() map[string]interface{} 13 | } 14 | 15 | func DefaultErrorPresenter(ctx context.Context, err error) *gqlerror.Error { 16 | if gqlerr, ok := err.(*gqlerror.Error); ok { 17 | if gqlerr.Path == nil { 18 | gqlerr.Path = GetResolverContext(ctx).Path() 19 | } 20 | return gqlerr 21 | } 22 | 23 | var extensions map[string]interface{} 24 | if ee, ok := err.(ExtendedError); ok { 25 | extensions = ee.Extensions() 26 | } 27 | 28 | return &gqlerror.Error{ 29 | Message: err.Error(), 30 | Path: GetResolverContext(ctx).Path(), 31 | Extensions: extensions, 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /vendor/github.com/99designs/gqlgen/graphql/fieldset.go: -------------------------------------------------------------------------------- 1 | package graphql 2 | 3 | import ( 4 | "io" 5 | "sync" 6 | ) 7 | 8 | type FieldSet struct { 9 | fields []CollectedField 10 | Values []Marshaler 11 | delayed []delayedResult 12 | } 13 | 14 | type delayedResult struct { 15 | i int 16 | f func() Marshaler 17 | } 18 | 19 | func NewFieldSet(fields []CollectedField) *FieldSet { 20 | return &FieldSet{ 21 | fields: fields, 22 | Values: make([]Marshaler, len(fields)), 23 | } 24 | } 25 | 26 | func (m *FieldSet) Concurrently(i int, f func() Marshaler) { 27 | m.delayed = append(m.delayed, delayedResult{i: i, f: f}) 28 | } 29 | 30 | func (m *FieldSet) Dispatch() { 31 | if len(m.delayed) == 1 { 32 | // only one concurrent task, no need to spawn a goroutine or deal create waitgroups 33 | d := m.delayed[0] 34 | m.Values[d.i] = d.f() 35 | } else if len(m.delayed) > 1 { 36 | // more than one concurrent task, use the main goroutine to do one, only spawn goroutines for the others 37 | 38 | var wg sync.WaitGroup 39 | for _, d := range m.delayed[1:] { 40 | wg.Add(1) 41 | go func(d delayedResult) { 42 | m.Values[d.i] = d.f() 43 | wg.Done() 44 | }(d) 45 | } 46 | 47 | m.Values[m.delayed[0].i] = m.delayed[0].f() 48 | wg.Wait() 49 | } 50 | } 51 | 52 | func (m *FieldSet) MarshalGQL(writer io.Writer) { 53 | writer.Write(openBrace) 54 | for i, field := range m.fields { 55 | if i != 0 { 56 | writer.Write(comma) 57 | } 58 | writeQuotedString(writer, field.Alias) 59 | writer.Write(colon) 60 | m.Values[i].MarshalGQL(writer) 61 | } 62 | writer.Write(closeBrace) 63 | } 64 | -------------------------------------------------------------------------------- /vendor/github.com/99designs/gqlgen/graphql/float.go: -------------------------------------------------------------------------------- 1 | package graphql 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io" 7 | "strconv" 8 | ) 9 | 10 | func MarshalFloat(f float64) Marshaler { 11 | return WriterFunc(func(w io.Writer) { 12 | io.WriteString(w, fmt.Sprintf("%g", f)) 13 | }) 14 | } 15 | 16 | func UnmarshalFloat(v interface{}) (float64, error) { 17 | switch v := v.(type) { 18 | case string: 19 | return strconv.ParseFloat(v, 64) 20 | case int: 21 | return float64(v), nil 22 | case int64: 23 | return float64(v), nil 24 | case float64: 25 | return v, nil 26 | case json.Number: 27 | return strconv.ParseFloat(string(v), 64) 28 | default: 29 | return 0, fmt.Errorf("%T is not an float", v) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /vendor/github.com/99designs/gqlgen/graphql/id.go: -------------------------------------------------------------------------------- 1 | package graphql 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io" 7 | "strconv" 8 | ) 9 | 10 | func MarshalID(s string) Marshaler { 11 | return WriterFunc(func(w io.Writer) { 12 | io.WriteString(w, strconv.Quote(s)) 13 | }) 14 | } 15 | func UnmarshalID(v interface{}) (string, error) { 16 | switch v := v.(type) { 17 | case string: 18 | return v, nil 19 | case json.Number: 20 | return string(v), nil 21 | case int: 22 | return strconv.Itoa(v), nil 23 | case int64: 24 | return strconv.FormatInt(v, 10), nil 25 | case float64: 26 | return fmt.Sprintf("%f", v), nil 27 | case bool: 28 | if v { 29 | return "true", nil 30 | } else { 31 | return "false", nil 32 | } 33 | case nil: 34 | return "null", nil 35 | default: 36 | return "", fmt.Errorf("%T is not a string", v) 37 | } 38 | } 39 | 40 | func MarshalIntID(i int) Marshaler { 41 | return WriterFunc(func(w io.Writer) { 42 | writeQuotedString(w, strconv.Itoa(i)) 43 | }) 44 | } 45 | 46 | func UnmarshalIntID(v interface{}) (int, error) { 47 | switch v := v.(type) { 48 | case string: 49 | return strconv.Atoi(v) 50 | case int: 51 | return v, nil 52 | case int64: 53 | return int(v), nil 54 | case json.Number: 55 | return strconv.Atoi(string(v)) 56 | default: 57 | return 0, fmt.Errorf("%T is not an int", v) 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /vendor/github.com/99designs/gqlgen/graphql/int.go: -------------------------------------------------------------------------------- 1 | package graphql 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io" 7 | "strconv" 8 | ) 9 | 10 | func MarshalInt(i int) Marshaler { 11 | return WriterFunc(func(w io.Writer) { 12 | io.WriteString(w, strconv.Itoa(i)) 13 | }) 14 | } 15 | 16 | func UnmarshalInt(v interface{}) (int, error) { 17 | switch v := v.(type) { 18 | case string: 19 | return strconv.Atoi(v) 20 | case int: 21 | return v, nil 22 | case int64: 23 | return int(v), nil 24 | case json.Number: 25 | return strconv.Atoi(string(v)) 26 | default: 27 | return 0, fmt.Errorf("%T is not an int", v) 28 | } 29 | } 30 | 31 | func MarshalInt64(i int64) Marshaler { 32 | return WriterFunc(func(w io.Writer) { 33 | io.WriteString(w, strconv.FormatInt(i, 10)) 34 | }) 35 | } 36 | 37 | func UnmarshalInt64(v interface{}) (int64, error) { 38 | switch v := v.(type) { 39 | case string: 40 | return strconv.ParseInt(v, 10, 64) 41 | case int: 42 | return int64(v), nil 43 | case int64: 44 | return v, nil 45 | case json.Number: 46 | return strconv.ParseInt(string(v), 10, 64) 47 | default: 48 | return 0, fmt.Errorf("%T is not an int", v) 49 | } 50 | } 51 | 52 | func MarshalInt32(i int32) Marshaler { 53 | return WriterFunc(func(w io.Writer) { 54 | io.WriteString(w, strconv.FormatInt(int64(i), 10)) 55 | }) 56 | } 57 | 58 | func UnmarshalInt32(v interface{}) (int32, error) { 59 | switch v := v.(type) { 60 | case string: 61 | iv, err := strconv.ParseInt(v, 10, 32) 62 | if err != nil { 63 | return 0, err 64 | } 65 | return int32(iv), nil 66 | case int: 67 | return int32(v), nil 68 | case int64: 69 | return int32(v), nil 70 | case json.Number: 71 | iv, err := strconv.ParseInt(string(v), 10, 32) 72 | if err != nil { 73 | return 0, err 74 | } 75 | return int32(iv), nil 76 | default: 77 | return 0, fmt.Errorf("%T is not an int", v) 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /vendor/github.com/99designs/gqlgen/graphql/introspection/introspection.go: -------------------------------------------------------------------------------- 1 | // introspection implements the spec defined in https://github.com/facebook/graphql/blob/master/spec/Section%204%20--%20Introspection.md#schema-introspection 2 | package introspection 3 | 4 | import "github.com/vektah/gqlparser/ast" 5 | 6 | type ( 7 | Directive struct { 8 | Name string 9 | Description string 10 | Locations []string 11 | Args []InputValue 12 | } 13 | 14 | EnumValue struct { 15 | Name string 16 | Description string 17 | deprecation *ast.Directive 18 | } 19 | 20 | Field struct { 21 | Name string 22 | Description string 23 | Type *Type 24 | Args []InputValue 25 | deprecation *ast.Directive 26 | } 27 | 28 | InputValue struct { 29 | Name string 30 | Description string 31 | DefaultValue *string 32 | Type *Type 33 | } 34 | ) 35 | 36 | func WrapSchema(schema *ast.Schema) *Schema { 37 | return &Schema{schema: schema} 38 | } 39 | 40 | func (f *EnumValue) IsDeprecated() bool { 41 | return f.deprecation != nil 42 | } 43 | 44 | func (f *EnumValue) DeprecationReason() *string { 45 | if f.deprecation == nil { 46 | return nil 47 | } 48 | 49 | reason := f.deprecation.Arguments.ForName("reason") 50 | if reason == nil { 51 | return nil 52 | } 53 | 54 | return &reason.Value.Raw 55 | } 56 | 57 | func (f *Field) IsDeprecated() bool { 58 | return f.deprecation != nil 59 | } 60 | 61 | func (f *Field) DeprecationReason() *string { 62 | if f.deprecation == nil { 63 | return nil 64 | } 65 | 66 | reason := f.deprecation.Arguments.ForName("reason") 67 | if reason == nil { 68 | return nil 69 | } 70 | 71 | return &reason.Value.Raw 72 | } 73 | -------------------------------------------------------------------------------- /vendor/github.com/99designs/gqlgen/graphql/introspection/query.go: -------------------------------------------------------------------------------- 1 | package introspection 2 | 3 | // Query is the query generated by graphiql to determine type information 4 | const Query = ` 5 | query IntrospectionQuery { 6 | __schema { 7 | queryType { 8 | name 9 | } 10 | mutationType { 11 | name 12 | } 13 | subscriptionType { 14 | name 15 | } 16 | types { 17 | ...FullType 18 | } 19 | directives { 20 | name 21 | description 22 | locations 23 | args { 24 | ...InputValue 25 | } 26 | } 27 | } 28 | } 29 | 30 | fragment FullType on __Type { 31 | kind 32 | name 33 | description 34 | fields(includeDeprecated: true) { 35 | name 36 | description 37 | args { 38 | ...InputValue 39 | } 40 | type { 41 | ...TypeRef 42 | } 43 | isDeprecated 44 | deprecationReason 45 | } 46 | inputFields { 47 | ...InputValue 48 | } 49 | interfaces { 50 | ...TypeRef 51 | } 52 | enumValues(includeDeprecated: true) { 53 | name 54 | description 55 | isDeprecated 56 | deprecationReason 57 | } 58 | possibleTypes { 59 | ...TypeRef 60 | } 61 | } 62 | 63 | fragment InputValue on __InputValue { 64 | name 65 | description 66 | type { 67 | ...TypeRef 68 | } 69 | defaultValue 70 | } 71 | 72 | fragment TypeRef on __Type { 73 | kind 74 | name 75 | ofType { 76 | kind 77 | name 78 | ofType { 79 | kind 80 | name 81 | ofType { 82 | kind 83 | name 84 | ofType { 85 | kind 86 | name 87 | ofType { 88 | kind 89 | name 90 | ofType { 91 | kind 92 | name 93 | ofType { 94 | kind 95 | name 96 | } 97 | } 98 | } 99 | } 100 | } 101 | } 102 | } 103 | } 104 | ` 105 | -------------------------------------------------------------------------------- /vendor/github.com/99designs/gqlgen/graphql/introspection/schema.go: -------------------------------------------------------------------------------- 1 | package introspection 2 | 3 | import ( 4 | "strings" 5 | 6 | "github.com/vektah/gqlparser/ast" 7 | ) 8 | 9 | type Schema struct { 10 | schema *ast.Schema 11 | } 12 | 13 | func (s *Schema) Types() []Type { 14 | types := make([]Type, 0, len(s.schema.Types)) 15 | for _, typ := range s.schema.Types { 16 | if strings.HasPrefix(typ.Name, "__") { 17 | continue 18 | } 19 | types = append(types, *WrapTypeFromDef(s.schema, typ)) 20 | } 21 | return types 22 | } 23 | 24 | func (s *Schema) QueryType() *Type { 25 | return WrapTypeFromDef(s.schema, s.schema.Query) 26 | } 27 | 28 | func (s *Schema) MutationType() *Type { 29 | return WrapTypeFromDef(s.schema, s.schema.Mutation) 30 | } 31 | 32 | func (s *Schema) SubscriptionType() *Type { 33 | return WrapTypeFromDef(s.schema, s.schema.Subscription) 34 | } 35 | 36 | func (s *Schema) Directives() []Directive { 37 | res := make([]Directive, 0, len(s.schema.Directives)) 38 | 39 | for _, d := range s.schema.Directives { 40 | res = append(res, s.directiveFromDef(d)) 41 | } 42 | 43 | return res 44 | } 45 | 46 | func (s *Schema) directiveFromDef(d *ast.DirectiveDefinition) Directive { 47 | locs := make([]string, len(d.Locations)) 48 | for i, loc := range d.Locations { 49 | locs[i] = string(loc) 50 | } 51 | 52 | args := make([]InputValue, len(d.Arguments)) 53 | for i, arg := range d.Arguments { 54 | args[i] = InputValue{ 55 | Name: arg.Name, 56 | Description: arg.Description, 57 | DefaultValue: defaultValue(arg.DefaultValue), 58 | Type: WrapTypeFromType(s.schema, arg.Type), 59 | } 60 | } 61 | 62 | return Directive{ 63 | Name: d.Name, 64 | Description: d.Description, 65 | Locations: locs, 66 | Args: args, 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /vendor/github.com/99designs/gqlgen/graphql/jsonw.go: -------------------------------------------------------------------------------- 1 | package graphql 2 | 3 | import ( 4 | "io" 5 | ) 6 | 7 | var nullLit = []byte(`null`) 8 | var trueLit = []byte(`true`) 9 | var falseLit = []byte(`false`) 10 | var openBrace = []byte(`{`) 11 | var closeBrace = []byte(`}`) 12 | var openBracket = []byte(`[`) 13 | var closeBracket = []byte(`]`) 14 | var colon = []byte(`:`) 15 | var comma = []byte(`,`) 16 | 17 | var Null = &lit{nullLit} 18 | var True = &lit{trueLit} 19 | var False = &lit{falseLit} 20 | 21 | type Marshaler interface { 22 | MarshalGQL(w io.Writer) 23 | } 24 | 25 | type Unmarshaler interface { 26 | UnmarshalGQL(v interface{}) error 27 | } 28 | 29 | type WriterFunc func(writer io.Writer) 30 | 31 | func (f WriterFunc) MarshalGQL(w io.Writer) { 32 | f(w) 33 | } 34 | 35 | type Array []Marshaler 36 | 37 | func (a Array) MarshalGQL(writer io.Writer) { 38 | writer.Write(openBracket) 39 | for i, val := range a { 40 | if i != 0 { 41 | writer.Write(comma) 42 | } 43 | val.MarshalGQL(writer) 44 | } 45 | writer.Write(closeBracket) 46 | } 47 | 48 | type lit struct{ b []byte } 49 | 50 | func (l lit) MarshalGQL(w io.Writer) { 51 | w.Write(l.b) 52 | } 53 | -------------------------------------------------------------------------------- /vendor/github.com/99designs/gqlgen/graphql/map.go: -------------------------------------------------------------------------------- 1 | package graphql 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io" 7 | ) 8 | 9 | func MarshalMap(val map[string]interface{}) Marshaler { 10 | return WriterFunc(func(w io.Writer) { 11 | err := json.NewEncoder(w).Encode(val) 12 | if err != nil { 13 | panic(err) 14 | } 15 | }) 16 | } 17 | 18 | func UnmarshalMap(v interface{}) (map[string]interface{}, error) { 19 | if m, ok := v.(map[string]interface{}); ok { 20 | return m, nil 21 | } 22 | 23 | return nil, fmt.Errorf("%T is not a map", v) 24 | } 25 | -------------------------------------------------------------------------------- /vendor/github.com/99designs/gqlgen/graphql/oneshot.go: -------------------------------------------------------------------------------- 1 | package graphql 2 | 3 | func OneShot(resp *Response) func() *Response { 4 | var oneshot bool 5 | 6 | return func() *Response { 7 | if oneshot { 8 | return nil 9 | } 10 | oneshot = true 11 | 12 | return resp 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /vendor/github.com/99designs/gqlgen/graphql/recovery.go: -------------------------------------------------------------------------------- 1 | package graphql 2 | 3 | import ( 4 | "context" 5 | "errors" 6 | "fmt" 7 | "os" 8 | "runtime/debug" 9 | ) 10 | 11 | type RecoverFunc func(ctx context.Context, err interface{}) (userMessage error) 12 | 13 | func DefaultRecover(ctx context.Context, err interface{}) error { 14 | fmt.Fprintln(os.Stderr, err) 15 | fmt.Fprintln(os.Stderr) 16 | debug.PrintStack() 17 | 18 | return errors.New("internal system error") 19 | } 20 | -------------------------------------------------------------------------------- /vendor/github.com/99designs/gqlgen/graphql/response.go: -------------------------------------------------------------------------------- 1 | package graphql 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "fmt" 7 | 8 | "github.com/vektah/gqlparser/gqlerror" 9 | ) 10 | 11 | // Errors are intentionally serialized first based on the advice in 12 | // https://github.com/facebook/graphql/commit/7b40390d48680b15cb93e02d46ac5eb249689876#diff-757cea6edf0288677a9eea4cfc801d87R107 13 | // and https://github.com/facebook/graphql/pull/384 14 | type Response struct { 15 | Errors gqlerror.List `json:"errors,omitempty"` 16 | Data json.RawMessage `json:"data"` 17 | Extensions map[string]interface{} `json:"extensions,omitempty"` 18 | } 19 | 20 | func ErrorResponse(ctx context.Context, messagef string, args ...interface{}) *Response { 21 | return &Response{ 22 | Errors: gqlerror.List{{Message: fmt.Sprintf(messagef, args...)}}, 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /vendor/github.com/99designs/gqlgen/graphql/root.go: -------------------------------------------------------------------------------- 1 | package graphql 2 | 3 | type Query struct{} 4 | 5 | type Mutation struct{} 6 | 7 | type Subscription struct{} 8 | -------------------------------------------------------------------------------- /vendor/github.com/99designs/gqlgen/graphql/string.go: -------------------------------------------------------------------------------- 1 | package graphql 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "strconv" 7 | ) 8 | 9 | const encodeHex = "0123456789ABCDEF" 10 | 11 | func MarshalString(s string) Marshaler { 12 | return WriterFunc(func(w io.Writer) { 13 | writeQuotedString(w, s) 14 | }) 15 | } 16 | 17 | func writeQuotedString(w io.Writer, s string) { 18 | start := 0 19 | io.WriteString(w, `"`) 20 | 21 | for i, c := range s { 22 | if c < 0x20 || c == '\\' || c == '"' { 23 | io.WriteString(w, s[start:i]) 24 | 25 | switch c { 26 | case '\t': 27 | io.WriteString(w, `\t`) 28 | case '\r': 29 | io.WriteString(w, `\r`) 30 | case '\n': 31 | io.WriteString(w, `\n`) 32 | case '\\': 33 | io.WriteString(w, `\\`) 34 | case '"': 35 | io.WriteString(w, `\"`) 36 | default: 37 | io.WriteString(w, `\u00`) 38 | w.Write([]byte{encodeHex[c>>4], encodeHex[c&0xf]}) 39 | } 40 | 41 | start = i + 1 42 | } 43 | } 44 | 45 | io.WriteString(w, s[start:]) 46 | io.WriteString(w, `"`) 47 | } 48 | 49 | func UnmarshalString(v interface{}) (string, error) { 50 | switch v := v.(type) { 51 | case string: 52 | return v, nil 53 | case int: 54 | return strconv.Itoa(v), nil 55 | case float64: 56 | return fmt.Sprintf("%f", v), nil 57 | case bool: 58 | if v { 59 | return "true", nil 60 | } else { 61 | return "false", nil 62 | } 63 | case nil: 64 | return "null", nil 65 | default: 66 | return "", fmt.Errorf("%T is not a string", v) 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /vendor/github.com/99designs/gqlgen/graphql/time.go: -------------------------------------------------------------------------------- 1 | package graphql 2 | 3 | import ( 4 | "errors" 5 | "io" 6 | "strconv" 7 | "time" 8 | ) 9 | 10 | func MarshalTime(t time.Time) Marshaler { 11 | if t.IsZero() { 12 | return Null 13 | } 14 | 15 | return WriterFunc(func(w io.Writer) { 16 | io.WriteString(w, strconv.Quote(t.Format(time.RFC3339))) 17 | }) 18 | } 19 | 20 | func UnmarshalTime(v interface{}) (time.Time, error) { 21 | if tmpStr, ok := v.(string); ok { 22 | return time.Parse(time.RFC3339, tmpStr) 23 | } 24 | return time.Time{}, errors.New("time should be RFC3339 formatted string") 25 | } 26 | -------------------------------------------------------------------------------- /vendor/github.com/99designs/gqlgen/graphql/tracer.go: -------------------------------------------------------------------------------- 1 | package graphql 2 | 3 | import ( 4 | "context" 5 | ) 6 | 7 | var _ Tracer = (*NopTracer)(nil) 8 | 9 | type Tracer interface { 10 | StartOperationParsing(ctx context.Context) context.Context 11 | EndOperationParsing(ctx context.Context) 12 | StartOperationValidation(ctx context.Context) context.Context 13 | EndOperationValidation(ctx context.Context) 14 | StartOperationExecution(ctx context.Context) context.Context 15 | StartFieldExecution(ctx context.Context, field CollectedField) context.Context 16 | StartFieldResolverExecution(ctx context.Context, rc *ResolverContext) context.Context 17 | StartFieldChildExecution(ctx context.Context) context.Context 18 | EndFieldExecution(ctx context.Context) 19 | EndOperationExecution(ctx context.Context) 20 | } 21 | 22 | type NopTracer struct{} 23 | 24 | func (NopTracer) StartOperationParsing(ctx context.Context) context.Context { 25 | return ctx 26 | } 27 | 28 | func (NopTracer) EndOperationParsing(ctx context.Context) { 29 | } 30 | 31 | func (NopTracer) StartOperationValidation(ctx context.Context) context.Context { 32 | return ctx 33 | } 34 | 35 | func (NopTracer) EndOperationValidation(ctx context.Context) { 36 | } 37 | 38 | func (NopTracer) StartOperationExecution(ctx context.Context) context.Context { 39 | return ctx 40 | } 41 | 42 | func (NopTracer) StartFieldExecution(ctx context.Context, field CollectedField) context.Context { 43 | return ctx 44 | } 45 | 46 | func (NopTracer) StartFieldResolverExecution(ctx context.Context, rc *ResolverContext) context.Context { 47 | return ctx 48 | } 49 | 50 | func (NopTracer) StartFieldChildExecution(ctx context.Context) context.Context { 51 | return ctx 52 | } 53 | 54 | func (NopTracer) EndFieldExecution(ctx context.Context) { 55 | } 56 | 57 | func (NopTracer) EndOperationExecution(ctx context.Context) { 58 | } 59 | -------------------------------------------------------------------------------- /vendor/github.com/99designs/gqlgen/graphql/upload.go: -------------------------------------------------------------------------------- 1 | package graphql 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | ) 7 | 8 | type Upload struct { 9 | File io.Reader 10 | Filename string 11 | Size int64 12 | } 13 | 14 | func MarshalUpload(f Upload) Marshaler { 15 | return WriterFunc(func(w io.Writer) { 16 | io.Copy(w, f.File) 17 | }) 18 | } 19 | 20 | func UnmarshalUpload(v interface{}) (Upload, error) { 21 | upload, ok := v.(Upload) 22 | if !ok { 23 | return Upload{}, fmt.Errorf("%T is not an Upload", v) 24 | } 25 | return upload, nil 26 | } 27 | -------------------------------------------------------------------------------- /vendor/github.com/99designs/gqlgen/graphql/version.go: -------------------------------------------------------------------------------- 1 | package graphql 2 | 3 | const Version = "v0.10.2" 4 | -------------------------------------------------------------------------------- /vendor/github.com/99designs/gqlgen/handler/context.go: -------------------------------------------------------------------------------- 1 | package handler 2 | 3 | import "context" 4 | 5 | type key string 6 | 7 | const ( 8 | initpayload key = "ws_initpayload_context" 9 | ) 10 | 11 | // InitPayload is a structure that is parsed from the websocket init message payload. TO use 12 | // request headers for non-websocket, instead wrap the graphql handler in a middleware. 13 | type InitPayload map[string]interface{} 14 | 15 | // GetString safely gets a string value from the payload. It returns an empty string if the 16 | // payload is nil or the value isn't set. 17 | func (payload InitPayload) GetString(key string) string { 18 | if payload == nil { 19 | return "" 20 | } 21 | 22 | if value, ok := payload[key]; ok { 23 | res, _ := value.(string) 24 | return res 25 | } 26 | 27 | return "" 28 | } 29 | 30 | // Authorization is a short hand for getting the Authorization header from the 31 | // payload. 32 | func (payload InitPayload) Authorization() string { 33 | if value := payload.GetString("Authorization"); value != "" { 34 | return value 35 | } 36 | 37 | if value := payload.GetString("authorization"); value != "" { 38 | return value 39 | } 40 | 41 | return "" 42 | } 43 | 44 | func withInitPayload(ctx context.Context, payload InitPayload) context.Context { 45 | return context.WithValue(ctx, initpayload, payload) 46 | } 47 | 48 | // GetInitPayload gets a map of the data sent with the connection_init message, which is used by 49 | // graphql clients as a stand-in for HTTP headers. 50 | func GetInitPayload(ctx context.Context) InitPayload { 51 | payload, ok := ctx.Value(initpayload).(InitPayload) 52 | if !ok { 53 | return nil 54 | } 55 | 56 | return payload 57 | } 58 | -------------------------------------------------------------------------------- /vendor/github.com/99designs/gqlgen/handler/mock.go: -------------------------------------------------------------------------------- 1 | package handler 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/99designs/gqlgen/graphql" 7 | "github.com/vektah/gqlparser" 8 | "github.com/vektah/gqlparser/ast" 9 | ) 10 | 11 | type executableSchemaMock struct { 12 | QueryFunc func(ctx context.Context, op *ast.OperationDefinition) *graphql.Response 13 | MutationFunc func(ctx context.Context, op *ast.OperationDefinition) *graphql.Response 14 | } 15 | 16 | var _ graphql.ExecutableSchema = &executableSchemaMock{} 17 | 18 | func (e *executableSchemaMock) Schema() *ast.Schema { 19 | return gqlparser.MustLoadSchema(&ast.Source{Input: ` 20 | schema { query: Query, mutation: Mutation } 21 | type Query { 22 | empty: String! 23 | } 24 | scalar Upload 25 | type File { 26 | id: Int! 27 | } 28 | input UploadFile { 29 | id: Int! 30 | file: Upload! 31 | } 32 | type Mutation { 33 | singleUpload(file: Upload!): File! 34 | singleUploadWithPayload(req: UploadFile!): File! 35 | multipleUpload(files: [Upload!]!): [File!]! 36 | multipleUploadWithPayload(req: [UploadFile!]!): [File!]! 37 | } 38 | `}) 39 | } 40 | 41 | func (e *executableSchemaMock) Complexity(typeName, field string, childComplexity int, args map[string]interface{}) (int, bool) { 42 | return 0, false 43 | } 44 | 45 | func (e *executableSchemaMock) Query(ctx context.Context, op *ast.OperationDefinition) *graphql.Response { 46 | if e.QueryFunc == nil { 47 | return graphql.ErrorResponse(ctx, "queries are not supported") 48 | } 49 | return e.QueryFunc(ctx, op) 50 | } 51 | 52 | func (e *executableSchemaMock) Mutation(ctx context.Context, op *ast.OperationDefinition) *graphql.Response { 53 | return e.MutationFunc(ctx, op) 54 | } 55 | 56 | func (e *executableSchemaMock) Subscription(ctx context.Context, op *ast.OperationDefinition) func() *graphql.Response { 57 | return func() *graphql.Response { 58 | <-ctx.Done() 59 | return nil 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /vendor/github.com/99designs/gqlgen/handler/playground.go: -------------------------------------------------------------------------------- 1 | package handler 2 | 3 | import ( 4 | "html/template" 5 | "net/http" 6 | ) 7 | 8 | var page = template.Must(template.New("graphiql").Parse(` 9 | 10 | 11 | 12 | 13 | 14 | 16 | 18 | 20 | {{.title}} 21 | 22 | 23 | 27 |
28 | 43 | 44 | 45 | `)) 46 | 47 | func Playground(title string, endpoint string) http.HandlerFunc { 48 | return func(w http.ResponseWriter, r *http.Request) { 49 | w.Header().Add("Content-Type", "text/html") 50 | err := page.Execute(w, map[string]string{ 51 | "title": title, 52 | "endpoint": endpoint, 53 | "version": "1.7.20", 54 | "cssSRI": "sha256-cS9Vc2OBt9eUf4sykRWukeFYaInL29+myBmFDSa7F/U=", 55 | "faviconSRI": "sha256-GhTyE+McTU79R4+pRO6ih+4TfsTOrpPwD8ReKFzb3PM=", 56 | "jsSRI": "sha256-4QG1Uza2GgGdlBL3RCBCGtGeZB6bDbsw8OltCMGeJsA=", 57 | }) 58 | if err != nil { 59 | panic(err) 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /vendor/github.com/99designs/gqlgen/handler/stub.go: -------------------------------------------------------------------------------- 1 | package handler 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/99designs/gqlgen/graphql" 7 | "github.com/vektah/gqlparser" 8 | "github.com/vektah/gqlparser/ast" 9 | ) 10 | 11 | type executableSchemaStub struct { 12 | NextResp chan struct{} 13 | } 14 | 15 | var _ graphql.ExecutableSchema = &executableSchemaStub{} 16 | 17 | func (e *executableSchemaStub) Schema() *ast.Schema { 18 | return gqlparser.MustLoadSchema(&ast.Source{Input: ` 19 | schema { query: Query } 20 | type Query { 21 | me: User! 22 | user(id: Int): User! 23 | } 24 | type User { name: String! } 25 | `}) 26 | } 27 | 28 | func (e *executableSchemaStub) Complexity(typeName, field string, childComplexity int, args map[string]interface{}) (int, bool) { 29 | return 0, false 30 | } 31 | 32 | func (e *executableSchemaStub) Query(ctx context.Context, op *ast.OperationDefinition) *graphql.Response { 33 | return &graphql.Response{Data: []byte(`{"name":"test"}`)} 34 | } 35 | 36 | func (e *executableSchemaStub) Mutation(ctx context.Context, op *ast.OperationDefinition) *graphql.Response { 37 | return graphql.ErrorResponse(ctx, "mutations are not supported") 38 | } 39 | 40 | func (e *executableSchemaStub) Subscription(ctx context.Context, op *ast.OperationDefinition) func() *graphql.Response { 41 | return func() *graphql.Response { 42 | select { 43 | case <-ctx.Done(): 44 | return nil 45 | case <-e.NextResp: 46 | return &graphql.Response{ 47 | Data: []byte(`{"name":"test"}`), 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /vendor/github.com/agnivade/levenshtein/.gitignore: -------------------------------------------------------------------------------- 1 | coverage.txt 2 | fuzz/fuzz-fuzz.zip 3 | fuzz/corpus/corpus/* 4 | fuzz/corpus/suppressions/* 5 | fuzz/corpus/crashes/* 6 | -------------------------------------------------------------------------------- /vendor/github.com/agnivade/levenshtein/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.9.x 5 | - 1.10.x 6 | - 1.11.x 7 | - tip 8 | -------------------------------------------------------------------------------- /vendor/github.com/agnivade/levenshtein/License.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Agniva De Sarker 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/github.com/agnivade/levenshtein/Makefile: -------------------------------------------------------------------------------- 1 | all: test install 2 | 3 | install: 4 | go install 5 | 6 | lint: 7 | gofmt -l -s -w . && go tool vet -all . && golint 8 | 9 | test: 10 | go test -race -v -coverprofile=coverage.txt -covermode=atomic 11 | 12 | bench: 13 | go test -run=XXX -bench=. -benchmem 14 | -------------------------------------------------------------------------------- /vendor/github.com/agnivade/levenshtein/README.md: -------------------------------------------------------------------------------- 1 | levenshtein [![Build Status](https://travis-ci.org/agnivade/levenshtein.svg?branch=master)](https://travis-ci.org/agnivade/levenshtein) [![Go Report Card](https://goreportcard.com/badge/github.com/agnivade/levenshtein)](https://goreportcard.com/report/github.com/agnivade/levenshtein) [![GoDoc](https://godoc.org/github.com/agnivade/levenshtein?status.svg)](https://godoc.org/github.com/agnivade/levenshtein) 2 | =========== 3 | 4 | [Go](http://golang.org) package to calculate the [Levenshtein Distance](http://en.wikipedia.org/wiki/Levenshtein_distance) 5 | 6 | The library is fully capable of working with non-ascii strings. But the strings are not normalized. That is left as a user-dependant use case. Please normalize the strings before passing it to the library if you have such a requirement. 7 | - https://blog.golang.org/normalization 8 | 9 | Install 10 | ------- 11 | 12 | go get github.com/agnivade/levenshtein 13 | 14 | Example 15 | ------- 16 | 17 | ```go 18 | package main 19 | 20 | import ( 21 | "fmt" 22 | "github.com/agnivade/levenshtein" 23 | ) 24 | 25 | func main() { 26 | s1 := "kitten" 27 | s2 := "sitting" 28 | distance := levenshtein.ComputeDistance(s1, s2) 29 | fmt.Printf("The distance between %s and %s is %d.\n", s1, s2, distance) 30 | // Output: 31 | // The distance between kitten and sitting is 3. 32 | } 33 | 34 | ``` 35 | 36 | Benchmarks 37 | ---------- 38 | 39 | ``` 40 | name time/op 41 | Simple/ASCII-4 537ns ± 2% 42 | Simple/French-4 956ns ± 0% 43 | Simple/Nordic-4 1.95µs ± 1% 44 | Simple/Tibetan-4 1.53µs ± 2% 45 | 46 | name alloc/op 47 | Simple/ASCII-4 96.0B ± 0% 48 | Simple/French-4 128B ± 0% 49 | Simple/Nordic-4 192B ± 0% 50 | Simple/Tibetan-4 144B ± 0% 51 | 52 | name allocs/op 53 | Simple/ASCII-4 1.00 ± 0% 54 | Simple/French-4 1.00 ± 0% 55 | Simple/Nordic-4 1.00 ± 0% 56 | Simple/Tibetan-4 1.00 ± 0% 57 | ``` 58 | -------------------------------------------------------------------------------- /vendor/github.com/agnivade/levenshtein/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/agnivade/levenshtein 2 | -------------------------------------------------------------------------------- /vendor/github.com/agnivade/levenshtein/levenshtein.go: -------------------------------------------------------------------------------- 1 | // Package levenshtein is a Go implementation to calculate Levenshtein Distance. 2 | // 3 | // Implementation taken from 4 | // https://gist.github.com/andrei-m/982927#gistcomment-1931258 5 | package levenshtein 6 | 7 | import "unicode/utf8" 8 | 9 | // ComputeDistance computes the levenshtein distance between the two 10 | // strings passed as an argument. The return value is the levenshtein distance 11 | // 12 | // Works on runes (Unicode code points) but does not normalize 13 | // the input strings. See https://blog.golang.org/normalization 14 | // and the golang.org/x/text/unicode/norm pacage. 15 | func ComputeDistance(a, b string) int { 16 | if len(a) == 0 { 17 | return utf8.RuneCountInString(b) 18 | } 19 | 20 | if len(b) == 0 { 21 | return utf8.RuneCountInString(a) 22 | } 23 | 24 | if a == b { 25 | return 0 26 | } 27 | 28 | // We need to convert to []rune if the strings are non-ascii. 29 | // This could be avoided by using utf8.RuneCountInString 30 | // and then doing some juggling with rune indices. 31 | // The primary challenge is keeping track of the previous rune. 32 | // With a range loop, its not that easy. And with a for-loop 33 | // we need to keep track of the inter-rune width using utf8.DecodeRuneInString 34 | s1 := []rune(a) 35 | s2 := []rune(b) 36 | 37 | // swap to save some memory O(min(a,b)) instead of O(a) 38 | if len(s1) > len(s2) { 39 | s1, s2 = s2, s1 40 | } 41 | lenS1 := len(s1) 42 | lenS2 := len(s2) 43 | 44 | // init the row 45 | x := make([]int, lenS1+1) 46 | for i := 0; i <= lenS1; i++ { 47 | x[i] = i 48 | } 49 | 50 | // fill in the rest 51 | for i := 1; i <= lenS2; i++ { 52 | prev := i 53 | var current int 54 | 55 | for j := 1; j <= lenS1; j++ { 56 | 57 | if s2[i-1] == s1[j-1] { 58 | current = x[j-1] // match 59 | } else { 60 | current = min(min(x[j-1]+1, prev+1), x[j]+1) 61 | } 62 | x[j-1] = prev 63 | prev = current 64 | } 65 | x[lenS1] = prev 66 | } 67 | return x[lenS1] 68 | } 69 | 70 | func min(a, b int) int { 71 | if a < b { 72 | return a 73 | } 74 | return b 75 | } 76 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/.gitignore: -------------------------------------------------------------------------------- 1 | *.rdb 2 | testdata/*/ 3 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: go 3 | 4 | services: 5 | - redis-server 6 | 7 | go: 8 | - 1.9.x 9 | - 1.10.x 10 | - 1.11.x 11 | - 1.12.x 12 | - tip 13 | 14 | matrix: 15 | allow_failures: 16 | - go: tip 17 | 18 | install: 19 | - go get github.com/onsi/ginkgo 20 | - go get github.com/onsi/gomega 21 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## Unreleased 4 | 5 | - Cluster and Ring pipelines process commands for each node in its own goroutine. 6 | 7 | ## 6.14 8 | 9 | - Added Options.MinIdleConns. 10 | - Added Options.MaxConnAge. 11 | - PoolStats.FreeConns is renamed to PoolStats.IdleConns. 12 | - Add Client.Do to simplify creating custom commands. 13 | - Add Cmd.String, Cmd.Int, Cmd.Int64, Cmd.Uint64, Cmd.Float64, and Cmd.Bool helpers. 14 | - Lower memory usage. 15 | 16 | ## v6.13 17 | 18 | - Ring got new options called `HashReplicas` and `Hash`. It is recommended to set `HashReplicas = 1000` for better keys distribution between shards. 19 | - Cluster client was optimized to use much less memory when reloading cluster state. 20 | - PubSub.ReceiveMessage is re-worked to not use ReceiveTimeout so it does not lose data when timeout occurres. In most cases it is recommended to use PubSub.Channel instead. 21 | - Dialer.KeepAlive is set to 5 minutes by default. 22 | 23 | ## v6.12 24 | 25 | - ClusterClient got new option called `ClusterSlots` which allows to build cluster of normal Redis Servers that don't have cluster mode enabled. See https://godoc.org/github.com/go-redis/redis#example-NewClusterClient--ManualSetup 26 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 The github.com/go-redis/redis Authors. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above 11 | copyright notice, this list of conditions and the following disclaimer 12 | in the documentation and/or other materials provided with the 13 | distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/Makefile: -------------------------------------------------------------------------------- 1 | all: testdeps 2 | go test ./... 3 | go test ./... -short -race 4 | env GOOS=linux GOARCH=386 go test ./... 5 | go vet 6 | go get github.com/gordonklaus/ineffassign 7 | ineffassign . 8 | 9 | testdeps: testdata/redis/src/redis-server 10 | 11 | bench: testdeps 12 | go test ./... -test.run=NONE -test.bench=. -test.benchmem 13 | 14 | .PHONY: all test testdeps bench 15 | 16 | testdata/redis: 17 | mkdir -p $@ 18 | wget -qO- https://github.com/antirez/redis/archive/5.0.tar.gz | tar xvz --strip-components=1 -C $@ 19 | 20 | testdata/redis/src/redis-server: testdata/redis 21 | sed -i.bak 's/libjemalloc.a/libjemalloc.a -lrt/g' $= hash }) 74 | 75 | // Means we have cycled back to the first replica. 76 | if idx == len(m.keys) { 77 | idx = 0 78 | } 79 | 80 | return m.hashMap[m.keys[idx]] 81 | } 82 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/internal/error.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import ( 4 | "io" 5 | "net" 6 | "strings" 7 | 8 | "github.com/go-redis/redis/internal/proto" 9 | ) 10 | 11 | func IsRetryableError(err error, retryTimeout bool) bool { 12 | if err == nil { 13 | return false 14 | } 15 | if err == io.EOF { 16 | return true 17 | } 18 | if netErr, ok := err.(net.Error); ok { 19 | if netErr.Timeout() { 20 | return retryTimeout 21 | } 22 | return true 23 | } 24 | s := err.Error() 25 | if s == "ERR max number of clients reached" { 26 | return true 27 | } 28 | if strings.HasPrefix(s, "LOADING ") { 29 | return true 30 | } 31 | if strings.HasPrefix(s, "READONLY ") { 32 | return true 33 | } 34 | if strings.HasPrefix(s, "CLUSTERDOWN ") { 35 | return true 36 | } 37 | return false 38 | } 39 | 40 | func IsRedisError(err error) bool { 41 | _, ok := err.(proto.RedisError) 42 | return ok 43 | } 44 | 45 | func IsBadConn(err error, allowTimeout bool) bool { 46 | if err == nil { 47 | return false 48 | } 49 | if IsRedisError(err) { 50 | // #790 51 | return IsReadOnlyError(err) 52 | } 53 | if allowTimeout { 54 | if netErr, ok := err.(net.Error); ok && netErr.Timeout() { 55 | return false 56 | } 57 | } 58 | return true 59 | } 60 | 61 | func IsMovedError(err error) (moved bool, ask bool, addr string) { 62 | if !IsRedisError(err) { 63 | return 64 | } 65 | 66 | s := err.Error() 67 | if strings.HasPrefix(s, "MOVED ") { 68 | moved = true 69 | } else if strings.HasPrefix(s, "ASK ") { 70 | ask = true 71 | } else { 72 | return 73 | } 74 | 75 | ind := strings.LastIndex(s, " ") 76 | if ind == -1 { 77 | return false, false, "" 78 | } 79 | addr = s[ind+1:] 80 | return 81 | } 82 | 83 | func IsLoadingError(err error) bool { 84 | return strings.HasPrefix(err.Error(), "LOADING ") 85 | } 86 | 87 | func IsReadOnlyError(err error) bool { 88 | return strings.HasPrefix(err.Error(), "READONLY ") 89 | } 90 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/internal/hashtag/hashtag.go: -------------------------------------------------------------------------------- 1 | package hashtag 2 | 3 | import ( 4 | "math/rand" 5 | "strings" 6 | ) 7 | 8 | const slotNumber = 16384 9 | 10 | // CRC16 implementation according to CCITT standards. 11 | // Copyright 2001-2010 Georges Menie (www.menie.org) 12 | // Copyright 2013 The Go Authors. All rights reserved. 13 | // http://redis.io/topics/cluster-spec#appendix-a-crc16-reference-implementation-in-ansi-c 14 | var crc16tab = [256]uint16{ 15 | 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 16 | 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 17 | 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 18 | 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 19 | 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 20 | 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, 21 | 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 22 | 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, 23 | 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, 24 | 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, 25 | 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 26 | 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, 27 | 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 28 | 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, 29 | 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, 30 | 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, 31 | 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 32 | 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, 33 | 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 34 | 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, 35 | 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 36 | 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 37 | 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, 38 | 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, 39 | 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 40 | 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, 41 | 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 42 | 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, 43 | 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 44 | 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, 45 | 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 46 | 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0, 47 | } 48 | 49 | func Key(key string) string { 50 | if s := strings.IndexByte(key, '{'); s > -1 { 51 | if e := strings.IndexByte(key[s+1:], '}'); e > 0 { 52 | return key[s+1 : s+e+1] 53 | } 54 | } 55 | return key 56 | } 57 | 58 | func RandomSlot() int { 59 | return rand.Intn(slotNumber) 60 | } 61 | 62 | // hashSlot returns a consistent slot number between 0 and 16383 63 | // for any given string key. 64 | func Slot(key string) int { 65 | if key == "" { 66 | return RandomSlot() 67 | } 68 | key = Key(key) 69 | return int(crc16sum(key)) % slotNumber 70 | } 71 | 72 | func crc16sum(key string) (crc uint16) { 73 | for i := 0; i < len(key); i++ { 74 | crc = (crc << 8) ^ crc16tab[(byte(crc>>8)^key[i])&0x00ff] 75 | } 76 | return 77 | } 78 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/internal/internal.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import ( 4 | "math/rand" 5 | "time" 6 | ) 7 | 8 | // Retry backoff with jitter sleep to prevent overloaded conditions during intervals 9 | // https://www.awsarchitectureblog.com/2015/03/backoff.html 10 | func RetryBackoff(retry int, minBackoff, maxBackoff time.Duration) time.Duration { 11 | if retry < 0 { 12 | retry = 0 13 | } 14 | 15 | backoff := minBackoff << uint(retry) 16 | if backoff > maxBackoff || backoff < minBackoff { 17 | backoff = maxBackoff 18 | } 19 | 20 | if backoff == 0 { 21 | return 0 22 | } 23 | return time.Duration(rand.Int63n(int64(backoff))) 24 | } 25 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/internal/log.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | ) 7 | 8 | var Logger *log.Logger 9 | 10 | func Logf(s string, args ...interface{}) { 11 | if Logger == nil { 12 | return 13 | } 14 | Logger.Output(2, fmt.Sprintf(s, args...)) 15 | } 16 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/internal/once.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 The Camlistore Authors 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package internal 18 | 19 | import ( 20 | "sync" 21 | "sync/atomic" 22 | ) 23 | 24 | // A Once will perform a successful action exactly once. 25 | // 26 | // Unlike a sync.Once, this Once's func returns an error 27 | // and is re-armed on failure. 28 | type Once struct { 29 | m sync.Mutex 30 | done uint32 31 | } 32 | 33 | // Do calls the function f if and only if Do has not been invoked 34 | // without error for this instance of Once. In other words, given 35 | // var once Once 36 | // if once.Do(f) is called multiple times, only the first call will 37 | // invoke f, even if f has a different value in each invocation unless 38 | // f returns an error. A new instance of Once is required for each 39 | // function to execute. 40 | // 41 | // Do is intended for initialization that must be run exactly once. Since f 42 | // is niladic, it may be necessary to use a function literal to capture the 43 | // arguments to a function to be invoked by Do: 44 | // err := config.once.Do(func() error { return config.init(filename) }) 45 | func (o *Once) Do(f func() error) error { 46 | if atomic.LoadUint32(&o.done) == 1 { 47 | return nil 48 | } 49 | // Slow-path. 50 | o.m.Lock() 51 | defer o.m.Unlock() 52 | var err error 53 | if o.done == 0 { 54 | err = f() 55 | if err == nil { 56 | atomic.StoreUint32(&o.done, 1) 57 | } 58 | } 59 | return err 60 | } 61 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/internal/pool/conn.go: -------------------------------------------------------------------------------- 1 | package pool 2 | 3 | import ( 4 | "net" 5 | "sync/atomic" 6 | "time" 7 | 8 | "github.com/go-redis/redis/internal/proto" 9 | ) 10 | 11 | var noDeadline = time.Time{} 12 | 13 | type Conn struct { 14 | netConn net.Conn 15 | 16 | rd *proto.Reader 17 | rdLocked bool 18 | wr *proto.Writer 19 | 20 | Inited bool 21 | pooled bool 22 | createdAt time.Time 23 | usedAt atomic.Value 24 | } 25 | 26 | func NewConn(netConn net.Conn) *Conn { 27 | cn := &Conn{ 28 | netConn: netConn, 29 | createdAt: time.Now(), 30 | } 31 | cn.rd = proto.NewReader(netConn) 32 | cn.wr = proto.NewWriter(netConn) 33 | cn.SetUsedAt(time.Now()) 34 | return cn 35 | } 36 | 37 | func (cn *Conn) UsedAt() time.Time { 38 | return cn.usedAt.Load().(time.Time) 39 | } 40 | 41 | func (cn *Conn) SetUsedAt(tm time.Time) { 42 | cn.usedAt.Store(tm) 43 | } 44 | 45 | func (cn *Conn) SetNetConn(netConn net.Conn) { 46 | cn.netConn = netConn 47 | cn.rd.Reset(netConn) 48 | cn.wr.Reset(netConn) 49 | } 50 | 51 | func (cn *Conn) setReadTimeout(timeout time.Duration) error { 52 | now := time.Now() 53 | cn.SetUsedAt(now) 54 | if timeout > 0 { 55 | return cn.netConn.SetReadDeadline(now.Add(timeout)) 56 | } 57 | return cn.netConn.SetReadDeadline(noDeadline) 58 | } 59 | 60 | func (cn *Conn) setWriteTimeout(timeout time.Duration) error { 61 | now := time.Now() 62 | cn.SetUsedAt(now) 63 | if timeout > 0 { 64 | return cn.netConn.SetWriteDeadline(now.Add(timeout)) 65 | } 66 | return cn.netConn.SetWriteDeadline(noDeadline) 67 | } 68 | 69 | func (cn *Conn) Write(b []byte) (int, error) { 70 | return cn.netConn.Write(b) 71 | } 72 | 73 | func (cn *Conn) RemoteAddr() net.Addr { 74 | return cn.netConn.RemoteAddr() 75 | } 76 | 77 | func (cn *Conn) WithReader(timeout time.Duration, fn func(rd *proto.Reader) error) error { 78 | _ = cn.setReadTimeout(timeout) 79 | return fn(cn.rd) 80 | } 81 | 82 | func (cn *Conn) WithWriter(timeout time.Duration, fn func(wr *proto.Writer) error) error { 83 | _ = cn.setWriteTimeout(timeout) 84 | 85 | firstErr := fn(cn.wr) 86 | err := cn.wr.Flush() 87 | if err != nil && firstErr == nil { 88 | firstErr = err 89 | } 90 | return firstErr 91 | } 92 | 93 | func (cn *Conn) Close() error { 94 | return cn.netConn.Close() 95 | } 96 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/internal/pool/pool_sticky.go: -------------------------------------------------------------------------------- 1 | package pool 2 | 3 | import "sync" 4 | 5 | type StickyConnPool struct { 6 | pool *ConnPool 7 | reusable bool 8 | 9 | cn *Conn 10 | closed bool 11 | mu sync.Mutex 12 | } 13 | 14 | var _ Pooler = (*StickyConnPool)(nil) 15 | 16 | func NewStickyConnPool(pool *ConnPool, reusable bool) *StickyConnPool { 17 | return &StickyConnPool{ 18 | pool: pool, 19 | reusable: reusable, 20 | } 21 | } 22 | 23 | func (p *StickyConnPool) NewConn() (*Conn, error) { 24 | panic("not implemented") 25 | } 26 | 27 | func (p *StickyConnPool) CloseConn(*Conn) error { 28 | panic("not implemented") 29 | } 30 | 31 | func (p *StickyConnPool) Get() (*Conn, error) { 32 | p.mu.Lock() 33 | defer p.mu.Unlock() 34 | 35 | if p.closed { 36 | return nil, ErrClosed 37 | } 38 | if p.cn != nil { 39 | return p.cn, nil 40 | } 41 | 42 | cn, err := p.pool.Get() 43 | if err != nil { 44 | return nil, err 45 | } 46 | 47 | p.cn = cn 48 | return cn, nil 49 | } 50 | 51 | func (p *StickyConnPool) putUpstream() { 52 | p.pool.Put(p.cn) 53 | p.cn = nil 54 | } 55 | 56 | func (p *StickyConnPool) Put(cn *Conn) {} 57 | 58 | func (p *StickyConnPool) removeUpstream(reason error) { 59 | p.pool.Remove(p.cn, reason) 60 | p.cn = nil 61 | } 62 | 63 | func (p *StickyConnPool) Remove(cn *Conn, reason error) { 64 | p.removeUpstream(reason) 65 | } 66 | 67 | func (p *StickyConnPool) Len() int { 68 | p.mu.Lock() 69 | defer p.mu.Unlock() 70 | 71 | if p.cn == nil { 72 | return 0 73 | } 74 | return 1 75 | } 76 | 77 | func (p *StickyConnPool) IdleLen() int { 78 | p.mu.Lock() 79 | defer p.mu.Unlock() 80 | 81 | if p.cn == nil { 82 | return 1 83 | } 84 | return 0 85 | } 86 | 87 | func (p *StickyConnPool) Stats() *Stats { 88 | return nil 89 | } 90 | 91 | func (p *StickyConnPool) Close() error { 92 | p.mu.Lock() 93 | defer p.mu.Unlock() 94 | 95 | if p.closed { 96 | return ErrClosed 97 | } 98 | p.closed = true 99 | 100 | if p.cn != nil { 101 | if p.reusable { 102 | p.putUpstream() 103 | } else { 104 | p.removeUpstream(ErrClosed) 105 | } 106 | } 107 | 108 | return nil 109 | } 110 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/internal/proto/writer.go: -------------------------------------------------------------------------------- 1 | package proto 2 | 3 | import ( 4 | "bufio" 5 | "encoding" 6 | "fmt" 7 | "io" 8 | "strconv" 9 | 10 | "github.com/go-redis/redis/internal/util" 11 | ) 12 | 13 | type Writer struct { 14 | wr *bufio.Writer 15 | 16 | lenBuf []byte 17 | numBuf []byte 18 | } 19 | 20 | func NewWriter(wr io.Writer) *Writer { 21 | return &Writer{ 22 | wr: bufio.NewWriter(wr), 23 | 24 | lenBuf: make([]byte, 64), 25 | numBuf: make([]byte, 64), 26 | } 27 | } 28 | 29 | func (w *Writer) WriteArgs(args []interface{}) error { 30 | err := w.wr.WriteByte(ArrayReply) 31 | if err != nil { 32 | return err 33 | } 34 | 35 | err = w.writeLen(len(args)) 36 | if err != nil { 37 | return err 38 | } 39 | 40 | for _, arg := range args { 41 | err := w.writeArg(arg) 42 | if err != nil { 43 | return err 44 | } 45 | } 46 | 47 | return nil 48 | } 49 | 50 | func (w *Writer) writeLen(n int) error { 51 | w.lenBuf = strconv.AppendUint(w.lenBuf[:0], uint64(n), 10) 52 | w.lenBuf = append(w.lenBuf, '\r', '\n') 53 | _, err := w.wr.Write(w.lenBuf) 54 | return err 55 | } 56 | 57 | func (w *Writer) writeArg(v interface{}) error { 58 | switch v := v.(type) { 59 | case nil: 60 | return w.string("") 61 | case string: 62 | return w.string(v) 63 | case []byte: 64 | return w.bytes(v) 65 | case int: 66 | return w.int(int64(v)) 67 | case int8: 68 | return w.int(int64(v)) 69 | case int16: 70 | return w.int(int64(v)) 71 | case int32: 72 | return w.int(int64(v)) 73 | case int64: 74 | return w.int(v) 75 | case uint: 76 | return w.uint(uint64(v)) 77 | case uint8: 78 | return w.uint(uint64(v)) 79 | case uint16: 80 | return w.uint(uint64(v)) 81 | case uint32: 82 | return w.uint(uint64(v)) 83 | case uint64: 84 | return w.uint(v) 85 | case float32: 86 | return w.float(float64(v)) 87 | case float64: 88 | return w.float(v) 89 | case bool: 90 | if v { 91 | return w.int(1) 92 | } else { 93 | return w.int(0) 94 | } 95 | case encoding.BinaryMarshaler: 96 | b, err := v.MarshalBinary() 97 | if err != nil { 98 | return err 99 | } 100 | return w.bytes(b) 101 | default: 102 | return fmt.Errorf( 103 | "redis: can't marshal %T (implement encoding.BinaryMarshaler)", v) 104 | } 105 | } 106 | 107 | func (w *Writer) bytes(b []byte) error { 108 | err := w.wr.WriteByte(StringReply) 109 | if err != nil { 110 | return err 111 | } 112 | 113 | err = w.writeLen(len(b)) 114 | if err != nil { 115 | return err 116 | } 117 | 118 | _, err = w.wr.Write(b) 119 | if err != nil { 120 | return err 121 | } 122 | 123 | return w.crlf() 124 | } 125 | 126 | func (w *Writer) string(s string) error { 127 | return w.bytes(util.StringToBytes(s)) 128 | } 129 | 130 | func (w *Writer) uint(n uint64) error { 131 | w.numBuf = strconv.AppendUint(w.numBuf[:0], n, 10) 132 | return w.bytes(w.numBuf) 133 | } 134 | 135 | func (w *Writer) int(n int64) error { 136 | w.numBuf = strconv.AppendInt(w.numBuf[:0], n, 10) 137 | return w.bytes(w.numBuf) 138 | } 139 | 140 | func (w *Writer) float(f float64) error { 141 | w.numBuf = strconv.AppendFloat(w.numBuf[:0], f, 'f', -1, 64) 142 | return w.bytes(w.numBuf) 143 | } 144 | 145 | func (w *Writer) crlf() error { 146 | err := w.wr.WriteByte('\r') 147 | if err != nil { 148 | return err 149 | } 150 | return w.wr.WriteByte('\n') 151 | } 152 | 153 | func (w *Writer) Reset(wr io.Writer) { 154 | w.wr.Reset(wr) 155 | } 156 | 157 | func (w *Writer) Flush() error { 158 | return w.wr.Flush() 159 | } 160 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/internal/util.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import "github.com/go-redis/redis/internal/util" 4 | 5 | func ToLower(s string) string { 6 | if isLower(s) { 7 | return s 8 | } 9 | 10 | b := make([]byte, len(s)) 11 | for i := range b { 12 | c := s[i] 13 | if c >= 'A' && c <= 'Z' { 14 | c += 'a' - 'A' 15 | } 16 | b[i] = c 17 | } 18 | return util.BytesToString(b) 19 | } 20 | 21 | func isLower(s string) bool { 22 | for i := 0; i < len(s); i++ { 23 | c := s[i] 24 | if c >= 'A' && c <= 'Z' { 25 | return false 26 | } 27 | } 28 | return true 29 | } 30 | 31 | func Unwrap(err error) error { 32 | u, ok := err.(interface { 33 | Unwrap() error 34 | }) 35 | if !ok { 36 | return nil 37 | } 38 | return u.Unwrap() 39 | } 40 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/internal/util/safe.go: -------------------------------------------------------------------------------- 1 | // +build appengine 2 | 3 | package util 4 | 5 | func BytesToString(b []byte) string { 6 | return string(b) 7 | } 8 | 9 | func StringToBytes(s string) []byte { 10 | return []byte(s) 11 | } 12 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/internal/util/strconv.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import "strconv" 4 | 5 | func Atoi(b []byte) (int, error) { 6 | return strconv.Atoi(BytesToString(b)) 7 | } 8 | 9 | func ParseInt(b []byte, base int, bitSize int) (int64, error) { 10 | return strconv.ParseInt(BytesToString(b), base, bitSize) 11 | } 12 | 13 | func ParseUint(b []byte, base int, bitSize int) (uint64, error) { 14 | return strconv.ParseUint(BytesToString(b), base, bitSize) 15 | } 16 | 17 | func ParseFloat(b []byte, bitSize int) (float64, error) { 18 | return strconv.ParseFloat(BytesToString(b), bitSize) 19 | } 20 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/internal/util/unsafe.go: -------------------------------------------------------------------------------- 1 | // +build !appengine 2 | 3 | package util 4 | 5 | import ( 6 | "unsafe" 7 | ) 8 | 9 | // BytesToString converts byte slice to string. 10 | func BytesToString(b []byte) string { 11 | return *(*string)(unsafe.Pointer(&b)) 12 | } 13 | 14 | // StringToBytes converts string to byte slice. 15 | func StringToBytes(s string) []byte { 16 | return *(*[]byte)(unsafe.Pointer( 17 | &struct { 18 | string 19 | Cap int 20 | }{s, len(s)}, 21 | )) 22 | } 23 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/iterator.go: -------------------------------------------------------------------------------- 1 | package redis 2 | 3 | import "sync" 4 | 5 | // ScanIterator is used to incrementally iterate over a collection of elements. 6 | // It's safe for concurrent use by multiple goroutines. 7 | type ScanIterator struct { 8 | mu sync.Mutex // protects Scanner and pos 9 | cmd *ScanCmd 10 | pos int 11 | } 12 | 13 | // Err returns the last iterator error, if any. 14 | func (it *ScanIterator) Err() error { 15 | it.mu.Lock() 16 | err := it.cmd.Err() 17 | it.mu.Unlock() 18 | return err 19 | } 20 | 21 | // Next advances the cursor and returns true if more values can be read. 22 | func (it *ScanIterator) Next() bool { 23 | it.mu.Lock() 24 | defer it.mu.Unlock() 25 | 26 | // Instantly return on errors. 27 | if it.cmd.Err() != nil { 28 | return false 29 | } 30 | 31 | // Advance cursor, check if we are still within range. 32 | if it.pos < len(it.cmd.page) { 33 | it.pos++ 34 | return true 35 | } 36 | 37 | for { 38 | // Return if there is no more data to fetch. 39 | if it.cmd.cursor == 0 { 40 | return false 41 | } 42 | 43 | // Fetch next page. 44 | if it.cmd._args[0] == "scan" { 45 | it.cmd._args[1] = it.cmd.cursor 46 | } else { 47 | it.cmd._args[2] = it.cmd.cursor 48 | } 49 | 50 | err := it.cmd.process(it.cmd) 51 | if err != nil { 52 | return false 53 | } 54 | 55 | it.pos = 1 56 | 57 | // Redis can occasionally return empty page. 58 | if len(it.cmd.page) > 0 { 59 | return true 60 | } 61 | } 62 | } 63 | 64 | // Val returns the key/field at the current cursor position. 65 | func (it *ScanIterator) Val() string { 66 | var v string 67 | it.mu.Lock() 68 | if it.cmd.Err() == nil && it.pos > 0 && it.pos <= len(it.cmd.page) { 69 | v = it.cmd.page[it.pos-1] 70 | } 71 | it.mu.Unlock() 72 | return v 73 | } 74 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/pipeline.go: -------------------------------------------------------------------------------- 1 | package redis 2 | 3 | import ( 4 | "sync" 5 | 6 | "github.com/go-redis/redis/internal/pool" 7 | ) 8 | 9 | type pipelineExecer func([]Cmder) error 10 | 11 | // Pipeliner is an mechanism to realise Redis Pipeline technique. 12 | // 13 | // Pipelining is a technique to extremely speed up processing by packing 14 | // operations to batches, send them at once to Redis and read a replies in a 15 | // singe step. 16 | // See https://redis.io/topics/pipelining 17 | // 18 | // Pay attention, that Pipeline is not a transaction, so you can get unexpected 19 | // results in case of big pipelines and small read/write timeouts. 20 | // Redis client has retransmission logic in case of timeouts, pipeline 21 | // can be retransmitted and commands can be executed more then once. 22 | // To avoid this: it is good idea to use reasonable bigger read/write timeouts 23 | // depends of your batch size and/or use TxPipeline. 24 | type Pipeliner interface { 25 | StatefulCmdable 26 | Do(args ...interface{}) *Cmd 27 | Process(cmd Cmder) error 28 | Close() error 29 | Discard() error 30 | Exec() ([]Cmder, error) 31 | } 32 | 33 | var _ Pipeliner = (*Pipeline)(nil) 34 | 35 | // Pipeline implements pipelining as described in 36 | // http://redis.io/topics/pipelining. It's safe for concurrent use 37 | // by multiple goroutines. 38 | type Pipeline struct { 39 | statefulCmdable 40 | 41 | exec pipelineExecer 42 | 43 | mu sync.Mutex 44 | cmds []Cmder 45 | closed bool 46 | } 47 | 48 | func (c *Pipeline) Do(args ...interface{}) *Cmd { 49 | cmd := NewCmd(args...) 50 | _ = c.Process(cmd) 51 | return cmd 52 | } 53 | 54 | // Process queues the cmd for later execution. 55 | func (c *Pipeline) Process(cmd Cmder) error { 56 | c.mu.Lock() 57 | c.cmds = append(c.cmds, cmd) 58 | c.mu.Unlock() 59 | return nil 60 | } 61 | 62 | // Close closes the pipeline, releasing any open resources. 63 | func (c *Pipeline) Close() error { 64 | c.mu.Lock() 65 | c.discard() 66 | c.closed = true 67 | c.mu.Unlock() 68 | return nil 69 | } 70 | 71 | // Discard resets the pipeline and discards queued commands. 72 | func (c *Pipeline) Discard() error { 73 | c.mu.Lock() 74 | err := c.discard() 75 | c.mu.Unlock() 76 | return err 77 | } 78 | 79 | func (c *Pipeline) discard() error { 80 | if c.closed { 81 | return pool.ErrClosed 82 | } 83 | c.cmds = c.cmds[:0] 84 | return nil 85 | } 86 | 87 | // Exec executes all previously queued commands using one 88 | // client-server roundtrip. 89 | // 90 | // Exec always returns list of commands and error of the first failed 91 | // command if any. 92 | func (c *Pipeline) Exec() ([]Cmder, error) { 93 | c.mu.Lock() 94 | defer c.mu.Unlock() 95 | 96 | if c.closed { 97 | return nil, pool.ErrClosed 98 | } 99 | 100 | if len(c.cmds) == 0 { 101 | return nil, nil 102 | } 103 | 104 | cmds := c.cmds 105 | c.cmds = nil 106 | 107 | return cmds, c.exec(cmds) 108 | } 109 | 110 | func (c *Pipeline) pipelined(fn func(Pipeliner) error) ([]Cmder, error) { 111 | if err := fn(c); err != nil { 112 | return nil, err 113 | } 114 | cmds, err := c.Exec() 115 | _ = c.Close() 116 | return cmds, err 117 | } 118 | 119 | func (c *Pipeline) Pipelined(fn func(Pipeliner) error) ([]Cmder, error) { 120 | return c.pipelined(fn) 121 | } 122 | 123 | func (c *Pipeline) Pipeline() Pipeliner { 124 | return c 125 | } 126 | 127 | func (c *Pipeline) TxPipelined(fn func(Pipeliner) error) ([]Cmder, error) { 128 | return c.pipelined(fn) 129 | } 130 | 131 | func (c *Pipeline) TxPipeline() Pipeliner { 132 | return c 133 | } 134 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/script.go: -------------------------------------------------------------------------------- 1 | package redis 2 | 3 | import ( 4 | "crypto/sha1" 5 | "encoding/hex" 6 | "io" 7 | "strings" 8 | ) 9 | 10 | type scripter interface { 11 | Eval(script string, keys []string, args ...interface{}) *Cmd 12 | EvalSha(sha1 string, keys []string, args ...interface{}) *Cmd 13 | ScriptExists(hashes ...string) *BoolSliceCmd 14 | ScriptLoad(script string) *StringCmd 15 | } 16 | 17 | var _ scripter = (*Client)(nil) 18 | var _ scripter = (*Ring)(nil) 19 | var _ scripter = (*ClusterClient)(nil) 20 | 21 | type Script struct { 22 | src, hash string 23 | } 24 | 25 | func NewScript(src string) *Script { 26 | h := sha1.New() 27 | io.WriteString(h, src) 28 | return &Script{ 29 | src: src, 30 | hash: hex.EncodeToString(h.Sum(nil)), 31 | } 32 | } 33 | 34 | func (s *Script) Hash() string { 35 | return s.hash 36 | } 37 | 38 | func (s *Script) Load(c scripter) *StringCmd { 39 | return c.ScriptLoad(s.src) 40 | } 41 | 42 | func (s *Script) Exists(c scripter) *BoolSliceCmd { 43 | return c.ScriptExists(s.hash) 44 | } 45 | 46 | func (s *Script) Eval(c scripter, keys []string, args ...interface{}) *Cmd { 47 | return c.Eval(s.src, keys, args...) 48 | } 49 | 50 | func (s *Script) EvalSha(c scripter, keys []string, args ...interface{}) *Cmd { 51 | return c.EvalSha(s.hash, keys, args...) 52 | } 53 | 54 | // Run optimistically uses EVALSHA to run the script. If script does not exist 55 | // it is retried using EVAL. 56 | func (s *Script) Run(c scripter, keys []string, args ...interface{}) *Cmd { 57 | r := s.EvalSha(c, keys, args...) 58 | if err := r.Err(); err != nil && strings.HasPrefix(err.Error(), "NOSCRIPT ") { 59 | return s.Eval(c, keys, args...) 60 | } 61 | return r 62 | } 63 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/tx.go: -------------------------------------------------------------------------------- 1 | package redis 2 | 3 | import ( 4 | "github.com/go-redis/redis/internal/pool" 5 | "github.com/go-redis/redis/internal/proto" 6 | ) 7 | 8 | // TxFailedErr transaction redis failed. 9 | const TxFailedErr = proto.RedisError("redis: transaction failed") 10 | 11 | // Tx implements Redis transactions as described in 12 | // http://redis.io/topics/transactions. It's NOT safe for concurrent use 13 | // by multiple goroutines, because Exec resets list of watched keys. 14 | // If you don't need WATCH it is better to use Pipeline. 15 | type Tx struct { 16 | statefulCmdable 17 | baseClient 18 | } 19 | 20 | func (c *Client) newTx() *Tx { 21 | tx := Tx{ 22 | baseClient: baseClient{ 23 | opt: c.opt, 24 | connPool: pool.NewStickyConnPool(c.connPool.(*pool.ConnPool), true), 25 | }, 26 | } 27 | tx.baseClient.init() 28 | tx.statefulCmdable.setProcessor(tx.Process) 29 | return &tx 30 | } 31 | 32 | // Watch prepares a transaction and marks the keys to be watched 33 | // for conditional execution if there are any keys. 34 | // 35 | // The transaction is automatically closed when fn exits. 36 | func (c *Client) Watch(fn func(*Tx) error, keys ...string) error { 37 | tx := c.newTx() 38 | if len(keys) > 0 { 39 | if err := tx.Watch(keys...).Err(); err != nil { 40 | _ = tx.Close() 41 | return err 42 | } 43 | } 44 | 45 | err := fn(tx) 46 | _ = tx.Close() 47 | return err 48 | } 49 | 50 | // Close closes the transaction, releasing any open resources. 51 | func (c *Tx) Close() error { 52 | _ = c.Unwatch().Err() 53 | return c.baseClient.Close() 54 | } 55 | 56 | // Watch marks the keys to be watched for conditional execution 57 | // of a transaction. 58 | func (c *Tx) Watch(keys ...string) *StatusCmd { 59 | args := make([]interface{}, 1+len(keys)) 60 | args[0] = "watch" 61 | for i, key := range keys { 62 | args[1+i] = key 63 | } 64 | cmd := NewStatusCmd(args...) 65 | c.Process(cmd) 66 | return cmd 67 | } 68 | 69 | // Unwatch flushes all the previously watched keys for a transaction. 70 | func (c *Tx) Unwatch(keys ...string) *StatusCmd { 71 | args := make([]interface{}, 1+len(keys)) 72 | args[0] = "unwatch" 73 | for i, key := range keys { 74 | args[1+i] = key 75 | } 76 | cmd := NewStatusCmd(args...) 77 | c.Process(cmd) 78 | return cmd 79 | } 80 | 81 | // Pipeline creates a new pipeline. It is more convenient to use Pipelined. 82 | func (c *Tx) Pipeline() Pipeliner { 83 | pipe := Pipeline{ 84 | exec: c.processTxPipeline, 85 | } 86 | pipe.statefulCmdable.setProcessor(pipe.Process) 87 | return &pipe 88 | } 89 | 90 | // Pipelined executes commands queued in the fn in a transaction. 91 | // 92 | // When using WATCH, EXEC will execute commands only if the watched keys 93 | // were not modified, allowing for a check-and-set mechanism. 94 | // 95 | // Exec always returns list of commands. If transaction fails 96 | // TxFailedErr is returned. Otherwise Exec returns an error of the first 97 | // failed command or nil. 98 | func (c *Tx) Pipelined(fn func(Pipeliner) error) ([]Cmder, error) { 99 | return c.Pipeline().Pipelined(fn) 100 | } 101 | 102 | // TxPipelined is an alias for Pipelined. 103 | func (c *Tx) TxPipelined(fn func(Pipeliner) error) ([]Cmder, error) { 104 | return c.Pipelined(fn) 105 | } 106 | 107 | // TxPipeline is an alias for Pipeline. 108 | func (c *Tx) TxPipeline() Pipeliner { 109 | return c.Pipeline() 110 | } 111 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | 24 | .idea/ 25 | *.iml 26 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/AUTHORS: -------------------------------------------------------------------------------- 1 | # This is the official list of Gorilla WebSocket authors for copyright 2 | # purposes. 3 | # 4 | # Please keep the list sorted. 5 | 6 | Gary Burd 7 | Google LLC (https://opensource.google.com/) 8 | Joachim Bauch 9 | 10 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 The Gorilla WebSocket Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are met: 5 | 6 | Redistributions of source code must retain the above copyright notice, this 7 | list of conditions and the following disclaimer. 8 | 9 | Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 17 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 19 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 20 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 21 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 22 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/client_clone.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build go1.8 6 | 7 | package websocket 8 | 9 | import "crypto/tls" 10 | 11 | func cloneTLSConfig(cfg *tls.Config) *tls.Config { 12 | if cfg == nil { 13 | return &tls.Config{} 14 | } 15 | return cfg.Clone() 16 | } 17 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/client_clone_legacy.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build !go1.8 6 | 7 | package websocket 8 | 9 | import "crypto/tls" 10 | 11 | // cloneTLSConfig clones all public fields except the fields 12 | // SessionTicketsDisabled and SessionTicketKey. This avoids copying the 13 | // sync.Mutex in the sync.Once and makes it safe to call cloneTLSConfig on a 14 | // config in active use. 15 | func cloneTLSConfig(cfg *tls.Config) *tls.Config { 16 | if cfg == nil { 17 | return &tls.Config{} 18 | } 19 | return &tls.Config{ 20 | Rand: cfg.Rand, 21 | Time: cfg.Time, 22 | Certificates: cfg.Certificates, 23 | NameToCertificate: cfg.NameToCertificate, 24 | GetCertificate: cfg.GetCertificate, 25 | RootCAs: cfg.RootCAs, 26 | NextProtos: cfg.NextProtos, 27 | ServerName: cfg.ServerName, 28 | ClientAuth: cfg.ClientAuth, 29 | ClientCAs: cfg.ClientCAs, 30 | InsecureSkipVerify: cfg.InsecureSkipVerify, 31 | CipherSuites: cfg.CipherSuites, 32 | PreferServerCipherSuites: cfg.PreferServerCipherSuites, 33 | ClientSessionCache: cfg.ClientSessionCache, 34 | MinVersion: cfg.MinVersion, 35 | MaxVersion: cfg.MaxVersion, 36 | CurvePreferences: cfg.CurvePreferences, 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/conn_write.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build go1.8 6 | 7 | package websocket 8 | 9 | import "net" 10 | 11 | func (c *Conn) writeBufs(bufs ...[]byte) error { 12 | b := net.Buffers(bufs) 13 | _, err := b.WriteTo(c.conn) 14 | return err 15 | } 16 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/conn_write_legacy.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build !go1.8 6 | 7 | package websocket 8 | 9 | func (c *Conn) writeBufs(bufs ...[]byte) error { 10 | for _, buf := range bufs { 11 | if len(buf) > 0 { 12 | if _, err := c.conn.Write(buf); err != nil { 13 | return err 14 | } 15 | } 16 | } 17 | return nil 18 | } 19 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/gorilla/websocket 2 | 3 | go 1.12 4 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/go.sum: -------------------------------------------------------------------------------- 1 | github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= 2 | github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= 3 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/join.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package websocket 6 | 7 | import ( 8 | "io" 9 | "strings" 10 | ) 11 | 12 | // JoinMessages concatenates received messages to create a single io.Reader. 13 | // The string term is appended to each message. The returned reader does not 14 | // support concurrent calls to the Read method. 15 | func JoinMessages(c *Conn, term string) io.Reader { 16 | return &joinReader{c: c, term: term} 17 | } 18 | 19 | type joinReader struct { 20 | c *Conn 21 | term string 22 | r io.Reader 23 | } 24 | 25 | func (r *joinReader) Read(p []byte) (int, error) { 26 | if r.r == nil { 27 | var err error 28 | _, r.r, err = r.c.NextReader() 29 | if err != nil { 30 | return 0, err 31 | } 32 | if r.term != "" { 33 | r.r = io.MultiReader(r.r, strings.NewReader(r.term)) 34 | } 35 | } 36 | n, err := r.r.Read(p) 37 | if err == io.EOF { 38 | err = nil 39 | r.r = nil 40 | } 41 | return n, err 42 | } 43 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/json.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package websocket 6 | 7 | import ( 8 | "encoding/json" 9 | "io" 10 | ) 11 | 12 | // WriteJSON writes the JSON encoding of v as a message. 13 | // 14 | // Deprecated: Use c.WriteJSON instead. 15 | func WriteJSON(c *Conn, v interface{}) error { 16 | return c.WriteJSON(v) 17 | } 18 | 19 | // WriteJSON writes the JSON encoding of v as a message. 20 | // 21 | // See the documentation for encoding/json Marshal for details about the 22 | // conversion of Go values to JSON. 23 | func (c *Conn) WriteJSON(v interface{}) error { 24 | w, err := c.NextWriter(TextMessage) 25 | if err != nil { 26 | return err 27 | } 28 | err1 := json.NewEncoder(w).Encode(v) 29 | err2 := w.Close() 30 | if err1 != nil { 31 | return err1 32 | } 33 | return err2 34 | } 35 | 36 | // ReadJSON reads the next JSON-encoded message from the connection and stores 37 | // it in the value pointed to by v. 38 | // 39 | // Deprecated: Use c.ReadJSON instead. 40 | func ReadJSON(c *Conn, v interface{}) error { 41 | return c.ReadJSON(v) 42 | } 43 | 44 | // ReadJSON reads the next JSON-encoded message from the connection and stores 45 | // it in the value pointed to by v. 46 | // 47 | // See the documentation for the encoding/json Unmarshal function for details 48 | // about the conversion of JSON to a Go value. 49 | func (c *Conn) ReadJSON(v interface{}) error { 50 | _, r, err := c.NextReader() 51 | if err != nil { 52 | return err 53 | } 54 | err = json.NewDecoder(r).Decode(v) 55 | if err == io.EOF { 56 | // One value is expected in the message. 57 | err = io.ErrUnexpectedEOF 58 | } 59 | return err 60 | } 61 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/mask.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Gorilla WebSocket Authors. All rights reserved. Use of 2 | // this source code is governed by a BSD-style license that can be found in the 3 | // LICENSE file. 4 | 5 | // +build !appengine 6 | 7 | package websocket 8 | 9 | import "unsafe" 10 | 11 | const wordSize = int(unsafe.Sizeof(uintptr(0))) 12 | 13 | func maskBytes(key [4]byte, pos int, b []byte) int { 14 | // Mask one byte at a time for small buffers. 15 | if len(b) < 2*wordSize { 16 | for i := range b { 17 | b[i] ^= key[pos&3] 18 | pos++ 19 | } 20 | return pos & 3 21 | } 22 | 23 | // Mask one byte at a time to word boundary. 24 | if n := int(uintptr(unsafe.Pointer(&b[0]))) % wordSize; n != 0 { 25 | n = wordSize - n 26 | for i := range b[:n] { 27 | b[i] ^= key[pos&3] 28 | pos++ 29 | } 30 | b = b[n:] 31 | } 32 | 33 | // Create aligned word size key. 34 | var k [wordSize]byte 35 | for i := range k { 36 | k[i] = key[(pos+i)&3] 37 | } 38 | kw := *(*uintptr)(unsafe.Pointer(&k)) 39 | 40 | // Mask one word at a time. 41 | n := (len(b) / wordSize) * wordSize 42 | for i := 0; i < n; i += wordSize { 43 | *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&b[0])) + uintptr(i))) ^= kw 44 | } 45 | 46 | // Mask one byte at a time for remaining bytes. 47 | b = b[n:] 48 | for i := range b { 49 | b[i] ^= key[pos&3] 50 | pos++ 51 | } 52 | 53 | return pos & 3 54 | } 55 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/mask_safe.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Gorilla WebSocket Authors. All rights reserved. Use of 2 | // this source code is governed by a BSD-style license that can be found in the 3 | // LICENSE file. 4 | 5 | // +build appengine 6 | 7 | package websocket 8 | 9 | func maskBytes(key [4]byte, pos int, b []byte) int { 10 | for i := range b { 11 | b[i] ^= key[pos&3] 12 | pos++ 13 | } 14 | return pos & 3 15 | } 16 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/prepared.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package websocket 6 | 7 | import ( 8 | "bytes" 9 | "net" 10 | "sync" 11 | "time" 12 | ) 13 | 14 | // PreparedMessage caches on the wire representations of a message payload. 15 | // Use PreparedMessage to efficiently send a message payload to multiple 16 | // connections. PreparedMessage is especially useful when compression is used 17 | // because the CPU and memory expensive compression operation can be executed 18 | // once for a given set of compression options. 19 | type PreparedMessage struct { 20 | messageType int 21 | data []byte 22 | mu sync.Mutex 23 | frames map[prepareKey]*preparedFrame 24 | } 25 | 26 | // prepareKey defines a unique set of options to cache prepared frames in PreparedMessage. 27 | type prepareKey struct { 28 | isServer bool 29 | compress bool 30 | compressionLevel int 31 | } 32 | 33 | // preparedFrame contains data in wire representation. 34 | type preparedFrame struct { 35 | once sync.Once 36 | data []byte 37 | } 38 | 39 | // NewPreparedMessage returns an initialized PreparedMessage. You can then send 40 | // it to connection using WritePreparedMessage method. Valid wire 41 | // representation will be calculated lazily only once for a set of current 42 | // connection options. 43 | func NewPreparedMessage(messageType int, data []byte) (*PreparedMessage, error) { 44 | pm := &PreparedMessage{ 45 | messageType: messageType, 46 | frames: make(map[prepareKey]*preparedFrame), 47 | data: data, 48 | } 49 | 50 | // Prepare a plain server frame. 51 | _, frameData, err := pm.frame(prepareKey{isServer: true, compress: false}) 52 | if err != nil { 53 | return nil, err 54 | } 55 | 56 | // To protect against caller modifying the data argument, remember the data 57 | // copied to the plain server frame. 58 | pm.data = frameData[len(frameData)-len(data):] 59 | return pm, nil 60 | } 61 | 62 | func (pm *PreparedMessage) frame(key prepareKey) (int, []byte, error) { 63 | pm.mu.Lock() 64 | frame, ok := pm.frames[key] 65 | if !ok { 66 | frame = &preparedFrame{} 67 | pm.frames[key] = frame 68 | } 69 | pm.mu.Unlock() 70 | 71 | var err error 72 | frame.once.Do(func() { 73 | // Prepare a frame using a 'fake' connection. 74 | // TODO: Refactor code in conn.go to allow more direct construction of 75 | // the frame. 76 | mu := make(chan bool, 1) 77 | mu <- true 78 | var nc prepareConn 79 | c := &Conn{ 80 | conn: &nc, 81 | mu: mu, 82 | isServer: key.isServer, 83 | compressionLevel: key.compressionLevel, 84 | enableWriteCompression: true, 85 | writeBuf: make([]byte, defaultWriteBufferSize+maxFrameHeaderSize), 86 | } 87 | if key.compress { 88 | c.newCompressionWriter = compressNoContextTakeover 89 | } 90 | err = c.WriteMessage(pm.messageType, pm.data) 91 | frame.data = nc.buf.Bytes() 92 | }) 93 | return pm.messageType, frame.data, err 94 | } 95 | 96 | type prepareConn struct { 97 | buf bytes.Buffer 98 | net.Conn 99 | } 100 | 101 | func (pc *prepareConn) Write(p []byte) (int, error) { return pc.buf.Write(p) } 102 | func (pc *prepareConn) SetWriteDeadline(t time.Time) error { return nil } 103 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/proxy.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package websocket 6 | 7 | import ( 8 | "bufio" 9 | "encoding/base64" 10 | "errors" 11 | "net" 12 | "net/http" 13 | "net/url" 14 | "strings" 15 | ) 16 | 17 | type netDialerFunc func(network, addr string) (net.Conn, error) 18 | 19 | func (fn netDialerFunc) Dial(network, addr string) (net.Conn, error) { 20 | return fn(network, addr) 21 | } 22 | 23 | func init() { 24 | proxy_RegisterDialerType("http", func(proxyURL *url.URL, forwardDialer proxy_Dialer) (proxy_Dialer, error) { 25 | return &httpProxyDialer{proxyURL: proxyURL, forwardDial: forwardDialer.Dial}, nil 26 | }) 27 | } 28 | 29 | type httpProxyDialer struct { 30 | proxyURL *url.URL 31 | forwardDial func(network, addr string) (net.Conn, error) 32 | } 33 | 34 | func (hpd *httpProxyDialer) Dial(network string, addr string) (net.Conn, error) { 35 | hostPort, _ := hostPortNoPort(hpd.proxyURL) 36 | conn, err := hpd.forwardDial(network, hostPort) 37 | if err != nil { 38 | return nil, err 39 | } 40 | 41 | connectHeader := make(http.Header) 42 | if user := hpd.proxyURL.User; user != nil { 43 | proxyUser := user.Username() 44 | if proxyPassword, passwordSet := user.Password(); passwordSet { 45 | credential := base64.StdEncoding.EncodeToString([]byte(proxyUser + ":" + proxyPassword)) 46 | connectHeader.Set("Proxy-Authorization", "Basic "+credential) 47 | } 48 | } 49 | 50 | connectReq := &http.Request{ 51 | Method: "CONNECT", 52 | URL: &url.URL{Opaque: addr}, 53 | Host: addr, 54 | Header: connectHeader, 55 | } 56 | 57 | if err := connectReq.Write(conn); err != nil { 58 | conn.Close() 59 | return nil, err 60 | } 61 | 62 | // Read response. It's OK to use and discard buffered reader here becaue 63 | // the remote server does not speak until spoken to. 64 | br := bufio.NewReader(conn) 65 | resp, err := http.ReadResponse(br, connectReq) 66 | if err != nil { 67 | conn.Close() 68 | return nil, err 69 | } 70 | 71 | if resp.StatusCode != 200 { 72 | conn.Close() 73 | f := strings.SplitN(resp.Status, " ", 2) 74 | return nil, errors.New(f[1]) 75 | } 76 | return conn, nil 77 | } 78 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/trace.go: -------------------------------------------------------------------------------- 1 | // +build go1.8 2 | 3 | package websocket 4 | 5 | import ( 6 | "crypto/tls" 7 | "net/http/httptrace" 8 | ) 9 | 10 | func doHandshakeWithTrace(trace *httptrace.ClientTrace, tlsConn *tls.Conn, cfg *tls.Config) error { 11 | if trace.TLSHandshakeStart != nil { 12 | trace.TLSHandshakeStart() 13 | } 14 | err := doHandshake(tlsConn, cfg) 15 | if trace.TLSHandshakeDone != nil { 16 | trace.TLSHandshakeDone(tlsConn.ConnectionState(), err) 17 | } 18 | return err 19 | } 20 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/trace_17.go: -------------------------------------------------------------------------------- 1 | // +build !go1.8 2 | 3 | package websocket 4 | 5 | import ( 6 | "crypto/tls" 7 | "net/http/httptrace" 8 | ) 9 | 10 | func doHandshakeWithTrace(trace *httptrace.ClientTrace, tlsConn *tls.Conn, cfg *tls.Config) error { 11 | return doHandshake(tlsConn, cfg) 12 | } 13 | -------------------------------------------------------------------------------- /vendor/github.com/hashicorp/golang-lru/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | *.test 24 | -------------------------------------------------------------------------------- /vendor/github.com/hashicorp/golang-lru/README.md: -------------------------------------------------------------------------------- 1 | golang-lru 2 | ========== 3 | 4 | This provides the `lru` package which implements a fixed-size 5 | thread safe LRU cache. It is based on the cache in Groupcache. 6 | 7 | Documentation 8 | ============= 9 | 10 | Full docs are available on [Godoc](http://godoc.org/github.com/hashicorp/golang-lru) 11 | 12 | Example 13 | ======= 14 | 15 | Using the LRU is very simple: 16 | 17 | ```go 18 | l, _ := New(128) 19 | for i := 0; i < 256; i++ { 20 | l.Add(i, nil) 21 | } 22 | if l.Len() != 128 { 23 | panic(fmt.Sprintf("bad len: %v", l.Len())) 24 | } 25 | ``` 26 | -------------------------------------------------------------------------------- /vendor/github.com/hashicorp/golang-lru/doc.go: -------------------------------------------------------------------------------- 1 | // Package lru provides three different LRU caches of varying sophistication. 2 | // 3 | // Cache is a simple LRU cache. It is based on the 4 | // LRU implementation in groupcache: 5 | // https://github.com/golang/groupcache/tree/master/lru 6 | // 7 | // TwoQueueCache tracks frequently used and recently used entries separately. 8 | // This avoids a burst of accesses from taking out frequently used entries, 9 | // at the cost of about 2x computational overhead and some extra bookkeeping. 10 | // 11 | // ARCCache is an adaptive replacement cache. It tracks recent evictions as 12 | // well as recent usage in both the frequent and recent caches. Its 13 | // computational overhead is comparable to TwoQueueCache, but the memory 14 | // overhead is linear with the size of the cache. 15 | // 16 | // ARC has been patented by IBM, so do not use it if that is problematic for 17 | // your program. 18 | // 19 | // All caches in this package take locks while operating, and are therefore 20 | // thread-safe for consumers. 21 | package lru 22 | -------------------------------------------------------------------------------- /vendor/github.com/hashicorp/golang-lru/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/hashicorp/golang-lru 2 | -------------------------------------------------------------------------------- /vendor/github.com/hashicorp/golang-lru/lru.go: -------------------------------------------------------------------------------- 1 | package lru 2 | 3 | import ( 4 | "sync" 5 | 6 | "github.com/hashicorp/golang-lru/simplelru" 7 | ) 8 | 9 | // Cache is a thread-safe fixed size LRU cache. 10 | type Cache struct { 11 | lru simplelru.LRUCache 12 | lock sync.RWMutex 13 | } 14 | 15 | // New creates an LRU of the given size. 16 | func New(size int) (*Cache, error) { 17 | return NewWithEvict(size, nil) 18 | } 19 | 20 | // NewWithEvict constructs a fixed size cache with the given eviction 21 | // callback. 22 | func NewWithEvict(size int, onEvicted func(key interface{}, value interface{})) (*Cache, error) { 23 | lru, err := simplelru.NewLRU(size, simplelru.EvictCallback(onEvicted)) 24 | if err != nil { 25 | return nil, err 26 | } 27 | c := &Cache{ 28 | lru: lru, 29 | } 30 | return c, nil 31 | } 32 | 33 | // Purge is used to completely clear the cache. 34 | func (c *Cache) Purge() { 35 | c.lock.Lock() 36 | c.lru.Purge() 37 | c.lock.Unlock() 38 | } 39 | 40 | // Add adds a value to the cache. Returns true if an eviction occurred. 41 | func (c *Cache) Add(key, value interface{}) (evicted bool) { 42 | c.lock.Lock() 43 | defer c.lock.Unlock() 44 | return c.lru.Add(key, value) 45 | } 46 | 47 | // Get looks up a key's value from the cache. 48 | func (c *Cache) Get(key interface{}) (value interface{}, ok bool) { 49 | c.lock.Lock() 50 | defer c.lock.Unlock() 51 | return c.lru.Get(key) 52 | } 53 | 54 | // Contains checks if a key is in the cache, without updating the 55 | // recent-ness or deleting it for being stale. 56 | func (c *Cache) Contains(key interface{}) bool { 57 | c.lock.RLock() 58 | defer c.lock.RUnlock() 59 | return c.lru.Contains(key) 60 | } 61 | 62 | // Peek returns the key value (or undefined if not found) without updating 63 | // the "recently used"-ness of the key. 64 | func (c *Cache) Peek(key interface{}) (value interface{}, ok bool) { 65 | c.lock.RLock() 66 | defer c.lock.RUnlock() 67 | return c.lru.Peek(key) 68 | } 69 | 70 | // ContainsOrAdd checks if a key is in the cache without updating the 71 | // recent-ness or deleting it for being stale, and if not, adds the value. 72 | // Returns whether found and whether an eviction occurred. 73 | func (c *Cache) ContainsOrAdd(key, value interface{}) (ok, evicted bool) { 74 | c.lock.Lock() 75 | defer c.lock.Unlock() 76 | 77 | if c.lru.Contains(key) { 78 | return true, false 79 | } 80 | evicted = c.lru.Add(key, value) 81 | return false, evicted 82 | } 83 | 84 | // Remove removes the provided key from the cache. 85 | func (c *Cache) Remove(key interface{}) { 86 | c.lock.Lock() 87 | c.lru.Remove(key) 88 | c.lock.Unlock() 89 | } 90 | 91 | // RemoveOldest removes the oldest item from the cache. 92 | func (c *Cache) RemoveOldest() { 93 | c.lock.Lock() 94 | c.lru.RemoveOldest() 95 | c.lock.Unlock() 96 | } 97 | 98 | // Keys returns a slice of the keys in the cache, from oldest to newest. 99 | func (c *Cache) Keys() []interface{} { 100 | c.lock.RLock() 101 | defer c.lock.RUnlock() 102 | return c.lru.Keys() 103 | } 104 | 105 | // Len returns the number of items in the cache. 106 | func (c *Cache) Len() int { 107 | c.lock.RLock() 108 | defer c.lock.RUnlock() 109 | return c.lru.Len() 110 | } 111 | -------------------------------------------------------------------------------- /vendor/github.com/hashicorp/golang-lru/simplelru/lru_interface.go: -------------------------------------------------------------------------------- 1 | package simplelru 2 | 3 | // LRUCache is the interface for simple LRU cache. 4 | type LRUCache interface { 5 | // Adds a value to the cache, returns true if an eviction occurred and 6 | // updates the "recently used"-ness of the key. 7 | Add(key, value interface{}) bool 8 | 9 | // Returns key's value from the cache and 10 | // updates the "recently used"-ness of the key. #value, isFound 11 | Get(key interface{}) (value interface{}, ok bool) 12 | 13 | // Check if a key exsists in cache without updating the recent-ness. 14 | Contains(key interface{}) (ok bool) 15 | 16 | // Returns key's value without updating the "recently used"-ness of the key. 17 | Peek(key interface{}) (value interface{}, ok bool) 18 | 19 | // Removes a key from the cache. 20 | Remove(key interface{}) bool 21 | 22 | // Removes the oldest entry from cache. 23 | RemoveOldest() (interface{}, interface{}, bool) 24 | 25 | // Returns the oldest entry from the cache. #key, value, isFound 26 | GetOldest() (interface{}, interface{}, bool) 27 | 28 | // Returns a slice of the keys in the cache, from oldest to newest. 29 | Keys() []interface{} 30 | 31 | // Returns the number of items in the cache. 32 | Len() int 33 | 34 | // Clear all cache entries 35 | Purge() 36 | } 37 | -------------------------------------------------------------------------------- /vendor/github.com/kelseyhightower/envconfig/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.4.x 5 | - 1.5.x 6 | - 1.6.x 7 | - 1.7.x 8 | - 1.8.x 9 | - 1.9.x 10 | - 1.10.x 11 | - 1.11.x 12 | - 1.12.x 13 | - tip 14 | -------------------------------------------------------------------------------- /vendor/github.com/kelseyhightower/envconfig/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 Kelsey Hightower 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 7 | of the Software, and to permit persons to whom the Software is furnished to do 8 | so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /vendor/github.com/kelseyhightower/envconfig/MAINTAINERS: -------------------------------------------------------------------------------- 1 | Kelsey Hightower kelsey.hightower@gmail.com github.com/kelseyhightower 2 | Travis Parker travis.parker@gmail.com github.com/teepark 3 | -------------------------------------------------------------------------------- /vendor/github.com/kelseyhightower/envconfig/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Kelsey Hightower. All rights reserved. 2 | // Use of this source code is governed by the MIT License that can be found in 3 | // the LICENSE file. 4 | 5 | // Package envconfig implements decoding of environment variables based on a user 6 | // defined specification. A typical use is using environment variables for 7 | // configuration settings. 8 | package envconfig 9 | -------------------------------------------------------------------------------- /vendor/github.com/kelseyhightower/envconfig/env_os.go: -------------------------------------------------------------------------------- 1 | // +build appengine go1.5 2 | 3 | package envconfig 4 | 5 | import "os" 6 | 7 | var lookupEnv = os.LookupEnv 8 | -------------------------------------------------------------------------------- /vendor/github.com/kelseyhightower/envconfig/env_syscall.go: -------------------------------------------------------------------------------- 1 | // +build !appengine,!go1.5 2 | 3 | package envconfig 4 | 5 | import "syscall" 6 | 7 | var lookupEnv = syscall.Getenv 8 | -------------------------------------------------------------------------------- /vendor/github.com/kelseyhightower/envconfig/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/kelseyhightower/envconfig 2 | -------------------------------------------------------------------------------- /vendor/github.com/rs/cors/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go: 3 | - "1.10" 4 | - "1.11" 5 | - "1.12" 6 | - tip 7 | matrix: 8 | allow_failures: 9 | - go: tip 10 | -------------------------------------------------------------------------------- /vendor/github.com/rs/cors/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Olivier Poitrey 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is furnished 8 | to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /vendor/github.com/rs/cors/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/rs/cors 2 | -------------------------------------------------------------------------------- /vendor/github.com/rs/cors/utils.go: -------------------------------------------------------------------------------- 1 | package cors 2 | 3 | import "strings" 4 | 5 | const toLower = 'a' - 'A' 6 | 7 | type converter func(string) string 8 | 9 | type wildcard struct { 10 | prefix string 11 | suffix string 12 | } 13 | 14 | func (w wildcard) match(s string) bool { 15 | return len(s) >= len(w.prefix)+len(w.suffix) && strings.HasPrefix(s, w.prefix) && strings.HasSuffix(s, w.suffix) 16 | } 17 | 18 | // convert converts a list of string using the passed converter function 19 | func convert(s []string, c converter) []string { 20 | out := []string{} 21 | for _, i := range s { 22 | out = append(out, c(i)) 23 | } 24 | return out 25 | } 26 | 27 | // parseHeaderList tokenize + normalize a string containing a list of headers 28 | func parseHeaderList(headerList string) []string { 29 | l := len(headerList) 30 | h := make([]byte, 0, l) 31 | upper := true 32 | // Estimate the number headers in order to allocate the right splice size 33 | t := 0 34 | for i := 0; i < l; i++ { 35 | if headerList[i] == ',' { 36 | t++ 37 | } 38 | } 39 | headers := make([]string, 0, t) 40 | for i := 0; i < l; i++ { 41 | b := headerList[i] 42 | switch { 43 | case b >= 'a' && b <= 'z': 44 | if upper { 45 | h = append(h, b-toLower) 46 | } else { 47 | h = append(h, b) 48 | } 49 | case b >= 'A' && b <= 'Z': 50 | if !upper { 51 | h = append(h, b+toLower) 52 | } else { 53 | h = append(h, b) 54 | } 55 | case b == '-' || b == '_' || (b >= '0' && b <= '9'): 56 | h = append(h, b) 57 | } 58 | 59 | if b == ' ' || b == ',' || i == l-1 { 60 | if len(h) > 0 { 61 | // Flush the found header 62 | headers = append(headers, string(h)) 63 | h = h[:0] 64 | upper = true 65 | } 66 | } else { 67 | upper = b == '-' || b == '_' 68 | } 69 | } 70 | return headers 71 | } 72 | -------------------------------------------------------------------------------- /vendor/github.com/segmentio/ksuid/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | *.test 24 | *.prof 25 | /ksuid 26 | 27 | # Emacs 28 | *~ 29 | 30 | # govendor 31 | /vendor/*/ 32 | -------------------------------------------------------------------------------- /vendor/github.com/segmentio/ksuid/LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Segment.io 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/github.com/segmentio/ksuid/rand.go: -------------------------------------------------------------------------------- 1 | package ksuid 2 | 3 | import ( 4 | cryptoRand "crypto/rand" 5 | "encoding/binary" 6 | "io" 7 | "math/rand" 8 | ) 9 | 10 | // FastRander is an io.Reader that uses math/rand and is optimized for 11 | // generating 16 bytes KSUID payloads. It is intended to be used as a 12 | // performance improvements for programs that have no need for 13 | // cryptographically secure KSUIDs and are generating a lot of them. 14 | var FastRander = newRBG() 15 | 16 | func newRBG() io.Reader { 17 | r, err := newRandomBitsGenerator() 18 | if err != nil { 19 | panic(err) 20 | } 21 | return r 22 | } 23 | 24 | func newRandomBitsGenerator() (r io.Reader, err error) { 25 | var seed int64 26 | 27 | if seed, err = readCryptoRandomSeed(); err != nil { 28 | return 29 | } 30 | 31 | r = &randSourceReader{source: rand.NewSource(seed).(rand.Source64)} 32 | return 33 | } 34 | 35 | func readCryptoRandomSeed() (seed int64, err error) { 36 | var b [8]byte 37 | 38 | if _, err = io.ReadFull(cryptoRand.Reader, b[:]); err != nil { 39 | return 40 | } 41 | 42 | seed = int64(binary.LittleEndian.Uint64(b[:])) 43 | return 44 | } 45 | 46 | type randSourceReader struct { 47 | source rand.Source64 48 | } 49 | 50 | func (r *randSourceReader) Read(b []byte) (int, error) { 51 | // optimized for generating 16 bytes payloads 52 | binary.LittleEndian.PutUint64(b[:8], r.source.Uint64()) 53 | binary.LittleEndian.PutUint64(b[8:], r.source.Uint64()) 54 | return 16, nil 55 | } 56 | -------------------------------------------------------------------------------- /vendor/github.com/segmentio/ksuid/sequence.go: -------------------------------------------------------------------------------- 1 | package ksuid 2 | 3 | import ( 4 | "encoding/binary" 5 | "errors" 6 | "math" 7 | ) 8 | 9 | // Sequence is a KSUID generator which produces a sequence of ordered KSUIDs 10 | // from a seed. 11 | // 12 | // Up to 65536 KSUIDs can be generated by for a single seed. 13 | // 14 | // A typical usage of a Sequence looks like this: 15 | // 16 | // seq := ksuid.Sequence{ 17 | // Seed: ksuid.New(), 18 | // } 19 | // id, err := seq.Next() 20 | // 21 | // Sequence values are not safe to use concurrently from multiple goroutines. 22 | type Sequence struct { 23 | // The seed is used as base for the KSUID generator, all generated KSUIDs 24 | // share the same leading 18 bytes of the seed. 25 | Seed KSUID 26 | count uint32 // uint32 for overflow, only 2 bytes are used 27 | } 28 | 29 | // Next produces the next KSUID in the sequence, or returns an error if the 30 | // sequence has been exhausted. 31 | func (seq *Sequence) Next() (KSUID, error) { 32 | id := seq.Seed // copy 33 | count := seq.count 34 | if count > math.MaxUint16 { 35 | return Nil, errors.New("too many IDs were generated") 36 | } 37 | seq.count++ 38 | return withSequenceNumber(id, uint16(count)), nil 39 | } 40 | 41 | // Bounds returns the inclusive min and max bounds of the KSUIDs that may be 42 | // generated by the sequence. If all ids have been generated already then the 43 | // returned min value is equal to the max. 44 | func (seq *Sequence) Bounds() (min KSUID, max KSUID) { 45 | count := seq.count 46 | if count > math.MaxUint16 { 47 | count = math.MaxUint16 48 | } 49 | return withSequenceNumber(seq.Seed, uint16(count)), withSequenceNumber(seq.Seed, math.MaxUint16) 50 | } 51 | 52 | func withSequenceNumber(id KSUID, n uint16) KSUID { 53 | binary.BigEndian.PutUint16(id[len(id)-2:], n) 54 | return id 55 | } 56 | -------------------------------------------------------------------------------- /vendor/github.com/segmentio/ksuid/uint128.go: -------------------------------------------------------------------------------- 1 | package ksuid 2 | 3 | import "fmt" 4 | 5 | // uint128 represents an unsigned 128 bits little endian integer. 6 | type uint128 [2]uint64 7 | 8 | func uint128Payload(ksuid KSUID) uint128 { 9 | return makeUint128FromPayload(ksuid[timestampLengthInBytes:]) 10 | } 11 | 12 | func makeUint128(high uint64, low uint64) uint128 { 13 | return uint128{low, high} 14 | } 15 | 16 | func makeUint128FromPayload(payload []byte) uint128 { 17 | return uint128{ 18 | // low 19 | uint64(payload[8])<<56 | 20 | uint64(payload[9])<<48 | 21 | uint64(payload[10])<<40 | 22 | uint64(payload[11])<<32 | 23 | uint64(payload[12])<<24 | 24 | uint64(payload[13])<<16 | 25 | uint64(payload[14])<<8 | 26 | uint64(payload[15]), 27 | // high 28 | uint64(payload[0])<<56 | 29 | uint64(payload[1])<<48 | 30 | uint64(payload[2])<<40 | 31 | uint64(payload[3])<<32 | 32 | uint64(payload[4])<<24 | 33 | uint64(payload[5])<<16 | 34 | uint64(payload[6])<<8 | 35 | uint64(payload[7]), 36 | } 37 | } 38 | 39 | func (v uint128) ksuid(timestamp uint32) KSUID { 40 | return KSUID{ 41 | // time 42 | byte(timestamp >> 24), 43 | byte(timestamp >> 16), 44 | byte(timestamp >> 8), 45 | byte(timestamp), 46 | 47 | // high 48 | byte(v[1] >> 56), 49 | byte(v[1] >> 48), 50 | byte(v[1] >> 40), 51 | byte(v[1] >> 32), 52 | byte(v[1] >> 24), 53 | byte(v[1] >> 16), 54 | byte(v[1] >> 8), 55 | byte(v[1]), 56 | 57 | // low 58 | byte(v[0] >> 56), 59 | byte(v[0] >> 48), 60 | byte(v[0] >> 40), 61 | byte(v[0] >> 32), 62 | byte(v[0] >> 24), 63 | byte(v[0] >> 16), 64 | byte(v[0] >> 8), 65 | byte(v[0]), 66 | } 67 | } 68 | 69 | func (v uint128) bytes() [16]byte { 70 | return [16]byte{ 71 | // high 72 | byte(v[1] >> 56), 73 | byte(v[1] >> 48), 74 | byte(v[1] >> 40), 75 | byte(v[1] >> 32), 76 | byte(v[1] >> 24), 77 | byte(v[1] >> 16), 78 | byte(v[1] >> 8), 79 | byte(v[1]), 80 | 81 | // low 82 | byte(v[0] >> 56), 83 | byte(v[0] >> 48), 84 | byte(v[0] >> 40), 85 | byte(v[0] >> 32), 86 | byte(v[0] >> 24), 87 | byte(v[0] >> 16), 88 | byte(v[0] >> 8), 89 | byte(v[0]), 90 | } 91 | } 92 | 93 | func (v uint128) String() string { 94 | return fmt.Sprintf("0x%016X%016X", v[0], v[1]) 95 | } 96 | 97 | const wordBitSize = 64 98 | 99 | func cmp128(x, y uint128) int { 100 | if x[1] < y[1] { 101 | return -1 102 | } 103 | if x[1] > y[1] { 104 | return 1 105 | } 106 | if x[0] < y[0] { 107 | return -1 108 | } 109 | if x[0] > y[0] { 110 | return 1 111 | } 112 | return 0 113 | } 114 | 115 | func add128(x, y uint128) (z uint128) { 116 | x0 := x[0] 117 | y0 := y[0] 118 | z0 := x0 + y0 119 | z[0] = z0 120 | 121 | c := (x0&y0 | (x0|y0)&^z0) >> (wordBitSize - 1) 122 | 123 | z[1] = x[1] + y[1] + c 124 | return 125 | } 126 | 127 | func sub128(x, y uint128) (z uint128) { 128 | x0 := x[0] 129 | y0 := y[0] 130 | z0 := x0 - y0 131 | z[0] = z0 132 | 133 | c := (y0&^x0 | (y0|^x0)&z0) >> (wordBitSize - 1) 134 | 135 | z[1] = x[1] - y[1] - c 136 | return 137 | } 138 | 139 | func incr128(x uint128) uint128 { 140 | return add128(x, uint128{1, 0}) 141 | } 142 | -------------------------------------------------------------------------------- /vendor/github.com/tinrab/retry/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | -------------------------------------------------------------------------------- /vendor/github.com/tinrab/retry/.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.dll 4 | *.so 5 | *.dylib 6 | 7 | # Test binary, build with `go test -c` 8 | *.test 9 | 10 | # Output of the go coverage tool, specifically when used with LiteIDE 11 | *.out 12 | 13 | # Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736 14 | .glide/ 15 | -------------------------------------------------------------------------------- /vendor/github.com/tinrab/retry/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Tin Rabzelj 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/github.com/tinrab/retry/README.md: -------------------------------------------------------------------------------- 1 | # Retry 2 | 3 | A simple retry package for Go. 4 | 5 | ## Usage 6 | 7 | Retry 10 times. 8 | 9 | ```go 10 | err := retry.Do(10, thisFunctionMayFail) 11 | if err != nil { 12 | log.Fatal(err) 13 | } 14 | ``` 15 | 16 | Retry with a delay. 17 | 18 | ```go 19 | err := retry.DoSleep(10, 3 * time.Second, thisFunctionMayFail) 20 | if err != nil { 21 | log.Fatal(err) 22 | } 23 | ``` 24 | 25 | Retry forever. 26 | 27 | ```go 28 | retry.DoForever(thisFunctionMayFail) 29 | ``` 30 | -------------------------------------------------------------------------------- /vendor/github.com/tinrab/retry/retry.go: -------------------------------------------------------------------------------- 1 | package retry 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | type RetryFunc func(int) error 8 | 9 | // Do retries calling function f n-times. 10 | // It returns an error if none of the tries succeeds. 11 | func Do(n int, f RetryFunc) (err error) { 12 | for i := 0; i < n; i++ { 13 | err = f(i) 14 | if err == nil { 15 | return nil 16 | } 17 | } 18 | return err 19 | } 20 | 21 | // DoSleep retries calling function f n-times and sleeps for d after each call. 22 | // It returns an error if none of the tries succeeds. 23 | func DoSleep(n int, d time.Duration, f RetryFunc) (err error) { 24 | for i := 0; i < n; i++ { 25 | err = f(i) 26 | if err == nil { 27 | return nil 28 | } 29 | time.Sleep(d) 30 | } 31 | return err 32 | } 33 | 34 | // Forever keeps trying to call function f until it succeeds. 35 | func Forever(f RetryFunc) { 36 | for i := 0; ; i++ { 37 | err := f(i) 38 | if err == nil { 39 | return 40 | } 41 | } 42 | } 43 | 44 | // ForeverSleep keeps trying to call function f until it succeeds, and sleeps after each failure. 45 | func ForeverSleep(d time.Duration, f RetryFunc) { 46 | for i := 0; ; i++ { 47 | err := f(i) 48 | if err == nil { 49 | return 50 | } 51 | time.Sleep(d) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /vendor/github.com/vektah/gqlparser/.gitignore: -------------------------------------------------------------------------------- 1 | /vendor 2 | /validator/imported/node_modules 3 | /validator/imported/graphql-js 4 | 5 | .idea/ 6 | -------------------------------------------------------------------------------- /vendor/github.com/vektah/gqlparser/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 Adam Scarr 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. -------------------------------------------------------------------------------- /vendor/github.com/vektah/gqlparser/ast/argmap.go: -------------------------------------------------------------------------------- 1 | package ast 2 | 3 | func arg2map(defs ArgumentDefinitionList, args ArgumentList, vars map[string]interface{}) map[string]interface{} { 4 | result := map[string]interface{}{} 5 | var err error 6 | 7 | for _, argDef := range defs { 8 | var val interface{} 9 | var hasValue bool 10 | 11 | if argValue := args.ForName(argDef.Name); argValue != nil { 12 | if argValue.Value.Kind == Variable { 13 | val, hasValue = vars[argValue.Value.Raw] 14 | } else { 15 | val, err = argValue.Value.Value(vars) 16 | if err != nil { 17 | panic(err) 18 | } 19 | hasValue = true 20 | } 21 | } 22 | 23 | if !hasValue && argDef.DefaultValue != nil { 24 | val, err = argDef.DefaultValue.Value(vars) 25 | if err != nil { 26 | panic(err) 27 | } 28 | hasValue = true 29 | } 30 | 31 | if hasValue { 32 | result[argDef.Name] = val 33 | } 34 | } 35 | 36 | return result 37 | } 38 | -------------------------------------------------------------------------------- /vendor/github.com/vektah/gqlparser/ast/collections.go: -------------------------------------------------------------------------------- 1 | package ast 2 | 3 | type FieldList []*FieldDefinition 4 | 5 | func (l FieldList) ForName(name string) *FieldDefinition { 6 | for _, it := range l { 7 | if it.Name == name { 8 | return it 9 | } 10 | } 11 | return nil 12 | } 13 | 14 | type EnumValueList []*EnumValueDefinition 15 | 16 | func (l EnumValueList) ForName(name string) *EnumValueDefinition { 17 | for _, it := range l { 18 | if it.Name == name { 19 | return it 20 | } 21 | } 22 | return nil 23 | } 24 | 25 | type DirectiveList []*Directive 26 | 27 | func (l DirectiveList) ForName(name string) *Directive { 28 | for _, it := range l { 29 | if it.Name == name { 30 | return it 31 | } 32 | } 33 | return nil 34 | } 35 | 36 | func (l DirectiveList) ForNames(name string) []*Directive { 37 | resp := []*Directive{} 38 | for _, it := range l { 39 | if it.Name == name { 40 | resp = append(resp, it) 41 | } 42 | } 43 | return resp 44 | } 45 | 46 | type OperationList []*OperationDefinition 47 | 48 | func (l OperationList) ForName(name string) *OperationDefinition { 49 | if name == "" && len(l) == 1 { 50 | return l[0] 51 | } 52 | for _, it := range l { 53 | if it.Name == name { 54 | return it 55 | } 56 | } 57 | return nil 58 | } 59 | 60 | type FragmentDefinitionList []*FragmentDefinition 61 | 62 | func (l FragmentDefinitionList) ForName(name string) *FragmentDefinition { 63 | for _, it := range l { 64 | if it.Name == name { 65 | return it 66 | } 67 | } 68 | return nil 69 | } 70 | 71 | type VariableDefinitionList []*VariableDefinition 72 | 73 | func (l VariableDefinitionList) ForName(name string) *VariableDefinition { 74 | for _, it := range l { 75 | if it.Variable == name { 76 | return it 77 | } 78 | } 79 | return nil 80 | } 81 | 82 | type ArgumentList []*Argument 83 | 84 | func (l ArgumentList) ForName(name string) *Argument { 85 | for _, it := range l { 86 | if it.Name == name { 87 | return it 88 | } 89 | } 90 | return nil 91 | } 92 | 93 | type ArgumentDefinitionList []*ArgumentDefinition 94 | 95 | func (l ArgumentDefinitionList) ForName(name string) *ArgumentDefinition { 96 | for _, it := range l { 97 | if it.Name == name { 98 | return it 99 | } 100 | } 101 | return nil 102 | } 103 | 104 | type SchemaDefinitionList []*SchemaDefinition 105 | 106 | type DirectiveDefinitionList []*DirectiveDefinition 107 | 108 | func (l DirectiveDefinitionList) ForName(name string) *DirectiveDefinition { 109 | for _, it := range l { 110 | if it.Name == name { 111 | return it 112 | } 113 | } 114 | return nil 115 | } 116 | 117 | type DefinitionList []*Definition 118 | 119 | func (l DefinitionList) ForName(name string) *Definition { 120 | for _, it := range l { 121 | if it.Name == name { 122 | return it 123 | } 124 | } 125 | return nil 126 | } 127 | 128 | type OperationTypeDefinitionList []*OperationTypeDefinition 129 | 130 | func (l OperationTypeDefinitionList) ForType(name string) *OperationTypeDefinition { 131 | for _, it := range l { 132 | if it.Type == name { 133 | return it 134 | } 135 | } 136 | return nil 137 | } 138 | 139 | type ChildValueList []*ChildValue 140 | 141 | func (v ChildValueList) ForName(name string) *Value { 142 | for _, f := range v { 143 | if f.Name == name { 144 | return f.Value 145 | } 146 | } 147 | return nil 148 | } 149 | -------------------------------------------------------------------------------- /vendor/github.com/vektah/gqlparser/ast/definition.go: -------------------------------------------------------------------------------- 1 | package ast 2 | 3 | type DefinitionKind string 4 | 5 | const ( 6 | Scalar DefinitionKind = "SCALAR" 7 | Object DefinitionKind = "OBJECT" 8 | Interface DefinitionKind = "INTERFACE" 9 | Union DefinitionKind = "UNION" 10 | Enum DefinitionKind = "ENUM" 11 | InputObject DefinitionKind = "INPUT_OBJECT" 12 | ) 13 | 14 | // ObjectDefinition is the core type definition object, it includes all of the definable types 15 | // but does *not* cover schema or directives. 16 | // 17 | // @vektah: Javascript implementation has different types for all of these, but they are 18 | // more similar than different and don't define any behaviour. I think this style of 19 | // "some hot" struct works better, at least for go. 20 | // 21 | // Type extensions are also represented by this same struct. 22 | type Definition struct { 23 | Kind DefinitionKind 24 | Description string 25 | Name string 26 | Directives DirectiveList 27 | Interfaces []string // object and input object 28 | Fields FieldList // object and input object 29 | Types []string // union 30 | EnumValues EnumValueList // enum 31 | 32 | Position *Position `dump:"-"` 33 | BuiltIn bool `dump:"-"` 34 | } 35 | 36 | func (d *Definition) IsLeafType() bool { 37 | return d.Kind == Enum || d.Kind == Scalar 38 | } 39 | 40 | func (d *Definition) IsAbstractType() bool { 41 | return d.Kind == Interface || d.Kind == Union 42 | } 43 | 44 | func (d *Definition) IsCompositeType() bool { 45 | return d.Kind == Object || d.Kind == Interface || d.Kind == Union 46 | } 47 | 48 | func (d *Definition) IsInputType() bool { 49 | return d.Kind == Scalar || d.Kind == Enum || d.Kind == InputObject 50 | } 51 | 52 | func (d *Definition) OneOf(types ...string) bool { 53 | for _, t := range types { 54 | if d.Name == t { 55 | return true 56 | } 57 | } 58 | return false 59 | } 60 | 61 | type FieldDefinition struct { 62 | Description string 63 | Name string 64 | Arguments ArgumentDefinitionList // only for objects 65 | DefaultValue *Value // only for input objects 66 | Type *Type 67 | Directives DirectiveList 68 | Position *Position `dump:"-"` 69 | } 70 | 71 | type ArgumentDefinition struct { 72 | Description string 73 | Name string 74 | DefaultValue *Value 75 | Type *Type 76 | Directives DirectiveList 77 | Position *Position `dump:"-"` 78 | } 79 | 80 | type EnumValueDefinition struct { 81 | Description string 82 | Name string 83 | Directives DirectiveList 84 | Position *Position `dump:"-"` 85 | } 86 | 87 | type DirectiveDefinition struct { 88 | Description string 89 | Name string 90 | Arguments ArgumentDefinitionList 91 | Locations []DirectiveLocation 92 | Position *Position `dump:"-"` 93 | } 94 | -------------------------------------------------------------------------------- /vendor/github.com/vektah/gqlparser/ast/directive.go: -------------------------------------------------------------------------------- 1 | package ast 2 | 3 | type DirectiveLocation string 4 | 5 | const ( 6 | // Executable 7 | LocationQuery DirectiveLocation = `QUERY` 8 | LocationMutation DirectiveLocation = `MUTATION` 9 | LocationSubscription DirectiveLocation = `SUBSCRIPTION` 10 | LocationField DirectiveLocation = `FIELD` 11 | LocationFragmentDefinition DirectiveLocation = `FRAGMENT_DEFINITION` 12 | LocationFragmentSpread DirectiveLocation = `FRAGMENT_SPREAD` 13 | LocationInlineFragment DirectiveLocation = `INLINE_FRAGMENT` 14 | 15 | // Type System 16 | LocationSchema DirectiveLocation = `SCHEMA` 17 | LocationScalar DirectiveLocation = `SCALAR` 18 | LocationObject DirectiveLocation = `OBJECT` 19 | LocationFieldDefinition DirectiveLocation = `FIELD_DEFINITION` 20 | LocationArgumentDefinition DirectiveLocation = `ARGUMENT_DEFINITION` 21 | LocationInterface DirectiveLocation = `INTERFACE` 22 | LocationUnion DirectiveLocation = `UNION` 23 | LocationEnum DirectiveLocation = `ENUM` 24 | LocationEnumValue DirectiveLocation = `ENUM_VALUE` 25 | LocationInputObject DirectiveLocation = `INPUT_OBJECT` 26 | LocationInputFieldDefinition DirectiveLocation = `INPUT_FIELD_DEFINITION` 27 | ) 28 | 29 | type Directive struct { 30 | Name string 31 | Arguments ArgumentList 32 | Position *Position `dump:"-"` 33 | 34 | // Requires validation 35 | ParentDefinition *Definition 36 | Definition *DirectiveDefinition 37 | Location DirectiveLocation 38 | } 39 | 40 | func (d *Directive) ArgumentMap(vars map[string]interface{}) map[string]interface{} { 41 | return arg2map(d.Definition.Arguments, d.Arguments, vars) 42 | } 43 | -------------------------------------------------------------------------------- /vendor/github.com/vektah/gqlparser/ast/document.go: -------------------------------------------------------------------------------- 1 | package ast 2 | 3 | type QueryDocument struct { 4 | Operations OperationList 5 | Fragments FragmentDefinitionList 6 | Position *Position `dump:"-"` 7 | } 8 | 9 | type SchemaDocument struct { 10 | Schema SchemaDefinitionList 11 | SchemaExtension SchemaDefinitionList 12 | Directives DirectiveDefinitionList 13 | Definitions DefinitionList 14 | Extensions DefinitionList 15 | Position *Position `dump:"-"` 16 | } 17 | 18 | func (d *SchemaDocument) Merge(other *SchemaDocument) { 19 | d.Schema = append(d.Schema, other.Schema...) 20 | d.SchemaExtension = append(d.SchemaExtension, other.SchemaExtension...) 21 | d.Directives = append(d.Directives, other.Directives...) 22 | d.Definitions = append(d.Definitions, other.Definitions...) 23 | d.Extensions = append(d.Extensions, other.Extensions...) 24 | } 25 | 26 | type Schema struct { 27 | Query *Definition 28 | Mutation *Definition 29 | Subscription *Definition 30 | 31 | Types map[string]*Definition 32 | Directives map[string]*DirectiveDefinition 33 | 34 | PossibleTypes map[string][]*Definition 35 | Implements map[string][]*Definition 36 | } 37 | 38 | func (s *Schema) AddPossibleType(name string, def *Definition) { 39 | s.PossibleTypes[name] = append(s.PossibleTypes[name], def) 40 | } 41 | 42 | // GetPossibleTypes will enumerate all the definitions for a given interface or union 43 | func (s *Schema) GetPossibleTypes(def *Definition) []*Definition { 44 | return s.PossibleTypes[def.Name] 45 | } 46 | 47 | func (s *Schema) AddImplements(name string, iface *Definition) { 48 | s.Implements[name] = append(s.Implements[name], iface) 49 | } 50 | 51 | // GetImplements returns all the interface and union definitions that the given definition satisfies 52 | func (s *Schema) GetImplements(def *Definition) []*Definition { 53 | return s.Implements[def.Name] 54 | } 55 | 56 | type SchemaDefinition struct { 57 | Description string 58 | Directives DirectiveList 59 | OperationTypes OperationTypeDefinitionList 60 | Position *Position `dump:"-"` 61 | } 62 | 63 | type OperationTypeDefinition struct { 64 | Operation Operation 65 | Type string 66 | Position *Position `dump:"-"` 67 | } 68 | -------------------------------------------------------------------------------- /vendor/github.com/vektah/gqlparser/ast/fragment.go: -------------------------------------------------------------------------------- 1 | package ast 2 | 3 | type FragmentSpread struct { 4 | Name string 5 | Directives DirectiveList 6 | 7 | // Require validation 8 | ObjectDefinition *Definition 9 | Definition *FragmentDefinition 10 | 11 | Position *Position `dump:"-"` 12 | } 13 | 14 | type InlineFragment struct { 15 | TypeCondition string 16 | Directives DirectiveList 17 | SelectionSet SelectionSet 18 | 19 | // Require validation 20 | ObjectDefinition *Definition 21 | 22 | Position *Position `dump:"-"` 23 | } 24 | 25 | type FragmentDefinition struct { 26 | Name string 27 | // Note: fragment variable definitions are experimental and may be changed 28 | // or removed in the future. 29 | VariableDefinition VariableDefinitionList 30 | TypeCondition string 31 | Directives DirectiveList 32 | SelectionSet SelectionSet 33 | 34 | // Require validation 35 | Definition *Definition 36 | 37 | Position *Position `dump:"-"` 38 | } 39 | -------------------------------------------------------------------------------- /vendor/github.com/vektah/gqlparser/ast/operation.go: -------------------------------------------------------------------------------- 1 | package ast 2 | 3 | type Operation string 4 | 5 | const ( 6 | Query Operation = "query" 7 | Mutation Operation = "mutation" 8 | Subscription Operation = "subscription" 9 | ) 10 | 11 | type OperationDefinition struct { 12 | Operation Operation 13 | Name string 14 | VariableDefinitions VariableDefinitionList 15 | Directives DirectiveList 16 | SelectionSet SelectionSet 17 | Position *Position `dump:"-"` 18 | } 19 | 20 | type VariableDefinition struct { 21 | Variable string 22 | Type *Type 23 | DefaultValue *Value 24 | Position *Position `dump:"-"` 25 | 26 | // Requires validation 27 | Definition *Definition 28 | Used bool `dump:"-"` 29 | } 30 | -------------------------------------------------------------------------------- /vendor/github.com/vektah/gqlparser/ast/selection.go: -------------------------------------------------------------------------------- 1 | package ast 2 | 3 | type SelectionSet []Selection 4 | 5 | type Selection interface { 6 | isSelection() 7 | GetPosition() *Position 8 | } 9 | 10 | func (*Field) isSelection() {} 11 | func (*FragmentSpread) isSelection() {} 12 | func (*InlineFragment) isSelection() {} 13 | 14 | func (s *Field) GetPosition() *Position { return s.Position } 15 | func (s *FragmentSpread) GetPosition() *Position { return s.Position } 16 | func (s *InlineFragment) GetPosition() *Position { return s.Position } 17 | 18 | type Field struct { 19 | Alias string 20 | Name string 21 | Arguments ArgumentList 22 | Directives DirectiveList 23 | SelectionSet SelectionSet 24 | Position *Position `dump:"-"` 25 | 26 | // Require validation 27 | Definition *FieldDefinition 28 | ObjectDefinition *Definition 29 | } 30 | 31 | type Argument struct { 32 | Name string 33 | Value *Value 34 | Position *Position `dump:"-"` 35 | } 36 | 37 | func (f *Field) ArgumentMap(vars map[string]interface{}) map[string]interface{} { 38 | return arg2map(f.Definition.Arguments, f.Arguments, vars) 39 | } 40 | -------------------------------------------------------------------------------- /vendor/github.com/vektah/gqlparser/ast/source.go: -------------------------------------------------------------------------------- 1 | package ast 2 | 3 | // Source covers a single *.graphql file 4 | type Source struct { 5 | // Name is the filename of the source 6 | Name string 7 | // Input is the actual contents of the source file 8 | Input string 9 | // BuiltIn indicate whether the source is a part of the specification 10 | BuiltIn bool 11 | } 12 | 13 | type Position struct { 14 | Start int // The starting position, in runes, of this token in the input. 15 | End int // The end position, in runes, of this token in the input. 16 | Line int // The line number at the start of this item. 17 | Column int // The column number at the start of this item. 18 | Src *Source // The source document this token belongs to 19 | } 20 | -------------------------------------------------------------------------------- /vendor/github.com/vektah/gqlparser/ast/type.go: -------------------------------------------------------------------------------- 1 | package ast 2 | 3 | func NonNullNamedType(named string, pos *Position) *Type { 4 | return &Type{NamedType: named, NonNull: true, Position: pos} 5 | } 6 | 7 | func NamedType(named string, pos *Position) *Type { 8 | return &Type{NamedType: named, NonNull: false, Position: pos} 9 | } 10 | 11 | func NonNullListType(elem *Type, pos *Position) *Type { 12 | return &Type{Elem: elem, NonNull: true, Position: pos} 13 | } 14 | 15 | func ListType(elem *Type, pos *Position) *Type { 16 | return &Type{Elem: elem, NonNull: false, Position: pos} 17 | } 18 | 19 | type Type struct { 20 | NamedType string 21 | Elem *Type 22 | NonNull bool 23 | Position *Position `dump:"-"` 24 | } 25 | 26 | func (t *Type) Name() string { 27 | if t.NamedType != "" { 28 | return t.NamedType 29 | } 30 | 31 | return t.Elem.Name() 32 | } 33 | 34 | func (t *Type) String() string { 35 | nn := "" 36 | if t.NonNull { 37 | nn = "!" 38 | } 39 | if t.NamedType != "" { 40 | return t.NamedType + nn 41 | } 42 | 43 | return "[" + t.Elem.String() + "]" + nn 44 | } 45 | 46 | func (t *Type) IsCompatible(other *Type) bool { 47 | if t.NamedType != other.NamedType { 48 | return false 49 | } 50 | 51 | if t.Elem != nil && other.Elem == nil { 52 | return false 53 | } 54 | 55 | if t.Elem != nil && !t.Elem.IsCompatible(other.Elem) { 56 | return false 57 | } 58 | 59 | if other.NonNull { 60 | return t.NonNull 61 | } 62 | 63 | return true 64 | } 65 | 66 | func (v *Type) Dump() string { 67 | return v.String() 68 | } 69 | -------------------------------------------------------------------------------- /vendor/github.com/vektah/gqlparser/ast/value.go: -------------------------------------------------------------------------------- 1 | package ast 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | "strings" 7 | ) 8 | 9 | type ValueKind int 10 | 11 | const ( 12 | Variable ValueKind = iota 13 | IntValue 14 | FloatValue 15 | StringValue 16 | BlockValue 17 | BooleanValue 18 | NullValue 19 | EnumValue 20 | ListValue 21 | ObjectValue 22 | ) 23 | 24 | type Value struct { 25 | Raw string 26 | Children ChildValueList 27 | Kind ValueKind 28 | Position *Position `dump:"-"` 29 | 30 | // Require validation 31 | Definition *Definition 32 | VariableDefinition *VariableDefinition 33 | ExpectedType *Type 34 | } 35 | 36 | type ChildValue struct { 37 | Name string 38 | Value *Value 39 | Position *Position `dump:"-"` 40 | } 41 | 42 | func (v *Value) Value(vars map[string]interface{}) (interface{}, error) { 43 | if v == nil { 44 | return nil, nil 45 | } 46 | switch v.Kind { 47 | case Variable: 48 | if value, ok := vars[v.Raw]; ok { 49 | return value, nil 50 | } 51 | if v.VariableDefinition != nil && v.VariableDefinition.DefaultValue != nil { 52 | return v.VariableDefinition.DefaultValue.Value(vars) 53 | } 54 | return nil, nil 55 | case IntValue: 56 | return strconv.ParseInt(v.Raw, 10, 64) 57 | case FloatValue: 58 | return strconv.ParseFloat(v.Raw, 64) 59 | case StringValue, BlockValue, EnumValue: 60 | return v.Raw, nil 61 | case BooleanValue: 62 | return strconv.ParseBool(v.Raw) 63 | case NullValue: 64 | return nil, nil 65 | case ListValue: 66 | var val []interface{} 67 | for _, elem := range v.Children { 68 | elemVal, err := elem.Value.Value(vars) 69 | if err != nil { 70 | return val, err 71 | } 72 | val = append(val, elemVal) 73 | } 74 | return val, nil 75 | case ObjectValue: 76 | val := map[string]interface{}{} 77 | for _, elem := range v.Children { 78 | elemVal, err := elem.Value.Value(vars) 79 | if err != nil { 80 | return val, err 81 | } 82 | val[elem.Name] = elemVal 83 | } 84 | return val, nil 85 | default: 86 | panic(fmt.Errorf("unknown value kind %d", v.Kind)) 87 | } 88 | } 89 | 90 | func (v *Value) String() string { 91 | if v == nil { 92 | return "" 93 | } 94 | switch v.Kind { 95 | case Variable: 96 | return "$" + v.Raw 97 | case IntValue, FloatValue, EnumValue, BooleanValue, NullValue: 98 | return v.Raw 99 | case StringValue, BlockValue: 100 | return strconv.Quote(v.Raw) 101 | case ListValue: 102 | var val []string 103 | for _, elem := range v.Children { 104 | val = append(val, elem.Value.String()) 105 | } 106 | return "[" + strings.Join(val, ",") + "]" 107 | case ObjectValue: 108 | var val []string 109 | for _, elem := range v.Children { 110 | val = append(val, elem.Name+":"+elem.Value.String()) 111 | } 112 | return "{" + strings.Join(val, ",") + "}" 113 | default: 114 | panic(fmt.Errorf("unknown value kind %d", v.Kind)) 115 | } 116 | } 117 | 118 | func (v *Value) Dump() string { 119 | return v.String() 120 | } 121 | -------------------------------------------------------------------------------- /vendor/github.com/vektah/gqlparser/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/vektah/gqlparser 2 | 3 | go 1.12 4 | 5 | require ( 6 | github.com/agnivade/levenshtein v1.0.1 7 | github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 8 | github.com/sergi/go-diff v1.0.0 // indirect 9 | github.com/stretchr/testify v1.3.0 10 | golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6 11 | gopkg.in/yaml.v2 v2.2.2 12 | ) 13 | -------------------------------------------------------------------------------- /vendor/github.com/vektah/gqlparser/go.sum: -------------------------------------------------------------------------------- 1 | github.com/agnivade/levenshtein v1.0.1 h1:3oJU7J3FGFmyhn8KHjmVaZCN5hxTr7GxgRue+sxIXdQ= 2 | github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= 3 | github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ= 4 | github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= 5 | github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= 6 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 7 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 8 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 9 | github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= 10 | github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= 11 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 12 | github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= 13 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 14 | golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6 h1:iZgcI2DDp6zW5v9Z/5+f0NuqoxNdmzg4hivjk2WLXpY= 15 | golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 16 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 17 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 18 | gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= 19 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 20 | -------------------------------------------------------------------------------- /vendor/github.com/vektah/gqlparser/gqlerror/error.go: -------------------------------------------------------------------------------- 1 | package gqlerror 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "strconv" 7 | 8 | "github.com/vektah/gqlparser/ast" 9 | ) 10 | 11 | // Error is the standard graphql error type described in https://facebook.github.io/graphql/draft/#sec-Errors 12 | type Error struct { 13 | Message string `json:"message"` 14 | Path []interface{} `json:"path,omitempty"` 15 | Locations []Location `json:"locations,omitempty"` 16 | Extensions map[string]interface{} `json:"extensions,omitempty"` 17 | Rule string `json:"-"` 18 | } 19 | 20 | func (err *Error) SetFile(file string) { 21 | if file == "" { 22 | return 23 | } 24 | if err.Extensions == nil { 25 | err.Extensions = map[string]interface{}{} 26 | } 27 | 28 | err.Extensions["file"] = file 29 | } 30 | 31 | type Location struct { 32 | Line int `json:"line,omitempty"` 33 | Column int `json:"column,omitempty"` 34 | } 35 | 36 | type List []*Error 37 | 38 | func (err *Error) Error() string { 39 | var res bytes.Buffer 40 | if err == nil { 41 | return "" 42 | } 43 | filename, _ := err.Extensions["file"].(string) 44 | if filename == "" { 45 | filename = "input" 46 | } 47 | res.WriteString(filename) 48 | 49 | if len(err.Locations) > 0 { 50 | res.WriteByte(':') 51 | res.WriteString(strconv.Itoa(err.Locations[0].Line)) 52 | } 53 | 54 | res.WriteString(": ") 55 | if ps := err.pathString(); ps != "" { 56 | res.WriteString(ps) 57 | res.WriteByte(' ') 58 | } 59 | 60 | res.WriteString(err.Message) 61 | 62 | return res.String() 63 | } 64 | 65 | func (err Error) pathString() string { 66 | var str bytes.Buffer 67 | for i, v := range err.Path { 68 | 69 | switch v := v.(type) { 70 | case int, int64: 71 | str.WriteString(fmt.Sprintf("[%d]", v)) 72 | default: 73 | if i != 0 { 74 | str.WriteByte('.') 75 | } 76 | str.WriteString(fmt.Sprint(v)) 77 | } 78 | } 79 | return str.String() 80 | } 81 | 82 | func (errs List) Error() string { 83 | var buf bytes.Buffer 84 | for _, err := range errs { 85 | buf.WriteString(err.Error()) 86 | buf.WriteByte('\n') 87 | } 88 | return buf.String() 89 | } 90 | 91 | func WrapPath(path []interface{}, err error) *Error { 92 | return &Error{ 93 | Message: err.Error(), 94 | Path: path, 95 | } 96 | } 97 | 98 | func Errorf(message string, args ...interface{}) *Error { 99 | return &Error{ 100 | Message: fmt.Sprintf(message, args...), 101 | } 102 | } 103 | 104 | func ErrorPathf(path []interface{}, message string, args ...interface{}) *Error { 105 | return &Error{ 106 | Message: fmt.Sprintf(message, args...), 107 | Path: path, 108 | } 109 | } 110 | 111 | func ErrorPosf(pos *ast.Position, message string, args ...interface{}) *Error { 112 | return ErrorLocf( 113 | pos.Src.Name, 114 | pos.Line, 115 | pos.Column, 116 | message, 117 | args..., 118 | ) 119 | } 120 | 121 | func ErrorLocf(file string, line int, col int, message string, args ...interface{}) *Error { 122 | var extensions map[string]interface{} 123 | if file != "" { 124 | extensions = map[string]interface{}{"file": file} 125 | } 126 | return &Error{ 127 | Message: fmt.Sprintf(message, args...), 128 | Extensions: extensions, 129 | Locations: []Location{ 130 | {Line: line, Column: col}, 131 | }, 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /vendor/github.com/vektah/gqlparser/gqlparser.go: -------------------------------------------------------------------------------- 1 | package gqlparser 2 | 3 | import ( 4 | "github.com/vektah/gqlparser/ast" 5 | "github.com/vektah/gqlparser/gqlerror" 6 | "github.com/vektah/gqlparser/parser" 7 | "github.com/vektah/gqlparser/validator" 8 | _ "github.com/vektah/gqlparser/validator/rules" 9 | ) 10 | 11 | func LoadSchema(str ...*ast.Source) (*ast.Schema, *gqlerror.Error) { 12 | return validator.LoadSchema(append([]*ast.Source{validator.Prelude}, str...)...) 13 | } 14 | 15 | func MustLoadSchema(str ...*ast.Source) *ast.Schema { 16 | s, err := validator.LoadSchema(append([]*ast.Source{validator.Prelude}, str...)...) 17 | if err != nil { 18 | panic(err) 19 | } 20 | return s 21 | } 22 | 23 | func LoadQuery(schema *ast.Schema, str string) (*ast.QueryDocument, gqlerror.List) { 24 | query, err := parser.ParseQuery(&ast.Source{Input: str}) 25 | if err != nil { 26 | return nil, gqlerror.List{err} 27 | } 28 | errs := validator.Validate(schema, query) 29 | if errs != nil { 30 | return nil, errs 31 | } 32 | 33 | return query, nil 34 | } 35 | 36 | func MustLoadQuery(schema *ast.Schema, str string) *ast.QueryDocument { 37 | q, err := LoadQuery(schema, str) 38 | if err != nil { 39 | panic(err) 40 | } 41 | return q 42 | } 43 | -------------------------------------------------------------------------------- /vendor/github.com/vektah/gqlparser/lexer/blockstring.go: -------------------------------------------------------------------------------- 1 | package lexer 2 | 3 | import ( 4 | "math" 5 | "strings" 6 | ) 7 | 8 | // blockStringValue produces the value of a block string from its parsed raw value, similar to 9 | // Coffeescript's block string, Python's docstring trim or Ruby's strip_heredoc. 10 | // 11 | // This implements the GraphQL spec's BlockStringValue() static algorithm. 12 | func blockStringValue(raw string) string { 13 | lines := strings.Split(raw, "\n") 14 | 15 | commonIndent := math.MaxInt32 16 | for _, line := range lines { 17 | indent := leadingWhitespace(line) 18 | if indent < len(line) && indent < commonIndent { 19 | commonIndent = indent 20 | if commonIndent == 0 { 21 | break 22 | } 23 | } 24 | } 25 | 26 | if commonIndent != math.MaxInt32 && len(lines) > 0 { 27 | for i := 1; i < len(lines); i++ { 28 | if len(lines[i]) < commonIndent { 29 | lines[i] = "" 30 | } else { 31 | lines[i] = lines[i][commonIndent:] 32 | } 33 | } 34 | } 35 | 36 | start := 0 37 | end := len(lines) 38 | 39 | for start < end && leadingWhitespace(lines[start]) == math.MaxInt32 { 40 | start++ 41 | } 42 | 43 | for start < end && leadingWhitespace(lines[end-1]) == math.MaxInt32 { 44 | end-- 45 | } 46 | 47 | return strings.Join(lines[start:end], "\n") 48 | } 49 | 50 | func leadingWhitespace(str string) int { 51 | for i, r := range str { 52 | if r != ' ' && r != '\t' { 53 | return i 54 | } 55 | } 56 | // this line is made up entirely of whitespace, its leading whitespace doesnt count. 57 | return math.MaxInt32 58 | } 59 | -------------------------------------------------------------------------------- /vendor/github.com/vektah/gqlparser/lexer/token.go: -------------------------------------------------------------------------------- 1 | package lexer 2 | 3 | import ( 4 | "strconv" 5 | 6 | "github.com/vektah/gqlparser/ast" 7 | ) 8 | 9 | const ( 10 | Invalid Type = iota 11 | EOF 12 | Bang 13 | Dollar 14 | Amp 15 | ParenL 16 | ParenR 17 | Spread 18 | Colon 19 | Equals 20 | At 21 | BracketL 22 | BracketR 23 | BraceL 24 | BraceR 25 | Pipe 26 | Name 27 | Int 28 | Float 29 | String 30 | BlockString 31 | Comment 32 | ) 33 | 34 | func (t Type) Name() string { 35 | switch t { 36 | case Invalid: 37 | return "Invalid" 38 | case EOF: 39 | return "EOF" 40 | case Bang: 41 | return "Bang" 42 | case Dollar: 43 | return "Dollar" 44 | case Amp: 45 | return "Amp" 46 | case ParenL: 47 | return "ParenL" 48 | case ParenR: 49 | return "ParenR" 50 | case Spread: 51 | return "Spread" 52 | case Colon: 53 | return "Colon" 54 | case Equals: 55 | return "Equals" 56 | case At: 57 | return "At" 58 | case BracketL: 59 | return "BracketL" 60 | case BracketR: 61 | return "BracketR" 62 | case BraceL: 63 | return "BraceL" 64 | case BraceR: 65 | return "BraceR" 66 | case Pipe: 67 | return "Pipe" 68 | case Name: 69 | return "Name" 70 | case Int: 71 | return "Int" 72 | case Float: 73 | return "Float" 74 | case String: 75 | return "String" 76 | case BlockString: 77 | return "BlockString" 78 | case Comment: 79 | return "Comment" 80 | } 81 | return "Unknown " + strconv.Itoa(int(t)) 82 | } 83 | 84 | func (t Type) String() string { 85 | switch t { 86 | case Invalid: 87 | return "" 88 | case EOF: 89 | return "" 90 | case Bang: 91 | return "!" 92 | case Dollar: 93 | return "$" 94 | case Amp: 95 | return "&" 96 | case ParenL: 97 | return "(" 98 | case ParenR: 99 | return ")" 100 | case Spread: 101 | return "..." 102 | case Colon: 103 | return ":" 104 | case Equals: 105 | return "=" 106 | case At: 107 | return "@" 108 | case BracketL: 109 | return "[" 110 | case BracketR: 111 | return "]" 112 | case BraceL: 113 | return "{" 114 | case BraceR: 115 | return "}" 116 | case Pipe: 117 | return "|" 118 | case Name: 119 | return "Name" 120 | case Int: 121 | return "Int" 122 | case Float: 123 | return "Float" 124 | case String: 125 | return "String" 126 | case BlockString: 127 | return "BlockString" 128 | case Comment: 129 | return "Comment" 130 | } 131 | return "Unknown " + strconv.Itoa(int(t)) 132 | } 133 | 134 | // Kind represents a type of token. The types are predefined as constants. 135 | type Type int 136 | 137 | type Token struct { 138 | Kind Type // The token type. 139 | Value string // The literal value consumed. 140 | Pos ast.Position // The file and line this token was read from 141 | } 142 | 143 | func (t Token) String() string { 144 | if t.Value != "" { 145 | return t.Kind.String() + " " + strconv.Quote(t.Value) 146 | } 147 | return t.Kind.String() 148 | } 149 | -------------------------------------------------------------------------------- /vendor/github.com/vektah/gqlparser/parser/parser.go: -------------------------------------------------------------------------------- 1 | package parser 2 | 3 | import ( 4 | "strconv" 5 | 6 | "github.com/vektah/gqlparser/ast" 7 | "github.com/vektah/gqlparser/gqlerror" 8 | "github.com/vektah/gqlparser/lexer" 9 | ) 10 | 11 | type parser struct { 12 | lexer lexer.Lexer 13 | err *gqlerror.Error 14 | 15 | peeked bool 16 | peekToken lexer.Token 17 | peekError *gqlerror.Error 18 | 19 | prev lexer.Token 20 | } 21 | 22 | func (p *parser) peekPos() *ast.Position { 23 | if p.err != nil { 24 | return nil 25 | } 26 | 27 | peek := p.peek() 28 | return &peek.Pos 29 | } 30 | 31 | func (p *parser) peek() lexer.Token { 32 | if p.err != nil { 33 | return p.prev 34 | } 35 | 36 | if !p.peeked { 37 | p.peekToken, p.peekError = p.lexer.ReadToken() 38 | p.peeked = true 39 | } 40 | 41 | return p.peekToken 42 | } 43 | 44 | func (p *parser) error(tok lexer.Token, format string, args ...interface{}) { 45 | if p.err != nil { 46 | return 47 | } 48 | p.err = gqlerror.ErrorLocf(tok.Pos.Src.Name, tok.Pos.Line, tok.Pos.Column, format, args...) 49 | } 50 | 51 | func (p *parser) next() lexer.Token { 52 | if p.err != nil { 53 | return p.prev 54 | } 55 | if p.peeked { 56 | p.peeked = false 57 | p.prev, p.err = p.peekToken, p.peekError 58 | } else { 59 | p.prev, p.err = p.lexer.ReadToken() 60 | } 61 | return p.prev 62 | } 63 | 64 | func (p *parser) expectKeyword(value string) lexer.Token { 65 | tok := p.peek() 66 | if tok.Kind == lexer.Name && tok.Value == value { 67 | return p.next() 68 | } 69 | 70 | p.error(tok, "Expected %s, found %s", strconv.Quote(value), tok.String()) 71 | return tok 72 | } 73 | 74 | func (p *parser) expect(kind lexer.Type) lexer.Token { 75 | tok := p.peek() 76 | if tok.Kind == kind { 77 | return p.next() 78 | } 79 | 80 | p.error(tok, "Expected %s, found %s", kind, tok.Kind.String()) 81 | return tok 82 | } 83 | 84 | func (p *parser) skip(kind lexer.Type) bool { 85 | if p.err != nil { 86 | return false 87 | } 88 | 89 | tok := p.peek() 90 | 91 | if tok.Kind != kind { 92 | return false 93 | } 94 | p.next() 95 | return true 96 | } 97 | 98 | func (p *parser) unexpectedError() { 99 | p.unexpectedToken(p.peek()) 100 | } 101 | 102 | func (p *parser) unexpectedToken(tok lexer.Token) { 103 | p.error(tok, "Unexpected %s", tok.String()) 104 | } 105 | 106 | func (p *parser) many(start lexer.Type, end lexer.Type, cb func()) { 107 | hasDef := p.skip(start) 108 | if !hasDef { 109 | return 110 | } 111 | 112 | for p.peek().Kind != end && p.err == nil { 113 | cb() 114 | } 115 | p.next() 116 | } 117 | 118 | func (p *parser) some(start lexer.Type, end lexer.Type, cb func()) { 119 | hasDef := p.skip(start) 120 | if !hasDef { 121 | return 122 | } 123 | 124 | called := false 125 | for p.peek().Kind != end && p.err == nil { 126 | called = true 127 | cb() 128 | } 129 | 130 | if !called { 131 | p.error(p.peek(), "expected at least one definition, found %s", p.peek().Kind.String()) 132 | return 133 | } 134 | 135 | p.next() 136 | } 137 | -------------------------------------------------------------------------------- /vendor/github.com/vektah/gqlparser/readme.md: -------------------------------------------------------------------------------- 1 | gqlparser [![CircleCI](https://badgen.net/circleci/github/vektah/gqlparser/master)](https://circleci.com/gh/vektah/gqlparser) [![Go Report Card](https://goreportcard.com/badge/github.com/vektah/gqlparser)](https://goreportcard.com/report/github.com/vektah/gqlparser) [![Coverage Status](https://badgen.net/coveralls/c/github/vektah/gqlparser)](https://coveralls.io/github/vektah/gqlparser?branch=master) 2 | === 3 | 4 | This is a parser for graphql, written to mirror the graphql-js reference implementation as closely while remaining idiomatic and easy to use. 5 | 6 | spec target: June 2018 (Schema definition language, block strings as descriptions, error paths & extension) 7 | 8 | This parser is used by [gqlgen](https://github.com/99designs/gqlgen), and it should be reasonablly stable. 9 | 10 | Guiding principles: 11 | 12 | - maintainability: It should be easy to stay up to date with the spec 13 | - well tested: It shouldnt need a graphql server to validate itself. Changes to this repo should be self contained. 14 | - server agnostic: It should be usable by any of the graphql server implementations, and any graphql client tooling. 15 | - idiomatic & stable api: It should follow go best practices, especially around forwards compatibility. 16 | - fast: Where it doesnt impact on the above it should be fast. Avoid unnecessary allocs in hot paths. 17 | - close to reference: Where it doesnt impact on the above, it should stay close to the [graphql/graphql-js](https://github.com/graphql/graphql-js) reference implementation. 18 | -------------------------------------------------------------------------------- /vendor/github.com/vektah/gqlparser/validator/error.go: -------------------------------------------------------------------------------- 1 | package validator 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/vektah/gqlparser/ast" 7 | "github.com/vektah/gqlparser/gqlerror" 8 | ) 9 | 10 | type ErrorOption func(err *gqlerror.Error) 11 | 12 | func Message(msg string, args ...interface{}) ErrorOption { 13 | return func(err *gqlerror.Error) { 14 | err.Message += fmt.Sprintf(msg, args...) 15 | } 16 | } 17 | 18 | func At(position *ast.Position) ErrorOption { 19 | return func(err *gqlerror.Error) { 20 | if position == nil { 21 | return 22 | } 23 | err.Locations = append(err.Locations, gqlerror.Location{ 24 | Line: position.Line, 25 | Column: position.Column, 26 | }) 27 | if position.Src.Name != "" { 28 | err.SetFile(position.Src.Name) 29 | } 30 | } 31 | } 32 | 33 | func SuggestListQuoted(prefix string, typed string, suggestions []string) ErrorOption { 34 | suggested := SuggestionList(typed, suggestions) 35 | return func(err *gqlerror.Error) { 36 | if len(suggested) > 0 { 37 | err.Message += " " + prefix + " " + QuotedOrList(suggested...) + "?" 38 | } 39 | } 40 | } 41 | 42 | func SuggestListUnquoted(prefix string, typed string, suggestions []string) ErrorOption { 43 | suggested := SuggestionList(typed, suggestions) 44 | return func(err *gqlerror.Error) { 45 | if len(suggested) > 0 { 46 | err.Message += " " + prefix + " " + OrList(suggested...) + "?" 47 | } 48 | } 49 | } 50 | 51 | func Suggestf(suggestion string, args ...interface{}) ErrorOption { 52 | return func(err *gqlerror.Error) { 53 | err.Message += " Did you mean " + fmt.Sprintf(suggestion, args...) + "?" 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /vendor/github.com/vektah/gqlparser/validator/messaging.go: -------------------------------------------------------------------------------- 1 | package validator 2 | 3 | import "bytes" 4 | 5 | // Given [ A, B, C ] return '"A", "B", or "C"'. 6 | func QuotedOrList(items ...string) string { 7 | itemsQuoted := make([]string, len(items)) 8 | for i, item := range items { 9 | itemsQuoted[i] = `"` + item + `"` 10 | } 11 | return OrList(itemsQuoted...) 12 | } 13 | 14 | // Given [ A, B, C ] return 'A, B, or C'. 15 | func OrList(items ...string) string { 16 | var buf bytes.Buffer 17 | 18 | if len(items) > 5 { 19 | items = items[:5] 20 | } 21 | if len(items) == 2 { 22 | buf.WriteString(items[0]) 23 | buf.WriteString(" or ") 24 | buf.WriteString(items[1]) 25 | return buf.String() 26 | } 27 | 28 | for i, item := range items { 29 | if i != 0 { 30 | if i == len(items)-1 { 31 | buf.WriteString(", or ") 32 | } else { 33 | buf.WriteString(", ") 34 | } 35 | } 36 | buf.WriteString(item) 37 | } 38 | return buf.String() 39 | } 40 | -------------------------------------------------------------------------------- /vendor/github.com/vektah/gqlparser/validator/prelude.go: -------------------------------------------------------------------------------- 1 | package validator 2 | 3 | import "github.com/vektah/gqlparser/ast" 4 | 5 | var Prelude = &ast.Source{ 6 | Name: "prelude.graphql", 7 | Input: "# This file defines all the implicitly declared types that are required by the graphql spec. It is implicitly included by calls to LoadSchema\n\n\"The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.\"\nscalar Int\n\n\"The `Float` scalar type represents signed double-precision fractional values as specified by [IEEE 754](http://en.wikipedia.org/wiki/IEEE_floating_point).\"\nscalar Float\n\n\"The `String`scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.\"\nscalar String\n\n\"The `Boolean` scalar type represents `true` or `false`.\"\nscalar Boolean\n\n\"\"\"The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as \"4\") or integer (such as 4) input value will be accepted as an ID.\"\"\"\nscalar ID\n\n\"The @include directive may be provided for fields, fragment spreads, and inline fragments, and allows for conditional inclusion during execution as described by the if argument.\"\ndirective @include(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT\n\n\"The @skip directive may be provided for fields, fragment spreads, and inline fragments, and allows for conditional exclusion during execution as described by the if argument.\"\ndirective @skip(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT\n\n\"The @deprecated directive is used within the type system definition language to indicate deprecated portions of a GraphQL service’s schema, such as deprecated fields on a type or deprecated enum values.\"\ndirective @deprecated(reason: String = \"No longer supported\") on FIELD_DEFINITION | ENUM_VALUE\n\ntype __Schema {\n types: [__Type!]!\n queryType: __Type!\n mutationType: __Type\n subscriptionType: __Type\n directives: [__Directive!]!\n}\n\ntype __Type {\n kind: __TypeKind!\n name: String\n description: String\n\n # OBJECT and INTERFACE only\n fields(includeDeprecated: Boolean = false): [__Field!]\n\n # OBJECT only\n interfaces: [__Type!]\n\n # INTERFACE and UNION only\n possibleTypes: [__Type!]\n\n # ENUM only\n enumValues(includeDeprecated: Boolean = false): [__EnumValue!]\n\n # INPUT_OBJECT only\n inputFields: [__InputValue!]\n\n # NON_NULL and LIST only\n ofType: __Type\n}\n\ntype __Field {\n name: String!\n description: String\n args: [__InputValue!]!\n type: __Type!\n isDeprecated: Boolean!\n deprecationReason: String\n}\n\ntype __InputValue {\n name: String!\n description: String\n type: __Type!\n defaultValue: String\n}\n\ntype __EnumValue {\n name: String!\n description: String\n isDeprecated: Boolean!\n deprecationReason: String\n}\n\nenum __TypeKind {\n SCALAR\n OBJECT\n INTERFACE\n UNION\n ENUM\n INPUT_OBJECT\n LIST\n NON_NULL\n}\n\ntype __Directive {\n name: String!\n description: String\n locations: [__DirectiveLocation!]!\n args: [__InputValue!]!\n}\n\nenum __DirectiveLocation {\n QUERY\n MUTATION\n SUBSCRIPTION\n FIELD\n FRAGMENT_DEFINITION\n FRAGMENT_SPREAD\n INLINE_FRAGMENT\n SCHEMA\n SCALAR\n OBJECT\n FIELD_DEFINITION\n ARGUMENT_DEFINITION\n INTERFACE\n UNION\n ENUM\n ENUM_VALUE\n INPUT_OBJECT\n INPUT_FIELD_DEFINITION\n}\n", 8 | BuiltIn: true, 9 | } 10 | -------------------------------------------------------------------------------- /vendor/github.com/vektah/gqlparser/validator/rules/fields_on_correct_type.go: -------------------------------------------------------------------------------- 1 | package validator 2 | 3 | import ( 4 | "fmt" 5 | "sort" 6 | 7 | "github.com/vektah/gqlparser/ast" 8 | . "github.com/vektah/gqlparser/validator" 9 | ) 10 | 11 | func init() { 12 | AddRule("FieldsOnCorrectType", func(observers *Events, addError AddErrFunc) { 13 | observers.OnField(func(walker *Walker, field *ast.Field) { 14 | if field.ObjectDefinition == nil || field.Definition != nil { 15 | return 16 | } 17 | 18 | message := fmt.Sprintf(`Cannot query field "%s" on type "%s".`, field.Name, field.ObjectDefinition.Name) 19 | 20 | if suggestedTypeNames := getSuggestedTypeNames(walker, field.ObjectDefinition, field.Name); suggestedTypeNames != nil { 21 | message += " Did you mean to use an inline fragment on " + QuotedOrList(suggestedTypeNames...) + "?" 22 | } else if suggestedFieldNames := getSuggestedFieldNames(field.ObjectDefinition, field.Name); suggestedFieldNames != nil { 23 | message += " Did you mean " + QuotedOrList(suggestedFieldNames...) + "?" 24 | } 25 | 26 | addError( 27 | Message(message), 28 | At(field.Position), 29 | ) 30 | }) 31 | }) 32 | } 33 | 34 | // Go through all of the implementations of type, as well as the interfaces 35 | // that they implement. If any of those types include the provided field, 36 | // suggest them, sorted by how often the type is referenced, starting 37 | // with Interfaces. 38 | func getSuggestedTypeNames(walker *Walker, parent *ast.Definition, name string) []string { 39 | if !parent.IsAbstractType() { 40 | return nil 41 | } 42 | 43 | var suggestedObjectTypes []string 44 | var suggestedInterfaceTypes []string 45 | interfaceUsageCount := map[string]int{} 46 | 47 | for _, possibleType := range walker.Schema.GetPossibleTypes(parent) { 48 | field := possibleType.Fields.ForName(name) 49 | if field == nil { 50 | continue 51 | } 52 | 53 | suggestedObjectTypes = append(suggestedObjectTypes, possibleType.Name) 54 | 55 | for _, possibleInterface := range possibleType.Interfaces { 56 | interfaceField := walker.Schema.Types[possibleInterface] 57 | if interfaceField != nil && interfaceField.Fields.ForName(name) != nil { 58 | if interfaceUsageCount[possibleInterface] == 0 { 59 | suggestedInterfaceTypes = append(suggestedInterfaceTypes, possibleInterface) 60 | } 61 | interfaceUsageCount[possibleInterface]++ 62 | } 63 | } 64 | } 65 | 66 | sort.SliceStable(suggestedInterfaceTypes, func(i, j int) bool { 67 | return interfaceUsageCount[suggestedInterfaceTypes[i]] > interfaceUsageCount[suggestedInterfaceTypes[j]] 68 | }) 69 | 70 | return append(suggestedInterfaceTypes, suggestedObjectTypes...) 71 | } 72 | 73 | // For the field name provided, determine if there are any similar field names 74 | // that may be the result of a typo. 75 | func getSuggestedFieldNames(parent *ast.Definition, name string) []string { 76 | if parent.Kind != ast.Object && parent.Kind != ast.Interface { 77 | return nil 78 | } 79 | 80 | var possibleFieldNames []string 81 | for _, field := range parent.Fields { 82 | possibleFieldNames = append(possibleFieldNames, field.Name) 83 | } 84 | 85 | return SuggestionList(name, possibleFieldNames) 86 | } 87 | -------------------------------------------------------------------------------- /vendor/github.com/vektah/gqlparser/validator/rules/fragments_on_composite_types.go: -------------------------------------------------------------------------------- 1 | package validator 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/vektah/gqlparser/ast" 7 | . "github.com/vektah/gqlparser/validator" 8 | ) 9 | 10 | func init() { 11 | AddRule("FragmentsOnCompositeTypes", func(observers *Events, addError AddErrFunc) { 12 | observers.OnInlineFragment(func(walker *Walker, inlineFragment *ast.InlineFragment) { 13 | fragmentType := walker.Schema.Types[inlineFragment.TypeCondition] 14 | if fragmentType == nil || fragmentType.IsCompositeType() { 15 | return 16 | } 17 | 18 | message := fmt.Sprintf(`Fragment cannot condition on non composite type "%s".`, inlineFragment.TypeCondition) 19 | 20 | addError( 21 | Message(message), 22 | At(inlineFragment.Position), 23 | ) 24 | }) 25 | 26 | observers.OnFragment(func(walker *Walker, fragment *ast.FragmentDefinition) { 27 | if fragment.Definition == nil || fragment.TypeCondition == "" || fragment.Definition.IsCompositeType() { 28 | return 29 | } 30 | 31 | message := fmt.Sprintf(`Fragment "%s" cannot condition on non composite type "%s".`, fragment.Name, fragment.TypeCondition) 32 | 33 | addError( 34 | Message(message), 35 | At(fragment.Position), 36 | ) 37 | }) 38 | }) 39 | } 40 | -------------------------------------------------------------------------------- /vendor/github.com/vektah/gqlparser/validator/rules/known_argument_names.go: -------------------------------------------------------------------------------- 1 | package validator 2 | 3 | import ( 4 | "github.com/vektah/gqlparser/ast" 5 | . "github.com/vektah/gqlparser/validator" 6 | ) 7 | 8 | func init() { 9 | AddRule("KnownArgumentNames", func(observers *Events, addError AddErrFunc) { 10 | // A GraphQL field is only valid if all supplied arguments are defined by that field. 11 | observers.OnField(func(walker *Walker, field *ast.Field) { 12 | if field.Definition == nil || field.ObjectDefinition == nil { 13 | return 14 | } 15 | for _, arg := range field.Arguments { 16 | def := field.Definition.Arguments.ForName(arg.Name) 17 | if def != nil { 18 | continue 19 | } 20 | 21 | var suggestions []string 22 | for _, argDef := range field.Definition.Arguments { 23 | suggestions = append(suggestions, argDef.Name) 24 | } 25 | 26 | addError( 27 | Message(`Unknown argument "%s" on field "%s" of type "%s".`, arg.Name, field.Name, field.ObjectDefinition.Name), 28 | SuggestListQuoted("Did you mean", arg.Name, suggestions), 29 | At(field.Position), 30 | ) 31 | } 32 | }) 33 | 34 | observers.OnDirective(func(walker *Walker, directive *ast.Directive) { 35 | if directive.Definition == nil { 36 | return 37 | } 38 | for _, arg := range directive.Arguments { 39 | def := directive.Definition.Arguments.ForName(arg.Name) 40 | if def != nil { 41 | continue 42 | } 43 | 44 | var suggestions []string 45 | for _, argDef := range directive.Definition.Arguments { 46 | suggestions = append(suggestions, argDef.Name) 47 | } 48 | 49 | addError( 50 | Message(`Unknown argument "%s" on directive "@%s".`, arg.Name, directive.Name), 51 | SuggestListQuoted("Did you mean", arg.Name, suggestions), 52 | At(directive.Position), 53 | ) 54 | } 55 | }) 56 | }) 57 | } 58 | -------------------------------------------------------------------------------- /vendor/github.com/vektah/gqlparser/validator/rules/known_directives.go: -------------------------------------------------------------------------------- 1 | package validator 2 | 3 | import ( 4 | "github.com/vektah/gqlparser/ast" 5 | . "github.com/vektah/gqlparser/validator" 6 | ) 7 | 8 | func init() { 9 | AddRule("KnownDirectives", func(observers *Events, addError AddErrFunc) { 10 | observers.OnDirective(func(walker *Walker, directive *ast.Directive) { 11 | if directive.Definition == nil { 12 | addError( 13 | Message(`Unknown directive "%s".`, directive.Name), 14 | At(directive.Position), 15 | ) 16 | return 17 | } 18 | 19 | for _, loc := range directive.Definition.Locations { 20 | if loc == directive.Location { 21 | return 22 | } 23 | } 24 | 25 | addError( 26 | Message(`Directive "%s" may not be used on %s.`, directive.Name, directive.Location), 27 | At(directive.Position), 28 | ) 29 | }) 30 | }) 31 | } 32 | -------------------------------------------------------------------------------- /vendor/github.com/vektah/gqlparser/validator/rules/known_fragment_names.go: -------------------------------------------------------------------------------- 1 | package validator 2 | 3 | import ( 4 | "github.com/vektah/gqlparser/ast" 5 | . "github.com/vektah/gqlparser/validator" 6 | ) 7 | 8 | func init() { 9 | AddRule("KnownFragmentNames", func(observers *Events, addError AddErrFunc) { 10 | observers.OnFragmentSpread(func(walker *Walker, fragmentSpread *ast.FragmentSpread) { 11 | if fragmentSpread.Definition == nil { 12 | addError( 13 | Message(`Unknown fragment "%s".`, fragmentSpread.Name), 14 | At(fragmentSpread.Position), 15 | ) 16 | } 17 | }) 18 | }) 19 | } 20 | -------------------------------------------------------------------------------- /vendor/github.com/vektah/gqlparser/validator/rules/known_type_names.go: -------------------------------------------------------------------------------- 1 | package validator 2 | 3 | import ( 4 | "github.com/vektah/gqlparser/ast" 5 | . "github.com/vektah/gqlparser/validator" 6 | ) 7 | 8 | func init() { 9 | AddRule("KnownTypeNames", func(observers *Events, addError AddErrFunc) { 10 | observers.OnOperation(func(walker *Walker, operation *ast.OperationDefinition) { 11 | for _, vdef := range operation.VariableDefinitions { 12 | typeName := vdef.Type.Name() 13 | def := walker.Schema.Types[typeName] 14 | if def != nil { 15 | continue 16 | } 17 | 18 | addError( 19 | Message(`Unknown type "%s".`, typeName), 20 | At(operation.Position), 21 | ) 22 | } 23 | }) 24 | 25 | observers.OnInlineFragment(func(walker *Walker, inlineFragment *ast.InlineFragment) { 26 | typedName := inlineFragment.TypeCondition 27 | if typedName == "" { 28 | return 29 | } 30 | 31 | def := walker.Schema.Types[typedName] 32 | if def != nil { 33 | return 34 | } 35 | 36 | addError( 37 | Message(`Unknown type "%s".`, typedName), 38 | At(inlineFragment.Position), 39 | ) 40 | }) 41 | 42 | observers.OnFragment(func(walker *Walker, fragment *ast.FragmentDefinition) { 43 | typeName := fragment.TypeCondition 44 | def := walker.Schema.Types[typeName] 45 | if def != nil { 46 | return 47 | } 48 | 49 | var possibleTypes []string 50 | for _, t := range walker.Schema.Types { 51 | possibleTypes = append(possibleTypes, t.Name) 52 | } 53 | 54 | addError( 55 | Message(`Unknown type "%s".`, typeName), 56 | SuggestListQuoted("Did you mean", typeName, possibleTypes), 57 | At(fragment.Position), 58 | ) 59 | }) 60 | }) 61 | } 62 | -------------------------------------------------------------------------------- /vendor/github.com/vektah/gqlparser/validator/rules/lone_anonymous_operation.go: -------------------------------------------------------------------------------- 1 | package validator 2 | 3 | import ( 4 | "github.com/vektah/gqlparser/ast" 5 | . "github.com/vektah/gqlparser/validator" 6 | ) 7 | 8 | func init() { 9 | AddRule("LoneAnonymousOperation", func(observers *Events, addError AddErrFunc) { 10 | observers.OnOperation(func(walker *Walker, operation *ast.OperationDefinition) { 11 | if operation.Name == "" && len(walker.Document.Operations) > 1 { 12 | addError( 13 | Message(`This anonymous operation must be the only defined operation.`), 14 | At(operation.Position), 15 | ) 16 | } 17 | }) 18 | }) 19 | } 20 | -------------------------------------------------------------------------------- /vendor/github.com/vektah/gqlparser/validator/rules/no_fragment_cycles.go: -------------------------------------------------------------------------------- 1 | package validator 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | 7 | "github.com/vektah/gqlparser/ast" 8 | . "github.com/vektah/gqlparser/validator" 9 | ) 10 | 11 | func init() { 12 | AddRule("NoFragmentCycles", func(observers *Events, addError AddErrFunc) { 13 | visitedFrags := make(map[string]bool) 14 | 15 | observers.OnFragment(func(walker *Walker, fragment *ast.FragmentDefinition) { 16 | var spreadPath []*ast.FragmentSpread 17 | spreadPathIndexByName := make(map[string]int) 18 | 19 | var recursive func(fragment *ast.FragmentDefinition) 20 | recursive = func(fragment *ast.FragmentDefinition) { 21 | if visitedFrags[fragment.Name] { 22 | return 23 | } 24 | 25 | visitedFrags[fragment.Name] = true 26 | 27 | spreadNodes := getFragmentSpreads(fragment.SelectionSet) 28 | if len(spreadNodes) == 0 { 29 | return 30 | } 31 | spreadPathIndexByName[fragment.Name] = len(spreadPath) 32 | 33 | for _, spreadNode := range spreadNodes { 34 | spreadName := spreadNode.Name 35 | 36 | cycleIndex, ok := spreadPathIndexByName[spreadName] 37 | 38 | spreadPath = append(spreadPath, spreadNode) 39 | if !ok { 40 | spreadFragment := walker.Document.Fragments.ForName(spreadName) 41 | if spreadFragment != nil { 42 | recursive(spreadFragment) 43 | } 44 | } else { 45 | cyclePath := spreadPath[cycleIndex : len(spreadPath)-1] 46 | var fragmentNames []string 47 | for _, fs := range cyclePath { 48 | fragmentNames = append(fragmentNames, fs.Name) 49 | } 50 | var via string 51 | if len(fragmentNames) != 0 { 52 | via = fmt.Sprintf(" via %s", strings.Join(fragmentNames, ", ")) 53 | } 54 | addError( 55 | Message(`Cannot spread fragment "%s" within itself%s.`, spreadName, via), 56 | At(spreadNode.Position), 57 | ) 58 | } 59 | 60 | spreadPath = spreadPath[:len(spreadPath)-1] 61 | } 62 | 63 | delete(spreadPathIndexByName, fragment.Name) 64 | } 65 | 66 | recursive(fragment) 67 | }) 68 | }) 69 | } 70 | 71 | func getFragmentSpreads(node ast.SelectionSet) []*ast.FragmentSpread { 72 | var spreads []*ast.FragmentSpread 73 | 74 | setsToVisit := []ast.SelectionSet{node} 75 | 76 | for len(setsToVisit) != 0 { 77 | set := setsToVisit[len(setsToVisit)-1] 78 | setsToVisit = setsToVisit[:len(setsToVisit)-1] 79 | 80 | for _, selection := range set { 81 | switch selection := selection.(type) { 82 | case *ast.FragmentSpread: 83 | spreads = append(spreads, selection) 84 | case *ast.Field: 85 | setsToVisit = append(setsToVisit, selection.SelectionSet) 86 | case *ast.InlineFragment: 87 | setsToVisit = append(setsToVisit, selection.SelectionSet) 88 | } 89 | } 90 | } 91 | 92 | return spreads 93 | } 94 | -------------------------------------------------------------------------------- /vendor/github.com/vektah/gqlparser/validator/rules/no_undefined_variables.go: -------------------------------------------------------------------------------- 1 | package validator 2 | 3 | import ( 4 | "github.com/vektah/gqlparser/ast" 5 | . "github.com/vektah/gqlparser/validator" 6 | ) 7 | 8 | func init() { 9 | AddRule("NoUndefinedVariables", func(observers *Events, addError AddErrFunc) { 10 | observers.OnValue(func(walker *Walker, value *ast.Value) { 11 | if walker.CurrentOperation == nil || value.Kind != ast.Variable || value.VariableDefinition != nil { 12 | return 13 | } 14 | 15 | if walker.CurrentOperation.Name != "" { 16 | addError( 17 | Message(`Variable "%s" is not defined by operation "%s".`, value, walker.CurrentOperation.Name), 18 | At(walker.CurrentOperation.Position), 19 | ) 20 | } else { 21 | addError( 22 | Message(`Variable "%s" is not defined.`, value), 23 | At(value.Position), 24 | ) 25 | } 26 | }) 27 | }) 28 | } 29 | -------------------------------------------------------------------------------- /vendor/github.com/vektah/gqlparser/validator/rules/no_unused_fragments.go: -------------------------------------------------------------------------------- 1 | package validator 2 | 3 | import ( 4 | "github.com/vektah/gqlparser/ast" 5 | . "github.com/vektah/gqlparser/validator" 6 | ) 7 | 8 | func init() { 9 | AddRule("NoUnusedFragments", func(observers *Events, addError AddErrFunc) { 10 | 11 | inFragmentDefinition := false 12 | fragmentNameUsed := make(map[string]bool) 13 | 14 | observers.OnFragmentSpread(func(walker *Walker, fragmentSpread *ast.FragmentSpread) { 15 | if !inFragmentDefinition { 16 | fragmentNameUsed[fragmentSpread.Name] = true 17 | } 18 | }) 19 | 20 | observers.OnFragment(func(walker *Walker, fragment *ast.FragmentDefinition) { 21 | inFragmentDefinition = true 22 | if !fragmentNameUsed[fragment.Name] { 23 | addError( 24 | Message(`Fragment "%s" is never used.`, fragment.Name), 25 | At(fragment.Position), 26 | ) 27 | } 28 | }) 29 | }) 30 | } 31 | -------------------------------------------------------------------------------- /vendor/github.com/vektah/gqlparser/validator/rules/no_unused_variables.go: -------------------------------------------------------------------------------- 1 | package validator 2 | 3 | import ( 4 | "github.com/vektah/gqlparser/ast" 5 | . "github.com/vektah/gqlparser/validator" 6 | ) 7 | 8 | func init() { 9 | AddRule("NoUnusedVariables", func(observers *Events, addError AddErrFunc) { 10 | observers.OnOperation(func(walker *Walker, operation *ast.OperationDefinition) { 11 | for _, varDef := range operation.VariableDefinitions { 12 | if varDef.Used { 13 | continue 14 | } 15 | 16 | if operation.Name != "" { 17 | addError( 18 | Message(`Variable "$%s" is never used in operation "%s".`, varDef.Variable, operation.Name), 19 | At(varDef.Position), 20 | ) 21 | } else { 22 | addError( 23 | Message(`Variable "$%s" is never used.`, varDef.Variable), 24 | At(varDef.Position), 25 | ) 26 | } 27 | } 28 | }) 29 | }) 30 | } 31 | -------------------------------------------------------------------------------- /vendor/github.com/vektah/gqlparser/validator/rules/possible_fragment_spreads.go: -------------------------------------------------------------------------------- 1 | package validator 2 | 3 | import ( 4 | "github.com/vektah/gqlparser/ast" 5 | . "github.com/vektah/gqlparser/validator" 6 | ) 7 | 8 | func init() { 9 | AddRule("PossibleFragmentSpreads", func(observers *Events, addError AddErrFunc) { 10 | 11 | validate := func(walker *Walker, parentDef *ast.Definition, fragmentName string, emitError func()) { 12 | if parentDef == nil { 13 | return 14 | } 15 | 16 | var parentDefs []*ast.Definition 17 | switch parentDef.Kind { 18 | case ast.Object: 19 | parentDefs = []*ast.Definition{parentDef} 20 | case ast.Interface, ast.Union: 21 | parentDefs = walker.Schema.GetPossibleTypes(parentDef) 22 | default: 23 | return 24 | } 25 | 26 | fragmentDefType := walker.Schema.Types[fragmentName] 27 | if fragmentDefType == nil { 28 | return 29 | } 30 | if !fragmentDefType.IsCompositeType() { 31 | // checked by FragmentsOnCompositeTypes 32 | return 33 | } 34 | fragmentDefs := walker.Schema.GetPossibleTypes(fragmentDefType) 35 | 36 | for _, fragmentDef := range fragmentDefs { 37 | for _, parentDef := range parentDefs { 38 | if parentDef.Name == fragmentDef.Name { 39 | return 40 | } 41 | } 42 | } 43 | 44 | emitError() 45 | } 46 | 47 | observers.OnInlineFragment(func(walker *Walker, inlineFragment *ast.InlineFragment) { 48 | validate(walker, inlineFragment.ObjectDefinition, inlineFragment.TypeCondition, func() { 49 | addError( 50 | Message(`Fragment cannot be spread here as objects of type "%s" can never be of type "%s".`, inlineFragment.ObjectDefinition.Name, inlineFragment.TypeCondition), 51 | At(inlineFragment.Position), 52 | ) 53 | }) 54 | }) 55 | 56 | observers.OnFragmentSpread(func(walker *Walker, fragmentSpread *ast.FragmentSpread) { 57 | if fragmentSpread.Definition == nil { 58 | return 59 | } 60 | validate(walker, fragmentSpread.ObjectDefinition, fragmentSpread.Definition.TypeCondition, func() { 61 | addError( 62 | Message(`Fragment "%s" cannot be spread here as objects of type "%s" can never be of type "%s".`, fragmentSpread.Name, fragmentSpread.ObjectDefinition.Name, fragmentSpread.Definition.TypeCondition), 63 | At(fragmentSpread.Position), 64 | ) 65 | }) 66 | }) 67 | }) 68 | } 69 | -------------------------------------------------------------------------------- /vendor/github.com/vektah/gqlparser/validator/rules/provided_required_arguments.go: -------------------------------------------------------------------------------- 1 | package validator 2 | 3 | import ( 4 | "github.com/vektah/gqlparser/ast" 5 | . "github.com/vektah/gqlparser/validator" 6 | ) 7 | 8 | func init() { 9 | AddRule("ProvidedRequiredArguments", func(observers *Events, addError AddErrFunc) { 10 | 11 | observers.OnField(func(walker *Walker, field *ast.Field) { 12 | if field.Definition == nil { 13 | return 14 | } 15 | 16 | argDef: 17 | for _, argDef := range field.Definition.Arguments { 18 | if !argDef.Type.NonNull { 19 | continue 20 | } 21 | if argDef.DefaultValue != nil { 22 | continue 23 | } 24 | for _, arg := range field.Arguments { 25 | if arg.Name == argDef.Name { 26 | continue argDef 27 | } 28 | } 29 | 30 | addError( 31 | Message(`Field "%s" argument "%s" of type "%s" is required but not provided.`, field.Name, argDef.Name, argDef.Type.String()), 32 | At(field.Position), 33 | ) 34 | } 35 | }) 36 | 37 | observers.OnDirective(func(walker *Walker, directive *ast.Directive) { 38 | if directive.Definition == nil { 39 | return 40 | } 41 | 42 | argDef: 43 | for _, argDef := range directive.Definition.Arguments { 44 | if !argDef.Type.NonNull { 45 | continue 46 | } 47 | if argDef.DefaultValue != nil { 48 | continue 49 | } 50 | for _, arg := range directive.Arguments { 51 | if arg.Name == argDef.Name { 52 | continue argDef 53 | } 54 | } 55 | 56 | addError( 57 | Message(`Directive "@%s" argument "%s" of type "%s" is required but not provided.`, directive.Definition.Name, argDef.Name, argDef.Type.String()), 58 | At(directive.Position), 59 | ) 60 | } 61 | }) 62 | }) 63 | } 64 | -------------------------------------------------------------------------------- /vendor/github.com/vektah/gqlparser/validator/rules/scalar_leafs.go: -------------------------------------------------------------------------------- 1 | package validator 2 | 3 | import ( 4 | "github.com/vektah/gqlparser/ast" 5 | . "github.com/vektah/gqlparser/validator" 6 | ) 7 | 8 | func init() { 9 | AddRule("ScalarLeafs", func(observers *Events, addError AddErrFunc) { 10 | observers.OnField(func(walker *Walker, field *ast.Field) { 11 | if field.Definition == nil { 12 | return 13 | } 14 | 15 | fieldType := walker.Schema.Types[field.Definition.Type.Name()] 16 | if fieldType == nil { 17 | return 18 | } 19 | 20 | if fieldType.IsLeafType() && len(field.SelectionSet) > 0 { 21 | addError( 22 | Message(`Field "%s" must not have a selection since type "%s" has no subfields.`, field.Name, fieldType.Name), 23 | At(field.Position), 24 | ) 25 | } 26 | 27 | if !fieldType.IsLeafType() && len(field.SelectionSet) == 0 { 28 | addError( 29 | Message(`Field "%s" of type "%s" must have a selection of subfields.`, field.Name, field.Definition.Type.String()), 30 | Suggestf(`"%s { ... }"`, field.Name), 31 | At(field.Position), 32 | ) 33 | } 34 | }) 35 | }) 36 | } 37 | -------------------------------------------------------------------------------- /vendor/github.com/vektah/gqlparser/validator/rules/single_field_subscriptions.go: -------------------------------------------------------------------------------- 1 | package validator 2 | 3 | import ( 4 | "strconv" 5 | 6 | "github.com/vektah/gqlparser/ast" 7 | . "github.com/vektah/gqlparser/validator" 8 | ) 9 | 10 | func init() { 11 | AddRule("SingleFieldSubscriptions", func(observers *Events, addError AddErrFunc) { 12 | observers.OnOperation(func(walker *Walker, operation *ast.OperationDefinition) { 13 | if operation.Operation != ast.Subscription { 14 | return 15 | } 16 | 17 | if len(operation.SelectionSet) > 1 { 18 | name := "Anonymous Subscription" 19 | if operation.Name != "" { 20 | name = `Subscription ` + strconv.Quote(operation.Name) 21 | } 22 | 23 | addError( 24 | Message(`%s must select only one top level field.`, name), 25 | At(operation.SelectionSet[1].GetPosition()), 26 | ) 27 | } 28 | }) 29 | }) 30 | } 31 | -------------------------------------------------------------------------------- /vendor/github.com/vektah/gqlparser/validator/rules/unique_argument_names.go: -------------------------------------------------------------------------------- 1 | package validator 2 | 3 | import ( 4 | "github.com/vektah/gqlparser/ast" 5 | . "github.com/vektah/gqlparser/validator" 6 | ) 7 | 8 | func init() { 9 | AddRule("UniqueArgumentNames", func(observers *Events, addError AddErrFunc) { 10 | observers.OnField(func(walker *Walker, field *ast.Field) { 11 | checkUniqueArgs(field.Arguments, addError) 12 | }) 13 | 14 | observers.OnDirective(func(walker *Walker, directive *ast.Directive) { 15 | checkUniqueArgs(directive.Arguments, addError) 16 | }) 17 | }) 18 | } 19 | 20 | func checkUniqueArgs(args ast.ArgumentList, addError AddErrFunc) { 21 | knownArgNames := map[string]bool{} 22 | 23 | for _, arg := range args { 24 | if knownArgNames[arg.Name] { 25 | addError( 26 | Message(`There can be only one argument named "%s".`, arg.Name), 27 | At(arg.Position), 28 | ) 29 | } 30 | 31 | knownArgNames[arg.Name] = true 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /vendor/github.com/vektah/gqlparser/validator/rules/unique_directives_per_location.go: -------------------------------------------------------------------------------- 1 | package validator 2 | 3 | import ( 4 | "github.com/vektah/gqlparser/ast" 5 | . "github.com/vektah/gqlparser/validator" 6 | ) 7 | 8 | func init() { 9 | AddRule("UniqueDirectivesPerLocation", func(observers *Events, addError AddErrFunc) { 10 | observers.OnDirectiveList(func(walker *Walker, directives []*ast.Directive) { 11 | seen := map[string]bool{} 12 | 13 | for _, dir := range directives { 14 | if seen[dir.Name] { 15 | addError( 16 | Message(`The directive "%s" can only be used once at this location.`, dir.Name), 17 | At(dir.Position), 18 | ) 19 | } 20 | seen[dir.Name] = true 21 | } 22 | }) 23 | }) 24 | } 25 | -------------------------------------------------------------------------------- /vendor/github.com/vektah/gqlparser/validator/rules/unique_fragment_names.go: -------------------------------------------------------------------------------- 1 | package validator 2 | 3 | import ( 4 | "github.com/vektah/gqlparser/ast" 5 | . "github.com/vektah/gqlparser/validator" 6 | ) 7 | 8 | func init() { 9 | AddRule("UniqueFragmentNames", func(observers *Events, addError AddErrFunc) { 10 | seenFragments := map[string]bool{} 11 | 12 | observers.OnFragment(func(walker *Walker, fragment *ast.FragmentDefinition) { 13 | if seenFragments[fragment.Name] { 14 | addError( 15 | Message(`There can be only one fragment named "%s".`, fragment.Name), 16 | At(fragment.Position), 17 | ) 18 | } 19 | seenFragments[fragment.Name] = true 20 | }) 21 | }) 22 | } 23 | -------------------------------------------------------------------------------- /vendor/github.com/vektah/gqlparser/validator/rules/unique_input_field_names.go: -------------------------------------------------------------------------------- 1 | package validator 2 | 3 | import ( 4 | "github.com/vektah/gqlparser/ast" 5 | . "github.com/vektah/gqlparser/validator" 6 | ) 7 | 8 | func init() { 9 | AddRule("UniqueInputFieldNames", func(observers *Events, addError AddErrFunc) { 10 | observers.OnValue(func(walker *Walker, value *ast.Value) { 11 | if value.Kind != ast.ObjectValue { 12 | return 13 | } 14 | 15 | seen := map[string]bool{} 16 | for _, field := range value.Children { 17 | if seen[field.Name] { 18 | addError( 19 | Message(`There can be only one input field named "%s".`, field.Name), 20 | At(field.Position), 21 | ) 22 | } 23 | seen[field.Name] = true 24 | } 25 | }) 26 | }) 27 | } 28 | -------------------------------------------------------------------------------- /vendor/github.com/vektah/gqlparser/validator/rules/unique_operation_names.go: -------------------------------------------------------------------------------- 1 | package validator 2 | 3 | import ( 4 | "github.com/vektah/gqlparser/ast" 5 | . "github.com/vektah/gqlparser/validator" 6 | ) 7 | 8 | func init() { 9 | AddRule("UniqueOperationNames", func(observers *Events, addError AddErrFunc) { 10 | seen := map[string]bool{} 11 | 12 | observers.OnOperation(func(walker *Walker, operation *ast.OperationDefinition) { 13 | if seen[operation.Name] { 14 | addError( 15 | Message(`There can be only one operation named "%s".`, operation.Name), 16 | At(operation.Position), 17 | ) 18 | } 19 | seen[operation.Name] = true 20 | }) 21 | }) 22 | } 23 | -------------------------------------------------------------------------------- /vendor/github.com/vektah/gqlparser/validator/rules/unique_variable_names.go: -------------------------------------------------------------------------------- 1 | package validator 2 | 3 | import ( 4 | "github.com/vektah/gqlparser/ast" 5 | . "github.com/vektah/gqlparser/validator" 6 | ) 7 | 8 | func init() { 9 | AddRule("UniqueVariableNames", func(observers *Events, addError AddErrFunc) { 10 | observers.OnOperation(func(walker *Walker, operation *ast.OperationDefinition) { 11 | seen := map[string]bool{} 12 | for _, def := range operation.VariableDefinitions { 13 | if seen[def.Variable] { 14 | addError( 15 | Message(`There can be only one variable named "%s".`, def.Variable), 16 | At(def.Position), 17 | ) 18 | } 19 | seen[def.Variable] = true 20 | } 21 | }) 22 | }) 23 | } 24 | -------------------------------------------------------------------------------- /vendor/github.com/vektah/gqlparser/validator/rules/variables_are_input_types.go: -------------------------------------------------------------------------------- 1 | package validator 2 | 3 | import ( 4 | "github.com/vektah/gqlparser/ast" 5 | . "github.com/vektah/gqlparser/validator" 6 | ) 7 | 8 | func init() { 9 | AddRule("VariablesAreInputTypes", func(observers *Events, addError AddErrFunc) { 10 | observers.OnOperation(func(walker *Walker, operation *ast.OperationDefinition) { 11 | for _, def := range operation.VariableDefinitions { 12 | if def.Definition == nil { 13 | continue 14 | } 15 | if !def.Definition.IsInputType() { 16 | addError( 17 | Message( 18 | `Variable "$%s" cannot be non-input type "%s".`, 19 | def.Variable, 20 | def.Type.String(), 21 | ), 22 | At(def.Position), 23 | ) 24 | } 25 | } 26 | }) 27 | }) 28 | } 29 | -------------------------------------------------------------------------------- /vendor/github.com/vektah/gqlparser/validator/rules/variables_in_allowed_position.go: -------------------------------------------------------------------------------- 1 | package validator 2 | 3 | import ( 4 | "github.com/vektah/gqlparser/ast" 5 | . "github.com/vektah/gqlparser/validator" 6 | ) 7 | 8 | func init() { 9 | AddRule("VariablesInAllowedPosition", func(observers *Events, addError AddErrFunc) { 10 | observers.OnValue(func(walker *Walker, value *ast.Value) { 11 | if value.Kind != ast.Variable || value.ExpectedType == nil || value.VariableDefinition == nil || walker.CurrentOperation == nil { 12 | return 13 | } 14 | 15 | // todo: move me into walk 16 | // If there is a default non nullable types can be null 17 | if value.VariableDefinition.DefaultValue != nil && value.VariableDefinition.DefaultValue.Kind != ast.NullValue { 18 | if value.ExpectedType.NonNull { 19 | value.ExpectedType.NonNull = false 20 | } 21 | } 22 | 23 | if !value.VariableDefinition.Type.IsCompatible(value.ExpectedType) { 24 | addError( 25 | Message( 26 | `Variable "%s" of type "%s" used in position expecting type "%s".`, 27 | value, 28 | value.VariableDefinition.Type.String(), 29 | value.ExpectedType.String(), 30 | ), 31 | At(value.Position), 32 | ) 33 | } 34 | }) 35 | }) 36 | } 37 | -------------------------------------------------------------------------------- /vendor/github.com/vektah/gqlparser/validator/suggestionList.go: -------------------------------------------------------------------------------- 1 | package validator 2 | 3 | import ( 4 | "sort" 5 | "strings" 6 | 7 | "github.com/agnivade/levenshtein" 8 | ) 9 | 10 | // Given an invalid input string and a list of valid options, returns a filtered 11 | // list of valid options sorted based on their similarity with the input. 12 | func SuggestionList(input string, options []string) []string { 13 | var results []string 14 | optionsByDistance := map[string]int{} 15 | 16 | for _, option := range options { 17 | distance := lexicalDistance(input, option) 18 | threshold := calcThreshold(input, option) 19 | if distance <= threshold { 20 | results = append(results, option) 21 | optionsByDistance[option] = distance 22 | } 23 | } 24 | 25 | sort.Slice(results, func(i, j int) bool { 26 | return optionsByDistance[results[i]] < optionsByDistance[results[j]] 27 | }) 28 | return results 29 | } 30 | 31 | func calcThreshold(a, b string) (threshold int) { 32 | if len(a) >= len(b) { 33 | threshold = len(a) / 2 34 | } else { 35 | threshold = len(b) / 2 36 | } 37 | if threshold < 1 { 38 | threshold = 1 39 | } 40 | return 41 | } 42 | 43 | // Computes the lexical distance between strings A and B. 44 | // 45 | // The "distance" between two strings is given by counting the minimum number 46 | // of edits needed to transform string A into string B. An edit can be an 47 | // insertion, deletion, or substitution of a single character, or a swap of two 48 | // adjacent characters. 49 | // 50 | // Includes a custom alteration from Damerau-Levenshtein to treat case changes 51 | // as a single edit which helps identify mis-cased values with an edit distance 52 | // of 1. 53 | // 54 | // This distance can be useful for detecting typos in input or sorting 55 | func lexicalDistance(a, b string) int { 56 | if a == b { 57 | return 0 58 | } 59 | 60 | a = strings.ToLower(a) 61 | b = strings.ToLower(b) 62 | 63 | // Any case change counts as a single edit 64 | if a == b { 65 | return 1 66 | } 67 | 68 | return levenshtein.ComputeDistance(a, b) 69 | } 70 | -------------------------------------------------------------------------------- /vendor/github.com/vektah/gqlparser/validator/validator.go: -------------------------------------------------------------------------------- 1 | package validator 2 | 3 | import ( 4 | . "github.com/vektah/gqlparser/ast" 5 | "github.com/vektah/gqlparser/gqlerror" 6 | ) 7 | 8 | type AddErrFunc func(options ...ErrorOption) 9 | 10 | type ruleFunc func(observers *Events, addError AddErrFunc) 11 | 12 | type rule struct { 13 | name string 14 | rule ruleFunc 15 | } 16 | 17 | var rules []rule 18 | 19 | // addRule to rule set. 20 | // f is called once each time `Validate` is executed. 21 | func AddRule(name string, f ruleFunc) { 22 | rules = append(rules, rule{name: name, rule: f}) 23 | } 24 | 25 | func Validate(schema *Schema, doc *QueryDocument) gqlerror.List { 26 | var errs gqlerror.List 27 | 28 | observers := &Events{} 29 | for i := range rules { 30 | rule := rules[i] 31 | rule.rule(observers, func(options ...ErrorOption) { 32 | err := &gqlerror.Error{ 33 | Rule: rule.name, 34 | } 35 | for _, o := range options { 36 | o(err) 37 | } 38 | errs = append(errs, err) 39 | }) 40 | } 41 | 42 | Walk(schema, doc, observers) 43 | return errs 44 | } 45 | -------------------------------------------------------------------------------- /vendor/modules.txt: -------------------------------------------------------------------------------- 1 | # github.com/99designs/gqlgen v0.10.2 2 | github.com/99designs/gqlgen/complexity 3 | github.com/99designs/gqlgen/graphql 4 | github.com/99designs/gqlgen/graphql/introspection 5 | github.com/99designs/gqlgen/handler 6 | # github.com/agnivade/levenshtein v1.0.1 7 | github.com/agnivade/levenshtein 8 | # github.com/go-redis/redis v6.15.6+incompatible 9 | github.com/go-redis/redis 10 | github.com/go-redis/redis/internal 11 | github.com/go-redis/redis/internal/consistenthash 12 | github.com/go-redis/redis/internal/hashtag 13 | github.com/go-redis/redis/internal/pool 14 | github.com/go-redis/redis/internal/proto 15 | github.com/go-redis/redis/internal/util 16 | # github.com/gorilla/websocket v1.4.1 17 | github.com/gorilla/websocket 18 | # github.com/hashicorp/golang-lru v0.5.0 19 | github.com/hashicorp/golang-lru 20 | github.com/hashicorp/golang-lru/simplelru 21 | # github.com/kelseyhightower/envconfig v1.4.0 22 | github.com/kelseyhightower/envconfig 23 | # github.com/rs/cors v1.7.0 24 | github.com/rs/cors 25 | # github.com/segmentio/ksuid v1.0.2 26 | github.com/segmentio/ksuid 27 | # github.com/tinrab/retry v1.0.0 28 | github.com/tinrab/retry 29 | # github.com/vektah/gqlparser v1.2.0 30 | github.com/vektah/gqlparser 31 | github.com/vektah/gqlparser/ast 32 | github.com/vektah/gqlparser/gqlerror 33 | github.com/vektah/gqlparser/lexer 34 | github.com/vektah/gqlparser/parser 35 | github.com/vektah/gqlparser/validator 36 | github.com/vektah/gqlparser/validator/rules 37 | --------------------------------------------------------------------------------