diff --git a/server/src/routes/public.ts b/server/src/routes/public.ts index d8c039a..85e0b46 100644 --- a/server/src/routes/public.ts +++ b/server/src/routes/public.ts @@ -7,6 +7,7 @@ import type { CreateTransactionResponse, Drink, } from '@wutzcalc/shared'; +import { sendProblem } from '../problem-details.js'; export function registerPublicRoutes(app: FastifyInstance, db: DB) { app.get('/api/bars', async () => { @@ -16,12 +17,12 @@ export function registerPublicRoutes(app: FastifyInstance, db: DB) { app.get<{ Querystring: { bar: string } }>('/api/config', async (req, reply) => { const barId = Number(req.query.bar); - if (!Number.isInteger(barId)) return reply.code(400).send({ error: 'bar required' }); + if (!Number.isInteger(barId)) return sendProblem(req, reply, 400, 'Bad Request', 'bar required'); const bar = db .prepare('SELECT id, name, pfand_cents FROM bars WHERE id = ?') .get(barId) as Bar | undefined; - if (!bar) return reply.code(404).send({ error: 'bar not found' }); + if (!bar) return sendProblem(req, reply, 404, 'Not Found', 'bar not found'); const drinks = db .prepare( @@ -49,29 +50,29 @@ export function registerPublicRoutes(app: FastifyInstance, db: DB) { const { client_uuid, bar_id, crew, items } = body; if (!client_uuid || typeof client_uuid !== 'string') { - return reply.code(400).send({ error: 'client_uuid required' }); + return sendProblem(req, reply, 400, 'Bad Request', 'client_uuid required'); } if (!Number.isInteger(bar_id)) { - return reply.code(400).send({ error: 'bar_id required' }); + return sendProblem(req, reply, 400, 'Bad Request', 'bar_id required'); } if (!Array.isArray(items)) { - return reply.code(400).send({ error: 'items required' }); + return sendProblem(req, reply, 400, 'Bad Request', 'items required'); } if (items.length > MAX_ITEMS_PER_TRANSACTION) { - return reply.code(400).send({ error: 'too many items' }); + return sendProblem(req, reply, 400, 'Bad Request', 'too many items'); } const rawPfandReturns = body.pfand_returns ?? 0; if (!Number.isInteger(rawPfandReturns) || rawPfandReturns < 0) { - return reply.code(400).send({ error: 'pfand_returns must be a non-negative integer' }); + return sendProblem(req, reply, 400, 'Bad Request', 'pfand_returns must be a non-negative integer'); } if (rawPfandReturns > MAX_PFAND_RETURNS) { - return reply.code(400).send({ error: 'pfand_returns too large' }); + return sendProblem(req, reply, 400, 'Bad Request', 'pfand_returns too large'); } const pfand_returns = rawPfandReturns; if (items.length === 0 && pfand_returns === 0) { - return reply.code(400).send({ error: 'empty transaction' }); + return sendProblem(req, reply, 400, 'Bad Request', 'empty transaction'); } const findByUuid = () => @@ -88,7 +89,7 @@ export function registerPublicRoutes(app: FastifyInstance, db: DB) { const bar = db .prepare('SELECT id, pfand_cents FROM bars WHERE id = ?') .get(bar_id) as { id: number; pfand_cents: number } | undefined; - if (!bar) return reply.code(404).send({ error: 'bar not found' }); + if (!bar) return sendProblem(req, reply, 404, 'Not Found', 'bar not found'); const drinkStmt = db.prepare( `SELECT d.id, d.price_cents @@ -112,12 +113,14 @@ export function registerPublicRoutes(app: FastifyInstance, db: DB) { item.qty <= 0 || item.qty > MAX_QTY_PER_LINE ) { - return reply.code(400).send({ error: 'invalid item' }); + return sendProblem(req, reply, 400, 'Bad Request', 'invalid item'); } const drink = drinkStmt.get(bar_id, item.drink_id) as | { id: number; price_cents: number } | undefined; - if (!drink) return reply.code(400).send({ error: `drink ${item.drink_id} not at bar` }); + if (!drink) { + return sendProblem(req, reply, 400, 'Bad Request', `drink ${item.drink_id} not at bar`); + } const lineUnit = drink.price_cents + bar.pfand_cents; total += lineUnit * item.qty;