Skip to content

Commit

Permalink
[v3] Fix binding generator output and import paths (#3334)
Browse files Browse the repository at this point in the history
* Fix relative import path computation

* Fix models output path

* Add option to generate bindings using bundled runtime

* Update binding example

* Fix testdata

* Update changelog

---------

Co-authored-by: Lea Anthony <[email protected]>
  • Loading branch information
fbbdev and leaanthony authored Mar 22, 2024
1 parent f0986a6 commit 45b2681
Show file tree
Hide file tree
Showing 56 changed files with 364 additions and 372 deletions.
3 changes: 3 additions & 0 deletions mkdocs-website/docs/en/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Expose the `WebviewWindow.IsFocused` method on the `Window` interface by [@fbbdev](https://github.com/fbbdev) in [#3295](https://github.com/wailsapp/wails/pull/3295)
- Support multiple space-separated trigger events in the WML system by [@fbbdev](https://github.com/fbbdev) in [#3295](https://github.com/wailsapp/wails/pull/3295)
- Add ESM exports from the bundled JS runtime script by [@fbbdev](https://github.com/fbbdev) in [#3295](https://github.com/wailsapp/wails/pull/3295)
- Add binding generator flag for using the bundled JS runtime script instead of the npm package by [@fbbdev](https://github.com/fbbdev) in [#3334](https://github.com/wailsapp/wails/pull/3334)

### Fixed

Expand All @@ -51,6 +52,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Correctly compute `startURL` across multiple `GetStartURL` invocations when `FRONTEND_DEVSERVER_URL` is present. [#3299](https://github.com/wailsapp/wails/pull/3299)
- Fix the JS type of the `Screen` struct to match its Go counterpart by [@fbbdev](https://github.com/fbbdev) in [#3295](https://github.com/wailsapp/wails/pull/3295)
- Fix the `WML.Reload` method to ensure proper cleanup of registered event listeners by [@fbbdev](https://github.com/fbbdev) in [#3295](https://github.com/wailsapp/wails/pull/3295)
- Fix the output path and extension of model files produced by the binding generator by [@fbbdev](https://github.com/fbbdev) in [#3334](https://github.com/wailsapp/wails/pull/3334)
- Fix the import paths of model files in JS code produced by the binding generator by [@fbbdev](https://github.com/fbbdev) in [#3334](https://github.com/wailsapp/wails/pull/3334)

### Changed

Expand Down
8 changes: 3 additions & 5 deletions v3/examples/binding/GreetService.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package main

type Person struct {
name string
}
import "github.com/wailsapp/wails/v3/examples/binding/data"

// GreetService is a service that greets people
type GreetService struct {
Expand All @@ -14,6 +12,6 @@ func (*GreetService) Greet(name string) string {
}

// GreetPerson greets a person
func (*GreetService) GreetPerson(person Person) string {
return "Hello " + person.name
func (*GreetService) GreetPerson(person data.Person) string {
return "Hello " + person.Name
}
2 changes: 1 addition & 1 deletion v3/examples/binding/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

This example demonstrates how to generate bindings for your application.

To generate bindings, run `wails3 generate bindings -d assets` in this directory.
To generate bindings, run `wails3 generate bindings -b -d assets/bindings` in this directory.

See more options by running `wails3 generate bindings --help`.

Expand Down
28 changes: 28 additions & 0 deletions v3/examples/binding/assets/bindings/data/models.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// @ts-check
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT

// Person holds someone's most important attributes
export const Person = class {
/**
* Creates a new Person instance.
* @constructor
* @param {Object} source - The source object to create the Person.
* @param {string} source.Name
*/
constructor(source = {}) {
const { name = "" } = source;
this.name = name;
}

/**
* Creates a new Person instance from a string or object.
* @param {string|object} source - The source data to create a Person instance from.
* @returns {Person} A new Person instance.
*/
static createFrom(source) {
let parsedSource = typeof source === 'string' ? JSON.parse(source) : source;
return new Person(parsedSource);
}
};

28 changes: 28 additions & 0 deletions v3/examples/binding/assets/bindings/main/GreetService.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// @ts-check
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT

import {Call} from '/wails/runtime.js';
/**
* @typedef {import('../data/models').Person} dataPerson
*/

/**
* Greet greets a person
* @function Greet
* @param name {string}
* @returns {Promise<string>}
**/
export async function Greet(name) {
return Call.ByName("main.GreetService.Greet", ...Array.prototype.slice.call(arguments, 0));
}

/**
* GreetPerson greets a person
* @function GreetPerson
* @param person {dataPerson}
* @returns {Promise<string>}
**/
export async function GreetPerson(person) {
return Call.ByName("main.GreetService.GreetPerson", ...Array.prototype.slice.call(arguments, 0));
}
26 changes: 0 additions & 26 deletions v3/examples/binding/assets/bindings_main.js

This file was deleted.

19 changes: 9 additions & 10 deletions v3/examples/binding/assets/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -78,18 +78,17 @@
<div class="result" id="result">Please enter your name below 👇</div>
<div class="input-box" id="input">
<input autofocus autocomplete="off" class="input" id="name" type="text"/>
<button class="btn" onclick="greet()">Greet</button>
<button class="btn" id="greet-btn">Greet</button>
</div>
<script type="module" src='/wails/runtime.js'></script>
<script src='bindings_main.js'></script>
<script>
let resultText = "";
let name = "";
<script type="module">
import * as GreetService from "./bindings/main/GreetService.js";

function greet() {
window.go.main.GreetService.Greet(document.getElementById("name").value).then((result) =>
document.getElementById("result").innerHTML = result);
}
async function greet() {
document.getElementById("result").innerHTML =
await GreetService.Greet(document.getElementById("name").value);
}

document.getElementById("greet-btn").onclick = greet;
</script>
</body>
</html>
27 changes: 0 additions & 27 deletions v3/examples/binding/assets/main.js

This file was deleted.

23 changes: 0 additions & 23 deletions v3/examples/binding/assets/models.ts

This file was deleted.

7 changes: 7 additions & 0 deletions v3/examples/binding/data/person.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package data

// Person holds someone's most important attributes
type Person struct {
// Name is the person's name
Name string `json:"name"`
}
24 changes: 0 additions & 24 deletions v3/examples/binding/models.ts

This file was deleted.

19 changes: 10 additions & 9 deletions v3/internal/flags/bindings.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package flags

type GenerateBindingsOptions struct {
Silent bool `name:"silent" description:"Silent mode"`
ModelsFilename string `name:"m" description:"The filename for the models file" default:"models.ts"`
TS bool `name:"ts" description:"Generate Typescript bindings"`
TSPrefix string `description:"The prefix for the typescript names" default:""`
TSSuffix string `description:"The postfix for the typescript names" default:""`
UseInterfaces bool `name:"i" description:"Use interfaces instead of classes"`
ProjectDirectory string `name:"p" description:"The project directory" default:"."`
UseIDs bool `name:"ids" description:"Use IDs instead of names in the binding calls"`
OutputDirectory string `name:"d" description:"The output directory" default:"frontend/bindings"`
Silent bool `name:"silent" description:"Silent mode"`
ModelsFilename string `name:"m" description:"The filename for the models file, excluding the extension" default:"models"`
TS bool `name:"ts" description:"Generate Typescript bindings"`
TSPrefix string `description:"The prefix for the typescript names" default:""`
TSSuffix string `description:"The postfix for the typescript names" default:""`
UseInterfaces bool `name:"i" description:"Use interfaces instead of classes"`
UseBundledRuntime bool `name:"b" description:"Use the bundled runtime instead of importing the npm package"`
ProjectDirectory string `name:"p" description:"The project directory" default:"."`
UseIDs bool `name:"ids" description:"Use IDs instead of names in the binding calls"`
OutputDirectory string `name:"d" description:"The output directory" default:"frontend/bindings"`
}
14 changes: 9 additions & 5 deletions v3/internal/parser/bindings.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const headerTypescript = `// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â M
`

const bindingTemplate = `
/**Comments
/**Comments
* @function {{methodName}}* @param names {string}
* @returns {Promise<string>}
**/
Expand Down Expand Up @@ -345,7 +345,7 @@ func isContext(input *Parameter) bool {
return input.Type.Package == "context" && input.Type.Name == "Context"
}

func (p *Project) GenerateBindings(bindings map[string]map[string][]*BoundMethod, useIDs bool, useTypescript bool) map[string]map[string]string {
func (p *Project) GenerateBindings(bindings map[string]map[string][]*BoundMethod, modelsFilename string, useIDs bool, useTypescript bool, useBundledRuntime bool) map[string]map[string]string {

var result = make(map[string]map[string]string)

Expand Down Expand Up @@ -374,7 +374,11 @@ func (p *Project) GenerateBindings(bindings map[string]map[string][]*BoundMethod
var models []string
var mainImports = ""
if len(methods) > 0 {
mainImports = "import {Call} from '@wailsio/runtime';\n"
if useBundledRuntime {
mainImports = "import {Call} from '/wails/runtime.js';\n"
} else {
mainImports = "import {Call} from '@wailsio/runtime';\n"
}
}
for _, method := range methods {
if useTypescript {
Expand Down Expand Up @@ -405,7 +409,7 @@ func (p *Project) GenerateBindings(bindings map[string]map[string][]*BoundMethod
sort.Strings(namespacedStructNames)
for _, thisStructName := range namespacedStructNames {
structInfo := namespacedStruct[thisStructName]
typedefs += " * @typedef {import('" + relativePackageDir + "/models')." + thisStructName + "} " + namePrefix + structInfo.Name + "\n"
typedefs += " * @typedef {import('" + relativePackageDir + "/" + modelsFilename + "')." + thisStructName + "} " + namePrefix + structInfo.Name + "\n"
}
}
typedefs += " */\n"
Expand All @@ -429,7 +433,7 @@ func (p *Project) GenerateBindings(bindings map[string]map[string][]*BoundMethod
if namePrefix != "" {
imports += "import {" + thisStructName + " as " + namePrefix + structInfo.Name + "} from '" + relativePackageDir + "/models';\n"
} else {
imports += "import {" + thisStructName + "} from '" + relativePackageDir + "/models';\n"
imports += "import {" + thisStructName + "} from '" + relativePackageDir + "/" + modelsFilename + "';\n"
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion v3/internal/parser/bindings_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -684,7 +684,7 @@ func TestGenerateBindings(t *testing.T) {
project.outputDirectory = "frontend/bindings"

// Generate Bindings
got := project.GenerateBindings(project.BoundMethods, tt.useIDs, tt.useTypescript)
got := project.GenerateBindings(project.BoundMethods, "models", tt.useIDs, tt.useTypescript, false)

for dirName, structDetails := range got {
// iterate the struct names in structDetails
Expand Down
5 changes: 3 additions & 2 deletions v3/internal/parser/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ package parser
import (
"bytes"
"embed"
"github.com/wailsapp/wails/v3/internal/flags"
"io"
"sort"
"strings"
"text/template"

"github.com/wailsapp/wails/v3/internal/flags"
)

//go:embed templates
Expand Down Expand Up @@ -36,7 +37,7 @@ func (p *Project) GenerateModel(wr io.Writer, def *ModelDefinitions, options *fl

tmpl, err := template.New(templateName).ParseFS(templates, "templates/"+templateName)
if err != nil {
println("Unable to create class template: " + err.Error())
println("Unable to initialize model template: " + err.Error())
return err
}

Expand Down
Loading

0 comments on commit 45b2681

Please sign in to comment.