mirror of
https://github.com/cubixle/tuugen.git
synced 2026-04-24 23:04:45 +01:00
wip
This commit is contained in:
46
README.md
Normal file
46
README.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# Tuugen
|
||||
|
||||
Tuugen takes a tuugen.yml and a grpc proto definition to generate common boiler plate logic. Some of the common boiler plate it generates is http routes, grpc service, data model structs and a main file with some default plumbing.
|
||||
|
||||
Tuugen adds an interactor package which the http and grpc transport layers use for business logic.
|
||||
|
||||
Feel free to pull the repo and play around with the example_project.
|
||||
|
||||
## Using Tuugen.
|
||||
|
||||
```
|
||||
go install github.com/cubixle/tuugen
|
||||
```
|
||||
|
||||
And the run `tuugen` in the root dir of your project or wherever you have your tuugen and proto file.
|
||||
|
||||
## Example tuugen file
|
||||
```yaml
|
||||
project: tuugen_test_project
|
||||
import_path: github.com/cubixle/tuugen/example_project
|
||||
proto_file: service.proto
|
||||
grpc_file: internal/pb/service/service_grpc.pb.go
|
||||
service_name: Service
|
||||
data_models:
|
||||
- name: User
|
||||
properties:
|
||||
- name: id
|
||||
type: varchar
|
||||
autoinc: true
|
||||
- name: team_id
|
||||
type: varchar
|
||||
- name: name
|
||||
type: varchar
|
||||
- name: email
|
||||
type: varchar
|
||||
- name: created_at
|
||||
type: timestamp
|
||||
- name: updated_at
|
||||
type: timestamp
|
||||
- name: Team
|
||||
properties:
|
||||
- name: id
|
||||
type: varchar
|
||||
- name: name
|
||||
type: varchar
|
||||
```
|
||||
@@ -18,7 +18,7 @@ func main() {
|
||||
}
|
||||
|
||||
s := grpc.NewServer()
|
||||
pb.RegisterServiceServer(s, service.New(store))
|
||||
pb.RegisterServiceServer(s, service.New())
|
||||
if err := s.Serve(lis); err != nil {
|
||||
log.Fatalf("failed to serve: %v", err)
|
||||
}
|
||||
|
||||
@@ -4,8 +4,6 @@ import (
|
||||
"embed"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
|
||||
"github.com/cubixle/tuugen"
|
||||
)
|
||||
|
||||
//go:embed templates/*
|
||||
@@ -17,47 +15,47 @@ func main() {
|
||||
if err != nil {
|
||||
log.Fatalf("failed to find tuugen.yaml, %v", err)
|
||||
}
|
||||
cfg, err := tuugen.YamlToConfig(d)
|
||||
cfg, err := YamlToConfig(d)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to load config, %v", err)
|
||||
}
|
||||
|
||||
log.Printf("Generating protos from %s\n", cfg.ProtoFile)
|
||||
err = tuugen.GenerateProtos(cfg.ProtoFile)
|
||||
err = GenerateProtos(cfg.ProtoFile)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
log.Println("Generating service implementation")
|
||||
err = tuugen.GenerateService(FS, cfg)
|
||||
err = GenerateService(FS, cfg)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to generate service: %v", err)
|
||||
}
|
||||
log.Println("Generating interactor stubs")
|
||||
err = tuugen.GenerateInteractor(FS, cfg)
|
||||
err = GenerateInteractor(FS, cfg)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to generate interactor: %v", err)
|
||||
}
|
||||
|
||||
log.Println("Generating data models")
|
||||
if err := tuugen.GenerateDataModels(FS, cfg); err != nil {
|
||||
if err := GenerateDataModels(FS, cfg); err != nil {
|
||||
log.Fatalf("failed to generate data models: %v", err)
|
||||
}
|
||||
|
||||
log.Println("Generate main.go")
|
||||
if err := tuugen.GenerateMain(FS, cfg); err != nil {
|
||||
if err := GenerateMain(FS, cfg); err != nil {
|
||||
log.Fatalf("failed to generate main file: %v", err)
|
||||
}
|
||||
|
||||
log.Printf("Running 'go mod init %s' \n", cfg.ImportPath)
|
||||
if err := tuugen.GoModInit(cfg.ImportPath); err != nil {
|
||||
if err := GoModInit(cfg.ImportPath); err != nil {
|
||||
log.Fatalf("failed to run 'go mod init': %v", err)
|
||||
}
|
||||
log.Println("Running clean up")
|
||||
if err := tuugen.GoFmt(); err != nil {
|
||||
if err := GoFmt(); err != nil {
|
||||
log.Fatalf("failed to run gofmt: %v", err)
|
||||
}
|
||||
if err := tuugen.GoImports(); err != nil {
|
||||
if err := GoImports(); err != nil {
|
||||
log.Fatalf("failed to run 'goimports': %v", err)
|
||||
}
|
||||
log.Println("------")
|
||||
27
service.go
27
service.go
@@ -1,4 +1,4 @@
|
||||
package tuugen
|
||||
package main
|
||||
|
||||
import (
|
||||
"embed"
|
||||
@@ -67,20 +67,24 @@ func createFileFromProto(FS embed.FS, cfg Config, templateFile, outputFile strin
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
funcs, err := methodsFromProto(cfg)
|
||||
def, err := parseProto(cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := t.Execute(f, funcs); err != nil {
|
||||
// dirty check to see if we need to import the interactors.
|
||||
if strings.Contains(templateFile, "service") {
|
||||
def.Imports = append(def.Imports, cfg.ImportPath+"/internal/interactors")
|
||||
}
|
||||
|
||||
if err := t.Execute(f, def); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return f.Close()
|
||||
}
|
||||
|
||||
func methodsFromProto(cfg Config) (serviceDef, error) {
|
||||
funcs := []serviceFuncDef{}
|
||||
func parseProto(cfg Config) (serviceDef, error) {
|
||||
fset := token.NewFileSet()
|
||||
f, err := parser.ParseFile(fset, cfg.GRPCFile, nil, 0)
|
||||
if err != nil {
|
||||
@@ -90,10 +94,17 @@ func methodsFromProto(cfg Config) (serviceDef, error) {
|
||||
importStrs := []string{}
|
||||
servicePath := filepath.Dir(cfg.GRPCFile)
|
||||
for _, i := range f.Imports {
|
||||
importStrs = append(importStrs, i.Name.Name)
|
||||
importStrs = append(importStrs, i.Path.Value)
|
||||
}
|
||||
importStrs = append(importStrs, strings.Join([]string{cfg.ImportPath, strings.TrimLeft(servicePath, "/")}, "/"), cfg.ImportPath+"/internal/interactors")
|
||||
importStrs = append(importStrs, strings.Join([]string{cfg.ImportPath, strings.TrimLeft(servicePath, "/")}, "/"))
|
||||
|
||||
funcs := parseFuncs(cfg, f)
|
||||
|
||||
return serviceDef{Funcs: funcs, Imports: importStrs}, nil
|
||||
}
|
||||
|
||||
func parseFuncs(cfg Config, f *ast.File) []serviceFuncDef {
|
||||
funcs := []serviceFuncDef{}
|
||||
for _, m := range f.Scope.Objects {
|
||||
if m.Name != cfg.ServiceName+"Server" {
|
||||
continue
|
||||
@@ -118,7 +129,7 @@ func methodsFromProto(cfg Config) (serviceDef, error) {
|
||||
funcs = append(funcs, f)
|
||||
}
|
||||
}
|
||||
return serviceDef{Funcs: funcs, Imports: importStrs}, nil
|
||||
return funcs
|
||||
}
|
||||
|
||||
func parseFieldList(fl *ast.FieldList) []string {
|
||||
|
||||
@@ -18,7 +18,7 @@ func main() {
|
||||
}
|
||||
|
||||
s := grpc.NewServer()
|
||||
pb.Register{{.ServiceName}}Server(s, service.New(store))
|
||||
pb.Register{{.ServiceName}}Server(s, service.New())
|
||||
if err := s.Serve(lis); err != nil {
|
||||
log.Fatalf("failed to serve: %v", err)
|
||||
}
|
||||
@@ -4,6 +4,10 @@ import ({{ range .Imports }}
|
||||
"{{ . }}"{{ end }}
|
||||
)
|
||||
|
||||
func New() *Service {
|
||||
return &Service{}
|
||||
}
|
||||
|
||||
type Service struct {
|
||||
interactor *interactors.Interactor
|
||||
}
|
||||
Reference in New Issue
Block a user