import { jsonResponse, errorResponse } from '../utils/cors' // Torch state - which client has control interface TorchClient { id: string userAgent: string hostname: string connectedAt: Date } let torchState: { holderId: string | null clients: Map } = { holderId: null, clients: new Map() } // Generate unique client ID let clientIdCounter = 1 function generateClientId(): string { return `client_${clientIdCounter++}_${Date.now().toString(36)}` } // GET /api/torch - Get current torch state export async function handleTorchGet() { const clients = Array.from(torchState.clients.values()).map(c => ({ ...c, connectedAt: c.connectedAt.toISOString(), hasTorch: c.id === torchState.holderId })) return jsonResponse({ holderId: torchState.holderId, clients }) } // POST /api/torch/register - Register a new client export async function handleTorchRegister(req: Request) { const body = await req.json() const { userAgent, hostname } = body const id = generateClientId() const client: TorchClient = { id, userAgent: userAgent || 'Unknown', hostname: hostname || 'Unknown', connectedAt: new Date() } torchState.clients.set(id, client) // Auto-assign torch if no one has it const shouldHaveTorch = !torchState.holderId if (shouldHaveTorch) { torchState.holderId = id } console.log(`[Torch] Client registered: ${id} (torch: ${shouldHaveTorch})`) return jsonResponse({ id, hasTorch: shouldHaveTorch }) } // POST /api/torch/request - Request the torch export async function handleTorchRequest(req: Request) { const body = await req.json() const { clientId } = body if (!clientId || !torchState.clients.has(clientId)) { return errorResponse('Invalid client ID', 400) } const previousHolder = torchState.holderId torchState.holderId = clientId console.log(`[Torch] Torch transferred: ${previousHolder} -> ${clientId}`) return jsonResponse({ success: true, previousHolder }) } // POST /api/torch/release - Release the torch export async function handleTorchRelease(req: Request) { const body = await req.json() const { clientId } = body if (torchState.holderId !== clientId) { return errorResponse('You do not have the torch', 400) } torchState.holderId = null console.log(`[Torch] Torch released by: ${clientId}`) return jsonResponse({ success: true }) } // DELETE /api/torch/client/:id - Unregister a client export async function handleTorchUnregister(clientId: string) { if (!torchState.clients.has(clientId)) { return errorResponse('Client not found', 404) } torchState.clients.delete(clientId) // If this client had the torch, release it if (torchState.holderId === clientId) { torchState.holderId = null // Auto-assign to next client if any const nextClient = torchState.clients.keys().next().value if (nextClient) { torchState.holderId = nextClient console.log(`[Torch] Auto-assigned to: ${nextClient}`) } } console.log(`[Torch] Client unregistered: ${clientId}`) return jsonResponse({ success: true }) } // Main handler export async function handleTorch(req: Request, url: URL) { const path = url.pathname // GET /api/torch - Get state if (req.method === 'GET' && path === '/api/torch') { return handleTorchGet() } // POST /api/torch/register - Register client if (req.method === 'POST' && path === '/api/torch/register') { return handleTorchRegister(req) } // POST /api/torch/request - Request torch if (req.method === 'POST' && path === '/api/torch/request') { return handleTorchRequest(req) } // POST /api/torch/release - Release torch if (req.method === 'POST' && path === '/api/torch/release') { return handleTorchRelease(req) } // DELETE /api/torch/client/:id - Unregister const unregisterMatch = path.match(/^\/api\/torch\/client\/(.+)$/) if (req.method === 'DELETE' && unregisterMatch) { return handleTorchUnregister(unregisterMatch[1]) } return null }