wails icon indicating copy to clipboard operation
wails copied to clipboard

Binding has no exported member despite already generated (the binding is not refreshed)

Open thoriqadillah opened this issue 1 year ago • 9 comments

Description

When I make a function binding to see what I can do with this framework, I got an error that tells me the binding I made has no exported member despite presents on the wailsjs/go/main/App. This behavior only presents in dev mode I tried to read a file from the backend and then send it to frontend, using this

package setting

type Setting struct {
	Themes Themes
}

func New() Setting {
	return Setting{
		Themes: Theme(),
	}
}
package setting

import (
	"encoding/json"
	"io"
	"log"
	"os"
)

const DEFAULT_THEME_PATH = "/home/thoriqadillah/Development/Go/gown/frontend/theme/default.json"

type Themes struct {
	Components
}

func theme(path string) Components {
	f, err := os.Open(path)
	if err != nil {
		log.Panicf("Error when opening file: %v\n", err)
	}

	data, err := io.ReadAll(f)
	if err != nil {
		log.Panicf("Error when reading file: %v\n", err)
	}

	var components Components
	if err := json.Unmarshal(data, &components); err != nil {
		log.Panicf("Error when reading file: %v\n", err)
	}

	return components
}

func Theme() Themes {
	return Themes{
		Components: theme(DEFAULT_THEME_PATH),
	}
}

type Components struct {
	TextColor       string `json:"textColor"`
	BackgroundColor string `json:"backgroundColor"`
}

after that, I'm assigning the struct on the app struct like this

package main

import (
	"changeme/backend/setting"
	"context"
	"fmt"
)

// App struct
type App struct {
	ctx     context.Context
	Setting setting.Setting
}

// NewApp creates a new App application struct
func NewApp() *App {
	return &App{
		Setting: setting.New(),
	}
}

func (a *App) Theme() setting.Themes {
	return a.Setting.Themes
}

after that, it generates the following on wailsjs

// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT
import {setting} from '../models';

export function Greet(arg1:string):Promise<string>;

export function Theme():Promise<setting.Themes>;

but when I start to import it, it says Module "../../wailsjs/go/main/App" has no exported member 'Theme"

To Reproduce

  1. Create struct outside main package
  2. Add the struct as property in app struct
  3. Add function for binding
  4. Import the function from frontend
  5. You'll see the error

Expected behaviour

The function can be imported without error

Screenshots

Screenshot_20230402_123028

Attempted Fixes

I have tried make the project from new but the problem remains

System Details

Wails CLI v2.4.1

Scanning system - Please wait (this may take a long time)...Done.

# System

OS           | Fedora Linux
Version      | 37          
ID           | fedora      
Go Version   | go1.19.6    
Platform     | linux       
Architecture | amd64       

# Wails

Version         | v2.4.1
Package Manager | dnf   

# Dependencies

Dependency | Package Name        | Status    | Version
*docker    | Unknown             | Not Found |        
gcc        | gcc-c++             | Installed | 12.2.1 
libgtk-3   | gtk3-devel          | Installed | 3.24.37
libwebkit  | webkit2gtk4.0-devel | Installed | 2.40.0 
npm        | npm                 | Installed | 9.3.1  
pkg-config | pkgconf-pkg-config  | Installed | 1.8.0  
*upx       | upx                 | Installed | 4.0.2  
* - Optional Dependency

# Diagnosis

Your system is ready for Wails development!
 ♥   If Wails is useful to you or your company, please consider sponsoring the project:
https://github.com/sponsors/leaanthony

Additional context

No response

thoriqadillah avatar Apr 02 '23 06:04 thoriqadillah

Thanks for trying Wails and opening the issue. It looks like the binding is correct. Perhaps there's a caching issue in VSC?

leaanthony avatar Apr 02 '23 22:04 leaanthony

How do i delete the cache in vscode?

thoriqadillah avatar Apr 03 '23 00:04 thoriqadillah

This is a vscode specific problem in your environment. Restart the language server.

mateothegreat avatar Apr 16 '23 23:04 mateothegreat

@thoriqadillah - any updates?

leaanthony avatar May 21 '23 08:05 leaanthony

In Windows, you need to change '/' to '\\' @leaanthony

YCarlB avatar Jul 04 '23 12:07 YCarlB

@leaanthony I think the binding is not updated correctly if I'm not mistaken. I tried to reproduce the issue in dummy project and got the issue, i stop the local dev and then re-run the local dev. And then it's fixed

thoriqadillah avatar Jul 04 '23 12:07 thoriqadillah

wails doctor

Wails CLI v2.5.1

 SUCCESS  Done.                                                                                                                                                 

# System

OS           | MacOS   
Version      | 13.4.1  
ID           | 22F82   
Go Version   | go1.20.5
Platform     | darwin  
Architecture | arm64   

