WebSocket
Establish real-time, bidirectional communication with your sandbox for streaming updates and live terminal sessions.
Connection
WebSocket URL
wss://sandbox.oblien.com:55872?token=YOUR_AUTH_TOKEN
Connect to WebSocket
// Using SDK
const ws = await sandbox.websocket.connect();
ws.on('open', () => {
console.log('Connected to sandbox');
});
ws.on('message', (data) => {
console.log('Received:', data);
});
ws.on('error', (error) => {
console.error('WebSocket error:', error);
});
ws.on('close', () => {
console.log('Disconnected from sandbox');
});
// Using native WebSocket
const ws = new WebSocket('wss://sandbox.oblien.com:55872?token=YOUR_TOKEN');
ws.onopen = () => {
console.log('Connected');
};
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
console.log('Received:', data);
};
ws.onerror = (error) => {
console.error('Error:', error);
};
ws.onclose = () => {
console.log('Disconnected');
};
Authentication
WebSocket connections require authentication via query parameter:
const ws = new WebSocket(
`wss://sandbox.oblien.com:55872?token=${process.env.SANDBOX_TOKEN}`
);
⚠️ Warning: Never expose your token in client-side code. WebSocket connections should be made from your backend or trusted environment.
Message Format
All WebSocket messages use JSON format:
{
"type": "event_type",
"data": { ... },
"timestamp": "2025-10-16T12:00:00Z"
}
Event Types
File Change Events
Receive notifications when files change:
ws.on('message', (message) => {
if (message.type === 'file:changed') {
console.log('File changed:', message.data.path);
console.log('Change type:', message.data.changeType); // 'created', 'modified', 'deleted'
}
});
Event Data:
{
"type": "file:changed",
"data": {
"path": "/opt/app/src/index.js",
"changeType": "modified",
"size": 1245,
"timestamp": "2025-10-16T12:00:00Z"
}
}
Terminal Output Events
Stream terminal output in real-time:
// Send terminal command
ws.send(JSON.stringify({
type: 'terminal:execute',
data: {
command: 'npm run dev',
cwd: '/opt/app'
}
}));
// Receive output
ws.on('message', (message) => {
if (message.type === 'terminal:output') {
process.stdout.write(message.data.output);
}
if (message.type === 'terminal:exit') {
console.log('Command finished with exit code:', message.data.exitCode);
}
});
Git Events
Receive Git operation progress:
ws.on('message', (message) => {
if (message.type === 'git:progress') {
console.log('Git progress:', message.data.percent);
console.log('Status:', message.data.status);
}
if (message.type === 'git:complete') {
console.log('Git operation complete');
}
});
Snapshot Events
Get notified about snapshot operations:
ws.on('message', (message) => {
if (message.type === 'snapshot:created') {
console.log('Snapshot created:', message.data.commitHash);
}
if (message.type === 'snapshot:restored') {
console.log('Restored to:', message.data.commitHash);
}
});
Sending Messages
Execute Terminal Commands
ws.send(JSON.stringify({
type: 'terminal:execute',
data: {
command: 'ls -la',
cwd: '/opt/app'
}
}));
Request File Updates
ws.send(JSON.stringify({
type: 'file:watch',
data: {
paths: ['/opt/app/src/**/*.js'],
events: ['created', 'modified', 'deleted']
}
}));
Ping/Pong
Keep connection alive:
// Server sends ping every 30 seconds
ws.on('message', (message) => {
if (message.type === 'ping') {
// Respond with pong
ws.send(JSON.stringify({ type: 'pong' }));
}
});
Binary Mode
For binary data (file transfers):
const ws = new WebSocket(
'wss://sandbox.oblien.com:55872?token=YOUR_TOKEN&binary=true'
);
ws.binaryType = 'arraybuffer';
ws.onmessage = (event) => {
if (event.data instanceof ArrayBuffer) {
// Handle binary data
const bytes = new Uint8Array(event.data);
console.log('Received binary data:', bytes.length, 'bytes');
}
};
Connection Management
Check Connection Status
// Using SDK
const connected = await sandbox.websocket.isConnected();
if (!connected) {
await sandbox.websocket.connect();
}
GET /ws/connection HTTP/1.1
Authorization: Bearer YOUR_TOKEN
Response:
{
"success": true,
"wsConnected": true
}
Disconnect
// Using SDK
await sandbox.websocket.disconnect();
POST /ws/disconnect HTTP/1.1
Authorization: Bearer YOUR_TOKEN
Content-Type: application/json
{
"token": "YOUR_TOKEN"
}
Get Active Connections
// Using SDK
const connections = await sandbox.websocket.getConnections();
GET /ws/connections HTTP/1.1
Authorization: Bearer YOUR_TOKEN
Response:
{
"success": true,
"connections": [
{
"id": "conn-123",
"connected": "2025-10-16T12:00:00Z",
"lastPing": "2025-10-16T12:05:00Z"
}
]
}
Advanced Usage
Reconnection Logic
let ws;
let reconnectAttempts = 0;
const maxReconnectAttempts = 5;
function connect() {
ws = new WebSocket(`wss://sandbox.oblien.com:55872?token=${token}`);
ws.onopen = () => {
console.log('Connected');
reconnectAttempts = 0;
};
ws.onclose = () => {
if (reconnectAttempts < maxReconnectAttempts) {
reconnectAttempts++;
console.log(`Reconnecting... (${reconnectAttempts}/${maxReconnectAttempts})`);
setTimeout(connect, 2000 * reconnectAttempts);
}
};
}
connect();
Heartbeat Monitor
let heartbeatInterval;
ws.on('open', () => {
heartbeatInterval = setInterval(() => {
ws.send(JSON.stringify({ type: 'ping' }));
}, 30000);
});
ws.on('close', () => {
clearInterval(heartbeatInterval);
});
Message Queue
const messageQueue = [];
let wsReady = false;
ws.on('open', () => {
wsReady = true;
// Send queued messages
while (messageQueue.length > 0) {
ws.send(messageQueue.shift());
}
});
function sendMessage(message) {
const payload = JSON.stringify(message);
if (wsReady && ws.readyState === WebSocket.OPEN) {
ws.send(payload);
} else {
messageQueue.push(payload);
}
}
Silent Mode
Disable notifications for batch operations:
POST /ws/connect HTTP/1.1
Authorization: Bearer YOUR_TOKEN
X-Notify-Type: silent
This prevents flooding with file change notifications during batch operations.
Complete Example
import { SandboxClient } from '@oblien/sandbox-sdk';
const sandbox = new SandboxClient({
baseURL: 'https://sandbox.oblien.com:55872',
token: process.env.SANDBOX_TOKEN
});
// Connect to WebSocket
const ws = await sandbox.websocket.connect();
// Listen for file changes
ws.on('message', (message) => {
switch (message.type) {
case 'file:changed':
console.log(`File ${message.data.changeType}:`, message.data.path);
break;
case 'terminal:output':
process.stdout.write(message.data.output);
break;
case 'terminal:exit':
console.log('Command finished:', message.data.exitCode);
break;
}
});
// Execute command with real-time output
ws.send(JSON.stringify({
type: 'terminal:execute',
data: {
command: 'npm install && npm run build',
cwd: '/opt/app'
}
}));
Next Steps
- Learn about File Watcher for file change events
- Explore Terminal for command execution
- Check Snapshots for state management