All Projects → EGT-Ukraine → go2gql

EGT-Ukraine / go2gql

Licence: MIT license
graphql-go schema generator by proto files

Programming Languages

go
31211 projects - #10 most used programming language
Makefile
30231 projects

Projects that are alternatives of or similar to go2gql

proto2gql
The project has been migrated to https://github.com/EGT-Ukraine/go2gql.
Stars: ✭ 21 (-36.36%)
Mutual labels:  schema, protobuf, api-gateway, protoc, codegenerator, proto, graphql-go
Protobuf Dynamic
Protocol Buffers Dynamic Schema - create protobuf schemas programmatically
Stars: ✭ 186 (+463.64%)
Mutual labels:  schema, protobuf, protoc
Protodot
transforming your .proto files into .dot files (and .svg, .png if you happen to have graphviz installed)
Stars: ✭ 107 (+224.24%)
Mutual labels:  protobuf, protoc
Protoc Gen Doc
Documentation generator plugin for Google Protocol Buffers
Stars: ✭ 1,792 (+5330.3%)
Mutual labels:  protobuf, protoc
metastore
A protobuf schema registry on steroids. It will keep track of the contracts throughout your organization, making sure no contract is broken.
Stars: ✭ 43 (+30.3%)
Mutual labels:  schema, protobuf
Protobuf Swift
Google ProtocolBuffers for Apple Swift
Stars: ✭ 925 (+2703.03%)
Mutual labels:  protobuf, protoc
Protoc Jar
Protocol Buffers protobuf compiler - multi-platform executable protoc JAR and API
Stars: ✭ 103 (+212.12%)
Mutual labels:  protobuf, protoc
Goprotowrap
A package-at-a-time wrapper for protoc, for generating Go protobuf code.
Stars: ✭ 147 (+345.45%)
Mutual labels:  protobuf, protoc
Protoc Gen Gotemplate
📂 generic protocol generator based on golang's text/template (grpc/protobuf)
Stars: ✭ 284 (+760.61%)
Mutual labels:  protobuf, protoc
Rules protobuf
Bazel rules for building protocol buffers and gRPC services (java, c++, go, ...)
Stars: ✭ 206 (+524.24%)
Mutual labels:  protobuf, protoc
Protobuf Convert
Macros for convenient serialization of Rust data structures into/from Protocol Buffers 3
Stars: ✭ 22 (-33.33%)
Mutual labels:  schema, protobuf
Prototool
Your Swiss Army Knife for Protocol Buffers
Stars: ✭ 4,932 (+14845.45%)
Mutual labels:  protobuf, protoc
Protobuf
A pure Elixir implementation of Google Protobuf
Stars: ✭ 442 (+1239.39%)
Mutual labels:  protobuf, protoc
Protobuf
Protocol Buffers - Google's data interchange format
Stars: ✭ 52,305 (+158400%)
Mutual labels:  protobuf, protoc
Protolock
Protocol Buffer companion tool. Track your .proto files and prevent changes to messages and services which impact API compatibility.
Stars: ✭ 394 (+1093.94%)
Mutual labels:  protobuf, protoc
Pb And K
Kotlin Code Generator and Runtime for Protocol Buffers
Stars: ✭ 137 (+315.15%)
Mutual labels:  protobuf, protoc
protoc-gen-kit
Protoc compiler for Go kit code
Stars: ✭ 17 (-48.48%)
Mutual labels:  protobuf, protoc
Buf
A new way of working with Protocol Buffers.
Stars: ✭ 3,328 (+9984.85%)
Mutual labels:  protobuf, protoc
Protoc Jar Maven Plugin
Protocol Buffers protobuf maven plugin - based on protoc-jar multi-platform executable protoc JAR
Stars: ✭ 177 (+436.36%)
Mutual labels:  protobuf, protoc
Schema Registry
Confluent Schema Registry for Kafka
Stars: ✭ 1,647 (+4890.91%)
Mutual labels:  schema, protobuf

go2gql

Build Status Coverage Status

Tool, which generates GraphQL Schema for graphql-go package based on external data sources

Installation