# Wails

Version | v2.5.1

# Dependencies

Dependency                | Package Name | Status    | Version         
Xcode command line tools  | N/A          | Installed | 2397            
Nodejs                    | N/A          | Installed | 20.0.0          
npm                       | N/A          | Installed | 9.8.0           
*Xcode                    | N/A          | Installed | 14.3.1 (14E300c)
*upx                      | N/A          | Available |                 
*nsis                     | N/A          | Available |                 
* - Optional Dependency

# Diagnosis

Your system is ready for Wails development!
Optional package(s) installation details: 
  - upx : Available at https://upx.github.io/
  - nsis : More info at https://wails.io/docs/guides/windows-installer/

 ♥   If Wails is useful to you or your company, please consider sponsoring the project:
https://github.com/sponsors/leaanthony

report

Howdy, I landed here by googling about a problem I'm experiencing that seems related to this issue.

I've a library written in go that exposes a marshal package, all structs used in interfacing with the game library are there each with its marshal function.

package marshal

import (
	"errors"
	// imports 
)

// error returned when a player has pending actions
var ErrPending = errors.New("player has pending actions")

// player id
type PlayerID players.PID

// game id
type GameID engine.GID

// card id
type CardID cards.CID

// game edition
type Edition cards.Edition

const (
	// human card set
	EditionHuman Edition = Edition(cards.EditionHuman)
	// pet card set
	EditionPet Edition = Edition(cards.EditionPet)
	// use both editions
	EditionBoth Edition = Edition(cards.EditionBoth)
)

// journal entry
type JournalEntry struct {
	*Move
	// journal entry sequence number
	SEQ int `json:"seq,omitempty"`
}

// dig action
type Dig struct {
	*CardWithID
	// source of the dig action
	Source PlayerID `json:"source"  validate:""`
	Target PlayerID `json:"target"  validate:""`
	Qty    int      `json:"qty"  validate:""`
}

// card information
type Card struct {
	// card title
	Title string `json:"title"  validate:""`
	// card type
	Type string `json:"type"  validate:"required,oneof=Zombie Tomb Development Corpse"`
	// card edition
	Edition Edition `json:"edition"  validate:"required,oneof=human pet both"`
	// card value
	Value int `json:"value"  validate:"required,gt=0"`
	// card effect
	Effect string `json:"effect"  validate:""`
	// card description
	Description string `json:"description"  validate:""`
}

// card information with unique id
type CardWithID struct {
	*Card
	// card id
	ID CardID `json:"id"  validate:""`
}

// player grave
type PlayerGrave struct {
	*CardWithID
	// burial level
	Burial int `json:"burial"  validate:""`
}

// player information
type Player struct {
	// player id
	ID PlayerID
	// number of cards in the player hand
	Hand int
	// player's graves
	Grave []*PlayerGrave
	// player's zombies
	Zombies []*Card
	// player's good development card
	Good *Card
	// player's bad development card
	Bad *Card
}

// game status
type Game struct {
	// game id
	ID GameID `json:"id"  validate:""`
	// game name
	Name string `json:"name"  validate:""`
	// current dig status (if any)
	Dig *Dig `json:"dig"  validate:""`
	// game owner
	Owner PlayerID `json:"owner"  validate:""`
	// active player
	ActivePlayer PlayerID `json:"active_player"  validate:""`
	// last update timestamp
	LastUpdated int `json:"last_updated"  validate:""`
	// game completion timestamp
	CompletedAt int `json:"completed_at"  validate:""`
	// number of cards in the table
	Table int `json:"table"  validate:""`
	// number of cards in the table discard pile
	TableDiscards int `json:"table_discards"  validate:""`
	// number of cards in the zombies pile
	Zombies int `json:"zombies"  validate:""`
	// number of cards in the zombies discard pile
	ZombiesDiscards int `json:"zombies_discards"  validate:""`
	// current round
	Round int `json:"round"  validate:""`
	// current turn
	Turn int `json:"turn"  validate:""`
	// current stage
	Stage string `json:"stage"  validate:""`
	// players
	Players map[PlayerID]Player `json:"players"  validate:""`
}

// describes a play action
type Move struct {
	// action type
	Action cards.Action `json:"action,omitempty"`
	// player submitting the action
	Player players.PID `json:"player,omitempty"`
	// desired targets
	Targets []players.PID `json:"targets,omitempty"`
	// cards to be used
	Played []cards.CID `json:"played,omitempty"`
	// when a quantitative action is performed defined the quantity.
	// <=0 means no quantity
	Qty int `json:"qty,omitempty"`
}

The issue I've is that some structs from marshal are not exported to the typescript modules:

image

