The Inspatial Cloud Client SDK provides real-time event subscriptions through the InLiveClient, enabling your application to receive instant updates when entries are created, updated, or deleted.
Initialize the Live Client
Create an instance of InLiveClient to manage real-time connections.
import { InLiveClient } from '@inspatial/cloud-client' ;
const liveClient = new InLiveClient ( 'wss://api.yourapp.com' );
The InLiveClient constructor accepts an optional host parameter. If omitted, it uses the default host configuration.
Start and Stop Connection
Manage the WebSocket connection lifecycle.
Start the connection
Begin listening for real-time events: // Start with optional authentication token
liveClient . start ( 'your-auth-token' );
The connection will automatically reconnect if it drops. You can monitor the connection status using onConnectionStatus.
Stop the connection
Close the WebSocket connection when no longer needed:
Method Signatures
start ( authToken ?: string ): void
stop (): void
Monitor Connection Status
Track the connection state and handle reconnection events.
const listenerId = liveClient . onConnectionStatus (( status ) => {
switch ( status ) {
case 'connected' :
console . log ( 'WebSocket connected' );
break ;
case 'disconnected' :
console . log ( 'WebSocket disconnected' );
break ;
case 'connecting' :
console . log ( 'WebSocket connecting...' );
break ;
case 'error' :
console . log ( 'WebSocket error' );
break ;
}
});
// Later, remove the listener
liveClient . removeConnectionStatusListener ( listenerId );
Method Signatures
onConnectionStatus (
listener : ( status : SocketStatus ) => void
): string
removeConnectionStatusListener ( id : string ): void
type SocketStatus = 'connected' | 'disconnected' | 'connecting' | 'error' ;
Subscribe to Individual Entries
Listen for events on specific entries by their entryType and id.
Add Entry Listener
interface Product {
id : string ;
name : string ;
price : number ;
stock : number ;
}
// Define a listener
liveClient . onEntry < Product >( 'product' , 'prod_123' , {
name: 'productUpdateListener' ,
callback : ( event , data ) => {
switch ( event ) {
case 'update' :
console . log ( 'Product updated:' , data );
// Update UI with new data
break ;
case 'delete' :
console . log ( 'Product deleted' );
// Remove from UI
break ;
case 'create' :
console . log ( 'Product created:' , data );
break ;
}
}
});
When you add the first listener for an entry, the client automatically joins the server room for that entry. No manual room management needed!
Remove Entry Listener
// Remove specific listener by name
liveClient . removeEntryListener ( 'product' , 'prod_123' , 'productUpdateListener' );
Leave Entry Room
// Remove all listeners and leave the room
liveClient . leaveEntry ( 'product' , 'prod_123' );
Calling leaveEntry removes all listeners for that entry and stops receiving events. Use removeEntryListener to remove individual listeners while keeping others active.
Method Signatures
onEntry < T extends Entry = Entry > (
entryType : string ,
id : string ,
listener : EntryListener < T >
): void
removeEntryListener (
entryType : string ,
id : string ,
listenerName : string
): void
leaveEntry ( entryType : string , id : string ): void
interface EntryListener < T > {
name : string ;
callback : ( event : EntryEvent , data : T | Record < string , unknown >) => void ;
}
type EntryEvent = 'create' | 'update' | 'delete' ;
Subscribe to Entry Types
Listen for events across all entries of a specific type.
Add Entry Type Listener
liveClient . onEntryType < Product >( 'product' , {
name: 'allProductsListener' ,
callback : ( event , data ) => {
switch ( event ) {
case 'create' :
console . log ( 'New product created:' , data );
// Add to product list in UI
break ;
case 'update' :
console . log ( 'Product updated:' , data );
// Update product in list
break ;
case 'delete' :
console . log ( 'Product deleted:' , data );
// Remove from product list
break ;
}
}
});
Entry type listeners receive events for all entries of that type, making them perfect for list views and dashboards.
Remove Entry Type Listener
// Remove specific listener
liveClient . removeEntryTypeListener ( 'product' , 'allProductsListener' );
// Or leave the entire entry type room
liveClient . leaveEntryType ( 'product' );
Method Signatures
onEntryType < T extends Record < string , any >> (
entryType : string ,
listener : EntryTypeListener < T >
): void
removeEntryTypeListener (
entryType : string ,
listenerName : string
): void
leaveEntryType ( entryType : string ): void
interface EntryTypeListener < T > {
name : string ;
callback : ( event : string , data : T | Record < string , unknown >) => void ;
}
Subscribe to Settings Changes
Monitor changes to application settings in real-time.
liveClient . onSettings ( 'appSettings' , {
name: 'settingsWatcher' ,
callback : ( event , data ) => {
console . log ( 'Settings changed:' , event , data );
// Update app configuration
}
});
// Remove listener
liveClient . removeSettingsListener ( 'appSettings' , 'settingsWatcher' );
// Or leave settings room
liveClient . leaveSettings ( 'appSettings' );
Method Signatures
onSettings < L extends SettingsListener > (
settings : string ,
listener : L
): void
removeSettingsListener (
settings : string ,
listenerName : string
): void
leaveSettings ( settings : string ): void
interface SettingsListener {
name : string ;
callback : ( event : string , data : Record < string , unknown >) => void ;
}
Custom Room Management
For advanced use cases, you can manually join and leave custom rooms.
// Join a custom room
liveClient . joinRoom ( 'custom-room-name' );
// Join a global room (available to all users)
liveClient . joinRoom ( 'announcements' , true );
// Leave a room
liveClient . leaveRoom ( 'custom-room-name' );
Method Signatures
joinRoom ( room : string , global ?: boolean ): void
leaveRoom ( room : string , global ?: boolean ): void
Complete Real-Time Dashboard Example
Here’s a comprehensive example of a real-time product dashboard:
import { InCloudClient , InLiveClient } from '@inspatial/cloud-client' ;
const client = new InCloudClient ( 'https://api.yourapp.com' );
const liveClient = new InLiveClient ( 'wss://api.yourapp.com' );
interface Product {
id : string ;
name : string ;
price : number ;
stock : number ;
status : 'active' | 'inactive' ;
}
class ProductDashboard {
private products : Map < string , Product > = new Map ();
async initialize () {
// Get authentication token
const session = await client . auth . authCheck ();
if ( ! session ) {
throw new Error ( 'Not authenticated' );
}
// Load initial data
const response = await client . entry . getEntryList < Product >( 'product' );
response . rows . forEach ( product => {
this . products . set ( product . id , product );
});
// Start live connection
liveClient . start ();
// Monitor connection status
liveClient . onConnectionStatus (( status ) => {
console . log ( 'Connection status:' , status );
this . updateConnectionIndicator ( status );
});
// Subscribe to all product changes
liveClient . onEntryType < Product >( 'product' , {
name: 'dashboardListener' ,
callback : ( event , data ) => {
this . handleProductEvent ( event , data as Product );
}
});
// Subscribe to specific high-value product
liveClient . onEntry < Product >( 'product' , 'premium-prod-001' , {
name: 'premiumProductListener' ,
callback : ( event , data ) => {
if ( event === 'update' ) {
this . notifyAdmins ( 'Premium product updated' , data );
}
}
});
}
handleProductEvent ( event : string , product : Product ) {
switch ( event ) {
case 'create' :
this . products . set ( product . id , product );
this . renderProduct ( product );
this . showNotification ( `New product: ${ product . name } ` );
break ;
case 'update' :
this . products . set ( product . id , product );
this . updateProductInUI ( product );
break ;
case 'delete' :
this . products . delete ( product . id );
this . removeProductFromUI ( product . id );
this . showNotification ( `Product deleted: ${ product . name } ` );
break ;
}
}
cleanup () {
// Clean up when component unmounts
liveClient . leaveEntryType ( 'product' );
liveClient . leaveEntry ( 'product' , 'premium-prod-001' );
liveClient . stop ();
}
// UI update methods
private renderProduct ( product : Product ) {
console . log ( 'Rendering new product:' , product . name );
// Update your UI framework here
}
private updateProductInUI ( product : Product ) {
console . log ( 'Updating product in UI:' , product . name );
// Update your UI framework here
}
private removeProductFromUI ( productId : string ) {
console . log ( 'Removing product from UI:' , productId );
// Update your UI framework here
}
private updateConnectionIndicator ( status : string ) {
console . log ( 'Connection indicator:' , status );
// Update connection status in UI
}
private showNotification ( message : string ) {
console . log ( 'Notification:' , message );
// Show toast/notification in UI
}
private notifyAdmins ( title : string , data : any ) {
console . log ( 'Admin notification:' , title , data );
// Send notification to admins
}
}
// Usage
const dashboard = new ProductDashboard ();
await dashboard . initialize ();
// Later, when cleaning up
dashboard . cleanup ();
Event Types Reference
Common events you’ll receive from subscriptions:
Event Description Data Included createNew entry created Full entry data updateEntry modified Updated entry data deleteEntry removed Entry ID and type
Best Practices
Clean Up Listeners Always remove listeners and leave rooms when components unmount to prevent memory leaks.
Handle Reconnection Monitor connection status and reload data after reconnection to ensure consistency.
Use Unique Names Give each listener a unique name to avoid conflicts when managing multiple subscriptions.
Optimize Subscriptions Only subscribe to the data you need. Use entry-specific listeners for detail views and type listeners for lists.
Troubleshooting
Verify the WebSocket connection is active using onConnectionStatus
Ensure the listener name is unique and not already registered
Check that you’ve called start() to begin the connection
Verify your authentication token is valid
Connection keeps dropping
Check your network stability
Verify the WebSocket URL is correct (should use wss:// for secure connections)
Monitor the connection status to detect reconnection attempts
Consider implementing exponential backoff for manual reconnection
Memory leaks in React/Vue
Always clean up subscriptions in the component cleanup phase:
React: Use useEffect cleanup function
Vue: Use onUnmounted hook
Remove all listeners before stopping the connection