Spaces:
Paused
Paused
| import type { NextApiRequest, NextApiResponse } from 'next'; | |
| // In-memory input queue | |
| const inputQueue: Array<{ | |
| type: string; | |
| data: Record<string, unknown>; | |
| timestamp: number; | |
| }> = []; | |
| export default async function handler( | |
| req: NextApiRequest, | |
| res: NextApiResponse | |
| ) { | |
| // CORS headers | |
| res.setHeader('Access-Control-Allow-Origin', '*'); | |
| res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS'); | |
| res.setHeader('Access-Control-Allow-Headers', 'Content-Type'); | |
| if (req.method === 'OPTIONS') { | |
| res.status(200).end(); | |
| return; | |
| } | |
| if (req.method === 'POST') { | |
| try { | |
| const { type, data } = req.body; | |
| if (!type) { | |
| return res.status(400).json({ error: 'Missing event type' }); | |
| } | |
| // Validate event type | |
| const validTypes = ['mousemove', 'mousedown', 'mouseup', 'keydown', 'keyup', 'wheel', 'text']; | |
| if (!validTypes.includes(type)) { | |
| return res.status(400).json({ error: 'Invalid event type' }); | |
| } | |
| // Process input event | |
| const event = { | |
| type, | |
| data: data || {}, | |
| timestamp: Date.now(), | |
| }; | |
| // Queue the input event | |
| inputQueue.push(event); | |
| // Process input immediately | |
| await processInputEvent(event); | |
| res.status(200).json({ | |
| success: true, | |
| queued: inputQueue.length, | |
| timestamp: event.timestamp, | |
| }); | |
| } catch (error) { | |
| console.error('Input error:', error); | |
| res.status(500).json({ error: 'Failed to process input' }); | |
| } | |
| } else if (req.method === 'GET') { | |
| // Get pending input count (for debugging) | |
| res.status(200).json({ | |
| pending: inputQueue.length, | |
| events: inputQueue.slice(-10), // Last 10 events | |
| }); | |
| } else { | |
| res.status(405).json({ error: 'Method not allowed' }); | |
| } | |
| } | |
| async function processInputEvent(event: { type: string; data: Record<string, unknown> }): Promise<void> { | |
| try { | |
| // Import input simulator dynamically | |
| const { InputSimulator } = await import('@/lib/input-simulation'); | |
| const simulator = new InputSimulator({ | |
| displayWidth: 1280, | |
| displayHeight: 720, | |
| }); | |
| switch (event.type) { | |
| case 'mousemove': | |
| if ('x' in event.data && 'y' in event.data) { | |
| await simulator.mouseMove( | |
| event.data.x as number, | |
| event.data.y as number | |
| ); | |
| } | |
| break; | |
| case 'mousedown': | |
| if ('button' in event.data) { | |
| await simulator.mouseDown(event.data.button as number); | |
| } | |
| break; | |
| case 'mouseup': | |
| if ('button' in event.data) { | |
| await simulator.mouseUp(event.data.button as number); | |
| } | |
| break; | |
| case 'wheel': | |
| if ('deltaX' in event.data && 'deltaY' in event.data) { | |
| await simulator.mouseWheel( | |
| event.data.deltaX as number, | |
| event.data.deltaY as number | |
| ); | |
| } | |
| break; | |
| case 'keydown': | |
| if ('keyCode' in event.data) { | |
| await simulator.keyDown(event.data.keyCode as number); | |
| } | |
| break; | |
| case 'keyup': | |
| if ('keyCode' in event.data) { | |
| await simulator.keyUp(event.data.keyCode as number); | |
| } | |
| break; | |
| case 'text': | |
| if ('text' in event.data) { | |
| await simulator.typeText(event.data.text as string); | |
| } | |
| break; | |
| } | |
| } catch (error) { | |
| console.error('Error processing input event:', error); | |
| // Input simulation may fail in headless environment - that's okay | |
| } | |
| } | |
| // Export for external use | |
| export function getInputQueue(): typeof inputQueue { | |
| return inputQueue; | |
| } | |
| export function clearInputQueue(): void { | |
| inputQueue.length = 0; | |
| } | |