├── .dockerignore ├── .github └── workflows │ └── main.yml ├── .gitignore ├── Dockerfile ├── LICENSE ├── README.md ├── cmd ├── mqtt.go ├── mqtt.md ├── mqttStartConsumer.go ├── mqttStartProducer.go ├── nats.go ├── nats.md ├── natsStartConsumer.go ├── natsStartProducer.go ├── root.go └── serve.go ├── go.mod ├── go.sum ├── httpbin_pipeline.json ├── logger.config.json ├── main.go ├── person.wasm └── schema.graphql /.dockerignore: -------------------------------------------------------------------------------- 1 | Dockerfile -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Publish Docker 2 | on: [push] 3 | jobs: 4 | build: 5 | runs-on: ubuntu-latest 6 | steps: 7 | - uses: actions/checkout@master 8 | - name: Publish to Registry 9 | uses: HurricanKai/Publish-Docker-Github-Action@master 10 | with: 11 | name: jensneuse/graphql-gateway 12 | username: ${{ secrets.DOCKER_USERNAME }} 13 | password: ${{ secrets.DOCKER_PASSWORD }} 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang AS builder 2 | WORKDIR /app 3 | ADD go.mod /app 4 | ADD go.sum /app 5 | RUN go mod download 6 | ADD . /app/ 7 | RUN CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -a -o /graphql-gateway main.go 8 | RUN chmod +x /graphql-gateway 9 | COPY /logger.config.json / 10 | COPY /schema.graphql / 11 | COPY /person.wasm / 12 | EXPOSE 9111 13 | WORKDIR / 14 | ENTRYPOINT ["/graphql-gateway"] -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright © 2019 Jens Neuse 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 13 | all 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 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This codebase is **deprecated**! 2 | Please use https://github.com/jensneuse/graphql-go-tools instead. 3 | 4 | # GraphQL Gateway 5 | 6 | GraphQL Gateway turns an annotated schema into an executable GraphQL Server. 7 | Simply describe your schema and use directives to describe how the execution engine should resolve a field. 8 | No code needs to be written, no code generation, just configuration and the execution engine does its thing. 9 | 10 | Currently DataSources can be Static, GraphQL or JSON HTTP APIs. 11 | You can nest GraphQL data sources into REST data sources into GraphQL data sources into... 12 | Have a look at the schema.graphql file to fully understand the concept. 13 | 14 | This is experimental, don't use in production! But please, try it out! 15 | 16 | # Run 17 | 18 | Run the gateway using docker. 19 | 20 | ```shell script 21 | docker run -p 0.0.0.0:9111:9111 jensneuse/graphql-gateway serve 22 | ``` 23 | 24 | # Docs 25 | 26 | https://jens-neuse.gitbook.io/graphql-gateway/ 27 | 28 | # Develop 29 | 30 | 1. Install go 1.15 (golang.org) 31 | 2. git clone https://github.com/jensneuse/graphql-gateway.git 32 | 3. cd graphql-gateway 33 | 4. run: 34 | 35 | ```shell script 36 | go run main.go serve 37 | ``` 38 | 39 | Use GraphQL Playground to explore your API. 40 | 41 | Update the schema and make use of the directives. 42 | Take inspiration from the schema.graphql file on how to use the directives. 43 | If something doesn't work for you please supply a schema file so I can reconstruct the problem. 44 | 45 | # Motivation 46 | 47 | Writing resolvers on top of existing data sources is repetitive. 48 | The logic can be encapsulated into directives. 49 | If a directive doesn't give enough flexibility you're free to open an issue and/or PR. 50 | 51 | Before wrapping existing data sources think about the costs of writing and maintaining the resolver code. 52 | Implementing, extending and maintaining a bunch of directives scales a lot better than writing individual resolvers. 53 | There's a lot of tooling for writing efficient REST services. Also it's very easy to apply caching (e.g. using Varnish) to a REST API. 54 | 55 | With the help of this gateway you'll get the best of both worlds, easy to reason about backend services and the benefits of GraphQL at the front end layer: 56 | Write simple CRUD based REST APIs, apply server side caching and turn them into a GraphQL API with very little effort. 57 | 58 | # Architecture 59 | 60 | Query -> Lexing -> Parsing -> Normalization -> Validation -> Create Query Execution Plan -> Execute Query Plan -> Return Result 61 | 62 | Caching of execution plans will be possible to increase performance. 63 | This will enable skipping validation and query planning for recurring operations. 64 | After normalization the input can be hashed and the hash will be used to fill a query plan map / retrieve a cached query plan. 65 | 66 | # *any DataSource 67 | 68 | *any DataSource can be supported implementing the necessary interfaces. 69 | Currently supported: 70 | - GraphQL (multiple GraphQL services can be combined) 71 | - static (static embedded data) 72 | - HTTP JSON 73 | - HTTP JSON Streaming (uses polling to create a stream) 74 | - MQTT 75 | - Nats 76 | - Webassembly (resolve a Request using WASI compliant modules) 77 | 78 | # Contribute 79 | 80 | Please try this tool for your use case and submit issues in case it didn't work for you. 81 | It's far from being production ready so I'm relying on your input to find missing features & bugs. 82 | 83 | # Goals 84 | 85 | 1. Based on you input I want to evolve the engine to support as many use cases as possible. 86 | 2. When it feels "production ready" I'll focus on increasing performance because I took a few shortcuts to release this PoC faster (e.g. no parallel fetching, creation of unnecessary garbage collection) 87 | 88 | # Comparison 89 | 90 | ### nautilus gateway 91 | https://github.com/nautilus/gateway 92 | 93 | Nautilus is based around the assumption that all your services are GraphQL Services. It uses the Node interface ([Relay Gloabl Object Identification](https://facebook.github.io/relay/graphql/objectidentification.htm)) to automatically federate between multiple services. This approach is quite similar to the approach Apollo Federation took. So all services have to comply to the Relay Global Object spec and you're ready to go. Nautilus gateway will analyze your services via introspection at startup time and generate the final gateway schema. 94 | 95 | In contrast this library goes a complete different approach. The basic assumption is that your public gateway schema should not be an artifact. The gateway schema is the contract between gateway and clients. The gateway doesn't make any assumptions on your services other than complying to some protocol and some spec. It's a lot more manual work at the beginning but this gives a lot of advantages. Because the gateway is the single source of truth regarding the schema you cannot easily break the contract. With federation an upstream service can directly break the contract. Additionally you're not limited to GraphQL upstreams. While GraphQL upstreams are supported it's only a matter of implementing another DataSource interface to support more upstream protocols, e.g. SOAP, MQTT, KAFKA, Redis etc.. On top of that, because the gateway schema is the single source of truth you'll get two additional benefits. First, you can swap DataSources for a given schema without changing the contract. E.g. you could replace a REST User-Service with a GraphQL User-Service without changing the contract between client and gateway. This could help to easily transition from legacy to more modern architectures. Second, because the gateway owns the schema you can apply features like rate limiting, authorization etc. at the gateway level. 96 | 97 | To conclude, if you have only GraphQL services complying to the Relay Global Object spec and there are no special requirements like rate limiting or authZ you're best off using nautilus as it's a lot easier to get started. 98 | 99 | If you have a heterogenous mesh of services and more specific requirements that would require customizing the schema you'd want to put in the extra effort to configure it all manually in exchange for the benefits described above. 100 | 101 | As a sidenote, nautilus relies on the amazing gqlgen library as well as gqlparser from vektah, both amazing tools which are quire mature I think. In comparison I've implemented the GraphQL spec myself ([graphql-go-tools](https://github.com/jensneuse/graphql-go-tools)) for this specific use case. I've paid extra attention to implement features like parsing/lexing/validation/ast-walking in a zero garbage collection fashion which ultimately leads to better performance and more consistent latencies than every available implementation. I won't add benchmarks here because I'm biased but you're invited to prove me wrong. 102 | -------------------------------------------------------------------------------- /cmd/mqtt.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2019 NAME HERE 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 | package cmd 17 | 18 | import ( 19 | "fmt" 20 | 21 | "github.com/spf13/cobra" 22 | ) 23 | 24 | // mqttCmd represents the mqtt command 25 | var mqttCmd = &cobra.Command{ 26 | Use: "mqtt", 27 | Short: "A brief description of your command", 28 | Long: `A longer description that spans multiple lines and likely contains examples 29 | and usage of using your command. For example: 30 | 31 | Cobra is a CLI library for Go that empowers applications. 32 | This application is a tool to generate the needed files 33 | to quickly create a Cobra application.`, 34 | Run: func(cmd *cobra.Command, args []string) { 35 | fmt.Println("mqtt called") 36 | }, 37 | } 38 | 39 | func init() { 40 | rootCmd.AddCommand(mqttCmd) 41 | 42 | // Here you will define your flags and configuration settings. 43 | 44 | // Cobra supports Persistent Flags which will work for this command 45 | // and all subcommands, e.g.: 46 | // mqttCmd.PersistentFlags().String("foo", "", "A help for foo") 47 | 48 | // Cobra supports local flags which will only run when this command 49 | // is called directly, e.g.: 50 | // mqttCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") 51 | } 52 | -------------------------------------------------------------------------------- /cmd/mqtt.md: -------------------------------------------------------------------------------- 1 | # mqtt 2 | 3 | ## start broker 4 | 5 | ```shell script 6 | docker run -ti -p 1883:1883 -p 9001:9001 toke/mosquitto 7 | ``` -------------------------------------------------------------------------------- /cmd/mqttStartConsumer.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2019 NAME HERE 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 | package cmd 17 | 18 | import ( 19 | "encoding/json" 20 | "fmt" 21 | mqtt "github.com/eclipse/paho.mqtt.golang" 22 | "log" 23 | "os" 24 | "time" 25 | 26 | "github.com/spf13/cobra" 27 | ) 28 | 29 | // mqttStartConsumerCmd represents the mqttStartConsumer command 30 | var mqttStartConsumerCmd = &cobra.Command{ 31 | Use: "startConsumer", 32 | Short: "A brief description of your command", 33 | Long: `A longer description that spans multiple lines and likely contains examples 34 | and usage of using your command. For example: 35 | 36 | Cobra is a CLI library for Go that empowers applications. 37 | This application is a tool to generate the needed files 38 | to quickly create a Cobra application.`, 39 | Run: func(cmd *cobra.Command, args []string) { 40 | fmt.Println("mqtt startConsumer called") 41 | startMQTTConsumer() 42 | }, 43 | } 44 | 45 | func init() { 46 | mqttCmd.AddCommand(mqttStartConsumerCmd) 47 | 48 | // Here you will define your flags and configuration settings. 49 | 50 | // Cobra supports Persistent Flags which will work for this command 51 | // and all subcommands, e.g.: 52 | // mqttStartConsumerCmd.PersistentFlags().String("foo", "", "A help for foo") 53 | 54 | // Cobra supports local flags which will only run when this command 55 | // is called directly, e.g.: 56 | // mqttStartConsumerCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") 57 | } 58 | 59 | func startMQTTConsumer() { 60 | mqtt.DEBUG = log.New(os.Stdout, "", 0) 61 | mqtt.ERROR = log.New(os.Stdout, "", 0) 62 | opts := mqtt.NewClientOptions().AddBroker("tcp://localhost:1883").SetClientID("consumer") 63 | opts.SetKeepAlive(2 * time.Second) 64 | ch := make(chan mqtt.Message) 65 | opts.SetDefaultPublishHandler(func(client mqtt.Client, msg mqtt.Message) { 66 | ch <- msg 67 | msg.Ack() 68 | }) 69 | opts.SetPingTimeout(1 * time.Second) 70 | 71 | c := mqtt.NewClient(opts) 72 | if token := c.Connect(); token.Wait() && token.Error() != nil { 73 | panic(token.Error()) 74 | } 75 | 76 | if token := c.Subscribe("time", 0, nil); token.Wait() && token.Error() != nil { 77 | fmt.Println(token.Error()) 78 | os.Exit(1) 79 | } 80 | 81 | for msg := range ch { 82 | var timeMessage TimeMessage 83 | err := json.Unmarshal(msg.Payload(),&timeMessage) 84 | if err != nil { 85 | panic(err) 86 | } 87 | fmt.Printf("consumed: %+v\n",timeMessage) 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /cmd/mqttStartProducer.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2019 NAME HERE 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 | package cmd 17 | 18 | import ( 19 | "encoding/json" 20 | "fmt" 21 | mqtt "github.com/eclipse/paho.mqtt.golang" 22 | "log" 23 | "os" 24 | "time" 25 | 26 | "github.com/spf13/cobra" 27 | ) 28 | 29 | // mqttStartProducerCmd represents the mqttStartProducer command 30 | var mqttStartProducerCmd = &cobra.Command{ 31 | Use: "startProducer", 32 | Short: "A brief description of your command", 33 | Long: `A longer description that spans multiple lines and likely contains examples 34 | and usage of using your command. For example: 35 | 36 | Cobra is a CLI library for Go that empowers applications. 37 | This application is a tool to generate the needed files 38 | to quickly create a Cobra application.`, 39 | Run: func(cmd *cobra.Command, args []string) { 40 | fmt.Println("mqtt startProducer called") 41 | startMQTTProducer() 42 | }, 43 | } 44 | 45 | func init() { 46 | mqttCmd.AddCommand(mqttStartProducerCmd) 47 | 48 | // Here you will define your flags and configuration settings. 49 | 50 | // Cobra supports Persistent Flags which will work for this command 51 | // and all subcommands, e.g.: 52 | // mqttStartProducerCmd.PersistentFlags().String("foo", "", "A help for foo") 53 | 54 | // Cobra supports local flags which will only run when this command 55 | // is called directly, e.g.: 56 | // mqttStartProducerCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") 57 | } 58 | 59 | func startMQTTProducer() { 60 | mqtt.DEBUG = log.New(os.Stdout, "", 0) 61 | mqtt.ERROR = log.New(os.Stdout, "", 0) 62 | opts := mqtt.NewClientOptions().AddBroker("tcp://localhost:1883").SetClientID("producer") 63 | opts.SetKeepAlive(2 * time.Second) 64 | opts.SetDefaultPublishHandler(func(client mqtt.Client, msg mqtt.Message) { 65 | fmt.Printf("TOPIC: %s\n", msg.Topic()) 66 | fmt.Printf("MSG: %s\n", msg.Payload()) 67 | }) 68 | opts.SetPingTimeout(1 * time.Second) 69 | 70 | c := mqtt.NewClient(opts) 71 | if token := c.Connect(); token.Wait() && token.Error() != nil { 72 | panic(token.Error()) 73 | } 74 | 75 | for { 76 | 77 | message := TimeMessage{ 78 | Time: time.Now(), 79 | } 80 | 81 | data,_ := json.Marshal(message) 82 | 83 | token := c.Publish("time", 0, false, string(data)) 84 | token.Wait() 85 | time.Sleep(time.Second) 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /cmd/nats.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2019 NAME HERE 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 | package cmd 17 | 18 | import ( 19 | "fmt" 20 | 21 | "github.com/spf13/cobra" 22 | ) 23 | 24 | // natsCmd represents the nats command 25 | var natsCmd = &cobra.Command{ 26 | Use: "nats", 27 | Short: "A brief description of your command", 28 | Long: `A longer description that spans multiple lines and likely contains examples 29 | and usage of using your command. For example: 30 | 31 | Cobra is a CLI library for Go that empowers applications. 32 | This application is a tool to generate the needed files 33 | to quickly create a Cobra application.`, 34 | Run: func(cmd *cobra.Command, args []string) { 35 | fmt.Println("nats called") 36 | }, 37 | } 38 | 39 | func init() { 40 | rootCmd.AddCommand(natsCmd) 41 | 42 | // Here you will define your flags and configuration settings. 43 | 44 | // Cobra supports Persistent Flags which will work for this command 45 | // and all subcommands, e.g.: 46 | // natsCmd.PersistentFlags().String("foo", "", "A help for foo") 47 | 48 | // Cobra supports local flags which will only run when this command 49 | // is called directly, e.g.: 50 | // natsCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") 51 | } 52 | -------------------------------------------------------------------------------- /cmd/nats.md: -------------------------------------------------------------------------------- 1 | # nats example 2 | 3 | ## start nats server 4 | 5 | ````shell script 6 | docker run -p -d 4222:4222 nats 7 | ```` 8 | 9 | ## start producer 10 | 11 | ```shell script 12 | go run main.go nats startProducer 13 | ``` 14 | 15 | ## start consumer 16 | 17 | Just in case you'd like to watch the raw nats messages. 18 | 19 | ```shell script 20 | go run main.go nats startConsumer 21 | ``` -------------------------------------------------------------------------------- /cmd/natsStartConsumer.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2019 NAME HERE 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 | package cmd 17 | 18 | import ( 19 | "encoding/json" 20 | "fmt" 21 | "github.com/nats-io/nats.go" 22 | "time" 23 | 24 | "github.com/spf13/cobra" 25 | ) 26 | 27 | // startConsumerCmd represents the startConsumer command 28 | var startConsumerCmd = &cobra.Command{ 29 | Use: "startConsumer", 30 | Short: "A brief description of your command", 31 | Long: `A longer description that spans multiple lines and likely contains examples 32 | and usage of using your command. For example: 33 | 34 | Cobra is a CLI library for Go that empowers applications. 35 | This application is a tool to generate the needed files 36 | to quickly create a Cobra application.`, 37 | Run: func(cmd *cobra.Command, args []string) { 38 | fmt.Println("startConsumer called") 39 | startNatsConsumer() 40 | }, 41 | } 42 | 43 | func init() { 44 | natsCmd.AddCommand(startConsumerCmd) 45 | 46 | // Here you will define your flags and configuration settings. 47 | 48 | // Cobra supports Persistent Flags which will work for this command 49 | // and all subcommands, e.g.: 50 | // startConsumerCmd.PersistentFlags().String("foo", "", "A help for foo") 51 | 52 | // Cobra supports local flags which will only run when this command 53 | // is called directly, e.g.: 54 | // startConsumerCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") 55 | } 56 | 57 | func startNatsConsumer(){ 58 | nc, _ := nats.Connect(nats.DefaultURL) 59 | sub,err := nc.SubscribeSync("time") 60 | if err != nil { 61 | panic(err) 62 | } 63 | for { 64 | msg,err := sub.NextMsg(time.Minute) 65 | if err != nil { 66 | panic(err) 67 | } 68 | var message TimeMessage 69 | err = json.Unmarshal(msg.Data,&message) 70 | if err != nil { 71 | panic(err) 72 | } 73 | fmt.Printf("consumed message: %+v\n",message) 74 | } 75 | } -------------------------------------------------------------------------------- /cmd/natsStartProducer.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2019 NAME HERE 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 | package cmd 17 | 18 | import ( 19 | "encoding/json" 20 | "fmt" 21 | "github.com/nats-io/nats.go" 22 | "github.com/spf13/cobra" 23 | "time" 24 | ) 25 | 26 | // startProducerCmd represents the startProducer command 27 | var startProducerCmd = &cobra.Command{ 28 | Use: "startProducer", 29 | Short: "A brief description of your command", 30 | Long: `A longer description that spans multiple lines and likely contains examples 31 | and usage of using your command. For example: 32 | 33 | Cobra is a CLI library for Go that empowers applications. 34 | This application is a tool to generate the needed files 35 | to quickly create a Cobra application.`, 36 | Run: func(cmd *cobra.Command, args []string) { 37 | fmt.Println("startProducer called") 38 | startNatsProducer() 39 | }, 40 | } 41 | 42 | func init() { 43 | natsCmd.AddCommand(startProducerCmd) 44 | 45 | // Here you will define your flags and configuration settings. 46 | 47 | // Cobra supports Persistent Flags which will work for this command 48 | // and all subcommands, e.g.: 49 | // startProducerCmd.PersistentFlags().String("foo", "", "A help for foo") 50 | 51 | // Cobra supports local flags which will only run when this command 52 | // is called directly, e.g.: 53 | // startProducerCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") 54 | } 55 | 56 | type TimeMessage struct { 57 | Time time.Time 58 | } 59 | 60 | func startNatsProducer(){ 61 | nc, _ := nats.Connect(nats.DefaultURL) 62 | for { 63 | message := TimeMessage{ 64 | Time:time.Now(), 65 | } 66 | data,err := json.Marshal(message) 67 | if err != nil { 68 | panic(err) 69 | } 70 | err = nc.Publish("time",data) 71 | if err != nil { 72 | panic(err) 73 | } 74 | 75 | fmt.Printf("produced message: %+v\n",message) 76 | 77 | time.Sleep(time.Second * time.Duration(1)) 78 | } 79 | } -------------------------------------------------------------------------------- /cmd/root.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2019 Jens Neuse 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | */ 22 | package cmd 23 | 24 | import ( 25 | "fmt" 26 | "os" 27 | "github.com/spf13/cobra" 28 | 29 | homedir "github.com/mitchellh/go-homedir" 30 | "github.com/spf13/viper" 31 | 32 | ) 33 | 34 | 35 | var cfgFile string 36 | 37 | 38 | // rootCmd represents the base command when called without any subcommands 39 | var rootCmd = &cobra.Command{ 40 | Use: "graphql-gateway", 41 | Short: "A brief description of your application", 42 | Long: `A longer description that spans multiple lines and likely contains 43 | examples and usage of using your application. For example: 44 | 45 | Cobra is a CLI library for Go that empowers applications. 46 | This application is a tool to generate the needed files 47 | to quickly create a Cobra application.`, 48 | // Uncomment the following line if your bare application 49 | // has an action associated with it: 50 | // Run: func(cmd *cobra.Command, args []string) { }, 51 | } 52 | 53 | // Execute adds all child commands to the root command and sets flags appropriately. 54 | // This is called by main.main(). It only needs to happen once to the rootCmd. 55 | func Execute() { 56 | if err := rootCmd.Execute(); err != nil { 57 | fmt.Println(err) 58 | os.Exit(1) 59 | } 60 | } 61 | 62 | func init() { 63 | cobra.OnInitialize(initConfig) 64 | 65 | // Here you will define your flags and configuration settings. 66 | // Cobra supports persistent flags, which, if defined here, 67 | // will be global for your application. 68 | 69 | rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.graphql-gateway.yaml)") 70 | 71 | 72 | // Cobra also supports local flags, which will only run 73 | // when this action is called directly. 74 | rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") 75 | } 76 | 77 | 78 | // initConfig reads in config file and ENV variables if set. 79 | func initConfig() { 80 | if cfgFile != "" { 81 | // Use config file from the flag. 82 | viper.SetConfigFile(cfgFile) 83 | } else { 84 | // Find home directory. 85 | home, err := homedir.Dir() 86 | if err != nil { 87 | fmt.Println(err) 88 | os.Exit(1) 89 | } 90 | 91 | // Search config in home directory with name ".graphql-gateway" (without extension). 92 | viper.AddConfigPath(home) 93 | viper.SetConfigName(".graphql-gateway") 94 | } 95 | 96 | viper.AutomaticEnv() // read in environment variables that match 97 | 98 | // If a config file is found, read it in. 99 | if err := viper.ReadInConfig(); err == nil { 100 | fmt.Println("Using config file:", viper.ConfigFileUsed()) 101 | } 102 | } 103 | 104 | -------------------------------------------------------------------------------- /cmd/serve.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "github.com/gobwas/ws" 7 | log "github.com/jensneuse/abstractlogger" 8 | "github.com/jensneuse/graphql-go-tools/pkg/execution" 9 | gqlHTTP "github.com/jensneuse/graphql-go-tools/pkg/http" 10 | "github.com/jensneuse/graphql-go-tools/pkg/playground" 11 | "github.com/spf13/viper" 12 | "go.uber.org/zap" 13 | "io/ioutil" 14 | "net/http" 15 | "strings" 16 | "time" 17 | 18 | "github.com/spf13/cobra" 19 | ) 20 | 21 | // serveCmd represents the serve command 22 | var serveCmd = &cobra.Command{ 23 | Use: "serve", 24 | Short: "starts the gateway", 25 | Run: func(cmd *cobra.Command, args []string) { 26 | startServer() 27 | }, 28 | } 29 | 30 | var ( 31 | schemaFile string 32 | loggerConfigFile string 33 | ) 34 | 35 | func init() { 36 | rootCmd.AddCommand(serveCmd) 37 | serveCmd.PersistentFlags().StringVar(&schemaFile, "schema", "./schema.graphql", "schema is the configuration file") 38 | serveCmd.PersistentFlags().StringVar(&loggerConfigFile, "loggerConfig", "./logger.config.json", "configures the logger") 39 | _ = viper.BindPFlag("schema", rootCmd.PersistentFlags().Lookup("schema")) 40 | _ = viper.BindPFlag("loggerConfig", rootCmd.PersistentFlags().Lookup("loggerConfig")) 41 | } 42 | 43 | func logger() log.Logger { 44 | configData, err := ioutil.ReadFile(loggerConfigFile) 45 | if err != nil { 46 | panic(err) 47 | } 48 | var cfg zap.Config 49 | if err := json.Unmarshal(configData, &cfg); err != nil { 50 | panic(err) 51 | } 52 | logger, err := cfg.Build() 53 | if err != nil { 54 | panic(err) 55 | } 56 | return log.NewZapLogger(logger,log.DebugLevel) 57 | } 58 | 59 | func startServer() { 60 | 61 | logger := logger() 62 | logger.Info("logger initialized") 63 | 64 | mux := http.NewServeMux() 65 | graphqlEndpoint := "/graphql" 66 | schemaData, err := ioutil.ReadFile(schemaFile) 67 | if err != nil { 68 | logger.Fatal("reading schema",log.Error(err)) 69 | } 70 | handler, err := execution.NewHandler(schemaData, logger) 71 | if err != nil { 72 | logger.Fatal("creating handler",log.Error(err)) 73 | } 74 | 75 | upgrader := &ws.DefaultHTTPUpgrader 76 | upgrader.Header = http.Header{} 77 | upgrader.Header.Add("Sec-Websocket-Protocol", "graphql-ws") 78 | mux.HandleFunc("/time", func(writer http.ResponseWriter, request *http.Request) { 79 | _, err := writer.Write(fakeResponse()) 80 | if err != nil { 81 | logger.Error("time_write_err", 82 | log.Error(err), 83 | ) 84 | } 85 | }) 86 | mux.Handle(graphqlEndpoint, gqlHTTP.NewGraphqlHTTPHandlerFunc(handler, logger, upgrader)) 87 | playgroundURLPrefix := "/playground" 88 | playgroundURL := "" 89 | err = playground.ConfigureHandlers(mux, playground.Config{ 90 | URLPrefix: playgroundURLPrefix, 91 | PlaygroundURL: playgroundURL, 92 | GraphqlEndpoint: graphqlEndpoint, 93 | GraphQLSubscriptionEndpoint: graphqlEndpoint, 94 | }) 95 | if err != nil { 96 | logger.Fatal("configure handlers",log.Error(err)) 97 | return 98 | } 99 | addr := "0.0.0.0:9111" 100 | logger.Info("Listening", 101 | log.String("add", addr), 102 | ) 103 | fmt.Printf("Access Playground on: http://%s%s%s\n", prettyAddr(addr), playgroundURLPrefix, playgroundURL) 104 | logger.Fatal("failed listening", 105 | log.Error(http.ListenAndServe(addr, mux)), 106 | ) 107 | } 108 | 109 | func fakeResponse() []byte { 110 | return []byte(`{"week_number":45,"utc_offset":"+01:00","utc_datetime":"2019-11-07T14:02:02.475928+00:00","unixtime":1573135322,"timezone":"Europe/Berlin","raw_offset":3600,"dst_until":null,"dst_offset":0,"dst_from":null,"dst":false,"day_of_year":311,"day_of_week":4,"datetime":"` + time.Now().String() + `","client_ip":"92.216.144.100","abbreviation":"CET"}`) 111 | } 112 | 113 | func prettyAddr(addr string) string { 114 | return strings.Replace(addr, "0.0.0.0", "localhost", -1) 115 | } 116 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/jensneuse/graphql-gateway 2 | 3 | go 1.15 4 | 5 | require ( 6 | github.com/buger/jsonparser v0.0.0-20191004114745-ee4c978eae7e // indirect 7 | github.com/eclipse/paho.mqtt.golang v1.2.0 8 | github.com/gobuffalo/envy v1.7.1 // indirect 9 | github.com/gobwas/ws v1.0.2 10 | github.com/jensneuse/abstractlogger v0.0.4 11 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20200115132524-2cb19fec47c7 12 | github.com/magiconair/properties v1.8.1 // indirect 13 | github.com/mitchellh/go-homedir v1.1.0 14 | github.com/nats-io/nats.go v1.9.1 15 | github.com/pelletier/go-toml v1.6.0 // indirect 16 | github.com/rogpeppe/go-internal v1.5.0 // indirect 17 | github.com/spf13/afero v1.2.2 // indirect 18 | github.com/spf13/cobra v0.0.5 19 | github.com/spf13/pflag v1.0.5 // indirect 20 | github.com/spf13/viper v1.4.0 21 | github.com/wasmerio/go-ext-wasm v0.3.1 // indirect 22 | go.uber.org/zap v1.13.0 23 | golang.org/x/text v0.3.2 // indirect 24 | ) 25 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 3 | github.com/Masterminds/goutils v1.1.0 h1:zukEsf/1JZwCMgHiK3GZftabmxiCw4apj3a28RPBiVg= 4 | github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= 5 | github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= 6 | github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= 7 | github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60= 8 | github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= 9 | github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= 10 | github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 11 | github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= 12 | github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= 13 | github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= 14 | github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= 15 | github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23 h1:D21IyuvjDCshj1/qq+pCNd3VZOAEI9jy6Bi131YlXgI= 16 | github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= 17 | github.com/buger/jsonparser v0.0.0-20191004114745-ee4c978eae7e h1:oJCXMss/3rg5F6Poy9wG3JQusc58Mzk5B9Z6wSnssNE= 18 | github.com/buger/jsonparser v0.0.0-20191004114745-ee4c978eae7e/go.mod h1:errmMKH8tTB49UR2A8C8DPYkyudelsYJwJFaZHQ6ik8= 19 | github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= 20 | github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= 21 | github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= 22 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 23 | github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= 24 | github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= 25 | github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= 26 | github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= 27 | github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= 28 | github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= 29 | github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= 30 | github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= 31 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 32 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 33 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 34 | github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= 35 | github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= 36 | github.com/eclipse/paho.mqtt.golang v1.2.0 h1:1F8mhG9+aO5/xpdtFkW4SxOJB67ukuDC3t2y2qayIX0= 37 | github.com/eclipse/paho.mqtt.golang v1.2.0/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts= 38 | github.com/fauna/faunadb-go v2.0.1-0.20190528212028-db401cd29d12+incompatible/go.mod h1:WYAh1hNDFEgbsKKeUhsHPGIFkpQ1CGn/5XejAFfOhHg= 39 | github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= 40 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 41 | github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 42 | github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= 43 | github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= 44 | github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= 45 | github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= 46 | github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= 47 | github.com/gobuffalo/envy v1.7.0 h1:GlXgaiBkmrYMHco6t4j7SacKO4XUjvh5pwXh0f4uxXU= 48 | github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= 49 | github.com/gobuffalo/envy v1.7.1 h1:OQl5ys5MBea7OGCdvPbBJWRgnhC/fGona6QKfvFeau8= 50 | github.com/gobuffalo/envy v1.7.1/go.mod h1:FurDp9+EDPE4aIUS3ZLyD+7/9fpx7YRt/ukY6jIHf0w= 51 | github.com/gobuffalo/logger v1.0.0/go.mod h1:2zbswyIUa45I+c+FLXuWl9zSWEiVuthsk8ze5s8JvPs= 52 | github.com/gobuffalo/packd v0.3.0 h1:eMwymTkA1uXsqxS0Tpoop3Lc0u3kTfiMBE6nKtQU4g4= 53 | github.com/gobuffalo/packd v0.3.0/go.mod h1:zC7QkmNkYVGKPw4tHpBQ+ml7W/3tIebgeo1b36chA3Q= 54 | github.com/gobuffalo/packr v1.30.1 h1:hu1fuVR3fXEZR7rXNW3h8rqSML8EVAf6KNm0NKO/wKg= 55 | github.com/gobuffalo/packr v1.30.1/go.mod h1:ljMyFO2EcrnzsHsN99cvbq055Y9OhRrIaviy289eRuk= 56 | github.com/gobuffalo/packr/v2 v2.5.1/go.mod h1:8f9c96ITobJlPzI44jj+4tHnEKNt0xXWSVlXRN9X1Iw= 57 | github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0= 58 | github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= 59 | github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8= 60 | github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= 61 | github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo= 62 | github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= 63 | github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= 64 | github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= 65 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 66 | github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 67 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 68 | github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 69 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 70 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 71 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 72 | github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 73 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 74 | github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= 75 | github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= 76 | github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 77 | github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= 78 | github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= 79 | github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= 80 | github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= 81 | github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= 82 | github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= 83 | github.com/huandu/xstrings v1.2.1 h1:v6IdmkCnDhJG/S0ivr58PeIfg+tyhqQYy4YsCsQ0Pdc= 84 | github.com/huandu/xstrings v1.2.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= 85 | github.com/imdario/mergo v0.3.8 h1:CGgOkSJeqMRmt0D9XLWExdT4m4F1vd3FV3VPt+0VxkQ= 86 | github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= 87 | github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= 88 | github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= 89 | github.com/jensneuse/abstractlogger v0.0.4 h1:sa4EH8fhWk3zlTDbSncaWKfwxYM8tYSlQ054ETLyyQY= 90 | github.com/jensneuse/abstractlogger v0.0.4/go.mod h1:6WuamOHuykJk8zED/R0LNiLhWR6C7FIAo43ocUEB3mo= 91 | github.com/jensneuse/diffview v1.0.0/go.mod h1:i6IacuD8LnEaPuiyzMHA+Wfz5mAuycMOf3R/orUY9y4= 92 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191027145825-a4372b9a3b39 h1:wi5xeEkdBURcj+oQ5tUu6HNqhxwpGhfylIyqvqPqPUY= 93 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191027145825-a4372b9a3b39/go.mod h1:eSQ22FOZShZPIisYCT2/ZpnFKqumySc3Kp7Zdw0+mEA= 94 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191028082415-8820c270443a h1:M2gPrgdQlozaNicmXUDlHRqTdTTj7JADLIi28iMpwiI= 95 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191028082415-8820c270443a/go.mod h1:MVY07TQITImlYTWr5lnEFNVCRDYLFoMgjc2mLbWCsB8= 96 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191028110544-d8e155d98ca6 h1:/9zfUHAjSC+HzIAZ615xluA9vRnN5HN6F5Nk9Rgs4UI= 97 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191028110544-d8e155d98ca6/go.mod h1:MVY07TQITImlYTWr5lnEFNVCRDYLFoMgjc2mLbWCsB8= 98 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191104205606-81115e714e46 h1:nNBIbKFKVy4kVxoWwlM0AvkBoYBkrRe9icC6v2FimC8= 99 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191104205606-81115e714e46/go.mod h1:bwiXNgOHeNJ5/zTpfG7wuCf+iJbbRhGQjQivSI2oPNA= 100 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191104211029-f5b9594e7d16 h1:KI+8BRsU7KcLdAO49ct8/O1X1T3rI8LADENf2VpPvw0= 101 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191104211029-f5b9594e7d16/go.mod h1:bwiXNgOHeNJ5/zTpfG7wuCf+iJbbRhGQjQivSI2oPNA= 102 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191105141156-fd04e65fa021 h1:IX0KJ2tqbK7cZj6Z1rcZH/bOmWwmVyj1DWwGE+cs5aY= 103 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191105141156-fd04e65fa021/go.mod h1:bwiXNgOHeNJ5/zTpfG7wuCf+iJbbRhGQjQivSI2oPNA= 104 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191105155414-a934882cd4d5 h1:3ZFii6vRZk0r70Oro1eI8sTspIXE4k17/kqiE8pJk10= 105 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191105155414-a934882cd4d5/go.mod h1:bwiXNgOHeNJ5/zTpfG7wuCf+iJbbRhGQjQivSI2oPNA= 106 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191105160039-0ae606645aca h1:mS5eRvLLzpRNDzsWUFvUFZrwRxCW5iggCnTuohtNWeU= 107 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191105160039-0ae606645aca/go.mod h1:bwiXNgOHeNJ5/zTpfG7wuCf+iJbbRhGQjQivSI2oPNA= 108 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191105162332-f05b38c8be09 h1:fuF1NQVoDvYM+yZP0g/w7rOVlrhzQljMJq0TmLPbcqI= 109 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191105162332-f05b38c8be09/go.mod h1:bwiXNgOHeNJ5/zTpfG7wuCf+iJbbRhGQjQivSI2oPNA= 110 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191105163052-cbd4cbe9fcc9/go.mod h1:bwiXNgOHeNJ5/zTpfG7wuCf+iJbbRhGQjQivSI2oPNA= 111 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191105170045-2cbdb4eb7987 h1:xOuaTMxKKvLPH1JzzmbD+BBlDDoZs8GTrNTDlErNzjQ= 112 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191105170045-2cbdb4eb7987/go.mod h1:bwiXNgOHeNJ5/zTpfG7wuCf+iJbbRhGQjQivSI2oPNA= 113 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191105174048-bed36546a466 h1:KKHNIJBvanzzlXoxiiIe4xOy6fSwM0/uHf5zvIyFYR0= 114 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191105174048-bed36546a466/go.mod h1:bwiXNgOHeNJ5/zTpfG7wuCf+iJbbRhGQjQivSI2oPNA= 115 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191106072144-a0d797cc0613 h1:83avfLyYx66Y3YLpNkkWWFBGxHKGv+bgej9UmjcaiMU= 116 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191106072144-a0d797cc0613/go.mod h1:bwiXNgOHeNJ5/zTpfG7wuCf+iJbbRhGQjQivSI2oPNA= 117 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191106072647-38e87afa7181 h1:pUBQf1UTYMr/GSV1xERUgXoOS1GJSOnrCmfZlkPCQbg= 118 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191106072647-38e87afa7181/go.mod h1:bwiXNgOHeNJ5/zTpfG7wuCf+iJbbRhGQjQivSI2oPNA= 119 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191106074401-d95e063340e9 h1:nVFKFWIzQ039l9LCMV6vjfpM2V1jGMxVR2/x5FYM+94= 120 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191106074401-d95e063340e9/go.mod h1:bwiXNgOHeNJ5/zTpfG7wuCf+iJbbRhGQjQivSI2oPNA= 121 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191106075427-4834f2973eca h1:nz6A6PUS37V5IDuRAry7IdeCt6IxMK6eg7euAQo88KE= 122 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191106075427-4834f2973eca/go.mod h1:bwiXNgOHeNJ5/zTpfG7wuCf+iJbbRhGQjQivSI2oPNA= 123 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191106075938-5a0d9bbae3de h1:AC7U20VegVIPclEgw/uLB5Ro9VGPwixm2zcswB49IAw= 124 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191106075938-5a0d9bbae3de/go.mod h1:bwiXNgOHeNJ5/zTpfG7wuCf+iJbbRhGQjQivSI2oPNA= 125 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191106080342-61f93f08ba96 h1:bGNKuTpWwrrayEdaeQcpwZi6oz2Z+fyiDIM611WQD5Q= 126 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191106080342-61f93f08ba96/go.mod h1:bwiXNgOHeNJ5/zTpfG7wuCf+iJbbRhGQjQivSI2oPNA= 127 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191106081250-347abe23e8cd h1:VxPJVQem2HjdS1HcGTzvJpX6UsiJiW+zx1ga5W5Q9bo= 128 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191106081250-347abe23e8cd/go.mod h1:bwiXNgOHeNJ5/zTpfG7wuCf+iJbbRhGQjQivSI2oPNA= 129 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191106082227-5a803e871324 h1:RBFAuc66A4qz4Rs6bHeHBjfIA3pnynFLWJV82gfHJ2g= 130 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191106082227-5a803e871324/go.mod h1:bwiXNgOHeNJ5/zTpfG7wuCf+iJbbRhGQjQivSI2oPNA= 131 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191106083001-1b6cc83ddf98 h1:HjwjuelqTQNieoH5sJ6CAlQicHjFNpUY/uK9Uf5iWdE= 132 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191106083001-1b6cc83ddf98/go.mod h1:bwiXNgOHeNJ5/zTpfG7wuCf+iJbbRhGQjQivSI2oPNA= 133 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191106083604-a994b20e1019 h1:GM06GcgKnIwcRpZiHYZjb6qgE2ZyuhR7kpoFf+uRAiI= 134 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191106083604-a994b20e1019/go.mod h1:bwiXNgOHeNJ5/zTpfG7wuCf+iJbbRhGQjQivSI2oPNA= 135 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191106084255-63637a60dd70 h1:dHmdx/4wNj7OZIO9jG98E32POwwBxTMi51RWjmUTMZ8= 136 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191106084255-63637a60dd70/go.mod h1:bwiXNgOHeNJ5/zTpfG7wuCf+iJbbRhGQjQivSI2oPNA= 137 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191106085024-6d41a327fab4 h1:QcGP4Xz2bXhuiQMYEgK3VXpD6bMnxGE2EbKBRjsTfPo= 138 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191106085024-6d41a327fab4/go.mod h1:bwiXNgOHeNJ5/zTpfG7wuCf+iJbbRhGQjQivSI2oPNA= 139 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191107113820-fd2c22131515 h1:cFKdFtnqi7B8UtSHjQOtC1a5QVKpbeLFiOSavAUkKPA= 140 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191107113820-fd2c22131515/go.mod h1:0LvRsc/ug52VbHlsdCr8hl9/ClNUPExce4MOOEPNogE= 141 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191107115943-77d3200424b5 h1:i3aqUQvMr/0E/XLldWiLGygggllv62E/iZmCMdjSZd8= 142 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191107115943-77d3200424b5/go.mod h1:tdw/5PykMKiGiylfRhyHR73nfe+NGL6nn/inGGQ2XFE= 143 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191107121610-624d137b8d49 h1:neCYnyb+03sDDWKT06k4tkobKW5nWGKAX4W4z+ygI44= 144 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191107121610-624d137b8d49/go.mod h1:tdw/5PykMKiGiylfRhyHR73nfe+NGL6nn/inGGQ2XFE= 145 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191107123249-6c6d0f06664c h1:T1xAjOCuuyQjqPn/FnzsuFU4HxdCe3i4emlGJo48Y4o= 146 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191107123249-6c6d0f06664c/go.mod h1:tdw/5PykMKiGiylfRhyHR73nfe+NGL6nn/inGGQ2XFE= 147 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191107135238-a38ed86c1a56 h1:LxzDVK/T6xbXoZhqSob1NOYBEGQ7yd2/AC7m5xu4e6o= 148 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191107135238-a38ed86c1a56/go.mod h1:tdw/5PykMKiGiylfRhyHR73nfe+NGL6nn/inGGQ2XFE= 149 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191107135629-a99f51a5f574 h1:kBAWm9KbUAgWDRzQWafffHMxdZOQSqhZ4fQ8OIHRuWk= 150 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191107135629-a99f51a5f574/go.mod h1:tdw/5PykMKiGiylfRhyHR73nfe+NGL6nn/inGGQ2XFE= 151 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191107135917-5124167e086d h1:/9f+BgLcKYKxomckAEPELWO5jN8KkxWOJkOnqlG3a5U= 152 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191107135917-5124167e086d/go.mod h1:tdw/5PykMKiGiylfRhyHR73nfe+NGL6nn/inGGQ2XFE= 153 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191107141405-00336ea6d81e h1:j+2jBs4Ro4mz8xSdXtptlpv/xy0nxwGD7dRgY4e80AQ= 154 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191107141405-00336ea6d81e/go.mod h1:tdw/5PykMKiGiylfRhyHR73nfe+NGL6nn/inGGQ2XFE= 155 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191107141738-6af8ce41d88a h1:mlZxsVoBcs+AxWBaFbfeBLeA7BJbSy+WGFotvIw4exE= 156 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191107141738-6af8ce41d88a/go.mod h1:tdw/5PykMKiGiylfRhyHR73nfe+NGL6nn/inGGQ2XFE= 157 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191107142948-3abf364078fb h1:KFpDLDDmHx9JXEHv0/NRGlWZU4cR7PcdB1UEpdNJ5us= 158 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191107142948-3abf364078fb/go.mod h1:tdw/5PykMKiGiylfRhyHR73nfe+NGL6nn/inGGQ2XFE= 159 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191107145304-1df5f6a916eb h1:4pLS3/VJtFjROksUrgGgEbHCuTOgkaNvO+nW7KFacTc= 160 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191107145304-1df5f6a916eb/go.mod h1:tdw/5PykMKiGiylfRhyHR73nfe+NGL6nn/inGGQ2XFE= 161 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191110100631-52bb0084b31c h1:YmAktMeeKXgBFnpBP8AAB0HSIazyLSQE2ufYjwalANY= 162 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191110100631-52bb0084b31c/go.mod h1:tdw/5PykMKiGiylfRhyHR73nfe+NGL6nn/inGGQ2XFE= 163 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191110103104-4618afce2edd h1:MhCSkik89plcy3KdRU2Rv1yL8fU/YuMyzN0nlWOU7Lo= 164 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191110103104-4618afce2edd/go.mod h1:tdw/5PykMKiGiylfRhyHR73nfe+NGL6nn/inGGQ2XFE= 165 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191110112223-bcb51850b6cc h1:PgR3Xv9PHGSL+NeFSvsfEPULm5QrCPGlkfde5335nK8= 166 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191110112223-bcb51850b6cc/go.mod h1:tdw/5PykMKiGiylfRhyHR73nfe+NGL6nn/inGGQ2XFE= 167 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191110121827-1f6904cefcf9 h1:+2sb5/kVsRAkR2Wr2p2HamwlhssyPGoL9KTdp6T0QMQ= 168 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191110121827-1f6904cefcf9/go.mod h1:tdw/5PykMKiGiylfRhyHR73nfe+NGL6nn/inGGQ2XFE= 169 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191112113933-60c5af42e080 h1:tWYXXAkCdfpKot5ClpWRwb5YfWKZp+J58UoRbxpXnYU= 170 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191112113933-60c5af42e080/go.mod h1:tdw/5PykMKiGiylfRhyHR73nfe+NGL6nn/inGGQ2XFE= 171 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191128135457-3a499a5350d5 h1:kdQ4n2afzFsVByWvxsI8EPO1tW3PiSwlBhdneYf5HJo= 172 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191128135457-3a499a5350d5/go.mod h1:tdw/5PykMKiGiylfRhyHR73nfe+NGL6nn/inGGQ2XFE= 173 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191201102959-f5819e1741ce h1:vKa/96WNColPO9BII+gPn3trE8N4wwj/tMLiOu92VTs= 174 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191201102959-f5819e1741ce/go.mod h1:tdw/5PykMKiGiylfRhyHR73nfe+NGL6nn/inGGQ2XFE= 175 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191201115034-a3acb38a8705 h1:d8GuqvT8CkHvz9SkUFKSQ1tgoGFEChv7XkHIBwEVc3s= 176 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191201115034-a3acb38a8705/go.mod h1:tdw/5PykMKiGiylfRhyHR73nfe+NGL6nn/inGGQ2XFE= 177 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191201123430-8079bbf5422b h1:48EsNI8qWBTVvbG45r+9pr+ywJe9WFvPidx1ZcsWt8Y= 178 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191201123430-8079bbf5422b/go.mod h1:tdw/5PykMKiGiylfRhyHR73nfe+NGL6nn/inGGQ2XFE= 179 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191201124936-5eac7b00c11a h1:baN2xJXOQdGxf7HqGLCJ1F6VD1oJ0JGH1yCHwnliLqQ= 180 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191201124936-5eac7b00c11a/go.mod h1:tdw/5PykMKiGiylfRhyHR73nfe+NGL6nn/inGGQ2XFE= 181 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191201125532-9844f699ef49 h1:WoNxsSG0rJEKC8gWIrvZ1W1RWM0ZAKWbzLiCo9EK40Q= 182 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191201125532-9844f699ef49/go.mod h1:tdw/5PykMKiGiylfRhyHR73nfe+NGL6nn/inGGQ2XFE= 183 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191201130149-db8e785954af h1:23jH+Y+JprIXrG2g6knXBP4Hgtxsxn8agj+6dG0bNCY= 184 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191201130149-db8e785954af/go.mod h1:tdw/5PykMKiGiylfRhyHR73nfe+NGL6nn/inGGQ2XFE= 185 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191202074336-eb0951db4eb7 h1:G6K6JFp1u6JGMhNAWUDbXys4fU1GpMGKSq2XFSz+Pqc= 186 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191202074336-eb0951db4eb7/go.mod h1:tdw/5PykMKiGiylfRhyHR73nfe+NGL6nn/inGGQ2XFE= 187 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191202103943-68e745af8893 h1:wkK2HIJrmIcUPS9N66wK2+/o3eRqHC0CVr2X4mFykLg= 188 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191202103943-68e745af8893/go.mod h1:BuKOrbohnqflSY4wY8tsBG/b5lvXNPe9yhfO72kugr8= 189 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191202130603-14f2e2337225 h1:52BsvcQScO669heTaT0O3s/qzp3lN7VBe8SJUwpNfyM= 190 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191202130603-14f2e2337225/go.mod h1:BuKOrbohnqflSY4wY8tsBG/b5lvXNPe9yhfO72kugr8= 191 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191202150321-019706357c01 h1:sRw8ZrqP+WtNAEXF+su8A+FpOpbnywdC8EH85f96zG0= 192 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191202150321-019706357c01/go.mod h1:BuKOrbohnqflSY4wY8tsBG/b5lvXNPe9yhfO72kugr8= 193 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191202154600-dd4c38efa6f0 h1:XNZ7U12ImRPP2EGSQRGVga/SkUc6V/hUTkziKqi3iKM= 194 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191202154600-dd4c38efa6f0/go.mod h1:BuKOrbohnqflSY4wY8tsBG/b5lvXNPe9yhfO72kugr8= 195 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191204094855-24d24950e6b9 h1:AmOU2TXHpiN5jX9SECy7l0G2pY1UE0vIhdnCXK4nAqg= 196 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191204094855-24d24950e6b9/go.mod h1:na8VNl4dA8Q+Z9yujs570ILvxQlGMkM3PuWWg5B7ZWw= 197 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191204135148-8d622f11a8c3 h1:ws7U9+Fm9Frf04FaVq/fJo3+0v23DQleUIT/C0bkImg= 198 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191204135148-8d622f11a8c3/go.mod h1:na8VNl4dA8Q+Z9yujs570ILvxQlGMkM3PuWWg5B7ZWw= 199 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191204161338-6fda1b395e06 h1:XQFnQzunUa3YrbhSVwX5NFvtGnn+dLFaoHIX8lnBOfs= 200 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191204161338-6fda1b395e06/go.mod h1:Y6k/0HGM6BllZrR7XdjboyD9JvPmmQbK+adnDVdtzGc= 201 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191204163605-49790e3c35b3 h1:9rMGfZ7sgvlug72poI3iJUN8wS3ASbnydqIDTp02Z8U= 202 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191204163605-49790e3c35b3/go.mod h1:Y6k/0HGM6BllZrR7XdjboyD9JvPmmQbK+adnDVdtzGc= 203 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191204163857-3f98a173cb46 h1:zzYGZCmFb8NefPrIf78maHIqcSdBmzFWQB31P3iyeOw= 204 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191204163857-3f98a173cb46/go.mod h1:Y6k/0HGM6BllZrR7XdjboyD9JvPmmQbK+adnDVdtzGc= 205 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191204164031-0596409f78b1 h1:ggoe7soZHSlVT81yWMXp1dQtxLRM1/2cIu5Qapb8IoI= 206 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191204164031-0596409f78b1/go.mod h1:Y6k/0HGM6BllZrR7XdjboyD9JvPmmQbK+adnDVdtzGc= 207 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191204164220-8864c86914a8 h1:7wDPlBO/nmEy4ss06K2xLhuFM5uGfPe1fqJPjgbNuXw= 208 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191204164220-8864c86914a8/go.mod h1:Y6k/0HGM6BllZrR7XdjboyD9JvPmmQbK+adnDVdtzGc= 209 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191204164852-708fb8da48bf h1:Rq1ivQJDko5oRLbkExXVd0lHQXf7047IIiASltL9jCM= 210 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191204164852-708fb8da48bf/go.mod h1:Y6k/0HGM6BllZrR7XdjboyD9JvPmmQbK+adnDVdtzGc= 211 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191204165546-6287426d87af h1:PdhP3nDIV/pYFOHMVyR2CkSEL6GSgy9VrHsykBKML/Y= 212 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191204165546-6287426d87af/go.mod h1:Y6k/0HGM6BllZrR7XdjboyD9JvPmmQbK+adnDVdtzGc= 213 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191204165732-19ecc955fcac h1:kNDk4xu1jbIjrWlbf1tKEUs5QWBE8oqw0VMSbD4XhXM= 214 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191204165732-19ecc955fcac/go.mod h1:Y6k/0HGM6BllZrR7XdjboyD9JvPmmQbK+adnDVdtzGc= 215 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191206110844-687e47e1eb95 h1:18X4BTnYFVHxEHgQNSQ+1PYKXljElERiGX7fnCNExv0= 216 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191206110844-687e47e1eb95/go.mod h1:Y6k/0HGM6BllZrR7XdjboyD9JvPmmQbK+adnDVdtzGc= 217 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191206114750-3286a9d69271 h1:76SteTxFJOrkG6MGvuaJw+85kYxd2KZwipoOGR/sVu4= 218 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191206114750-3286a9d69271/go.mod h1:Y6k/0HGM6BllZrR7XdjboyD9JvPmmQbK+adnDVdtzGc= 219 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191206115002-18c43eaa9efc h1:lRhWZ0nZ3eKqpRvipbBQDEiBFWq4ht3YZhCNjZbPMtE= 220 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191206115002-18c43eaa9efc/go.mod h1:Y6k/0HGM6BllZrR7XdjboyD9JvPmmQbK+adnDVdtzGc= 221 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191206115548-4408ea501560 h1:uQa3LSVAafyiFoYhmJerRNCb4l0uqKCFXYYQB/nFUOk= 222 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191206115548-4408ea501560/go.mod h1:Y6k/0HGM6BllZrR7XdjboyD9JvPmmQbK+adnDVdtzGc= 223 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191206120251-8fdff248fada h1:f2pO62sL5RQzYYaNz3xDzb6QsFwBBgtJtC3Qp1Jd/NY= 224 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191206120251-8fdff248fada/go.mod h1:Y6k/0HGM6BllZrR7XdjboyD9JvPmmQbK+adnDVdtzGc= 225 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191206120910-42d7dc498650 h1:LS9X7PsQg0GF27AVvrYeo10nGwbNdZRA84DjMkbSBLI= 226 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191206120910-42d7dc498650/go.mod h1:Y6k/0HGM6BllZrR7XdjboyD9JvPmmQbK+adnDVdtzGc= 227 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191208124515-106fc5632957 h1:nrjmgN/Jg6NayFGumUQyXq8sFKKMh4TcgMYkeDIvPcM= 228 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191208124515-106fc5632957/go.mod h1:Y6k/0HGM6BllZrR7XdjboyD9JvPmmQbK+adnDVdtzGc= 229 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191210100247-395fc5ca3e66 h1:u1BpW3x/t1N5EmKW/BPg4xZWogbgobUD8UD+6A+ne/c= 230 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191210100247-395fc5ca3e66/go.mod h1:YU7k8fkeMqJx4Wh4eF6ygYj1MIo4/6QcCf+Q3P1W0zw= 231 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191210101333-4348f8a69922 h1:WBx2pDYTIxKXUAluEromOpSQ/7wrKmb2AUZKChtChs4= 232 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191210101333-4348f8a69922/go.mod h1:YU7k8fkeMqJx4Wh4eF6ygYj1MIo4/6QcCf+Q3P1W0zw= 233 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191210101603-dd6a2e8934f6 h1:7rvtdfvh/k+dRLIhzcGmXJDYwQEtgqEBJ3f7YzYfkeI= 234 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191210101603-dd6a2e8934f6/go.mod h1:YU7k8fkeMqJx4Wh4eF6ygYj1MIo4/6QcCf+Q3P1W0zw= 235 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191210102224-b763fff5e84c h1:agmfSW7Z9a/CB72A8vb/A6siXnthjSZglnb5LLyRCeM= 236 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191210102224-b763fff5e84c/go.mod h1:YU7k8fkeMqJx4Wh4eF6ygYj1MIo4/6QcCf+Q3P1W0zw= 237 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191210104321-3490a372ea20 h1:iwHbJo8H4Xka7SwG5koSb8lrxd8yDV7M4yrlJGcqBEg= 238 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191210104321-3490a372ea20/go.mod h1:YU7k8fkeMqJx4Wh4eF6ygYj1MIo4/6QcCf+Q3P1W0zw= 239 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191210105231-47a117b17a7a h1:nxUs2uPZ55pkTc/Ft9z025Sm5M/87g69lFoDN/iAg1k= 240 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191210105231-47a117b17a7a/go.mod h1:YU7k8fkeMqJx4Wh4eF6ygYj1MIo4/6QcCf+Q3P1W0zw= 241 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191210105551-afbfc8719afe h1:bT7O1+rNOkGVtuvfDYtKhWsO0uHvJ65ty4Wuey6lHD0= 242 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191210105551-afbfc8719afe/go.mod h1:YU7k8fkeMqJx4Wh4eF6ygYj1MIo4/6QcCf+Q3P1W0zw= 243 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191210110105-23bdcaea95d2 h1:pXVVZ1P0TOPmfZRvOs34Jkdpz7uxpevVIthoo7XPMoE= 244 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191210110105-23bdcaea95d2/go.mod h1:YU7k8fkeMqJx4Wh4eF6ygYj1MIo4/6QcCf+Q3P1W0zw= 245 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191213195032-3c4a3f1c2b16 h1:Fuymxg5muAoXvEWjSWY7Hq9RZtlHVqT2JRoT4NIjwDw= 246 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191213195032-3c4a3f1c2b16/go.mod h1:axSooW39DtL/kqE2qaQlJVBXr9/fD/20uOr6M5oExJI= 247 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191213200519-8322c3a109bb h1:5Fo+DrXwfqlh8NtIx8ZwgDi8FCVAEFtvuudtRkCYKKE= 248 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191213200519-8322c3a109bb/go.mod h1:axSooW39DtL/kqE2qaQlJVBXr9/fD/20uOr6M5oExJI= 249 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191213200756-f3f116aa9673 h1:CbOrJwMVlumAp+m/q3lTB8Db66uul1ze8Sg5pd49UGY= 250 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191213200756-f3f116aa9673/go.mod h1:axSooW39DtL/kqE2qaQlJVBXr9/fD/20uOr6M5oExJI= 251 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191213202058-dce00b0dfde7 h1:9sxBZ1/uXbK8orhubN4+tzV6Tz3kXk7axeTojVwEM9I= 252 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191213202058-dce00b0dfde7/go.mod h1:axSooW39DtL/kqE2qaQlJVBXr9/fD/20uOr6M5oExJI= 253 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191215133759-33330eee74a9 h1:52ioyrXhoohZ28LjulDZcTila4UzvR4qUQY2luNe9qc= 254 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191215133759-33330eee74a9/go.mod h1:axSooW39DtL/kqE2qaQlJVBXr9/fD/20uOr6M5oExJI= 255 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191227153246-79033fb74966 h1:uWWLDHIDFV73XD8MCe1iNCTQexz7VPXVe+i0UaDoCzM= 256 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20191227153246-79033fb74966/go.mod h1:frYIe/W7VDJUil/79plNgRLMiH5pGc9vL8rrWnw2GbI= 257 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20200109161701-964c808d40a7 h1:iPp34XlB68OpUh3lHnxqLaSJjL33XA38VBrV7Pq/Ju8= 258 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20200109161701-964c808d40a7/go.mod h1:uM0HeIqb4mv6BHwO99uZ8NrKh7sOrwwOLuvphvDAOek= 259 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20200110085204-33547f7335d4 h1:9UVrfMlf/pCoWCbQ4KIWbadVY12bm2qcwAm5ZHmYoMM= 260 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20200110085204-33547f7335d4/go.mod h1:uM0HeIqb4mv6BHwO99uZ8NrKh7sOrwwOLuvphvDAOek= 261 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20200115132524-2cb19fec47c7 h1:TZ1NEUaHB5eD8D0cUCLdh3fQmAD/66vsMQ0o+g2yYUI= 262 | github.com/jensneuse/graphql-go-tools v1.8.3-0.20200115132524-2cb19fec47c7/go.mod h1:fA44UXpCWdbj0Lguv/ZMMALoiuGd5E11dZKoueY8UbU= 263 | github.com/jensneuse/pipeline v0.0.0-20200109160550-f4ca9aef3017 h1:Y7IKk+A9QWsLdG0crjrD8RU32fRk0U0a7tEPh8kOoIM= 264 | github.com/jensneuse/pipeline v0.0.0-20200109160550-f4ca9aef3017/go.mod h1:UsfzaMt+keVOxa007GcCJMFeTHr6voRfBGMQEW7DkdM= 265 | github.com/jensneuse/pipeline v0.0.0-20200110090712-e40ec448f28d h1:WhhY2ZdyCvYSb1S2aP91fK9gqlnK2mM3uzcrSu8sfLo= 266 | github.com/jensneuse/pipeline v0.0.0-20200110090712-e40ec448f28d/go.mod h1:UsfzaMt+keVOxa007GcCJMFeTHr6voRfBGMQEW7DkdM= 267 | github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= 268 | github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= 269 | github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= 270 | github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= 271 | github.com/karrick/godirwalk v1.10.12/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA= 272 | github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= 273 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 274 | github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= 275 | github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= 276 | github.com/klauspost/cpuid v0.0.0-20180405133222-e7e905edc00e/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= 277 | github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= 278 | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 279 | github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 280 | github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= 281 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 282 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 283 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 284 | github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY= 285 | github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= 286 | github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= 287 | github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= 288 | github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= 289 | github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ= 290 | github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= 291 | github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= 292 | github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= 293 | github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= 294 | github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= 295 | github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY= 296 | github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= 297 | github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= 298 | github.com/nats-io/jwt v0.3.0 h1:xdnzwFETV++jNc4W1mw//qFyJGb2ABOombmZJQS4+Qo= 299 | github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= 300 | github.com/nats-io/jwt v0.3.2 h1:+RB5hMpXUUA2dfxuhBTEkMOrYmM+gKIZYS1KjSostMI= 301 | github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= 302 | github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= 303 | github.com/nats-io/nats.go v1.9.1 h1:ik3HbLhZ0YABLto7iX80pZLPw/6dx3T+++MZJwLnMrQ= 304 | github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= 305 | github.com/nats-io/nkeys v0.1.0 h1:qMd4+pRHgdr1nAClu+2h/2a5F2TmKcCzjCDazVgRoX4= 306 | github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= 307 | github.com/nats-io/nkeys v0.1.3 h1:6JrEfig+HzTH85yxzhSVbjHRJv9cn0p6n3IngIcM5/k= 308 | github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= 309 | github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= 310 | github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= 311 | github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= 312 | github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= 313 | github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= 314 | github.com/pelletier/go-toml v1.6.0 h1:aetoXYr0Tv7xRU/V4B4IZJ2QcbtMUFoNb3ORp7TzIK4= 315 | github.com/pelletier/go-toml v1.6.0/go.mod h1:5N711Q9dKgbdkxHL+MEfF31hpT7l0S0s/t2kKREewys= 316 | github.com/phayes/freeport v0.0.0-20171002181615-b8543db493a5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= 317 | github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 318 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 319 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 320 | github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= 321 | github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= 322 | github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= 323 | github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 324 | github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= 325 | github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= 326 | github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= 327 | github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= 328 | github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= 329 | github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= 330 | github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= 331 | github.com/rogpeppe/go-internal v1.3.0 h1:RR9dF3JtopPvtkroDZuVD7qquD0bnHlKSqaQhgwt8yk= 332 | github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= 333 | github.com/rogpeppe/go-internal v1.3.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= 334 | github.com/rogpeppe/go-internal v1.5.0 h1:Usqs0/lDK/NqTkvrmKSwA/3XkZAs7ZAW/eLeQ2MVBTw= 335 | github.com/rogpeppe/go-internal v1.5.0/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= 336 | github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= 337 | github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 338 | github.com/sebdah/goldie v0.0.0-20180424091453-8784dd1ab561/go.mod h1:lvjGftC8oe7XPtyrOidaMi0rp5B9+XY/ZRUynGnuaxQ= 339 | github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= 340 | github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= 341 | github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= 342 | github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= 343 | github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= 344 | github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= 345 | github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI= 346 | github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= 347 | github.com/spf13/afero v1.2.1 h1:qgMbHoJbPbw579P+1zVY+6n4nIFuIchaIjzZ/I/Yq8M= 348 | github.com/spf13/afero v1.2.1/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= 349 | github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc= 350 | github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= 351 | github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= 352 | github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= 353 | github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s= 354 | github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= 355 | github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= 356 | github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= 357 | github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= 358 | github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= 359 | github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= 360 | github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 361 | github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= 362 | github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= 363 | github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= 364 | github.com/spf13/viper v1.4.0 h1:yXHLWeravcrgGyFSyCgdYpXQ9dR9c/WED3pg1RhxqEU= 365 | github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= 366 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 367 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 368 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 369 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 370 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 371 | github.com/tidwall/gjson v1.2.1/go.mod h1:c/nTNbUr0E0OrXEhq1pwa8iEgc2DOt4ZZqAt1HtCkPA= 372 | github.com/tidwall/gjson v1.3.5 h1:2oW9FBNu8qt9jy5URgrzsVx/T/KSn3qn/smJQ0crlDQ= 373 | github.com/tidwall/gjson v1.3.5/go.mod h1:P256ACg0Mn+j1RXIDXoss50DeIABTYK1PULOJHhxOls= 374 | github.com/tidwall/match v1.0.1 h1:PnKP62LPNxHKTwvHHZZzdOAOCtsJTjo6dZLCwpKm5xc= 375 | github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E= 376 | github.com/tidwall/pretty v0.0.0-20180105212114-65a9db5fad51/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= 377 | github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= 378 | github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= 379 | github.com/tidwall/sjson v1.0.4/go.mod h1:bURseu1nuBkFpIES5cz6zBtjmYeOQmEESshn7VpF15Y= 380 | github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= 381 | github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= 382 | github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= 383 | github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= 384 | github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= 385 | github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= 386 | github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= 387 | github.com/valyala/fasthttp v1.2.0/go.mod h1:4vX61m6KN+xDduDNwXrhIAVZaZaZiQ1luJk8LWSxF3s= 388 | github.com/valyala/fasttemplate v1.1.0 h1:RZqt0yGBsps8NGvLSGW804QQqCUYYLsaOjTVHy1Ocw4= 389 | github.com/valyala/fasttemplate v1.1.0/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= 390 | github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= 391 | github.com/wasmerio/go-ext-wasm v0.0.0-20191213132134-adcef605ea8e h1:ztyC+E8g/uepTARRmWz94eZz450GbD1GwZtUPFLhYdQ= 392 | github.com/wasmerio/go-ext-wasm v0.0.0-20191213132134-adcef605ea8e/go.mod h1:B0C/D0a2vNos7Y3IxQhMpGOY9PCuCKfLvfry33a1cKA= 393 | github.com/wasmerio/go-ext-wasm v0.3.1 h1:G95XP3fE2FszQSwIU+fHPBYzD0Csmd2ef33snQXNA5Q= 394 | github.com/wasmerio/go-ext-wasm v0.3.1/go.mod h1:VGyarTzasuS7k5KhSIGpM3tciSZlkP31Mp9VJTHMMeI= 395 | github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= 396 | github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= 397 | go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= 398 | go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= 399 | go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= 400 | go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= 401 | go.uber.org/atomic v1.5.1 h1:rsqfU5vBkVknbhUGbAUwQKR2H4ItV8tjJ+6kJX4cxHM= 402 | go.uber.org/atomic v1.5.1/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= 403 | go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= 404 | go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= 405 | go.uber.org/multierr v1.2.0 h1:6I+W7f5VwC5SV9dNrZ3qXrDB9mD0dyGOi/ZJmYw03T4= 406 | go.uber.org/multierr v1.2.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= 407 | go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= 408 | go.uber.org/multierr v1.4.0 h1:f3WCSC2KzAcBXGATIxAB1E2XuCpNU255wNKZ505qi3E= 409 | go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= 410 | go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= 411 | go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= 412 | go.uber.org/zap v1.11.0 h1:gSmpCfs+R47a4yQPAI4xJ0IPDLTRGXskm6UelqNXpqE= 413 | go.uber.org/zap v1.11.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= 414 | go.uber.org/zap v1.13.0 h1:nR6NoDBgAf67s68NhaXbsojM+2gxp3S1hWkHDl27pVU= 415 | go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= 416 | golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 417 | golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 418 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 419 | golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 420 | golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 421 | golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc= 422 | golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 423 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8= 424 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 425 | golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876 h1:sKJQZMuxjOAR/Uo2LBfU90onWEf1dF4C+0hPJCc9Mpc= 426 | golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 427 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 428 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 429 | golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 430 | golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= 431 | golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= 432 | golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 433 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 434 | golang.org/x/net v0.0.0-20180911220305-26e67e76b6c3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 435 | golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 436 | golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 437 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 438 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 439 | golang.org/x/net v0.0.0-20190522155817-f3200d17e092 h1:4QSRKanuywn15aTZvI/mIDEgPQpswuFndXpOj3rKEco= 440 | golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= 441 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI= 442 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 443 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 444 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 445 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 446 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 447 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 448 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 449 | golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 450 | golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 451 | golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 452 | golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 453 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= 454 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 455 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 456 | golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 457 | golang.org/x/sys v0.0.0-20190515120540-06a5c4944438 h1:khxRGsvPk4n2y8I/mLLjp7e5dMTJmH75wvqS6nMwUtY= 458 | golang.org/x/sys v0.0.0-20190515120540-06a5c4944438/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 459 | golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 460 | golang.org/x/sys v0.0.0-20191027211539-f8518d3b3627 h1:/FZUR3d/QsXe4AcJyJFCc40TOj3y6Hs23Y3YJlvVkWo= 461 | golang.org/x/sys v0.0.0-20191027211539-f8518d3b3627/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 462 | golang.org/x/sys v0.0.0-20200113162924-86b910548bc1 h1:gZpLHxUX5BdYLA08Lj4YCJNN/jk7KtquiArPoeX0WvA= 463 | golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 464 | golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= 465 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 466 | golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= 467 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 468 | golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 469 | golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 470 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 471 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 472 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 473 | golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 474 | golang.org/x/tools v0.0.0-20190624180213-70d37148ca0c/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 475 | golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 476 | golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 477 | golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 478 | golang.org/x/tools v0.0.0-20191213221258-04c2e8eff935/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 479 | golang.org/x/tools v0.0.0-20200115044656-831fdb1e1868/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 480 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 481 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 482 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 483 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 484 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 485 | google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= 486 | gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= 487 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 488 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 489 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 490 | gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= 491 | gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= 492 | gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= 493 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 494 | gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= 495 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 496 | gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= 497 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 498 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 499 | honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= 500 | -------------------------------------------------------------------------------- /httpbin_pipeline.json: -------------------------------------------------------------------------------- 1 | { 2 | "steps": [ 3 | { 4 | "kind": "HTTP", 5 | "config": { 6 | "default_timeout": 10000000000, 7 | "default_method": "GET" 8 | } 9 | }, 10 | { 11 | "kind": "JSON", 12 | "config": { 13 | "template": "{{ .body.origin }}" 14 | } 15 | } 16 | ] 17 | } -------------------------------------------------------------------------------- /logger.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "level": "debug", 3 | "encoding": "json", 4 | "outputPaths": ["stdout"], 5 | "errorOutputPaths": ["stderr"], 6 | "encoderConfig": { 7 | "messageKey": "message", 8 | "levelKey": "level", 9 | "levelEncoder": "lowercase" 10 | } 11 | } -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2019 Jens Neuse 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | */ 22 | package main 23 | 24 | import "github.com/jensneuse/graphql-gateway/cmd" 25 | 26 | func main() { 27 | cmd.Execute() 28 | } 29 | -------------------------------------------------------------------------------- /person.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jensneuse/graphql-gateway/f027e5a200a39d9a6506be30473877335255c4a2/person.wasm -------------------------------------------------------------------------------- /schema.graphql: -------------------------------------------------------------------------------- 1 | directive @ListFilterFirstN(n: Int!) on FIELD_DEFINITION 2 | 3 | directive @StaticDataSource ( 4 | data: String 5 | ) on FIELD_DEFINITION 6 | 7 | directive @PipelineDataSource ( 8 | """ 9 | configFilePath is the path where the pipeline configuration file can be found 10 | it needs to be in the json format according to the pipeline json schema 11 | see this url for more info: https://github.com/jensneuse/pipeline 12 | """ 13 | configFilePath: String 14 | """ 15 | configString is a string to configure the pipeline 16 | it needs to be in the json format according to the pipeline json schema 17 | see this url for more info: https://github.com/jensneuse/pipeline 18 | 19 | The PipelinDataSourcePlanner will always choose the configString over the configFilePath in case both are defined. 20 | """ 21 | configString: String 22 | """ 23 | inputJSON is the template to define a JSON object based on the request, parameters etc. which gets passed to the first pipeline step 24 | """ 25 | inputJSON: String! 26 | ) on FIELD_DEFINITION 27 | 28 | directive @NatsDataSource ( 29 | addr: String! 30 | topic: String! 31 | ) on FIELD_DEFINITION 32 | 33 | directive @WasmDataSource ( 34 | input: String! 35 | wasmFile: String! 36 | ) on FIELD_DEFINITION 37 | 38 | directive @MQTTDataSource ( 39 | brokerAddr: String! 40 | clientID: String! 41 | topic: String! 42 | ) on FIELD_DEFINITION 43 | 44 | directive @mapping( 45 | mode: MAPPING_MODE! = PATH_SELECTOR 46 | pathSelector: String 47 | ) on FIELD_DEFINITION 48 | 49 | enum MAPPING_MODE { 50 | NONE 51 | PATH_SELECTOR 52 | } 53 | 54 | directive @HttpJsonDataSource ( 55 | host: String! 56 | url: String! 57 | method: HTTP_METHOD = GET 58 | params: [Parameter] 59 | body: String 60 | headers: [Header] 61 | ) on FIELD_DEFINITION 62 | 63 | input Header { 64 | key: String! 65 | value: String! 66 | } 67 | 68 | directive @GraphQLDataSource ( 69 | host: String! 70 | url: String! 71 | method: HTTP_METHOD = POST 72 | field: String 73 | params: [Parameter] 74 | ) on FIELD_DEFINITION 75 | 76 | directive @HttpPollingStreamDataSource ( 77 | host: String! 78 | url: String! 79 | method: HTTP_METHOD = GET 80 | delaySeconds: Int = 5 81 | params: [Parameter] 82 | ) on FIELD_DEFINITION 83 | 84 | enum HTTP_METHOD { 85 | GET 86 | POST 87 | UPDATE 88 | DELETE 89 | } 90 | 91 | input Parameter { 92 | name: String! 93 | sourceKind: PARAMETER_SOURCE! 94 | sourceName: String! 95 | variableType: String! 96 | } 97 | 98 | enum PARAMETER_SOURCE { 99 | CONTEXT_VARIABLE 100 | OBJECT_VARIABLE_ARGUMENT 101 | FIELD_ARGUMENTS 102 | } 103 | 104 | schema { 105 | query: Query 106 | mutation: Mutation 107 | subscription: Subscription 108 | } 109 | 110 | type Foo { 111 | bar: String! 112 | } 113 | 114 | type Headers { 115 | userAgent: String! @mapping(pathSelector: "User-Agent") 116 | host: String! @mapping(pathSelector: "Host") 117 | acceptEncoding: String @mapping(pathSelector: "Accept-Encoding") 118 | Authorization: String 119 | } 120 | 121 | type HttpBinGet { 122 | headers: Headers! 123 | } 124 | 125 | type JSONPlaceholderPost { 126 | userId: Int! 127 | id: Int! 128 | title: String! 129 | body: String! 130 | comments: [JSONPlaceholderComment] 131 | @HttpJsonDataSource( 132 | host: "jsonplaceholder.typicode.com" 133 | url: "/comments?postId={{ .postId }}" 134 | params: [ 135 | { 136 | name: "postId" 137 | sourceKind: OBJECT_VARIABLE_ARGUMENT 138 | sourceName: "id" 139 | variableType: "String" 140 | } 141 | ] 142 | ) 143 | @mapping(mode: NONE) 144 | } 145 | 146 | type JSONPlaceholderComment { 147 | postId: Int! 148 | id: Int! 149 | name: String! 150 | email: String! 151 | body: String! 152 | } 153 | 154 | type Observation { 155 | description: String 156 | skyDescription: String 157 | temperature: Float 158 | temperatureDesc: String 159 | highTemperature: Float 160 | lowTemperature: Float 161 | } 162 | 163 | type Location { 164 | country: String 165 | state: String 166 | city: String 167 | observation: [Observation] 168 | @ListFilterFirstN(n: 1) 169 | } 170 | 171 | type Observations { 172 | location: [Location] 173 | @ListFilterFirstN(n: 1) 174 | } 175 | 176 | type Weather { 177 | observations: Observations 178 | } 179 | 180 | type Coordinates { 181 | lat: Float 182 | lon: Float 183 | } 184 | 185 | type Country { 186 | code: String 187 | name: String 188 | native: String 189 | phone: String 190 | continent: Continent 191 | currency: String 192 | languages: [Language] 193 | emoji: String 194 | emojiU: String 195 | coordinates: [Coordinates] 196 | @HttpJsonDataSource( 197 | host: "locationiq.com" 198 | url: "/v1/search_sandbox.php?format=json&q={{ .object.name }}&accept-language=en" 199 | ) 200 | @mapping(mode: NONE) 201 | } 202 | 203 | type Continent { 204 | code: String 205 | name: String 206 | countries: [Country] 207 | } 208 | 209 | type Language { 210 | code: String 211 | name: String 212 | native: String 213 | rtl: Int 214 | } 215 | 216 | "The query type, represents all of the entry points into our object graph" 217 | type Query { 218 | hello: String! 219 | @StaticDataSource( 220 | data: "World!" 221 | ) 222 | @mapping(mode: NONE) 223 | staticBoolean: Boolean! 224 | @StaticDataSource( 225 | data: "true" 226 | ) 227 | @mapping(mode: NONE) 228 | nonNullInt: Int! 229 | @StaticDataSource( 230 | data: "1" 231 | ) 232 | @mapping(mode: NONE) 233 | nullableInt: Int 234 | @StaticDataSource( 235 | data: null 236 | ) 237 | @mapping(mode: NONE) 238 | foo: Foo! 239 | @StaticDataSource( 240 | data: "{\"bar\": \"baz\"}" 241 | ) 242 | @mapping(mode: NONE) 243 | httpBinGet: HttpBinGet 244 | @HttpJsonDataSource( 245 | host: "httpbin.org" 246 | url: "/get" 247 | headers: [ 248 | { 249 | key: "Authorization" 250 | value: "{{ .request.headers.Authorization }}" 251 | } 252 | ] 253 | ) 254 | @mapping(mode: NONE) 255 | post(id: Int!): JSONPlaceholderPost 256 | @HttpJsonDataSource( 257 | host: "jsonplaceholder.typicode.com" 258 | url: "/posts/{{ .arguments.id }}" 259 | ) 260 | @mapping(mode: NONE) 261 | country(code: String!): Country 262 | @GraphQLDataSource( 263 | host: "countries.trevorblades.com" 264 | url: "/" 265 | field: "country" 266 | params: [ 267 | { 268 | name: "code" 269 | sourceKind: FIELD_ARGUMENTS 270 | sourceName: "code" 271 | variableType: "String!" 272 | } 273 | ] 274 | ) 275 | person(id: String!): Person 276 | @WasmDataSource( 277 | wasmFile: "./person.wasm" 278 | input: "{\"id\":\"{{ .arguments.id }}\"}" 279 | ) 280 | @mapping(mode: NONE) 281 | httpBinPipeline: String 282 | @PipelineDataSource( 283 | configFilePath: "./httpbin_pipeline.json" 284 | inputJSON: """ 285 | { 286 | "url": "https://httpbin.org/get", 287 | "method": "GET" 288 | } 289 | """ 290 | ) 291 | @mapping(mode: NONE) 292 | __schema: __Schema! 293 | __type(name: String!): __Type 294 | } 295 | 296 | type Person { 297 | id: String! 298 | name: String 299 | age: Int 300 | } 301 | 302 | type Subscription { 303 | localTime: LocalTime 304 | @HttpPollingStreamDataSource( 305 | host: "http://localhost:9111" 306 | url: "/time" 307 | ) 308 | @mapping(mode: NONE) 309 | natsTime: TimeObject 310 | @NatsDataSource( 311 | addr: "nats://0.0.0.0:4222" 312 | topic: "time" 313 | ) 314 | @mapping(mode: NONE) 315 | mqttTime: TimeObject 316 | @MQTTDataSource( 317 | brokerAddr: "tcp://localhost:1883" 318 | clientID: "graphql" 319 | topic: "time" 320 | ) 321 | @mapping(mode: NONE) 322 | } 323 | 324 | type TimeObject { 325 | time: String! @mapping(pathSelector: "Time") 326 | } 327 | 328 | type LocalTime { 329 | datetime: String 330 | timezone: String 331 | abbreviation: String 332 | } 333 | 334 | 335 | type Mutation { 336 | httpBinPost(input: HttpBinPostInput): HttpBinPostResponse 337 | @HttpJsonDataSource( 338 | host: "httpbin.org" 339 | url: "/post" 340 | method: POST 341 | body: "{{ .arguments.input }}" 342 | ) 343 | @mapping(mode: NONE) 344 | } 345 | 346 | input HttpBinPostInput { 347 | foo: String! 348 | } 349 | 350 | type HttpBinPostResponse { 351 | headers: Headers 352 | data: HttpBinPostResponseData @mapping(pathSelector: "json") 353 | } 354 | 355 | type HttpBinPostResponseData { 356 | foo: String 357 | } --------------------------------------------------------------------------------