TASK22229: P2-S2 batch 3 migrate case/event relay GET endpoints

This commit is contained in:
2026-03-24 07:49:28 +00:00
parent fdf95dd0b1
commit 44b32a618a
6 changed files with 106 additions and 116 deletions
+34
View File
@@ -836,3 +836,37 @@ Validation:
Follow-ups:
- Continue P2-S2 with Batch 3 as the next dedicated commit on this branch.
---
### CL-022: TASK22229 P2-S2 Batch 3 (case/event relay GET cluster)
date: 2026-03-24
author: Cline
scope: `pages/api/endpoint/{getcase_api,getcasebyid_api,getincidentbyid_api,getsipsevents_api}.js`, `tests/phase21/endpoint-handler-contract.test.cjs`
type: change
rationale: Deliver third P2-S2 commit by migrating an additional bounded case/event endpoint cluster onto shared `relayGet` while preserving route contracts.
impact: Further relay boilerplate reduction and consistent forwarding behavior with no intended contract changes.
status: completed
Summary:
- Migrated Batch 3 endpoints to `relayGet`:
- `getcase_api.js` (preserved `@odata.nextLink` normalization)
- `getcasebyid_api.js` (preserved `@odata.nextLink` normalization and array-wrapped success payload)
- `getincidentbyid_api.js`
- `getsipsevents_api.js`
- Updated phase21 endpoint contract tests to mock `relayGet` for migrated handlers in guard/catch paths.
Validation:
- `node tests/phase21/api-contract-slice1.test.cjs` -> pass
- helper: 4/4
- file-handler: 53/53
- email-handler: 12/12
- endpoint-handler: 152/152
- documents-handler: 3/3
Follow-ups:
- Continue P2-S2 with next bounded batch (e.g. search/listing cluster) as a separate commit if required.
+19 -31
View File
@@ -10,17 +10,9 @@
* description: Success
*/
import axios from "axios";
import _ from "lodash";
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 ||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
import { respondError } from "../middleware/apiResponse";
import { relayGet } from "../middleware/relayForwarding";
export default async function ApiProxy(req, res) {
const incidentID = req.query.incidentID;
@@ -33,30 +25,26 @@ export default async function ApiProxy(req, res) {
});
}
try {
const token = await getToken();
const queryUrl =
"incidents(" +
incidentID +
")?$select=ticketnumber,title,pinswg_appealcasetype";
const queryUrl =
"incidents(" +
incidentID +
")?$select=ticketnumber,title,pinswg_appealcasetype";
const { data } = await axios.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeaders(token.access_token)
);
return relayGet({
queryUrl,
res,
transformData: (data) => {
if (_.has(data, "@odata.nextLink") === true) {
const dataStr = JSON.stringify(data["@odata.nextLink"]);
data["@odata.nextLink"] = dataStr.split("/v8.2/")[1];
}
if (_.has(data, "@odata.nextLink") === true) {
const dataStr = JSON.stringify(data["@odata.nextLink"]);
data["@odata.nextLink"] = dataStr.split("/v8.2/")[1];
}
return respondSuccess(res, data);
} catch (error) {
consoleLogger(error);
return respondError(res, {
return data;
},
errorResponse: {
status: 400,
code: "CASE_FETCH_FAILED",
message: "Failed to fetch case"
});
}
}
});
}
+16 -28
View File
@@ -10,17 +10,9 @@
* description: Success
*/
import axios from "axios";
import _ from "lodash";
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 ||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
import { respondError } from "../middleware/apiResponse";
import { relayGet } from "../middleware/relayForwarding";
export default async function ApiProxy(req, res) {
const incidentID = req.query.incidentID;
@@ -33,27 +25,23 @@ export default async function ApiProxy(req, res) {
});
}
try {
const token = await getToken();
const queryUrl = "incidents(" + incidentID + ")";
const queryUrl = "incidents(" + incidentID + ")";
const { data } = await axios.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeaders(token.access_token)
);
return relayGet({
queryUrl,
res,
transformData: (data) => {
if (_.has(data, "@odata.nextLink") === true) {
const dataStr = JSON.stringify(data["@odata.nextLink"]);
data["@odata.nextLink"] = dataStr.split("/v8.2/")[1];
}
if (_.has(data, "@odata.nextLink") === true) {
const dataStr = JSON.stringify(data["@odata.nextLink"]);
data["@odata.nextLink"] = dataStr.split("/v8.2/")[1];
}
return respondSuccess(res, [data]);
} catch (error) {
consoleLogger(error);
return respondError(res, {
return [data];
},
errorResponse: {
status: 400,
code: "CASE_BY_ID_FETCH_FAILED",
message: "Failed to fetch case by id"
});
}
}
});
}
+13 -29
View File
@@ -15,16 +15,8 @@
* description: Success
*/
import axios from "axios";
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 ||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
import { respondError } from "../middleware/apiResponse";
import { relayGet } from "../middleware/relayForwarding";
export default async function ApiProxy(req, res) {
let searchString = req.query.searchString;
@@ -37,28 +29,20 @@ export default async function ApiProxy(req, res) {
});
}
try {
const token = await getToken();
searchString = searchString.replace(/\'/g, "''");
searchString = searchString.replace(/\'/g, "''");
const queryUrl =
"incidents?$select=pinswg_environmentalstatementlocation,pinswg_publishtoweb,modifiedon,description,numberofchildincidents,_accountid_value,_customerid_value,_pinswg_associatedlpa_value,_ownerid_value,pinswg_appealcasetype,statuscode,ticketnumber,title, _primarycontactid_value,pinswg_lpareference,pinswg_appellantagent,pinswg_appellantfirstname,pinswg_appellantlastname&$expand=primarycontactid($select=fullname)&$filter=incidentid eq " +
searchString +
" and pinswg_appealcasetype ne null &$orderby=createdon desc&$count=true";
const queryUrl =
"incidents?$select=pinswg_environmentalstatementlocation,pinswg_publishtoweb,modifiedon,description,numberofchildincidents,_accountid_value,_customerid_value,_pinswg_associatedlpa_value,_ownerid_value,pinswg_appealcasetype,statuscode,ticketnumber,title, _primarycontactid_value,pinswg_lpareference,pinswg_appellantagent,pinswg_appellantfirstname,pinswg_appellantlastname&$expand=primarycontactid($select=fullname)&$filter=incidentid eq " +
searchString +
" and pinswg_appealcasetype ne null &$orderby=createdon desc&$count=true";
const { data } = await axios.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeaders(token.access_token)
);
return respondSuccess(res, data);
} catch (error) {
consoleLogger(error);
return respondError(res, {
return relayGet({
queryUrl,
res,
errorResponse: {
status: 400,
code: "INCIDENT_BY_ID_FETCH_FAILED",
message: "Failed to fetch incident by id"
});
}
}
});
}
+12 -28
View File
@@ -1,13 +1,5 @@
import axios from "axios";
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 ||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
import { respondError } from "../middleware/apiResponse";
import { relayGet } from "../middleware/relayForwarding";
export default async function ApiProxy(req, res) {
const caseid = req.query.caseid;
@@ -20,26 +12,18 @@ export default async function ApiProxy(req, res) {
});
}
try {
const token = await getToken();
const queryUrl =
"pinswg_sipsevents?$filter=_pinswg_sipseventsid_value eq " +
caseid +
"&$count=true";
const queryUrl =
"pinswg_sipsevents?$filter=_pinswg_sipseventsid_value eq " +
caseid +
"&$count=true";
const { data } = await axios.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeaders(token.access_token)
);
return respondSuccess(res, data);
} catch (error) {
consoleLogger(error);
return respondError(res, {
return relayGet({
queryUrl,
res,
errorResponse: {
status: 400,
code: "SIPS_EVENTS_FETCH_FAILED",
message: "Failed to fetch SIPS events"
});
}
}
});
}
@@ -2439,6 +2439,7 @@ test("getcase returns INCIDENT_ID_REQUIRED when incidentID missing", async () =>
const mod = loadModule("pages/api/endpoint/getcase_api.js", {
respondError: respondErrorMock,
respondSuccess: respondSuccessMock,
relayGet: async () => ({}),
getToken: async () => ({ access_token: "token" }),
hashAPIPath: () => "&hash=expected",
azureHeaders: () => ({}),
@@ -2459,6 +2460,8 @@ test("getcase catch path returns CASE_FETCH_FAILED", async () => {
const mod = loadModule("pages/api/endpoint/getcase_api.js", {
respondError: respondErrorMock,
respondSuccess: respondSuccessMock,
relayGet: async ({ res, errorResponse }) =>
respondErrorMock(res, errorResponse),
getToken: async () => ({ access_token: "token" }),
hashAPIPath: () => "&hash=expected",
azureHeaders: () => ({}),
@@ -2483,6 +2486,7 @@ test("getcasebyid returns INCIDENT_ID_REQUIRED when incidentID missing", async (
const mod = loadModule("pages/api/endpoint/getcasebyid_api.js", {
respondError: respondErrorMock,
respondSuccess: respondSuccessMock,
relayGet: async () => ({}),
getToken: async () => ({ access_token: "token" }),
hashAPIPath: () => "&hash=expected",
azureHeaders: () => ({}),
@@ -2503,6 +2507,8 @@ test("getcasebyid catch path returns CASE_BY_ID_FETCH_FAILED", async () => {
const mod = loadModule("pages/api/endpoint/getcasebyid_api.js", {
respondError: respondErrorMock,
respondSuccess: respondSuccessMock,
relayGet: async ({ res, errorResponse }) =>
respondErrorMock(res, errorResponse),
getToken: async () => ({ access_token: "token" }),
hashAPIPath: () => "&hash=expected",
azureHeaders: () => ({}),
@@ -2530,6 +2536,7 @@ test("getincidentbyid returns SEARCH_STRING_REQUIRED when searchString missing",
const mod = loadModule("pages/api/endpoint/getincidentbyid_api.js", {
respondError: respondErrorMock,
respondSuccess: respondSuccessMock,
relayGet: async () => ({}),
getToken: async () => ({ access_token: "token" }),
hashAPIPath: () => "&hash=expected",
azureHeaders: () => ({}),
@@ -2549,6 +2556,8 @@ test("getincidentbyid catch path returns INCIDENT_BY_ID_FETCH_FAILED", async ()
const mod = loadModule("pages/api/endpoint/getincidentbyid_api.js", {
respondError: respondErrorMock,
respondSuccess: respondSuccessMock,
relayGet: async ({ res, errorResponse }) =>
respondErrorMock(res, errorResponse),
getToken: async () => ({ access_token: "token" }),
hashAPIPath: () => "&hash=expected",
azureHeaders: () => ({}),
@@ -3135,6 +3144,7 @@ test("getsipsevents returns CASE_ID_REQUIRED when caseid missing", async () => {
const mod = loadModule("pages/api/endpoint/getsipsevents_api.js", {
respondError: respondErrorMock,
respondSuccess: respondSuccessMock,
relayGet: async () => ({}),
getToken: async () => ({ access_token: "token" }),
hashAPIPath: () => "&hash=expected",
azureHeaders: () => ({}),
@@ -3154,6 +3164,8 @@ test("getsipsevents catch path returns SIPS_EVENTS_FETCH_FAILED", async () => {
const mod = loadModule("pages/api/endpoint/getsipsevents_api.js", {
respondError: respondErrorMock,
respondSuccess: respondSuccessMock,
relayGet: async ({ res, errorResponse }) =>
respondErrorMock(res, errorResponse),
getToken: async () => ({ access_token: "token" }),
hashAPIPath: () => "&hash=expected",
azureHeaders: () => ({}),