add code generate code

This commit is contained in:
Yavolte 2025-06-10 16:07:15 +08:00
parent a694e40b13
commit 0997b9c520
5 changed files with 384 additions and 1 deletions

2
.gitignore vendored
View File

@ -1,5 +1,5 @@
bin/ bin/
tests/
.svn/ .svn/
.godeps .godeps
./build ./build

View File

@ -0,0 +1,113 @@
package generator
import (
"bytes"
"embed"
"html/template"
"io"
"io/fs"
"os"
"path"
"time"
"git.nobla.cn/golang/aeus/tools/gen/internal/types"
)
var (
fileMap = map[string]string{
"cmd/main.go": MainTemp,
"internal/scope/scope.go": ScopeTemp,
"internal/service/service.go": ServiceLoaderTemp,
"api/v1/pb/greeter.proto": GreeterTemp,
"version/version.go": VersionTemp,
"Makefile": MakefileTemp,
".gitignore": GitIgnoreTemp,
"README.md": ReadmeTemp,
"go.mod": GoModTemp,
}
)
var (
//go:embed third_party
protoDir embed.FS
)
type (
TemplateData struct {
ShortName string
PackageName string
Datetime string
Version string
}
)
func writeFile(file string, buf []byte) (err error) {
dirname := path.Dir(file)
if _, err = os.Stat(dirname); err != nil {
if err = os.MkdirAll(dirname, 0755); err != nil {
return
}
}
err = os.WriteFile(file, buf, 0644)
return
}
func scanDir(s embed.FS, dirname string, callback func(file string) error) (err error) {
var (
entities []fs.DirEntry
)
if entities, err = s.ReadDir(dirname); err != nil {
return nil
}
for _, entity := range entities {
if entity.Name() == "." || entity.Name() == ".." {
continue
}
name := path.Join(dirname, entity.Name())
if entity.IsDir() {
scanDir(s, name, callback)
} else {
if err = callback(name); err != nil {
break
}
}
}
return
}
func Geerate(app *types.Applicetion) (err error) {
shortName := app.ShortName()
data := TemplateData{
ShortName: shortName,
PackageName: app.Package,
Version: "v0.0.1",
Datetime: time.Now().Format(time.DateTime),
}
var t *template.Template
writer := bytes.NewBuffer(nil)
for name, tmpl := range fileMap {
if t, err = template.New(name).Parse(tmpl); err != nil {
return
}
if err = t.Execute(writer, data); err != nil {
return
}
if err = writeFile(path.Join(shortName, name), writer.Bytes()); err != nil {
return
}
writer.Reset()
}
err = scanDir(protoDir, "third_party", func(filename string) error {
if fp, openerr := protoDir.Open(filename); openerr != nil {
return openerr
} else {
if buf, readerr := io.ReadAll(fp); readerr == nil {
writeFile(path.Join(shortName, filename), buf)
}
fp.Close()
}
return nil
})
return
}

View File

