diff --git a/v2/internal/appng/app_bindings.go b/v2/internal/appng/app_bindings.go index 097606770..563dff791 100644 --- a/v2/internal/appng/app_bindings.go +++ b/v2/internal/appng/app_bindings.go @@ -103,6 +103,12 @@ func generateBindings(bindings *binding.Bindings) error { return err } + bindingsTypes := filepath.Join(targetDir, "bindings.d.ts") + err = bindings.GenerateBackendTS(bindingsTypes) + if err != nil { + return err + } + return nil } diff --git a/v2/internal/appng/app_dev.go b/v2/internal/appng/app_dev.go index ee501c25f..b232e21dc 100644 --- a/v2/internal/appng/app_dev.go +++ b/v2/internal/appng/app_dev.go @@ -193,6 +193,13 @@ func generateBindings(bindings *binding.Bindings) error { if err != nil { return err } + + bindingsTypes := filepath.Join(targetDir, "bindings.d.ts") + err = bindings.GenerateBackendTS(bindingsTypes) + if err != nil { + return err + } + return nil } diff --git a/v2/internal/binding/generate.go b/v2/internal/binding/generate.go index dd90f2ae0..5546b950b 100644 --- a/v2/internal/binding/generate.go +++ b/v2/internal/binding/generate.go @@ -122,6 +122,83 @@ export default go;`) return os.WriteFile(targetfile, output.Bytes(), 0755) } +// GenerateBackendTS generates typescript bindings for +// the bound methods. +func (b *Bindings) GenerateBackendTS(targetfile string) error { + + store := b.db.store + var output bytes.Buffer + + output.WriteString("interface go {\n") + + var sortedPackageNames slicer.StringSlicer + for packageName := range store { + sortedPackageNames.Add(packageName) + } + sortedPackageNames.Sort() + sortedPackageNames.Each(func(packageName string) { + packages := store[packageName] + output.WriteString(fmt.Sprintf(" \"%s\": {", packageName)) + output.WriteString("\n") + var sortedStructNames slicer.StringSlicer + for structName := range packages { + sortedStructNames.Add(structName) + } + sortedStructNames.Sort() + + sortedStructNames.Each(func(structName string) { + structs := packages[structName] + output.WriteString(fmt.Sprintf(" \"%s\": {", structName)) + output.WriteString("\n") + + var sortedMethodNames slicer.StringSlicer + for methodName := range structs { + sortedMethodNames.Add(methodName) + } + sortedMethodNames.Sort() + + sortedMethodNames.Each(func(methodName string) { + methodDetails := structs[methodName] + output.WriteString(fmt.Sprintf("\t\t%s(", methodName)) + + var args slicer.StringSlicer + for count, input := range methodDetails.Inputs { + arg := fmt.Sprintf("arg%d", count+1) + args.Add(arg + ":" + goTypeToJSDocType(input.TypeName)) + } + output.WriteString(args.Join(",") + "):") + returnType := "Promise" + if methodDetails.OutputCount() > 0 { + firstType := goTypeToJSDocType(methodDetails.Outputs[0].TypeName) + returnType += "<" + firstType + if methodDetails.OutputCount() == 2 { + secondType := goTypeToJSDocType(methodDetails.Outputs[1].TypeName) + returnType += "|" + secondType + } + returnType += ">" + } else { + returnType = "Promise" + } + output.WriteString(returnType + "\n") + }) + + output.WriteString(" },\n") + }) + output.WriteString(" }\n\n") + }) + output.WriteString("}\n") + + globals := ` +declare global { + interface Window { + go: go; + } +} +export {};` + output.WriteString(globals) + return os.WriteFile(targetfile, output.Bytes(), 0755) +} + func goTypeToJSDocType(input string) string { switch true { case input == "string":