$ go get github.com/EGT-Ukraine/go2gql/cmd/go2gql

Usage

$ ./go2gql -c "<config path>"

Generation process

Plugins

The generation process is built around plugins. Plugin is a go type that implements interface

type Plugin interface {
	Init(*GenerateConfig, []Plugin) error
	Prepare() error
	Name() string
	PrintInfo(info Infos)
	Infos() map[string]string
	Generate() error
}
  1. reading config
  2. plugins initialization ( calling Init() method of each plugin )
  3. plugins preparation ( calling Prepare() method of each plugin )
  4. plugins generation ( calling Generate() method of each plugin )

Default plugins

Default plugins places in ./generator/plugins

graphql plugin

graphql generates:

  • GraphQL Schema based on config and relying on data sent to him from other packages
  • GraphQL types and resolvers relying on data sent to him from other packages

config example

Here's a simple config example of how to generate such GraphQL schema

type Query {
    fieldA FieldA
}
type FieldA {
    srvField SomeServiceObj
}
type SomeServiceObj {
    ... SomeService methods
}
type Mutation {
    ... SomeServiceMutations methods
}
...
...
graphql_schemas:
  - name: "ExampleSchema"                           # Schema name
    output_path: "./services_api/schema/auth.go"    # Where to put schema code
    output_package: "schema"                        # Package name
    queries:
      type: "OBJECT"
      fields:
        - field:       "fieldA"
          type:        "OBJECT"                     # Field type (OBJECT|SERVICE)
          object_name: "FieldA"
          fields:
            - field:        "srvField"
              object_name:  "SomeServiceObj"
              service:      "SomeService"           # Service name
              type:         "SERVICE"
              exclude_methods:
                - "excluded_method_1"
              filter_methods:
                - "excluded_method_1"
                - "excluded_method_3"

    mutations:
      # similary to queries
      type: "SERVICE"
      service: "SomeServiceMutations"
...

proto2gql plugin

proto2gql plugin parses .proto files, defined in config and pass them to graphql plugin.

Service names

For each service of each proto file, proto2gql adds two services to graphql plugins with names:

  • ServiceName or ServiceAlias
  • ServiceNameMutations or ServiceAliasMutations

Config example

...
...
proto2gql:
    output_path: "./proto_out/"      # path, where to put generated code
    paths:                           # path, where parser will search for imports
        - "./vendor"
        - "$GOPATH/src"
    import_aliases:                  # imports aliases for all files
        - google/protobuf/descriptor.proto: "github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.proto"
        - google/protobuf/timestamp.proto:  "github.com/golang/protobuf/ptypes/timestamp/timestamp.proto"
        - google/protobuf/empty.proto:      "github.com/golang/protobuf/ptypes/empty/empty.proto"
    files:
      # If you want to add some settings to imported .proto file, just add it here
      - name: "Name"                  # name of .proto file
        proto_path: "./a.proto"       # path to .proto file
        output_path: "./schema/name"  # file-specific path, where to put generated code
        proto_go_package: "github.com/gogo/protobuf/types" # Go package of .proto file grpc client (which was previously generated by `protoc`)
        gql_messages_prefix: "Msg"    # prefix, which will be added to all generated GraphQL Messages(including maps)
        gql_enums_prefix:    "Enm"    # prefix, which will be added to all generated GraphQL Enums
        paths:                        # file specific path, where parser will search for imports
          - "./a_proto_deps/"
        imports_aiases:               # file specific imports aliases
          - google/protobuf/timestamp.proto:  "github.com/gogo/protobuf/protobuf/google/protobuf/timestamp.proto"
        services:                     # services settings
          "serviceName":              # service name
            service_name: "someAlias" # service name alias
            methods:
              "methodName":           # method name
                alias: "methodAlias"
                request_type: "QUERY" # method type in GraphQL Schema (QUERY|MUTATION)
        messages:                     # messages settings
          - "Request$":               # message name match regex
              unwrap_field: true      # unpack input message field. Useful for google.protobuf.wrappers.
              fields:
                "ip_address":
                  context_key: "ip"   # context key, where unmarshaller will get this field from
          - "Response$":
              unwrap_field: true      # In proto we can't use primitive or repeated type in method response.
                                      # If unwrap_field = true unpack response gql object with 1 field.
              error_field: "Error"    # name of payload error field
      - ...
      - ...


