package main import ( "flag" "fmt" protogen2 "git.diulo.com/mogfee/kit/protogen" "google.golang.org/protobuf/compiler/protogen" "google.golang.org/protobuf/types/descriptorpb" "strings" ) func main() { u := &Kit{ imports: map[string]string{}, } var flags flag.FlagSet flags.StringVar(&u.Prefix, "prefix", "", "API path prefix") protogen.Options{ ParamFunc: flags.Set, }.Run(u.Generate) protogen.Options{}.Run(u.Generate) } type Kit struct { Prefix string imports map[string]string } func (u *Kit) addImports(imp string) { u.imports[imp] = imp } func (u *Kit) packageName(f *protogen.File) string { a := f.Desc.Options().(*descriptorpb.FileOptions) p := strings.Split(*a.GoPackage, ";") if len(p) == 2 { return p[1] } return fmt.Sprintf("%s", f.Desc.Name()) } func (u *Kit) Generate(plugin *protogen.Plugin) error { if len(plugin.Files) < 1 { return nil } u.addImports("context") u.addImports("git.diulo.com/mogfee/kit/middleware") u.addImports("git.diulo.com/mogfee/kit/errors") u.addImports("git.diulo.com/mogfee/kit/response") u.addImports("github.com/gin-gonic/gin") for _, f := range plugin.Files { if len(f.Services) == 0 { continue } fname := f.GeneratedFilenamePrefix + ".http.go" t := plugin.NewGeneratedFile(fname, f.GoImportPath) t.P("package ", u.packageName(f)) t.P("import (") for _, v := range u.imports { t.P(`"` + v + `"`) } t.P(")") for _, s := range f.Services { serverName := s.GoName t.P(`func Register`, serverName, `Handler(app *gin.Engine,srv `, serverName, `Server,m ...middleware.Middleware) {`) for _, m := range s.Methods { method, path := protogen2.GetProtoMethod(m) if method == "" { continue } if u.Prefix != "" { path = u.Prefix + path } t.P(`app.`, method, `("`, path, `",http`, m.GoName, `Handler(srv,m...))`) } t.P(`}`) } for _, s := range f.Services { serverName := s.GoName for _, m := range s.Methods { method, _ := protogen2.GetProtoMethod(m) if method == "" { continue } switch method { case protogen2.METHOD_GET: u.genGet(serverName, t, m) case protogen2.METHOD_POST: u.genPost(serverName, t, m) case protogen2.METHOD_DELETE: u.genDelete(serverName, t, m) case protogen2.METHOD_PUT: u.genPut(serverName, t, m) } } } } return nil } func (u *Kit) genGet(serverName string, t *protogen.GeneratedFile, m *protogen.Method) { t.P("func http", m.GoName, "Handler(srv ", serverName, "Server,m ...middleware.Middleware)func(c *gin.Context){") t.P(`return func(c *gin.Context) { var post `, m.Input.GoIdent.GoName, ` resp := response.New(c) if err := resp.BindQuery(&post); err != nil { resp.Error(err) return } h := func(ctx context.Context, a any) (any, error) { return srv.`, m.GoName, `(ctx, a.(*`, m.Input.GoIdent.GoName, `)) } out, err := middleware.HttpMiddleware(c, h, m...)(c, &post) if err != nil { resp.Error(err) } else { if v, ok := out.(*`, m.Output.GoIdent.GoName, `); ok { resp.Success(v) } else { resp.Error(errors.InternalServer("RESULT_TYPE_ERROR", "`, m.Output.GoIdent.GoName, `")) } } }`) t.P("}") } func (u *Kit) genPost(serverName string, t *protogen.GeneratedFile, m *protogen.Method) { t.P("func http", m.GoName, "Handler(srv ", serverName, "Server,m ...middleware.Middleware)func(c *gin.Context){") t.P(`return func(c *gin.Context) { var post `, m.Input.GoIdent.GoName, ` resp := response.New(c) if err := resp.BindJSON(&post); err != nil { resp.Error(err) return } h := func(ctx context.Context, a any) (any, error) { return srv.`, m.GoName, `(ctx, a.(*`, m.Input.GoIdent.GoName, `)) } out, err := middleware.HttpMiddleware(c, h, m...)(c, &post) if err != nil { resp.Error(err) } else { if v, ok := out.(*`, m.Output.GoIdent.GoName, `); ok { resp.Success(v) } else { resp.Error(errors.InternalServer("RESULT_TYPE_ERROR", "`, m.Output.GoIdent.GoName, `")) } } }`) t.P("}") } func (u *Kit) genDelete(serverName string, t *protogen.GeneratedFile, m *protogen.Method) { t.P("func http", m.GoName, "Handler(srv ", serverName, "Server,m ...middleware.Middleware)func(c *gin.Context){") t.P(`return func(c *gin.Context) { var post `, m.Input.GoIdent.GoName, ` resp := response.New(c) if err := resp.BindJSON(&post); err != nil { resp.Error(err) return } h := func(ctx context.Context, a any) (any, error) { return srv.`, m.GoName, `(ctx, a.(*`, m.Input.GoIdent.GoName, `)) } out, err := middleware.HttpMiddleware(c, h, m...)(c, &post) if err != nil { resp.Error(err) } else { if v, ok := out.(*`, m.Output.GoIdent.GoName, `); ok { resp.Success(v) } else { resp.Error(errors.InternalServer("RESULT_TYPE_ERROR", "`, m.Output.GoIdent.GoName, `")) } } }`) t.P("}") } func (u *Kit) genPut(serverName string, t *protogen.GeneratedFile, m *protogen.Method) { t.P("func http", m.GoName, "Handler(srv ", serverName, "Server,m ...middleware.Middleware)func(c *gin.Context){") t.P(`return func(c *gin.Context) { var post `, m.Input.GoIdent.GoName, ` resp := response.New(c) if err := resp.BindJSON(&post); err != nil { resp.Error(err) return } h := func(ctx context.Context, a any) (any, error) { return srv.`, m.GoName, `(ctx, a.(*`, m.Input.GoIdent.GoName, `)) } out, err := middleware.HttpMiddleware(c, h, m...)(c, &post) if err != nil { resp.Error(err) } else { if v, ok := out.(*`, m.Output.GoIdent.GoName, `); ok { resp.Success(v) } else { resp.Error(errors.InternalServer("RESULT_TYPE_ERROR", "`, m.Output.GoIdent.GoName, `")) } } }`) t.P("}") }