Recovering operational
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
package lib
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func manageComments(a *ast.CommentGroup) map[string]string {
|
||||
ret := make(map[string]string)
|
||||
|
||||
if a == nil {
|
||||
return ret
|
||||
}
|
||||
|
||||
var myExp = regexp.MustCompile(`\/?\*?@(?P<k>.*)\s*:\s*(?P<v>.*)\*?\/?`)
|
||||
|
||||
var myExp2 = regexp.MustCompile(`\/?\*?@(?P<k>.*?)\*?\/?$`)
|
||||
|
||||
for _, v := range a.List {
|
||||
lines := strings.Split(v.Text, "\n")
|
||||
for _, l := range lines {
|
||||
m := myExp.FindStringSubmatch(l)
|
||||
if m != nil {
|
||||
ret[m[1]] = m[2]
|
||||
} else {
|
||||
m := myExp2.FindStringSubmatch(l)
|
||||
if m != nil {
|
||||
ret[m[1]] = "OK"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func manageCommentsGroups(as []*ast.CommentGroup) map[string]string {
|
||||
ret := make(map[string]string)
|
||||
|
||||
if as == nil {
|
||||
return ret
|
||||
}
|
||||
|
||||
for _, a := range as {
|
||||
|
||||
var myExp = regexp.MustCompile(`\/?\*?@(?P<k>.*)\s*:\s*(?P<v>.*)\*?\/?`)
|
||||
|
||||
var myExp2 = regexp.MustCompile(`\/?\*?@(?P<k>.*?)\*?\/?$`)
|
||||
|
||||
for _, v := range a.List {
|
||||
lines := strings.Split(v.Text, "\n")
|
||||
for _, l := range lines {
|
||||
m := myExp.FindStringSubmatch(l)
|
||||
if m != nil {
|
||||
ret[m[1]] = m[2]
|
||||
} else {
|
||||
m := myExp2.FindStringSubmatch(l)
|
||||
if m != nil {
|
||||
ret[m[1]] = "OK"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package lib
|
||||
|
||||
//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)
|
||||
//}
|
||||
+345
@@ -0,0 +1,345 @@
|
||||
package lib
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/fatih/structtag"
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"log"
|
||||
"net/http"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var api API
|
||||
|
||||
func llog(s string, p ...interface{}) {
|
||||
fmt.Printf(s+"\n", p...)
|
||||
}
|
||||
|
||||
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
|
||||
llog("Adding type: %s => %#v", tp.Name, md)
|
||||
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:
|
||||
api.UsedImportsTypes[z.X.(*ast.Ident).Name] = api.Imports[z.X.(*ast.Ident).Name]
|
||||
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:
|
||||
api.UsedImportsTypes[z.Name] = api.Imports[z.Name]
|
||||
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:
|
||||
api.UsedImportsTypes[z.Name] = api.Imports[z.Name]
|
||||
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
|
||||
}
|
||||
|
||||
llog("Adding Fuction: %s => %#v", a.Name, md)
|
||||
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:
|
||||
api.UsedImportsFunctions[y.X.(*ast.Ident).Name] = api.Imports[y.X.(*ast.Ident).Name]
|
||||
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:
|
||||
api.UsedImportsFunctions[y.X.(*ast.Ident).Name] = api.Imports[y.X.(*ast.Ident).Name]
|
||||
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:
|
||||
api.UsedImportsFunctions[z.X.(*ast.Ident).Name] = api.Imports[z.X.(*ast.Ident).Name]
|
||||
reqType.Typename = z.X.(*ast.Ident).Name + "." + z.Sel.Name
|
||||
}
|
||||
}
|
||||
case *ast.Ident:
|
||||
reqType.Typename = x.Name
|
||||
case *ast.SelectorExpr:
|
||||
api.UsedImportsFunctions[x.X.(*ast.Ident).Name] = api.Imports[x.X.(*ast.Ident).Name]
|
||||
reqType.Typename = x.X.(*ast.Ident).Name + "." + x.Sel.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:
|
||||
api.UsedImportsFunctions[y.X.(*ast.Ident).Name] = api.Imports[y.X.(*ast.Ident).Name]
|
||||
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:
|
||||
api.UsedImportsFunctions[y.X.(*ast.Ident).Name] = api.Imports[y.X.(*ast.Ident).Name]
|
||||
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:
|
||||
api.UsedImportsFunctions[z.X.(*ast.Ident).Name] = api.Imports[z.X.(*ast.Ident).Name]
|
||||
resType.Typename = z.X.(*ast.Ident).Name + "." + z.Sel.Name
|
||||
}
|
||||
}
|
||||
case *ast.Ident:
|
||||
resType.Typename = x.Name
|
||||
case *ast.SelectorExpr:
|
||||
api.UsedImportsFunctions[x.X.(*ast.Ident).Name] = api.Imports[x.X.(*ast.Ident).Name]
|
||||
resType.Typename = x.X.(*ast.Ident).Name + "." + x.Sel.Name
|
||||
|
||||
}
|
||||
|
||||
if md["RAW"] == "true" {
|
||||
reqType.Typename = md["REQ"]
|
||||
resType.Typename = md["RES"]
|
||||
}
|
||||
|
||||
verb := md["VERB"]
|
||||
if verb == "" {
|
||||
verb = http.MethodPost
|
||||
}
|
||||
fn := APIMethod{
|
||||
Name: a.Name.Name,
|
||||
Desc: a.Name.Name,
|
||||
Verb: verb,
|
||||
Path: md["PATH"],
|
||||
Perm: md["PERM"],
|
||||
ReqType: reqType,
|
||||
ResType: resType,
|
||||
}
|
||||
|
||||
if fn.Path == "" {
|
||||
fn.Path = "/" + strings.Replace(strings.ToLower(a.Name.Name), "_", "/", -1)
|
||||
}
|
||||
|
||||
api.Methods[a.Name.Name] = &fn
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func load(src string) error {
|
||||
|
||||
api.Types = (make(map[string]*APIType))
|
||||
api.Methods = (make(map[string]*APIMethod))
|
||||
api.Imports = make(map[string]string)
|
||||
api.UsedImportsTypes = make(map[string]string)
|
||||
api.UsedImportsFunctions = make(map[string]string)
|
||||
api.Paths = make(map[string]*APIPath)
|
||||
api.SortedPaths = make([]*APIPath, 0)
|
||||
|
||||
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 {
|
||||
|
||||
llog("Loading Package: %s", v.Name)
|
||||
// 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.ImportSpec:
|
||||
var impkey = ""
|
||||
var impval = ""
|
||||
impval = strings.Replace(x.Path.Value, "\"", "", -1)
|
||||
impval = strings.Replace(impval, "'", "", -1)
|
||||
if x.Name != nil && x.Name.Name != "" {
|
||||
impkey = x.Name.Name
|
||||
} else {
|
||||
parts := strings.Split(impval, "/")
|
||||
impkey = parts[len(parts)-1]
|
||||
}
|
||||
api.Imports[impkey] = impval
|
||||
case *ast.File:
|
||||
manageCommentsGroups(x.Comments)
|
||||
case *ast.FuncDecl:
|
||||
addFunction(x)
|
||||
llog("Adding fn: %s", x.Name)
|
||||
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 {
|
||||
path, ok := api.Paths[v.Path]
|
||||
if !ok {
|
||||
path = &APIPath{
|
||||
Path: v.Path,
|
||||
MapVerbs: make(map[string]*APIVerb),
|
||||
SortedVerbs: make([]*APIVerb, 0),
|
||||
}
|
||||
api.Paths[v.Path] = path
|
||||
}
|
||||
path.MapVerbs[v.Verb] = &APIVerb{
|
||||
Verb: v.Verb,
|
||||
Method: v,
|
||||
}
|
||||
pathmap, ok := httpMapper[v.Path]
|
||||
if !ok {
|
||||
httpMapper[v.Path] = make(map[string]string)
|
||||
pathmap = httpMapper[v.Path]
|
||||
}
|
||||
pathmap[v.Verb] = k
|
||||
}
|
||||
|
||||
pathNames := make([]string, 0)
|
||||
for k, v := range api.Paths {
|
||||
verbs := make([]string, 0)
|
||||
for k, _ := range v.MapVerbs {
|
||||
verbs = append(verbs, k)
|
||||
}
|
||||
sort.Strings(verbs)
|
||||
|
||||
for _, sv := range verbs {
|
||||
v.SortedVerbs = append(v.SortedVerbs, v.MapVerbs[sv])
|
||||
}
|
||||
pathNames = append(pathNames, k)
|
||||
}
|
||||
sort.Strings(pathNames)
|
||||
for _, p := range pathNames {
|
||||
api.SortedPaths = append(api.SortedPaths, api.Paths[p])
|
||||
}
|
||||
|
||||
api.Namespace = packageName
|
||||
|
||||
return nil
|
||||
}
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
package lib
|
||||
|
||||
import (
|
||||
"github.com/alecthomas/kong"
|
||||
"github.com/pkg/errors"
|
||||
"log"
|
||||
)
|
||||
|
||||
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"
|
||||
|
||||
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"`
|
||||
//Gin struct {
|
||||
// Src string `arg help:"Source Dir"`
|
||||
//} `cmd help:"Gens Gin Server impl"`
|
||||
Gocli struct {
|
||||
Src string `arg help:"Source Dir"`
|
||||
Dst string `arg help:"Dst file"`
|
||||
} `cmd help:"Gens Go Cli impl"`
|
||||
Pycli struct {
|
||||
Src string `arg help:"Source Dir"`
|
||||
Dst string `arg help:"Dst file"`
|
||||
} `cmd help:"Gens Python 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 Run() {
|
||||
|
||||
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 "gin <src>":
|
||||
// log.Printf("Gen Gin Server")
|
||||
// src = CLI.Gin.Src
|
||||
// processor = func() error {
|
||||
// return processGinServerOutput(CLI.Gin.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 "pycli <src> <dst>":
|
||||
log.Printf("Gen Python Client")
|
||||
src = CLI.Pycli.Src
|
||||
processor = func() error {
|
||||
return processPyClientOutput(CLI.Pycli.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")
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
err = load(src)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
err = processor()
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
//loadConfig()
|
||||
//
|
||||
|
||||
//os.Remove(config.Gofname)
|
||||
|
||||
//process(&api)
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
package lib
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
)
|
||||
|
||||
func processGoClientOutput(f string) error {
|
||||
|
||||
buf := &bytes.Buffer{}
|
||||
W := func(s string, p ...interface{}) {
|
||||
buf.WriteString(fmt.Sprintf(s, p...))
|
||||
}
|
||||
WNL := func(s string, p ...interface{}) {
|
||||
buf.WriteString(fmt.Sprintf(s+"\n", p...))
|
||||
}
|
||||
|
||||
ResDecType := func(v *APIParamType) string {
|
||||
ret := ""
|
||||
if v.IsArray {
|
||||
ret = ret + "[]"
|
||||
}
|
||||
if v.Ispointer {
|
||||
ret = ret + "*"
|
||||
}
|
||||
ret += " " + v.Typename
|
||||
return ret
|
||||
}
|
||||
|
||||
ResImplType := func(v *APIParamType) string {
|
||||
ret := ""
|
||||
if v.IsArray {
|
||||
ret = ret + "[]"
|
||||
}
|
||||
if v.Ispointer {
|
||||
ret = ret + "*"
|
||||
}
|
||||
ret += v.Typename
|
||||
ret += " = "
|
||||
if !v.IsArray || v.Ispointer {
|
||||
ret = ret + "&"
|
||||
}
|
||||
ret += v.Typename + "{}"
|
||||
return ret
|
||||
}
|
||||
|
||||
WNL("package %s", api.Namespace)
|
||||
WNL(`import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
var Basepath string = ""
|
||||
var Host string = ""
|
||||
var ExtraHeaders map[string]string = make(map[string]string)
|
||||
|
||||
func invoke(m string, path string, bodyo interface{}) (*json.Decoder, error) {
|
||||
b := &bytes.Buffer{}
|
||||
err := json.NewEncoder(b).Encode(bodyo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
body := bytes.NewReader(b.Bytes())
|
||||
req, err := http.NewRequest(m, Host+Basepath+path, body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.Header.Set("Content-type", "application/json")
|
||||
|
||||
for k, v := range ExtraHeaders {
|
||||
req.Header.Set(k, v)
|
||||
}
|
||||
|
||||
cli := http.Client{}
|
||||
res, err := cli.Do(req)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer res.Body.Close()
|
||||
|
||||
if res.StatusCode >= 400 {
|
||||
bs, err := ioutil.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return nil,err
|
||||
}
|
||||
return nil, errors.New(string(bs))
|
||||
}
|
||||
|
||||
ret := json.NewDecoder(res.Body)
|
||||
return ret, nil
|
||||
}
|
||||
`)
|
||||
|
||||
for k, v := range api.Types {
|
||||
WNL(`type %s struct {`, k)
|
||||
for fn, f := range v.Fields {
|
||||
W(` %s `, fn)
|
||||
if f.Array {
|
||||
W("[]")
|
||||
}
|
||||
if f.Map {
|
||||
W("map[%s]%s", f.Mapkey, f.Mapval)
|
||||
} else {
|
||||
WNL(f.Type)
|
||||
}
|
||||
}
|
||||
WNL(`}`)
|
||||
}
|
||||
|
||||
for k, v := range api.Methods {
|
||||
WNL(`func %s(req %s) (res %s, err error){`, k, ResDecType(v.ReqType), ResDecType(v.ResType))
|
||||
WNL(` var dec *json.Decoder
|
||||
dec, err = invoke("%s", "%s", res)
|
||||
if err!=nil{
|
||||
return
|
||||
}
|
||||
var ret %s`, v.Verb, v.Path, ResImplType(v.ResType))
|
||||
W(` err = dec.Decode(`)
|
||||
if v.ResType.IsArray || !v.ResType.Ispointer {
|
||||
W("&")
|
||||
}
|
||||
WNL(`ret)
|
||||
return ret, err
|
||||
}`)
|
||||
|
||||
}
|
||||
|
||||
return os.WriteFile(f, buf.Bytes(), 0600)
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
package lib
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
func processGoServerOutput(f string) error {
|
||||
buf := &bytes.Buffer{}
|
||||
W := func(s string, p ...interface{}) {
|
||||
buf.WriteString(fmt.Sprintf(s, p...))
|
||||
}
|
||||
WNL := func(s string, p ...interface{}) {
|
||||
buf.WriteString(fmt.Sprintf(s+"\n", p...))
|
||||
}
|
||||
|
||||
WNL("package %s", api.Namespace)
|
||||
WNL(`import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"net/http"
|
||||
)`)
|
||||
|
||||
for k := range api.UsedImportsFunctions {
|
||||
W(`import "%s"`, k)
|
||||
}
|
||||
|
||||
WNL(`type API struct {
|
||||
Mux *http.ServeMux
|
||||
Perms map[string]string
|
||||
}
|
||||
|
||||
func (a *API) GetPerm(r *http.Request) string {
|
||||
return a.Perms[r.Method+"_"+strings.Split(r.RequestURI, "?")[0]]
|
||||
}
|
||||
`)
|
||||
|
||||
WNL(`func Init() *API{
|
||||
mux := &http.ServeMux{}
|
||||
|
||||
ret := &API{
|
||||
Mux: mux,
|
||||
Perms: make(map[string]string),
|
||||
}`)
|
||||
for _, v := range api.Methods {
|
||||
if v.Perm != "" {
|
||||
WNL(` ret.Perms["%s_%s"]="%s"`, v.Verb, v.Path, v.Perm)
|
||||
}
|
||||
|
||||
}
|
||||
for _, v := range api.SortedPaths {
|
||||
WNL(` mux.HandleFunc("%s",func(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.Method {`, v.Path)
|
||||
for _, v1 := range v.SortedVerbs {
|
||||
WNL(` case "%s":`, v1.Method.Verb)
|
||||
if v1.Method.Raw {
|
||||
WNL(` %s(w,r)`, v1.Method.Name)
|
||||
} else {
|
||||
WNL(` h_%s(w,r)`, v1.Method.Name)
|
||||
}
|
||||
|
||||
WNL(` default:
|
||||
http.Error(w,"Method not allowed",500)`)
|
||||
}
|
||||
|
||||
WNL(` }`)
|
||||
|
||||
WNL(` })
|
||||
return ret
|
||||
}`)
|
||||
|
||||
}
|
||||
|
||||
for _, v := range api.Methods {
|
||||
WNL(`func h_%s(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
ctx = context.WithValue(r.Context(), "REQ", r)
|
||||
ctx = context.WithValue(ctx, "RES", w)`, v.Name)
|
||||
|
||||
W(" var req ")
|
||||
|
||||
if v.ReqType.IsArray {
|
||||
W("[]")
|
||||
}
|
||||
if v.ReqType.Ispointer {
|
||||
W("*")
|
||||
}
|
||||
WNL(v.ReqType.Typename)
|
||||
|
||||
WNL(` if r.Method!=http.MethodGet && r.Method!=http.MethodHead {`)
|
||||
|
||||
if v.ReqType.Ispointer || v.ReqType.IsArray {
|
||||
WNL(" err := json.NewDecoder(r.Body).Decode(req)")
|
||||
} else {
|
||||
WNL(" err := json.NewDecoder(r.Body).Decode(&req)")
|
||||
}
|
||||
|
||||
WNL(` if err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
}`)
|
||||
|
||||
WNL(` res, err := %s(ctx,req)`, v.Name)
|
||||
WNL(` if err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
w.Header().Add("Content-Type","Application/json")
|
||||
err=json.NewEncoder(w).Encode(res)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
}`)
|
||||
|
||||
}
|
||||
|
||||
return os.WriteFile(f, buf.Bytes(), 0600)
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package lib
|
||||
|
||||
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
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
package lib
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func processPyClientOutput(f string) error {
|
||||
|
||||
var tstypemapper map[string]string = make(map[string]string)
|
||||
var exceptionaltypemapper map[string]string = make(map[string]string)
|
||||
exceptionaltypemapper["[]byte"] = "str"
|
||||
exceptionaltypemapper["[]string"] = "List[str]"
|
||||
|
||||
tstypemapper["string"] = "str"
|
||||
tstypemapper["time.Time"] = "int"
|
||||
tstypemapper["primitive.ObjectID"] = "str"
|
||||
tstypemapper["time.Duration"] = "int"
|
||||
tstypemapper["int"] = "int"
|
||||
tstypemapper["int32"] = "int"
|
||||
tstypemapper["int64"] = "int"
|
||||
tstypemapper["float"] = "float"
|
||||
tstypemapper["float64"] = "float"
|
||||
tstypemapper["uint8"] = "int"
|
||||
tstypemapper["uint16"] = "int"
|
||||
tstypemapper["uint32"] = "int"
|
||||
tstypemapper["error"] = "Exception"
|
||||
tstypemapper["bool"] = "bool"
|
||||
tstypemapper["interface{}"] = "dict"
|
||||
tstypemapper["bson.M"] = "dict"
|
||||
|
||||
_typeName := func(m *APIParamType) string {
|
||||
if m.IsArray {
|
||||
return "List[" + m.Typename + "]"
|
||||
}
|
||||
return m.Typename
|
||||
}
|
||||
|
||||
b := bytes.Buffer{}
|
||||
|
||||
b.WriteString("from dataclasses import dataclass\n")
|
||||
b.WriteString("import requests\n")
|
||||
b.WriteString("import json\n")
|
||||
b.WriteString("from typing import List\n")
|
||||
|
||||
b.WriteString("#region Base\n")
|
||||
b.WriteString(fmt.Sprintf(`
|
||||
|
||||
__ctx = {"apibase":"%s"}
|
||||
|
||||
|
||||
def SetAPIBase(s: str):
|
||||
__ctx["apibase"] = s
|
||||
|
||||
|
||||
def GetAPIBase() -> str:
|
||||
return __ctx["apibase"]
|
||||
|
||||
|
||||
def SetCookie(s: str):
|
||||
__ctx["cookie"] = s
|
||||
|
||||
|
||||
def GetCookie() -> str:
|
||||
return __ctx["cookie"]
|
||||
|
||||
|
||||
def InvokeTxt(path: str, method: str, body) -> str:
|
||||
headers = {"Content-type": "application/json", "Cookie": "dc="+GetCookie()}
|
||||
fpath = GetAPIBase() + path
|
||||
r = requests.request(method, fpath, json=body, headers=headers)
|
||||
return r.text
|
||||
|
||||
|
||||
def InvokeJSON(path: str, method: str, body) -> dict:
|
||||
d = body.__dict__
|
||||
return json.loads(InvokeTxt(path, method, d))
|
||||
|
||||
`, api.BasePath))
|
||||
b.WriteString("#endregion\n\n")
|
||||
b.WriteString("#region Types\n")
|
||||
for k, v := range api.Types {
|
||||
if v.Desc != "" {
|
||||
//b.WriteString(fmt.Sprintf("/**\n%s*/\n", v.Desc))
|
||||
}
|
||||
if len(v.Fields) < 1 {
|
||||
b.WriteString(fmt.Sprintf("@ dataclass\nclass %s :\n\tpass\n\n", k))
|
||||
} else {
|
||||
b.WriteString(fmt.Sprintf("@ dataclass\nclass %s :\n", k))
|
||||
var ftype string
|
||||
var ok bool
|
||||
for kf, f := range v.Fields {
|
||||
ftype, ok = exceptionaltypemapper[f.String()]
|
||||
if ok {
|
||||
log.Printf("Mapped exceptional type: %s ==> %s", f.String(), ftype)
|
||||
}
|
||||
|
||||
if !ok {
|
||||
if f.Array {
|
||||
ftype, ok = tstypemapper["[]"+f.Type]
|
||||
} else {
|
||||
ftype, ok = tstypemapper[f.Type]
|
||||
}
|
||||
}
|
||||
|
||||
if !ok {
|
||||
ftype = f.Type
|
||||
}
|
||||
if f.Map {
|
||||
//fm, ok := tstypemapper[f.Mapkey]
|
||||
//if !ok {
|
||||
// fm = f.Mapkey
|
||||
//}
|
||||
//fv, ok := tstypemapper[f.Mapval]
|
||||
//if !ok {
|
||||
// fv = f.Mapval
|
||||
//}
|
||||
//ftype = "{[s:" + fm + "]:" + fv + "}"
|
||||
ftype = "dict"
|
||||
}
|
||||
|
||||
if f.Desc != "" {
|
||||
//b.WriteString(fmt.Sprintf("\t/**\n%s*/\n", f.Desc))
|
||||
}
|
||||
b.WriteString(fmt.Sprintf("\t%s: %s\n", strings.ToLower(kf), ftype))
|
||||
}
|
||||
|
||||
b.WriteString(fmt.Sprintf("\n\n"))
|
||||
}
|
||||
}
|
||||
b.WriteString("#endregion\n\n")
|
||||
b.WriteString("#region Methods\n")
|
||||
for k, m := range api.Methods {
|
||||
if m.Desc != "" {
|
||||
//b.WriteString(fmt.Sprintf("/**\n%s*/\n", m.Desc))
|
||||
}
|
||||
|
||||
rettype := _typeName(m.ResType)
|
||||
if rettype != "" {
|
||||
b.WriteString(fmt.Sprintf("def %s(req:%s)-> %s:\n", k, _typeName(m.ReqType), rettype))
|
||||
} else {
|
||||
b.WriteString(fmt.Sprintf("def %s(req:%s):\n", k, _typeName(m.ReqType)))
|
||||
}
|
||||
|
||||
b.WriteString(fmt.Sprintf("\treturn InvokeJSON(\"%s\",\"%s\",req)\n", m.Path, m.Verb))
|
||||
b.WriteString(fmt.Sprintf("\n\n"))
|
||||
//}
|
||||
|
||||
}
|
||||
b.WriteString("#endregion\n")
|
||||
|
||||
err := ioutil.WriteFile(f, b.Bytes(), 0600)
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
package lib
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"strings"
|
||||
)
|
||||
|
||||
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 {
|
||||
return m.Typename + "[]"
|
||||
}
|
||||
return m.Typename
|
||||
}
|
||||
|
||||
b := bytes.Buffer{}
|
||||
|
||||
b.WriteString("//#region Base\n")
|
||||
b.WriteString(fmt.Sprintf(`
|
||||
|
||||
var apibase="%s";
|
||||
|
||||
export function SetAPIBase(s:string){
|
||||
apibase=s;
|
||||
}
|
||||
|
||||
export function GetAPIBase(): string{
|
||||
return apibase;
|
||||
}
|
||||
|
||||
let REGEX_DATE = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)(Z|([+\-])(\d{2}):(\d{2}))$/
|
||||
|
||||
type HTMLMethod = "GET" | "POST" | "PUT" | "DELETE" | "HEAD" | "TRACE"
|
||||
|
||||
async function Invoke(path: string, method: HTMLMethod, body?: any): Promise<Response> {
|
||||
let jbody = undefined
|
||||
let init = {method: method, mode: "cors", credentials: "include", withCredentials: true}
|
||||
if (!!body) {
|
||||
let jbody = JSON.stringify(body)
|
||||
//@ts-ignore
|
||||
init.body = jbody
|
||||
}
|
||||
if (apibase.endsWith("/") && path.startsWith("/")) {
|
||||
path = path.substr(1, path.length)
|
||||
}
|
||||
let fpath = (apibase + path)
|
||||
//@ts-ignore
|
||||
let res = await fetch(fpath, init)
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
async function InvokeJSON(path: string, method: HTMLMethod, body?: any): Promise<any> {
|
||||
|
||||
let txt = await InvokeTxt(path, method, body)
|
||||
if (txt == "") {
|
||||
txt = "{}"
|
||||
}
|
||||
let ret = JSON.parse(txt, (k: string, v: string) => {
|
||||
if (REGEX_DATE.exec(v)) {
|
||||
return new Date(v)
|
||||
}
|
||||
return v
|
||||
})
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
async function InvokeTxt(path: string, method: HTMLMethod, body?: any): Promise<string> {
|
||||
//@ts-ignore
|
||||
let res = await Invoke(path, method, body)
|
||||
|
||||
let txt = await res.text()
|
||||
|
||||
if (res.status < 200 || res.status >= 400) {
|
||||
// webix.alert("API Error:" + res.status + "\n" + txt)
|
||||
console.error("API Error:" + res.status + "\n" + txt)
|
||||
let e = new Error(txt)
|
||||
throw e
|
||||
}
|
||||
|
||||
return txt
|
||||
}
|
||||
|
||||
async function InvokeOk(path: string, method: HTMLMethod, body?: any): Promise<boolean> {
|
||||
|
||||
//@ts-ignore
|
||||
let res = await Invoke(path, method, body)
|
||||
|
||||
let txt = await res.text()
|
||||
if (res.status >= 400) {
|
||||
console.error("API Error:" + res.status + "\n" + txt)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
`, api.BasePath))
|
||||
b.WriteString("//#endregion\n\n")
|
||||
b.WriteString("//#region Types\n")
|
||||
for k, v := range api.Types {
|
||||
if v.Desc != "" {
|
||||
b.WriteString(fmt.Sprintf("/**\n%s*/\n", v.Desc))
|
||||
}
|
||||
|
||||
b.WriteString(fmt.Sprintf("export interface %s {\n", k))
|
||||
var ftype string
|
||||
var ok bool
|
||||
for kf, f := range v.Fields {
|
||||
ftype, ok = exceptionaltypemapper[f.String()]
|
||||
if ok {
|
||||
log.Printf("Mapped exceptional type: %s ==> %s", f.String(), ftype)
|
||||
}
|
||||
|
||||
if !ok {
|
||||
if f.Array {
|
||||
ftype, ok = tstypemapper["[]"+f.Type]
|
||||
} else {
|
||||
ftype, ok = tstypemapper[f.Type]
|
||||
}
|
||||
}
|
||||
|
||||
if !ok {
|
||||
ftype = f.Type
|
||||
}
|
||||
if f.Map {
|
||||
fm, ok := tstypemapper[f.Mapkey]
|
||||
if !ok {
|
||||
fm = f.Mapkey
|
||||
}
|
||||
fv, ok := tstypemapper[f.Mapval]
|
||||
if !ok {
|
||||
fv = f.Mapval
|
||||
}
|
||||
ftype = "{[s:" + fm + "]:" + fv + "}"
|
||||
}
|
||||
|
||||
if f.Desc != "" {
|
||||
b.WriteString(fmt.Sprintf("\t/**\n%s*/\n", f.Desc))
|
||||
}
|
||||
b.WriteString(fmt.Sprintf("\t%s ?: %s\n", strings.ToLower(kf), ftype))
|
||||
}
|
||||
|
||||
b.WriteString(fmt.Sprintf("}\n\n"))
|
||||
}
|
||||
b.WriteString("//#endregion\n\n")
|
||||
b.WriteString("//#region Methods\n")
|
||||
for k, m := range api.Methods {
|
||||
if m.Desc != "" {
|
||||
b.WriteString(fmt.Sprintf("/**\n%s*/\n", m.Desc))
|
||||
}
|
||||
|
||||
b.WriteString(fmt.Sprintf("export async function %s(req:%s):Promise<%s>{\n", k, _typeName(m.ReqType), _typeName(m.ResType)))
|
||||
b.WriteString(fmt.Sprintf("\treturn InvokeJSON(\"%s\",\"%s\",req)\n", m.Path, m.Verb))
|
||||
b.WriteString(fmt.Sprintf("}\n\n"))
|
||||
//}
|
||||
|
||||
}
|
||||
b.WriteString("//#endregion\n")
|
||||
|
||||
err := ioutil.WriteFile(f, b.Bytes(), 0600)
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package lib
|
||||
|
||||
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
|
||||
}
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
package lib
|
||||
|
||||
type API struct {
|
||||
BasePath string `yaml:"basepath,omitempty"`
|
||||
Host string `yaml:"host,omitempty"`
|
||||
Types map[string]*APIType `yaml:"types,omitempty"`
|
||||
Methods map[string]*APIMethod `yaml:"methods,omitempty"`
|
||||
Namespace string `yaml:"namespace"`
|
||||
Imports map[string]string `yaml:"imports"`
|
||||
UsedImportsTypes map[string]string `yaml:"used_imports_types"`
|
||||
UsedImportsFunctions map[string]string `yaml:"used_imports_functions"`
|
||||
SortedPaths []*APIPath `yaml:"sorted_paths"`
|
||||
Paths map[string]*APIPath `yaml:"paths"`
|
||||
}
|
||||
|
||||
type APIPath struct {
|
||||
Path string `yaml:"path"`
|
||||
MapVerbs map[string]*APIVerb `yaml:"map_verbs"`
|
||||
SortedVerbs []*APIVerb `yaml:"sorted_verbs"`
|
||||
}
|
||||
|
||||
type APIVerb struct {
|
||||
Verb string `yaml:"verb"`
|
||||
Method *APIMethod `yaml:"method"`
|
||||
}
|
||||
type APIFieldTag struct {
|
||||
Key string `yaml:"key"`
|
||||
Name string `yaml:"name"`
|
||||
Opts []string `yaml:"opts"`
|
||||
}
|
||||
type APIField struct {
|
||||
Type string `yaml:"type,omitempty"`
|
||||
Array bool `yaml:"array,omitempty"`
|
||||
Desc string `yaml:"desc,omitempty"`
|
||||
Map bool `yaml:"map,omitempty"`
|
||||
Mapkey string `yaml:"mapkey,omitempty"`
|
||||
Mapval string `yaml:"mapval,omitempty"`
|
||||
Tags map[string]APIFieldTag `yaml:"tags,omitempty"`
|
||||
}
|
||||
|
||||
func (a *APIField) String() string {
|
||||
if a.Array {
|
||||
return "[]" + a.Type
|
||||
} else {
|
||||
return a.Type
|
||||
}
|
||||
}
|
||||
|
||||
type APIType struct {
|
||||
Name string `yaml:"name,omitempty"`
|
||||
Desc string `yaml:"desc,omitempty"`
|
||||
Fields map[string]*APIField `yaml:"fields,omitempty"`
|
||||
Col string `yaml:"col,omitempty"`
|
||||
TypeDef string `yaml:"-"`
|
||||
}
|
||||
|
||||
type APIParamType struct {
|
||||
Typename string
|
||||
Ispointer bool
|
||||
IsArray bool
|
||||
}
|
||||
|
||||
type APIMethod struct {
|
||||
Name string `yaml:"name"`
|
||||
Desc string `yaml:"desc"`
|
||||
Verb string `yaml:"verb"`
|
||||
Path string `yaml:"path"`
|
||||
Perm string `yaml:perm`
|
||||
Raw bool `yaml:"raw"`
|
||||
ReqType *APIParamType
|
||||
ResType *APIParamType
|
||||
}
|
||||
|
||||
func APIParamTypeToString(t *APIParamType) string {
|
||||
ret := ""
|
||||
if t.IsArray {
|
||||
ret = "[]"
|
||||
if t.Ispointer {
|
||||
ret = ret + "*"
|
||||
}
|
||||
ret = ret + t.Typename
|
||||
return ret
|
||||
}
|
||||
if t.Ispointer {
|
||||
ret = ret + "*"
|
||||
}
|
||||
ret = ret + t.Typename
|
||||
return ret
|
||||
}
|
||||
|
||||
func APIParamTypeDecToString(t *APIParamType) string {
|
||||
ret := ""
|
||||
if t.IsArray {
|
||||
ret = "[]"
|
||||
if t.Ispointer {
|
||||
ret = ret + "*"
|
||||
}
|
||||
ret = ret + t.Typename
|
||||
return ret
|
||||
}
|
||||
if t.Ispointer {
|
||||
ret = ret + "*"
|
||||
}
|
||||
ret = ret + t.Typename
|
||||
return ret
|
||||
}
|
||||
|
||||
func APIParamTypeUseRef(t *APIParamType) string {
|
||||
if t.IsArray || !t.Ispointer {
|
||||
return "&"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package lib
|
||||
|
||||
import (
|
||||
"log"
|
||||
)
|
||||
|
||||
func Err(e error) {
|
||||
if e != nil {
|
||||
panic(e)
|
||||
}
|
||||
}
|
||||
|
||||
func Debug(s string, p ...interface{}) {
|
||||
log.Printf("DEBUG: "+s, p...)
|
||||
}
|
||||
|
||||
func Log(s string, p ...interface{}) {
|
||||
log.Printf("LOG: "+s, p...)
|
||||
}
|
||||
Reference in New Issue
Block a user