Skip to content

marwan-at-work/protoc-gen-twirpql

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

38 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

A Protoc plugin that generates a GraphQL layer on top of Twirp servers.

Status

There have been a few breaking changes in the upstream dependencies (protobufs and gqlgen) which makes this plugin a bit outdated if not flat out broken. So the go.mod file to pin the versions that would work with this library or feel free to open a PR upgrading to the latest of the two versions. See #9

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:

  1. Automatic client generation
  2. 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