refactor(routes): replace errorFormatter with ApiError/ValidationError throws (4a dep sweep)
This commit is contained in:
parent
3a4e44c089
commit
de7bf6aaac
|
|
@ -1,7 +1,7 @@
|
|||
// @ts-nocheck — route controller converted to .cts; handler req/res typed, full type-check deferred (thin glue over typed services).
|
||||
import type { Req, Res, Next } from '../types/http';
|
||||
const express = require('express');
|
||||
const { standardizeError } = require('../middleware/errorFormatter.cts');
|
||||
const { ValidationError } = require('../utils/apiError.cts');
|
||||
const router = express.Router();
|
||||
const { getDb } = require('../db/database.cts');
|
||||
const { buildTrackerRow, getCycleRange } = require('../services/statusService.cts');
|
||||
|
|
@ -104,22 +104,10 @@ router.get('/', (req: Req, res: Res) => {
|
|||
const month = parseInt(req.query.month || now.getMonth() + 1, 10);
|
||||
|
||||
if (isNaN(year) || year < 2000 || year > 2100) {
|
||||
return res
|
||||
.status(400)
|
||||
.json(
|
||||
standardizeError(
|
||||
'year must be a 4-digit integer between 2000 and 2100',
|
||||
'VALIDATION_ERROR',
|
||||
'year',
|
||||
),
|
||||
);
|
||||
throw ValidationError('year must be a 4-digit integer between 2000 and 2100', 'year');
|
||||
}
|
||||
if (isNaN(month) || month < 1 || month > 12) {
|
||||
return res
|
||||
.status(400)
|
||||
.json(
|
||||
standardizeError('month must be an integer between 1 and 12', 'VALIDATION_ERROR', 'month'),
|
||||
);
|
||||
throw ValidationError('month must be an integer between 1 and 12', 'month');
|
||||
}
|
||||
|
||||
const today = localDateString(now);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
// @ts-nocheck — route controller converted to .cts; handler req/res typed, full type-check deferred (thin glue over typed services).
|
||||
import type { Req, Res, Next } from '../types/http';
|
||||
const express = require('express');
|
||||
const { standardizeError } = require('../middleware/errorFormatter.cts');
|
||||
const {
|
||||
ApiError,
|
||||
ValidationError,
|
||||
|
|
@ -269,12 +268,14 @@ router.post('/', (req: Req, res: Res) => {
|
|||
)
|
||||
.get(bill.id, payment.paid_date, payment.amount);
|
||||
if (existingDuplicate) {
|
||||
// Deliberate hand-rolled body (documented exception): carries the
|
||||
// `existing` payment the client's "add anyway?" flow renders —
|
||||
// formatError has no extras channel. Shape matches the standard envelope.
|
||||
return res.status(409).json({
|
||||
...standardizeError(
|
||||
'A matching payment already exists for this bill, date, and amount',
|
||||
'DUPLICATE_SUSPECTED',
|
||||
'amount',
|
||||
),
|
||||
error: 'DUPLICATE_SUSPECTED',
|
||||
message: 'A matching payment already exists for this bill, date, and amount',
|
||||
code: 'DUPLICATE_SUSPECTED',
|
||||
field: 'amount',
|
||||
existing: serializePayment(existingDuplicate),
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,16 @@ const { getDb } = require('../db/database.cts');
|
|||
const { seedDemoData } = require('../scripts/seedDemoData.cts');
|
||||
const { demoDataLimiter } = require('../middleware/rateLimiter.cts');
|
||||
const { eraseUserData, clearSeededDemoData } = require('../services/userDataService.cts');
|
||||
const { standardizeError } = require('../middleware/errorFormatter.cts');
|
||||
const { ApiError, ValidationError } = require('../utils/apiError.cts');
|
||||
|
||||
// 4xx service errors keep their message/code on the wire; anything else is
|
||||
// rethrown raw so the terminal handler masks + logs it as a 5xx.
|
||||
function toUserOpError(err, fallbackCode) {
|
||||
if (err.status && err.status < 500) {
|
||||
return new ApiError(err.code || fallbackCode, err.message, err.status);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
// GET /api/user/seeded-status — whether the current user has demo data, with counts
|
||||
router.get('/seeded-status', (req: Req, res: Res) => {
|
||||
|
|
@ -39,14 +48,7 @@ router.get('/seeded-status', (req: Req, res: Res) => {
|
|||
seededTransactions,
|
||||
});
|
||||
} catch (err) {
|
||||
res
|
||||
.status(err.status || 500)
|
||||
.json(
|
||||
standardizeError(
|
||||
err.message || 'Seeded status check failed',
|
||||
err.code || 'SEEDED_STATUS_ERROR',
|
||||
),
|
||||
);
|
||||
throw toUserOpError(err, 'SEEDED_STATUS_ERROR');
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -66,14 +68,7 @@ router.post('/clear-demo-data', demoDataLimiter, (req: Req, res: Res) => {
|
|||
counts: result.counts,
|
||||
});
|
||||
} catch (err) {
|
||||
res
|
||||
.status(err.status || 500)
|
||||
.json(
|
||||
standardizeError(
|
||||
err.message || 'Clear demo data operation failed',
|
||||
err.code || 'CLEAR_DEMO_ERROR',
|
||||
),
|
||||
);
|
||||
throw toUserOpError(err, 'CLEAR_DEMO_ERROR');
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -102,9 +97,7 @@ router.post('/seed-demo-data', demoDataLimiter, (req: Req, res: Res) => {
|
|||
counts: result.counts,
|
||||
});
|
||||
} catch (err) {
|
||||
res
|
||||
.status(err.status || 500)
|
||||
.json(standardizeError(err.message || 'Seed operation failed', err.code || 'SEED_ERROR'));
|
||||
throw toUserOpError(err, 'SEED_ERROR');
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -116,17 +109,13 @@ router.post('/erase-data', demoDataLimiter, (req: Req, res: Res) => {
|
|||
.trim()
|
||||
.toUpperCase();
|
||||
if (confirm !== 'ERASE') {
|
||||
return res
|
||||
.status(400)
|
||||
.json(standardizeError('Type ERASE to confirm.', 'ERASE_CONFIRM_REQUIRED', 'confirm'));
|
||||
throw ValidationError('Type ERASE to confirm.', 'confirm', 'ERASE_CONFIRM_REQUIRED');
|
||||
}
|
||||
try {
|
||||
const result = eraseUserData(getDb(), req.user.id);
|
||||
res.json({ success: true, ...result });
|
||||
} catch (err) {
|
||||
res
|
||||
.status(err.status || 500)
|
||||
.json(standardizeError(err.message || 'Failed to erase data', err.code || 'ERASE_ERROR'));
|
||||
throw toUserOpError(err, 'ERASE_ERROR');
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue