gowm
repoGoWM simplifies the integration of Go WebAssembly modules into your JavaScript projects.
README.md
GoWM - Go Wasm Manager
✨ Features
- 🚀 Loader System - Intelligent loader for all source types (files, URLs, GitHub)
- 🔧 Cross-Platform - Full support for Node.js and browser environments
- 🎯 Auto-Detection - Automatically detects source type and optimal loading strategy
- 📦 GitHub Direct Loading - Load WASM modules directly from GitHub repositories
- 🏷️ Version Control - Support for branches, tags, and specific commits
- 🛡️ Enhanced Error Handling - Robust error handling with fallback strategies
- 🧹 Smart Memory Management - Safe memory allocation and resource cleanup
- 📊 Comprehensive Statistics - Built-in monitoring, testing, and performance metrics
- 🔄 Flexible API - Both synchronous and asynchronous function calls
- 📝 TypeScript Support - Full TypeScript definitions included
- ⚛️ React Hooks -
useWasm()anduseWasmFromGitHub()hooks - 💚 Vue Composables -
useWasm()anduseWasmFromGitHub()composables - 🔧 CLI -
npx gowm list|info|types|verify|install - 📡 Event System -
on()/off()/once()/on('module:loaded'),on('module:error'),on('memory:warning')with chaining for module lifecycle events - 🏗️ Type Generator - Generate TypeScript interfaces from
module.json - ⚛️ React Hooks -
import { useWasm } from 'gowm/react'with auto-cleanup and reload - 💚 Vue 3 Composables -
import { useWasm } from 'gowm/vue'with reactive refs and watch - 🔧 CLI -
npx gowm list|info|types|verify|installfor module discovery and management - 🏗️ Type Generator -
generateTypes()creates TypeScript interfaces frommodule.json - 📦 ESM Exports Map - Sub-path exports
gowm/react,gowm/vue,gowm/tools/type-generator - 📋 TypeScript Definitions - Dedicated
types/react.d.tsandtypes/vue.d.ts - 📋 Module Metadata - Automatic
module.jsonfetching from GitHub repositories - 🔒 SHA256 Integrity - WASM file integrity verification via
.wasm.integrityfiles (SRI format) - 🎯 readySignal Auto-Discovery - Uses
gowmConfig.readySignalfrom metadata instead of generic polling - ✅ Function Call Validation - Parameter count validation, type warnings in debug mode
- 📖
describe()Documentation - Inline documentation for functions (bridge.describe('add')) - 📊
getDetailedFunctions()- Rich function listing with parameters, types, examples - 🗂️
getFunctionCategories()- Organized function categories from metadata - 💾 Multi-Level Cache - Memory (L1) + disk/IndexedDB (L2) caching with configurable TTL
- 🔁 Retry with Backoff - Automatic retry with exponential backoff on network failures
- ⚡ Streaming Instantiation -
WebAssembly.instantiateStreaming()for HTTP loads (compile during download) - 🎯 Promise-Based Readiness - Callback-first signals with adaptive polling fallback
- 📦 Compressed WASM - Auto-detect and decompress
.wasm.gzand.wasm.brfiles - 🔒 Module Namespace Isolation - Each module gets its own namespace via
globalThis.__gowm_modules_ - 🌿 Auto Branch Detection - GitHub default branch auto-detected via API
- 🔍 Improved Source Detection - Strict local path and GitHub URL detection
- 📝 Configurable Logging - Log levels with custom logger support
- 🛡️ Safe Memory Allocation - Removed unsafe offset-based fallback
- 🧪 274 Unit Tests - Extended coverage for all features
📥 Installation
npm install gowm # or yarn add gowm # or pnpm add gowm
🚀 Quick Start
Node.js Example
const { GoWM } = require("gowm"); async function example() { try { // Create a GoWM instance with configurable logging const gowm = new GoWM({ logLevel: "info" }); // Load from GitHub repository (branch auto-detected) // module.json metadata fetched, SHA256 integrity verified const math = await gowm.loadFromGitHub( "benoitpetit/wasm-modules-repository", { name: "math", path: "math-wasm", retries: 3, // retry on network failure cache: { ttl: 3600000 }, // cache for 1 hour // metadata: true, // auto-fetch module.json (default) // integrity: true, // verify SHA256 hash (default) // validateCalls: true, // validate parameters (default) }, ); // Call functions (parameters validated against metadata) const result = math.call("add", 5, 3); console.log("5 + 3 =", result); // 8 // Describe a function from module.json metadata const desc = gowm.describeFunction("math", "add"); console.log(desc); // { name: 'add', description: '...', parameters: [...], returnType: '...' } // Get detailed function list with metadata const functions = math.getDetailedFunctions(); console.log("Functions:", functions.length); // Get function categories const categories = math.getFunctionCategories(); console.log("Categories:", Object.keys(categories)); // Module metadata const metadata = gowm.getModuleMetadata("math"); console.log(`${metadata.name} v${metadata.version}`); // Load from HTTP URL (uses streaming instantiation when possible) const remoteWasm = await gowm.loadFromUrl( "https://example.com/module.wasm", ); // Load from local file const localWasm = await gowm.load("./math.wasm", { name: "local-math" }); // Disable cache for a specific load const freshLoad = await gowm.load("./module.wasm", { cache: false }); // Async calls const asyncResult = await math.callAsync("multiply", 4, 7); console.log("4 * 7 =", asyncResult); // 28 // Check available functions if (math.hasFunction("divide")) { console.log("divide function is available"); } // Get comprehensive statistics const stats = math.getStats(); console.log("Available functions:", stats.functions); console.log("Memory usage:", stats.memoryUsage); // Clear the cache await gowm.clearCache(); } catch (error) { console.error("Error:", error); } } example();
🔄 Loader System
GoWM features a loader system that handles all source types with a single API:
Auto-Detection
const { load } = require("gowm"); // Automatically detects source type await load("owner/repo"); // → GitHub repository await load("https://example.com/module.wasm"); // → HTTP URL await load("./local/module.wasm"); // → Local file await load("/absolute/path/module.wasm"); // → Absolute path
Specific Loading Methods
const { loadFromFile, loadFromUrl, loadFromGitHub } = require("gowm"); // Explicit methods for specific sources await loadFromFile("./module.wasm"); // Node.js only await loadFromUrl("https://example.com/mod.wasm"); // HTTP/HTTPS await loadFromGitHub("owner/repo", options); // GitHub repository
🐙 GitHub Repository Loading
GoWM excels at loading WASM modules directly from GitHub repositories with intelligent file discovery and automatic default branch detection:
const { GoWM } = require("gowm"); const gowm = new GoWM(); async function examples() { // Basic loading — branch auto-detected via GitHub API const math = await gowm.loadFromGitHub( "benoitpetit/wasm-modules-repository", { path: "math-wasm", }, ); // Advanced loading with specific options const crypto = await gowm.loadFromGitHub( "benoitpetit/wasm-modules-repository", { path: "crypto-wasm", filename: "main.wasm", name: "crypto-processor", timeout: 30000, // Custom timeout }, ); // Load from full GitHub URL const image = await gowm.loadFromGitHub( "https://github.com/benoitpetit/wasm-modules-repository", { path: "image-wasm", filename: "main.wasm", }, ); }
Automatic File Discovery
GoWM automatically searches for WASM files in these locations:
- Root directory:
main.wasm,index.wasm,{repo-name}.wasm - Common folders:
wasm/,dist/,build/ - GitHub releases: Searches release assets for WASM files
- Custom paths: Respects your specified path and filename
📚 API Reference
Core Functions
load(source, options)
Universal loading function that auto-detects source type.
Parameters:
source(string): Can be file path, HTTP URL, or GitHub repooptions(object, optional):name(string): Module identifiertimeout(number): Initialization timeout (default: 15000ms)preInit(boolean): Pre-initialize module (default: true)goRuntimePath(string): Custom path to wasm_exec.js
Returns: Promise
loadFromGitHub(githubRepo, options)
Loads a WASM module from a GitHub repository with automatic file resolution.
Parameters:
githubRepo(string): GitHub repository ("owner/repo" or full GitHub URL)options(object, optional):name(string): Module identifier (default: repository name)branch(string): Git branch (default: auto-detected via GitHub API)tag(string): Git tag (takes precedence over branch)path(string): Path within repository (default: '')filename(string): Specific filename (default: auto-detect)timeout(number): Initialization timeout (default: 15000ms)goRuntimePath(string): Custom path to wasm_exec.jspreInit(boolean): Pre-initialize the module (default: true)metadata(boolean): Fetch module.json metadata (default: true)integrity(boolean): Verify SHA256 integrity (default: true)validateCalls(boolean): Validate function parameters (default: true)
Returns: Promise
loadFromUrl(url, options)
Loads a WASM module from HTTP/HTTPS URL.
Parameters:
url(string): HTTP/HTTPS URL to WASM fileoptions(object, optional): Same asload()options
Returns: Promise
loadFromFile(filePath, options)
Loads a WASM module from local file (Node.js only).
Parameters:
filePath(string): Path to the .wasm fileoptions(object, optional): Same asload()options
Returns: Promise
get(name)
Retrieves an already loaded module by name.
Parameters:
name(string, optional): Module name (default: 'default')
Returns: UnifiedWasmBridge | null
Enhanced Bridge Methods
The bridge provides comprehensive functionality:
call(funcName, ...args)
Calls a WASM function synchronously. Validates parameter count and types (debug mode) against module.json metadata.
callAsync(funcName, ...args)
Calls a WASM function asynchronously.
describe(funcName)
Returns inline documentation for a function from module.json metadata.
Returns: { name, description, category, parameters, returnType, example, errorPattern } or null
getDetailedFunctions()
Returns all functions with their full metadata (parameters, types, descriptions).
Returns: Array<{ name, description, category, parameters, returnType, example }>
getMetadata()
Returns the raw module.json metadata object.
getFunctionCategories()
Returns function categories from metadata.
Returns: { [category: string]: string[] } or null
createBuffer(data)
Creates a buffer for data transfer with enhanced type support.
Supported Types:
Float64Array,Float32ArrayUint8Array,Uint16Array,Uint32ArrayInt8Array,Int16Array,Int32ArrayArray,string
test()
Runs comprehensive tests on the module.
Returns: Object with test results:
{ functionCalls: boolean, memoryAllocation: boolean, callbacks: boolean, asyncCalls: boolean, errors: string[] }
getStats()
Gets comprehensive module statistics.
Returns: Object with detailed statistics:
{ name: string, ready: boolean, environment: 'Node.js' | 'Browser', functions: string[], callbacks: string[], allocatedBuffers: number, memoryUsage: { total: number, wasm: number, go: number, buffers: number, buffersCount: number }, supportedDataTypes: string[], loadedAt: string }
Utility Functions
listModules(): List all loaded modulesgetStats(): Get statistics for all modulesunload(name): Unload a specific moduleunloadAll(): Unload all modulesisLoaded(name): Check if a module is loadedgetTotalMemoryUsage(): Get total memory usagetestAll(): Test all loaded modulesgetHelp(): Get comprehensive help informationgetVersion(): Get GoWM version stringclearCache(): Clear all cached WASM bytesgetModuleMetadata(name): Get module.json metadatadescribeFunction(moduleName, funcName): Describe a function from metadataon(event, callback): Register event listeneroff(event, callback): Remove event listeneronce(event, callback): One-time event listenergenerateTypes(metadata, options): Generate TypeScript typesgenerateTypesFromGitHub(repo, options): Generate types from GitHub
🌐 Browser Usage
For browser environments, GoWM automatically optimizes for the browser:
<!DOCTYPE html> <html> <head> <script type="module"> import { loadFromGitHub } from "./node_modules/gowm/src/browser.js"; async function init() { const wasm = await loadFromGitHub( "benoitpetit/wasm-modules-repository", { path: "math-wasm", }, ); const result = wasm.call("add", 21, 21); console.log("21 + 21 =", result); // 42 } init(); </script> </head> <body> <h1>GoWM Browser Example</h1> </body> </html>
Global Usage
<script src="path/to/gowm/src/browser.js"></script> <script> GoWM.loadFromUrl("https://example.com/module.wasm"); </script>
📡 Event System
Monitor module lifecycle with event listeners:
const gowm = new GoWM({ memoryWarningThreshold: 50 * 1024 * 1024 }); gowm .on("module:loading", ({ name, source }) => console.log(`Loading ${name}...`)) .on("module:loaded", ({ name, loadTime }) => console.log(`Loaded in ${loadTime}ms`), ) .on("module:error", ({ name, error }) => console.error(`Failed: ${error.message}`), ) .on("module:unloaded", ({ name }) => console.log(`Unloaded ${name}`)) .on("memory:warning", ({ totalMemory, threshold }) => console.warn("Memory warning!"), ); // One-time listener gowm.once("module:loaded", ({ name }) => console.log(`First module loaded: ${name}`), ); // Remove listener const handler = (data) => console.log(data); gowm.on("module:loaded", handler); gowm.off("module:loaded", handler);
⚛️ React Hooks
npm install gowm react
import { useWasm, useWasmFromGitHub } from "gowm/react"; function Calculator() { const { bridge, loading, error, reload } = useWasmFromGitHub( "benoitpetit/wasm-modules-repository", { path: "math-wasm" }, ); if (loading) return <p>Loading...</p>; if (error) return <p>Error: {error.message}</p>; return ( <div> <p>5 + 3 = {bridge.call("add", 5, 3)}</p> <button onClick={reload}>Reload</button> </div> ); }
💚 Vue 3 Composables
npm install gowm vue
<script setup> import { useWasmFromGitHub } from "gowm/vue"; const { bridge, loading, error, metadata, reload } = useWasmFromGitHub( "benoitpetit/wasm-modules-repository", { path: "math-wasm" }, ); </script> <template> <p v-if="loading">Loading...</p> <p v-else-if="error">Error: {{ error.message }}</p> <div v-else> <p>{{ metadata?.name }} v{{ metadata?.version }}</p> <p>5 + 3 = {{ bridge.call("add", 5, 3) }}</p> <button @click="reload">Reload</button> </div> </template>
🔧 CLI
# List available modules in a repository npx gowm list benoitpetit/wasm-modules-repository # Get module info from module.json npx gowm info benoitpetit/wasm-modules-repository math-wasm # Generate TypeScript types from module.json npx gowm types benoitpetit/wasm-modules-repository math-wasm --out math-wasm.d.ts # Verify WASM file integrity npx gowm verify ./main.wasm --integrity sha256-xxxxxxxxx # Download a module (wasm + module.json + integrity) npx gowm install benoitpetit/wasm-modules-repository math-wasm --dir ./wasm
🏗️ Type Generator
Generate TypeScript interfaces from module.json:
const { generateTypes, generateTypesFromGitHub } = require("gowm"); // From a metadata object const ts = generateTypes(metadata, { includeJSDoc: true }); // From GitHub const ts = await generateTypesFromGitHub( "benoitpetit/wasm-modules-repository/math-wasm", { branch: "master" }, );
Generated output:
import { WasmBridge } from "gowm"; /** math-wasm v0.2.0 - Mathematical functions */ export interface MathWasmBridge extends WasmBridge { /** Add two numbers */ call(func: "add", a: number, b: number): number; /** Calculate factorial */ call(func: "factorial", n: number): number; // ... }
🏗️ Architecture
GoWM features a clean architecture:
src/
├── core/gowm.js # Main GoWM class (events, logging)
├── loaders/unified-loader.js # Universal loading system with metadata & integrity
├── bridges/unified-bridge.js # Namespace-aware bridge with validation & describe()
├── react/index.js # React hooks (useWasm, useWasmFromGitHub)
├── vue/index.js # Vue 3 composables (useWasm, useWasmFromGitHub)
├── cli/gowm-cli.js # CLI (list, info, types, verify, install)
├── tools/type-generator.js # TypeScript type generation from module.json
├── index.js # Main entry point
└── browser.js # Browser-optimized entry
types/
├── index.d.ts # Core TypeScript definitions
├── react.d.ts # React hooks types
└── vue.d.ts # Vue composables types
📊 Examples
Check out the /examples directory for comprehensive examples:
- Node.js examples: Basic, crypto, text, and JSON/XML usage patterns
- Browser examples: Vanilla JavaScript implementations
Running Examples
# Run basic Node.js example npm run test:basic # Run crypto example npm run test:crypto # Serve browser examples npm run demo:serve
🔧 Development
Running Tests
# Run all unit tests npm test # Run tests with coverage report npm run test:coverage # Run all tests (unit + integration + examples) npm run test:all
Testing Your Modules
const { GoWM } = require("gowm"); const gowm = new GoWM({ logLevel: "debug" }); // Load and test a module const module = await gowm.load("your-module.wasm"); const testResults = module.test(); console.log("Test results:", testResults); // Get comprehensive statistics const stats = gowm.getStats(); console.log("System stats:", stats);
Custom Loading
const { WasmLoader, WasmBridge } = require("gowm"); // Use components directly for advanced scenarios const loader = new WasmLoader(); const module = await loader.loadModule("source"); const bridge = new WasmBridge(module, { moduleId: "my-module" });
📄 License
MIT License - see the LICENSE file for details.
