tiye/thin_ws is a thin WebSocket FFI package for MoonBit with typed JSON messaging.
- Node.js server: starts a
ws-based WebSocket server with UUID-keyed client registry. - Browser client: wraps the native
WebSocketAPI, auto-builds the backend URL for dev/prod.
Both sides speak typed MoonBit values. JSON serialization/deserialization is handled internally — callers never touch raw text.
let send = @thin_ws.run_json_server(
5022, // port — nothing hardcoded
"/ws", // path
fn(sid) { log("connect \{sid}") },
fn(sid, op : MyClientOp) { handle(sid, op) },
fn(sid) { log("disconnect \{sid}") },
)
// send a typed message to a client
send(sid, my_server_event)let url = @thin_ws.make_ws_url("5173,5174", 5022, "/ws")
let (socket, send) = @thin_ws.connect_json(
url,
fn() { log("opened") },
fn(payload : MyServerEvent) { apply_delta(payload) },
fn() { log("closed") },
)
// send a typed op to the server (no-op until the connection opens)
send(my_client_op)- Generic over message types —
In : @json.FromJson/Out : ToJson - No hardcoded ports or paths — all caller-supplied
- Ready guard on browser side —
sendis safe to call before the socket opens; messages are dropped silently - Log helpers —
server_log,ws_log,ws_warn,ws_errorwrite to runtime monitor and console
In your moon.pkg (or moon.pkg.json):
import {
"tiye/thin_ws" @thin_ws,
}
node_server.mbt compiles only for ["js"] target (Node.js).
browser_client.mbt compiles only for ["js"] target (browser).