@trackthatride/realtime
v1.0.0
Published
Real-time tracking via Server-Sent Events for Track That Ride SDK
Downloads
11
Maintainers
Readme
@trackthatride/realtime
Real-time tracking session management for Track That Ride using Server-Sent Events (SSE). Provides automatic reconnection, state management, and event handling for live delivery tracking.
Installation
npm install @trackthatride/realtimeThis package depends on @trackthatride/core, which will be installed automatically.
Quick Start
import { TrackingSession } from '@trackthatride/realtime';
// Create a tracking session
const session = new TrackingSession({
baseUrl: 'https://your-app.replit.app'
});
// Subscribe to updates
const unsubscribe = session.subscribe((state) => {
console.log('Ride status:', state.ride?.status);
console.log('Driver location:', state.currentLocation);
console.log('ETA:', state.estimatedArrival);
});
// Connect to a specific tracking code
await session.connect('TR123456789');
// Clean up when done
session.destroy();
unsubscribe();Configuration
Basic Configuration
const session = new TrackingSession({
baseUrl: 'https://your-app.replit.app', // Required: Your API base URL
apiKey?: string, // Optional: API key for authenticated endpoints
enableLogging?: boolean, // Optional: Enable debug logging (default: false)
autoConnect?: boolean, // Optional: Auto-connect on creation (default: false)
reconnectDelay?: number, // Optional: Delay between reconnect attempts in ms (default: 3000)
maxReconnectAttempts?: number // Optional: Max reconnection attempts (default: Infinity)
});Advanced Configuration
const session = new TrackingSession({
baseUrl: 'https://your-app.replit.app',
enableLogging: true, // See detailed logs
reconnectDelay: 5000, // Wait 5 seconds before reconnecting
maxReconnectAttempts: 10, // Give up after 10 attempts
autoConnect: false // Manual connection control
});API Reference
TrackingSession
Constructor
const session = new TrackingSession(config: TrackingSessionConfig);Methods
connect(trackingCode: string): Promise
Connect to a tracking code and start receiving real-time updates.
await session.connect('TR123456789');disconnect(): void
Disconnect from the current tracking session and stop receiving updates.
session.disconnect();isConnected(): boolean
Check if the session is currently connected.
if (session.isConnected()) {
console.log('Currently receiving live updates');
}getState(): TrackingSessionState | null
Get the current tracking state synchronously.
const state = session.getState();
if (state?.ride) {
console.log('Current status:', state.ride.status);
}subscribe(callback: StateCallback): UnsubscribeFunction
Subscribe to state changes. Returns an unsubscribe function.
const unsubscribe = session.subscribe((state) => {
console.log('State updated:', state);
});
// Later, when done
unsubscribe();onSSEEvent(event: string, callback: EventCallback): UnsubscribeFunction
Listen to specific SSE events (status_update, location_update, error, etc.).
const unsubscribe = session.onSSEEvent('location_update', (data) => {
console.log('Driver moved to:', data.latitude, data.longitude);
});Available events:
status_update: Ride status changedlocation_update: Driver location updatedeta_update: Estimated arrival time updateddriver_assigned: Driver assigned to rideerror: Error occurredconnected: Connection establisheddisconnected: Connection lost
refresh(): Promise
Manually fetch the latest tracking data (useful for polling in background mode).
await session.refresh();destroy(): void
Clean up all resources, close connections, and remove all listeners.
session.destroy();Type Definitions
TrackingSessionState
interface TrackingSessionState {
ride: Ride | null; // Current ride information
driver?: Driver | null; // Assigned driver information
currentLocation?: { // Real-time driver location
latitude: number;
longitude: number;
} | null;
estimatedArrival?: string | null; // ISO timestamp of estimated arrival
connectionStatus: ConnectionStatus; // Connection state
lastUpdate: string; // ISO timestamp of last update
}
type ConnectionStatus = 'connecting' | 'connected' | 'reconnecting' | 'disconnected';TrackingSessionConfig
interface TrackingSessionConfig {
baseUrl: string; // Required: API base URL
apiKey?: string; // Optional: API key
enableLogging?: boolean; // Optional: Debug logging
autoConnect?: boolean; // Optional: Auto-connect on creation
reconnectDelay?: number; // Optional: Reconnection delay (ms)
maxReconnectAttempts?: number; // Optional: Max reconnection attempts
}Usage Examples
Basic Tracking
import { TrackingSession } from '@trackthatride/realtime';
const session = new TrackingSession({
baseUrl: 'https://your-app.replit.app'
});
// Subscribe to all state changes
const unsubscribe = session.subscribe((state) => {
console.log('Tracking Code:', state.ride?.tracking_code);
console.log('Status:', state.ride?.status);
console.log('Customer:', state.ride?.customer_name);
if (state.driver) {
console.log('Driver:', state.driver.firstName, state.driver.lastName);
}
if (state.currentLocation) {
console.log('Current Location:', state.currentLocation);
}
if (state.estimatedArrival) {
console.log('ETA:', new Date(state.estimatedArrival).toLocaleString());
}
});
// Connect to tracking code
await session.connect('TR123456789');
// Clean up
// unsubscribe();
// session.destroy();Event-Based Updates
Listen to specific events instead of subscribing to all state changes:
const session = new TrackingSession({
baseUrl: 'https://your-app.replit.app'
});
// Listen for status changes
session.onSSEEvent('status_update', (data) => {
console.log('Status changed to:', data.status);
if (data.status === 'delivered') {
console.log('Delivery completed!');
}
});
// Listen for driver location updates
session.onSSEEvent('location_update', (data) => {
console.log('Driver at:', data.latitude, data.longitude);
});
// Listen for ETA changes
session.onSSEEvent('eta_update', (data) => {
console.log('New ETA:', data.estimatedArrival);
});
// Listen for errors
session.onSSEEvent('error', (data) => {
console.error('Tracking error:', data.message);
});
await session.connect('TR123456789');Handling Connection States
const session = new TrackingSession({
baseUrl: 'https://your-app.replit.app',
reconnectDelay: 3000,
maxReconnectAttempts: 5
});
const unsubscribe = session.subscribe((state) => {
switch (state.connectionStatus) {
case 'connecting':
console.log('Establishing connection...');
break;
case 'connected':
console.log('Connected! Receiving live updates');
break;
case 'reconnecting':
console.log('Connection lost, attempting to reconnect...');
break;
case 'disconnected':
console.log('Disconnected from tracking');
break;
}
});
await session.connect('TR123456789');Manual Refresh (Polling Mode)
Useful for background updates or when SSE is not available:
const session = new TrackingSession({
baseUrl: 'https://your-app.replit.app',
autoConnect: false // Disable SSE
});
// Poll every 30 seconds
const interval = setInterval(async () => {
try {
await session.refresh();
const state = session.getState();
console.log('Status:', state?.ride?.status);
} catch (error) {
console.error('Failed to refresh:', error);
}
}, 30000);
// Initial fetch
await session.refresh();
// Clean up
// clearInterval(interval);
// session.destroy();React Native Background Mode
import { AppState } from 'react-native';
const session = new TrackingSession({
baseUrl: 'https://your-app.replit.app'
});
let backgroundTimer: NodeJS.Timeout | null = null;
// Handle app state changes
const handleAppStateChange = (nextAppState: string) => {
if (nextAppState === 'background') {
// App going to background - disconnect SSE
session.disconnect();
// Use polling instead to save battery
backgroundTimer = setInterval(async () => {
await session.refresh();
}, 30000); // 30 seconds
} else if (nextAppState === 'active') {
// App coming to foreground - resume SSE
if (backgroundTimer) {
clearInterval(backgroundTimer);
backgroundTimer = null;
}
await session.connect('TR123456789');
}
};
AppState.addEventListener('change', handleAppStateChange);Multiple Tracking Codes
const sessions = new Map<string, TrackingSession>();
const createSession = (trackingCode: string) => {
const session = new TrackingSession({
baseUrl: 'https://your-app.replit.app'
});
session.subscribe((state) => {
console.log(`[${trackingCode}] Status:`, state.ride?.status);
});
session.connect(trackingCode);
sessions.set(trackingCode, session);
};
// Track multiple deliveries
createSession('TR123456789');
createSession('TR987654321');
createSession('TR555555555');
// Clean up all sessions
sessions.forEach(session => session.destroy());
sessions.clear();Error Handling
import { TrackingSession } from '@trackthatride/realtime';
const session = new TrackingSession({
baseUrl: 'https://your-app.replit.app',
enableLogging: true
});
// Handle connection errors
try {
await session.connect('TR123456789');
} catch (error) {
console.error('Failed to connect:', error);
}
// Handle SSE errors
session.onSSEEvent('error', (errorData) => {
console.error('SSE Error:', errorData.message);
// Optionally disconnect on critical errors
if (errorData.critical) {
session.disconnect();
}
});
// Handle disconnections
session.subscribe((state) => {
if (state.connectionStatus === 'disconnected') {
console.log('Connection closed');
// Optionally attempt manual reconnection
}
});Best Practices
Clean Up Resources: Always call
destroy()when done to prevent memory leaks.useEffect(() => { const session = new TrackingSession({ baseUrl: '...' }); return () => session.destroy(); }, []);Handle Connection States: Provide user feedback for different connection states.
Implement Error Handling: Always handle connection errors and SSE errors.
Use Reconnection Limits: Set reasonable
maxReconnectAttemptsto avoid infinite retries.Enable Logging in Development: Use
enableLogging: trueduring development.Background Mode Strategy: For mobile apps, switch to polling mode when app goes to background.
Validate Tracking Codes: Verify tracking codes before connecting.
Connection Lifecycle
[disconnected] → connect() → [connecting] → [connected]
↓
reconnect() ← [reconnecting] ← connection lost
↓
[disconnected] (after max attempts)Server-Sent Events (SSE)
The realtime package uses SSE for efficient, server-pushed updates. SSE provides:
- Low Latency: Updates arrive immediately as they happen
- Automatic Reconnection: Built-in reconnection logic
- Efficient: No polling overhead
- Firewall Friendly: Uses standard HTTP
SSE Events
The server sends these events through SSE:
status_update: Ride status changedlocation_update: Driver location updatedeta_update: ETA changeddriver_assigned: Driver assigned to ridedriver_unassigned: Driver removed from rideride_updated: General ride information updated
TypeScript Support
Full TypeScript support with exported types:
import {
TrackingSession,
TrackingSessionState,
TrackingSessionConfig,
ConnectionStatus,
StateCallback,
EventCallback,
UnsubscribeFunction
} from '@trackthatride/realtime';Performance Tips
- Reuse Sessions: Don't create a new session for every update.
- Unsubscribe Properly: Always unsubscribe when components unmount.
- Debounce Updates: For high-frequency updates, consider debouncing UI updates.
- Background Mode: Switch to polling mode in background to save battery.
Troubleshooting
Connection Issues
Problem: Session won't connect
Solution:
- Verify
baseUrlis correct - Check that tracking code exists
- Ensure server supports SSE
Problem: Frequent reconnections
Solution:
- Increase
reconnectDelay - Check network stability
- Verify server is running
No Updates Received
Problem: Connected but not receiving updates
Solution:
- Check if driver location updates are being broadcast
- Verify ride status is active
- Enable logging to see SSE events
License
MIT
Support
For support, please contact Track That Ride support or visit our documentation at /docs on your Track That Ride instance.
