github.com/buth/gqlgen@v0.7.2/codegen/build.go (about)

     1  package codegen
     2  
     3  import (
     4  	"fmt"
     5  	"go/build"
     6  	"go/types"
     7  	"os"
     8  
     9  	"github.com/pkg/errors"
    10  	"golang.org/x/tools/go/loader"
    11  )
    12  
    13  type Build struct {
    14  	PackageName      string
    15  	Objects          Objects
    16  	Inputs           Objects
    17  	Interfaces       []*Interface
    18  	QueryRoot        *Object
    19  	MutationRoot     *Object
    20  	SubscriptionRoot *Object
    21  	SchemaRaw        map[string]string
    22  	SchemaFilename   SchemaFilenames
    23  	Directives       []*Directive
    24  }
    25  
    26  type ModelBuild struct {
    27  	PackageName string
    28  	Models      []Model
    29  	Enums       []Enum
    30  }
    31  
    32  type ResolverBuild struct {
    33  	PackageName   string
    34  	ResolverType  string
    35  	Objects       Objects
    36  	ResolverFound bool
    37  }
    38  
    39  type ServerBuild struct {
    40  	PackageName         string
    41  	ExecPackageName     string
    42  	ResolverPackageName string
    43  }
    44  
    45  // Create a list of models that need to be generated
    46  func (cfg *Config) models() (*ModelBuild, error) {
    47  	namedTypes := cfg.buildNamedTypes()
    48  
    49  	progLoader := cfg.newLoaderWithoutErrors()
    50  
    51  	prog, err := progLoader.Load()
    52  	if err != nil {
    53  		return nil, errors.Wrap(err, "loading failed")
    54  	}
    55  
    56  	cfg.bindTypes(namedTypes, cfg.Model.Dir(), prog)
    57  
    58  	models, err := cfg.buildModels(namedTypes, prog)
    59  	if err != nil {
    60  		return nil, err
    61  	}
    62  	return &ModelBuild{
    63  		PackageName: cfg.Model.Package,
    64  		Models:      models,
    65  		Enums:       cfg.buildEnums(namedTypes),
    66  	}, nil
    67  }
    68  
    69  // bind a schema together with some code to generate a Build
    70  func (cfg *Config) resolver() (*ResolverBuild, error) {
    71  	progLoader := cfg.newLoaderWithoutErrors()
    72  	progLoader.Import(cfg.Resolver.ImportPath())
    73  
    74  	prog, err := progLoader.Load()
    75  	if err != nil {
    76  		return nil, err
    77  	}
    78  
    79  	destDir := cfg.Resolver.Dir()
    80  
    81  	namedTypes := cfg.buildNamedTypes()
    82  
    83  	cfg.bindTypes(namedTypes, destDir, prog)
    84  
    85  	objects, err := cfg.buildObjects(namedTypes, prog)
    86  	if err != nil {
    87  		return nil, err
    88  	}
    89  
    90  	def, _ := findGoType(prog, cfg.Resolver.ImportPath(), cfg.Resolver.Type)
    91  	resolverFound := def != nil
    92  
    93  	return &ResolverBuild{
    94  		PackageName:   cfg.Resolver.Package,
    95  		Objects:       objects,
    96  		ResolverType:  cfg.Resolver.Type,
    97  		ResolverFound: resolverFound,
    98  	}, nil
    99  }
   100  
   101  func (cfg *Config) server(destDir string) *ServerBuild {
   102  	return &ServerBuild{
   103  		PackageName:         cfg.Resolver.Package,
   104  		ExecPackageName:     cfg.Exec.ImportPath(),
   105  		ResolverPackageName: cfg.Resolver.ImportPath(),
   106  	}
   107  }
   108  
   109  // bind a schema together with some code to generate a Build
   110  func (cfg *Config) bind() (*Build, error) {
   111  	namedTypes := cfg.buildNamedTypes()
   112  
   113  	progLoader := cfg.newLoaderWithoutErrors()
   114  	prog, err := progLoader.Load()
   115  	if err != nil {
   116  		return nil, errors.Wrap(err, "loading failed")
   117  	}
   118  
   119  	cfg.bindTypes(namedTypes, cfg.Exec.Dir(), prog)
   120  
   121  	objects, err := cfg.buildObjects(namedTypes, prog)
   122  	if err != nil {
   123  		return nil, err
   124  	}
   125  
   126  	inputs, err := cfg.buildInputs(namedTypes, prog)
   127  	if err != nil {
   128  		return nil, err
   129  	}
   130  	directives, err := cfg.buildDirectives(namedTypes)
   131  	if err != nil {
   132  		return nil, err
   133  	}
   134  
   135  	b := &Build{
   136  		PackageName:    cfg.Exec.Package,
   137  		Objects:        objects,
   138  		Interfaces:     cfg.buildInterfaces(namedTypes, prog),
   139  		Inputs:         inputs,
   140  		SchemaRaw:      cfg.SchemaStr,
   141  		SchemaFilename: cfg.SchemaFilename,
   142  		Directives:     directives,
   143  	}
   144  
   145  	if cfg.schema.Query != nil {
   146  		b.QueryRoot = b.Objects.ByName(cfg.schema.Query.Name)
   147  	} else {
   148  		return b, fmt.Errorf("query entry point missing")
   149  	}
   150  
   151  	if cfg.schema.Mutation != nil {
   152  		b.MutationRoot = b.Objects.ByName(cfg.schema.Mutation.Name)
   153  	}
   154  
   155  	if cfg.schema.Subscription != nil {
   156  		b.SubscriptionRoot = b.Objects.ByName(cfg.schema.Subscription.Name)
   157  	}
   158  	return b, nil
   159  }
   160  
   161  func (cfg *Config) validate() error {
   162  	progLoader := cfg.newLoaderWithErrors()
   163  	_, err := progLoader.Load()
   164  	return err
   165  }
   166  
   167  func (cfg *Config) newLoaderWithErrors() loader.Config {
   168  	conf := loader.Config{}
   169  
   170  	for _, pkg := range cfg.Models.referencedPackages() {
   171  		conf.Import(pkg)
   172  	}
   173  	return conf
   174  }
   175  
   176  func (cfg *Config) newLoaderWithoutErrors() loader.Config {
   177  	conf := cfg.newLoaderWithErrors()
   178  	conf.AllowErrors = true
   179  	conf.TypeChecker = types.Config{
   180  		Error: func(e error) {},
   181  	}
   182  	return conf
   183  }
   184  
   185  func resolvePkg(pkgName string) (string, error) {
   186  	cwd, _ := os.Getwd()
   187  
   188  	pkg, err := build.Default.Import(pkgName, cwd, build.FindOnly)
   189  	if err != nil {
   190  		return "", err
   191  	}
   192  
   193  	return pkg.ImportPath, nil
   194  }