Skip to content

Commit 368d546

Browse files
Apollo Federation MVP
1 parent f869f5a commit 368d546

File tree

12 files changed

+440
-29
lines changed

12 files changed

+440
-29
lines changed

api/generate.go

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"github.com/99designs/gqlgen/codegen"
77
"github.com/99designs/gqlgen/codegen/config"
88
"github.com/99designs/gqlgen/plugin"
9+
"github.com/99designs/gqlgen/plugin/federation"
910
"github.com/99designs/gqlgen/plugin/modelgen"
1011
"github.com/99designs/gqlgen/plugin/resolvergen"
1112
"github.com/99designs/gqlgen/plugin/schemaconfig"
@@ -18,17 +19,33 @@ func Generate(cfg *config.Config, option ...Option) error {
1819
if cfg.Model.IsDefined() {
1920
_ = syscall.Unlink(cfg.Model.Filename)
2021
}
22+
if err := cfg.Check(); err != nil {
23+
return errors.Wrap(err, "generating core failed")
24+
}
2125

2226
plugins := []plugin.Plugin{schemaconfig.New()}
2327
if cfg.Model.IsDefined() {
2428
plugins = append(plugins, modelgen.New())
2529
}
2630
plugins = append(plugins, resolvergen.New())
31+
if cfg.Federated {
32+
plugins = append([]plugin.Plugin{federation.New()}, plugins...)
33+
}
2734

2835
for _, o := range option {
2936
o(cfg, &plugins)
3037
}
3138

39+
schemaMutators := []codegen.SchemaMutator{}
40+
for _, p := range plugins {
41+
if inj, ok := p.(plugin.SourcesInjector); ok {
42+
inj.InjectSources(cfg)
43+
}
44+
if mut, ok := p.(codegen.SchemaMutator); ok {
45+
schemaMutators = append(schemaMutators, mut)
46+
}
47+
}
48+
3249
for _, p := range plugins {
3350
if mut, ok := p.(plugin.ConfigMutator); ok {
3451
err := mut.MutateConfig(cfg)
@@ -38,7 +55,7 @@ func Generate(cfg *config.Config, option ...Option) error {
3855
}
3956
}
4057
// Merge again now that the generated models have been injected into the typemap
41-
data, err := codegen.BuildData(cfg)
58+
data, err := codegen.BuildData(cfg, schemaMutators)
4259
if err != nil {
4360
return errors.Wrap(err, "merging type systems failed")
4461
}
@@ -56,6 +73,10 @@ func Generate(cfg *config.Config, option ...Option) error {
5673
}
5774
}
5875

76+
if err = codegen.GenerateCode(data); err != nil {
77+
return errors.Wrap(err, "generating core failed")
78+
}
79+
5980
if !cfg.SkipValidation {
6081
if err := validate(cfg); err != nil {
6182
return errors.Wrap(err, "validation failed")

codegen/config/config.go

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ type Config struct {
3030
Directives map[string]DirectiveConfig `yaml:"directives,omitempty"`
3131
OmitSliceElementPointers bool `yaml:"omit_slice_element_pointers,omitempty"`
3232
SkipValidation bool `yaml:"skip_validation,omitempty"`
33+
Federated bool `yaml:"federated,omitempty"`
34+
AdditionalSources []*ast.Source `yaml:"-"`
3335
}
3436

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

150152
type TypeMapField struct {
151-
Resolver bool `yaml:"resolver"`
152-
FieldName string `yaml:"fieldName"`
153+
Resolver bool `yaml:"resolver"`
154+
FieldName string `yaml:"fieldName"`
155+
GeneratedMethod string `yaml:"-"`
153156
}
154157

155158
type StringList []string
@@ -486,12 +489,9 @@ func (c *Config) InjectBuiltins(s *ast.Schema) {
486489
}
487490
}
488491

489-
func (c *Config) LoadSchema() (*ast.Schema, map[string]string, error) {
490-
schemaStrings := map[string]string{}
491-
492-
sources := make([]*ast.Source, len(c.SchemaFilename))
493-
494-
for i, filename := range c.SchemaFilename {
492+
func (c *Config) LoadSchema() (*ast.Schema, error) {
493+
sources := append([]*ast.Source{}, c.AdditionalSources...)
494+
for _, filename := range c.SchemaFilename {
495495
filename = filepath.ToSlash(filename)
496496
var err error
497497
var schemaRaw []byte
@@ -500,15 +500,14 @@ func (c *Config) LoadSchema() (*ast.Schema, map[string]string, error) {
500500
fmt.Fprintln(os.Stderr, "unable to open schema: "+err.Error())
501501
os.Exit(1)
502502
}
503-
schemaStrings[filename] = string(schemaRaw)
504-
sources[i] = &ast.Source{Name: filename, Input: schemaStrings[filename]}
503+
sources = append(sources, &ast.Source{Name: filename, Input: string(schemaRaw)})
505504
}
506505

507506
schema, err := gqlparser.LoadSchema(sources...)
508507
if err != nil {
509-
return nil, nil, err
508+
return nil, err
510509
}
511-
return schema, schemaStrings, nil
510+
return schema, nil
512511
}
513512

514513
func abs(path string) string {

codegen/data.go

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
package codegen
22

33
import (
4+
"bytes"
45
"fmt"
56
"sort"
67

78
"github.com/99designs/gqlgen/codegen/config"
89
"github.com/pkg/errors"
910
"github.com/vektah/gqlparser/ast"
11+
"github.com/vektah/gqlparser/formatter"
1012
)
1113

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

38-
func BuildData(cfg *config.Config) (*Data, error) {
40+
type SchemaMutator interface {
41+
MutateSchema(s *ast.Schema) error
42+
}
43+
44+
func BuildData(cfg *config.Config, plugins []SchemaMutator) (*Data, error) {
3945
b := builder{
4046
Config: cfg,
4147
}
4248

4349
var err error
44-
b.Schema, b.SchemaStr, err = cfg.LoadSchema()
50+
b.Schema, err = cfg.LoadSchema()
4551
if err != nil {
4652
return nil, err
4753
}
@@ -58,6 +64,13 @@ func BuildData(cfg *config.Config) (*Data, error) {
5864

5965
cfg.InjectBuiltins(b.Schema)
6066

67+
for _, p := range plugins {
68+
err = p.MutateSchema(b.Schema)
69+
if err != nil {
70+
return nil, fmt.Errorf("error running MutateSchema: %v", err)
71+
}
72+
}
73+
6174
b.Binder, err = b.Config.NewBinder(b.Schema)
6275
if err != nil {
6376
return nil, err
@@ -143,6 +156,10 @@ func BuildData(cfg *config.Config) (*Data, error) {
143156
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")
144157
}
145158

159+
var buf bytes.Buffer
160+
formatter.NewFormatter(&buf).FormatSchema(b.Schema)
161+
s.SchemaStr = map[string]string{"schema.graphql": buf.String()}
162+
146163
return &s, nil
147164
}
148165

codegen/directives.gotpl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
{{ define "implDirectives" }}{{ $in := .DirectiveObjName }}
22
{{- range $i, $directive := .ImplDirectives -}}
33
directive{{add $i 1}} := func(ctx context.Context) (interface{}, error) {
4+
if ec.directives.{{ $directive.Name|ucFirst }} == nil {
5+
return directive0(ctx)
6+
}
47
{{- range $arg := $directive.Args }}
58
{{- if notNil "Value" $arg }}
69
{{ $arg.VarName }}, err := ec.{{ $arg.TypeReference.UnmarshalFunc }}(ctx, {{ $arg.Value | dump }})

codegen/field.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,18 @@ func (b *builder) bindField(obj *Object, f *Field) (errret error) {
9898
f.GoReceiverName = "ec"
9999
f.GoFieldName = "introspectType"
100100
return nil
101+
case f.Name == "_entities":
102+
f.GoFieldType = GoFieldMethod
103+
f.GoReceiverName = "ec"
104+
f.GoFieldName = "__resolve_entities"
105+
f.MethodHasContext = true
106+
return nil
107+
case f.Name == "_service":
108+
f.GoFieldType = GoFieldMethod
109+
f.GoReceiverName = "ec"
110+
f.GoFieldName = "__resolve__service"
111+
f.MethodHasContext = true
112+
return nil
101113
case obj.Root:
102114
f.IsResolver = true
103115
return nil

0 commit comments

Comments
 (0)