Sendbox / server.js
RaBU1234's picture
Update server.js
c904528 verified
const express = require('express');
const cors = require('cors');
const SimpleSandboxManager = require('./simple-sandbox-manager');
const app = express();
// Development ke liye sabhi origins ko allow karein
app.use(cors({ origin: '*' }));
app.use(express.json({ limit: '50mb' }));
const sandboxManager = new SimpleSandboxManager();
(async () => {
await sandboxManager.initialize();
console.log('πŸš€ Custom Sandbox Manager is ready.');
})();
// Health check
app.get('/health', (req, res) => {
res.status(200).json({
status: 'healthy',
sandboxes: sandboxManager.sandboxes.size
});
});
// === Vercel SDK Compatible API Endpoints ===
// 1. Create a new sandbox
app.post('/api/sandboxes', async (req, res) => {
try {
const { timeout = 600000, template = 'next-js' } = req.body;
const sandboxId = `sbx_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
const sandbox = await sandboxManager.createSandbox(sandboxId, { timeout, template });
// Sirf sandboxId return karein, jaisa original SDK expect karta hai
res.json({ id: sandboxId, sandboxId: sandboxId }); // 'id' for compatibility
} catch (error) {
console.error('❌ Create error:', error);
res.status(500).json({ error: error.message });
}
});
// 2. Get sandbox status (for findById)
app.get('/api/sandboxes/:id', async (req, res) => {
try {
const { id } = req.params;
const sandbox = sandboxManager.getSandbox(id);
if (!sandbox || sandboxManager.isTimedOut(id)) {
if (sandbox) await sandboxManager.destroySandbox(id);
return res.status(404).json({ error: 'Sandbox not found or has timed out' });
}
// Status running bhejein agar sandbox maujood hai
res.json({ status: 'running' });
} catch (error) {
console.error('❌ Status error:', error);
res.status(500).json({ error: error.message });
}
});
// 3. Execute a command
app.post('/api/sandboxes/:id/cmd', async (req, res) => {
try {
const { id } = req.params;
const { command } = req.body;
const result = await sandboxManager.executeCommand(id, command);
res.json({ commandId: result.commandId, id: result.commandId }); // 'id' for compatibility
} catch (error) {
console.error('❌ Command error:', error);
res.status(500).json({ error: error.message });
}
});
// 4. Get final command info (for cmd.wait())
app.get('/api/sandboxes/:id/cmds/:cmdId', async (req, res) => {
try {
const { id, cmdId } = req.params;
const cmdData = sandboxManager.getCommandData(id, cmdId);
if (!cmdData || cmdData.exitCode === null) {
// Agar command abhi bhi chal raha hai ya nahi mil raha, to running state bhejein
return res.json({ exitCode: null, stdout: cmdData?.stdout || '', stderr: cmdData?.stderr || '' });
}
res.json({
exitCode: cmdData.exitCode,
stdout: cmdData.stdout || '',
stderr: cmdData.stderr || ''
});
} catch (error) {
console.error('❌ Get command error:', error);
res.status(404).json({ error: 'Command not found' });
}
});
// 5. Stream command logs (SSE)
app.get('/api/sandboxes/:id/cmds/:cmdId/logs', (req, res) => {
const { id, cmdId } = req.params;
console.log(`πŸ“‘ SSE stream requested for ${id}/${cmdId}`);
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Connection', 'keep-alive');
res.setHeader('X-Accel-Buffering', 'no');
res.setHeader('Access-Control-Allow-Origin', '*');
res.flushHeaders();
sandboxManager.addStreamClient(id, cmdId, res);
req.on('close', () => {
sandboxManager.removeStreamClient(id, cmdId, res);
console.log(`πŸ“‘ SSE stream closed for ${id}/${cmdId}`);
res.end();
});
});
// 6. Write a file
app.post('/api/sandboxes/:id/fs/write', async (req, res) => {
try {
const { id } = req.params;
const { path: filePath, content } = req.body;
await sandboxManager.writeFile(id, filePath, content);
res.status(204).send(); // 204 No Content is standard for successful writes
} catch (error) {
console.error('❌ File write error:', error);
res.status(500).json({ error: error.message });
}
});
// 7. Get Sandbox URL
app.get('/api/sandboxes/:id/url', async (req, res) => {
try {
const { id } = req.params;
const url = await sandboxManager.getURL(id);
res.json({ url });
} catch (error) {
console.error('❌ Get URL error:', error);
res.status(404).json({ error: 'Sandbox or URL not found' });
}
});
// Auto cleanup inactive sandboxes
setInterval(() => {
sandboxManager.cleanupInactive();
}, 5 * 60 * 1000); // Har 5 minute me check karein
const PORT = 3001;
app.listen(PORT, '0.0.0.0', () => {
console.log(`πŸš€ Custom Sandbox API running on http://localhost:${PORT}`);
});
process.on('SIGTERM', async () => {
console.log('⚠️ Shutting down... cleaning up all sandboxes.');
await sandboxManager.destroyAllSandboxes();
process.exit(0);
});