wails generate module doesn't show any error, weirdly mentions twice marshal.Dig but no mentions of marshal.Player, marshal.Card or marshal.CardWithID.

2023/07/27 19:46:38 KnownStructs: marshal.Dig   marshal.Game    marshal.Move
marshal.Dig

 ♥   If Wails is useful to you or your company, please consider sponsoring the project:
https://github.com/sponsors/leaanthony

I don't know if the reason the struct aren't exported is because they are not directly exposed by any function, but adding the following seems to produce the correct output. However please note that marshal.Game has a field []Player but no definition of such type.

// returns nil.
func (app *App) NilPlayer() *marshal.Player {
	return nil
}

// returns nil. do not use this method.
func (app *App) NilCardWithID() *marshal.CardWithID {
	return nil
}

The result from wails generate module:

2023/07/27 19:54:23 KnownStructs: marshal.Card  marshal.CardWithID      marshal.Dig     marshal.Game    marshal.Move    marshal.Player
marshal.Dig

 ♥   If Wails is useful to you or your company, please consider sponsoring the project:
https://github.com/sponsors/leaanthony

Reading another ticket it was suggested to checkout wails trunk and try by replacing wails with the trunk version. Unsure if that referred to the golang imports or the cli tool itself I've tried both.

problem persists using 84d2576e061477269e334a751e0d79831e471162 in either imports or replacing the wails cmd with the compiled one.

replace github.com/wailsapp/wails/v2 => ../wails/v2

cd wails/v2/cmd/wails
go build -o ~/bin/wails-git

Any more information i can provide? any other branch I should try out?

thetechpanda avatar Jul 27 '23 10:07 thetechpanda

While I can see the struct in the output of wails generate module, models.ts does not define marshal.Player struct.

I thought the issue could be a name conflict in exported methods vs structs as I export both game.Player() and marshal.Player; however after renaming marshal.Player to PlayerInfo (that is unique) nothing changed.

Below my App.d.ts; unresolved: marshal.GameID, marshal.PlayerID, marshal.PlayerInfo

// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT
import {marshal} from '../models';
import {cemetery} from '../models';
export function Delete(arg1:marshal.GameID):Promise<void>;
export function Fetch(arg1:marshal.GameID):Promise<cemetery.GameHandler|boolean>;
export function New(arg1:number):Promise<void>;
export function NilCardWithID():Promise<marshal.CardWithID>;
export function NilPlayer():Promise<marshal.PlayerInfo>;
export function Play(arg1:marshal.GameID,arg2:marshal.Move):Promise<void>;
export function Player(arg1:marshal.GameID,arg2:marshal.PlayerID):Promise<marshal.Game>;
export function Status(arg1:marshal.GameID):Promise<void>;
export function Store(arg1:cemetery.GameHandler):Promise<void>;

wails doctor

Wails CLI v2.5.1

 SUCCESS  Done.                                                                                                                                                 

# System

OS           | MacOS   
Version      | 13.4.1  
ID           | 22F82   
Go Version   | go1.20.5
Platform     | darwin  
Architecture | arm64   

# Wails

Version | v2.5.1

# Dependencies

Dependency                | Package Name | Status    | Version         
Xcode command line tools  | N/A          | Installed | 2397            
Nodejs                    | N/A          | Installed | 20.0.0          
npm                       | N/A          | Installed | 9.8.0           
*Xcode                    | N/A          | Installed | 14.3.1 (14E300c)
*upx                      | N/A          | Available |                 
*nsis                     | N/A          | Available |                 
* - Optional Dependency

# Diagnosis

Your system is ready for Wails development!
Optional package(s) installation details: 
  - upx : Available at https://upx.github.io/
  - nsis : More info at https://wails.io/docs/guides/windows-installer/

 ♥   If Wails is useful to you or your company, please consider sponsoring the project:
https://github.com/sponsors/leaanthony

report

Howdy, I landed here by googling about a problem I'm experiencing that seems related to this issue.

I've a library written in go that exposes a marshal package, all structs used in interfacing with the game library are there each with its marshal function.

package marshal

import (
	"errors"
	// imports 
)

// error returned when a player has pending actions
var ErrPending = errors.New("player has pending actions")

// player id
type PlayerID players.PID

// game id
type GameID engine.GID

// card id
type CardID cards.CID

// game edition
type Edition cards.Edition

const (
	// human card set
	EditionHuman Edition = Edition(cards.EditionHuman)
	// pet card set
	EditionPet Edition = Edition(cards.EditionPet)
	// use both editions
	EditionBoth Edition = Edition(cards.EditionBoth)
)

// journal entry
type JournalEntry struct {
	*Move
	// journal entry sequence number
	SEQ int `json:"seq,omitempty"`
}