...
...

swagger2gql plugin

proto2gql plugin parses swagger files, defined in config and pass them to graphql plugin.

Service names

For each tag of each swagger file, proto2gql adds two services to graphql plugins with names:

  • pascalized(tag-name) or ServiceAlias
  • pascalized(tag-name)Mutations or ServiceAliasMutations

pascalized() here means, that it converts string to CamelCase format and removes all characters that is not valid in GraphQL Object name

Config example

...
...
swagger2gql:
    output_path: "./swagger_out/"           # Path, where to put generated code
    objects:                                # GraphQL objects configs
      - "Response$":                        # Object name
          error_field: "error"              # name of payload error field
      - "InputParams$":
          fields:                           # Object fields config
            ip:                             # field name
              context_key: "user_ip"        # context key, where unmarshaller will get this field from
    files:
      - name: "Swagger file number 1"         # swagger file name
        path: "./service1/swagger.json"       # path to swagger file
        models_go_path: "github.com/myproject/service1/client/models" # path to generated using goswagger models
        output_pkg: "gql_service1"            # output go package name
        output_path: "./service1/schema/"     # file-specific path, where to put generated code
        gql_objects_prefix: "Srv1"            # prefix, which will be added to all generated GraphQL Objects
        tags:                                 # tags settings
          "some-swagger-tag":                 # tag name
            client_go_package: "github.com/myproject/service1/client/some_swagger_tag/client"   # go client package
            service_name: "SomeSwaggerTag"    # service name alias
            methods:                          # tag method settings
              "/somes":                       # request path
                get:                          # request method (get/post/put/options...)
                  alias: "get"
                  request_type: "QUERY"       # request type (QUERY|MUTATIONS)
        params_config:                        # file specific object parameters settings
         - param_name: "user_id"
           context_key: "user_id"          
        objects:                              # file specific objects settings
         - "Request$":
           fields:
             "user_id":
               context_key: "user_id"
...
...

Simple plugin example

Here's a simple plugin, that gets access to graphql plugin. Fetches information about services and their methods, and then, render them to .yml file

package main

import (
	"os"

	"github.com/pkg/errors"
	"github.com/EGT-Ukraine/go2gql/generator"
	"github.com/EGT-Ukraine/go2gql/generator/plugins/graphql"
)

const Name = "gql_services_rules"

type plugin struct {
	gqlPlugin *graphql.Plugin
}

func (p *plugin) Init(_ *generator.GenerateConfig, plugins []generator.Plugin) error {
	for _, plugin := range plugins {
		if g, ok := plugin.(*graphql.Plugin); ok {
			p.gqlPlugin = g
			return nil
		}
	}
	return errors.New("graphql plugin was not found")
}

func (p plugin) Generate() error {
	file, err := os.OpenFile("./services_access.yml", os.O_TRUNC|os.O_WRONLY, 0666)
	if err != nil {
		return errors.Wrap(err, "failed to open services_access.yml")
	}
	defer file.Close()
	for _, typesFile := range p.gqlPlugin.Types() {
		for _, service := range typesFile.Services {
			if len(service.QueryMethods) == 0 {
				continue
			}
			file.WriteString(service.Name + ":\n")
			for _, method := range service.QueryMethods {
				file.WriteString("   " + method.Name + ":\n")
			}
		}
	}
	return nil
}
func (plugin) Name() string                   { return Name }
func (plugin) Prepare() error                 { return nil }
func (plugin) PrintInfo(info generator.Infos) {}
func (plugin) Infos() map[string]string       { return nil }

func Plugin() generator.Plugin {
	return new(plugin)
}
func main(){}

Dataloader support

Config example:

data_loaders:
  output_path: "./generated/schema/loaders/"

