Server SDKs
Go SDK
Server-side Hypen SDK for Go applications
Go SDK
The Go SDK provides a complete server-side Hypen implementation for Go applications with reactive state management, routing, and Remote UI streaming.
Installation
go get github.com/hypen-lang/hypen-golangQuick Start
package main
import (
"github.com/hypen-lang/hypen-golang/core"
"github.com/hypen-lang/hypen-golang/remote"
)
func main() {
// Create a counter module
counter := core.NewAppBuilder(map[string]any{"count": 0}, nil).
OnAction("increment", func(ctx core.ActionHandlerContext) {
count := ctx.State.Get("count").(int)
ctx.State.Set("count", count+1)
}).
OnAction("decrement", func(ctx core.ActionHandlerContext) {
count := ctx.State.Get("count").(int)
ctx.State.Set("count", count-1)
}).
Build()
// Start Remote UI server
server := remote.NewServer(counter)
server.Listen(":3000")
}State Management
The SDK provides reactive ObservableState with automatic change tracking:
// Create observable state
state := core.NewObservableState(map[string]any{
"user": map[string]any{
"name": "Alice",
"email": "alice@example.com",
},
"items": []string{},
}, &core.StateObserverOptions{
OnChange: func(change core.StateChange) {
fmt.Printf("Changed paths: %v\n", change.Paths)
},
})
// Get values
name := state.Get("user.name").(string)
// Set values (triggers OnChange)
state.Set("user.name", "Bob")
// Batch multiple updates
state.BatchUpdate(func() {
state.Set("user.name", "Charlie")
state.Set("user.email", "charlie@example.com")
})Action Handlers
Action handlers receive a context object with access to state, routing, and global context:
counter := core.NewAppBuilder(initialState, nil).
OnAction("submit", func(ctx core.ActionHandlerContext) {
// Access action details
payload := ctx.Action.Payload.(map[string]any)
// Modify state
ctx.State.Set("submitted", true)
// Navigate
ctx.Next.Router.Push("/success")
// Access other modules
auth := ctx.Context.GetModule("auth")
if auth != nil {
// ...
}
}).
Build()Handler Context
| Field | Type | Description |
|---|---|---|
ctx.Action.Name | string | Action name |
ctx.Action.Payload | any | Action payload |
ctx.Action.Sender | string | Sender component ID |
ctx.State | *ObservableState | Reactive state |
ctx.Next.Router | *HypenRouter | Router for navigation |
ctx.Context | GlobalContext | Cross-module access |
Routing
The HypenRouter provides URL-based navigation with pattern matching:
router := core.NewHypenRouter("/")
// Navigate
router.Push("/users/123")
router.Replace("/login")
router.Back()
router.Forward()
// Get current route
route := router.CurrentRoute()
fmt.Println(route.Path) // "/users/123"
fmt.Println(route.Params) // map[string]string{}
// Pattern matching
match, params := router.MatchPath("/users/:id")
// match = true, params = {"id": "123"}
// Listen for route changes
router.OnRouteChange(func(route core.Route) {
fmt.Printf("Navigated to: %s\n", route.Path)
})Event System
The SDK includes a typed event emitter for pub/sub messaging:
emitter := core.CreateEventEmitter()
// Subscribe to events
unsubscribe := emitter.On("userLoggedIn", func(payload any) {
user := payload.(map[string]any)
fmt.Printf("User logged in: %s\n", user["name"])
})
// Emit events
emitter.Emit("userLoggedIn", map[string]any{"name": "Alice"})
// Unsubscribe
unsubscribe()
// One-time listener
emitter.Once("ready", func(payload any) {
fmt.Println("Ready!")
})Remote UI Server
Stream UI updates over WebSocket:
import "github.com/hypen-lang/hypen-golang/remote"
// Create server with your module
server := remote.NewServer(myModule)
// Configure options
server.SetOptions(remote.ServerOptions{
HeartbeatInterval: 30 * time.Second,
MaxConnections: 1000,
})
// Custom HTTP handler integration
http.HandleFunc("/ws", server.HandleWebSocket)
http.ListenAndServe(":3000", nil)Client Messages
The server handles these client messages:
| Type | Description |
|---|---|
dispatchAction | Dispatch an action from the client |
ping | Heartbeat ping |
Server Messages
The server sends these messages:
| Type | Description |
|---|---|
initialTree | Full UI tree on connect |
patch | Incremental UI updates |
stateUpdate | State changes |
pong | Heartbeat response |
Testing
Use MockEngine to test modules without the full WASM engine:
func TestCounter(t *testing.T) {
// Create mock engine
engine := core.NewMockEngine()
// Build module with mock
counter := core.NewAppBuilder(map[string]any{"count": 0}, engine).
OnAction("increment", func(ctx core.ActionHandlerContext) {
count := ctx.State.Get("count").(int)
ctx.State.Set("count", count+1)
}).
Build()
// Trigger action
engine.TriggerAction("increment", nil)
// Verify state
count := counter.State().Get("count").(int)
if count != 1 {
t.Errorf("Expected count=1, got %d", count)
}
}Component Loading
Discover and load .hypen components from the filesystem:
// Load all components from a directory
loader := core.NewComponentLoader("./components")
components, err := loader.LoadAll()
// Load specific component
component, err := loader.Load("Counter")Requirements
- Go 1.21+
- gorilla/websocket (for WebSocket support)