// dig action
type Dig struct {
	*CardWithID
	// source of the dig action
	Source PlayerID `json:"source"  validate:""`
	Target PlayerID `json:"target"  validate:""`
	Qty    int      `json:"qty"  validate:""`
}

// card information
type Card struct {
	// card title
	Title string `json:"title"  validate:""`
	// card type
	Type string `json:"type"  validate:"required,oneof=Zombie Tomb Development Corpse"`
	// card edition
	Edition Edition `json:"edition"  validate:"required,oneof=human pet both"`
	// card value
	Value int `json:"value"  validate:"required,gt=0"`
	// card effect
	Effect string `json:"effect"  validate:""`
	// card description
	Description string `json:"description"  validate:""`
}

// card information with unique id
type CardWithID struct {
	*Card
	// card id
	ID CardID `json:"id"  validate:""`
}

// player grave
type PlayerGrave struct {
	*CardWithID
	// burial level
	Burial int `json:"burial"  validate:""`
}

// player information
type Player struct {
	// player id
	ID PlayerID
	// number of cards in the player hand
	Hand int
	// player's graves
	Grave []*PlayerGrave
	// player's zombies
	Zombies []*Card
	// player's good development card
	Good *Card
	// player's bad development card
	Bad *Card
}

// game status
type Game struct {
	// game id
	ID GameID `json:"id"  validate:""`
	// game name
	Name string `json:"name"  validate:""`
	// current dig status (if any)
	Dig *Dig `json:"dig"  validate:""`
	// game owner
	Owner PlayerID `json:"owner"  validate:""`
	// active player
	ActivePlayer PlayerID `json:"active_player"  validate:""`
	// last update timestamp
	LastUpdated int `json:"last_updated"  validate:""`
	// game completion timestamp
	CompletedAt int `json:"completed_at"  validate:""`
	// number of cards in the table
	Table int `json:"table"  validate:""`
	// number of cards in the table discard pile
	TableDiscards int `json:"table_discards"  validate:""`
	// number of cards in the zombies pile
	Zombies int `json:"zombies"  validate:""`
	// number of cards in the zombies discard pile
	ZombiesDiscards int `json:"zombies_discards"  validate:""`
	// current round
	Round int `json:"round"  validate:""`
	// current turn
	Turn int `json:"turn"  validate:""`
	// current stage
	Stage string `json:"stage"  validate:""`
	// players
	Players map[PlayerID]Player `json:"players"  validate:""`
}

// describes a play action
type Move struct {
	// action type
	Action cards.Action `json:"action,omitempty"`
	// player submitting the action
	Player players.PID `json:"player,omitempty"`
	// desired targets
	Targets []players.PID `json:"targets,omitempty"`
	// cards to be used
	Played []cards.CID `json:"played,omitempty"`
	// when a quantitative action is performed defined the quantity.
	// <=0 means no quantity
	Qty int `json:"qty,omitempty"`
}

The issue I've is that some structs from marshal are not exported to the typescript modules:

image

wails generate module doesn't show any error, weirdly mentions twice marshal.Dig but no mentions of marshal.Player, marshal.Card or marshal.CardWithID.

2023/07/27 19:46:38 KnownStructs: marshal.Dig   marshal.Game    marshal.Move
marshal.Dig

 ♥   If Wails is useful to you or your company, please consider sponsoring the project:
https://github.com/sponsors/leaanthony

I don't know if the reason the struct aren't exported is because they are not directly exposed by any function, but adding the following seems to produce the correct output. However please note that marshal.Game has a field []Player but no definition of such type.

// returns nil.
func (app *App) NilPlayer() *marshal.Player {
	return nil
}

// returns nil. do not use this method.
func (app *App) NilCardWithID() *marshal.CardWithID {
	return nil
}

The result from wails generate module:

2023/07/27 19:54:23 KnownStructs: marshal.Card  marshal.CardWithID      marshal.Dig     marshal.Game    marshal.Move    marshal.Player
marshal.Dig

 ♥   If Wails is useful to you or your company, please consider sponsoring the project:
https://github.com/sponsors/leaanthony

Reading another ticket it was suggested to checkout wails trunk and try by replacing wails with the trunk version. Unsure if that referred to the golang imports or the cli tool itself I've tried both.

problem persists using 84d2576e061477269e334a751e0d79831e471162 in either imports or replacing the wails cmd with the compiled one.

replace github.com/wailsapp/wails/v2 => ../wails/v2

cd wails/v2/cmd/wails
go build -o ~/bin/wails-git

Any more information i can provide? any other branch I should try out?

thetechpanda avatar Jul 27 '23 23:07 thetechpanda

On my end I just don't see the models.ts on my frontend directory. 😢 image

image

nicanordlc avatar Apr 27 '24 18:04 nicanordlc