Skip to content

Commit 2c50837

Browse files
committed
1 parent 8921e6f commit 2c50837

4 files changed

Lines changed: 49 additions & 152 deletions

File tree

go.mod

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ go 1.22.0
55
require (
66
github.com/fsnotify/fsnotify v1.7.0
77
gopkg.in/yaml.v2 v2.4.0
8-
gopkg.in/yaml.v3 v3.0.1
98
)
109

1110
require golang.org/x/sys v0.4.0 // indirect

go.sum

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,3 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+
66
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
77
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
88
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
9-
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
10-
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

lib/service-gen.go

Lines changed: 44 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ import (
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

2018
type 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

3329
type 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

4738
const 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
325255
func 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)

main.go

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package main
22

33
import (
44
"flag"
5-
"fmt"
65
"github.com/cloudimpl/next-gen/lib"
76
"github.com/fsnotify/fsnotify"
87
"log"
@@ -87,13 +86,11 @@ func watch(appPath string, onChange func()) {
8786
<-done
8887
}
8988

90-
func generate(appPath string) error {
89+
func generate(appPath string) {
9190
err := lib.GenerateServices(appPath, true)
9291
if err != nil {
93-
return fmt.Errorf("Error generating services: %s\n", err.Error())
92+
log.Fatalf("Error generating services: %s\n", err.Error())
9493
}
95-
96-
return nil
9794
}
9895

9996
func watchAndGenerate(appPath string) {
@@ -106,9 +103,9 @@ func watchAndGenerate(appPath string) {
106103
log.Printf("Starting watcher on: %s", servicesPath)
107104

108105
watch(servicesPath, func() {
109-
err := generate(appPath)
106+
err := lib.GenerateServices(appPath, true)
110107
if err != nil {
111-
log.Println(err.Error())
108+
log.Printf("Error generating services: %v", err)
112109
}
113110
})
114111
}
@@ -154,9 +151,6 @@ func main() {
154151
if *watch {
155152
watchAndGenerate(appPath)
156153
} else {
157-
err := generate(appPath)
158-
if err != nil {
159-
log.Fatalf(err.Error())
160-
}
154+
generate(appPath)
161155
}
162156
}

0 commit comments

Comments
 (0)