File size: 4,996 Bytes
0bedc61 cdda8ef 0bedc61 c904528 c4549b1 0bedc61 cdda8ef 19036c5 c4549b1 161aa64 c904528 c4549b1 0bedc61 0447e79 7dd64e7 c904528 3026f42 0bedc61 c904528 0447e79 3026f42 0bedc61 c904528 0bedc61 cdda8ef 0447e79 d3855e1 c904528 3026f42 d3855e1 0447e79 d3855e1 3026f42 c904528 d3855e1 0447e79 c904528 3026f42 d3855e1 0447e79 0bedc61 c904528 3026f42 0bedc61 0447e79 c904528 0bedc61 c904528 0bedc61 19036c5 0447e79 0bedc61 c904528 3026f42 7dd64e7 0447e79 c904528 7dd64e7 c904528 d3855e1 0447e79 d3855e1 c904528 6727a51 d3855e1 7dd64e7 41a968b c904528 7dd64e7 c904528 3026f42 0447e79 41a968b 7dd64e7 0447e79 7dd64e7 3026f42 41a968b 7dd64e7 c904528 3026f42 0bedc61 0447e79 3026f42 c904528 0bedc61 7a4e883 0447e79 0bedc61 c904528 3026f42 7a4e883 3026f42 7a4e883 3026f42 7a4e883 c904528 cdda8ef c904528 cdda8ef c70a332 0bedc61 3026f42 cdda8ef c904528 3026f42 cdda8ef 3026f42 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
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);
});
|