Skip to content

Commit

Permalink
Merge pull request #31 from lazygophers/luoxin
Browse files Browse the repository at this point in the history
客户端代码生成
  • Loading branch information
Luoxin authored Jun 20, 2024
2 parents 4ac66a6 + d72f800 commit 5995842
Show file tree
Hide file tree
Showing 17 changed files with 219 additions and 15 deletions.
12 changes: 4 additions & 8 deletions .goreleaser.yaml
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
project_name: codegen

version: 2
env:
- GO111MODULE=on
- GOSUMDB=off
- CGO_ENABLED=0
before:
hooks:
- go mod tidy

#gomod:
# proxy: true
# mod: mod
gomod:
proxy: true
mod: mod

builds:
- id: cli
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

帮助文档:https://lazygophers.pages.dev/

模板仓库:https://github.com/lazygophers/template

## 生成样例

首先,需要创建一个文件夹存放 `proto` 文件,假设文件夹名为 `proto`,并且在 `proto` 文件夹下存在一个 `hello.proto` 文件,内容如下
Expand Down
6 changes: 6 additions & 0 deletions cli/gen/gen_impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ var runGenImpl = func(cmd *cobra.Command, args []string) (err error) {
return err
}

err = codegen.GenerateClient(pb)
if err != nil {
log.Errorf("err:%v", err)
return err
}

return nil
}

Expand Down
5 changes: 5 additions & 0 deletions cli/gen/upmod.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package gen

