104 lines
2.7 KiB
JavaScript
104 lines
2.7 KiB
JavaScript
/**
|
|
* @file rr-error.js
|
|
* @description Centralized error class and assertion logic for Reynolds & Reynolds API calls.
|
|
* Provides consistent handling across all RR modules (customer, repair order, lookups, etc.)
|
|
*/
|
|
|
|
/**
|
|
* Custom Error type for RR API responses
|
|
*/
|
|
class RrApiError extends Error {
|
|
constructor(message, { reqId, url, apiName, errorData, status, statusText } = {}) {
|
|
super(message);
|
|
this.name = "RrApiError";
|
|
this.reqId = reqId || null;
|
|
this.url = url || null;
|
|
this.apiName = apiName || null;
|
|
this.errorData = errorData || null;
|
|
this.status = status || null;
|
|
this.statusText = statusText || null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Assert that a Reynolds & Reynolds response is successful.
|
|
*
|
|
* Expected success structure (based on Rome RR specs):
|
|
* {
|
|
* "SuccessFlag": true,
|
|
* "ErrorCode": "0",
|
|
* "ErrorMessage": "",
|
|
* "Data": { ... }
|
|
* }
|
|
*
|
|
* Or if SOAP/XML-based:
|
|
* {
|
|
* "Envelope": {
|
|
* "Body": {
|
|
* "Response": {
|
|
* "SuccessFlag": true,
|
|
* ...
|
|
* }
|
|
* }
|
|
* }
|
|
* }
|
|
*
|
|
* This helper unwraps and normalizes the response to detect any error cases.
|
|
*/
|
|
function assertRrOk(data, { apiName = "RR API Call", allowEmpty = false } = {}) {
|
|
if (!data && !allowEmpty) {
|
|
throw new RrApiError(`${apiName} returned no data`, { apiName });
|
|
}
|
|
|
|
// Normalize envelope
|
|
const response =
|
|
data?.Envelope?.Body?.Response ||
|
|
data?.Envelope?.Body?.[Object.keys(data.Envelope?.Body || {})[0]] ||
|
|
data?.Response ||
|
|
data;
|
|
|
|
// Handle array of errors or error objects
|
|
const errorBlock = response?.Errors || response?.Error || response?.Fault || null;
|
|
|
|
// Basic success conditions per RR documentation
|
|
const success =
|
|
response?.SuccessFlag === true ||
|
|
response?.ErrorCode === "0" ||
|
|
response?.ResultCode === "0" ||
|
|
(Array.isArray(errorBlock) && errorBlock.length === 0);
|
|
|
|
// If success, return normalized response
|
|
if (success || allowEmpty) {
|
|
return response?.Data || response;
|
|
}
|
|
|
|
// Construct contextual error info
|
|
const errorMessage = response?.ErrorMessage || response?.FaultString || response?.Message || "Unknown RR API error";
|
|
|
|
throw new RrApiError(`${apiName} failed: ${errorMessage}`, {
|
|
apiName,
|
|
errorData: response,
|
|
status: response?.ErrorCode || response?.ResultCode
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Safely unwrap nested RR API responses for consistency across handlers.
|
|
*/
|
|
function extractRrResponseData(data) {
|
|
if (!data) return null;
|
|
|
|
return (
|
|
data?.Envelope?.Body?.Response?.Data ||
|
|
data?.Envelope?.Body?.[Object.keys(data.Envelope?.Body || {})[0]]?.Data ||
|
|
data?.Data ||
|
|
data
|
|
);
|
|
}
|
|
|
|
module.exports = {
|
|
RrApiError,
|
|
assertRrOk,
|
|
extractRrResponseData
|
|
};
|