@ustriveneo/partner-realtime
v1.5.0
Published
Client-side realtime SDK for UStrive Partner integrations (chat, video, audio)
Maintainers
Readme
@ustriveneo/partner-realtime
Client-side realtime SDK for UStrive Partner integrations. Provides real-time chat, video calls, and audio calls between matched mentor-student pairs.
This package wraps Stream Chat and Stream Video so partners never need to import or configure Stream SDKs directly.
Installation
Web (with server runtime)
npm install @ustriveneo/partner-realtime @ustriveneo/partner-sdk stream-chat @stream-io/video-clientWeb (client-only / tokenProvider)
If using tokenProvider instead of partnerClient, you don't need @ustriveneo/partner-sdk on the client:
npm install @ustriveneo/partner-realtime stream-chat @stream-io/video-clientReact Native
npm install @ustriveneo/partner-realtime stream-chat @stream-io/video-react-native-sdkNote: @ustriveneo/partner-sdk is only needed on your server (to call getStreamToken). @stream-io/video-client and @stream-io/video-react-native-sdk are optional -- only install them if you need video/audio calls. See React Native Usage below.
Quick Start (Web with Server Runtime)
If your app has a server runtime (e.g. Next.js with API routes), you can pass the partner client directly:
import { UStrivePartnerClient } from '@ustriveneo/partner-sdk';
import { UStriveRealtimeClient } from '@ustriveneo/partner-realtime';
// 1. Initialize the server SDK (used for token generation)
const partnerClient = new UStrivePartnerClient({
apiKey: 'pk_live_xxx',
secret: 'sk_live_yyy',
});
// 2. Create the realtime client for a specific user
const realtime = new UStriveRealtimeClient({
partnerClient,
userId: 'user-id',
});
// 3. Connect (fetches token and auto-creates Stream clients)
await realtime.connect();Security: The
partnerClientmust be initialized server-side. Never expose your API key and secret in client-side browser code. If your app has no server runtime, usetokenProviderinstead (see below).
Quick Start (Client-Only Web / No Server Runtime)
If your app has no server runtime (static React, SPA, etc.), use tokenProvider to keep your API key and secret on your server. The realtime SDK calls your function to get a token instead of using partnerClient directly:
import { UStriveRealtimeClient } from '@ustriveneo/partner-realtime';
const realtime = new UStriveRealtimeClient({
tokenProvider: async () => {
// Call YOUR backend endpoint that proxies getStreamToken
const res = await fetch('/api/ustrive/stream-token', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ userId: 'user-id' }),
});
return res.json(); // must return { token: string, apiKey: string }
},
userId: 'user-id',
});
await realtime.connect();Your backend endpoint would look something like:
// /api/ustrive/stream-token (your server)
import { UStrivePartnerClient } from '@ustriveneo/partner-sdk';
const client = new UStrivePartnerClient({
apiKey: process.env.USTRIVE_API_KEY,
secret: process.env.USTRIVE_SECRET,
});
export async function POST(req) {
// Add your own authentication middleware to verify the caller
const { userId } = await req.json();
const { token, apiKey } = await client.messaging.getStreamToken(userId);
return Response.json({ token, apiKey });
}React Native Usage
React Native requires platform-specific Stream SDKs for camera/microphone access. Instead of letting partner-realtime auto-create clients, pass your own pre-initialized clients:
import { StreamChat } from 'stream-chat';
import { StreamVideoClient } from '@stream-io/video-react-native-sdk';
import { UStrivePartnerClient } from '@ustriveneo/partner-sdk';
import { UStriveRealtimeClient } from '@ustriveneo/partner-realtime';
const partnerClient = new UStrivePartnerClient({
apiKey: 'pk_live_xxx',
secret: 'sk_live_yyy',
});
// Get a token first to initialize the native clients
const { token, apiKey } = await partnerClient.messaging.getStreamToken('user-id');
// Initialize native-aware clients
const chatClient = StreamChat.getInstance(apiKey);
await chatClient.connectUser({ id: 'user-id' }, token);
const videoClient = new StreamVideoClient({
apiKey,
token,
user: { id: 'user-id' },
});
// Pass them to partner-realtime
const realtime = new UStriveRealtimeClient({
partnerClient,
userId: 'user-id',
chatClient, // Pre-initialized — won't be auto-created
videoClient, // Pre-initialized — native camera/mic bindings active
});
await realtime.connect();When injected clients are provided:
connect()still fetches the API key but skips client creationdisconnect()cleans up channel watchers and call state but does NOT disconnect injected clients (the host app manages their lifecycle)
Chat
Use the chat manager to send and receive messages in a match's channel. The channelId is the streamChatId returned when creating or fetching a match via the Partner SDK.
Open a Channel
const match = await partnerClient.matches.get('match-id');
const channel = await realtime.chat.openChat(match.streamChatId);Send a Message
await channel.sendMessage('Hello!');
// Or directly via the manager:
await realtime.chat.sendMessage(match.streamChatId, 'Hello!');Get Message History
const messages = await channel.getMessages({ limit: 50 });
// Or directly via the manager:
const messages = await realtime.chat.getMessages(match.streamChatId, { limit: 50 });Listen for New Messages
const unsubscribe = channel.onMessage((msg) => {
console.log(`${msg.userId}: ${msg.text}`);
});
// Or via the manager:
const unsubscribe = realtime.chat.onMessage(match.streamChatId, (msg) => {
console.log(`${msg.userId}: ${msg.text}`);
});
// Clean up when done
unsubscribe();Video & Audio Calls
Use the calls manager to join and manage calls. Calls use the match ID as the call identifier.
Note: calls returns null if no video client is available (neither injected nor auto-created). Check for availability before using:
if (realtime.calls) {
const activeCall = await realtime.calls.joinCall('match-id');
}Join a Call
const activeCall = await realtime.calls.joinCall('match-id', {
video: true, // Enable camera (default: true)
audio: true, // Enable microphone (default: true)
});Control Devices
await activeCall.setCamera(false); // Turn off camera (audio-only)
await activeCall.setMicrophone(false); // MuteListen for Call Events
const unsubscribe = activeCall.on('call.session_participant_joined', (event) => {
console.log('Participant joined');
});
unsubscribe();Leave a Call
await realtime.calls.leaveCall('match-id');Check Active Call
const call = realtime.calls?.getActiveCall('match-id');
if (call) {
// Currently in a call
}Disconnect
Always disconnect when done to clean up resources:
await realtime.disconnect();Full Example
import { UStrivePartnerClient } from '@ustriveneo/partner-sdk';
import { UStriveRealtimeClient } from '@ustriveneo/partner-realtime';
async function main() {
const partnerClient = new UStrivePartnerClient({
apiKey: process.env.USTRIVE_API_KEY,
secret: process.env.USTRIVE_SECRET,
});
// Get an active match
const { matches } = await partnerClient.matches.listByUser('student-id', {
status: 'ACTIVE',
});
const match = matches[0];
// Connect realtime for the student
const realtime = new UStriveRealtimeClient({
partnerClient,
userId: 'student-id',
});
await realtime.connect();
// Open chat and send a message
const channel = await realtime.chat.openChat(match.streamChatId);
await channel.sendMessage('Hi! Ready for our session?');
// Listen for replies
channel.onMessage((msg) => {
console.log(`New message from ${msg.userId}: ${msg.text}`);
});
// Start a video call
if (realtime.calls) {
const call = await realtime.calls.joinCall(match.id, { video: true });
}
// Clean up
await realtime.disconnect();
}Architecture
Partner App (Client)
|
v
@ustriveneo/partner-realtime <-- This package (wraps Stream)
|
v
@ustriveneo/partner-sdk <-- Gets Stream tokens via REST
|
v
UStrive Partner API <-- Generates tokens, manages channels
|
v
Stream (Chat + Video) <-- Third-party realtime infrastructurePartners interact only with @ustriveneo/partner-sdk (server-side) and @ustriveneo/partner-realtime (client-side). Stream is fully abstracted.
