import { Router } from 'express'; import { z } from 'zod'; import * as repo from '../../db/repos/jobs.js'; import { validate } from '../validate.js'; import { requireOwner } from '../cap.js'; import { NotFoundError, asyncWrap } from '../errors.js'; import { parsePagination } from '../pagination.js'; const STATES = ['created','retry','active','completed','expired','cancelled','failed']; const listQuery = z.object({ state: z.enum(STATES).optional(), name: z.string().optional(), limit: z.string().optional(), offset: z.string().optional() }); const idParams = z.object({ id: z.string().uuid() }); export const router = Router(); router.use(requireOwner); router.get('/', validate({ query: listQuery }), asyncWrap(async (req, res) => { const { limit } = parsePagination(req); res.json(await repo.list({ state: req.validatedQuery.state, name: req.validatedQuery.name, limit })); }) ); router.get('/:id', validate({ params: idParams }), asyncWrap(async (req, res) => { const row = await repo.getById(req.params.id); if (!row) throw new NotFoundError('job not found'); res.json(row); }) ); router.post('/:id/retry', validate({ params: idParams }), asyncWrap(async (req, res) => { const row = await repo.retry(req.params.id); if (!row) throw new NotFoundError('job not found'); res.json(row); }) ); router.delete('/:id', validate({ params: idParams }), asyncWrap(async (req, res) => { await repo.remove(req.params.id); res.status(204).end(); }) );