A Protoc plugin that generates a GraphQL layer on top of Twirp servers.
Features
-
Generates a full GraphQL server implementation based on gqlgen
-
Marshals/Unmarshals ProtoBuf enums (ints) to GraphQL enums (strings).
-
Generates GraphQL Scalars for Protobuf map types that can be used as encoded json strings.
-
Exposes a GraphQL handler as well as a Graph(i)QL interface to make Twirp servers interactive.
-
Unit tests and end to end tests.
-
Twirp Server Hooks -> GraphQL Middleware
Why
RPC Frameworks such as Twirp have two big benefits:
- Automatic client generation
- Documentation-first APIs ensure your contract is not out of date.
This makes it really easy for multiple teams to start using your program right away. But before they use it, they need to learn how it works. This is where GraphQL does a better job.
Twirp and many other frameworks do not provide a friendly UI to discover and interact with their services.
GraphQL comes with a very friendly UI that makes discovering an API quick, easy and fun. You get expressiveness and auto-completion out of the box.
By combining both technologies, my hope is that you get the best of both worlds.
Install
GO111MODULE=on go install marwan.io/protoc-gen-twirpql
Usage
For a full tutorial, click here.
protoc --go_out=. --twirp_out=. service.proto
protoc --twirpql_out=. service.proto
This will generate a subpackage that you can import and use as such:
package main
import (
"net/http"
"./twirpql"
"./mytwirpserver"
)
func main() {
s := mytwirpserver.New()
http.Handle("/query", twirpql.Handler(s, nil))
http.Handle("/play", twirpql.Playground("my service", "/query"))
}
Server Hooks
TwirpQL supports mapping the Error callback of twirp.ServerHooks
to a GraphQL middleware.
All you have to do is the following:
hooks := &twirpql.Handler{Error: myErrorHook}
http.Handle("/query", twirpql.Handler(s, hooks))
And TwirpQL will call your hook if the underlying service implementation returned an error.
Workflow
TwirpQL expects the service.proto to have already been used to generate a .pb.go
, and .twirp.go
files
in the same directory as the .proto
file.
The plugin will generate a twirpql
sub-package that contains the GraphQL layer with all types mapped to
the original .pb.go
file generated by your .proto
file.
Multiple Services
Currently you can only specify one target file such as service.proto
. In other words, the following is not allowed:
protoc --twirpql_out=. service.proto otherservice.proto
That said, service.proto
can import multiple protofiles so breaking out your proto files should not be problem.
However, each TwirpQL generation is meant for one service
declaration in a protocol buffer file. If a Protobuf file has one service declaration, that will be the one chosen. If the Protobuf file has multiple service declarations, then you must explicitly specify which service you'd like to generate a GraphQL layer for as such:
protoc --twirpql_out=service=SomeService:. service.proto
If you want to generate a GraphQL layer over multiple services, see here