@ -0,0 +1,230 @@
package generator
var (
MainTemp = `
package main
import (
"fmt"
"os"
"flag"
"git.nobla.cn/golang/aeus"
"git.nobla.cn/golang/aeus/transport/cli"
"git.nobla.cn/golang/aeus/transport/grpc"
"git.nobla.cn/golang/aeus/transport/http"
"{{.PackageName}}/version"
"{{.PackageName}}/internal/scope"
"{{.PackageName}}/internal/service"
)
var (
versionFlag = flag.Bool("version", false, "Show version")
)
func main() {
var (
err error
)
flag.Parse()
if *versionFlag{
fmt.Println(version.Info())
os.Exit(0)
}
app := aeus.New(
aeus.WithName("{{.ShortName}}"),
aeus.WithVersion("{{.Version}}"),
aeus.WithServer(
http.New(),
grpc.New(),
cli.New(),
),
aeus.WithScope(scope.NewScope()),
aeus.WithServiceLoader(service.NewLoader()),
)
if err = app.Run(); err != nil {
fmt.Println("app run error:", err)
os.Exit(1)
}
}
`
ScopeTemp = `
package scope
import (
"context"
"git.nobla.cn/golang/aeus/transport/cli"
"git.nobla.cn/golang/aeus/transport/grpc"
"git.nobla.cn/golang/aeus/transport/http"
)
type ScopeContext struct {
ctx context.Context
Http *http.Server
Grpc *grpc.Server
Cli *cli.Server
}
func (s *ScopeContext) Init(ctx context.Context) (err error) {
s.ctx = ctx
return
}
func NewScope() *ScopeContext {
return &ScopeContext{}
}
`
ServiceLoaderTemp = `
package service
import (
"context"
"{{.PackageName}}/internal/scope"
"git.nobla.cn/golang/aeus/transport/cli"
"git.nobla.cn/golang/aeus/transport/grpc"
"git.nobla.cn/golang/aeus/transport/http"
)
type serviceLoader struct {
Sope *scope.ScopeContext
Http *http.Server
Grpc *grpc.Server
Cli *cli.Server
}
func (s *serviceLoader) Init(ctx context.Context) (err error) {
// bind services here
return
}
func (s *serviceLoader) Run(ctx context.Context) (err error) {
return
}
func NewLoader() *serviceLoader {
return &serviceLoader{}
}
`
MakefileTemp = `
GOHOSTOS:=$(shell go env GOHOSTOS)
GOPATH:=$(shell go env GOPATH)
VERSION=$(shell git describe --tags --always)
DATETIME:=$(shell date "+%Y-%m-%d %H:%M:%S")
PROTO_DIR="api/v1/pb"
PROTO_OUT_DIR="api/v1/pb"
PROTO_FILES=$(shell find api -name *.proto)
.PHONY: proto
proto:
protoc --proto_path=$(PROTO_DIR) \
--proto_path=./third_party \
--go_out=paths=source_relative:$(PROTO_OUT_DIR) \
--go-grpc_out=paths=source_relative:$(PROTO_OUT_DIR) \
--go-aeus_out=paths=source_relative:$(PROTO_OUT_DIR) \
--validate_out=paths=source_relative,lang=go:$(PROTO_OUT_DIR) \
$(PROTO_FILES)
.PHONY: proto-clean
proto-clean:
rm -rf $(PROTO_OUT_DIR)/*.pb.go
rm -rf $(PROTO_OUT_DIR)/*.pb.validate.go
.PHONY: build
build:
go mod tidy
go mod vendor
go build -ldflags "-s -w -X '{{.PackageName}}/version.Version=$(VERSION)' -X '{{.PackageName}}/version.BuildDate=$(DATETIME)'" -o bin/{{.ShortName}} cmd/main.go
`
GreeterTemp = `
syntax = "proto3";
package greeter;
import "google/api/annotations.proto";
import "aeus/command.proto";
import "aeus/rest.proto";
import "validate/validate.proto";
option go_package = "{{.PackageName}}/api/v1/pb;pb";
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {
option (google.api.http) = {
get: "/helloworld/{name}"
};
option (aeus.command) = {
path: "/helloworld/:name",
description: "Greeter"
};
}
}
// The request message containing the user's name.
message HelloRequest {
option (aeus.rest) = {
table: "users"
};
int64 id = 1 [(aeus.field)={gorm:"primary_key"},(validate.rules).int64.gt = 999];
string name = 2;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
`
VersionTemp = `
package version
import "fmt"
var (
Version = "{{.Version}}"
BuildDate = "{{.Datetime}}"
ProductName = "{{.ShortName}}"
)
func Info() string {
return fmt.Sprintf("%s version: %s (built at %s)", ProductName, Version, BuildDate)
}
`
GitIgnoreTemp = `
.vscode
.idea
bin/
.svn/
.godeps
./build
.cover/
*.dat
vendor
*.o
*.a
*.so
# Folders
_obj
_test
`
ReadmeTemp = ``
GoModTemp = `
module {{.PackageName}}
go 1.23.0
`
)

View File

@ -0,0 +1,15 @@
package types
import "strings"
type Applicetion struct {
Package string
}
func (app *Applicetion) ShortName() string {
pos := strings.LastIndex(app.Package, "/")
if pos > -1 {
return app.Package[pos+1:]
}
return app.Package
}

25
tools/gen/main.go 100644
View File

@ -0,0 +1,25 @@
package main
import (
"flag"
"fmt"
"os"
"git.nobla.cn/golang/aeus/tools/gen/internal/generator"
"git.nobla.cn/golang/aeus/tools/gen/internal/types"
)
var (
packageFlag = flag.String("package", "", "package name")
)
func main() {
flag.Parse()
app := &types.Applicetion{
Package: *packageFlag,
}
if err := generator.Geerate(app); err != nil {
fmt.Println(err)
os.Exit(1)
}
}