client

package module
v0.3.15 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 18, 2025 License: MIT Imports: 16 Imported by: 0

README

tinywasm

Project Badges

Go package for intelligent WebAssembly compilation with automatic file detection and 3-mode compiler system.

Features

  • 3-Mode Compiler System: Large ("L"), Medium ("M"), Small ("S")
  • DevTUI Integration: FieldHandler interface for interactive mode switching
  • Smart file detection via prefixes (frontend/backend separation)
  • Triple compiler support: Go standard (fast dev), TinyGo debug (-opt=1), TinyGo production (-opt=z)
  • VS Code auto-configuration for WASM development
  • Dual Output Architecture: WASM binaries in src/web/public/, watchable JS in src/web/ui/js/

Quick Start

// Basic usage
config := tinywasm.NewConfig() // Pre-configured with defaults
config.SourceDir = "src/cmd/webclient"
config.OutputDir = "src/web/public"
config.WasmExecJsOutputDir = "src/web/ui/js"

tw := tinywasm.New(config)
tw.NewFileEvent("src/cmd/webclient/main.go", ".go", "src/cmd/webclient/main.go", "write")

// DevTUI Integration - 3 Mode System
fmt.Println("Current mode:", tw.Value()) // "L" (coding / large build)

// New API: Change now reports progress via a channel instead of returning (msg, err).
// Create and consume a progress channel before calling Change to avoid blocking.
progress := make(chan string)
go func() {
	for p := range progress {
		fmt.Println("Status:", p)
	}
}()
tw.Change("M", progress) // Switch to medium (debug) mode; messages arrive on the progress channel

// Advanced configuration
config := &tinywasm.Config{
    AppRootDir:          "/path/to/project",
    SourceDir:           "src/cmd/webclient",
    OutputDir:           "src/web/public",
    WasmExecJsOutputDir: "src/web/ui/js",
    MainInputFile:       "main.go",
    OutputName:          "main",
	BuildLargeSizeShortcut:   "L",  // Customizable shortcuts (default: L = Large/fast with go)
	BuildMediumSizeShortcut:    "M",
	BuildSmallSizeShortcut: "S",
    Logger:              logger,
}

DevTUI FieldHandler Interface

WasmClient implements the DevTUI FieldHandler interface for interactive development:

// DevTUI Integration
label := tw.Label()           // "Compiler Mode"
current := tw.Value()         // Current mode shortcut ("L", "M", "S")
canEdit := tw.Editable()      // true
timeout := tw.Timeout()       // 0 (no timeout)

// Interactive mode change with the new Change API
// Change now has signature: Change(newValue string, progress chan<- string)
// All validation messages, warnings (e.g. auto-compilation failed) and success
// messages are sent through the provided channel. The channel is closed when
// the operation completes.
progress := make(chan string)
go func() {
	for p := range progress {
		// Handle progress messages (show in TUI, log, etc.)
		fmt.Println("Progress:", p)
	}
}()
tw.Change("M", progress)
// No return values; read errors and status from the progress channel above.

VS Code Integration

Auto-creates .vscode/settings.json with WASM environment:

{"gopls": {"env": {"GOOS": "js", "GOARCH": "wasm"}}}

API

Core:

  • New(config *Config) *WasmClient
  • NewConfig() *Config - Pre-configured with sensible defaults
  • NewFileEvent(fileName, ext, path, event string) error
  • ShouldCompileToWasm(fileName, path string) bool

DevTUI FieldHandler Interface:

  • Label() string - Returns "Compiler Mode"
  • Value() string - Current mode shortcut ("L", "M", "S")
  • Editable() bool - Returns true (field is editable)
  • Change(newValue string, progress chan<- string) - Switch compiler mode and report progress via the provided channel. Validation errors, auto-compilation warnings and success messages are sent to the channel; the implemention closes the channel when finished.
  • Timeout() time.Duration - Returns 0 (no timeout)

Legacy Compiler Methods (deprecated):

  • TinyGoCompiler() bool - Use Value() instead
  • SetTinyGoCompiler(bool) error - Use Change() instead
  • VerifyTinyGoInstallation() error

Utils:

  • MainInputFileRelativePath() string
  • UnobservedFiles() []string
  • JavascriptForInitializing() (string, error)

Config

