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,
|
CreateTransactionResponse,
|
||||||
Drink,
|
Drink,
|
||||||
} from '@wutzcalc/shared';
|
} from '@wutzcalc/shared';
|
||||||
|
import { sendProblem } from '../problem-details.js';
|
||||||
|
|
||||||
export function registerPublicRoutes(app: FastifyInstance, db: DB) {
|
export function registerPublicRoutes(app: FastifyInstance, db: DB) {
|
||||||
app.get('/api/bars', async () => {
|
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) => {
|
app.get<{ Querystring: { bar: string } }>('/api/config', async (req, reply) => {
|
||||||
const barId = Number(req.query.bar);
|
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
|
const bar = db
|
||||||
.prepare('SELECT id, name, pfand_cents FROM bars WHERE id = ?')
|
.prepare('SELECT id, name, pfand_cents FROM bars WHERE id = ?')
|
||||||
.get(barId) as Bar | undefined;
|
.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
|
const drinks = db
|
||||||
.prepare(
|
.prepare(
|
||||||
|
|
@ -49,29 +50,29 @@ export function registerPublicRoutes(app: FastifyInstance, db: DB) {
|
||||||
const { client_uuid, bar_id, crew, items } = body;
|
const { client_uuid, bar_id, crew, items } = body;
|
||||||
|
|
||||||
if (!client_uuid || typeof client_uuid !== 'string') {
|
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)) {
|
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)) {
|
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) {
|
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;
|
const rawPfandReturns = body.pfand_returns ?? 0;
|
||||||
if (!Number.isInteger(rawPfandReturns) || rawPfandReturns < 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) {
|
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;
|
const pfand_returns = rawPfandReturns;
|
||||||
|
|
||||||
if (items.length === 0 && pfand_returns === 0) {
|
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 = () =>
|
const findByUuid = () =>
|
||||||
|
|
@ -88,7 +89,7 @@ export function registerPublicRoutes(app: FastifyInstance, db: DB) {
|
||||||
const bar = db
|
const bar = db
|
||||||
.prepare('SELECT id, pfand_cents FROM bars WHERE id = ?')
|
.prepare('SELECT id, pfand_cents FROM bars WHERE id = ?')
|
||||||
.get(bar_id) as { id: number; pfand_cents: number } | undefined;
|
.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(
|
const drinkStmt = db.prepare(
|
||||||
`SELECT d.id, d.price_cents
|
`SELECT d.id, d.price_cents
|
||||||
|
|
@ -112,12 +113,14 @@ export function registerPublicRoutes(app: FastifyInstance, db: DB) {
|
||||||
item.qty <= 0 ||
|
item.qty <= 0 ||
|
||||||
item.qty > MAX_QTY_PER_LINE
|
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
|
const drink = drinkStmt.get(bar_id, item.drink_id) as
|
||||||
| { id: number; price_cents: number }
|
| { id: number; price_cents: number }
|
||||||
| undefined;
|
| 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;
|
const lineUnit = drink.price_cents + bar.pfand_cents;
|
||||||
total += lineUnit * item.qty;
|
total += lineUnit * item.qty;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue