diff --git a/cli/gen_all.go b/cli/gen_all.go index 6fa1cd5..56eb362 100644 --- a/cli/gen_all.go +++ b/cli/gen_all.go @@ -12,6 +12,7 @@ var GenAllHooks = []GenHook{ runGenMod, runEditorconfig, runGenState, + runGenImpl, } var genAllCmd = &cobra.Command{ diff --git a/cli/gen_impl.go b/cli/gen_impl.go new file mode 100644 index 0000000..603641b --- /dev/null +++ b/cli/gen_impl.go @@ -0,0 +1,27 @@ +package cli + +import ( + "github.com/lazygophers/codegen/codegen" + "github.com/lazygophers/log" + "github.com/spf13/cobra" +) + +var genImplCmd = &cobra.Command{ + Use: "impl", + Short: "Generate implementation files", + RunE: runGenImpl, +} + +var runGenImpl = func(cmd *cobra.Command, args []string) (err error) { + err = codegen.GenerateImpl(pb) + if err != nil { + log.Errorf("err:%v", err) + return err + } + + return nil +} + +func init() { + genCmd.AddCommand(genImplCmd) +} diff --git a/codegen/generate_add_rpc.go b/codegen/generate_add_rpc.go index 3866f5c..b26d168 100644 --- a/codegen/generate_add_rpc.go +++ b/codegen/generate_add_rpc.go @@ -152,16 +152,7 @@ func GenerateAddRpc(pb *PbPackage, msg *PbMessage, opt *AddRpcOption) (err error } // NOTE: 寻找主键 - var pkField *PbNormalField - { - for _, field := range msg.normalFields { - // 先简单粗暴用 id 当作主键,后面再改 - if field.Name == "id" { - pkField = field - break - } - } - } + pkField := msg.PrimaryField() var rpcBlock string @@ -170,15 +161,18 @@ func GenerateAddRpc(pb *PbPackage, msg *PbMessage, opt *AddRpcOption) (err error args := map[string]interface{}{ "PB": pb, "Model": opt.Model, - "Role": role, "Action": action, "GenTo": opt.GenTo, "ListOptions": opt.ListOptions, } + if role != "" { + args["Role"] = role + } + if pkField != nil { - args["PprimaryKey"] = pkField.Name - args["PprimaryKeyType"] = pkField.Type() + args["PrimaryKey"] = pkField.Name + args["PrimaryKeyType"] = pkField.Type() } var rpcName string @@ -217,7 +211,7 @@ func GenerateAddRpc(pb *PbPackage, msg *PbMessage, opt *AddRpcOption) (err error // 处理 server.rpc if rpc := pb.GetRPC(rpcName); rpc == nil { - tpl, err := GetTemplate(TemplateTypeProtoService) + tpl, err := GetTemplate(TemplateTypeProtoRpc) if err != nil { log.Errorf("err:%v", err) return err diff --git a/codegen/generate_impl.go b/codegen/generate_impl.go new file mode 100644 index 0000000..868c3f1 --- /dev/null +++ b/codegen/generate_impl.go @@ -0,0 +1,176 @@ +package codegen + +import ( + "github.com/lazygophers/log" + "github.com/lazygophers/utils/osx" + "github.com/pterm/pterm" + "io/fs" + "os" + "path/filepath" +) + +func initImplDirectory(pb *PbPackage) error { + if osx.IsDir(GetPath(PathTypeImpl, pb)) { + return nil + } + + err := os.MkdirAll(GetPath(PathTypeImpl, pb), fs.ModePerm) + if err != nil { + log.Errorf("err:%s", err) + return err + } + + return nil +} + +func initImplFile(pb *PbPackage, genTo string) (err error) { + p := filepath.Join(GetPath(PathTypeImpl, pb), genTo+".go") + if osx.IsFile(p) { + return nil + } + + tpl, err := GetTemplate(TemplateTypeImpl) + if err != nil { + log.Errorf("err:%v", err) + return err + } + + file, err := os.OpenFile(p, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, fs.FileMode(0666)) + if err != nil { + log.Errorf("err:%v", err) + return err + } + defer file.Close() + + err = tpl.Execute(file, map[string]interface{}{ + "PB": pb, + }) + if err != nil { + log.Errorf("err:%v", err) + return err + } + + _, err = file.WriteString("\n") + if err != nil { + log.Errorf("err:%v", err) + return err + } + + return nil +} + +func generateImpl(pb *PbPackage, rpc *PbRPC) (err error) { + pterm.Info.Printfln("try generate impl %s to %s", rpc.Name, rpc.genOption.GenTo) + + err = initImplFile(pb, rpc.genOption.GenTo) + if err != nil { + log.Errorf("err:%v", err) + return err + } + + path := filepath.Join(GetPath(PathTypeImpl, pb), rpc.genOption.GenTo+".go") + + log.Infof("gen impl action %s", rpc.genOption.Action) + + // TODO: 缓存 + goFile, err := ParseGoFile(path) + if err != nil { + log.Errorf("err:%v", err) + return err + } + + for _, goFunc := range goFile.funcs { + if goFunc.RecvType != "" { + continue + } + + if goFunc.Name == rpc.Name { + pterm.Warning.Printfln("%s is exist, skip generate", rpc.Name) + return nil + } + } + + args := map[string]any{ + "PB": pb, + "RpcName": rpc.Name, + "RequestType": rpc.rpc.RequestType, + "ResponseType": rpc.rpc.ReturnsType, + } + + if rpc.genOption.Model != "" { + log.Infof("model:%s", rpc.genOption.Model) + + args["Model"] = rpc.genOption.Model + + msg := pb.GetMessage(rpc.genOption.Model) + if msg != nil { + pkField := msg.PrimaryField() + if pkField != nil { + args["PrimaryKey"] = pkField.Name + args["PrimaryKeyType"] = pkField.Type() + } + } + } + + tpl, err := GetTemplate(TemplateTypeImplAction, rpc.genOption.Action) + if err != nil { + log.Errorf("err:%v", err) + return err + } + + file, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_APPEND, fs.FileMode(0666)) + if err != nil { + log.Errorf("err:%v", err) + return err + } + defer file.Close() + + //_, err = file.Seek(0, io.SeekEnd) + //if err != nil { + // log.Errorf("err:%v", err) + // return err + //} + + err = tpl.Execute(file, args) + if err != nil { + log.Errorf("err:%v", err) + return err + } + + _, err = file.WriteString("\n") + if err != nil { + log.Errorf("err:%v", err) + return err + } + + pterm.Success.Printfln("generate %s success", rpc.Name) + + return nil +} + +func GenerateImpl(pb *PbPackage) (err error) { + pterm.Info.Printfln("Generating impl directory...") + + err = initImplDirectory(pb) + if err != nil { + log.Errorf("err:%v", err) + return err + } + + log.Info("————————————————————分割线————————————————") + + for _, rpc := range pb.RPCs() { + err = generateImpl(pb, rpc) + if err != nil { + log.Errorf("err:%v", err) + return err + } + + log.Info(rpc.Name) + log.Info(rpc.options) + log.Info(rpc.comment) + log.Info(rpc.genOption) + } + + return nil +} diff --git a/codegen/goparse.go b/codegen/goparse.go index 3787b62..2a26f92 100644 --- a/codegen/goparse.go +++ b/codegen/goparse.go @@ -178,15 +178,15 @@ type GoStruct struct { } type GoFile struct { - Imports []*GoImport - Funcs []*GoFunc - Structs []*GoStruct + imports []*GoImport + funcs []*GoFunc + structs []*GoStruct } func (p *GoPackage) buildFuncMap() { p.FuncMap = map[string]*GoFuncNode{} for _, v := range p.FileMap { - for _, x := range v.Funcs { + for _, x := range v.funcs { p.FuncMap[x.Name] = &GoFuncNode{ goFunc: x, goFile: v, @@ -370,7 +370,7 @@ func fetchImports(ctx *GoContext, f *ast.File, goFile *GoFile) { goImport.Name = path.Base(goImport.Path) } } - goFile.Imports = append(goFile.Imports, goImport) + goFile.imports = append(goFile.imports, goImport) } } func getSelectorExprIndents(ctx *GoContext, c ast.Expr, goFunc *GoFunc) []string { @@ -621,13 +621,12 @@ func parseFuncDecl(ctx *GoContext, f *ast.FuncDecl) *GoFunc { } func fetchFunc(ctx *GoContext, f *ast.FuncDecl, goFile *GoFile) { - log.Info(f.Doc) goFunc := parseFuncDecl(ctx, f) if goFunc == nil { return } - goFile.Funcs = append(goFile.Funcs, goFunc) + goFile.funcs = append(goFile.funcs, goFunc) } func fetchType(ctx *GoContext, ts *ast.TypeSpec, goFile *GoFile) { if ts.Type == nil { @@ -642,7 +641,7 @@ func fetchType(ctx *GoContext, ts *ast.TypeSpec, goFile *GoFile) { } switch ts.Type.(type) { case *ast.StructType: - goFile.Structs = append(goFile.Structs, &GoStruct{ + goFile.structs = append(goFile.structs, &GoStruct{ Name: name, }) } @@ -800,7 +799,7 @@ func (p *ScanErrCodeContext) Scan(mod, name string) { // 找下这个模块的 path goFile := node.goFile var impPath string - for _, x := range goFile.Imports { + for _, x := range goFile.imports { if x.Name == callMod { impPath = x.Path break diff --git a/codegen/path.go b/codegen/path.go index 4c71260..8433bd9 100644 --- a/codegen/path.go +++ b/codegen/path.go @@ -14,11 +14,14 @@ const ( PathTypeTableField PathTypeInternal + PathTypeState PathTypeStateTable PathTypeStateConf PathTypeStateCache PathTypeStateState + + PathTypeImpl ) func GetPath(t PathType, pb *PbPackage) string { @@ -59,6 +62,9 @@ func GetPath(t PathType, pb *PbPackage) string { case PathTypeStateState: return filepath.Join(GetPath(PathTypeState, pb), "state.go") + case PathTypeImpl: + return filepath.Join(GetPath(PathTypeInternal, pb), "impl") + default: panic("unsupported path type") } diff --git a/codegen/pbparse.go b/codegen/pbparse.go index 17c81ef..6be35ee 100644 --- a/codegen/pbparse.go +++ b/codegen/pbparse.go @@ -5,7 +5,10 @@ import ( "github.com/emicklei/proto" "github.com/lazygophers/codegen/state" "github.com/lazygophers/log" + "github.com/lazygophers/lrpc/middleware/core" "github.com/lazygophers/utils/candy" + "github.com/lazygophers/utils/json" + "github.com/lazygophers/utils/stringx" "github.com/pterm/pterm" "os" "path/filepath" @@ -25,9 +28,11 @@ func (p *PbOption) walk() { } func NewPbOption(o *proto.Option) *PbOption { - return &PbOption{ + p := &PbOption{ option: o, } + p.walk() + return p } type PbCommentTag struct { @@ -102,10 +107,14 @@ func (p *PbComment) walk() { } func NewPbComment(c *proto.Comment) *PbComment { - return &PbComment{ + p := &PbComment{ comment: c, tags: map[string]*PbCommentTag{}, } + + p.walk() + + return p } type PbEnum struct { @@ -117,7 +126,6 @@ func (p *PbEnum) Enum() *proto.Enum { } func (p *PbEnum) walk() { - } func NewPbEnum(e *proto.Enum) *PbEnum { @@ -125,12 +133,27 @@ func NewPbEnum(e *proto.Enum) *PbEnum { enum: e, } + p.walk() + return p } +type PbRpcGenOptions struct { + GenTo string + Model string + Action string + Role string + Method string + Path string +} + type PbRPC struct { rpc *proto.RPC Name string + + options map[string]map[string]string + comment *PbComment + genOption *PbRpcGenOptions } func (p *PbRPC) RPC() *proto.RPC { @@ -138,14 +161,96 @@ func (p *PbRPC) RPC() *proto.RPC { } func (p *PbRPC) walk() { + for _, option := range p.rpc.Options { + p.options[option.Name] = make(map[string]string, len(option.AggregatedConstants)) + for _, value := range option.AggregatedConstants { + p.options[option.Name][value.Name] = value.Literal.Source + } + } + + if p.rpc.Comment != nil { + p.comment = NewPbComment(p.rpc.Comment) + } + + // 优先解析 options 的 + if v, ok := p.options["core.lazygen"]; ok { + var gen core.LazyGen + buffer, err := json.Marshal(v) + if err != nil { + log.Panicf("err:%v", err) + return + } + + err = json.Unmarshal(buffer, &gen) + if err != nil { + log.Panicf("err:%v", err) + return + } + + if gen.Role != nil { + p.genOption.Role = *gen.Role + } + } + + if v, ok := p.options["core.http"]; ok { + var gen core.Http + buffer, err := json.Marshal(v) + if err != nil { + log.Panicf("err:%v", err) + return + } + + err = json.Unmarshal(buffer, &gen) + if err != nil { + log.Panicf("err:%v", err) + return + } + + if gen.Method != nil { + p.genOption.Method = *gen.Method + } + + if gen.Path != nil { + p.genOption.Path = *gen.Path + } + } + + // 然后解析 注释的 + if p.comment != nil { + if v, ok := p.comment.tags["gen"]; ok { + p.genOption.GenTo = strings.ReplaceAll(strings.Join(v.Lines(), ""), " ", "") + } + + if v, ok := p.comment.tags["model"]; ok { + p.genOption.Model = strings.ReplaceAll(strings.Join(v.Lines(), ""), " ", "") + } + + if v, ok := p.comment.tags["action"]; ok { + p.genOption.Action = strings.ReplaceAll(strings.Join(v.Lines(), ""), " ", "") + } + + if v, ok := p.comment.tags["role"]; ok { + p.genOption.Role = strings.ReplaceAll(strings.Join(v.Lines(), ""), " ", "") + } + } + + if p.genOption.GenTo == "" { + if p.genOption.Model != "" { + p.genOption.GenTo = stringx.ToSnake(strings.TrimPrefix(p.genOption.Model, "Model")) + } else { + p.genOption.GenTo = "impl" + } + } } func NewPbRPC(rpc *proto.RPC) *PbRPC { p := &PbRPC{ - Name: rpc.Name, - rpc: rpc, + Name: rpc.Name, + rpc: rpc, + options: make(map[string]map[string]string, len(rpc.Options)), + genOption: &PbRpcGenOptions{}, } - + p.walk() return p } @@ -165,6 +270,8 @@ func NewPbService(service *proto.Service) *PbService { service: service, } + p.walk() + return p } @@ -214,19 +321,21 @@ func (p *PbNormalField) walk() { if p.field.Comment != nil { p.comment = NewPbComment(p.field.Comment) - p.comment.walk() } if p.field.InlineComment != nil { p.inlineComment = NewPbComment(p.field.InlineComment) - p.inlineComment.walk() } } func NewPbNormalField(f *proto.NormalField) *PbNormalField { - return &PbNormalField{ + p := &PbNormalField{ field: f, } + + p.walk() + + return p } type PbMapField struct { @@ -246,11 +355,19 @@ func (p *PbMapField) IsSlice() bool { return false } +func (p *PbMapField) walk() { + +} + func NewPbMapField(f *proto.MapField) *PbMapField { - return &PbMapField{ + p := &PbMapField{ Name: f.Name, field: f, } + + p.walk() + + return p } type PbEnumField struct { @@ -285,6 +402,18 @@ type PbMessage struct { Name string } +func (p *PbMessage) PrimaryField() (pkField *PbNormalField) { + for _, field := range p.normalFields { + // 先简单粗暴用 id 当作主键,后面再改 + if field.Name == "id" { + pkField = field + break + } + } + + return pkField +} + func (p *PbMessage) NormalFields() []*PbNormalField { fields := make([]*PbNormalField, 0, len(p.normalFields)) for _, field := range p.normalFields { @@ -354,7 +483,6 @@ func (p *PbMessage) walk() { for _, field := range visitor.normalFields { pterm.Info.Printfln("find normal field:%s in %s", field.Name, p.Name) p.normalFields[field.Name] = NewPbNormalField(field) - p.normalFields[field.Name].walk() } for _, field := range visitor.enumFields { @@ -365,13 +493,15 @@ func (p *PbMessage) walk() { } func NewPbMessage(m *proto.Message) *PbMessage { - return &PbMessage{ + p := &PbMessage{ message: m, normalFields: map[string]*PbNormalField{}, mapFields: map[string]*PbMapField{}, enumFields: map[string]*PbEnumField{}, } + p.walk() + return p } type PbPackage struct { @@ -506,7 +636,6 @@ func (p *PbPackage) Walk() { pterm.Info.Printfln("find message:%s", m.Name) p.msgMap[m.Name] = NewPbMessage(m) - p.msgMap[m.Name].walk() p.messages = append(p.messages, p.msgMap[m.Name]) }), proto.WithService(func(s *proto.Service) { @@ -514,7 +643,6 @@ func (p *PbPackage) Walk() { pterm.Info.Printfln("find service:%s", s.Name) p.serviceMap[s.Name] = NewPbService(s) - p.serviceMap[s.Name].walk() p.services = append(p.services, p.serviceMap[s.Name]) }), proto.WithRPC(func(r *proto.RPC) { @@ -522,7 +650,6 @@ func (p *PbPackage) Walk() { pterm.Info.Printfln("find rpc:%s", r.Name) p.rpcMap[r.Name] = NewPbRPC(r) - p.rpcMap[r.Name].walk() p.rpcs = append(p.rpcs, p.rpcMap[r.Name]) }), proto.WithEnum(func(e *proto.Enum) { @@ -530,7 +657,6 @@ func (p *PbPackage) Walk() { pterm.Info.Printfln("find enum:%s", e.Name) p.enumMap[e.Name] = NewPbEnum(e) - p.enumMap[e.Name].walk() p.enums = append(p.enums, p.enumMap[e.Name]) }), proto.WithOption(func(option *proto.Option) { @@ -538,7 +664,6 @@ func (p *PbPackage) Walk() { pterm.Info.Printfln("find option:%s", option.Name) p.optionMap[option.Name] = NewPbOption(option) - p.optionMap[option.Name].walk() p.options = append(p.options, p.optionMap[option.Name]) }), proto.WithPackage(func(pp *proto.Package) { @@ -551,6 +676,10 @@ func (p *PbPackage) Walk() { if o, ok := p.optionMap["go_package"]; ok { p.RawGoPackage = o.Value + idx := strings.Index(p.RawGoPackage, ";") + if idx > 0 { + p.RawGoPackage = p.RawGoPackage[:idx] + } } } diff --git a/codegen/resource.go b/codegen/resource.go index ea8f10e..4a194be 100644 --- a/codegen/resource.go +++ b/codegen/resource.go @@ -7,6 +7,7 @@ import ( "github.com/lazygophers/log" "github.com/lazygophers/utils/anyx" "github.com/lazygophers/utils/candy" + "github.com/lazygophers/utils/osx" "github.com/lazygophers/utils/stringx" "github.com/pterm/pterm" "go.uber.org/atomic" @@ -17,6 +18,7 @@ import ( //go:embed template/* //go:embed template/state/* +//go:embed template/impl/* var embedFs embed.FS type TemplateType uint8 @@ -27,7 +29,7 @@ const ( TemplateTypeTableName TemplateTypeTableField - TemplateTypeProtoService + TemplateTypeProtoRpc TemplateTypeProtoRpcName TemplateTypeProtoRpcReq TemplateTypeProtoRpcResp @@ -36,6 +38,9 @@ const ( TemplateTypeStateConf TemplateTypeStateCache TemplateTypeStateState + + TemplateTypeImpl + TemplateTypeImplAction ) func GetTemplate(t TemplateType, args ...string) (tpl *template.Template, err error) { @@ -58,15 +63,15 @@ func GetTemplate(t TemplateType, args ...string) (tpl *template.Template, err er systemPath = state.Config.Template.TableField embedPath = "template/table_field.gen.gtpl" - case TemplateTypeProtoService: - systemPath = state.Config.Template.Proto.Service + case TemplateTypeProtoRpc: + systemPath = state.Config.Template.Proto.Rpc embedPath = "template/proto/rpc_service.gtpl" case TemplateTypeProtoRpcName: if len(args) != 1 { panic("Must provide") } - if v, ok := state.Config.Template.Proto.Rpc[args[0]]; ok && v != nil { + if v, ok := state.Config.Template.Proto.Action[args[0]]; ok && v != nil { systemPath = v.Name } embedPath = fmt.Sprintf("template/proto/%s.name.rpc.gtpl", args[0]) @@ -75,7 +80,7 @@ func GetTemplate(t TemplateType, args ...string) (tpl *template.Template, err er if len(args) != 1 { panic("Must provide") } - if v, ok := state.Config.Template.Proto.Rpc[args[0]]; ok && v != nil { + if v, ok := state.Config.Template.Proto.Action[args[0]]; ok && v != nil { systemPath = v.Req } embedPath = fmt.Sprintf("template/proto/%s.req.rpc.gtpl", args[0]) @@ -84,7 +89,7 @@ func GetTemplate(t TemplateType, args ...string) (tpl *template.Template, err er if len(args) != 1 { panic("Must provide") } - if v, ok := state.Config.Template.Proto.Rpc[args[0]]; ok && v != nil { + if v, ok := state.Config.Template.Proto.Action[args[0]]; ok && v != nil { systemPath = v.Resp } embedPath = fmt.Sprintf("template/proto/%s.resp.rpc.gtpl", args[0]) @@ -105,6 +110,21 @@ func GetTemplate(t TemplateType, args ...string) (tpl *template.Template, err er systemPath = state.Config.Template.State embedPath = "template/state/state.gtpl" + case TemplateTypeImpl: + systemPath = state.Config.Template.Impl.Impl + embedPath = "template/impl/impl.gtpl" + + case TemplateTypeImplAction: + systemPath = state.Config.Template.Impl.Action[args[0]] + if !osx.IsFile(systemPath) { + systemPath = state.Config.Template.Impl.Action[""] + } + + embedPath = fmt.Sprintf("template/impl/%s.rpc.gtpl", args[0]) + if !osx.FsHasFile(embedFs, embedPath) { + embedPath = "template/impl/.rpc.gtpl" + } + default: panic("unsupported template type") } @@ -183,11 +203,12 @@ func DecrWithKey(key string, def int64) int64 { } var DefaultTemplateFunc = template.FuncMap{ - "ToCamel": stringx.ToCamel, - "ToSnake": stringx.ToSnake, - "ToLower": strings.ToLower, - "ToUpper": strings.ToUpper, - "ToTitle": strings.ToTitle, + "ToCamel": stringx.ToCamel, + "ToSmallCamel": stringx.ToSmallCamel, + "ToSnake": stringx.ToSnake, + "ToLower": strings.ToLower, + "ToUpper": strings.ToUpper, + "ToTitle": strings.ToTitle, "TrimPrefix": strings.TrimPrefix, "TrimSuffix": strings.TrimSuffix, diff --git a/codegen/template/impl/.rpc.gtpl b/codegen/template/impl/.rpc.gtpl new file mode 100644 index 0000000..3c7b691 --- /dev/null +++ b/codegen/template/impl/.rpc.gtpl @@ -0,0 +1,5 @@ +func {{ RpcName }}(ctx *lrpc.Ctx, req *{{ .PB.GoPackageName }}.{{ ReqType }}) (*{{ .PB.GoPackageName }}.{{ .RespType }}, error) { + var resp {{ .PB.GoPackageName }}.{{ .RespType }} + + return &resp, nil +} diff --git a/codegen/template/impl/add.rpc.gtpl b/codegen/template/impl/add.rpc.gtpl new file mode 100644 index 0000000..5129a83 --- /dev/null +++ b/codegen/template/impl/add.rpc.gtpl @@ -0,0 +1,18 @@ +func {{ .RpcName }}(ctx *lrpc.Ctx, req *{{ .PB.GoPackageName }}.{{ .RequestType }}) (*{{ .PB.GoPackageName }}.{{ .ResponseType }}, error) { + var rsp {{ .PB.GoPackageName }}.{{ .ResponseType }} + + {{ ToSmallCamel (TrimPrefix .Model "Model") }} := *req.{{ ToCamel (TrimPrefix .Model "Model") }} + {{ ToSmallCamel (TrimPrefix .Model "Model") }}.{{ ToCamel .PrimaryKey }} = 0 + + err := state.{{ ToCamel (TrimPrefix .Model "Model") }}. + NewScoop(). + Create(&{{ ToSmallCamel (TrimPrefix .Model "Model") }}) + if err != nil { + log.Errorf("err:%v", err) + return nil, err + } + + rsp.{{ ToCamel (TrimPrefix .Model "Model") }} = &{{ ToSnake (TrimPrefix .Model "Model") }} + + return &rsp, nil +} diff --git a/codegen/template/impl/del.rpc.gtpl b/codegen/template/impl/del.rpc.gtpl new file mode 100644 index 0000000..51468d6 --- /dev/null +++ b/codegen/template/impl/del.rpc.gtpl @@ -0,0 +1,15 @@ +func {{ .RpcName }}(ctx *lrpc.Ctx, req *{{ .PB.GoPackageName }}.{{ .RequestType }}) (*{{ .PB.GoPackageName }}.{{ .ResponseType }}, error) { + var rsp {{ .PB.GoPackageName }}.{{ .ResponseType }} + + err := state.{{ ToCamel (TrimPrefix .Model "Model") }}. + NewScoop(). + Where("{{ .PrimaryKey }} = ?", req.{{ ToCamel .PrimaryKey }}). + Delete(). + Error + if err != nil { + log.Errorf("err:%v", err) + return nil, err + } + + return &rsp, nil +} diff --git a/codegen/template/impl/get.rpc.gtpl b/codegen/template/impl/get.rpc.gtpl new file mode 100644 index 0000000..274bbcd --- /dev/null +++ b/codegen/template/impl/get.rpc.gtpl @@ -0,0 +1,16 @@ +func {{ .RpcName }}(ctx *lrpc.Ctx, req *{{ .PB.GoPackageName }}.{{ .RequestType }}) (*{{ .PB.GoPackageName }}.{{ .ResponseType }}, error) { + var rsp {{ .PB.GoPackageName }}.{{ .ResponseType }} + + {{ ToSmallCamel (TrimPrefix .Model "Model") }}, err := state.{{ ToCamel (TrimPrefix .Model "Model") }}. + NewScoop(). + Where("{{ .PrimaryKey }} = ?", req.{{ ToCamel .PrimaryKey }}). + First() + if err != nil { + log.Errorf("err:%v", err) + return nil, err + } + + rsp.{{ ToCamel (TrimPrefix .Model "Model") }} = {{ ToSmallCamel (TrimPrefix .Model "Model") }} + + return &rsp, nil +} diff --git a/codegen/template/impl/impl.gtpl b/codegen/template/impl/impl.gtpl new file mode 100644 index 0000000..ab6905e --- /dev/null +++ b/codegen/template/impl/impl.gtpl @@ -0,0 +1,9 @@ +package impl + +import ( + "github.com/lazygophers/{{ .PB.GoPackageName }}" + "github.com/lazygophers/{{ .PB.GoPackageName }}/internal/state" + "github.com/lazygophers/log" + "github.com/lazygophers/lrpc" + "github.com/lazygophers/lrpc/middleware/xerror" +) diff --git a/codegen/template/impl/list.rpc.gtpl b/codegen/template/impl/list.rpc.gtpl new file mode 100644 index 0000000..9e09bb9 --- /dev/null +++ b/codegen/template/impl/list.rpc.gtpl @@ -0,0 +1,33 @@ +func {{ .RpcName }}(ctx *lrpc.Ctx, req *{{ .PB.GoPackageName }}.{{ .RequestType }}) (*{{ .PB.GoPackageName }}.{{ .ResponseType }}, error) { + var rsp {{ .PB.GoPackageName }}.{{ .ResponseType }} + + scoop := state.{{ ToCamel (TrimPrefix .Model "Model") }}.NewScoop() + + err := req.ListOption.Processor(). + //String(int32(example.ListTaskReq_ListOptionTitle), func(value string) error { + // scoop.Like(example.DbTitle, value) + // return nil + //}). + //String(int32(example.ListTaskReq_ListOptionUid), func(value string) error { + // scoop.Like(example.DbUid, value) + // return nil + //}). + Process() + if err != nil { + if xerror.CheckCode(err, xerror.ErrNoData) { + rsp.Paginate = req.ListOption.Paginate() + return &rsp, nil + } + + log.Errorf("err:%v", err) + return nil, err + } + + rsp.Paginate, rsp.List, err = scoop.FindByPage(req.ListOption) + if err != nil { + log.Errorf("err:%v", err) + return nil, err + } + + return &rsp, nil +} diff --git a/codegen/template/impl/set.rpc.gtpl b/codegen/template/impl/set.rpc.gtpl new file mode 100644 index 0000000..beaa774 --- /dev/null +++ b/codegen/template/impl/set.rpc.gtpl @@ -0,0 +1,26 @@ +func {{ .RpcName }}(ctx *lrpc.Ctx, req *{{ .PB.GoPackageName }}.{{ .RequestType }}) (*{{ .PB.GoPackageName }}.{{ .ResponseType }}, error) { + var rsp {{ .PB.GoPackageName }}.{{ .ResponseType }} + + {{ ToSmallCamel (TrimPrefix .Model "Model") }} := req.{{ ToCamel (TrimPrefix .Model "Model") }} + + err := state.{{ ToCamel (TrimPrefix .Model "Model") }}. + NewScoop(). + Where("{{ .PrimaryKey }} = ?", {{ ToSmallCamel (TrimPrefix .Model "Model") }}.{{ ToCamel .PrimaryKey }}). + Updates(&{{ ToSmallCamel (TrimPrefix .Model "Model") }}). + Error + if err != nil { + log.Errorf("err:%v", err) + return nil, err + } + + rsp.{{ ToCamel (TrimPrefix .Model "Model") }}, err = state.{{ ToCamel (TrimPrefix .Model "Model") }}. + NewScoop(). + Where("{{ .PrimaryKey }} = ?", {{ ToSmallCamel (TrimPrefix .Model "Model") }}.{{ ToCamel .PrimaryKey }}). + First() + if err != nil { + log.Errorf("err:%v", err) + return nil, err + } + + return &rsp, nil +} diff --git a/codegen/template/proto/del.req.rpc.gtpl b/codegen/template/proto/del.req.rpc.gtpl index c47b9d8..d37bfec 100644 --- a/codegen/template/proto/del.req.rpc.gtpl +++ b/codegen/template/proto/del.req.rpc.gtpl @@ -1,4 +1,4 @@ message {{ .RequestType }} { -{{with .PprimaryKey }} // @validate: required - {{ $.PprimaryKeyType}} {{ $.PprimaryKey }} = 1;{{end}} +{{with .PrimaryKey }} // @validate: required + {{ $.PrimaryKeyType}} {{ $.PrimaryKey }} = 1;{{end}} } diff --git a/codegen/template/proto/get.req.rpc.gtpl b/codegen/template/proto/get.req.rpc.gtpl index c47b9d8..d37bfec 100644 --- a/codegen/template/proto/get.req.rpc.gtpl +++ b/codegen/template/proto/get.req.rpc.gtpl @@ -1,4 +1,4 @@ message {{ .RequestType }} { -{{with .PprimaryKey }} // @validate: required - {{ $.PprimaryKeyType}} {{ $.PprimaryKey }} = 1;{{end}} +{{with .PrimaryKey }} // @validate: required + {{ $.PrimaryKeyType}} {{ $.PrimaryKey }} = 1;{{end}} } diff --git a/codegen/template/proto/list.resp.rpc.gtpl b/codegen/template/proto/list.resp.rpc.gtpl index 4cc67e0..92941bc 100644 --- a/codegen/template/proto/list.resp.rpc.gtpl +++ b/codegen/template/proto/list.resp.rpc.gtpl @@ -1,4 +1,4 @@ message {{ .ResponseType }} { - core.Paginate paginate = 1; - {{ .Model }} {{ ToSnake (TrimPrefix .Model "Model") }} = 2; + core.Paginate paginate = 1; + repeated {{ .Model }} list = 2; } diff --git a/codegen/template/proto/rpc_service.gtpl b/codegen/template/proto/rpc_service.gtpl index 9f3d111..7833855 100644 --- a/codegen/template/proto/rpc_service.gtpl +++ b/codegen/template/proto/rpc_service.gtpl @@ -1,8 +1,10 @@ -{{ with .Role }} - // @role: {{ $.Role }} {{end}}{{ with .Url }} +{{ with .Url }} // @url: {{ $.Url }} {{end}}{{ with .GenTo }} // @gen: {{ $.GenTo }} {{end}}{{ with .Model }} // @model: {{ $.Model }} {{end}}{{ with .Action }} // @action: {{ $.Action }} {{end}} rpc {{ .RpcName }} ({{ .RequestType }}) returns ({{ .ResponseType }}) { + option (core.lazygen) = { {{ with .Role }} + role: "{{ $.Role }}",{{ end }} + }; }; diff --git a/codegen/template/proto/update.req.rpc.gtpl b/codegen/template/proto/update.req.rpc.gtpl index c47b9d8..d37bfec 100644 --- a/codegen/template/proto/update.req.rpc.gtpl +++ b/codegen/template/proto/update.req.rpc.gtpl @@ -1,4 +1,4 @@ message {{ .RequestType }} { -{{with .PprimaryKey }} // @validate: required - {{ $.PprimaryKeyType}} {{ $.PprimaryKey }} = 1;{{end}} +{{with .PrimaryKey }} // @validate: required + {{ $.PrimaryKeyType}} {{ $.PrimaryKey }} = 1;{{end}} } diff --git a/codegen/template/state/cache.gtpl b/codegen/template/state/cache.gtpl index dbafeaf..b115772 100644 --- a/codegen/template/state/cache.gtpl +++ b/codegen/template/state/cache.gtpl @@ -2,7 +2,7 @@ package state import ( "github.com/lazygophers/log" - "github.com/lazygophers/utils/cache" + "github.com/lazygophers/lrpc/middleware/cache" ) var ( diff --git a/codegen/template/state/table.gtpl b/codegen/template/state/table.gtpl index fb1322a..55aa3b9 100644 --- a/codegen/template/state/table.gtpl +++ b/codegen/template/state/table.gtpl @@ -1,10 +1,10 @@ package state import ( - {{ .PB.GoPackage }} + "{{ .PB.GoPackage }}" "github.com/lazygophers/log" "github.com/lazygophers/lrpc/middleware/xerror" - "github.com/lazygophers/utils/db" + "github.com/lazygophers/lrpc/middleware/db" ) var ( diff --git a/example.codegen.cfg.yaml b/example.codegen.cfg.yaml index bb4d31d..3e6a6c1 100644 --- a/example.codegen.cfg.yaml +++ b/example.codegen.cfg.yaml @@ -9,7 +9,7 @@ go_module_prefix: " 的模板文件路径" + # rpc 相关的 + action: + # key → action value → 模版文件路径 + add: "创建数据的模板路径" + set: "修改数据的模板路径" + update: "更新数据的模板路径" + del: "删除数据的模板路径" + list: "列表数据的模板路径" + "": "默认的模版路径" + # state/table.go 模板文件路径 table: "" # state/conf.go 模板文件路径 diff --git a/state/config.go b/state/config.go index 380444f..faf133d 100644 --- a/state/config.go +++ b/state/config.go @@ -21,16 +21,22 @@ type CfgStyle struct { Go string `json:"go,omitempty" yaml:"go,omitempty" toml:"go,omitempty" default:"fiber"` } -type CfgProtoRpc struct { +type CfgProtoAction struct { Name string `json:"name,omitempty" yaml:"name,omitempty" toml:"name,omitempty"` Req string `json:"req,omitempty" yaml:"req,omitempty" toml:"req,omitempty"` Resp string `json:"resp,omitempty" yaml:"resp,omitempty" toml:"resp,omitempty"` } type CfgProto struct { - Rpc map[string]*CfgProtoRpc `json:"rpc,omitempty" yaml:"rpc,omitempty" toml:"rpc,omitempty"` + Action map[string]*CfgProtoAction `json:"action,omitempty" yaml:"action,omitempty" toml:"action,omitempty"` - Service string `json:"service,omitempty" yaml:"service,omitempty" toml:"service,omitempty"` + Rpc string `json:"rpc,omitempty" yaml:"rpc,omitempty" toml:"rpc,omitempty"` +} + +type CfgImpl struct { + Action map[string]string `json:"action,omitempty" yaml:"action,omitempty" toml:"action,omitempty"` + + Impl string `json:"impl,omitempty" yaml:"impl,omitempty" toml:"impl,omitempty"` } type CfgTemplate struct { @@ -41,6 +47,7 @@ type CfgTemplate struct { TableField string `json:"table_field,omitempty" yaml:"table_field,omitempty" toml:"table_field,omitempty"` Proto *CfgProto `json:"proto,omitempty" yaml:"proto,omitempty" toml:"proto,omitempty"` + Impl *CfgImpl `json:"impl,omitempty" yaml:"impl,omitempty" toml:"impl,omitempty"` Table string `json:"table,omitempty" yaml:"table,omitempty" toml:"table,omitempty"` Conf string `json:"conf,omitempty" yaml:"conf,omitempty" toml:"conf,omitempty"` @@ -127,8 +134,14 @@ func (p *Cfg) apply() (err error) { if p.Template.Proto == nil { p.Template.Proto = new(CfgProto) } - if len(p.Template.Proto.Rpc) == 0 { - p.Template.Proto.Rpc = make(map[string]*CfgProtoRpc) + if len(p.Template.Proto.Action) == 0 { + p.Template.Proto.Action = make(map[string]*CfgProtoAction) + } + if p.Template.Impl == nil { + p.Template.Impl = new(CfgImpl) + } + if len(p.Template.Impl.Action) == 0 { + p.Template.Impl.Action = make(map[string]string) } if p.Tables == nil {