├── .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 |
2 |
3 |
GraphQL Chat
4 |
5 |
6 |
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 |
2 |
3 |
4 |
5 |
6 |
9 |
10 |
13 |
14 |
15 |
16 |
17 |
18 |
38 |
--------------------------------------------------------------------------------
/frontend/src/components/Login.vue:
--------------------------------------------------------------------------------
1 |
2 |
21 |
22 |
23 |
45 |
46 |
52 |
--------------------------------------------------------------------------------
/frontend/src/components/Message.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{message.user}}: {{message.text}}
4 |
5 |
6 |
7 |
16 |
--------------------------------------------------------------------------------
/frontend/src/components/MessageForm.vue:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
57 |
--------------------------------------------------------------------------------
/frontend/src/components/MessageList.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
67 |
--------------------------------------------------------------------------------
/frontend/src/components/UserList.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Users
4 |
6 | {{user}}
7 |
8 |
9 |
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 [](https://travis-ci.org/agnivade/levenshtein) [](https://goreportcard.com/report/github.com/agnivade/levenshtein) [](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 [](https://circleci.com/gh/vektah/gqlparser) [](https://goreportcard.com/report/github.com/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 |
--------------------------------------------------------------------------------