proto2gql:
  output_path: "./generated/schema"
  paths:
    - "vendor"
    - "$GOPATH/src"
  imports_aliases:
    - google/protobuf/empty.proto:      "github.com/golang/protobuf/ptypes/empty/empty.proto"
  files:
    - proto_path: "./apis/reviews.proto"
      services:
        ItemsReviewService:
          methods:
            List:
              data_loaders:
                ItemReviewsByIDs:
                  request_field: "filter.item_ids"
                  result_field: "reviews"
                  match_field: "item_id"
                  type: "1-N"                       # Relation type (1-N|1-1)
                  wait_duration: 1h1m1s   ( WARNING!! this is only example, use some small duration)

    - proto_path: "./apis/category.proto"
      services:
        CategoryService:
          methods:
            List:
              data_loaders:
                CategoriesByIDs:
                  request_field: "filter.ids"
                  result_field: "categories"
                  match_field: "id"
                  type: "1-1"
                  wait_duration: 1s


    - proto_path: "./apis/user.proto"
      services:
        UserService:
          methods:
            List:
              data_loaders:
                UsersByIDs:
                  request_field: "filter.ids"
                  result_field: "users"
                  match_field: "id"
                  type: "1-1"
                  wait_duration: 1s
    - proto_path: "./apis/items.proto"
      services:
        ItemsService:
          methods:
            List:
              alias: "list"
              request_type: "QUERY"
      messages:
        - "Item$":
            data_loaders:
              - field_name: "category"
                key_field_name: "category_id"
                data_loader_name: "CategoriesByIDs"
              - field_name: "comments"
                key_field_name: "id"
                data_loader_name: "CommentsLoader"
              - field_name: "reviews"
                key_field_name: "id"
                data_loader_name: "ItemReviewsByIDs"

swagger2gql:
  output_path: "./generated/schema"
  files:
    - name: "Comments"
      path: "apis/swagger.json"
      models_go_path: "github.com/EGT-Ukraine/go2gql/tests/dataloader/generated/clients/models"
      tags:
        "comments-controller":
          service_name: "CommentsService"
          client_go_package: "github.com/EGT-Ukraine/go2gql/tests/dataloader/generated/clients/client/comments_controller"
          methods:
            "/items/comments/":
              post:
                data_loader_provider:
                  name: "CommentsLoader"
                  wait_duration_ms: 5
      objects:
        - "ItemComment$":
            data_loaders:
              - field_name: "user"
                key_field_name: "user_id"
                data_loader_name: "UserService"

graphql_schemas:
  - name: "API"
    output_path: "./generated/schema/api.go"
    output_package: "schema"
    queries:
      type: "OBJECT"
      fields:
        - field: "items"
          object_name: "Items"
          service: "ItemsService"
          type: "SERVICE"

Default wait duration 10ms.

Full example can be found in tests.

Note to users migrating from older releases

Migrating from 1.x to 2.0

Swagger plugin

service_name config field is removed. Use queries_service_name & mutations_service_name instead.

Proto plugin

alias config field for services is removed.

Use queries_service_name & mutations_service_name instead.

Migrating from 2.x to 3.0

Swagger plugin

queries_service_name & mutations_service_name config fields is removed. Use service_name instead.

Proto plugin

queries_service_name & mutations_service_name config fields is removed. Use service_name instead.

Migrating from 3.x to 4.0

tracer.Tracer was replaced with opentracing.Tracer

Schema initialization before:

import "github.com/EGT-Ukraine/go2gql/tracer"

var tracer tracer.Tracer

sch, err := schema.GetAPISchema(schemaApiClientsFactory.GetAPIClients(), schemaApiInterceptor, tracer)

now:

import opentracing_go "github.com/opentracing/opentracing-go"

var tracer opentracing_go.Tracer

sch, err := schema.GetAPISchema(schemaApiClientsFactory.GetAPIClients(), schemaApiInterceptor, tracer)

Migrating from 4.x to 5.0

github.com/saturn4er/graphql dependency was replaced with original github.com/graphql-go/graphql package.

Migrating from 5.x to 6.0

Implicit service & method registration in proto plugin disabled. For now you must declare each proto service & method in config.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].