@sofya-sdk/react
v1.1.0
Published
React hooks for Sofya SDK
Downloads
16
Maintainers
Readme
@sofya-sdk/react
React hooks for Sofya SDK - Plug-and-play integration for real-time EventRooms messaging.
Installation
pnpm add @sofya-sdk/react
# or
npm install @sofya-sdk/react
# or
yarn add @sofya-sdk/reactHooks
useCanal()
Creates a canal (room) via the backend API. Used by the receptor (desktop) side.
import { useCanal } from '@sofya-sdk/react';
function Receptor() {
const { canalId, qrCodeUrl, qrCodeBucketLink, loading, error } = useCanal({
backendUrl: 'https://api.sofya.app',
apiKey: process.env.REACT_APP_API_KEY || 'your-api-key',
autoCreate: true, // Auto-create on mount (default: true)
});
if (loading) return <div>Creating canal...</div>;
if (error) return <div>Error: {error.message}</div>;
return <QRCode value={qrCodeUrl} />;
}Options:
backendUrl(string, required) - Backend API base URLapiKey(string, required) - API key for authentication (x-api-key header)autoCreate(boolean, optional) - Auto-create canal on mount (default: true)
Returns:
canalId- Canal IDqrCodeUrl- PWA URL with canal parameterqrCodeBucketLink- QR code image URL from bucketmessagingEndpoint- Messaging WebSocket endpoint derived from the backend contractcontract- Normalized backend contract (STT, QR code assets, EventRooms)loading- Loading stateerror- Error if anycreateCanal()- Manually create canalreset()- Reset state
Tip: combine the returned
contractwithbuildEventRoomsConnectionfrom@sofya-sdk/qrto build the WebSocket connection parameters automatically.
useCanalConfig()
Fetches canal configuration from the backend. Used by the emissor (mic) side after scanning QR code.
import { useCanalConfig } from '@sofya-sdk/react';
import { parseCanalFromQR } from '@sofya-sdk/qr';
function Emissor() {
const canalId = parseCanalFromQR(window.location.href);
const { config, loading, error } = useCanalConfig({
canalId,
backendUrl: 'https://api.sofya.app',
});
if (loading) return <div>Loading config...</div>;
if (error) return <div>Error: {error.message}</div>;
return <div>STT: {config?.sttEndpoint}</div>;
}Options:
canalId(string | null, required) - Canal ID from QR codebackendUrl(string, required) - Backend API base URLauthToken(string, optional) - Authentication tokenautoFetch(boolean, optional) - Auto-fetch on mount (default: true)
Returns:
config- Canal configuration (sttEndpoint, messagingEndpoint, canalId, contract)loading- Loading stateerror- Error if anyfetchConfig()- Manually fetch configreset()- Reset state
The returned
config.contractmirrors the backend contract and can also be passed tobuildEventRoomsConnectionfor the emissor role.
useEventRooms()
Main hook for EventRooms WebSocket connection. Works for both receptor and emissor roles.
import { useEventRooms, useRoomEvent } from '@sofya-sdk/react';
function MyComponent() {
const {
connectionState,
connected,
client,
presence,
error,
sendEvent,
connect,
disconnect,
} = useEventRooms({
url: 'wss://messaging.sofya.app/ws',
canalId: 'CANAL123',
role: 'desktop', // or 'mic'
autoConnect: true,
autoReconnect: true,
maxReconnectAttempts: 5,
});
// Listen to specific events
useRoomEvent(client, 'transcription', (payload) => {
console.log('Transcription:', payload);
});
// Send event
const handleClick = () => {
sendEvent('transcription', { text: 'Hello', partial: false });
};
return (
<div>
<p>Status: {connectionState}</p>
<button onClick={handleClick}>Send Event</button>
<p>Clients in room: {presence?.clientsLocal || 0}</p>
</div>
);
}Options:
url(string, required) - WebSocket URLcanalId(string | null, required) - Canal (room) IDrole('desktop' | 'mic', required) - Client roleautoConnect(boolean, optional) - Auto-connect on mount (default: true)autoReconnect(boolean, optional) - Auto-reconnect on disconnect (default: true)maxReconnectAttempts(number, optional) - Maximum reconnection attempts (default: 5)
Returns:
connectionState- Current connection state ('disconnected' | 'connecting' | 'connected' | 'reconnecting' | 'failed')connected- Boolean flag for connected statepresence- Latest presence informationerror- Latest error messageclient- EventRooms client instance (for use with useRoomEvent)sendEvent(event, payload)- Send event to roomconnect()- Manually connectdisconnect()- Manually disconnect
useRoomEvent()
Listen to specific events from EventRooms. Must be used with an EventRooms client instance.
import { useRoomEvent } from '@sofya-sdk/react';
function MyComponent({ client }) {
useRoomEvent(client, 'transcription', (payload) => {
console.log('Transcription:', payload);
});
return <div>Listening to transcription events...</div>;
}Complete Examples
Receptor (Desktop) - Full Flow
import { useCanal, useEventRooms, useRoomEvent } from '@sofya-sdk/react';
import { generateQRCode } from '@sofya-sdk/qr';
import { useEffect, useState } from 'react';
function Receptor() {
const [qrDataUrl, setQrDataUrl] = useState<string>('');
const [transcriptions, setTranscriptions] = useState<string[]>([]);
// 1. Create canal
const { canalId, qrCodeUrl, messagingEndpoint, loading: canalLoading } = useCanal({
backendUrl: 'https://api.sofya.app',
apiKey: process.env.REACT_APP_API_KEY || 'your-api-key',
});
// 2. Generate QR code
useEffect(() => {
if (qrCodeUrl) {
generateQRCode(qrCodeUrl).then(setQrDataUrl);
}
}, [qrCodeUrl]);
// 3. Connect to EventRooms
const { connected, client, presence } = useEventRooms({
url: messagingEndpoint || 'wss://messaging.sofya.app/ws',
canalId,
role: 'desktop',
});
// 4. Listen to transcription events
useRoomEvent(client, 'transcription', (payload: any) => {
setTranscriptions((prev) => [...prev, payload.text]);
});
if (canalLoading) return <div>Creating canal...</div>;
return (
<div>
<h1>Receptor</h1>
{/* QR Code */}
{qrDataUrl && <img src={qrDataUrl} alt="QR Code" />}
{/* Status */}
<p>Canal: {canalId}</p>
<p>Status: {connected ? 'Connected' : 'Disconnected'}</p>
<p>Clients: {presence?.clientsLocal || 0}</p>
{/* Transcriptions */}
<div>
<h2>Transcriptions</h2>
{transcriptions.map((text, i) => (
<div key={i}>{text}</div>
))}
</div>
</div>
);
}Emissor (PWA) - Full Flow
import { useCanalConfig, useEventRooms } from '@sofya-sdk/react';
import { parseCanalFromQR } from '@sofya-sdk/qr';
function Emissor() {
// 1. Parse canal from URL
const canalId = parseCanalFromQR(window.location.href);
// 2. Fetch configuration
const { config, loading: configLoading } = useCanalConfig({
canalId,
backendUrl: 'https://api.sofya.app',
});
// 3. Connect to EventRooms
const { connected, sendEvent } = useEventRooms({
url: config?.messagingEndpoint || '',
canalId,
role: 'mic',
});
const handleSendTranscription = () => {
sendEvent('transcription', {
text: 'Hello from emissor',
partial: false,
});
};
if (configLoading) return <div>Loading configuration...</div>;
if (!config) return <div>Invalid canal</div>;
return (
<div>
<h1>Emissor</h1>
<p>Canal: {canalId}</p>
<p>Status: {connected ? 'Connected' : 'Disconnected'}</p>
<button onClick={handleSendTranscription} disabled={!connected}>
Send Transcription
</button>
</div>
);
}TypeScript
All hooks are fully typed. Import types from the package:
import type {
UseCanalResult,
UseCanalConfigResult,
UseEventRoomsResult,
EventMessage,
ConnectionState,
} from '@sofya-sdk/react';License
ISC
