mirror of
https://github.com/wailsapp/wails.git
synced 2025-05-02 23:39:21 +08:00
235 lines
6.3 KiB
Go
235 lines
6.3 KiB
Go
package binding
|
|
|
|
import (
|
|
"bytes"
|
|
_ "embed"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/wailsapp/wails/v2/internal/fs"
|
|
|
|
"github.com/leaanthony/slicer"
|
|
)
|
|
|
|
//go:embed assets/package.json
|
|
var packageJSON []byte
|
|
|
|
func (b *Bindings) GenerateBackendJS(targetfile string, isDevBindings bool) error {
|
|
|
|
store := b.db.store
|
|
var output bytes.Buffer
|
|
|
|
output.WriteString(`// @ts-check
|
|
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
|
// This file is automatically generated. DO NOT EDIT
|
|
`)
|
|
|
|
if isDevBindings {
|
|
json, err := b.ToJSON()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
output.WriteString("window.wailsbindings = " + json + ";")
|
|
output.WriteString("\n")
|
|
}
|
|
|
|
output.WriteString(`const go = {`)
|
|
output.WriteString("\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(" /**\n")
|
|
output.WriteString(" * " + methodName + "\n")
|
|
var args slicer.StringSlicer
|
|
for count, input := range methodDetails.Inputs {
|
|
arg := fmt.Sprintf("arg%d", count+1)
|
|
args.Add(arg)
|
|
output.WriteString(fmt.Sprintf(" * @param {%s} %s - Go Type: %s\n", goTypeToJSDocType(input.TypeName), arg, input.TypeName))
|
|
}
|
|
returnType := "Promise"
|
|
returnTypeDetails := ""
|
|
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 += ">"
|
|
returnTypeDetails = " - Go Type: " + methodDetails.Outputs[0].TypeName
|
|
} else {
|
|
returnType = "Promise<void>"
|
|
}
|
|
output.WriteString(" * @returns {" + returnType + "} " + returnTypeDetails + "\n")
|
|
output.WriteString(" */\n")
|
|
argsString := args.Join(", ")
|
|
output.WriteString(fmt.Sprintf(" \"%s\": (%s) => {", methodName, argsString))
|
|
output.WriteString("\n")
|
|
output.WriteString(fmt.Sprintf(" return window.go.%s.%s.%s(%s);", packageName, structName, methodName, argsString))
|
|
output.WriteString("\n")
|
|
output.WriteString(fmt.Sprintf(" },"))
|
|
output.WriteString("\n")
|
|
|
|
})
|
|
|
|
output.WriteString(" },\n")
|
|
})
|
|
|
|
output.WriteString(" },\n\n")
|
|
})
|
|
|
|
output.WriteString(`};
|
|
export default go;`)
|
|
output.WriteString("\n")
|
|
|
|
dir := filepath.Dir(targetfile)
|
|
packageJsonFile := filepath.Join(dir, "package.json")
|
|
if !fs.FileExists(packageJsonFile) {
|
|
err := os.WriteFile(packageJsonFile, packageJSON, 0755)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
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("export 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 + ":" + goTypeToTypescriptType(input.TypeName))
|
|
}
|
|
output.WriteString(args.Join(",") + "):")
|
|
returnType := "Promise"
|
|
if methodDetails.OutputCount() > 0 {
|
|
firstType := goTypeToTypescriptType(methodDetails.Outputs[0].TypeName)
|
|
returnType += "<" + firstType
|
|
if methodDetails.OutputCount() == 2 {
|
|
secondType := goTypeToTypescriptType(methodDetails.Outputs[1].TypeName)
|
|
returnType += "|" + secondType
|
|
}
|
|
returnType += ">"
|
|
} else {
|
|
returnType = "Promise<void>"
|
|
}
|
|
output.WriteString(returnType + "\n")
|
|
})
|
|
|
|
output.WriteString(" },\n")
|
|
})
|
|
output.WriteString(" }\n\n")
|
|
})
|
|
output.WriteString("}\n")
|
|
|
|
globals := `
|
|
declare global {
|
|
interface Window {
|
|
go: go;
|
|
}
|
|
}
|
|
`
|
|
output.WriteString(globals)
|
|
return os.WriteFile(targetfile, output.Bytes(), 0755)
|
|
}
|
|
|
|
func goTypeToJSDocType(input string) string {
|
|
switch true {
|
|
case input == "string":
|
|
return "string"
|
|
case input == "error":
|
|
return "Error"
|
|
case
|
|
strings.HasPrefix(input, "int"),
|
|
strings.HasPrefix(input, "uint"),
|
|
strings.HasPrefix(input, "float"):
|
|
return "number"
|
|
case input == "bool":
|
|
return "boolean"
|
|
case input == "[]byte":
|
|
return "string"
|
|
case strings.HasPrefix(input, "[]"):
|
|
arrayType := goTypeToJSDocType(input[2:])
|
|
return "Array<" + arrayType + ">"
|
|
default:
|
|
if strings.ContainsRune(input, '.') {
|
|
return strings.Split(input, ".")[1]
|
|
}
|
|
return "any"
|
|
}
|
|
}
|
|
|
|
func goTypeToTypescriptType(input string) string {
|
|
if strings.HasPrefix(input, "[]") {
|
|
arrayType := goTypeToJSDocType(input[2:])
|
|
return "Array<" + arrayType + ">"
|
|
}
|
|
return goTypeToJSDocType(input)
|
|
}
|