type Config struct {
	AppRootDir          string        // application root directory (absolute), defaults to "."
	SourceDir           string        // directory containing Go source (relative) eg: "src/cmd/webclient"
	OutputDir           string        // directory for WASM binary output (relative) eg: "src/web/public"
	WasmExecJsOutputDir string        // directory for watchable JS runtime (relative) eg: "src/web/ui/js"
	MainInputFile       string        // main input file for WASM compilation (default: "main.go")
	OutputName          string        // output name for WASM file (default: "main")
	Logger              func(message ...any) // For logging output to external systems (e.g., TUI, console)

	// NEW: Shortcut configuration (default: "f", "b", "m")
	BuildLargeSizeShortcut    string // "L" (large/fast) compile fast with go
	BuildMediumSizeShortcut     string // "M" (medium/debug) compile with tinygo debug
	BuildSmallSizeShortcut string // "S" (small/minimal) compile with tinygo minimal binary size

	// gobuild integration fields
	Callback           func(error)     // Optional callback for async compilation
	CompilingArguments func() []string // Build arguments for compilation (e.g., ldflags)

	// DisableWasmExecJsOutput prevents automatic creation of wasm_exec.js file
	// Useful when embedding wasm_exec.js content inline (e.g., Cloudflare Pages Advanced Mode)
	DisableWasmExecJsOutput bool
}

// Pre-configured constructor (recommended)
func NewConfig() *Config

Dual Output Architecture

WasmClient produces two types of outputs that serve different purposes in the build pipeline:

1. WASM Binary Output (OutputDir)
  • Location: src/web/public/main.wasm
  • Purpose: Final compiled WebAssembly binary loaded by the browser
  • Consumed by: Browser at runtime
  • Modes: All three compilation modes produce output here
2. Watchable JavaScript Output (WasmExecJsOutputDir)
  • Location: src/web/ui/js/wasm_exec.js
  • Purpose: Mode-specific JavaScript runtime that:
    • Informs external tools about the current compilation mode (Go vs TinyGo)
    • Triggers file watchers to reload the browser when mode changes
    • Gets compiled together with other JavaScript by external asset bundlers
  • Consumed by: File watchers (e.g., devwatch) and asset bundlers (e.g., assetmin)
  • Important: WasmClient's only responsibility is writing the correct wasm_exec.js according to the active mode. External tools handle final bundling.
Why Two Separate Directories?
  1. Separation of Concerns: Runtime assets vs. build-time integration
  2. Build Pipeline Integration: File watchers track wasm_exec.js changes
  3. No Dev/Prod States: All modes use the same directories
  4. Mode Transparency: External tools detect mode changes via wasm_exec.js

Mode Switching

// Example usage with the new channel-based Change API:
progress := make(chan string)
go func() {
	for p := range progress {
		fmt.Println(p)
	}
}()
tw.Change("S", progress) // production mode with TinyGo -opt=z

// Repeat for other modes as needed (always provide and consume a progress channel)
// tw.Change("M", progress)
// tw.Change("L", progress)

Requirements

  • Go 1.20+
  • TinyGo (optional, required for debug/production modes)
  • DevTUI (optional, for interactive development)

Benefits:

  • 🎯 3 optimized modes instead of binary choice
  • 🔧 DevTUI integration for interactive development
  • 📦 Smaller debug builds with TinyGo -opt=1
  • Auto-recompilation on mode switch
  • 🛠️ Better error handling with validation
  • 🏗️ Dual output architecture for better build pipeline integration

Contributing

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ClientStrategy added in v0.3.13

type ClientStrategy interface {
	// Compile performs the compilation.
	// For InMemory: compiles to buffer.
	// For External: compiles to disk.
	Compile() error

	// RegisterRoutes registers the WASM file handler on the mux.
	RegisterRoutes(mux *http.ServeMux)

	// Name returns the strategy name for logging/debugging
	Name() string
}

ClientStrategy defines the behavior for compiling and serving the WASM client.

type Config

type Config struct {

	// AppRootDir specifies the application root directory (absolute).
	// e.g., "/home/user/project". If empty, defaults to "." to preserve existing behavior.
	AppRootDir string

	// SourceDir specifies the directory containing the Go source for the webclient (relative to AppRootDir).
	// e.g., "web"
	SourceDir string

	// OutputDir specifies the directory for WASM and related assets (relative to AppRootDir).
	// e.g., "web/public"
	OutputDir string

	// AssetsURLPrefix is an optional URL prefix/folder for serving the WASM file.
	// e.g. "assets" -> serves at "/assets/client.wasm"
	// default: "" -> serves at "/client.wasm"
	AssetsURLPrefix string

	WasmExecJsOutputDir string // output dir for wasm_exec.js file (relative) eg: "web/js", "theme/js"
	MainInputFile       string // main input file for WASM compilation (default: "client.go")
	OutputName          string // output name for WASM file (default: "client")
	Logger              func(message ...any)

	BuildLargeSizeShortcut  string // "L" (Large) compile with go
	BuildMediumSizeShortcut string // "M" (Medium) compile with tinygo debug
	BuildSmallSizeShortcut  string // "S" (Small) compile with tinygo minimal binary size

	// gobuild integration fields
	Callback           func(error)     // Optional callback for async compilation
	CompilingArguments func() []string // Build arguments for compilation (e.g., ldflags)

	// DisableWasmExecJsOutput prevents automatic creation of wasm_exec.js file
	// Useful when embedding wasm_exec.js content inline (e.g., Cloudflare Pages Advanced Mode)
	DisableWasmExecJsOutput bool

	Store            Store  // Key-Value store for state persistence
	OnWasmExecChange func() // Callback for wasm_exec.js changes
	// contains filtered or unexported fields
}

