public.ts: convert error responses to RFC 7807, matching admin.ts
Follow-up from #25's review feedback — that PR converted admin.ts + the global error handler to application/problem+json (sendProblem/ProblemDetails), left public.ts (the tablet-facing /api/* routes) on the old ad hoc { error } shape to stay scoped to what #25 was actually fixing. Same conversion here, no functional changes — every reply.code(N).send({ error }) becomes sendProblem(req, reply, N, title, detail). Client already degrades gracefully either way (errText() in Admin.tsx checks detail/title first, falls back to .error), so this was purely consistency cleanup, not urgent. typecheck+build clean.
This commit is contained in:
parent
59eb54d9fb
commit
bec4a0080c
1 changed files with 15 additions and 12 deletions
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in a new issue