mirror of
https://github.com/foomo/gotsrpc.git
synced 2025-10-16 12:35:35 +00:00
preparing better demo
This commit is contained in:
parent
eff3d56c95
commit
df6b3449b1
@ -83,7 +83,7 @@ func main() {
|
||||
fmt.Fprintln(os.Stderr, "an error occured while trying to understand your code", err)
|
||||
os.Exit(2)
|
||||
}
|
||||
ts, err := gotsrpc.RenderTypeScript(services, structs, target.TypeScriptModule)
|
||||
ts, err := gotsrpc.RenderTypeScriptServices(services, conf.Mappings, target.TypeScriptModule)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, "could not generate ts code", err)
|
||||
os.Exit(3)
|
||||
@ -91,6 +91,17 @@ func main() {
|
||||
|
||||
fmt.Println(os.Stdout, ts)
|
||||
|
||||
mappedCode, err := gotsrpc.RenderStructsToPackages(structs, conf.Mappings)
|
||||
if err != nil {
|
||||
fmt.Println("struct gen err", err)
|
||||
os.Exit(4)
|
||||
}
|
||||
|
||||
for tsModule, code := range mappedCode {
|
||||
fmt.Println("-----------------", tsModule, "--------------------")
|
||||
fmt.Println(code)
|
||||
}
|
||||
|
||||
gocode, goerr := gotsrpc.RenderGo(services, packageName)
|
||||
if goerr != nil {
|
||||
fmt.Fprintln(os.Stderr, "could not generate go code", goerr)
|
||||
|
||||
@ -19,9 +19,11 @@ type Mapping struct {
|
||||
TypeScriptModule string `yaml:"module"`
|
||||
}
|
||||
|
||||
type TypeScriptMappings map[string]*Mapping
|
||||
|
||||
type Config struct {
|
||||
Targets map[string]*Target
|
||||
Mappings map[string]*Mapping
|
||||
Mappings TypeScriptMappings
|
||||
}
|
||||
|
||||
func LoadConfigFile(file string) (conf *Config, err error) {
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
---
|
||||
targets:
|
||||
demo:
|
||||
module: GoTSRPC.Demo
|
||||
services:
|
||||
- Service
|
||||
package: github.com/foomo/gotsrpc/demo
|
||||
@ -9,3 +10,6 @@ mappings:
|
||||
github.com/foomo/gotsrpc/demo:
|
||||
module: GoTSRPC.Demo
|
||||
out: /tmp/test-files.ts
|
||||
github.com/foomo/gotsrpc/demo/nested:
|
||||
module: GoTSRPC.Demo.Nested
|
||||
out: /tmp/test-files.ts
|
||||
@ -2,30 +2,48 @@
|
||||
package demo
|
||||
|
||||
import (
|
||||
"github.com/foomo/gotsrpc"
|
||||
"net/http"
|
||||
gotsrpc "github.com/foomo/gotsrpc"
|
||||
demo "github.com/foomo/gotsrpc/demo"
|
||||
http "net/http"
|
||||
)
|
||||
|
||||
type ServiceGoTSRPCProxy struct {
|
||||
EndPoint string
|
||||
service *Service
|
||||
EndPoint string
|
||||
allowOrigin []string
|
||||
service *Service
|
||||
}
|
||||
|
||||
func NewServiceGoTSRPCProxy(service *Service, endpoint string) *ServiceGoTSRPCProxy {
|
||||
func NewServiceGoTSRPCProxy(service *Service, endpoint string, allowOrigin []string) *ServiceGoTSRPCProxy {
|
||||
return &ServiceGoTSRPCProxy{
|
||||
EndPoint: endpoint,
|
||||
service: service,
|
||||
EndPoint: endpoint,
|
||||
allowOrigin: allowOrigin,
|
||||
service: service,
|
||||
}
|
||||
}
|
||||
|
||||
// ServeHTTP exposes your service
|
||||
func (p *ServiceGoTSRPCProxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
for _, origin := range p.allowOrigin {
|
||||
w.Header().Add("Access-Control-Allow-Origin", origin)
|
||||
}
|
||||
w.Header().Set("Access-Control-Allow-Credentials", "true")
|
||||
if r.Method != "POST" {
|
||||
gotsrpc.ErrorMethodNotAllowed(w)
|
||||
return
|
||||
}
|
||||
var args []interface{}
|
||||
switch gotsrpc.GetCalledFunc(r, p.EndPoint) {
|
||||
case "ExtractAddress":
|
||||
args = []interface{}{&Person{}}
|
||||
err := gotsrpc.LoadArgs(args, r)
|
||||
if err != nil {
|
||||
gotsrpc.ErrorCouldNotLoadArgs(w)
|
||||
return
|
||||
}
|
||||
extractAddressAddr, extractAddressE := p.service.ExtractAddress(args[0].(*demo.Person))
|
||||
gotsrpc.Reply([]interface{}{extractAddressAddr, extractAddressE}, w)
|
||||
return
|
||||
case "Hello":
|
||||
args = []interface{}{""}
|
||||
err := gotsrpc.LoadArgs(args, r)
|
||||
@ -40,48 +58,5 @@ func (p *ServiceGoTSRPCProxy) ServeHTTP(w http.ResponseWriter, r *http.Request)
|
||||
p.service.NothingInNothinOut()
|
||||
gotsrpc.Reply([]interface{}{}, w)
|
||||
return
|
||||
case "ExtractAddress":
|
||||
args = []interface{}{&Person{}}
|
||||
err := gotsrpc.LoadArgs(args, r)
|
||||
if err != nil {
|
||||
gotsrpc.ErrorCouldNotLoadArgs(w)
|
||||
return
|
||||
}
|
||||
extractAddressAddr, extractAddressE := p.service.ExtractAddress(args[0].(*Person))
|
||||
gotsrpc.Reply([]interface{}{extractAddressAddr, extractAddressE}, w)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
type FooGoTSRPCProxy struct {
|
||||
EndPoint string
|
||||
service *Foo
|
||||
}
|
||||
|
||||
func NewFooGoTSRPCProxy(service *Foo, endpoint string) *FooGoTSRPCProxy {
|
||||
return &FooGoTSRPCProxy{
|
||||
EndPoint: endpoint,
|
||||
service: service,
|
||||
}
|
||||
}
|
||||
|
||||
// ServeHTTP exposes your service
|
||||
func (p *FooGoTSRPCProxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != "POST" {
|
||||
gotsrpc.ErrorMethodNotAllowed(w)
|
||||
return
|
||||
}
|
||||
var args []interface{}
|
||||
switch gotsrpc.GetCalledFunc(r, p.EndPoint) {
|
||||
case "Hello":
|
||||
args = []interface{}{int64(0)}
|
||||
err := gotsrpc.LoadArgs(args, r)
|
||||
if err != nil {
|
||||
gotsrpc.ErrorCouldNotLoadArgs(w)
|
||||
return
|
||||
}
|
||||
helloRet := p.service.Hello(args[0].(int64))
|
||||
gotsrpc.Reply([]interface{}{helloRet}, w)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
10
go.go
10
go.go
@ -70,14 +70,6 @@ func ucfirst(str string) string {
|
||||
}
|
||||
|
||||
func strfirst(str string, strfunc func(string) string) string {
|
||||
/*
|
||||
if len(str) == 0 {
|
||||
return ""
|
||||
} else if len(str) == 1 {
|
||||
return strfunc(str)
|
||||
}
|
||||
return strfunc(str[0:1]) + str[1:]
|
||||
*/
|
||||
res := ""
|
||||
for i, char := range str {
|
||||
if i == 0 {
|
||||
@ -190,11 +182,9 @@ func renderServiceProxies(services []*Service, packageName string, g *code) erro
|
||||
for argI, arg := range method.Args {
|
||||
|
||||
if argI == 0 && arg.Value.isHTTPResponseWriter() {
|
||||
trace("skipping first arg is a http.ResponseWriter")
|
||||
continue
|
||||
}
|
||||
if argI == 1 && arg.Value.isHTTPRequest() {
|
||||
trace("skipping second arg is a *http.Request")
|
||||
isSessionRequest = true
|
||||
continue
|
||||
}
|
||||
|
||||
@ -154,7 +154,6 @@ func Read(goPath string, packageName string, serviceNames []string) (services []
|
||||
return
|
||||
}
|
||||
|
||||
jsonTrace(services)
|
||||
structTypes := map[string]*StructType{}
|
||||
for _, s := range services {
|
||||
for _, m := range s.Methods {
|
||||
@ -162,7 +161,6 @@ func Read(goPath string, packageName string, serviceNames []string) (services []
|
||||
collecStructTypes(m.Args, structTypes)
|
||||
}
|
||||
}
|
||||
jsonTrace(structTypes)
|
||||
structs = map[string]*Struct{}
|
||||
for wantedName := range structTypes {
|
||||
structs[wantedName] = nil
|
||||
@ -172,13 +170,13 @@ func Read(goPath string, packageName string, serviceNames []string) (services []
|
||||
|
||||
err = errors.New("error while collecting structs: " + collectErr.Error())
|
||||
}
|
||||
jsonTrace(structs)
|
||||
return
|
||||
}
|
||||
|
||||
func collectStructs(goPath string, structs map[string]*Struct) error {
|
||||
scannedPackages := map[string]map[string]*Struct{}
|
||||
for structsPending(structs) {
|
||||
trace("pending", len(structs))
|
||||
for fullName, strct := range structs {
|
||||
if strct != nil {
|
||||
continue
|
||||
@ -190,7 +188,7 @@ func collectStructs(goPath string, structs map[string]*Struct) error {
|
||||
|
||||
packageName := strings.Join(fullNameParts, ".")
|
||||
|
||||
//trace(fullName, "==========================>", fullNameParts, "=============>", packageName)
|
||||
// trace(fullName, "==========================>", fullNameParts, "=============>", packageName)
|
||||
|
||||
packageStructs, ok := scannedPackages[packageName]
|
||||
if !ok {
|
||||
@ -202,6 +200,7 @@ func collectStructs(goPath string, structs map[string]*Struct) error {
|
||||
scannedPackages[packageName] = packageStructs
|
||||
}
|
||||
for packageStructName, packageStruct := range packageStructs {
|
||||
// trace("------------------------------------>", packageStructName, packageStruct)
|
||||
existingStruct, needed := structs[packageStructName]
|
||||
if needed && existingStruct == nil {
|
||||
structs[packageStructName] = packageStruct
|
||||
@ -213,8 +212,12 @@ func collectStructs(goPath string, structs map[string]*Struct) error {
|
||||
}
|
||||
|
||||
func structsPending(structs map[string]*Struct) bool {
|
||||
for _, structType := range structs {
|
||||
if structType == nil || !structType.DepsSatisfied(structs) {
|
||||
for name, structType := range structs {
|
||||
if structType == nil {
|
||||
trace("missing", name)
|
||||
return true
|
||||
}
|
||||
if !structType.DepsSatisfied(structs) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@ -227,10 +230,11 @@ func (s *Struct) DepsSatisfied(structs map[string]*Struct) bool {
|
||||
if !ok {
|
||||
// hey there is more todo
|
||||
structs[fullName] = nil
|
||||
trace("need work ----------------------" + fullName)
|
||||
return true
|
||||
}
|
||||
if strct == nil {
|
||||
trace("need work " + fullName)
|
||||
trace("need work ----------------------" + fullName)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
@ -249,7 +253,6 @@ func (s *Struct) DepsSatisfied(structs map[string]*Struct) bool {
|
||||
if needsWork(fieldStructType.FullName()) {
|
||||
return false
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return !needsWork(s.FullName())
|
||||
@ -277,7 +280,6 @@ func getStructsInPackage(goPath string, packageName string) (structs map[string]
|
||||
pkg, err = parsePackage(runtime.GOROOT(), packageName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
}
|
||||
}
|
||||
structs, err = readStructs(pkg, packageName)
|
||||
|
||||
@ -30,7 +30,7 @@ func trace(args ...interface{}) {
|
||||
fmt.Fprintln(os.Stderr, args...)
|
||||
}
|
||||
}
|
||||
func jsonTrace(args ...interface{}) {
|
||||
func traceJSON(args ...interface{}) {
|
||||
if ReaderTrace {
|
||||
for _, arg := range args {
|
||||
jsonBytes, jsonErr := json.MarshalIndent(arg, "", " ")
|
||||
@ -231,7 +231,7 @@ func readField(astField *ast.Field, fileImports fileImportSpecMap) (name string,
|
||||
name = astField.Names[0].Name
|
||||
}
|
||||
|
||||
trace(" reading field with name", name, "of type", astField.Type)
|
||||
// trace(" reading field with name", name, "of type", astField.Type)
|
||||
v = &Value{}
|
||||
v.loadExpr(astField.Type, fileImports)
|
||||
if astField.Tag != nil {
|
||||
@ -264,11 +264,7 @@ func readFieldList(fieldList []*ast.Field, fileImports fileImportSpecMap) (field
|
||||
}
|
||||
|
||||
func extractStructs(file *ast.File, packageName string, structs map[string]*Struct) error {
|
||||
|
||||
trace("reading file", file.Name.Name)
|
||||
//for _, imp := range file.Imports {
|
||||
// fmt.Println("import", imp.Name, imp.Path)
|
||||
//}
|
||||
fileImports := getFileImports(file, packageName)
|
||||
for name, obj := range file.Scope.Objects {
|
||||
//fmt.Println(name, obj.Kind, obj.Data)
|
||||
|
||||
@ -4,6 +4,8 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/foomo/gotsrpc/config"
|
||||
)
|
||||
|
||||
func (f *Field) tsName() string {
|
||||
@ -14,18 +16,23 @@ func (f *Field) tsName() string {
|
||||
return n
|
||||
}
|
||||
|
||||
func (v *Value) tsType() string {
|
||||
func (v *Value) tsType(mappings config.TypeScriptMappings) string {
|
||||
switch true {
|
||||
case v.IsPtr:
|
||||
if v.StructType != nil {
|
||||
if len(v.StructType.Package) > 0 {
|
||||
return v.StructType.Package + "." + v.StructType.Name
|
||||
mapping, ok := mappings[v.StructType.Package]
|
||||
var tsModule string
|
||||
if ok {
|
||||
tsModule = mapping.TypeScriptModule
|
||||
}
|
||||
return tsModule + "." + v.StructType.Name
|
||||
}
|
||||
return v.StructType.Name
|
||||
}
|
||||
return string(v.ScalarType)
|
||||
case v.Array != nil:
|
||||
return v.Array.Value.tsType() + "[]"
|
||||
return v.Array.Value.tsType(mappings) + "[]"
|
||||
case len(v.ScalarType) > 0:
|
||||
switch v.ScalarType {
|
||||
case ScalarTypeBool:
|
||||
@ -39,8 +46,8 @@ func (v *Value) tsType() string {
|
||||
}
|
||||
}
|
||||
|
||||
func renderStruct(str *Struct, ts *code) error {
|
||||
ts.l("// " + str.Package + "." + str.Name).ind(1)
|
||||
func renderStruct(str *Struct, mappings config.TypeScriptMappings, ts *code) error {
|
||||
ts.l("// " + str.FullName())
|
||||
ts.l("export interface " + str.Name + " {").ind(1)
|
||||
for _, f := range str.Fields {
|
||||
if f.JSONInfo != nil && f.JSONInfo.Ignore {
|
||||
@ -50,7 +57,7 @@ func renderStruct(str *Struct, ts *code) error {
|
||||
if f.Value.IsPtr {
|
||||
ts.app("?")
|
||||
}
|
||||
ts.app(":" + f.Value.tsType())
|
||||
ts.app(":" + f.Value.tsType(mappings))
|
||||
ts.app(";")
|
||||
ts.nl()
|
||||
}
|
||||
@ -68,7 +75,7 @@ func renderStruct(str *Struct, ts *code) error {
|
||||
}
|
||||
*/
|
||||
|
||||
func renderService(service *Service, ts *code) error {
|
||||
func renderService(service *Service, mappings config.TypeScriptMappings, ts *code) error {
|
||||
clientName := service.Name + "Client"
|
||||
ts.l("export class " + clientName + " {").ind(1).
|
||||
l("static defaultInst = new " + clientName + ";").
|
||||
@ -90,7 +97,7 @@ func renderService(service *Service, ts *code) error {
|
||||
continue
|
||||
}
|
||||
|
||||
args = append(args, arg.tsName()+":"+arg.Value.tsType())
|
||||
args = append(args, arg.tsName()+":"+arg.Value.tsType(mappings))
|
||||
callArgs = append(callArgs, arg.Name)
|
||||
}
|
||||
ts.app(strings.Join(args, ", "))
|
||||
@ -104,7 +111,7 @@ func renderService(service *Service, ts *code) error {
|
||||
retArgName += "_" + fmt.Sprint(index)
|
||||
}
|
||||
}
|
||||
retArgs = append(retArgs, retArgName+":"+retField.Value.tsType())
|
||||
retArgs = append(retArgs, retArgName+":"+retField.Value.tsType(mappings))
|
||||
}
|
||||
if len(args) > 0 {
|
||||
ts.app(", ")
|
||||
@ -122,8 +129,33 @@ func renderService(service *Service, ts *code) error {
|
||||
ts.l("}")
|
||||
return nil
|
||||
}
|
||||
|
||||
func RenderTypeScript(services []*Service, structs map[string]*Struct, tsModuleName string) (typeScript string, err error) {
|
||||
func RenderStructsToPackages(structs map[string]*Struct, mappings config.TypeScriptMappings) (mappedTypeScript map[string]string, err error) {
|
||||
mappedTypeScript = map[string]string{}
|
||||
codeMap := map[string]*code{}
|
||||
for _, mapping := range mappings {
|
||||
codeMap[mapping.GoPackage] = newCode().l("module " + mapping.TypeScriptModule + " {").ind(1)
|
||||
}
|
||||
for name, str := range structs {
|
||||
if str == nil {
|
||||
err = errors.New("could not resolve: " + name)
|
||||
return
|
||||
}
|
||||
ts, ok := codeMap[str.Package]
|
||||
if !ok {
|
||||
err = errors.New("missing code mapping for: " + str.Package)
|
||||
return
|
||||
}
|
||||
err = renderStruct(str, mappings, ts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
for _, mapping := range mappings {
|
||||
mappedTypeScript[mapping.TypeScriptModule] = codeMap[mapping.GoPackage].ind(-1).l("}").string()
|
||||
}
|
||||
return
|
||||
}
|
||||
func RenderTypeScriptServices(services []*Service, mappings config.TypeScriptMappings, tsModuleName string) (typeScript string, err error) {
|
||||
ts := newCode()
|
||||
ts.l(`module GoTSRPC {
|
||||
export function call(endPoint:string, method:string, args:any[], success:any, err:any) {
|
||||
@ -153,18 +185,8 @@ func RenderTypeScript(services []*Service, structs map[string]*Struct, tsModuleN
|
||||
ts.l("module " + tsModuleName + " {")
|
||||
ts.ind(1)
|
||||
|
||||
for name, str := range structs {
|
||||
if str == nil {
|
||||
return "", errors.New("could not resolve: " + name)
|
||||
}
|
||||
err = renderStruct(str, ts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
for _, service := range services {
|
||||
err = renderService(service, ts)
|
||||
err = renderService(service, mappings, ts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user