UNPKG

rwsdk

Version:

Build fast, server-driven webapps on Cloudflare with SSR, RSC, and realtime

79 lines (78 loc) 3.06 kB
import { getConnection } from "../connection/connection.js"; import { sendMessage, makeMessageId } from "../connection/messages.js"; import { manager } from "./clientManager.js"; export function createSyncedStateClient(endpoint, webSocketFactory) { const client = { async getState(key) { const connection = getConnection(endpoint, webSocketFactory); return sendMessage(connection, { kind: "getState", key, id: makeMessageId(connection), }); }, async setState(value, key) { const connection = getConnection(endpoint, webSocketFactory); await sendMessage(connection, { kind: "setState", key, value, id: makeMessageId(connection), }); }, async subscribe(key, handler) { manager.addSubscription(key, handler, client); const connection = getConnection(endpoint, webSocketFactory); let handlers = connection.messageHandlers.get(key); if (!handlers) { handlers = new Set(); connection.messageHandlers.set(key, handlers); } handlers.add(handler); if (connection.isOpen) { try { await sendMessage(connection, { kind: "subscribe", key, id: makeMessageId(connection), }); } catch (error) { // Roll back local subscription state so we don't pretend to be // subscribed when the server rejected or never processed it. handlers.delete(handler); if (handlers.size === 0) connection.messageHandlers.delete(key); manager.removeSubscription(key, handler, client); throw error; } } }, async unsubscribe(key, handler) { manager.removeSubscription(key, handler, client); const connection = manager.getConnection(endpoint); if (!connection) return; const handlers = connection.messageHandlers.get(key); if (handlers) { handlers.delete(handler); if (handlers.size === 0) connection.messageHandlers.delete(key); } try { if (connection.isOpen) { await sendMessage(connection, { kind: "unsubscribe", key, id: makeMessageId(connection), }); } } catch { // Unsubscribe is often called during cleanup. Swallow errors from a // closing socket; the server attachment will be dropped anyway. } }, }; return client; }