aboutsummaryrefslogblamecommitdiffstats
path: root/vendor/github.com/99designs/gqlgen/codegen/build.go
blob: 582689a745493c29e096e2060b86a1fe110c6d04 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
















                                      


                                

                                          




                                     





                            






                                  







                                                    

                                                  



                                                              
 
                                                        
 
                                                        






                                                        




                                                            
                                                  









                                                    
 
                                                
 
                                                          








                                                                                






                                                        

                                                          

                                                               






                                                            
                                                  




                                                              
                                                       
 
                                                          



                               
                                                        












                                                                      





















                                                                                   
                                               



                                   
                                                        
                               











                                                             













                                                                      
package codegen

import (
	"fmt"
	"go/build"
	"go/types"
	"os"

	"github.com/pkg/errors"
	"golang.org/x/tools/go/loader"
)

type Build struct {
	PackageName      string
	Objects          Objects
	Inputs           Objects
	Interfaces       []*Interface
	QueryRoot        *Object
	MutationRoot     *Object
	SubscriptionRoot *Object
	SchemaRaw        map[string]string
	SchemaFilename   SchemaFilenames
	Directives       []*Directive
}

type ModelBuild struct {
	PackageName string
	Models      []Model
	Enums       []Enum
}

type ResolverBuild struct {
	PackageName   string
	ResolverType  string
	Objects       Objects
	ResolverFound bool
}

type ServerBuild struct {
	PackageName         string
	ExecPackageName     string
	ResolverPackageName string
}

// Create a list of models that need to be generated
func (cfg *Config) models() (*ModelBuild, error) {
	namedTypes := cfg.buildNamedTypes()

	progLoader := cfg.newLoaderWithoutErrors()

	prog, err := progLoader.Load()
	if err != nil {
		return nil, errors.Wrap(err, "loading failed")
	}

	cfg.bindTypes(namedTypes, cfg.Model.Dir(), prog)

	models, err := cfg.buildModels(namedTypes, prog)
	if err != nil {
		return nil, err
	}
	return &ModelBuild{
		PackageName: cfg.Model.Package,
		Models:      models,
		Enums:       cfg.buildEnums(namedTypes),
	}, nil
}

// bind a schema together with some code to generate a Build
func (cfg *Config) resolver() (*ResolverBuild, error) {
	progLoader := cfg.newLoaderWithoutErrors()
	progLoader.Import(cfg.Resolver.ImportPath())

	prog, err := progLoader.Load()
	if err != nil {
		return nil, err
	}

	destDir := cfg.Resolver.Dir()

	namedTypes := cfg.buildNamedTypes()

	cfg.bindTypes(namedTypes, destDir, prog)

	objects, err := cfg.buildObjects(namedTypes, prog)
	if err != nil {
		return nil, err
	}

	def, _ := findGoType(prog, cfg.Resolver.ImportPath(), cfg.Resolver.Type)
	resolverFound := def != nil

	return &ResolverBuild{
		PackageName:   cfg.Resolver.Package,
		Objects:       objects,
		ResolverType:  cfg.Resolver.Type,
		ResolverFound: resolverFound,
	}, nil
}

func (cfg *Config) server(destDir string) *ServerBuild {
	return &ServerBuild{
		PackageName:         cfg.Resolver.Package,
		ExecPackageName:     cfg.Exec.ImportPath(),
		ResolverPackageName: cfg.Resolver.ImportPath(),
	}
}

// bind a schema together with some code to generate a Build
func (cfg *Config) bind() (*Build, error) {
	namedTypes := cfg.buildNamedTypes()

	progLoader := cfg.newLoaderWithoutErrors()
	prog, err := progLoader.Load()
	if err != nil {
		return nil, errors.Wrap(err, "loading failed")
	}

	cfg.bindTypes(namedTypes, cfg.Exec.Dir(), prog)

	objects, err := cfg.buildObjects(namedTypes, prog)
	if err != nil {
		return nil, err
	}

	inputs, err := cfg.buildInputs(namedTypes, prog)
	if err != nil {
		return nil, err
	}
	directives, err := cfg.buildDirectives(namedTypes)
	if err != nil {
		return nil, err
	}

	b := &Build{
		PackageName:    cfg.Exec.Package,
		Objects:        objects,
		Interfaces:     cfg.buildInterfaces(namedTypes, prog),
		Inputs:         inputs,
		SchemaRaw:      cfg.SchemaStr,
		SchemaFilename: cfg.SchemaFilename,
		Directives:     directives,
	}

	if cfg.schema.Query != nil {
		b.QueryRoot = b.Objects.ByName(cfg.schema.Query.Name)
	} else {
		return b, fmt.Errorf("query entry point missing")
	}

	if cfg.schema.Mutation != nil {
		b.MutationRoot = b.Objects.ByName(cfg.schema.Mutation.Name)
	}

	if cfg.schema.Subscription != nil {
		b.SubscriptionRoot = b.Objects.ByName(cfg.schema.Subscription.Name)
	}
	return b, nil
}

func (cfg *Config) validate() error {
	progLoader := cfg.newLoaderWithErrors()
	_, err := progLoader.Load()
	return err
}

func (cfg *Config) newLoaderWithErrors() loader.Config {
	conf := loader.Config{}

	for _, pkg := range cfg.Models.referencedPackages() {
		conf.Import(pkg)
	}
	return conf
}

func (cfg *Config) newLoaderWithoutErrors() loader.Config {
	conf := cfg.newLoaderWithErrors()
	conf.AllowErrors = true
	conf.TypeChecker = types.Config{
		Error: func(e error) {},
	}
	return conf
}

func resolvePkg(pkgName string) (string, error) {
	cwd, _ := os.Getwd()

	pkg, err := build.Default.Import(pkgName, cwd, build.FindOnly)
	if err != nil {
		return "", err
	}

	return pkg.ImportPath, nil
}