feat: api

This commit is contained in:
Young Xu 2023-03-21 01:08:22 +08:00
commit 696184f41a
Signed by: xuthus5
GPG Key ID: A23CF9620CBB55F9
6 changed files with 249 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
.idea
go.sum

70
example.proto Normal file
View File

@ -0,0 +1,70 @@
syntax = "proto3";
package controller;
option go_package = "./;core";
// @route_group: true
// @route_api: /api/file
// @gen_to: ./core/file_controller.go
service File {
// @desc:
// @author: Young Xu
// @method: GET
// @api: /list
rpc List (ListReq) returns (ListResp);
// @desc:
// @author: Young Xu
// @method: POST
// @api: /upload
rpc Upload (UploadReq) returns (UploadResp);
// @desc:
// @author: Young Xu
// @method: POST
// @api: /delete
rpc Delete (DeleteReq) returns (DeleteResp);
// @desc:
// @author: Young Xu
// @method: GET
// @api: /download
rpc Download (DownloadReq) returns (DownloadResp);
// @desc:
// @author:
// @method:
// @api: /update_user_info
rpc UpdateUserInfo (UpdateUserInfoReq) returns (UpdateUserInfoResp);
}
message ListReq {}
message ListResp {
message Item {
string filename = 1; //
string file_size = 2; //
string created_at = 3; //
}
repeated Item items = 1; //
}
message UploadReq {}
message UploadResp {}
message DeleteReq {
string filename = 1; //
}
message DeleteResp {}
message DownloadReq {
// @v: required
string f = 1; //
}
message DownloadResp {}
message UpdateUserInfoReq {}
message UpdateUserInfoResp {}

15
go.mod Normal file
View File

@ -0,0 +1,15 @@
module gitter.top/coco/gobuf
go 1.18
require (
github.com/emicklei/proto v1.11.1
github.com/stretchr/testify v1.8.2
)
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
gitter.top/sync/proto-contrib v0.15.0
gopkg.in/yaml.v3 v3.0.1 // indirect
)

118
gobuf.go Normal file
View File

@ -0,0 +1,118 @@
package gobuf
import (
"bytes"
"github.com/emicklei/proto"
"gitter.top/sync/proto-contrib/pkg/protofmt"
"io"
"os"
)
type Parser struct {
filename string
rawData io.Reader
proto *proto.Proto
}
func NewParser(file string) (*Parser, error) {
reader, err := os.Open(file)
if err != nil {
return nil, err
}
defer reader.Close()
parser := proto.NewParser(reader)
definition, err := parser.Parse()
if err != nil {
return nil, err
}
return &Parser{
filename: file,
rawData: reader,
proto: definition,
}, nil
}
func (parser *Parser) ExistService(serviceName string) bool {
var result bool
proto.Walk(parser.proto, proto.WithService(func(service *proto.Service) {
if service.Name == serviceName {
result = true
}
}))
return result
}
func (parser *Parser) ExistMessage(messageName string) bool {
var result bool
proto.Walk(parser.proto, proto.WithMessage(func(message *proto.Message) {
if message.Name == messageName {
result = true
}
}))
return result
}
func (parser *Parser) ExistRPC(serviceName, rpcName string) bool {
var result bool
proto.Walk(parser.proto, proto.WithService(func(service *proto.Service) {
if service.Name != serviceName {
return
}
for _, element := range service.Elements {
if rpc, ok := element.(*proto.RPC); ok {
if rpc.Name == rpcName {
result = true
return
}
}
}
}))
return result
}
func (parser *Parser) AddRPC(serviceName, rpcName string) error {
proto.Walk(parser.proto, proto.WithService(func(service *proto.Service) {
if service.Name != serviceName {
return
}
service.Elements = append(service.Elements, &proto.RPC{
Comment: &proto.Comment{
Lines: []string{
" @desc: ",
" @author: ",
" @method: ",
" @api: /" + calm2Case(rpcName),
},
},
Name: rpcName,
RequestType: rpcName + "Req",
ReturnsType: rpcName + "Resp",
Parent: service,
})
}))
parser.proto.Elements = append(parser.proto.Elements, &proto.Message{
Name: rpcName + "Req",
Parent: parser.proto,
})
parser.proto.Elements = append(parser.proto.Elements, &proto.Message{
Name: rpcName + "Resp",
Parent: parser.proto,
})
return parser.writeSync()
}
func (parser *Parser) writeSync() error {
var buf = new(bytes.Buffer)
protofmt.NewFormatter(buf, " ").Format(parser.proto) // 1 tab
// write back to input
if err := os.WriteFile(parser.filename, buf.Bytes(), os.ModePerm); err != nil {
return err
}
return nil
}

22
gobuf_test.go Normal file
View File

@ -0,0 +1,22 @@
package gobuf
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestParser_AddRPC(t *testing.T) {
parser, err := NewParser("example.proto")
assert.Nil(t, err)
existService := parser.ExistService("File")
assert.EqualValues(t, true, existService)
existRPC := parser.ExistRPC("File", "List")
assert.EqualValues(t, true, existRPC)
existRPC = parser.ExistRPC("File", "List1")
assert.EqualValues(t, false, existRPC)
existMsg := parser.ExistMessage("DeleteReq")
assert.EqualValues(t, true, existMsg)
err = parser.AddRPC("File", "UpdateUserInfo")
assert.Nil(t, err)
}

22
utils.go Normal file
View File

@ -0,0 +1,22 @@
package gobuf
import (
"bytes"
"unicode"
)
// calm2Case 驼峰转下划线
func calm2Case(src string) string {
buffer := new(bytes.Buffer)
for i, r := range src {
if unicode.IsUpper(r) {
if i != 0 {
buffer.WriteRune('_')
}
buffer.WriteRune(unicode.ToLower(r))
} else {
buffer.WriteRune(r)
}
}
return buffer.String()
}