Added gocli output (untested)
parent
a18faee98e
commit
539cdc478e
|
@ -1,3 +1,4 @@
|
|||
gofname: test/goapi/api.go
|
||||
goimpldir: test/goapi
|
||||
tsfname: test/tscli/api.ts
|
||||
goclifname: test/gocli/apicli.go
|
||||
|
|
|
@ -7,9 +7,10 @@ import (
|
|||
)
|
||||
|
||||
type Config struct {
|
||||
Gofname string `yaml:"gofname"`
|
||||
Goimpldir string `yaml:"goimpldir"`
|
||||
Tsfname string `json:"tsfname"`
|
||||
Gofname string `yaml:"gofname"`
|
||||
Goimpldir string `yaml:"goimpldir"`
|
||||
Tsfname string `json:"tsfname"`
|
||||
Goclifname string `json:"goclifname"`
|
||||
}
|
||||
|
||||
var config Config
|
||||
|
|
275
main.go
275
main.go
|
@ -1,17 +1,12 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"dc"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
)
|
||||
|
||||
|
@ -159,275 +154,6 @@ func addFunction(a *ast.FuncDecl) {
|
|||
api.Methods[a.Name.Name] = &fn
|
||||
}
|
||||
|
||||
func processGoServerOutput(api *API) {
|
||||
|
||||
APIParamTypeToString := func(t *APIParamType) string {
|
||||
ret := ""
|
||||
if t.Ispointer {
|
||||
ret = ret + "&"
|
||||
}
|
||||
ret = ret + t.Typename
|
||||
return ret
|
||||
}
|
||||
|
||||
b := bytes.Buffer{}
|
||||
|
||||
f := config.Gofname
|
||||
|
||||
os.Remove(f)
|
||||
b.WriteString(fmt.Sprintf(`package %s
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"net/http"
|
||||
)
|
||||
`, packageName))
|
||||
|
||||
b.WriteString(`
|
||||
|
||||
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]]
|
||||
}
|
||||
|
||||
|
||||
func Init() API{
|
||||
mux := &http.ServeMux{}
|
||||
|
||||
ret := API{
|
||||
Mux: mux,
|
||||
Perms: make(map[string]string),
|
||||
}
|
||||
`)
|
||||
for _, m := range api.Methods {
|
||||
if m.Perm != "" {
|
||||
b.WriteString(fmt.Sprintf(`
|
||||
ret.Perms["%s_%s"]="%s"
|
||||
`, m.Verb, m.Path, m.Perm))
|
||||
}
|
||||
}
|
||||
|
||||
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)))
|
||||
b.WriteString(" switch r.Method{\n")
|
||||
|
||||
for v, id := range mv {
|
||||
|
||||
b.WriteString(fmt.Sprintf(" case \"%s\":", v))
|
||||
if api.Methods[id].Raw {
|
||||
b.WriteString(fmt.Sprintf(" %s(w , r)\n", id))
|
||||
} else {
|
||||
b.WriteString(fmt.Sprintf(" h_%s(w , r)\n", id))
|
||||
}
|
||||
}
|
||||
b.WriteString(" default:")
|
||||
b.WriteString(" http.Error(w,\"Method not allowed\",500)")
|
||||
|
||||
b.WriteString(" }\n")
|
||||
b.WriteString("})\n")
|
||||
}
|
||||
b.WriteString("return ret\n }\n")
|
||||
|
||||
for k, m := range api.Methods {
|
||||
if !m.Raw {
|
||||
b.WriteString(fmt.Sprintf("\n func h_%s(w http.ResponseWriter, r *http.Request) {\n", k))
|
||||
|
||||
b.WriteString(fmt.Sprintf(
|
||||
`
|
||||
ctx := r.Context()
|
||||
ctx = context.WithValue(r.Context(), "REQ", r)
|
||||
ctx = context.WithValue(ctx, "RES", w)
|
||||
req := %s{}
|
||||
if r.Method!=http.MethodGet && r.Method!=http.MethodHead {
|
||||
err := json.NewDecoder(r.Body).Decode(&req)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
res, err := %s(ctx,req)
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
`, APIParamTypeToString(m.ReqType), k))
|
||||
}
|
||||
}
|
||||
|
||||
err := ioutil.WriteFile(f, b.Bytes(), 0600)
|
||||
dc.Err(err)
|
||||
cmd := exec.Command("/bin/sh", "-c", "go fmt "+f)
|
||||
bs, err := cmd.Output()
|
||||
//dc.Err(err)
|
||||
dc.Log(string(bs))
|
||||
}
|
||||
func processTSClientOutput(f string, api *API) {
|
||||
b := bytes.Buffer{}
|
||||
if f == "" {
|
||||
f = config.Tsfname
|
||||
}
|
||||
|
||||
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))
|
||||
|
||||
for kf, f := range v.Fields {
|
||||
ftype, ok := tstypemapper[f.Type]
|
||||
if !ok {
|
||||
ftype = f.Type
|
||||
}
|
||||
if f.Array {
|
||||
ftype = ftype + "[]"
|
||||
} else 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))
|
||||
}
|
||||
//if m.Raw {
|
||||
// {
|
||||
// b.WriteString(fmt.Sprintf("export async function API_%s(req:any):Promise<any>{\n", k, m.ReqType))
|
||||
// b.WriteString(fmt.Sprintf("\treturn InvokeJSON(\"%s\",\"%s\",req)\n", m.Path, m.Verb))
|
||||
// b.WriteString(fmt.Sprintf("}\n\n"))
|
||||
// }
|
||||
//
|
||||
//} else {
|
||||
b.WriteString(fmt.Sprintf("export async function %s(req:%s):Promise<%s>{\n", k, m.ReqType.Typename, m.ResType.Typename))
|
||||
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)
|
||||
dc.Err(err)
|
||||
}
|
||||
|
||||
//func processHTTPTestOutput(f string, api *API) {
|
||||
//
|
||||
// for k, m := range api.Methods {
|
||||
|
@ -464,6 +190,7 @@ func process(api *API) {
|
|||
mapHttp(api)
|
||||
processGoServerOutput(api)
|
||||
processTSClientOutput("", api)
|
||||
processGoClientOutput(api)
|
||||
}
|
||||
|
||||
func load() {
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"dc"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func processGoClientOutput(api *API) {
|
||||
b := bytes.Buffer{}
|
||||
f := config.Goclifname
|
||||
fparts := strings.Split(f, "/")
|
||||
pkg := fparts[len(fparts)-2]
|
||||
|
||||
b.WriteString(fmt.Sprintf(`package %s
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"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
|
||||
}
|
||||
ret := json.NewDecoder(res.Body)
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func Some() (*struct{}, error) {
|
||||
dec, err := invoke("a", "/c/d", struct{}{})
|
||||
ret := &struct{}{}
|
||||
dec.Decode(ret)
|
||||
return ret, err
|
||||
|
||||
}
|
||||
`, pkg))
|
||||
|
||||
for k, v := range api.Types {
|
||||
|
||||
b.WriteString(fmt.Sprintf("type %s struct {\n", k))
|
||||
|
||||
for kf, f := range v.Fields {
|
||||
|
||||
ftype := f.Type
|
||||
|
||||
if f.Array {
|
||||
ftype = "[]" + ftype
|
||||
} else if f.Map {
|
||||
fm := f.Mapkey
|
||||
fv := f.Mapval
|
||||
ftype = "map[" + fm + "]" + fv
|
||||
}
|
||||
|
||||
b.WriteString(fmt.Sprintf("\t%s %s `json:\"%s\"` \n", strings.ToUpper(kf[:1])+strings.ToLower(kf[1:]), ftype, strings.ToLower(kf)))
|
||||
}
|
||||
|
||||
b.WriteString(fmt.Sprintf("}\n\n"))
|
||||
}
|
||||
|
||||
for k, m := range api.Methods {
|
||||
|
||||
b.WriteString(fmt.Sprintf("func %s(req *%s) (res *%s, err error){\n", k, m.ReqType.Typename, m.ResType.Typename))
|
||||
b.WriteString(fmt.Sprintf(` dec, err := invoke("%s", "%s", req)
|
||||
ret := &%s{}
|
||||
err = dec.Decode(ret)
|
||||
if err != nil{
|
||||
return nil,err
|
||||
}
|
||||
return ret, err
|
||||
}`, m.Verb, m.Path, m.ResType.Typename))
|
||||
//}
|
||||
|
||||
}
|
||||
|
||||
err := ioutil.WriteFile(f, b.Bytes(), 0600)
|
||||
dc.Err(err)
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"dc"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func processGoServerOutput(api *API) {
|
||||
|
||||
APIParamTypeToString := func(t *APIParamType) string {
|
||||
ret := ""
|
||||
if t.Ispointer {
|
||||
ret = ret + "&"
|
||||
}
|
||||
ret = ret + t.Typename
|
||||
return ret
|
||||
}
|
||||
|
||||
b := bytes.Buffer{}
|
||||
|
||||
f := config.Gofname
|
||||
|
||||
os.Remove(f)
|
||||
b.WriteString(fmt.Sprintf(`package %s
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"net/http"
|
||||
)
|
||||
`, packageName))
|
||||
|
||||
b.WriteString(`
|
||||
|
||||
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]]
|
||||
}
|
||||
|
||||
|
||||
func Init() API{
|
||||
mux := &http.ServeMux{}
|
||||
|
||||
ret := API{
|
||||
Mux: mux,
|
||||
Perms: make(map[string]string),
|
||||
}
|
||||
`)
|
||||
for _, m := range api.Methods {
|
||||
if m.Perm != "" {
|
||||
b.WriteString(fmt.Sprintf(`
|
||||
ret.Perms["%s_%s"]="%s"
|
||||
`, m.Verb, m.Path, m.Perm))
|
||||
}
|
||||
}
|
||||
|
||||
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)))
|
||||
b.WriteString(" switch r.Method{\n")
|
||||
|
||||
for v, id := range mv {
|
||||
|
||||
b.WriteString(fmt.Sprintf(" case \"%s\":", v))
|
||||
if api.Methods[id].Raw {
|
||||
b.WriteString(fmt.Sprintf(" %s(w , r)\n", id))
|
||||
} else {
|
||||
b.WriteString(fmt.Sprintf(" h_%s(w , r)\n", id))
|
||||
}
|
||||
}
|
||||
b.WriteString(" default:")
|
||||
b.WriteString(" http.Error(w,\"Method not allowed\",500)")
|
||||
|
||||
b.WriteString(" }\n")
|
||||
b.WriteString("})\n")
|
||||
}
|
||||
b.WriteString("return ret\n }\n")
|
||||
|
||||
for k, m := range api.Methods {
|
||||
if !m.Raw {
|
||||
b.WriteString(fmt.Sprintf("\n func h_%s(w http.ResponseWriter, r *http.Request) {\n", k))
|
||||
|
||||
b.WriteString(fmt.Sprintf(
|
||||
`
|
||||
ctx := r.Context()
|
||||
ctx = context.WithValue(r.Context(), "REQ", r)
|
||||
ctx = context.WithValue(ctx, "RES", w)
|
||||
req := %s{}
|
||||
if r.Method!=http.MethodGet && r.Method!=http.MethodHead {
|
||||
err := json.NewDecoder(r.Body).Decode(&req)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
res, err := %s(ctx,req)
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
`, APIParamTypeToString(m.ReqType), k))
|
||||
}
|
||||
}
|
||||
|
||||
err := ioutil.WriteFile(f, b.Bytes(), 0600)
|
||||
dc.Err(err)
|
||||
cmd := exec.Command("/bin/sh", "-c", "go fmt "+f)
|
||||
bs, err := cmd.Output()
|
||||
//dc.Err(err)
|
||||
dc.Log(string(bs))
|
||||
}
|
|
@ -0,0 +1,158 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"dc"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func processTSClientOutput(f string, api *API) {
|
||||
b := bytes.Buffer{}
|
||||
if f == "" {
|
||||
f = config.Tsfname
|
||||
}
|
||||
|
||||
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))
|
||||
|
||||
for kf, f := range v.Fields {
|
||||
ftype, ok := tstypemapper[f.Type]
|
||||
if !ok {
|
||||
ftype = f.Type
|
||||
}
|
||||
if f.Array {
|
||||
ftype = ftype + "[]"
|
||||
} else 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))
|
||||
}
|
||||
//if m.Raw {
|
||||
// {
|
||||
// b.WriteString(fmt.Sprintf("export async function API_%s(req:any):Promise<any>{\n", k, m.ReqType))
|
||||
// b.WriteString(fmt.Sprintf("\treturn InvokeJSON(\"%s\",\"%s\",req)\n", m.Path, m.Verb))
|
||||
// b.WriteString(fmt.Sprintf("}\n\n"))
|
||||
// }
|
||||
//
|
||||
//} else {
|
||||
b.WriteString(fmt.Sprintf("export async function %s(req:%s):Promise<%s>{\n", k, m.ReqType.Typename, m.ResType.Typename))
|
||||
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)
|
||||
dc.Err(err)
|
||||
}
|
|
@ -24,7 +24,7 @@ func Init() API {
|
|||
Perms: make(map[string]string),
|
||||
}
|
||||
|
||||
mux.HandleFunc("", func(w http.ResponseWriter, r *http.Request) {
|
||||
mux.HandleFunc("/someapi", func(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.Method {
|
||||
case "POST":
|
||||
h_SomeAPI(w, r)
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
|
||||
/*@API*/
|
||||
type ARequestStruct struct {
|
||||
A *string
|
||||
A *string `json:"a"`
|
||||
B int64
|
||||
C time.Time
|
||||
D *string
|
||||
|
@ -23,7 +23,7 @@ type AResponseStruct struct {
|
|||
|
||||
/*
|
||||
@API
|
||||
PATH: /someapi
|
||||
@PATH: /someapi
|
||||
*/
|
||||
func SomeAPI(ctx context.Context, a *ARequestStruct) (*AResponseStruct, error) {
|
||||
return nil, nil
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
package gocli
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"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
|
||||
}
|
||||
ret := json.NewDecoder(res.Body)
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func Some() (*struct{}, error) {
|
||||
dec, err := invoke("a", "/c/d", struct{}{})
|
||||
ret := &struct{}{}
|
||||
dec.Decode(ret)
|
||||
return ret, err
|
||||
|
||||
}
|
||||
|
||||
type ARequestStruct struct {
|
||||
A string `json:"a"`
|
||||
B int64 `json:"b"`
|
||||
C time.Time `json:"c"`
|
||||
D string `json:"d"`
|
||||
}
|
||||
|
||||
type AResponseStruct struct {
|
||||
A string `json:"a"`
|
||||
B int64 `json:"b"`
|
||||
C time.Time `json:"c"`
|
||||
D string `json:"d"`
|
||||
}
|
||||
|
||||
func SomeAPI(req *ARequestStruct) (res *AResponseStruct, err error) {
|
||||
dec, err := invoke("POST", "/someapi", req)
|
||||
ret := &AResponseStruct{}
|
||||
err = dec.Decode(ret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ret, err
|
||||
}
|
|
@ -82,10 +82,10 @@ async function InvokeOk(path: string, method: HTMLMethod, body?: any): Promise<b
|
|||
|
||||
//#region Types
|
||||
export interface ARequestStruct {
|
||||
c:Date
|
||||
d:string
|
||||
a:string
|
||||
b:number
|
||||
c:Date
|
||||
d:string
|
||||
}
|
||||
|
||||
export interface AResponseStruct {
|
||||
|
@ -101,7 +101,7 @@ export interface AResponseStruct {
|
|||
/**
|
||||
SomeAPI*/
|
||||
export async function SomeAPI(req:ARequestStruct):Promise<AResponseStruct>{
|
||||
return InvokeJSON("","POST",req)
|
||||
return InvokeJSON("/someapi","POST",req)
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
|
Loading…
Reference in New Issue