77 "go/ast"
88 "go/parser"
99 "go/token"
10- "gopkg.in/yaml.v3"
11- "io/fs"
1210 "os"
1311 "os/exec"
1412 "path/filepath"
@@ -18,30 +16,23 @@ import (
1816)
1917
2018type MethodInfo struct {
21- OriginalName string `yaml:"originalName"`
22- Name string `yaml:"name"`
23- InputType string `yaml:"inputType"`
24- IsInputPointer bool `yaml:"isInputPointer"` // Whether the input type is a pointer
25- InputSchema []Field `yaml:"inputSchema"`
26- OutputType string `yaml:"outputType"`
27- IsOutputPointer bool `yaml:"isOutputPointer"` // Whether the output type is a pointer
28- OutputSchema []Field `yaml:"outputSchema"`
29- IsWorkflow bool `yaml:"isWorkflow"`
30- IsService bool `yaml:"isService"`
19+ OriginalName string
20+ Name string
21+ InputType string
22+ InputSchema map [string ]interface {}
23+ OutputSchema map [string ]interface {}
24+ IsWorkflow bool
25+ IsService bool
26+ IsPointer bool // Whether the input type is a pointer
3127}
3228
3329type ServiceInfo struct {
34- ModuleName string `yaml:"moduleName"`
35- ServiceName string `yaml:"serviceName"`
36- ServiceStructName string `yaml:"serviceStructName"`
37- Methods []MethodInfo `yaml:"methods"`
38- IsProduction bool // New flag to determine if we are in production mode
39- Imports []string `yaml:"imports"`
40- }
41-
42- type Field struct {
43- Name string `yaml:"name"`
44- Type string `yaml:"type"`
30+ ModuleName string
31+ ServiceName string
32+ ServiceStructName string
33+ Methods []MethodInfo
34+ IsProduction bool // New flag to determine if we are in production mode
35+ Imports []string
4536}
4637
4738const wrapperTemplate = `package _polycode
@@ -98,7 +89,7 @@ func (t *{{.ServiceStructName}}) ExecuteService(ctx polycode.ServiceContext, met
9889 {{range .Methods}}{{if .IsService}}case "{{.Name}}":
9990 {
10091 // Pass the input correctly as a pointer or value based on the method signature
101- {{if .IsInputPointer }}
92+ {{if .IsPointer }}
10293 return service.{{.OriginalName}}(ctx, input.(*{{.InputType}}))
10394 {{else}}
10495 return service.{{.OriginalName}}(ctx, *(input.(*{{.InputType}})))
@@ -119,7 +110,7 @@ func (t *{{.ServiceStructName}}) ExecuteWorkflow(ctx polycode.WorkflowContext, m
119110 {{range .Methods}}{{if .IsWorkflow}}case "{{.Name}}":
120111 {
121112 // Pass the input correctly as a pointer or value based on the method signature
122- {{if .IsInputPointer }}
113+ {{if .IsPointer }}
123114 return service.{{.OriginalName}}(ctx, input.(*{{.InputType}}))
124115 {{else}}
125116 return service.{{.OriginalName}}(ctx, *(input.(*{{.InputType}})))
@@ -177,46 +168,8 @@ func getModuleName(filePath string) (string, error) {
177168 return "" , fmt .Errorf ("module name not found in go.mod" )
178169}
179170
180- func extractStructs (root string ) (map [string ][]Field , error ) {
181- structDefs := make (map [string ][]Field )
182- err := filepath .WalkDir (root , func (path string , d fs.DirEntry , err error ) error {
183- if err != nil || d .IsDir () || ! strings .HasSuffix (path , ".go" ) {
184- return err
185- }
186-
187- fset := token .NewFileSet ()
188- file , err := parser .ParseFile (fset , path , nil , parser .AllErrors )
189- if err != nil {
190- return nil
191- }
192-
193- for _ , decl := range file .Decls {
194- if g , ok := decl .(* ast.GenDecl ); ok && g .Tok == token .TYPE {
195- for _ , spec := range g .Specs {
196- if typeSpec , ok := spec .(* ast.TypeSpec ); ok {
197- if structType , ok := typeSpec .Type .(* ast.StructType ); ok {
198- var fields []Field
199- for _ , field := range structType .Fields .List {
200- if len (field .Names ) > 0 {
201- fields = append (fields , Field {
202- Name : field .Names [0 ].Name ,
203- Type : fmt .Sprint (field .Type ),
204- })
205- }
206- }
207- structDefs [typeSpec .Name .Name ] = fields
208- }
209- }
210- }
211- }
212- }
213- return nil
214- })
215- return structDefs , err
216- }
217-
218- func generateService (appPath string , servicePath string , moduleName string , serviceName string , structDefs map [string ][]Field , prod bool ) error {
219- methods , imports , err := parseDir (servicePath , structDefs )
171+ func generateService (appPath string , servicePath string , moduleName string , serviceName string , prod bool ) error {
172+ methods , imports , err := parseDir (servicePath )
220173 if err != nil {
221174 fmt .Printf ("Error parsing directory: %v\n " , err )
222175 return err
@@ -227,18 +180,7 @@ func generateService(appPath string, servicePath string, moduleName string, serv
227180 return nil
228181 }
229182
230- serviceStructName := toPascalCase (serviceName )
231-
232- serviceInfo := ServiceInfo {
233- ModuleName : moduleName ,
234- ServiceName : serviceName ,
235- ServiceStructName : serviceStructName ,
236- Methods : methods ,
237- IsProduction : prod ,
238- Imports : imports ,
239- }
240-
241- generatedCode , err := generateServiceCode (serviceInfo )
183+ generatedCode , err := generateServiceCode (moduleName , serviceName , methods , imports , prod )
242184 if err != nil {
243185 fmt .Printf ("Error generating code: %v\n " , err )
244186 return err
@@ -256,12 +198,6 @@ func generateService(appPath string, servicePath string, moduleName string, serv
256198 return err
257199 }
258200
259- err = writeServiceDefinition (appPath , serviceName , serviceInfo )
260- if err != nil {
261- fmt .Printf ("Error writing service definition: %v\n " , err )
262- return err
263- }
264-
265201 return nil
266202}
267203
@@ -272,12 +208,6 @@ func GenerateServices(appPath string, prod bool) error {
272208 return err
273209 }
274210
275- structDefs , err := extractStructs (appPath )
276- if err != nil {
277- fmt .Printf ("Error extracting structs: %v\n " , err )
278- return err
279- }
280-
281211 polycodeFolder := filepath .Join (appPath , ".polycode" )
282212 servicesFolder := filepath .Join (appPath , "services" )
283213
@@ -296,7 +226,7 @@ func GenerateServices(appPath string, prod bool) error {
296226 servicePath := filepath .Join (servicesFolder , entry .Name ())
297227 println ("Generating code for path: " , servicePath )
298228 serviceName := entry .Name ()
299- err = generateService (appPath , servicePath , moduleName , serviceName , structDefs , prod )
229+ err = generateService (appPath , servicePath , moduleName , serviceName , prod )
300230 if err != nil {
301231 fmt .Printf ("Error generating service: %v\n " , err )
302232 return err
@@ -321,7 +251,7 @@ func GenerateServices(appPath string, prod bool) error {
321251 return nil
322252}
323253
324- // ValidateFunctionParams to check for polycode.ServiceContext or polycode.WorkflowContext
254+ // Modified validateFunctionParams to check for polycode.ServiceContext or polycode.WorkflowContext
325255func validateFunctionParams (fn * ast.FuncDecl ) (string , error ) {
326256 // Check if there are at least two parameters (ctx and input)
327257 if fn .Type .Params == nil || len (fn .Type .Params .List ) < 2 {
@@ -346,7 +276,7 @@ func validateFunctionParams(fn *ast.FuncDecl) (string, error) {
346276}
347277
348278// Updated parseDir function to mark methods as workflow or service
349- func parseDir (serviceFolder string , structDefs map [ string ][] Field ) ([]MethodInfo , []string , error ) {
279+ func parseDir (serviceFolder string ) ([]MethodInfo , []string , error ) {
350280 fset := token .NewFileSet ()
351281
352282 var methods []MethodInfo
@@ -387,42 +317,27 @@ func parseDir(serviceFolder string, structDefs map[string][]Field) ([]MethodInfo
387317 // Extract the function name and input/output parameters
388318 methodName := strings .ToLower (fn .Name .Name ) // Normalize to lowercase
389319
390- inputType := ""
391- outputType := ""
392- isInputPointer := false
393- isOutputPointer := false
320+ paramType := ""
321+ isPointer := false
394322 // Handle pointer types and normal types
395323 if starExpr , ok := fn .Type .Params .List [1 ].Type .(* ast.StarExpr ); ok {
396- isInputPointer = true
324+ isPointer = true
397325 if selectorExpr , ok := starExpr .X .(* ast.SelectorExpr ); ok {
398- inputType = fmt .Sprintf ("%s.%s" , selectorExpr .X .(* ast.Ident ).Name , selectorExpr .Sel .Name )
326+ paramType = fmt .Sprintf ("%s.%s" , selectorExpr .X .(* ast.Ident ).Name , selectorExpr .Sel .Name )
399327 }
400328 } else if selectorExpr , ok := fn .Type .Params .List [1 ].Type .(* ast.SelectorExpr ); ok {
401- inputType = fmt .Sprintf ("%s.%s" , selectorExpr .X .(* ast.Ident ).Name , selectorExpr .Sel .Name )
402- }
403-
404- if starExpr , ok := fn .Type .Results .List [0 ].Type .(* ast.StarExpr ); ok {
405- isOutputPointer = true
406- if selectorExpr , ok := starExpr .X .(* ast.SelectorExpr ); ok {
407- outputType = fmt .Sprintf ("%s.%s" , selectorExpr .X .(* ast.Ident ).Name , selectorExpr .Sel .Name )
408- }
409- } else if selectorExpr , ok := fn .Type .Results .List [0 ].Type .(* ast.SelectorExpr ); ok {
410- outputType = fmt .Sprintf ("%s.%s" , selectorExpr .X .(* ast.Ident ).Name , selectorExpr .Sel .Name )
329+ paramType = fmt .Sprintf ("%s.%s" , selectorExpr .X .(* ast.Ident ).Name , selectorExpr .Sel .Name )
411330 }
412331
413332 // Append the method and its corresponding input type to methods
414- if inputType != "" && outputType != "" {
333+ if paramType != "" {
415334 methods = append (methods , MethodInfo {
416- OriginalName : OriginalName ,
417- Name : methodName ,
418- InputType : inputType ,
419- IsInputPointer : isInputPointer , // Track whether the input type is a pointer
420- InputSchema : structDefs [inputType ],
421- OutputType : outputType ,
422- IsOutputPointer : isOutputPointer ,
423- OutputSchema : structDefs [outputType ],
424- IsWorkflow : contextType == "Workflow" , // Mark as workflow or service
425- IsService : contextType == "Service" ,
335+ OriginalName : OriginalName ,
336+ Name : methodName ,
337+ InputType : paramType ,
338+ IsPointer : isPointer , // Track whether the input type is a pointer
339+ IsWorkflow : contextType == "Workflow" , // Mark as workflow or service
340+ IsService : contextType == "Service" ,
426341 })
427342 }
428343 }
@@ -468,28 +383,19 @@ func toPascalCase(input string) string {
468383 return strings .Join (words , "" )
469384}
470385
471- func writeServiceDefinition (appPath string , serviceName string , serviceInfo ServiceInfo ) error {
472- outputDir := filepath .Join (appPath , ".polycode/definition" )
473- if err := os .MkdirAll (outputDir , os .ModePerm ); err != nil {
474- return err
475- }
476-
477- ymlData , err := yaml .Marshal (serviceInfo )
478- if err != nil {
479- return err
480- }
386+ // GenerateService the wrapper code based on the extracted information
387+ func generateServiceCode (moduleName string , serviceName string , methods []MethodInfo , imports []string , isProd bool ) (string , error ) {
388+ serviceStructName := toPascalCase (serviceName )
481389
482- serviceFile := filepath .Join (outputDir , serviceName + ".yml" )
483- if err := os .WriteFile (serviceFile , ymlData , 0644 ); err != nil {
484- return err
390+ serviceInfo := ServiceInfo {
391+ ModuleName : moduleName ,
392+ ServiceName : serviceName ,
393+ ServiceStructName : serviceStructName ,
394+ Methods : methods ,
395+ IsProduction : isProd ,
396+ Imports : imports ,
485397 }
486398
487- fmt .Printf ("Generated definition for: %s\n " , serviceFile )
488- return nil
489- }
490-
491- // GenerateService the wrapper code based on the extracted information
492- func generateServiceCode (serviceInfo ServiceInfo ) (string , error ) {
493399 // Use template to generate the code
494400 var buf bytes.Buffer
495401 tmpl , err := template .New ("wrapper" ).Parse (wrapperTemplate )
0 commit comments