TASK22102: slice2 migrate remaining email handlers
This commit is contained in:
@@ -1339,3 +1339,35 @@ Follow-ups:
|
|||||||
|
|
||||||
- Slice 2 should migrate remaining email handlers (`getcaseref`, `getall`, `getevents`, `getdocuments`) to helper responses.
|
- 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.
|
- 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,6 +6,7 @@ import { consoleLogger } from "../../../actions/core/logger";
|
|||||||
import { getToken } from "../../../actions/core/token";
|
import { getToken } from "../../../actions/core/token";
|
||||||
import { formatDates } from "../../../components/utils";
|
import { formatDates } from "../../../components/utils";
|
||||||
import { hashAPIPath } from "../../../actions/core/hash";
|
import { hashAPIPath } from "../../../actions/core/hash";
|
||||||
|
import { respondError, respondSuccess } from "../middleware/apiResponse";
|
||||||
|
|
||||||
var NotifyClient = require("notifications-node-client").NotifyClient;
|
var NotifyClient = require("notifications-node-client").NotifyClient;
|
||||||
|
|
||||||
@@ -439,11 +440,13 @@ export default async function CombinedApiProxy(req, res) {
|
|||||||
sendingResults.push(result);
|
sendingResults.push(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
res.status(200).json({ sendingResults });
|
return respondSuccess(res, { sendingResults });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
consoleLogger(error);
|
consoleLogger(error);
|
||||||
res.status(500).json({
|
return respondError(res, {
|
||||||
error: "An error occurred while retrieving combined data.",
|
status: 500,
|
||||||
|
code: "EMAIL_COMBINED_FETCH_FAILED",
|
||||||
|
message: "An error occurred while retrieving combined data.",
|
||||||
details: error.message || error.toString()
|
details: error.message || error.toString()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { azureHeaders } from "../../../actions/core/headers";
|
|||||||
import { consoleLogger } from "../../../actions/core/logger";
|
import { consoleLogger } from "../../../actions/core/logger";
|
||||||
import { getToken } from "../../../actions/core/token";
|
import { getToken } from "../../../actions/core/token";
|
||||||
import { hashAPIPath } from "../../../actions/core/hash";
|
import { hashAPIPath } from "../../../actions/core/hash";
|
||||||
|
import { respondError, respondSuccess } from "../middleware/apiResponse";
|
||||||
|
|
||||||
const WEBAPI_URL =
|
const WEBAPI_URL =
|
||||||
process.env.RELAY_ROOT ||
|
process.env.RELAY_ROOT ||
|
||||||
@@ -23,7 +24,6 @@ function flattenWatchlistEntry(entry) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default async function ApiProxy(req, res) {
|
export default async function ApiProxy(req, res) {
|
||||||
const incidentID = req.query.incidentid;
|
|
||||||
var token = await getToken();
|
var token = await getToken();
|
||||||
|
|
||||||
var queryUrl =
|
var queryUrl =
|
||||||
@@ -39,10 +39,14 @@ export default async function ApiProxy(req, res) {
|
|||||||
|
|
||||||
const flattenedResults = data.value.map(flattenWatchlistEntry);
|
const flattenedResults = data.value.map(flattenWatchlistEntry);
|
||||||
|
|
||||||
res.status(200).json(flattenedResults);
|
return respondSuccess(res, flattenedResults);
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
consoleLogger(error);
|
consoleLogger(error);
|
||||||
res.status(400).json(error);
|
return respondError(res, {
|
||||||
|
status: 400,
|
||||||
|
code: "CASE_REF_FETCH_FAILED",
|
||||||
|
message: "Failed to fetch case references"
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { azureHeadersPaged } from "../../../actions/core/headers";
|
|||||||
import { consoleLogger } from "../../../actions/core/logger";
|
import { consoleLogger } from "../../../actions/core/logger";
|
||||||
import { getToken } from "../../../actions/core/token";
|
import { getToken } from "../../../actions/core/token";
|
||||||
import { hashAPIPath } from "../../../actions/core/hash";
|
import { hashAPIPath } from "../../../actions/core/hash";
|
||||||
|
import { respondError, respondSuccess } from "../middleware/apiResponse";
|
||||||
|
|
||||||
const WORDKEY = process.env.HASHKEY;
|
const WORDKEY = process.env.HASHKEY;
|
||||||
const WEBAPI_URL =
|
const WEBAPI_URL =
|
||||||
@@ -26,9 +27,11 @@ export default async function ApiProxy(req, res) {
|
|||||||
const incidentID = req.query.incidentid;
|
const incidentID = req.query.incidentid;
|
||||||
|
|
||||||
if (!incidentID) {
|
if (!incidentID) {
|
||||||
return res
|
return respondError(res, {
|
||||||
.status(400)
|
status: 400,
|
||||||
.json({ error: "incidentid query parameter is required." });
|
code: "INCIDENT_ID_REQUIRED",
|
||||||
|
message: "incidentid query parameter is required."
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
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) {
|
} catch (error) {
|
||||||
consoleLogger(error);
|
consoleLogger(error);
|
||||||
res.status(500).json({
|
return respondError(res, {
|
||||||
error: "Failed to fetch document details.",
|
status: 500,
|
||||||
|
code: "DOCUMENTS_FETCH_FAILED",
|
||||||
|
message: "Failed to fetch document details.",
|
||||||
details: error.message || error.toString()
|
details: error.message || error.toString()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { azureHeaders } from "../../../actions/core/headers";
|
|||||||
import { consoleLogger } from "../../../actions/core/logger";
|
import { consoleLogger } from "../../../actions/core/logger";
|
||||||
import { getToken } from "../../../actions/core/token";
|
import { getToken } from "../../../actions/core/token";
|
||||||
import { hashAPIPath } from "../../../actions/core/hash";
|
import { hashAPIPath } from "../../../actions/core/hash";
|
||||||
|
import { respondError, respondSuccess } from "../middleware/apiResponse";
|
||||||
|
|
||||||
const WORDKEY = process.env.HASHKEY;
|
const WORDKEY = process.env.HASHKEY;
|
||||||
const WEBAPI_URL =
|
const WEBAPI_URL =
|
||||||
@@ -18,7 +19,11 @@ export default async function ApiProxy(req, res) {
|
|||||||
const { incidentID } = req.query;
|
const { incidentID } = req.query;
|
||||||
|
|
||||||
if (!incidentID) {
|
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 {
|
try {
|
||||||
@@ -34,9 +39,11 @@ export default async function ApiProxy(req, res) {
|
|||||||
|
|
||||||
const sipsRecords = _.get(sipsResponse, "data.value", []);
|
const sipsRecords = _.get(sipsResponse, "data.value", []);
|
||||||
if (sipsRecords.length === 0) {
|
if (sipsRecords.length === 0) {
|
||||||
return res
|
return respondError(res, {
|
||||||
.status(404)
|
status: 404,
|
||||||
.json({ error: "No SIPs record found for this incidentID." });
|
code: "SIPS_RECORD_NOT_FOUND",
|
||||||
|
message: "No SIPs record found for this incidentID."
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const sipsId = sipsRecords[0].pinswg_sipsid;
|
const sipsId = sipsRecords[0].pinswg_sipsid;
|
||||||
@@ -53,11 +60,13 @@ export default async function ApiProxy(req, res) {
|
|||||||
azureHeaders(token.access_token)
|
azureHeaders(token.access_token)
|
||||||
);
|
);
|
||||||
|
|
||||||
res.status(200).json(eventsResponse.data);
|
return respondSuccess(res, eventsResponse.data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
consoleLogger(error);
|
consoleLogger(error);
|
||||||
res.status(500).json({
|
return respondError(res, {
|
||||||
error: "An error occurred while retrieving data.",
|
status: 500,
|
||||||
|
code: "EVENTS_FETCH_FAILED",
|
||||||
|
message: "An error occurred while retrieving data.",
|
||||||
details: error.message || error.toString()
|
details: error.message || error.toString()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user