multiple improvements
This commit is contained in:
+17
-23
@@ -1,25 +1,19 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"gopkg.in/yaml.v2"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Gofname string `yaml:"gofname"`
|
||||
Goimpldir string `yaml:"goimpldir"`
|
||||
Tsfname string `json:"tsfname"`
|
||||
Goclifname string `json:"goclifname"`
|
||||
}
|
||||
|
||||
var config Config
|
||||
|
||||
func loadConfig() {
|
||||
fname := flag.String("f", ".apigen.yaml", "File with config to load - defaults to '.apigen'")
|
||||
flag.Parse()
|
||||
bs, err := ioutil.ReadFile(*fname)
|
||||
Err(err)
|
||||
err = yaml.Unmarshal(bs, &config)
|
||||
Err(err)
|
||||
}
|
||||
//type Config struct {
|
||||
// Gofname string `yaml:"gofname"`
|
||||
// Goimpldir string `yaml:"goimpldir"`
|
||||
// Tsfname string `json:"tsfname"`
|
||||
// Goclifname string `json:"goclifname"`
|
||||
//}
|
||||
//
|
||||
//var config Config
|
||||
//
|
||||
//func loadConfig() {
|
||||
// fname := flag.String("f", ".apigen.yaml", "File with config to load - defaults to '.apigen'")
|
||||
// flag.Parse()
|
||||
// bs, err := ioutil.ReadFile(*fname)
|
||||
// Err(err)
|
||||
// err = yaml.Unmarshal(bs, &config)
|
||||
// Err(err)
|
||||
//}
|
||||
|
||||
+265
@@ -0,0 +1,265 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/fatih/structtag"
|
||||
"go/token"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"log"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var api API
|
||||
|
||||
func addStruct(a *ast.GenDecl) {
|
||||
md := manageComments(a.Doc)
|
||||
if md["API"] == "" {
|
||||
return
|
||||
}
|
||||
tp := APIType{
|
||||
Name: "",
|
||||
Desc: "",
|
||||
Fields: make(map[string]*APIField),
|
||||
Col: md["COL"],
|
||||
}
|
||||
tp.Name = a.Specs[0].(*ast.TypeSpec).Name.Name
|
||||
log.Printf("Type:" + tp.Name)
|
||||
for _, v := range a.Specs[0].(*ast.TypeSpec).Type.(*ast.StructType).Fields.List {
|
||||
tp.Fields[v.Names[0].Name] = &APIField{}
|
||||
tp.Fields[v.Names[0].Name].Tags = make(map[string]APIFieldTag)
|
||||
|
||||
switch x := v.Type.(type) {
|
||||
case *ast.Ident:
|
||||
tp.Fields[v.Names[0].Name].Type = x.Name
|
||||
case *ast.ArrayType:
|
||||
switch z := x.Elt.(type) {
|
||||
case *ast.Ident:
|
||||
tp.Fields[v.Names[0].Name].Type = z.Name
|
||||
tp.Fields[v.Names[0].Name].Array = true
|
||||
case *ast.InterfaceType:
|
||||
tp.Fields[v.Names[0].Name].Type = "interface{}"
|
||||
tp.Fields[v.Names[0].Name].Array = true
|
||||
|
||||
case *ast.SelectorExpr:
|
||||
tp.Fields[v.Names[0].Name].Type = z.X.(*ast.Ident).Name + "." + z.Sel.Name
|
||||
tp.Fields[v.Names[0].Name].Array = true
|
||||
}
|
||||
|
||||
case *ast.StarExpr:
|
||||
switch y := x.X.(type) {
|
||||
case *ast.Ident:
|
||||
tp.Fields[v.Names[0].Name].Type = y.Name
|
||||
case *ast.SelectorExpr:
|
||||
switch z := y.X.(type) {
|
||||
case *ast.Ident:
|
||||
tp.Fields[v.Names[0].Name].Type = z.Name + "." + y.Sel.Name
|
||||
}
|
||||
}
|
||||
case *ast.InterfaceType:
|
||||
tp.Fields[v.Names[0].Name].Type = "interface{}"
|
||||
|
||||
case *ast.SelectorExpr:
|
||||
|
||||
switch z := x.X.(type) {
|
||||
case *ast.Ident:
|
||||
tp.Fields[v.Names[0].Name].Type = z.Name + "." + x.Sel.Name
|
||||
}
|
||||
|
||||
case *ast.MapType:
|
||||
|
||||
switch z := x.Value.(type) {
|
||||
case *ast.Ident:
|
||||
tp.Fields[v.Names[0].Name].Type = ""
|
||||
tp.Fields[v.Names[0].Name].Mapkey = x.Key.(*ast.Ident).Name
|
||||
tp.Fields[v.Names[0].Name].Mapval = z.Name
|
||||
tp.Fields[v.Names[0].Name].Map = true
|
||||
case *ast.InterfaceType:
|
||||
tp.Fields[v.Names[0].Name].Type = "interface{}"
|
||||
tp.Fields[v.Names[0].Name].Array = true
|
||||
}
|
||||
|
||||
default:
|
||||
log.Printf("%#v", x)
|
||||
}
|
||||
if v.Tag != nil {
|
||||
tgstr := strings.ReplaceAll(v.Tag.Value, "`", "")
|
||||
tg, err := structtag.Parse(tgstr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for _, tgv := range tg.Keys() {
|
||||
atg, err := tg.Get(tgv)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
tp.Fields[v.Names[0].Name].Tags[tgv] = APIFieldTag{
|
||||
Key: tgv,
|
||||
Name: atg.Name,
|
||||
Opts: atg.Options,
|
||||
}
|
||||
}
|
||||
log.Printf("#%v", tg)
|
||||
}
|
||||
|
||||
}
|
||||
api.Types[tp.Name] = &tp
|
||||
}
|
||||
|
||||
func addFunction(a *ast.FuncDecl) {
|
||||
md := manageComments(a.Doc)
|
||||
|
||||
if md["API"] == "" {
|
||||
return
|
||||
}
|
||||
reqType := &APIParamType{}
|
||||
resType := &APIParamType{}
|
||||
|
||||
if len(a.Type.Params.List) > 1 {
|
||||
switch x := a.Type.Params.List[1].Type.(type) {
|
||||
case *ast.StarExpr:
|
||||
reqType.Ispointer = true
|
||||
switch y := x.X.(type) {
|
||||
case *ast.Ident:
|
||||
reqType.Typename = y.Name
|
||||
case *ast.SelectorExpr:
|
||||
reqType.Typename = y.X.(*ast.Ident).Name + "." + y.Sel.Name
|
||||
}
|
||||
case *ast.ArrayType:
|
||||
reqType.IsArray = true
|
||||
switch y := x.Elt.(type) {
|
||||
case *ast.Ident:
|
||||
reqType.Typename = y.Name
|
||||
case *ast.SelectorExpr:
|
||||
reqType.Typename = y.X.(*ast.Ident).Name + "." + y.Sel.Name
|
||||
case *ast.StarExpr:
|
||||
reqType.Ispointer = true
|
||||
switch z := y.X.(type) {
|
||||
case *ast.Ident:
|
||||
reqType.Typename = z.Name
|
||||
case *ast.SelectorExpr:
|
||||
reqType.Typename = z.X.(*ast.Ident).Name + "." + z.Sel.Name
|
||||
}
|
||||
}
|
||||
case *ast.Ident:
|
||||
reqType.Typename = x.Name
|
||||
}
|
||||
}
|
||||
|
||||
if a.Type.Results != nil && len(a.Type.Results.List) > 0 {
|
||||
|
||||
switch x := a.Type.Results.List[0].Type.(type) {
|
||||
case *ast.StarExpr:
|
||||
resType.Ispointer = true
|
||||
switch y := x.X.(type) {
|
||||
case *ast.Ident:
|
||||
resType.Typename = y.Name
|
||||
case *ast.SelectorExpr:
|
||||
resType.Typename = y.X.(*ast.Ident).Name + "." + y.Sel.Name
|
||||
}
|
||||
case *ast.ArrayType:
|
||||
resType.IsArray = true
|
||||
switch y := x.Elt.(type) {
|
||||
case *ast.Ident:
|
||||
resType.Typename = y.Name
|
||||
case *ast.SelectorExpr:
|
||||
resType.Typename = y.X.(*ast.Ident).Name + "." + y.Sel.Name
|
||||
case *ast.StarExpr:
|
||||
resType.Ispointer = true
|
||||
switch z := y.X.(type) {
|
||||
case *ast.Ident:
|
||||
resType.Typename = z.Name
|
||||
case *ast.SelectorExpr:
|
||||
resType.Typename = z.X.(*ast.Ident).Name + "." + z.Sel.Name
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if md["RAW"] == "true" {
|
||||
reqType.Typename = md["REQ"]
|
||||
resType.Typename = md["RES"]
|
||||
}
|
||||
|
||||
verb := md["VERB"]
|
||||
if verb == "" {
|
||||
verb = http.MethodPost
|
||||
}
|
||||
fn := APIMethod{
|
||||
Desc: a.Name.Name,
|
||||
Verb: verb,
|
||||
Path: md["PATH"],
|
||||
Perm: md["PERM"],
|
||||
ReqType: reqType,
|
||||
ResType: resType,
|
||||
Raw: md["RAW"] == "true",
|
||||
}
|
||||
api.Methods[a.Name.Name] = &fn
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func load(src string) error {
|
||||
|
||||
api.Types = (make(map[string]*APIType))
|
||||
api.Methods = (make(map[string]*APIMethod))
|
||||
|
||||
fset := token.NewFileSet() // positions are relative to fset
|
||||
|
||||
f, err := parser.ParseDir(fset, src, nil, parser.ParseComments)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, v := range f {
|
||||
// Print the AST.
|
||||
ast.Inspect(v, func(n ast.Node) bool {
|
||||
|
||||
switch x := n.(type) {
|
||||
|
||||
case *ast.GenDecl:
|
||||
if x.Tok == token.TYPE {
|
||||
addStruct(x)
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
|
||||
case *ast.File:
|
||||
c := manageCommentsGroups(x.Comments)
|
||||
log.Printf("%+v", c)
|
||||
case *ast.FuncDecl:
|
||||
addFunction(x)
|
||||
case *ast.ValueSpec:
|
||||
if x.Names[0].Name == "BASEPATH" {
|
||||
api.BasePath = strings.Replace(x.Values[0].(*ast.BasicLit).Value, "\"", "", -1)
|
||||
}
|
||||
if x.Names[0].Name == "NAMESPACE" {
|
||||
api.Namespace = strings.Replace(x.Values[0].(*ast.BasicLit).Value, "\"", "", -1)
|
||||
}
|
||||
log.Printf("%#v", x)
|
||||
case *ast.Package:
|
||||
packageName = x.Name
|
||||
default:
|
||||
//log.Printf("%#v", x)
|
||||
return true
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
for k, v := range api.Methods {
|
||||
pathmap, ok := httpMapper[v.Path]
|
||||
if !ok {
|
||||
httpMapper[v.Path] = make(map[string]string)
|
||||
pathmap = httpMapper[v.Path]
|
||||
}
|
||||
pathmap[v.Verb] = k
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
+84
-264
@@ -1,282 +1,102 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"github.com/alecthomas/kong"
|
||||
"github.com/pkg/errors"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var api API
|
||||
|
||||
//var httptestdir string
|
||||
var tstypemapper map[string]string = make(map[string]string)
|
||||
var exceptionaltypemapper map[string]string = make(map[string]string)
|
||||
var knownMethods map[string]bool = make(map[string]bool)
|
||||
var httpMapper map[string]map[string]string = make(map[string]map[string]string)
|
||||
var packageName string = "main"
|
||||
|
||||
func addStruct(a *ast.GenDecl) {
|
||||
md := manageComments(a.Doc)
|
||||
if md["API"] == "" {
|
||||
return
|
||||
}
|
||||
tp := APIType{
|
||||
Name: "",
|
||||
Desc: "",
|
||||
Fields: make(map[string]*APIField),
|
||||
Col: md["COL"],
|
||||
}
|
||||
tp.Name = a.Specs[0].(*ast.TypeSpec).Name.Name
|
||||
log.Printf("Type:" + tp.Name)
|
||||
for _, v := range a.Specs[0].(*ast.TypeSpec).Type.(*ast.StructType).Fields.List {
|
||||
tp.Fields[v.Names[0].Name] = &APIField{}
|
||||
switch x := v.Type.(type) {
|
||||
case *ast.Ident:
|
||||
tp.Fields[v.Names[0].Name].Type = x.Name
|
||||
case *ast.ArrayType:
|
||||
switch z := x.Elt.(type) {
|
||||
case *ast.Ident:
|
||||
tp.Fields[v.Names[0].Name].Type = z.Name
|
||||
tp.Fields[v.Names[0].Name].Array = true
|
||||
case *ast.InterfaceType:
|
||||
tp.Fields[v.Names[0].Name].Type = "interface{}"
|
||||
tp.Fields[v.Names[0].Name].Array = true
|
||||
|
||||
case *ast.SelectorExpr:
|
||||
tp.Fields[v.Names[0].Name].Type = z.X.(*ast.Ident).Name + "." + z.Sel.Name
|
||||
tp.Fields[v.Names[0].Name].Array = true
|
||||
}
|
||||
|
||||
case *ast.StarExpr:
|
||||
switch y := x.X.(type) {
|
||||
case *ast.Ident:
|
||||
tp.Fields[v.Names[0].Name].Type = y.Name
|
||||
case *ast.SelectorExpr:
|
||||
switch z := y.X.(type) {
|
||||
case *ast.Ident:
|
||||
tp.Fields[v.Names[0].Name].Type = z.Name + "." + y.Sel.Name
|
||||
}
|
||||
}
|
||||
case *ast.InterfaceType:
|
||||
tp.Fields[v.Names[0].Name].Type = "interface{}"
|
||||
|
||||
case *ast.SelectorExpr:
|
||||
|
||||
switch z := x.X.(type) {
|
||||
case *ast.Ident:
|
||||
tp.Fields[v.Names[0].Name].Type = z.Name + "." + x.Sel.Name
|
||||
}
|
||||
|
||||
case *ast.MapType:
|
||||
|
||||
switch z := x.Value.(type) {
|
||||
case *ast.Ident:
|
||||
tp.Fields[v.Names[0].Name].Type = ""
|
||||
tp.Fields[v.Names[0].Name].Mapkey = x.Key.(*ast.Ident).Name
|
||||
tp.Fields[v.Names[0].Name].Mapval = z.Name
|
||||
tp.Fields[v.Names[0].Name].Map = true
|
||||
case *ast.InterfaceType:
|
||||
tp.Fields[v.Names[0].Name].Type = "interface{}"
|
||||
tp.Fields[v.Names[0].Name].Array = true
|
||||
}
|
||||
|
||||
default:
|
||||
log.Printf("%#v", x)
|
||||
}
|
||||
|
||||
}
|
||||
api.Types[tp.Name] = &tp
|
||||
}
|
||||
|
||||
func addFunction(a *ast.FuncDecl) {
|
||||
md := manageComments(a.Doc)
|
||||
|
||||
if md["API"] == "" {
|
||||
return
|
||||
}
|
||||
reqType := &APIParamType{}
|
||||
resType := &APIParamType{}
|
||||
|
||||
if len(a.Type.Params.List) > 1 {
|
||||
switch x := a.Type.Params.List[1].Type.(type) {
|
||||
case *ast.StarExpr:
|
||||
reqType.Ispointer = true
|
||||
switch y := x.X.(type) {
|
||||
case *ast.Ident:
|
||||
reqType.Typename = y.Name
|
||||
case *ast.SelectorExpr:
|
||||
reqType.Typename = y.X.(*ast.Ident).Name + "." + y.Sel.Name
|
||||
}
|
||||
case *ast.ArrayType:
|
||||
reqType.IsArray = true
|
||||
switch y := x.Elt.(type) {
|
||||
case *ast.Ident:
|
||||
reqType.Typename = y.Name
|
||||
case *ast.SelectorExpr:
|
||||
reqType.Typename = y.X.(*ast.Ident).Name + "." + y.Sel.Name
|
||||
case *ast.StarExpr:
|
||||
reqType.Ispointer = true
|
||||
switch z := y.X.(type) {
|
||||
case *ast.Ident:
|
||||
reqType.Typename = z.Name
|
||||
case *ast.SelectorExpr:
|
||||
reqType.Typename = z.X.(*ast.Ident).Name + "." + z.Sel.Name
|
||||
}
|
||||
}
|
||||
case *ast.Ident:
|
||||
reqType.Typename = x.Name
|
||||
}
|
||||
}
|
||||
|
||||
if a.Type.Results != nil && len(a.Type.Results.List) > 0 {
|
||||
|
||||
switch x := a.Type.Results.List[0].Type.(type) {
|
||||
case *ast.StarExpr:
|
||||
resType.Ispointer = true
|
||||
switch y := x.X.(type) {
|
||||
case *ast.Ident:
|
||||
resType.Typename = y.Name
|
||||
case *ast.SelectorExpr:
|
||||
resType.Typename = y.X.(*ast.Ident).Name + "." + y.Sel.Name
|
||||
}
|
||||
case *ast.ArrayType:
|
||||
resType.IsArray = true
|
||||
switch y := x.Elt.(type) {
|
||||
case *ast.Ident:
|
||||
resType.Typename = y.Name
|
||||
case *ast.SelectorExpr:
|
||||
resType.Typename = y.X.(*ast.Ident).Name + "." + y.Sel.Name
|
||||
case *ast.StarExpr:
|
||||
resType.Ispointer = true
|
||||
switch z := y.X.(type) {
|
||||
case *ast.Ident:
|
||||
resType.Typename = z.Name
|
||||
case *ast.SelectorExpr:
|
||||
resType.Typename = z.X.(*ast.Ident).Name + "." + z.Sel.Name
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if md["RAW"] == "true" {
|
||||
reqType.Typename = md["REQ"]
|
||||
resType.Typename = md["RES"]
|
||||
}
|
||||
|
||||
verb := md["VERB"]
|
||||
if verb == "" {
|
||||
verb = http.MethodPost
|
||||
}
|
||||
fn := APIMethod{
|
||||
Desc: a.Name.Name,
|
||||
Verb: verb,
|
||||
Path: md["PATH"],
|
||||
Perm: md["PERM"],
|
||||
ReqType: reqType,
|
||||
ResType: resType,
|
||||
Raw: md["RAW"] == "true",
|
||||
}
|
||||
api.Methods[a.Name.Name] = &fn
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func mapHttp(api *API) {
|
||||
for k, v := range api.Methods {
|
||||
pathmap, ok := httpMapper[v.Path]
|
||||
if !ok {
|
||||
httpMapper[v.Path] = make(map[string]string)
|
||||
pathmap = httpMapper[v.Path]
|
||||
}
|
||||
pathmap[v.Verb] = k
|
||||
}
|
||||
}
|
||||
func process(api *API) {
|
||||
mapHttp(api)
|
||||
processGoServerOutput(api)
|
||||
processTSClientOutput("", api)
|
||||
processGoClientOutput(api)
|
||||
}
|
||||
|
||||
func load() {
|
||||
|
||||
api.Types = (make(map[string]*APIType))
|
||||
api.Methods = (make(map[string]*APIMethod))
|
||||
|
||||
fset := token.NewFileSet() // positions are relative to fset
|
||||
|
||||
f, err := parser.ParseDir(fset, config.Goimpldir, nil, parser.ParseComments)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for _, v := range f {
|
||||
// Print the AST.
|
||||
ast.Inspect(v, func(n ast.Node) bool {
|
||||
|
||||
switch x := n.(type) {
|
||||
|
||||
case *ast.GenDecl:
|
||||
if x.Tok == token.TYPE {
|
||||
addStruct(x)
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
|
||||
case *ast.File:
|
||||
c := manageCommentsGroups(x.Comments)
|
||||
log.Printf("%+v", c)
|
||||
case *ast.FuncDecl:
|
||||
addFunction(x)
|
||||
case *ast.ValueSpec:
|
||||
if x.Names[0].Name == "BASEPATH" {
|
||||
api.BasePath = strings.Replace(x.Values[0].(*ast.BasicLit).Value, "\"", "", -1)
|
||||
}
|
||||
if x.Names[0].Name == "NAMESPACE" {
|
||||
api.Namespace = strings.Replace(x.Values[0].(*ast.BasicLit).Value, "\"", "", -1)
|
||||
}
|
||||
log.Printf("%#v", x)
|
||||
case *ast.Package:
|
||||
packageName = x.Name
|
||||
default:
|
||||
//log.Printf("%#v", x)
|
||||
return true
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
var CLI struct {
|
||||
Yaml struct {
|
||||
Src string `arg help:"Source Dir"`
|
||||
Fname string `arg help:"File to be generated"`
|
||||
} `cmd help:"Gens YAML metamodel"`
|
||||
Goserver struct {
|
||||
Src string `arg help:"Source Dir"`
|
||||
} `cmd help:"Gens GO Server impl"`
|
||||
Gocli struct {
|
||||
Src string `arg help:"Source Dir"`
|
||||
Dst string `arg help:"Dst file"`
|
||||
} `cmd help:"Gens Go Cli impl"`
|
||||
Ts struct {
|
||||
Src string `arg help:"Source Dir"`
|
||||
Dst string `arg help:"Dst file"`
|
||||
} `cmd help:"Gens Typescript Cli impl"`
|
||||
Http struct {
|
||||
Src string `arg help:"Source Dir"`
|
||||
Dst string `arg help:"Dst file"`
|
||||
} `cmd help:"Gens Http call impl"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
loadConfig()
|
||||
var processor func() error
|
||||
kong.ConfigureHelp(kong.HelpOptions{
|
||||
NoAppSummary: false,
|
||||
Summary: true,
|
||||
Compact: true,
|
||||
Tree: true,
|
||||
Indenter: nil,
|
||||
})
|
||||
ctx := kong.Parse(&CLI)
|
||||
var err error
|
||||
var src string
|
||||
switch ctx.Command() {
|
||||
case "yaml <src> <fname>":
|
||||
log.Printf("Gens YAML")
|
||||
src = CLI.Yaml.Src
|
||||
processor = func() error {
|
||||
return processYaml(CLI.Yaml.Fname, nil)
|
||||
}
|
||||
case "goserver <src>":
|
||||
log.Printf("Gen GO Server")
|
||||
src = CLI.Goserver.Src
|
||||
processor = func() error {
|
||||
return processGoServerOutput(CLI.Goserver.Src + "/apigen.go")
|
||||
}
|
||||
case "gocli <src> <dst>":
|
||||
log.Printf("Gen GO Client")
|
||||
src = CLI.Gocli.Src
|
||||
processor = func() error {
|
||||
return processGoClientOutput(CLI.Gocli.Dst)
|
||||
}
|
||||
case "ts <src> <dst>":
|
||||
log.Printf("Gen TS Client")
|
||||
src = CLI.Ts.Src
|
||||
processor = func() error {
|
||||
return processTSClientOutput(CLI.Ts.Dst)
|
||||
}
|
||||
case "http <src> <dst>":
|
||||
log.Printf("Gen Http Client")
|
||||
src = CLI.Http.Src
|
||||
processor = func() error {
|
||||
return processHttpCallOut(CLI.Http.Dst)
|
||||
}
|
||||
default:
|
||||
err = errors.New("unknown option")
|
||||
}
|
||||
|
||||
exceptionaltypemapper["[]byte"] = "string"
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
err = load(src)
|
||||
|
||||
tstypemapper["time.Time"] = "Date"
|
||||
tstypemapper["primitive.ObjectID"] = "string"
|
||||
tstypemapper["time.Duration"] = "Date"
|
||||
tstypemapper["int"] = "number"
|
||||
tstypemapper["int32"] = "number"
|
||||
tstypemapper["int64"] = "number"
|
||||
tstypemapper["float"] = "number"
|
||||
tstypemapper["float64"] = "number"
|
||||
tstypemapper["uint8"] = "number"
|
||||
tstypemapper["uint16"] = "number"
|
||||
tstypemapper["uint32"] = "number"
|
||||
tstypemapper["error"] = "Error"
|
||||
tstypemapper["bool"] = "boolean"
|
||||
tstypemapper["interface{}"] = "any"
|
||||
tstypemapper["bson.M"] = "any"
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
err = processor()
|
||||
|
||||
os.Remove(config.Gofname)
|
||||
load()
|
||||
process(&api)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
//loadConfig()
|
||||
//
|
||||
|
||||
//os.Remove(config.Gofname)
|
||||
|
||||
//process(&api)
|
||||
}
|
||||
|
||||
@@ -7,9 +7,9 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
func processGoClientOutput(api *API) {
|
||||
func processGoClientOutput(f string) error {
|
||||
b := bytes.Buffer{}
|
||||
f := config.Goclifname
|
||||
|
||||
fparts := strings.Split(f, "/")
|
||||
pkg := fparts[len(fparts)-2]
|
||||
|
||||
@@ -109,7 +109,5 @@ func invoke(m string, path string, bodyo interface{}) (*json.Decoder, error) {
|
||||
}
|
||||
|
||||
err := ioutil.WriteFile(f, b.Bytes(), 0600)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -7,15 +7,26 @@ import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func processGoServerOutput(api *API) {
|
||||
func processGoServerOutput(f string) error {
|
||||
|
||||
strKeys := make([]string, 0)
|
||||
for k, _ := range api.Types {
|
||||
strKeys = append(strKeys, k)
|
||||
}
|
||||
sort.Strings(strKeys)
|
||||
|
||||
strMKeys := make([]string, 0)
|
||||
for k, _ := range api.Methods {
|
||||
strKeys = append(strMKeys, k)
|
||||
}
|
||||
sort.Strings(strMKeys)
|
||||
|
||||
b := bytes.Buffer{}
|
||||
|
||||
f := config.Gofname
|
||||
|
||||
os.Remove(f)
|
||||
b.WriteString(fmt.Sprintf(`package %s
|
||||
|
||||
@@ -47,7 +58,8 @@ func Init() API{
|
||||
Perms: make(map[string]string),
|
||||
}
|
||||
`)
|
||||
for _, m := range api.Methods {
|
||||
for _, k := range strMKeys {
|
||||
m := api.Methods[k]
|
||||
if m.Perm != "" {
|
||||
b.WriteString(fmt.Sprintf(`
|
||||
ret.Perms["%s_%s"]="%s"
|
||||
@@ -57,12 +69,25 @@ ret.Perms["%s_%s"]="%s"
|
||||
|
||||
b.WriteString("\n\n")
|
||||
|
||||
for p, mv := range httpMapper {
|
||||
|
||||
b.WriteString(fmt.Sprintf(" mux.HandleFunc(\"%s\",func(w http.ResponseWriter, r *http.Request) {\n", strings.Replace(p, "//", "/", -1)))
|
||||
sortedMapper := make([]string, 0)
|
||||
for k, _ := range httpMapper {
|
||||
sortedMapper = append(sortedMapper, k)
|
||||
}
|
||||
sort.Strings(sortedMapper)
|
||||
for _, p := range sortedMapper {
|
||||
mv := httpMapper[p]
|
||||
b.WriteString(fmt.Sprintf(" mux.HandleFunc(\"%s\",func(w http.ResponseWriter, r *http.Request) {\n",
|
||||
strings.Replace(p, "//", "/", -1)))
|
||||
b.WriteString(" switch r.Method{\n")
|
||||
|
||||
for v, id := range mv {
|
||||
sorteVerbs := make([]string, 0)
|
||||
for k, _ := range mv {
|
||||
sorteVerbs = append(sorteVerbs, k)
|
||||
}
|
||||
sort.Strings(sorteVerbs)
|
||||
|
||||
for _, v := range sorteVerbs {
|
||||
id := mv[v]
|
||||
|
||||
b.WriteString(fmt.Sprintf(" case \"%s\":", v))
|
||||
if api.Methods[id].Raw {
|
||||
@@ -116,10 +141,11 @@ ret.Perms["%s_%s"]="%s"
|
||||
|
||||
err := ioutil.WriteFile(f, b.Bytes(), 0600)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return err
|
||||
}
|
||||
cmd := exec.Command("/bin/sh", "-c", "go fmt "+f)
|
||||
bs, err := cmd.Output()
|
||||
//dc.Err(err)
|
||||
dc.Log(string(bs))
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func typeToJson(tn string) interface{} {
|
||||
|
||||
rootmap := make(map[string]interface{})
|
||||
|
||||
td, ok := api.Types[tn]
|
||||
if !ok {
|
||||
if tn == "string" {
|
||||
return "A STRING VALUE"
|
||||
}
|
||||
if tn == "bool" {
|
||||
return true
|
||||
}
|
||||
if strings.HasPrefix(strings.ToLower(tn), "int") {
|
||||
return 123456
|
||||
}
|
||||
if strings.HasPrefix(strings.ToLower(tn), "float") {
|
||||
return 123.456
|
||||
}
|
||||
}
|
||||
|
||||
for k, v := range td.Fields {
|
||||
tg, ok := v.Tags["json"]
|
||||
fname := strings.ToLower(k)
|
||||
if ok {
|
||||
fname = tg.Name
|
||||
}
|
||||
if v.Map {
|
||||
submapval := typeToJson(v.Mapval)
|
||||
submap := make(map[string]interface{})
|
||||
submap["a"] = submapval
|
||||
submap["b"] = submapval
|
||||
submap["c"] = submapval
|
||||
rootmap[fname] = submap
|
||||
|
||||
} else {
|
||||
submapval := typeToJson(v.Type)
|
||||
if v.Array {
|
||||
submap := make([]interface{}, 0)
|
||||
submap = append(submap, submapval)
|
||||
submap = append(submap, submapval)
|
||||
submap = append(submap, submapval)
|
||||
rootmap[fname] = submap
|
||||
} else {
|
||||
rootmap[fname] = submapval
|
||||
}
|
||||
}
|
||||
}
|
||||
return rootmap
|
||||
}
|
||||
|
||||
func typeToJsonStr(tn string) string {
|
||||
o := typeToJson(tn)
|
||||
bs, err := json.MarshalIndent(o, "", "\t")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return string(bs)
|
||||
}
|
||||
|
||||
func processHttpCallOut(f string) error {
|
||||
|
||||
b := bytes.Buffer{}
|
||||
|
||||
sortedMethods := make([]string, 0)
|
||||
for k, _ := range api.Methods {
|
||||
sortedMethods = append(sortedMethods, k)
|
||||
}
|
||||
sort.Strings(sortedMethods)
|
||||
|
||||
for _, k := range sortedMethods {
|
||||
m := api.Methods[k]
|
||||
tj := typeToJsonStr(m.ReqType.Typename)
|
||||
b.WriteString("###\n")
|
||||
if m.Desc != "" {
|
||||
b.WriteString(fmt.Sprintf("#%s", strings.Replace(m.Desc, "\n", "\n#", -1)))
|
||||
}
|
||||
b.WriteString(fmt.Sprintf("\n"))
|
||||
b.WriteString(fmt.Sprintf(m.Verb + " https://host/basepath" + m.Path + "\n"))
|
||||
b.WriteString("Content-Type: application/json\n")
|
||||
b.WriteString("Cookie: dc=<MYCOOKIE>\n\n")
|
||||
b.WriteString(tj)
|
||||
b.WriteString("\n\n")
|
||||
|
||||
}
|
||||
|
||||
err := ioutil.WriteFile(f, b.Bytes(), 0600)
|
||||
return err
|
||||
}
|
||||
@@ -8,7 +8,27 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
func processTSClientOutput(f string, api *API) {
|
||||
func processTSClientOutput(f string) error {
|
||||
|
||||
var tstypemapper map[string]string = make(map[string]string)
|
||||
var exceptionaltypemapper map[string]string = make(map[string]string)
|
||||
exceptionaltypemapper["[]byte"] = "string"
|
||||
|
||||
tstypemapper["time.Time"] = "Date"
|
||||
tstypemapper["primitive.ObjectID"] = "string"
|
||||
tstypemapper["time.Duration"] = "Date"
|
||||
tstypemapper["int"] = "number"
|
||||
tstypemapper["int32"] = "number"
|
||||
tstypemapper["int64"] = "number"
|
||||
tstypemapper["float"] = "number"
|
||||
tstypemapper["float64"] = "number"
|
||||
tstypemapper["uint8"] = "number"
|
||||
tstypemapper["uint16"] = "number"
|
||||
tstypemapper["uint32"] = "number"
|
||||
tstypemapper["error"] = "Error"
|
||||
tstypemapper["bool"] = "boolean"
|
||||
tstypemapper["interface{}"] = "any"
|
||||
tstypemapper["bson.M"] = "any"
|
||||
|
||||
_typeName := func(m *APIParamType) string {
|
||||
if m.IsArray {
|
||||
@@ -18,9 +38,6 @@ func processTSClientOutput(f string, api *API) {
|
||||
}
|
||||
|
||||
b := bytes.Buffer{}
|
||||
if f == "" {
|
||||
f = config.Tsfname
|
||||
}
|
||||
|
||||
b.WriteString("//#region Base\n")
|
||||
b.WriteString(fmt.Sprintf(`
|
||||
@@ -166,7 +183,5 @@ async function InvokeOk(path: string, method: HTMLMethod, body?: any): Promise<b
|
||||
b.WriteString("//#endregion\n")
|
||||
|
||||
err := ioutil.WriteFile(f, b.Bytes(), 0600)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"gopkg.in/yaml.v2"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
func processYaml(dst string, opts interface{}) error {
|
||||
bs, err := yaml.Marshal(api)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = ioutil.WriteFile(dst, bs, 0600)
|
||||
return err
|
||||
}
|
||||
+7
-1
@@ -7,6 +7,11 @@ type API struct {
|
||||
Methods map[string]*APIMethod `yaml:"methods"`
|
||||
Namespace string
|
||||
}
|
||||
type APIFieldTag struct {
|
||||
Key string
|
||||
Name string
|
||||
Opts []string
|
||||
}
|
||||
type APIField struct {
|
||||
Type string `yaml:"type"`
|
||||
Array bool `yaml:"array"`
|
||||
@@ -14,6 +19,7 @@ type APIField struct {
|
||||
Map bool `yaml:"map"`
|
||||
Mapkey string `yaml:"mapkey"`
|
||||
Mapval string `yaml:"mapval"`
|
||||
Tags map[string]APIFieldTag
|
||||
}
|
||||
|
||||
func (a *APIField) String() string {
|
||||
@@ -25,7 +31,7 @@ func (a *APIField) String() string {
|
||||
}
|
||||
|
||||
type APIType struct {
|
||||
Name string
|
||||
Name string `yaml:"name"`
|
||||
Desc string `yaml:"desc"`
|
||||
Fields map[string]*APIField `yaml:"fields"`
|
||||
Col string `yaml:"col"`
|
||||
|
||||
+3
-1
@@ -1,6 +1,8 @@
|
||||
package main
|
||||
|
||||
import "log"
|
||||
import (
|
||||
"log"
|
||||
)
|
||||
|
||||
func Err(e error) {
|
||||
if e != nil {
|
||||
|
||||
Reference in New Issue
Block a user