master
李伟乐 2 years ago
parent 556b089a60
commit 15d412e903
  1. 53
      cmd/kit/main.go
  2. 62
      cmd/ts/main.go
  3. 33
      pkg/protogen/protogen.go
  4. BIN
      proto/main
  5. 2
      proto/user.proto
  6. 54
      proto/v1/http.ts
  7. 19
      proto/v1/user.ts
  8. 4
      proto/v1/user_grpc.pb.go

@ -1,14 +1,10 @@
package main package main
import ( import (
"github.com/golang/protobuf/proto" protogen2 "git.diulo.com/mogfee/protoc-gen-kit/pkg/protogen"
"google.golang.org/genproto/googleapis/api/annotations"
"google.golang.org/protobuf/compiler/protogen" "google.golang.org/protobuf/compiler/protogen"
"google.golang.org/protobuf/types/descriptorpb"
) )
// go build && protoc --unknow_out=./proto --go_out=./proto/ --go-grpc_out=./proto proto/user.proto -I ./proto
// protoc --unknow_out=./proto proto/user.proto
func main() { func main() {
u := &Kit{ u := &Kit{
imports: map[string]string{}, imports: map[string]string{},
@ -49,7 +45,7 @@ func (u *Kit) Generate(plugin *protogen.Plugin) error {
serverName := s.GoName serverName := s.GoName
t.P(`func Register`, serverName, `Handler(app *gin.Engine,srv `, serverName, `Server,m ...middleware.Middleware) {`) t.P(`func Register`, serverName, `Handler(app *gin.Engine,srv `, serverName, `Server,m ...middleware.Middleware) {`)
for _, m := range s.Methods { for _, m := range s.Methods {
method, path := u.getMethod(m) method, path := protogen2.GetProtoMethod(m)
if method == "" { if method == "" {
continue continue
} }
@ -60,16 +56,16 @@ func (u *Kit) Generate(plugin *protogen.Plugin) error {
for _, s := range f.Services { for _, s := range f.Services {
serverName := s.GoName serverName := s.GoName
for _, m := range s.Methods { for _, m := range s.Methods {
method, _ := u.getMethod(m) method, _ := protogen2.GetProtoMethod(m)
if method == "" { if method == "" {
continue continue
} }
switch method { switch method {
case method_get: case protogen2.METHOD_GET:
u.genGet(serverName, t, m) u.genGet(serverName, t, m)
case method_post: case protogen2.METHOD_POST:
u.genPost(serverName, t, m) u.genPost(serverName, t, m)
case method_delete: case protogen2.METHOD_DELETE:
u.genDelete(serverName, t, m) u.genDelete(serverName, t, m)
} }
@ -154,40 +150,3 @@ func (u *Kit) genDelete(serverName string, t *protogen.GeneratedFile, m *protoge
}`) }`)
t.P("}") t.P("}")
} }
// func (Kit) getAuth(m *protogen.Method) *auth.AuthInfo {
// if op, ok := m.Desc.Options().(*descriptorpb.MethodOptions); ok {
// if opts, err := proto.GetExtension(op, auth.E_Auth); err != nil {
// log.Println(err)
// } else {
// if vv, ok := opts.(*auth.AuthInfo); ok {
// return vv
// }
// }
// }
// return &auth.AuthInfo{}
// }
func (Kit) getMethod(m *protogen.Method) (method string, path string) {
if op, ok := m.Desc.Options().(*descriptorpb.MethodOptions); ok {
if opts, err := proto.GetExtension(op, annotations.E_Http); err != nil {
//log.Println(err)
} else {
if vv, ok := opts.(*annotations.HttpRule); ok {
if vvv, ok := vv.Pattern.(*annotations.HttpRule_Get); ok {
return method_get, vvv.Get
} else if vvv, ok := vv.Pattern.(*annotations.HttpRule_Post); ok {
return method_post, vvv.Post
} else if vvv, ok := vv.Pattern.(*annotations.HttpRule_Delete); ok {
return method_delete, vvv.Delete
}
}
}
}
return "", ""
}
const (
method_get = "GET"
method_post = "POST"
method_delete = "DELETE"
)

@ -2,34 +2,31 @@ package main
import ( import (
"fmt" "fmt"
protogen2 "git.diulo.com/mogfee/protoc-gen-kit/pkg/protogen"
"google.golang.org/protobuf/compiler/protogen" "google.golang.org/protobuf/compiler/protogen"
"strings" "strings"
) )
func main() { func main() {
u := &Kit{ u := &Kit{}
imports: map[string]string{},
}
protogen.Options{}.Run(u.Generate) protogen.Options{}.Run(u.Generate)
} }
type Kit struct { type Kit struct {
imports map[string]string
} }
func (u *Kit) addImports(imp string) {
u.imports[imp] = imp
}
func (u *Kit) Generate(plugin *protogen.Plugin) error { func (u *Kit) Generate(plugin *protogen.Plugin) error {
if len(plugin.Files) < 1 { if len(plugin.Files) < 1 {
return nil return nil
} }
for _, f := range plugin.Files { for _, f := range plugin.Files {
if len(f.Services) == 0 { if len(f.Services) == 0 {
continue continue
} }
fname := f.GeneratedFilenamePrefix + ".ts" fname := f.GeneratedFilenamePrefix + ".ts"
t := plugin.NewGeneratedFile(fname, f.GoImportPath) t := plugin.NewGeneratedFile(fname, f.GoImportPath)
t.P(`import {Config,http} from "./http";`)
for _, s := range f.Messages { for _, s := range f.Messages {
t.P(`export interface `, s.Desc.Name(), ` {`) t.P(`export interface `, s.Desc.Name(), ` {`)
for _, vv := range s.Fields { for _, vv := range s.Fields {
@ -43,52 +40,49 @@ func (u *Kit) Generate(plugin *protogen.Plugin) error {
fields := vv.Desc.Message().Fields() fields := vv.Desc.Message().Fields()
typ = append(typ, fmt.Sprintf(`{ [key: %s]: %s }`, getType(fields.Get(0).Kind().String()), getType(fields.Get(1).Kind().String()))) typ = append(typ, fmt.Sprintf(`{ [key: %s]: %s }`, getType(fields.Get(0).Kind().String()), getType(fields.Get(1).Kind().String())))
} else if vv.Desc.Kind().String() == "message" { } else if vv.Desc.Kind().String() == "message" {
//t.P(vv.Desc.Message().Fields())
//t.P(vv.Desc.Message().Name())
//if vv.Desc.Message().Fields().Get(0).Name() == "value" {
// isRequired = "?:"
// //typ = append(typ, getType(vv.Desc.Message().Fields().Get(0).Kind().String()))
//} else {
fullName := fmt.Sprintf("%v", vv.Desc.Message().FullName()) fullName := fmt.Sprintf("%v", vv.Desc.Message().FullName())
if strings.HasPrefix(fullName, "google.protobuf") && strings.HasSuffix(fullName, "Value") { if strings.HasPrefix(fullName, "google.protobuf") && strings.HasSuffix(fullName, "Value") {
isRequired = "?:" isRequired = "?:"
} }
typ = append(typ, getType(fmt.Sprintf("%v", vv.Desc.Message().Name()))) typ = append(typ, getType(fmt.Sprintf("%v", vv.Desc.Message().Name())))
//}
} else { } else {
typ = append(typ, getType(vv.Desc.Kind().String())) typ = append(typ, getType(vv.Desc.Kind().String()))
} }
//vtype := fmt.Sprintf("%v", vv.Desc.Kind())
//if vtype == "bytes" {
// typ = append(typ, "Uint8Array")
//} else if vtype == "message" {
// if vv.Desc.IsMap() {
// typ = append(typ, fmt.Sprintf(`{ [key: %s]: %s }`, fields.Get(0).Kind().String(), fields.Get(1).Kind().String()))
// } else {
//
// }
//
// //for _,v:=range vv.Desc.Message().Fields(){
// //
// //}
// //t.P()
// //typ = append(typ, "Uint8Array")
//} else {
// typ = append(typ, vtype)
//}
if vv.Desc.IsList() { if vv.Desc.IsList() {
typ = append(typ, "[]") typ = append(typ, "[]")
} }
//t.P(vv.Desc)
t.P(` `, vv.Desc.JSONName(), isRequired, ` `, strings.Join(typ, "")) t.P(` `, vv.Desc.JSONName(), isRequired, ` `, strings.Join(typ, ""))
} }
t.P(`}`) t.P(`}`)
t.P() t.P()
} }
for _, s := range f.Services {
t.P(`export class `, s.Desc.Name(), `Service{`)
for _, m := range s.Methods {
method, path := protogen2.GetProtoMethod(m)
if method == "" {
continue
}
common := strings.TrimSpace(m.Comments.Leading.String())
if common != "" {
t.P(` `, common)
}
t.P(getInd(1), `static async `, m.Desc.Name(), `(data :`, m.Input.Desc.Name(), `, param?: Config<loginRequest>):Promise<`, m.Output.Desc.Name(), `>{`)
t.P(getInd(2), `return http<`, m.Input.Desc.Name(), `, `, m.Output.Desc.Name(), `>('`, path, `', {`)
t.P(getInd(3), `...param,`)
t.P(getInd(3), `data: data,`)
t.P(getInd(3), `method:'`, method, `'`)
t.P(getInd(2), `})`)
t.P(getInd(1), `}`)
}
t.P(`}`)
}
} }
return nil return nil
} }
func getInd(i int) string {
return strings.Repeat(` `, i)
}
func getType(key string) string { func getType(key string) string {
mps := map[string]string{ mps := map[string]string{
"int32": "number", "int32": "number",

@ -0,0 +1,33 @@
package protogen
import (
"github.com/golang/protobuf/proto"
"google.golang.org/genproto/googleapis/api/annotations"
"google.golang.org/protobuf/compiler/protogen"
"google.golang.org/protobuf/types/descriptorpb"
)
const (
METHOD_GET = "GET"
METHOD_POST = "POST"
METHOD_DELETE = "DELETE"
)
func GetProtoMethod(m *protogen.Method) (method string, path string) {
if op, ok := m.Desc.Options().(*descriptorpb.MethodOptions); ok {
if opts, err := proto.GetExtension(op, annotations.E_Http); err != nil {
//log.Println(err)
} else {
if vv, ok := opts.(*annotations.HttpRule); ok {
if vvv, ok := vv.Pattern.(*annotations.HttpRule_Get); ok {
return METHOD_GET, vvv.Get
} else if vvv, ok := vv.Pattern.(*annotations.HttpRule_Post); ok {
return METHOD_POST, vvv.Post
} else if vvv, ok := vv.Pattern.(*annotations.HttpRule_Delete); ok {
return METHOD_DELETE, vvv.Delete
}
}
}
}
return "", ""
}

Binary file not shown.

@ -10,11 +10,13 @@ import "google/protobuf/wrappers.proto";
import "google/protobuf/descriptor.proto"; import "google/protobuf/descriptor.proto";
service user{ service user{
//
rpc list(loginRequest)returns(loginResponse){ rpc list(loginRequest)returns(loginResponse){
option(google.api.http) = { option(google.api.http) = {
get:"/api/v1/user/list" get:"/api/v1/user/list"
}; };
} }
//
rpc login(loginRequest)returns(loginResponse){ rpc login(loginRequest)returns(loginResponse){
option (google.api.http) = { option (google.api.http) = {
post: "/api/v1/user/login", post: "/api/v1/user/login",

@ -0,0 +1,54 @@
//复制时倒入qs
// @ts-ignore
import qs from "qs";
const API_SERVER = process.env.NEXT_PUBLIC_WEB_SITE
export interface Config<T> extends RequestInit {
token?: string
data?: T
method?: 'POST' | 'GET'
}
interface IError {
status: number
details: [],
message: string
metadata: any
reason: string
}
const http = async <T, V>(endpoint: string, {data, token, headers, ...customConfig}: Config<T>) => {
const config = {
method: "GET",
headers: {
Authorization: token ? `Bearer ${token}` : '',
'Content-type': data ? 'application/json' : '',
},
...customConfig
}
if (config.method.toUpperCase() === "GET") {
endpoint += `?${qs.stringify(data)}`
} else {
config.body = JSON.stringify(data || {})
}
console.log(API_SERVER + endpoint, token)
return fetch(API_SERVER + endpoint, config).then(async response => {
if (response.status == 401) {
if (typeof window != 'undefined') {
// window.location.reload();
}
return Promise.reject({message: "请重新登录", status: 401})
}
const data = await response.json();
if (response.ok) {
return data as V;
} else {
return Promise.reject(data as IError);
}
})
}
export {
http
}

@ -1,3 +1,4 @@
import {Config,http} from "./http";
export interface loginRequest { export interface loginRequest {
//用户名 //用户名
username: string username: string
@ -10,3 +11,21 @@ export interface loginResponse {
token: string token: string
} }
export class userService{
//列表
static async list(data :loginRequest, param?: Config<loginRequest>):Promise<loginResponse>{
return http<loginRequest, loginResponse>('/api/v1/user/list', {
...param,
data: data,
method:'GET'
})
}
//等了
static async login(data :loginRequest, param?: Config<loginRequest>):Promise<loginResponse>{
return http<loginRequest, loginResponse>('/api/v1/user/login', {
...param,
data: data,
method:'POST'
})
}
}

@ -22,7 +22,9 @@ const _ = grpc.SupportPackageIsVersion7
// //
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type UserClient interface { type UserClient interface {
//列表
List(ctx context.Context, in *LoginRequest, opts ...grpc.CallOption) (*LoginResponse, error) List(ctx context.Context, in *LoginRequest, opts ...grpc.CallOption) (*LoginResponse, error)
//等了
Login(ctx context.Context, in *LoginRequest, opts ...grpc.CallOption) (*LoginResponse, error) Login(ctx context.Context, in *LoginRequest, opts ...grpc.CallOption) (*LoginResponse, error)
Delete(ctx context.Context, in *LoginRequest, opts ...grpc.CallOption) (*LoginResponse, error) Delete(ctx context.Context, in *LoginRequest, opts ...grpc.CallOption) (*LoginResponse, error)
} }
@ -66,7 +68,9 @@ func (c *userClient) Delete(ctx context.Context, in *LoginRequest, opts ...grpc.
// All implementations must embed UnimplementedUserServer // All implementations must embed UnimplementedUserServer
// for forward compatibility // for forward compatibility
type UserServer interface { type UserServer interface {
//列表
List(context.Context, *LoginRequest) (*LoginResponse, error) List(context.Context, *LoginRequest) (*LoginResponse, error)
//等了
Login(context.Context, *LoginRequest) (*LoginResponse, error) Login(context.Context, *LoginRequest) (*LoginResponse, error)
Delete(context.Context, *LoginRequest) (*LoginResponse, error) Delete(context.Context, *LoginRequest) (*LoginResponse, error)
mustEmbedUnimplementedUserServer() mustEmbedUnimplementedUserServer()

Loading…
Cancel
Save