go-quasar-partial-ssr/backend/pkg/ts-rpc/tsEndpoint.go

201 lines
5.1 KiB
Go

// exportable typescript generated from golang
// Copyright (C) 2022 Fabio Prada
package tsrpc
import (
"bytes"
"fmt"
"strings"
"text/template"
)
type TSEndpoint struct {
Name string
Path string
Method string
Request string
Response string
RequestTs string
ResponseTs string
Source string
File string
Line int
}
func ParseEndpoint(source string, file string, line int) TSEndpoint {
p := strings.Index(source, "TSEndpoint=")
s := strings.Trim(source[p+len("TSEndpoint="):], " ")
a := strings.Split(s, ";")
n := 0
endpoint := TSEndpoint{}
endpoint.Source = strings.Trim(source, "\t")
endpoint.File = file
endpoint.Line = line
for _, v := range a {
t := strings.Split(v, "=")
if len(t) < 2 || strings.Trim(t[1], " ") == "" {
exitOnError(fmt.Errorf("worong endpoint: %s", s))
}
if len(t) == 2 {
switch strings.Trim(t[0], " ") {
case "path":
n++
endpoint.Path = strings.Trim(t[1], " ")
case "method":
n++
endpoint.Method = strings.Trim(t[1], " ")
case "name":
n++
endpoint.Name = strings.Trim(t[1], " ")
case "request":
n++
endpoint.Request = strings.Trim(t[1], " ")
case "response":
n++
endpoint.Response = strings.Trim(t[1], " ")
}
} else {
exitOnError(fmt.Errorf("wrong endpoint props: %s", s))
}
}
if endpoint.Method != "POST" && endpoint.Method != "GET" {
exitOnError(fmt.Errorf("wrong endpoint method: %s", s))
}
if endpoint.Method == "GET" && n < 4 {
exitOnError(fmt.Errorf("wrong endpoint number of props: %s", s))
}
if endpoint.Method == "POST" && n < 5 {
exitOnError(fmt.Errorf("wrong endpoint number of props: %s", s))
}
return endpoint
}
type tplData struct {
E *TSEndpoint
Path string
Params []string
}
func (e *TSEndpoint) VerifyTypes(info TSInfo, p string) {
a := strings.Split(e.Request, ".")
if e.Request != "" {
if len(a) == 2 {
e.RequestTs = a[1]
if strings.HasPrefix(a[1], "[]") {
a[1] = strings.TrimPrefix(a[1], "[]")
e.RequestTs = fmt.Sprintf("%s[]", a[1])
}
if strings.HasPrefix(a[1], "*") {
a[1] = strings.TrimPrefix(a[1], "*")
e.RequestTs = fmt.Sprintf("Nullable<%s>", a[1])
}
e.Request = fmt.Sprintf("%s.%s", a[0], a[1])
if !info.find(a[0], a[1]) {
exitOnError(fmt.Errorf("endpoint request not found: %s AT %s Line: %d ", e.Request, e.File, e.Line))
}
info.setTypescript(a[0], a[1], true)
}
if len(a) == 1 {
e.RequestTs = a[0]
if strings.HasPrefix(a[0], "[]") {
a[0] = strings.TrimPrefix(a[0], "[]")
e.RequestTs = fmt.Sprintf("%s[]", a[0])
}
if strings.HasPrefix(a[0], "*") {
a[0] = strings.TrimPrefix(a[0], "*")
e.RequestTs = fmt.Sprintf("Nullable<%s>", a[0])
}
e.Request = a[0]
}
}
a = strings.Split(e.Response, ".")
if len(a) == 2 {
if !info.find(a[0], a[1]) {
exitOnError(fmt.Errorf("endpoint response not found: %s AT %s Line: %d ", e.Request, e.File, e.Line))
}
e.ResponseTs = a[1]
if strings.HasPrefix(a[1], "[]") {
a[1] = strings.TrimPrefix(a[1], "[]")
e.ResponseTs = fmt.Sprintf("%s[]", a[1])
}
if strings.HasPrefix(a[1], "*") {
a[1] = strings.TrimPrefix(a[1], "*")
e.ResponseTs = fmt.Sprintf("Nullable<%s>", a[1])
}
e.Response = fmt.Sprintf("%s.%s", a[0], a[1])
}
if len(a) == 1 {
e.ResponseTs = a[0]
if strings.HasPrefix(a[0], "[]") {
a[0] = strings.TrimPrefix(a[0], "[]")
e.ResponseTs = fmt.Sprintf("%s[]", a[0])
}
if strings.HasPrefix(a[0], "*") {
a[0] = strings.TrimPrefix(a[0], "*")
e.ResponseTs = fmt.Sprintf("Nullable<%s>", a[0])
}
e.Response = a[0]
}
}
func (e *TSEndpoint) ToTs(pkg string) string {
data := tplData{E: e, Path: e.Path, Params: []string{}}
tpl := `
{{ .E.Source }}
// {{ .E.File }} Line: {{ .E.Line }}
{{if eq .E.Method "GET"}}export const {{ .E.Name}} = async ({{range $v := .Params}}{{$v}}{{end}}):Promise<{ data:{{.E.ResponseTs}}; error: Nullable<string> }> => {
return await api.GET({{ .Path}}) as { data: {{ .E.ResponseTs}}; error: Nullable<string> };
}{{end}}{{if eq .E.Method "POST"}}export const {{ .E.Name}} = async (data: {{ .E.RequestTs}}):Promise<{ data:{{.E.ResponseTs}}; error: Nullable<string> }> => {
return await api.POST("{{ .Path}}", data) as { data: {{ .E.ResponseTs}}; error: Nullable<string> };
}{{end}}`
if e.Method == "GET" {
a := strings.Split(e.Path, "/")
c := ""
f := false
for _, v := range a {
if len(v) == 0 {
continue
}
prefix := v[0:1]
if f {
c = ", "
}
if prefix == ":" {
f = true
data.Params = append(data.Params, fmt.Sprintf("%s%s: string", c, v[1:]))
data.Path = strings.Replace(data.Path, v, fmt.Sprintf("${%s}", v[1:]), 1)
} else if prefix == "*" {
f = true
data.Params = append(data.Params, fmt.Sprintf("%s%s: Nullable<string>", c, v[1:]))
data.Path = strings.Replace(data.Path, v, fmt.Sprintf("${%s}", v[1:]), 1)
}
}
if len(data.Params) > 0 {
data.Path = fmt.Sprintf("`%s`", data.Path)
} else {
data.Path = fmt.Sprintf("\"%s\"", data.Path)
}
}
t, err := template.New("test").Parse(tpl)
if err != nil {
panic(err)
}
var result bytes.Buffer
err = t.Execute(&result, data)
if err != nil {
panic(err)
}
return result.String()
}