import { Job } from '../db/models.js'; import { enqueueJob } from '../jobs/queue.js'; import { registerClient } from '../ws/broadcast.js'; import { findModel, DEFAULT_MODEL_ID } from '../models.js'; /** * @param {import('fastify').FastifyInstance} fastify */ export async function jobRoutes(fastify) { // ------------------------------------------------------------------ // WebSocket — all clients connect here to receive live job updates // ------------------------------------------------------------------ fastify.get('/ws', { websocket: true }, (socket) => { registerClient(socket); Job.findAll({ order: [['createdAt', 'DESC']], limit: 100 }) .then((jobs) => { if (socket.readyState === 1) { socket.send(JSON.stringify({ type: 'init', jobs: jobs.map((j) => j.toJSON()) })); } }) .catch(() => {}); }); // ------------------------------------------------------------------ // POST /api/jobs // Multipart form fields: prompt (text), modelId (text), image (file) // ------------------------------------------------------------------ fastify.post('/api/jobs', async (req, reply) => { const data = await req.file(); if (!data) return reply.status(400).send({ error: 'No file uploaded' }); const fields = data.fields; const prompt = (fields.prompt?.value ?? '').trim(); const modelId = (fields.modelId?.value ?? DEFAULT_MODEL_ID).trim(); if (!prompt) return reply.status(400).send({ error: 'prompt is required' }); // Validate that the submitted model ID is in our allowed list const modelMeta = findModel(modelId); if (!modelMeta) { return reply.status(400).send({ error: `Unknown model: ${modelId}` }); } const chunks = []; for await (const chunk of data.file) chunks.push(chunk); const buffer = Buffer.concat(chunks); const mimeType = data.mimetype || 'image/jpeg'; const imageDataUrl = `data:${mimeType};base64,${buffer.toString('base64')}`; const job = await Job.create({ prompt, imageDataUrl, imageMimeType: mimeType, model: modelId, }); enqueueJob(job.id); return reply.status(201).send(job.toJSON()); }); // ------------------------------------------------------------------ // GET /api/jobs // ------------------------------------------------------------------ fastify.get('/api/jobs', async (_req, reply) => { const jobs = await Job.findAll({ order: [['createdAt', 'DESC']], limit: 100 }); return reply.send(jobs.map((j) => j.toJSON())); }); // ------------------------------------------------------------------ // GET /api/jobs/:id // ------------------------------------------------------------------ fastify.get('/api/jobs/:id', async (req, reply) => { const job = await Job.findByPk(req.params.id); if (!job) return reply.status(404).send({ error: 'Not found' }); return reply.send(job.toJSON()); }); }