magic / src /pages /api /vnc /input.ts
diamond-in's picture
Rename input.ts to src/pages/api/vnc/input.ts
b4ce4d7 verified
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;
}