TASK22102: slice2 migrate remaining email handlers

This commit is contained in:
2026-03-17 12:55:05 +00:00
parent 9ae8ce7136
commit f16161bcee
5 changed files with 72 additions and 19 deletions
+32
View File
@@ -1339,3 +1339,35 @@ Follow-ups:
- Slice 2 should migrate remaining email handlers (`getcaseref`, `getall`, `getevents`, `getdocuments`) to helper responses.
- After email/admin completion, expand to selected high-risk file handlers using same non-breaking helper model.
---
### CL-036: TASK22102 API contract consistency — Slice 2 (remaining email handlers)
date: 2026-03-17
author: Cline
scope: `pages/api/email/{getcaseref,getall,getevents,getdocuments}.js`
type: change
rationale: Complete the email-domain response-contract consistency rollout by moving remaining handlers to shared helper-based success/error responses.
impact: Removes raw error passthrough in remaining email handlers and standardizes structured error envelopes while preserving success payload compatibility.
status: completed
Summary:
- Migrated remaining email handlers to shared response helper usage:
- `getcaseref`
- `getall`
- `getevents`
- `getdocuments`
- Replaced direct `res.status(...).json(...)` branches with:
- `respondSuccess(...)`
- `respondError(...)`
- Added stable error codes/messages for expected negative paths and catch branches.
Validation:
- `npx next lint --file pages/api/email/getcaseref.js --file pages/api/email/getevents.js --file pages/api/email/getdocuments.js --file pages/api/email/getall.js` -> pass (no warnings/errors)
Follow-ups:
- Next slice can target selected file handlers for equivalent response contract cleanup.
+6 -3
View File
@@ -6,6 +6,7 @@ import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { formatDates } from "../../../components/utils";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
var NotifyClient = require("notifications-node-client").NotifyClient;
@@ -439,11 +440,13 @@ export default async function CombinedApiProxy(req, res) {
sendingResults.push(result);
}
res.status(200).json({ sendingResults });
return respondSuccess(res, { sendingResults });
} catch (error) {
consoleLogger(error);
res.status(500).json({
error: "An error occurred while retrieving combined data.",
return respondError(res, {
status: 500,
code: "EMAIL_COMBINED_FETCH_FAILED",
message: "An error occurred while retrieving combined data.",
details: error.message || error.toString()
});
}
+7 -3
View File
@@ -5,6 +5,7 @@ import { azureHeaders } from "../../../actions/core/headers";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WEBAPI_URL =
process.env.RELAY_ROOT ||
@@ -23,7 +24,6 @@ function flattenWatchlistEntry(entry) {
}
export default async function ApiProxy(req, res) {
const incidentID = req.query.incidentid;
var token = await getToken();
var queryUrl =
@@ -39,10 +39,14 @@ export default async function ApiProxy(req, res) {
const flattenedResults = data.value.map(flattenWatchlistEntry);
res.status(200).json(flattenedResults);
return respondSuccess(res, flattenedResults);
})
.catch((error) => {
consoleLogger(error);
res.status(400).json(error);
return respondError(res, {
status: 400,
code: "CASE_REF_FETCH_FAILED",
message: "Failed to fetch case references"
});
});
}
+11 -6
View File
@@ -5,6 +5,7 @@ import { azureHeadersPaged } from "../../../actions/core/headers";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WORDKEY = process.env.HASHKEY;
const WEBAPI_URL =
@@ -26,9 +27,11 @@ export default async function ApiProxy(req, res) {
const incidentID = req.query.incidentid;
if (!incidentID) {
return res
.status(400)
.json({ error: "incidentid query parameter is required." });
return respondError(res, {
status: 400,
code: "INCIDENT_ID_REQUIRED",
message: "incidentid query parameter is required."
});
}
try {
@@ -79,11 +82,13 @@ export default async function ApiProxy(req, res) {
)
}));
res.status(200).json({ ...data, value: resultsWithLinks });
return respondSuccess(res, { ...data, value: resultsWithLinks });
} catch (error) {
consoleLogger(error);
res.status(500).json({
error: "Failed to fetch document details.",
return respondError(res, {
status: 500,
code: "DOCUMENTS_FETCH_FAILED",
message: "Failed to fetch document details.",
details: error.message || error.toString()
});
}
+16 -7
View File
@@ -5,6 +5,7 @@ import { azureHeaders } from "../../../actions/core/headers";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WORDKEY = process.env.HASHKEY;
const WEBAPI_URL =
@@ -18,7 +19,11 @@ export default async function ApiProxy(req, res) {
const { incidentID } = req.query;
if (!incidentID) {
return res.status(400).json({ error: "incidentID is required" });
return respondError(res, {
status: 400,
code: "INCIDENT_ID_REQUIRED",
message: "incidentID is required"
});
}
try {
@@ -34,9 +39,11 @@ export default async function ApiProxy(req, res) {
const sipsRecords = _.get(sipsResponse, "data.value", []);
if (sipsRecords.length === 0) {
return res
.status(404)
.json({ error: "No SIPs record found for this incidentID." });
return respondError(res, {
status: 404,
code: "SIPS_RECORD_NOT_FOUND",
message: "No SIPs record found for this incidentID."
});
}
const sipsId = sipsRecords[0].pinswg_sipsid;
@@ -53,11 +60,13 @@ export default async function ApiProxy(req, res) {
azureHeaders(token.access_token)
);
res.status(200).json(eventsResponse.data);
return respondSuccess(res, eventsResponse.data);
} catch (error) {
consoleLogger(error);
res.status(500).json({
error: "An error occurred while retrieving data.",
return respondError(res, {
status: 500,
code: "EVENTS_FETCH_FAILED",
message: "An error occurred while retrieving data.",
details: error.message || error.toString()
});
}