...
1 package api
2
3 import (
4 "fmt"
5 "regexp"
6 "syscall"
7
8 "github.com/99designs/gqlgen/codegen"
9 "github.com/99designs/gqlgen/codegen/config"
10 "github.com/99designs/gqlgen/plugin"
11 "github.com/99designs/gqlgen/plugin/federation"
12 "github.com/99designs/gqlgen/plugin/modelgen"
13 "github.com/99designs/gqlgen/plugin/resolvergen"
14 )
15
16 func Generate(cfg *config.Config, option ...Option) error {
17 _ = syscall.Unlink(cfg.Exec.Filename)
18 if cfg.Model.IsDefined() {
19 _ = syscall.Unlink(cfg.Model.Filename)
20 }
21
22 plugins := []plugin.Plugin{}
23 if cfg.Model.IsDefined() {
24 plugins = append(plugins, modelgen.New())
25 }
26 plugins = append(plugins, resolvergen.New())
27 if cfg.Federation.IsDefined() {
28 if cfg.Federation.Version == 0 {
29 urlRegex := regexp.MustCompile(`(?s)@link.*\(.*url:.*?"(.*?)"[^)]+\)`)
30 versionRegex := regexp.MustCompile(`v(\d+).(\d+)$`)
31
32 for _, v := range cfg.Sources {
33 cfg.Federation.Version = 1
34 urlString := urlRegex.FindStringSubmatch(v.Input)
35
36 if urlString != nil {
37 matches := versionRegex.FindStringSubmatch(urlString[1])
38 if matches[1] == "2" {
39 cfg.Federation.Version = 2
40 break
41 }
42 }
43 }
44 }
45 plugins = append([]plugin.Plugin{federation.New(cfg.Federation.Version)}, plugins...)
46 }
47
48 for _, o := range option {
49 o(cfg, &plugins)
50 }
51
52 for _, p := range plugins {
53 if inj, ok := p.(plugin.EarlySourceInjector); ok {
54 if s := inj.InjectSourceEarly(); s != nil {
55 cfg.Sources = append(cfg.Sources, s)
56 }
57 }
58 }
59
60 if err := cfg.LoadSchema(); err != nil {
61 return fmt.Errorf("failed to load schema: %w", err)
62 }
63
64 for _, p := range plugins {
65 if inj, ok := p.(plugin.LateSourceInjector); ok {
66 if s := inj.InjectSourceLate(cfg.Schema); s != nil {
67 cfg.Sources = append(cfg.Sources, s)
68 }
69 }
70 }
71
72
73 if err := cfg.LoadSchema(); err != nil {
74 return fmt.Errorf("failed to load schema: %w", err)
75 }
76
77 if err := cfg.Init(); err != nil {
78 return fmt.Errorf("generating core failed: %w", err)
79 }
80
81 for _, p := range plugins {
82 if mut, ok := p.(plugin.ConfigMutator); ok {
83 err := mut.MutateConfig(cfg)
84 if err != nil {
85 return fmt.Errorf("%s: %w", p.Name(), err)
86 }
87 }
88 }
89
90 data_plugins := make([]interface{}, len(plugins))
91 for index := range plugins {
92 data_plugins[index] = plugins[index]
93 }
94 data, err := codegen.BuildData(cfg, data_plugins...)
95 if err != nil {
96 return fmt.Errorf("merging type systems failed: %w", err)
97 }
98
99 if err = codegen.GenerateCode(data); err != nil {
100 return fmt.Errorf("generating core failed: %w", err)
101 }
102
103 if !cfg.SkipModTidy {
104 if err = cfg.Packages.ModTidy(); err != nil {
105 return fmt.Errorf("tidy failed: %w", err)
106 }
107 }
108
109 for _, p := range plugins {
110 if mut, ok := p.(plugin.CodeGenerator); ok {
111 err := mut.GenerateCode(data)
112 if err != nil {
113 return fmt.Errorf("%s: %w", p.Name(), err)
114 }
115 }
116 }
117
118 if err = codegen.GenerateCode(data); err != nil {
119 return fmt.Errorf("generating core failed: %w", err)
120 }
121
122 if !cfg.SkipValidation {
123 if err := validate(cfg); err != nil {
124 return fmt.Errorf("validation failed: %w", err)
125 }
126 }
127
128 return nil
129 }
130
131 func validate(cfg *config.Config) error {
132 roots := []string{cfg.Exec.ImportPath()}
133 if cfg.Model.IsDefined() {
134 roots = append(roots, cfg.Model.ImportPath())
135 }
136
137 if cfg.Resolver.IsDefined() {
138 roots = append(roots, cfg.Resolver.ImportPath())
139 }
140
141 cfg.Packages.LoadAll(roots...)
142 errs := cfg.Packages.Errors()
143 if len(errs) > 0 {
144 return errs
145 }
146 return nil
147 }
148
View as plain text