@@ -34,8 +34,18 @@ type Resource struct {
3434 PostResourceResolver string
3535 Relations []string
3636 UnwrapEmbeddedStructs bool
37+
38+ // Used for generating the resolver and mock tests.
39+ // --------------------------------
40+ ShouldGenerateResolverAndMockTest bool
41+ ResolverAndMockTestTemplate string
42+
43+ // Needed because it's usually capitalised differently than 'Service'.
44+ // Used for accessing 'client.Services().{{.CloudqueryServiceName}}'.
45+ CloudqueryServiceName string
3746}
3847
48+ //go:embed templates/resolver_and_mock_test/*/*.go.tpl
3949//go:embed templates/*.go.tpl
4050var templatesFS embed.FS
4151
@@ -108,7 +118,12 @@ func (r *Resource) Generate() error {
108118 if ! ok {
109119 return fmt .Errorf ("failed to get caller information" )
110120 }
121+
111122 dir := path .Dir (filename )
123+ dir = path .Join (dir , "../../resources/services" , r .Service )
124+ if err := os .MkdirAll (dir , os .ModePerm ); err != nil {
125+ return fmt .Errorf ("failed to create directory %s: %w" , dir , err )
126+ }
112127
113128 var err error
114129 opts := []codegen.TableOption {
@@ -147,6 +162,23 @@ func (r *Resource) Generate() error {
147162 r .Table .Relations = r .Relations
148163 }
149164
165+ if err := r .generateSchema (dir ); err != nil {
166+ return err
167+ }
168+
169+ if r .ShouldGenerateResolverAndMockTest {
170+ if err := r .generateResolver (dir ); err != nil {
171+ return err
172+ }
173+ if err := r .generateMockTest (dir ); err != nil {
174+ return err
175+ }
176+ }
177+
178+ return nil
179+ }
180+
181+ func (r * Resource ) generateSchema (dir string ) error {
150182 tpl , err := template .New ("resource.go.tpl" ).Funcs (template.FuncMap {
151183 "ToCamel" : strcase .ToCamel ,
152184 "ToLower" : strings .ToLower ,
@@ -163,10 +195,6 @@ func (r *Resource) Generate() error {
163195 if err := tpl .Execute (& buff , r ); err != nil {
164196 return fmt .Errorf ("failed to execute template: %w" , err )
165197 }
166- dir = path .Join (dir , "../../resources/services" , r .Service )
167- if err := os .MkdirAll (dir , os .ModePerm ); err != nil {
168- return fmt .Errorf ("failed to create directory %s: %w" , dir , err )
169- }
170198
171199 filePath := path .Join (dir , r .SubService + ".go" )
172200 content := buff .Bytes ()
@@ -179,5 +207,77 @@ func (r *Resource) Generate() error {
179207 if err := os .WriteFile (filePath , content , 0644 ); err != nil {
180208 return fmt .Errorf ("failed to write file %s: %w" , filePath , err )
181209 }
210+
211+ return nil
212+ }
213+
214+ func (r * Resource ) generateResolver (dir string ) error {
215+ tpl , err := template .New ("fetch.go.tpl" ).Funcs (template.FuncMap {
216+ "ToCamel" : strcase .ToCamel ,
217+ "ToLower" : strings .ToLower ,
218+ }).ParseFS (templatesFS ,
219+ fmt .Sprintf ("templates/resolver_and_mock_test/%s/fetch.go.tpl" , r .ResolverAndMockTestTemplate ))
220+ if err != nil {
221+ return fmt .Errorf ("failed to parse gcp templates: %w" , err )
222+ }
223+
224+ var buff bytes.Buffer
225+ if err := tpl .Execute (& buff , r ); err != nil {
226+ return fmt .Errorf ("failed to execute template: %w" , err )
227+ }
228+
229+ filePath := path .Join (dir , r .SubService + "_fetch.go" )
230+ content := buff .Bytes ()
231+ formattedContent , err := format .Source (buff .Bytes ())
232+ if err != nil {
233+ fmt .Printf ("failed to format source: %s: %v\n " , filePath , err )
234+ } else {
235+ content = formattedContent
236+ }
237+
238+ if err := os .WriteFile (filePath , content , 0644 ); err != nil {
239+ return fmt .Errorf ("failed to write file %s: %w" , filePath , err )
240+ }
241+
242+ return nil
243+ }
244+
245+ func (r * Resource ) generateMockTest (dir string ) error {
246+ tpl , err := template .New ("mock_test.go.tpl" ).Funcs (template.FuncMap {
247+ "ToCamel" : strcase .ToCamel ,
248+ "ToLower" : strings .ToLower ,
249+ }).ParseFS (templatesFS ,
250+ fmt .Sprintf ("templates/resolver_and_mock_test/%s/mock_test.go.tpl" , r .ResolverAndMockTestTemplate ))
251+ if err != nil {
252+ return fmt .Errorf ("failed to parse gcp templates: %w" , err )
253+ }
254+
255+ var buff bytes.Buffer
256+ if err := tpl .Execute (& buff , r ); err != nil {
257+ return fmt .Errorf ("failed to execute template: %w" , err )
258+ }
259+
260+ filePath := path .Join (dir , r .SubService + "_mock_test.go" )
261+ content := buff .Bytes ()
262+ formattedContent , err := format .Source (buff .Bytes ())
263+ if err != nil {
264+ fmt .Printf ("failed to format source: %s: %v\n " , filePath , err )
265+ } else {
266+ content = formattedContent
267+ }
268+
269+ if err := os .WriteFile (filePath , content , 0644 ); err != nil {
270+ return fmt .Errorf ("failed to write file %s: %w" , filePath , err )
271+ }
272+
182273 return nil
183274}
275+
276+ // These methods are called from the template.
277+ // Because of this, we use a value receiver.
278+ // -------------------------------------------------------------------------------
279+
280+ // Because usually the 'Struct' field contains a pointer, we need to dereference with '.Elem()'.
281+ func (resource Resource ) StructName () string {
282+ return reflect .TypeOf (resource .Struct ).Elem ().Name ()
283+ }
0 commit comments