Config holds configuration for WASM compilation

func NewConfig

func NewConfig() *Config

NewConfig creates a WasmClient Config with sensible defaults

type ParameterMetadata

type ParameterMetadata struct {
	Name        string
	Description string
	Required    bool
	Type        string
	EnumValues  []string
	Default     any
}

ParameterMetadata describes a tool parameter

type Store added in v0.3.7

type Store interface {
	Get(key string) (string, error)
	Set(key, value string) error
}

Store defines the interface for a key-value storage system used to persist the compiler state (e.g. current mode).

type TinyWasm added in v0.3.7

type TinyWasm = WasmClient

TinyWasm is an alias for WasmClient to maintain backward compatibility

type ToolExecutor

type ToolExecutor func(args map[string]any, progress chan<- any)

ToolExecutor defines how a tool should be executed Channel accepts string messages (no binary data in tinywasm)

type ToolMetadata

type ToolMetadata struct {
	Name        string
	Description string
	Parameters  []ParameterMetadata
	Execute     ToolExecutor // Execution function
}

ToolMetadata provides MCP tool configuration metadata

type WasmClient

type WasmClient struct {
	*Config
	// contains filtered or unexported fields
}

WasmClient provides WebAssembly compilation capabilities with 3-mode compiler selection

func New

func New(c *Config) *WasmClient

New creates a new WasmClient instance with the provided configuration Timeout is set to 40 seconds maximum as TinyGo compilation can be slow Default values: MainInputFile in Config defaults to "main.wasm.go"

func (*WasmClient) Change

func (w *WasmClient) Change(newValue string, progress chan<- string)

Change updates the compiler mode for WasmClient and reports progress via the provided channel. Implements the HandlerEdit interface: Change(newValue string, progress chan<- string) NOTE: The caller (devtui) is responsible for closing the progress channel, NOT the handler.

func (*WasmClient) ClearJavaScriptCache

func (h *WasmClient) ClearJavaScriptCache()

ClearJavaScriptCache clears both cached JavaScript strings to force regeneration

func (*WasmClient) CreateDefaultWasmFileClientIfNotExist

func (t *WasmClient) CreateDefaultWasmFileClientIfNotExist() *WasmClient

CreateDefaultWasmFileClientIfNotExist creates a default WASM main.go file from the embedded markdown template It never overwrites an existing file and returns the WasmClient instance for method chaining.

func (*WasmClient) GetLastOperationID added in v0.3.11

func (w *WasmClient) GetLastOperationID() string

func (*WasmClient) GetMCPToolsMetadata

func (w *WasmClient) GetMCPToolsMetadata() []ToolMetadata

GetMCPToolsMetadata returns metadata for all WasmClient MCP tools

func (*WasmClient) GetTinyGoVersion

func (t *WasmClient) GetTinyGoVersion() (string, error)

GetTinyGoVersion returns the installed TinyGo version

func (*WasmClient) GetWasmExecJsPathGo

func (w *WasmClient) GetWasmExecJsPathGo() (string, error)

GetWasmExecJsPathGo returns the path to Go's wasm_exec.js file

func (*WasmClient) GetWasmExecJsPathTinyGo

func (w *WasmClient) GetWasmExecJsPathTinyGo() (string, error)

GetWasmExecJsPathTinyGo returns the path to TinyGo's wasm_exec.js file

func (*WasmClient) JavascriptForInitializing

func (h *WasmClient) JavascriptForInitializing(customizations ...string) (js string, err error)

JavascriptForInitializing returns the JavaScript code needed to initialize WASM.

Parameters (variadic):

  • customizations[0]: Custom header string to prepend to wasm_exec.js content. If not provided, defaults to "// WasmClient: mode=<current_mode>\n"
  • customizations[1]: Custom footer string to append after wasm_exec.js content. If not provided, defaults to WebAssembly initialization code with fetch and instantiate.

