nav-connect
Version:
Nav Online Invoice connection module
75 lines • 3.01 kB
JavaScript
import { XsdSchemaName, buildApiRequestXml, xmlParser, XmlValidationError } from "nav-osa-core";
import { NavApiError, NavApiHttpError, NavApiResponseError, NavApiTimeoutError, NavXmlValidationError, } from "./errors.js";
const TIMEOUT_ERROR_CODES = new Set(["ECONNABORTED", "ETIMEDOUT"]);
function toNavApiResponseError(result, httpStatus, technicalValidationMessages) {
return new NavApiResponseError({
funcCode: result.funcCode,
errorCode: result.errorCode,
message: result.message,
httpStatus,
technicalValidationMessages,
});
}
function checkResponseResult(result) {
if (!result)
return;
if (result.funcCode === "ERROR") {
throw toNavApiResponseError(result);
}
}
function throwIfGeneralError(parsed, httpStatus) {
const generalError = parsed.GeneralErrorResponse;
if (generalError?.result) {
throw toNavApiResponseError(generalError.result, httpStatus, generalError.technicalValidationMessages);
}
}
export async function handleAxiosError(error, timeoutMs) {
if (error.code !== undefined && TIMEOUT_ERROR_CODES.has(error.code)) {
throw new NavApiTimeoutError(timeoutMs);
}
const status = error.response?.status;
const statusText = error.response?.statusText;
const rawBody = typeof error.response?.data === "string" ? error.response.data : undefined;
if (rawBody) {
let parsed;
try {
parsed = await xmlParser(rawBody, XsdSchemaName.InvoiceApi, { validate: false });
}
catch (parseErr) {
if (parseErr instanceof XmlValidationError) {
throw new NavApiHttpError(status ?? 0, statusText, rawBody);
}
throw new NavApiHttpError(status ?? 0, statusText, rawBody, parseErr);
}
throwIfGeneralError(parsed, status ?? 0);
}
throw new NavApiHttpError(status ?? 0, statusText, rawBody);
}
export async function parseApiResponse(responseXml, rootName) {
const parsed = await xmlParser(responseXml, XsdSchemaName.InvoiceApi, {
validate: false,
});
// Nav always answers with the "<RequestType minus Request>Response"
// root element; anything else means we cannot interpret the reply.
// Functional errors arrive as GeneralErrorResponse with HTTP 200, so
// that envelope must be checked before giving up on the root element.
const data = parsed[rootName];
if (!data) {
throwIfGeneralError(parsed, 200);
throw new NavApiError(`Unexpected NAV response: missing '${rootName}' root element`);
}
checkResponseResult(data.result);
return data;
}
export async function buildRequestOrThrow(requestType, reqObj) {
try {
return await buildApiRequestXml(requestType, reqObj);
}
catch (error) {
if (error instanceof XmlValidationError) {
throw new NavXmlValidationError(requestType, error.errors);
}
throw error;
}
}
//# sourceMappingURL=errorMapping.js.map