package theater:simple;
/// # WebSocket Server Interface
///
/// The `websocket-server` interface provides capabilities for handling WebSocket connections,
/// receiving messages, and sending responses. It allows actors to implement real-time
/// bidirectional communication with web clients.
///
/// ## Purpose
///
/// This interface enables actors to build WebSocket-based applications such as chat servers,
/// real-time dashboards, collaborative tools, and streaming data services. It handles the
/// WebSocket protocol details and exposes a simple event-driven API for actors to process
/// messages and maintain connections.
///
/// ## Example
///
/// ```wit
/// // Using the websocket-server interface in a WIT definition
/// use theater:simple/websocket-server;
///
/// // Implementing the interface in Rust
/// impl websocket_server::Guest for MyActor {
/// fn handle_message(state: State, params: (websocket_server::WebsocketMessage,))
/// -> Result<(State, (websocket_server::WebsocketResponse,)), String> {
/// // Process the message and update state
/// // Return updated state and response
/// }
/// }
/// ```
///
/// ## Security
///
/// WebSocket connections can be long-lived and consume server resources, so implementations
/// should consider rate limiting, connection timeouts, and payload size limits. Validate
/// all incoming data and be cautious about trusting client-provided information.
///
/// ## Implementation Notes
///
/// The actor must implement the `handle_message` function, which is called for every
/// WebSocket event (connection, message, disconnection). The actor maintains its state
/// across these invocations, allowing it to track connected clients and conversation history.
/// Interface for handling WebSocket connections and messages
interface websocket-server {
/// The type of WebSocket message/event
///
/// ## Purpose
///
/// This enum represents the different types of WebSocket events that can occur,
/// including text and binary messages, connection events, and protocol control messages.
/// It allows actors to differentiate between different kinds of events and handle them
/// appropriately.
///
/// ## Example
///
/// ```rust
/// // In Rust actor code
/// match message.ty {
/// MessageType::Text => { /* Handle text message */ },
/// MessageType::Binary => { /* Handle binary message */ },
/// MessageType::Connect => { /* Handle new connection */ },
/// MessageType::Close => { /* Handle connection closed */ },
/// // Handle other message types
/// }
/// ```
variant message-type {
/// A text message
text,
/// A binary message
binary,
/// A new connection was established
connect,
/// The connection was closed
close,
/// A ping message (for keep-alive)
ping,
/// A pong message (response to ping)
pong,
/// Any other message type
other(string),
}
/// Represents a message sent or received over a WebSocket connection
///
/// ## Purpose
///
/// This record encapsulates the data for a WebSocket message or event, including its
/// type and payload (which can be either text or binary). It's the primary data structure
/// used for communication in the WebSocket system.
///
/// ## Example
///
/// ```rust
/// // In Rust actor code
/// if message.ty == MessageType::Text {
/// if let Some(text) = &message.text {
/// println!("Received text message: {}", text);
/// }
/// } else if message.ty == MessageType::Binary {
/// if let Some(data) = &message.data {
/// println!("Received binary message of {} bytes", data.len());
/// }
/// }
/// ```
///
/// ## Implementation Notes
///
/// For text messages, the `text` field will be populated and the `data` field will be None.
/// For binary messages, the `data` field will be populated and the `text` field will be None.
/// For control messages (connect, close, ping, pong), both fields may be None.
record websocket-message {
/// The type of the message
ty: message-type,
/// Binary data payload (used for binary messages)
data: option<list<u8>>,
/// Text payload (used for text messages)
text: option<string>,
}
/// Response containing messages to send back over the WebSocket
///
/// ## Purpose
///
/// This record contains the messages that the actor wants to send back to connected
/// WebSocket clients. It allows actors to respond to incoming messages or send
/// unsolicited messages to connected clients.
///
/// ## Example
///
/// ```rust
/// // In Rust actor code
/// let response = WebsocketResponse {
/// messages: vec![
/// WebsocketMessage {
/// ty: MessageType::Text,
/// data: None,
/// text: Some("Hello, client!".to_string()),
/// },
/// ],
/// };
/// ```
///
/// ## Implementation Notes
///
/// The response can contain multiple messages, which will be sent to the client in order.
/// An empty list means no messages will be sent back to the client.
record websocket-response {
/// List of messages to send back to the client
messages: list<websocket-message>,
}
/// Called for each event on the WebSocket (connections, messages, disconnections)
///
/// ## Purpose
///
/// This function is the core of the WebSocket interface. It's called by the Theater runtime
/// whenever a WebSocket event occurs (new connection, incoming message, disconnection). The
/// actor implements this function to handle the events, update its state, and respond to clients.
///
/// ## Parameters
///
/// * `state` - The current state of the actor
/// * `params` - A tuple containing the WebSocket message that triggered this call
///
/// ## Returns
///
/// * `Ok(tuple<state, tuple<websocket-response>>)` - The updated state and response to send
/// * `Err(string)` - An error message if processing fails
///
/// ## Example
///
/// ```rust
/// // In Rust actor code
/// fn handle_message(
/// state: State,
/// params: (WebsocketMessage,)
/// ) -> Result<(State, (WebsocketResponse,)), String> {
/// let message = ¶ms.0;
///
/// // Handle a text message
/// if message.ty == MessageType::Text {
/// if let Some(text) = &message.text {
/// // Echo the message back to the client
/// let response = WebsocketResponse {
/// messages: vec![
/// WebsocketMessage {
/// ty: MessageType::Text,
/// data: None,
/// text: Some(format!("You said: {}", text)),
/// },
/// ],
/// };
///
/// return Ok((state, (response,)));
/// }
/// }
///
/// // Handle a new connection
/// if message.ty == MessageType::Connect {
/// // Send a welcome message
/// let response = WebsocketResponse {
/// messages: vec![
/// WebsocketMessage {
/// ty: MessageType::Text,
/// data: None,
/// text: Some("Welcome to the WebSocket server!".to_string()),
/// },
/// ],
/// };
///
/// return Ok((state, (response,)));
/// }
///
/// // Return empty response for other message types
/// Ok((state, (WebsocketResponse { messages: vec![] },)))
/// }
/// ```
///
/// ## Security
///
/// Validate all incoming messages and don't trust client-provided data. Consider size limits
/// for message payloads and rate limiting to prevent abuse.
///
/// ## Implementation Notes
///
/// The function is called once for each WebSocket event. For efficient handling of multiple
/// connections, the actor should store connection IDs or other identifying information in its
/// state to track individual clients.
handle-message: func(state: option<list<u8>>, params: tuple<websocket-message>) -> result<tuple<option<list<u8>>, tuple<websocket-response>>, string>;
}