mirror of
https://github.com/wailsapp/wails.git
synced 2025-05-03 04:11:05 +08:00
Improved bindings generation
This commit is contained in:
parent
d119fce3c3
commit
4721949657
@ -4,6 +4,9 @@
|
||||
package appng
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/leaanthony/gosod"
|
||||
"github.com/wailsapp/wails/v2/internal/binding"
|
||||
wailsRuntime "github.com/wailsapp/wails/v2/internal/frontend/runtime"
|
||||
@ -12,8 +15,6 @@ import (
|
||||
"github.com/wailsapp/wails/v2/internal/logger"
|
||||
"github.com/wailsapp/wails/v2/internal/project"
|
||||
"github.com/wailsapp/wails/v2/pkg/options"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// App defines a Wails application structure
|
||||
@ -96,6 +97,10 @@ func generateBindings(bindings *binding.Bindings) error {
|
||||
return err
|
||||
}
|
||||
|
||||
err = bindings.GenerateGoBindings(targetDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Write backend method wrappers
|
||||
bindingsFilename := filepath.Join(targetDir, "bindings.js")
|
||||
err = bindings.GenerateBackendJS(bindingsFilename)
|
||||
|
@ -225,6 +225,11 @@ func generateBindings(bindings *binding.Bindings) error {
|
||||
return err
|
||||
}
|
||||
|
||||
err = bindings.GenerateGoBindings(targetDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Write backend method wrappers
|
||||
bindingsFilename := filepath.Join(targetDir, "bindings.js")
|
||||
err = bindings.GenerateBackendJS(bindingsFilename)
|
||||
|
@ -14,6 +14,7 @@ type BoundMethod struct {
|
||||
Outputs []*Parameter `json:"outputs,omitempty"`
|
||||
Comments string `json:"comments,omitempty"`
|
||||
Method reflect.Value `json:"-"`
|
||||
StructNames []string `json:"structNames"`
|
||||
}
|
||||
|
||||
// InputCount returns the number of inputs this bound method has
|
||||
|
@ -16,6 +16,83 @@ import (
|
||||
//go:embed assets/package.json
|
||||
var packageJSON []byte
|
||||
|
||||
func (b *Bindings) GenerateGoBindings(baseDir string) error {
|
||||
store := b.db.store
|
||||
for packageName, structs := range store {
|
||||
packageDir := filepath.Join(baseDir, packageName)
|
||||
err := fs.Mkdir(packageDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for structName, methods := range structs {
|
||||
var jsoutput bytes.Buffer
|
||||
jsoutput.WriteString(`// @ts-check
|
||||
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
||||
// This file is automatically generated. DO NOT EDIT
|
||||
`)
|
||||
var tsoutput bytes.Buffer
|
||||
tsoutput.WriteString(`// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
||||
// This file is automatically generated. DO NOT EDIT
|
||||
`)
|
||||
for methodName, methodDetails := range methods {
|
||||
|
||||
// Generate JS
|
||||
var args slicer.StringSlicer
|
||||
for count := range methodDetails.Inputs {
|
||||
arg := fmt.Sprintf("arg%d", count+1)
|
||||
args.Add(arg)
|
||||
}
|
||||
argsString := args.Join(", ")
|
||||
jsoutput.WriteString(fmt.Sprintf("\nexport function %s(%s) {", methodName, argsString))
|
||||
jsoutput.WriteString("\n")
|
||||
jsoutput.WriteString(fmt.Sprintf(" return window['go']['%s']['%s']['%s'](%s);", packageName, structName, methodName, argsString))
|
||||
jsoutput.WriteString("\n")
|
||||
jsoutput.WriteString(fmt.Sprintf("}"))
|
||||
jsoutput.WriteString("\n")
|
||||
|
||||
// Generate TS
|
||||
|
||||
if len(methodDetails.StructNames) > 0 {
|
||||
classes := strings.Join(methodDetails.StructNames, ", ")
|
||||
tsoutput.WriteString("import {" + classes + "} from '../models';")
|
||||
}
|
||||
tsoutput.WriteString(fmt.Sprintf("\nexport function %s(", methodName))
|
||||
|
||||
args.Clear()
|
||||
for count, input := range methodDetails.Inputs {
|
||||
arg := fmt.Sprintf("arg%d", count+1)
|
||||
args.Add(arg + ":" + goTypeToTypescriptType(input.TypeName, false))
|
||||
}
|
||||
tsoutput.WriteString(args.Join(",") + "):")
|
||||
returnType := "Promise"
|
||||
if methodDetails.OutputCount() > 0 {
|
||||
firstType := goTypeToTypescriptType(methodDetails.Outputs[0].TypeName, false)
|
||||
returnType += "<" + firstType
|
||||
if methodDetails.OutputCount() == 2 {
|
||||
secondType := goTypeToTypescriptType(methodDetails.Outputs[1].TypeName, false)
|
||||
returnType += "|" + secondType
|
||||
}
|
||||
returnType += ">"
|
||||
} else {
|
||||
returnType = "Promise<void>"
|
||||
}
|
||||
tsoutput.WriteString(returnType + ";\n")
|
||||
}
|
||||
jsfilename := filepath.Join(packageDir, structName+".js")
|
||||
err = os.WriteFile(jsfilename, jsoutput.Bytes(), 0755)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tsfilename := filepath.Join(packageDir, structName+".d.ts")
|
||||
err = os.WriteFile(tsfilename, tsoutput.Bytes(), 0755)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Bindings) GenerateBackendJS(targetfile string) error {
|
||||
|
||||
store := b.db.store
|
||||
@ -24,6 +101,13 @@ func (b *Bindings) GenerateBackendJS(targetfile string) error {
|
||||
output.WriteString(`// @ts-check
|
||||
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
||||
// This file is automatically generated. DO NOT EDIT
|
||||
|
||||
// ************************************************
|
||||
// This file is deprecated and will not be generated
|
||||
// in the next version of Wails. Bindings are now
|
||||
// generated in their own files.
|
||||
// ************************************************
|
||||
|
||||
`)
|
||||
|
||||
output.WriteString(`const go = {`)
|
||||
@ -63,15 +147,15 @@ func (b *Bindings) GenerateBackendJS(targetfile string) error {
|
||||
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))
|
||||
output.WriteString(fmt.Sprintf(" * @param {%s} %s - Go Type: %s\n", goTypeToJSDocType(input.TypeName, true), arg, input.TypeName))
|
||||
}
|
||||
returnType := "Promise"
|
||||
returnTypeDetails := ""
|
||||
if methodDetails.OutputCount() > 0 {
|
||||
firstType := goTypeToJSDocType(methodDetails.Outputs[0].TypeName)
|
||||
firstType := goTypeToJSDocType(methodDetails.Outputs[0].TypeName, true)
|
||||
returnType += "<" + firstType
|
||||
if methodDetails.OutputCount() == 2 {
|
||||
secondType := goTypeToJSDocType(methodDetails.Outputs[1].TypeName)
|
||||
secondType := goTypeToJSDocType(methodDetails.Outputs[1].TypeName, true)
|
||||
returnType += "|" + secondType
|
||||
}
|
||||
returnType += ">"
|
||||
@ -120,6 +204,16 @@ func (b *Bindings) GenerateBackendTS(targetfile string) error {
|
||||
store := b.db.store
|
||||
var output bytes.Buffer
|
||||
|
||||
output.WriteString(`
|
||||
|
||||
// ************************************************
|
||||
// This file is deprecated and will not be generated
|
||||
// in the next version of Wails. Bindings are now
|
||||
// generated in their own files.
|
||||
// ************************************************
|
||||
|
||||
`)
|
||||
|
||||
output.WriteString("import * as models from './models';\n\n")
|
||||
output.WriteString("export interface go {\n")
|
||||
|
||||
@ -140,7 +234,7 @@ func (b *Bindings) GenerateBackendTS(targetfile string) error {
|
||||
|
||||
sortedStructNames.Each(func(structName string) {
|
||||
structs := packages[structName]
|
||||
output.WriteString(fmt.Sprintf(" \"models.%s\": {", structName))
|
||||
output.WriteString(fmt.Sprintf(" \"%s\": {", structName))
|
||||
output.WriteString("\n")
|
||||
|
||||
var sortedMethodNames slicer.StringSlicer
|
||||
@ -156,15 +250,15 @@ func (b *Bindings) GenerateBackendTS(targetfile string) error {
|
||||
var args slicer.StringSlicer
|
||||
for count, input := range methodDetails.Inputs {
|
||||
arg := fmt.Sprintf("arg%d", count+1)
|
||||
args.Add(arg + ":" + goTypeToTypescriptType(input.TypeName))
|
||||
args.Add(arg + ":" + goTypeToTypescriptType(input.TypeName, true))
|
||||
}
|
||||
output.WriteString(args.Join(",") + "):")
|
||||
returnType := "Promise"
|
||||
if methodDetails.OutputCount() > 0 {
|
||||
firstType := goTypeToTypescriptType(methodDetails.Outputs[0].TypeName)
|
||||
firstType := goTypeToTypescriptType(methodDetails.Outputs[0].TypeName, true)
|
||||
returnType += "<" + firstType
|
||||
if methodDetails.OutputCount() == 2 {
|
||||
secondType := goTypeToTypescriptType(methodDetails.Outputs[1].TypeName)
|
||||
secondType := goTypeToTypescriptType(methodDetails.Outputs[1].TypeName, true)
|
||||
returnType += "|" + secondType
|
||||
}
|
||||
returnType += ">"
|
||||
@ -191,7 +285,7 @@ declare global {
|
||||
return os.WriteFile(targetfile, output.Bytes(), 0755)
|
||||
}
|
||||
|
||||
func goTypeToJSDocType(input string) string {
|
||||
func goTypeToJSDocType(input string, useModelsNamespace bool) string {
|
||||
switch true {
|
||||
case input == "interface{}":
|
||||
return "any"
|
||||
@ -209,20 +303,23 @@ func goTypeToJSDocType(input string) string {
|
||||
case input == "[]byte":
|
||||
return "string"
|
||||
case strings.HasPrefix(input, "[]"):
|
||||
arrayType := goTypeToJSDocType(input[2:])
|
||||
arrayType := goTypeToJSDocType(input[2:], useModelsNamespace)
|
||||
return "Array<" + arrayType + ">"
|
||||
default:
|
||||
if strings.ContainsRune(input, '.') {
|
||||
if useModelsNamespace {
|
||||
return "models." + strings.Split(input, ".")[1]
|
||||
}
|
||||
return strings.Split(input, ".")[1]
|
||||
}
|
||||
return "any"
|
||||
}
|
||||
}
|
||||
|
||||
func goTypeToTypescriptType(input string) string {
|
||||
func goTypeToTypescriptType(input string, useModelsNamespace bool) string {
|
||||
if strings.HasPrefix(input, "[]") {
|
||||
arrayType := goTypeToJSDocType(input[2:])
|
||||
arrayType := goTypeToJSDocType(input[2:], useModelsNamespace)
|
||||
return "Array<" + arrayType + ">"
|
||||
}
|
||||
return goTypeToJSDocType(input)
|
||||
return goTypeToJSDocType(input, useModelsNamespace)
|
||||
}
|
||||
|
@ -91,6 +91,7 @@ func (b *Bindings) getMethods(value interface{}) ([]*BoundMethod, error) {
|
||||
a := reflect.New(typ)
|
||||
s := reflect.Indirect(a).Interface()
|
||||
b.converter.Add(s)
|
||||
boundMethod.StructNames = append(boundMethod.StructNames, thisInput.Name())
|
||||
}
|
||||
}
|
||||
|
||||
@ -99,6 +100,7 @@ func (b *Bindings) getMethods(value interface{}) ([]*BoundMethod, error) {
|
||||
a := reflect.New(thisInput)
|
||||
s := reflect.Indirect(a).Interface()
|
||||
b.converter.Add(s)
|
||||
boundMethod.StructNames = append(boundMethod.StructNames, thisInput.Name())
|
||||
}
|
||||
|
||||
inputs = append(inputs, thisParam)
|
||||
@ -128,6 +130,7 @@ func (b *Bindings) getMethods(value interface{}) ([]*BoundMethod, error) {
|
||||
a := reflect.New(typ)
|
||||
s := reflect.Indirect(a).Interface()
|
||||
b.converter.Add(s)
|
||||
boundMethod.StructNames = append(boundMethod.StructNames, thisOutput.Name())
|
||||
}
|
||||
}
|
||||
|
||||
@ -136,6 +139,7 @@ func (b *Bindings) getMethods(value interface{}) ([]*BoundMethod, error) {
|
||||
a := reflect.New(thisOutput)
|
||||
s := reflect.Indirect(a).Interface()
|
||||
b.converter.Add(s)
|
||||
boundMethod.StructNames = append(boundMethod.StructNames, thisOutput.Name())
|
||||
}
|
||||
|
||||
outputs = append(outputs, thisParam)
|
||||
|
Loading…
Reference in New Issue
Block a user