Oblien Docs

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