Skip to content

Commit

Permalink
Apollo Federation MVP
Browse files Browse the repository at this point in the history
  • Loading branch information
marwan-at-work committed Dec 7, 2019
1 parent f869f5a commit 368d546
Show file tree
Hide file tree
Showing 12 changed files with 440 additions and 29 deletions.
23 changes: 22 additions & 1 deletion api/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"github.com/99designs/gqlgen/codegen"
"github.com/99designs/gqlgen/codegen/config"
"github.com/99designs/gqlgen/plugin"
"github.com/99designs/gqlgen/plugin/federation"
"github.com/99designs/gqlgen/plugin/modelgen"
"github.com/99designs/gqlgen/plugin/resolvergen"
"github.com/99designs/gqlgen/plugin/schemaconfig"
Expand All @@ -18,17 +19,33 @@ func Generate(cfg *config.Config, option ...Option) error {
if cfg.Model.IsDefined() {
_ = syscall.Unlink(cfg.Model.Filename)
}
if err := cfg.Check(); err != nil {
return errors.Wrap(err, "generating core failed")
}

plugins := []plugin.Plugin{schemaconfig.New()}
if cfg.Model.IsDefined() {
plugins = append(plugins, modelgen.New())
}
plugins = append(plugins, resolvergen.New())
if cfg.Federated {
plugins = append([]plugin.Plugin{federation.New()}, plugins...)
}

for _, o := range option {
o(cfg, &plugins)
}

schemaMutators := []codegen.SchemaMutator{}
for _, p := range plugins {
if inj, ok := p.(plugin.SourcesInjector); ok {
inj.InjectSources(cfg)
}
if mut, ok := p.(codegen.SchemaMutator); ok {
schemaMutators = append(schemaMutators, mut)
}
}

for _, p := range plugins {
if mut, ok := p.(plugin.ConfigMutator); ok {
err := mut.MutateConfig(cfg)
Expand All @@ -38,7 +55,7 @@ func Generate(cfg *config.Config, option ...Option) error {
}
}
// Merge again now that the generated models have been injected into the typemap
data, err := codegen.BuildData(cfg)
data, err := codegen.BuildData(cfg, schemaMutators)
if err != nil {
return errors.Wrap(err, "merging type systems failed")
}
Expand All @@ -56,6 +73,10 @@ func Generate(cfg *config.Config, option ...Option) error {
}
}

if err = codegen.GenerateCode(data); err != nil {
return errors.Wrap(err, "generating core failed")
}

if !cfg.SkipValidation {
if err := validate(cfg); err != nil {
return errors.Wrap(err, "validation failed")
Expand Down
23 changes: 11 additions & 12 deletions codegen/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ type Config struct {
Directives map[string]DirectiveConfig `yaml:"directives,omitempty"`
OmitSliceElementPointers bool `yaml:"omit_slice_element_pointers,omitempty"`
SkipValidation bool `yaml:"skip_validation,omitempty"`
Federated bool `yaml:"federated,omitempty"`
AdditionalSources []*ast.Source `yaml:"-"`
}

var cfgFilenames = []string{".gqlgen.yml", "gqlgen.yml", "gqlgen.yaml"}
Expand Down Expand Up @@ -148,8 +150,9 @@ type TypeMapEntry struct {
}

type TypeMapField struct {
Resolver bool `yaml:"resolver"`
FieldName string `yaml:"fieldName"`
Resolver bool `yaml:"resolver"`
FieldName string `yaml:"fieldName"`
GeneratedMethod string `yaml:"-"`
}

type StringList []string
Expand Down Expand Up @@ -486,12 +489,9 @@ func (c *Config) InjectBuiltins(s *ast.Schema) {
}
}

func (c *Config) LoadSchema() (*ast.Schema, map[string]string, error) {
schemaStrings := map[string]string{}

sources := make([]*ast.Source, len(c.SchemaFilename))

for i, filename := range c.SchemaFilename {
func (c *Config) LoadSchema() (*ast.Schema, error) {
sources := append([]*ast.Source{}, c.AdditionalSources...)
for _, filename := range c.SchemaFilename {
filename = filepath.ToSlash(filename)
var err error
var schemaRaw []byte
Expand All @@ -500,15 +500,14 @@ func (c *Config) LoadSchema() (*ast.Schema, map[string]string, error) {
fmt.Fprintln(os.Stderr, "unable to open schema: "+err.Error())
os.Exit(1)
}
schemaStrings[filename] = string(schemaRaw)
sources[i] = &ast.Source{Name: filename, Input: schemaStrings[filename]}
sources = append(sources, &ast.Source{Name: filename, Input: string(schemaRaw)})
}

schema, err := gqlparser.LoadSchema(sources...)
if err != nil {
return nil, nil, err
return nil, err
}
return schema, schemaStrings, nil
return schema, nil
}

func abs(path string) string {
Expand Down
21 changes: 19 additions & 2 deletions codegen/data.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package codegen

import (
"bytes"
"fmt"
"sort"

"github.com/99designs/gqlgen/codegen/config"
"github.com/pkg/errors"
"github.com/vektah/gqlparser/ast"
"github.com/vektah/gqlparser/formatter"
)

// Data is a unified model of the code to be generated. Plugins may modify this structure to do things like implement
Expand Down Expand Up @@ -35,13 +37,17 @@ type builder struct {
Directives map[string]*Directive
}

func BuildData(cfg *config.Config) (*Data, error) {
type SchemaMutator interface {
MutateSchema(s *ast.Schema) error
}

func BuildData(cfg *config.Config, plugins []SchemaMutator) (*Data, error) {
b := builder{
Config: cfg,
}

var err error
b.Schema, b.SchemaStr, err = cfg.LoadSchema()
b.Schema, err = cfg.LoadSchema()
if err != nil {
return nil, err
}
Expand All @@ -58,6 +64,13 @@ func BuildData(cfg *config.Config) (*Data, error) {

cfg.InjectBuiltins(b.Schema)

for _, p := range plugins {
err = p.MutateSchema(b.Schema)
if err != nil {
return nil, fmt.Errorf("error running MutateSchema: %v", err)
}
}

b.Binder, err = b.Config.NewBinder(b.Schema)
if err != nil {
return nil, err
Expand Down Expand Up @@ -143,6 +156,10 @@ func BuildData(cfg *config.Config) (*Data, error) {
return nil, fmt.Errorf("invalid types were encountered while traversing the go source code, this probably means the invalid code generated isnt correct. add try adding -v to debug")
}

var buf bytes.Buffer
formatter.NewFormatter(&buf).FormatSchema(b.Schema)
s.SchemaStr = map[string]string{"schema.graphql": buf.String()}

return &s, nil
}

Expand Down
3 changes: 3 additions & 0 deletions codegen/directives.gotpl
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
{{ define "implDirectives" }}{{ $in := .DirectiveObjName }}
{{- range $i, $directive := .ImplDirectives -}}
directive{{add $i 1}} := func(ctx context.Context) (interface{}, error) {
if ec.directives.{{ $directive.Name|ucFirst }} == nil {
return directive0(ctx)
}
{{- range $arg := $directive.Args }}
{{- if notNil "Value" $arg }}
{{ $arg.VarName }}, err := ec.{{ $arg.TypeReference.UnmarshalFunc }}(ctx, {{ $arg.Value | dump }})
Expand Down
12 changes: 12 additions & 0 deletions codegen/field.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,18 @@ func (b *builder) bindField(obj *Object, f *Field) (errret error) {
f.GoReceiverName = "ec"
f.GoFieldName = "introspectType"
return nil
case f.Name == "_entities":
f.GoFieldType = GoFieldMethod
f.GoReceiverName = "ec"
f.GoFieldName = "__resolve_entities"
f.MethodHasContext = true
return nil
case f.Name == "_service":
f.GoFieldType = GoFieldMethod
f.GoReceiverName = "ec"
f.GoFieldName = "__resolve__service"
f.MethodHasContext = true
return nil
case obj.Root:
f.IsResolver = true
return nil
Expand Down
Loading

0 comments on commit 368d546

Please sign in to comment.