Lewati ke konten

Binding Lanjutan

Panduan ini membahas teknik lanjutan untuk menyesuaikan dan mengoptimalkan proses pembuatan binding di Wails v3.

Menyesuaikan Kode yang Dihasilkan dengan Directive

Section titled “Menyesuaikan Kode yang Dihasilkan dengan Directive”

Directive //wails:inject memungkinkan Anda menginjeksi kode JavaScript/TypeScript kustom ke binding yang dihasilkan:

//wails:inject console.log("Hello from Wails!");
type MyService struct {}
func (s *MyService) Greet(name string) string {
return "Hello, " + name
}

Ini akan menginjeksi kode yang ditentukan ke file JavaScript/TypeScript yang dihasilkan untuk service MyService.

Anda juga dapat menggunakan injeksi kondisional untuk menargetkan format output tertentu:

//wails:inject j*:console.log("Hello JS!"); // JavaScript only
//wails:inject t*:console.log("Hello TS!"); // TypeScript only

Directive //wails:include memungkinkan Anda menyertakan file tambahan dengan binding yang dihasilkan:

//wails:include js/*.js
package mypackage

Directive ini biasanya digunakan dalam komentar dokumentasi paket untuk menyertakan file JavaScript/TypeScript tambahan dengan binding yang dihasilkan.

Directive //wails:internal menandai tipe atau metode sebagai internal, mencegahnya diekspor ke frontend:

//wails:internal
type InternalModel struct {
Field string
}
//wails:internal
func (s *MyService) InternalMethod() {}

Ini berguna untuk tipe dan metode yang hanya digunakan secara internal oleh kode Go Anda dan tidak boleh diekspos ke frontend.

Directive //wails:ignore sepenuhnya mengabaikan metode selama pembuatan binding:

//wails:ignore
func (s *MyService) IgnoredMethod() {}

Ini mirip dengan //wails:internal, tetapi sepenuhnya mengabaikan metode alih-alih menandainya sebagai internal.

Directive //wails:id menentukan ID kustom untuk metode, menimpa ID berbasis hash default:

//wails:id 42
func (s *MyService) CustomIDMethod() {}

Ini dapat berguna untuk menjaga kompatibilitas saat melakukan refactoring kode.

Generator binding menangani struct bersarang secara otomatis:

type Address struct {
Street string
City string
State string
Zip string
}
type Person struct {
Name string
Address Address
}
func (s *MyService) GetPerson() Person {
return Person{
Name: "John Doe",
Address: Address{
Street: "123 Main St",
City: "Anytown",
State: "CA",
Zip: "12345",
},
}
}

Kode JavaScript/TypeScript yang dihasilkan akan menyertakan class untuk Person dan Address.

Map dan slice juga ditangani secara otomatis:

type Person struct {
Name string
Attributes map[string]string
Friends []string
}
func (s *MyService) GetPerson() Person {
return Person{
Name: "John Doe",
Attributes: map[string]string{
"hair": "brown",
"eyes": "blue",
},
Friends: []string{"Jane", "Bob", "Alice"},
}
}

Di JavaScript, map direpresentasikan sebagai object dan slice sebagai array. Di TypeScript, map direpresentasikan sebagai Record<K, V> dan slice sebagai T[].

Generator binding mendukung tipe generik:

type Result[T any] struct {
Data T
Error string
}
func (s *MyService) GetResult() Result[string] {
return Result[string]{
Data: "Hello, World!",
Error: "",
}
}

Kode TypeScript yang dihasilkan akan menyertakan class generik untuk Result:

export class Result<T> {
"Data": T;
"Error": string;
constructor(source: Partial<Result<T>> = {}) {
if (!("Data" in source)) {
this["Data"] = null as any;
}
if (!("Error" in source)) {
this["Error"] = "";
}
Object.assign(this, source);
}
static createFrom<T>(source: string | object = {}): Result<T> {
let parsedSource = typeof source === "string" ? JSON.parse(source) : source;
return new Result<T>(parsedSource as Partial<Result<T>>);
}
}

Generator binding dapat menghasilkan interface TypeScript alih-alih class menggunakan flag -i:

Terminal window
wails3 generate bindings -ts -i

Ini akan menghasilkan interface TypeScript untuk semua model:

export interface Person {
Name: string;
Attributes: Record<string, string>;
Friends: string[];
}

Secara default, generator binding menggunakan ID berbasis hash untuk panggilan metode. Anda dapat menggunakan flag -names untuk menggunakan nama:

Terminal window
wails3 generate bindings -names

Ini akan menghasilkan kode yang memanggil metode terikat berdasarkan nama fully-qualified (<package>.<Service>.<Method>) dan menggunakan nama parameter posisional $0, $1, …:

export function Greet($0) {
let $resultPromise = $Call.ByName("main.GreetService.Greet", $0);
return $resultPromise;
}

Ini dapat membuat kode yang dihasilkan lebih mudah dibaca dan di-debug, tetapi mungkin sedikit kurang efisien.

Secara default, kode yang dihasilkan mengimpor runtime Wails dari paket npm @wailsio/runtime. Anda dapat menggunakan flag -b untuk membundel runtime dengan kode yang dihasilkan:

Terminal window
wails3 generate bindings -b

Ini akan menyertakan kode runtime langsung di file yang dihasilkan, menghilangkan kebutuhan paket npm.

Jika Anda tidak memerlukan file index, Anda dapat menggunakan flag -noindex untuk menonaktifkan pembuatannya:

Terminal window
wails3 generate bindings -noindex

Ini berguna jika Anda lebih suka mengimpor service dan model langsung dari file masing-masing.

Berikut contoh service autentikasi dengan directive kustom:

package auth
//wails:inject console.log("Auth service initialized");
type AuthService struct {
// Private fields
users map[string]User
}
type User struct {
Username string
Email string
Role string
}
type LoginRequest struct {
Username string
Password string
}
type LoginResponse struct {
Success bool
User User
Token string
Error string
}
// Login authenticates a user
func (s *AuthService) Login(req LoginRequest) LoginResponse {
// Implementation...
}
// GetCurrentUser returns the current user
func (s *AuthService) GetCurrentUser() User {
// Implementation...
}
// Internal helper method
//wails:internal
func (s *AuthService) validateCredentials(username, password string) bool {
// Implementation...
}

Berikut contoh service pemrosesan data dengan tipe generik:

package data
type ProcessingResult[T any] struct {
Data T
Error string
}
type DataService struct {}
// Process processes data and returns a result
func (s *DataService) Process(data string) ProcessingResult[map[string]int] {
// Implementation...
}
// ProcessBatch processes multiple data items
func (s *DataService) ProcessBatch(data []string) ProcessingResult[[]map[string]int] {
// Implementation...
}
// Internal helper method
//wails:internal
func (s *DataService) parseData(data string) (map[string]int, error) {
// Implementation...
}

Berikut contoh injeksi kode kondisional untuk format output berbeda:

//wails:inject j*:/**
//wails:inject j*: * @param {string} arg
//wails:inject j*: * @returns {Promise<void>}
//wails:inject j*: */
//wails:inject j*:export async function CustomMethod(arg) {
//wails:inject t*:export async function CustomMethod(arg: string): Promise<void> {
//wails:inject await InternalMethod("Hello " + arg + "!");
//wails:inject }
type Service struct{}

Ini menginjeksi kode berbeda untuk output JavaScript dan TypeScript, memberikan anotasi tipe yang sesuai untuk setiap bahasa.