// k6/ws MoonBit Facade
// WebSocket client for k6 load testing
///| WebSocket Connection
///|
/// WebSocket connection handle
pub struct Socket {
handle : @core.Any
}
///| WebSocket Events
///|
/// Event handler for WebSocket connection open
pub type OnOpenHandler = (@core.Any) -> Unit
///|
/// Event handler for WebSocket message
pub type OnMessageHandler = (@core.Any) -> Unit
///|
/// Event handler for WebSocket close
pub type OnCloseHandler = (@core.Any) -> Unit
///|
/// Event handler for WebSocket error
pub type OnErrorHandler = (@core.Any) -> Unit
///| WebSocket Params
///|
/// WebSocket connection parameters
pub struct WebSocketParams {
headers : Map[String, String]?
tags : Map[String, String]?
}
///|
/// Create default WebSocket params
pub fn WebSocketParams::default() -> WebSocketParams {
{ headers: None, tags: None }
}
///|
/// Convert Params to JS object
fn ws_params_to_js(params : WebSocketParams) -> @core.Any {
let obj = @core.new_object()
match params.headers {
Some(h) => {
let headers_obj = @core.new_object()
h.each(fn(key, value) { headers_obj[key] = @core.any(value) })
obj["headers"] = @core.any(headers_obj)
}
None => ()
}
match params.tags {
Some(t) => {
let tags_obj = @core.new_object()
t.each(fn(key, value) { tags_obj[key] = @core.any(value) })
obj["tags"] = @core.any(tags_obj)
}
None => ()
}
@core.any(obj)
}
///| WebSocket Response
///|
/// WebSocket connection response
pub struct WebSocketResponse {
url : String
status : Int
headers : @core.Any
}
///|
/// Create WebSocketResponse from JS object
fn ws_response_from_js(obj : @core.Any) -> WebSocketResponse {
let url : String = obj["url"].cast()
let status : Int = obj["status"].cast()
let headers = obj["headers"]
{ url, status, headers }
}
///| FFI Functions
///|
/// FFI: Connect to WebSocket
#module("k6/ws")
extern "js" fn ffi_connect(
url : String,
params : @core.Any,
callback : @core.Any
) -> @core.Any =
"connect"
///|
/// FFI: Send message
extern "js" fn ffi_socket_send(socket : @core.Any, data : String) -> Unit =
#|(socket, data) => socket.send(data)
///|
/// FFI: Close connection
extern "js" fn ffi_socket_close(socket : @core.Any) -> Unit =
#|(socket) => socket.close()
///|
/// FFI: Set event handlers
extern "js" fn ffi_socket_on(
socket : @core.Any,
event : String,
handler : @core.Any
) -> Unit =
#|(socket, event, handler) => socket.on(event, handler)
///|
/// FFI: Set timeout
extern "js" fn ffi_socket_set_timeout(socket : @core.Any, callback : @core.Any, delay : Int) -> Unit =
#|(socket, callback, delay) => socket.setTimeout(callback, delay)
///| Public API
///|
/// Connect to WebSocket server
/// The callback function receives a Socket object
pub fn connect(
url : String,
params : WebSocketParams,
callback : (Socket) -> Unit
) -> WebSocketResponse {
let params_obj = ws_params_to_js(params)
let wrapped_callback : @core.Any = @core.any(fn(socket_obj : @core.Any) {
let socket = { handle: socket_obj }
callback(socket)
})
let res = ffi_connect(url, params_obj, wrapped_callback)
ws_response_from_js(res)
}
///|
/// Send message to WebSocket server
pub fn Socket::send(self : Socket, data : String) -> Unit {
ffi_socket_send(self.handle, data)
}
///|
/// Close WebSocket connection
pub fn Socket::close(self : Socket) -> Unit {
ffi_socket_close(self.handle)
}
///|
/// Set event handler for WebSocket events
/// Events: "open", "message", "close", "error"
pub fn Socket::on(self : Socket, event : String, handler : @core.Any) -> Unit {
ffi_socket_on(self.handle, event, handler)
}
///|
/// Set timeout for WebSocket connection
pub fn Socket::set_timeout(
self : Socket,
callback : () -> Unit,
delay : Int
) -> Unit {
let wrapped : @core.Any = @core.any(callback)
ffi_socket_set_timeout(self.handle, wrapped, delay)
}