Examples:

  • JavascriptForInitializing() - Uses default header and footer
  • JavascriptForInitializing("// Custom Header\n") - Custom header, default footer
  • JavascriptForInitializing("// Custom Header\n", "console.log('loaded');") - Both custom

func (*WasmClient) Label

func (w *WasmClient) Label() string

Label returns the field label for DevTUI display

func (*WasmClient) MainInputFileRelativePath

func (w *WasmClient) MainInputFileRelativePath() string

MainInputFileRelativePath returns the relative path to the main WASM input file (e.g. "main.wasm.go").

func (*WasmClient) MainOutputFileAbsolutePath

func (w *WasmClient) MainOutputFileAbsolutePath() string

MainOutputFileAbsolutePath returns the absolute path to the main WASM output file (e.g. "main.wasm").

func (*WasmClient) Name

func (w *WasmClient) Name() string

Name returns the name of the WASM project

func (*WasmClient) NewFileEvent

func (w *WasmClient) NewFileEvent(fileName, extension, filePath, event string) error

NewFileEvent handles file events for WASM compilation with automatic project detection fileName: name of the file (e.g., main.wasm.go) extension: file extension (e.g., .go) filePath: full path to the file (e.g., ./home/userName/ProjectName/web/public/main.wasm.go) event: type of file event (e.g., create, remove, write, rename)

func (*WasmClient) OutputRelativePath

func (w *WasmClient) OutputRelativePath() string

OutputRelativePath returns the RELATIVE path to the final output file eg: "deploy/edgeworker/app.wasm" (relative to AppRootDir) This is used by file watchers to identify output files that should be ignored. The returned path always uses forward slashes (/) for consistency across platforms.

func (*WasmClient) RecompileMainWasm

func (w *WasmClient) RecompileMainWasm() error

RecompileMainWasm recompiles the main WASM file if it exists

func (*WasmClient) RegisterRoutes

func (w *WasmClient) RegisterRoutes(mux *http.ServeMux)

RegisterRoutes registers the WASM client file route on the provided mux. It delegates to the active strategy.

func (*WasmClient) SetLastOperationID added in v0.3.11

func (w *WasmClient) SetLastOperationID(id string)

func (*WasmClient) Shortcuts

func (w *WasmClient) Shortcuts() []map[string]string

func (*WasmClient) ShouldCompileToWasm

func (w *WasmClient) ShouldCompileToWasm(fileName, filePath string) bool

ShouldCompileToWasm determines if a file should trigger WASM compilation

func (*WasmClient) SupportedExtensions

func (w *WasmClient) SupportedExtensions() []string

func (*WasmClient) TinyGoCompiler

func (w *WasmClient) TinyGoCompiler() bool

TinyGoCompiler returns if TinyGo compiler should be used (dynamic based on configuration)

func (*WasmClient) UnobservedFiles

func (w *WasmClient) UnobservedFiles() []string

UnobservedFiles returns files that should not be watched for changes e.g: main.wasm

func (*WasmClient) Value

func (w *WasmClient) Value() string

Value returns the current compiler mode shortcut (c, d, or p)

func (*WasmClient) VerifyTinyGoInstallation

func (t *WasmClient) VerifyTinyGoInstallation() error

VerifyTinyGoInstallation checks if TinyGo is properly installed

func (*WasmClient) VerifyTinyGoProjectCompatibility

func (w *WasmClient) VerifyTinyGoProjectCompatibility()

VerifyTinyGoProjectCompatibility checks if the project is compatible with TinyGo compilation

func (*WasmClient) VisualStudioCodeWasmEnvConfig

func (w *WasmClient) VisualStudioCodeWasmEnvConfig()

VisualStudioCodeWasmEnvConfig automatically creates and configures VS Code settings for WASM development. This method resolves the "could not import syscall/js" error by setting proper environment variables in .vscode/settings.json file. On Windows, the .vscode directory is made hidden for a cleaner project view. This configuration enables VS Code's Go extension to properly recognize WASM imports and provide accurate IntelliSense, error detection, and code completion for syscall/js and other WASM-specific packages.

func (*WasmClient) WasmExecJsOutputPath

func (w *WasmClient) WasmExecJsOutputPath() string

WasmExecJsOutputPath returns the output path for wasm_exec.js

func (*WasmClient) WasmProjectTinyGoJsUse

func (w *WasmClient) WasmProjectTinyGoJsUse(mode ...string) (isWasmProject bool, useTinyGo bool)

WasmProjectTinyGoJsUse returns dynamic state based on current configuration

Directories

Path Synopsis
benchmark
shared command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL