68 lines
2.5 KiB
JavaScript
68 lines
2.5 KiB
JavaScript
// -----------------------------------------------------------------------------
|
|
// Error handling utilities for Reynolds & Reynolds (RR) API calls.
|
|
// This mirrors Fortellis/CDK error helpers so the call pipeline stays uniform.
|
|
//
|
|
// TODO:RR — Replace the heuristics in assertRrOk with the *actual* envelope and
|
|
// status semantics from the Rome RR specs. Examples in the PDFs may show:
|
|
// - <Status code="0" severity="INFO">Success</Status>
|
|
// - <Status code="123" severity="ERROR">Some message</Status>
|
|
// - or a SuccessFlag/ReturnCode element in the JSON/XML response.
|
|
// -----------------------------------------------------------------------------
|
|
|
|
class RrApiError extends Error {
|
|
/**
|
|
* @param {string} message - Human-readable message
|
|
* @param {object} opts
|
|
* @param {string} [opts.reqId] - Internal request identifier
|
|
* @param {string} [opts.url] - Target URL of the API call
|
|
* @param {string} [opts.apiName] - Which API was invoked (for context)
|
|
* @param {object} [opts.errorData] - Raw error payload from RR
|
|
* @param {number} [opts.status] - HTTP status code
|
|
* @param {string} [opts.statusText] - HTTP status text
|
|
*/
|
|
constructor(message, { reqId, url, apiName, errorData, status, statusText } = {}) {
|
|
super(message);
|
|
this.name = "RrApiError";
|
|
this.reqId = reqId;
|
|
this.url = url;
|
|
this.apiName = apiName;
|
|
this.errorData = errorData;
|
|
this.status = status;
|
|
this.statusText = statusText;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Assert that an RR API response is considered "OK".
|
|
* Throws RrApiError otherwise.
|
|
*
|
|
* @param {*} data - Parsed response object from MakeRRCall
|
|
* @param {object} opts
|
|
* @param {string} opts.apiName - Which API we're checking (for error messages)
|
|
* @param {boolean} [opts.allowEmpty=false] - If true, allow null/empty results
|
|
* @returns {*} - The same data if valid
|
|
*/
|
|
function assertRrOk(data, { apiName, allowEmpty = false } = {}) {
|
|
// TODO:RR — Update logic to exactly match RR's success envelope.
|
|
// Possible patterns to confirm from PDFs:
|
|
// - data.Status?.code === "0"
|
|
// - data.Return?.successFlag === true
|
|
// - data.Errors is missing or empty
|
|
//
|
|
// For now, we use a simple heuristic fallback.
|
|
|
|
const hasErrors =
|
|
data == null ||
|
|
data.error ||
|
|
(Array.isArray(data.errors) && data.errors.length > 0) ||
|
|
(data.Status && data.Status.severity === "ERROR");
|
|
|
|
if (!allowEmpty && hasErrors) {
|
|
throw new RrApiError(`${apiName} returned an error`, { errorData: data, apiName });
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
module.exports = { RrApiError, assertRrOk };
|