import (
"errors"
"github.com/lazygophers/codegen/cli/utils"
"github.com/lazygophers/codegen/codegen"
"github.com/lazygophers/codegen/state"
"github.com/lazygophers/log"
Expand Down Expand Up @@ -66,6 +67,10 @@ var upModCmd = &cobra.Command{
state.LazyConfig.Apply()
}

if cmd.Flag("goproxy").Value.String() != "" {
state.LazyConfig.GoMod.Goproxy = utils.GetString("goproxy", cmd)
}

err = codegen.UpdateGoMod(filepath.Join(projectDir, "go.mod"))
if err != nil {
log.Errorf("err:%v", err)
Expand Down
8 changes: 8 additions & 0 deletions cli/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,14 @@ var syncCmd = &cobra.Command{
// 存储到当前目录下的文件(按照文件名 hash)
fileName := filepath.Join(runtime.UserConfigDir(), app.Organization, "codegen", cryptox.Md5(c.Sync.Remote), "codegen.cfg.yaml")

Check failure on line 187 in cli/sync.go

View workflow job for this annotation

GitHub Actions / lint

cannot infer M (/home/runner/go/pkg/mod/github.com/lazygophers/[email protected]/cryptox/hash.go:12:10) (typecheck)

if !osx.IsDir(filepath.Dir(fileName)) {
err = os.MkdirAll(filepath.Dir(fileName), 0777)
if err != nil {
log.Errorf("err:%v", err)
return err
}
}

file, err := os.OpenFile(fileName, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0666)
if err != nil {
log.Errorf("err:%v", err)
Expand Down
152 changes: 152 additions & 0 deletions codegen/generate_impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -440,3 +440,155 @@ func GenerateImplRpcRoute(pb *PbPackage) (err error) {

return nil
}

func generateImplClient(pb *PbPackage, rpc *PbRPC) (err error) {
pterm.Info.Printfln("try generate impl client %s", rpc.Name)

args := map[string]any{
"PB": pb,
"RpcName": rpc.Name,
"RequestType": rpc.rpc.RequestType,
"ResponseType": rpc.rpc.ReturnsType,
"RPC": pbRpc2Route(rpc),
}

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(TemplateTypeImplClientCall, rpc.genOption.Action)
if err != nil {
log.Errorf("err:%v", err)
return err
}

file, err := os.OpenFile(GetPath(PathTypeImplClient, pb), 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.WriteString("\n")
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 initImplClient(pb *PbPackage) error {
if osx.IsFile(GetPath(PathTypeImplClient, pb)) {
return nil
}

tpl, err := GetTemplate(TemplateTypeImplClient)
if err != nil {
log.Errorf("err:%v", err)
return err
}

file, err := os.OpenFile(GetPath(PathTypeImplClient, pb), 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]any{
"PB": pb,
})
if err != nil {
log.Errorf("err:%v", err)
return err
}

return nil
}

func GenerateClient(pb *PbPackage) (err error) {
pterm.Info.Printfln("Generating impl client...")

err = initImplDirectory(pb)
if err != nil {
log.Errorf("err:%v", err)
return err
}

goPackage, err := ParseGoDir(filepath.Dir(GetPath(PathTypeImplClient, pb)))
if err != nil {
log.Errorf("err:%v", err)
return err
}

if len(goPackage) == 0 {
goPackage = make(map[string]*GoPackage)
}

if goPackage[pb.GoPackageName()] == nil {
goPackage[pb.GoPackageName()] = &GoPackage{}
}

if len(goPackage[pb.GoPackageName()].FuncMap) == 0 {
goPackage[pb.GoPackageName()].FuncMap = make(map[string]*GoFuncNode)
}

matchFunc := func(rpc *PbRPC) bool {
for _, goFuncNode := range goPackage[pb.GoPackageName()].FuncMap {
goFunc := goFuncNode.goFunc

if goFunc.RecvType != "" {
continue
}

if goFunc.Name == rpc.Name {
pterm.Warning.Printfln("%s is exist, skip generate", rpc.Name)
return true
}
}

return false
}

for _, rpc := range pb.RPCs() {
//path := filepath.Join(GetPath(PathTypeImpl, pb), rpc.genOption.GenTo+".go")

if matchFunc(rpc) {
continue
}

err = generateImplClient(pb, rpc)
if err != nil {
log.Errorf("err:%v", err)
return err
}
}

return nil
}
4 changes: 4 additions & 0 deletions codegen/path.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const (
PathTypeImpl
PathTypeImplPath
PathTypeImplRoute
PathTypeImplClient

PathTypeCmd
PathTypeCmdMain
Expand Down Expand Up @@ -94,6 +95,9 @@ func GetPath(t PathType, pb *PbPackage) string {
case PathTypeImplRoute:
return filepath.Join(GetPath(PathTypeCmd, pb), "route.gen.go")

case PathTypeImplClient:
return filepath.Join(pb.ProjectRoot(), "client.go")

case PathTypeCmd:
return filepath.Join(pb.ProjectRoot(), "cmd")

Expand Down
2 changes: 1 addition & 1 deletion codegen/pbparse.go
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ func NewPbRPC(rpc *proto.RPC) *PbRPC {
options: make(map[string]map[string]string, len(rpc.Options)),
genOption: &PbRpcGenOptions{
Method: "POST",
Path: rpc.Name,
Path: "/" + rpc.Name,
},
}
p.walk()
Expand Down
10 changes: 10 additions & 0 deletions codegen/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ const (
TemplateTypeImplAction
TemplateTypeImplPath
TemplateTypeImplRoute
TemplateTypeImplClient
TemplateTypeImplClientCall

TemplateTypeGoreleaser
TemplateTypeMakefile
Expand Down Expand Up @@ -151,6 +153,14 @@ func GetTemplate(t TemplateType, args ...string) (tpl *template.Template, err er
systemPath = state.Config.Template.Impl.Route
embedPath = "template/rpc_route.gtpl"

case TemplateTypeImplClient:
systemPath = state.Config.Template.Impl.Client
embedPath = "template/client.gtpl"

case TemplateTypeImplClientCall:
systemPath = state.Config.Template.Impl.ClientCall
embedPath = "template/client.call.gtpl"

case TemplateTypeCmd:
systemPath = state.Config.Template.Main
embedPath = "template/cmd.gtpl"
Expand Down
7 changes: 7 additions & 0 deletions codegen/template/client.call.gtpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
func {{ .RPC.RpcName }}(ctx *lrpc.Ctx, req *{{ .RequestType }}) (*{{ .ResponseType }}, error) {
var rsp {{ .ResponseType }}
return &rsp, lrpc.Call(ctx, &core.ServiceDiscoveryClient{
ServiceName: ServerName,
ServicePath: RpcPath{{ .RPC.RpcName }},
}, req, &rsp)
}
1 change: 1 addition & 0 deletions codegen/template/client.gtpl
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package lmq
2 changes: 1 addition & 1 deletion codegen/template/goreleaser.gtpl
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ builds:
- -X github.com/lazygophers/utils/app.Version={{ Self ".Version" }}
- -X github.com/lazygophers/utils/app.Tag={{ Self ".Tag" }}
- -X github.com/lazygophers/utils/app.BuildDate={{ Self ".Date" }}
- -X github.com/lazygophers/utils/app.GoVersion={{ .EnvSelf ".GOVERSION" }}
- -X github.com/lazygophers/utils/app.GoVersion={{ .EnvSelf ".Env.GOVERSION" }}
- -X github.com/lazygophers/utils/app.GoOS={{ Self ".Os" }}
- -X github.com/lazygophers/utils/app.Goarch={{ Self ".Arch" }}
- -X github.com/lazygophers/utils/app.Goarm={{ Self ".Arm" }}
Expand Down
3 changes: 2 additions & 1 deletion codegen/template/orm.gtpl
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package {{ .PB.GoPackageName }}

{{ if gt (len .Models) 0 }}
import (
"database/sql/driver"
"github.com/lazygophers/utils"
)
){{ end }}

{{ range $key, $value := .Models }}func (m *{{ $value }}) Scan(value interface{}) error {
return utils.Scan(m, value)
Expand Down
4 changes: 4 additions & 0 deletions codegen/template/rpc_path.gtpl
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package {{ .PB.GoPackageName }}

const (
ServerName = "{{ .PB.GoPackageName }}"
)

const ({{ range $key, $value := .RPCS }}
RpcPath{{ $value.RpcName }} = "{{ $value.Path }}"{{ end }}
)
6 changes: 6 additions & 0 deletions example.codegen.cfg.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,12 @@ template:
# 路由相关的配置
route: "<rpc-route.go> 的模板文件路径"

# 客户模板文件
client: "<client.go> 的模板文件"

# 调用函数的模板
client_call: "调用函数的模板文件"

# rpc 相关的
action:
# key → action value → 模版文件路径
Expand Down
8 changes: 5 additions & 3 deletions state/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,9 +137,11 @@ type CfgProto struct {
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"`
Path string `json:"path,omitempty" yaml:"path,omitempty" toml:"path,omitempty"`
Route string `json:"route,omitempty" yaml:"route,omitempty" toml:"route,omitempty"`
Impl string `json:"impl,omitempty" yaml:"impl,omitempty" toml:"impl,omitempty"`
Path string `json:"path,omitempty" yaml:"path,omitempty" toml:"path,omitempty"`
Route string `json:"route,omitempty" yaml:"route,omitempty" toml:"route,omitempty"`
Client string `json:"client,omitempty" yaml:"client,omitempty" toml:"client,omitempty"`
ClientCall string `json:"client_call,omitempty" yaml:"client_call,omitempty" toml:"client_call,omitempty"`
}

type CfgTemplateState struct {
Expand Down
2 changes: 1 addition & 1 deletion state/i18n.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,5 @@ func Localize(key string, args ...interface{}) string {
}

func LocalizeWithLanguage(lang string, key string, args ...interface{}) string {
return I18n.LocalizeWithLanguage(lang, key, args...)
return I18n.LocalizeWithLang(lang, key, args...)

Check failure on line 62 in state/i18n.go

View workflow job for this annotation

GitHub Actions / lint

I18n.LocalizeWithLang undefined (type *i18n.I18n has no field or method LocalizeWithLang)) (typecheck)

Check failure on line 62 in state/i18n.go

View workflow job for this annotation

GitHub Actions / lint

I18n.LocalizeWithLang undefined (type *i18n.I18n has no field or method LocalizeWithLang)) (typecheck)

Check failure on line 62 in state/i18n.go

View workflow job for this annotation

GitHub Actions / lint

I18n.LocalizeWithLang undefined (type *i18n.I18n has no field or method LocalizeWithLang)) (typecheck)
}

0 comments on commit 5995842

Please sign in to comment.