// Node.js me EventSource support ke liye polyfill if (typeof EventSource === 'undefined') { global.EventSource = require('eventsource'); } const { EventIterator } = require('event-iterator'); /** * Vercel Sandbox API-compatible wrapper. * Yeh class @vercel/sandbox SDK ki nakal karti hai, lekin humare custom API ka istemal karti hai. */ class VercelSandboxSDK { constructor(baseURL = 'http://localhost:3001') { this.baseURL = baseURL; } // Maps to: Sandbox.create({ template: '...' }) static async create(options = {}) { const sdk = new VercelSandboxSDK(); const response = await fetch(`${sdk.baseURL}/api/sandboxes`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(options) }); if (!response.ok) throw new Error(`Failed to create sandbox: ${await response.text()}`); const data = await response.json(); return new SandboxInstance(data.id, sdk.baseURL); } // Maps to: Sandbox.findById(id) static async findById(sandboxId) { const sdk = new VercelSandboxSDK(); const response = await fetch(`${sdk.baseURL}/api/sandboxes/${sandboxId}`); if (!response.ok) { const error = new Error('Sandbox not found'); error.code = 'sandbox_not_found'; throw error; } return new SandboxInstance(sandboxId, sdk.baseURL); } } /** * Ek active sandbox instance ko represent karta hai. */ class SandboxInstance { constructor(sandboxId, baseURL) { this.id = sandboxId; // Original SDK uses 'id' property this.baseURL = baseURL; // `sandbox.fs.write()` ke liye compatibility this.fs = { write: this.writeFile.bind(this) }; } // Maps to: sandbox.run('npm install') async run(command) { const response = await fetch(`${this.baseURL}/api/sandboxes/${this.id}/cmd`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ command }) }); if (!response.ok) throw new Error(`Command failed: ${await response.text()}`); const data = await response.json(); return new CommandInstance(this.id, data.id, this.baseURL); } // Maps to: sandbox.fs.write('path/file.js', 'content') async writeFile(filePath, content) { const response = await fetch(`${this.baseURL}/api/sandboxes/${this.id}/fs/write`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ path: filePath, content }) }); if (!response.ok) throw new Error(`File write failed: ${await response.text()}`); return; } // Maps to: sandbox.getURL() async getURL() { const response = await fetch(`${this.baseURL}/api/sandboxes/${this.id}/url`); if (!response.ok) throw new Error('Could not get sandbox URL'); const data = await response.json(); return data.url; } } /** * Ek command instance ko represent karta hai. */ class CommandInstance { constructor(sandboxId, cmdId, baseURL) { this.sandboxId = sandboxId; this.id = cmdId; // Original SDK uses 'id' this.baseURL = baseURL; } // Maps to: cmd.wait() async wait() { const response = await fetch( `${this.baseURL}/api/sandboxes/${this.sandboxId}/cmds/${this.id}` ); if (!response.ok) return { exitCode: 1, stdout: '', stderr: 'Failed to get command result' }; const data = await response.json(); // Original SDK functions `stdout()` and `stderr()` are async, so we mimic that return { exitCode: data.exitCode, stdout: async () => data.stdout, stderr: async () => data.stderr, }; } // Maps to: cmd.logs() for streaming logs logs() { const url = `${this.baseURL}/api/sandboxes/${this.sandboxId}/cmds/${this.id}/logs`; return new EventIterator(({ push, stop, fail }) => { const eventSource = new EventSource(url); eventSource.onmessage = (event) => { try { const message = JSON.parse(event.data); if (message.type === 'stdout' || message.type === 'stderr') { push({ data: message.data, stream: message.type }); } else if (message.type === 'complete') { stop(); } } catch (e) { /* Ignore non-JSON messages */ } }; eventSource.onerror = () => { eventSource.close(); stop(); }; return () => eventSource.close(); }); } } module.exports = { Sandbox: VercelSandboxSDK };