UNPKG

tauri-plugin-centrifugo-api

Version:

Tauri plugin for Centrifugo real-time communication using tokio-centrifuge

285 lines (282 loc) 8.76 kB
import { invoke } from '@tauri-apps/api/core'; import { listen } from '@tauri-apps/api/event'; /** * Connect to Centrifugo */ async function connect(config) { return await invoke('plugin:centrifugo|connect', { config }); } /** * Disconnect from Centrifugo */ async function disconnect() { return await invoke('plugin:centrifugo|disconnect'); } /** * Set authentication token */ async function setToken(token) { return await invoke('plugin:centrifugo|set_token', { token }); } /** * Publish message to channel */ async function publish(request) { return await invoke('plugin:centrifugo|publish', { request }); } /** * Execute RPC call */ async function rpc(request) { return await invoke('plugin:centrifugo|rpc', { request }); } /** * Get presence information for channel */ async function presence(request) { return await invoke('plugin:centrifugo|presence', { request }); } /** * Get presence statistics for channel */ async function presenceStats(request) { return await invoke('plugin:centrifugo|presence_stats', { request }); } /** * Get message history for channel */ async function history(request) { return await invoke('plugin:centrifugo|history', { request }); } /** * Send message to server */ async function send(request) { return await invoke('plugin:centrifugo|send', { request }); } /** * Refresh authentication token */ async function refresh(request) { return await invoke('plugin:centrifugo|refresh', { request }); } /** * Refresh subscription token */ async function subRefresh(request) { return await invoke('plugin:centrifugo|sub_refresh', { request }); } /** * Ping server */ async function ping() { return await invoke('plugin:centrifugo|ping'); } /** * Check if connected to Centrifugo */ async function isConnected() { return await invoke('plugin:centrifugo|is_connected'); } /** * Get current subscriptions */ async function getSubscriptions() { return await invoke('plugin:centrifugo|get_subscriptions'); } /** * Get connection state */ async function getConnectionState() { return await invoke('plugin:centrifugo|get_connection_state'); } /** * Add new subscription to channel */ async function addSubscription(channel) { return await invoke('plugin:centrifugo|add_subscription', { channel }); } /** * Remove subscription from channel */ async function removeSubscription(channel) { return await invoke('plugin:centrifugo|remove_subscription', { channel }); } /** * Listen to Centrifugo events */ async function onCentrifugoEvent(event, callback) { return await listen(`centrifugo:${event}`, callback); } // Event listener helpers const onConnecting = async (callback) => await onCentrifugoEvent('connecting', callback); const onConnected = async (callback) => await onCentrifugoEvent('connected', callback); const onDisconnected = async (callback) => await onCentrifugoEvent('disconnected', callback); const onError = async (callback) => await onCentrifugoEvent('error', callback); const onSubscribed = async (callback) => await onCentrifugoEvent('subscribed', callback); const onUnsubscribed = async (callback) => await onCentrifugoEvent('unsubscribed', callback); const onSubscribing = async (callback) => await onCentrifugoEvent('subscribing', callback); const onPublication = async (callback) => await onCentrifugoEvent('publication', callback); // Convenient event listeners for messages const onMessage = async (callback) => await onCentrifugoEvent('publication', (pubData) => { try { const decodedData = utils.decodeJson(pubData.payload.data); callback({ channel: pubData.payload.channel, data: decodedData }); } catch (error) { // If failed to decode JSON, return raw data callback({ channel: pubData.payload.channel, data: pubData.payload.data }); } }); const onChannelMessage = async (channel, callback) => await onCentrifugoEvent('publication', (pubData) => { if (pubData.payload.channel === channel) { try { const decodedData = utils.decodeJson(pubData.payload.data); callback(decodedData); } catch (error) { // If failed to decode JSON, return raw data callback(pubData.payload.data); } } }); const onAnyMessage = async (callback) => await onCentrifugoEvent('publication', (pubData) => { try { const decodedData = utils.decodeJson(pubData.payload.data); callback({ channel: pubData.payload.channel, data: decodedData, timestamp: Date.now() }); } catch (error) { callback({ channel: pubData.payload.channel, data: pubData.payload.data, timestamp: Date.now() }); } }); // Utility functions for base64 encoding/decoding const utils = { /** * Encode string to base64 */ encode: (data) => { if (typeof window !== 'undefined' && window.btoa) { return window.btoa(data); } throw new Error('btoa not available in this environment'); }, /** * Decode base64 to string */ decode: (data) => { if (typeof window !== 'undefined' && window.atob) { return window.atob(data); } throw new Error('atob not available in this environment'); }, /** * Encode object to base64 JSON */ encodeJson: (data) => { const jsonString = JSON.stringify(data); return utils.encode(jsonString); }, /** * Decode base64 JSON to object */ decodeJson: (data) => { const jsonString = utils.decode(data); return JSON.parse(jsonString); } }; // Convenience methods for common operations const helpers = { /** * Publish JSON data to channel (automatically encodes to base64) */ publishJson: async (channel, data) => { const base64Data = utils.encodeJson(data); await publish({ channel, data: base64Data }); }, /** * Execute RPC with JSON data (automatically encodes/decodes) */ rpcJson: async (method, data) => { const base64Data = utils.encodeJson(data); const result = await rpc({ method, data: base64Data }); return utils.decodeJson(result); }, /** * Subscribe to channel and listen for messages */ subscribeToChannel: async (channel, callback) => { await addSubscription(channel); return await onChannelMessage(channel, callback); }, /** * Subscribe to multiple channels */ subscribeToChannels: async (channels, callback) => { const unlisteners = []; for (const channel of channels) { await addSubscription(channel); const unlisten = await onChannelMessage(channel, (data) => { callback({ channel, data }); }); unlisteners.push(unlisten); } return unlisteners; }, /** * Wait for connection to be established */ waitForConnection: async (timeout = 10000) => { return new Promise((resolve) => { const startTime = Date.now(); const checkConnection = async () => { try { const connected = await isConnected(); if (connected) { resolve(true); return; } if (Date.now() - startTime > timeout) { resolve(false); return; } setTimeout(checkConnection, 100); } catch { resolve(false); } }; checkConnection(); }); }, /** * Get connection status with retry */ getConnectionStatus: async (retries = 3) => { for (let i = 0; i < retries; i++) { try { return await getConnectionState(); } catch (error) { if (i === retries - 1) throw error; await new Promise(resolve => setTimeout(resolve, 100)); } } throw new Error('Failed to get connection status'); } }; export { addSubscription, connect, disconnect, getConnectionState, getSubscriptions, helpers, history, isConnected, onAnyMessage, onCentrifugoEvent, onChannelMessage, onConnected, onConnecting, onDisconnected, onError, onMessage, onPublication, onSubscribed, onSubscribing, onUnsubscribed, ping, presence, presenceStats, publish, refresh, removeSubscription, rpc, send, setToken, subRefresh, utils };