@eldev/business-central-api
Version:
A Dynamics 365 Business Central client for TypeScript
120 lines • 4.33 kB
JavaScript
import { categorizeError, } from "./categorize.js";
function parseErrorResponse(data) {
const response = data;
if (!response.error?.code || !response.error?.message) {
throw new Error("Invalid BC error response format");
}
return {
code: response.error.code,
message: response.error.message,
};
}
export class BCError extends Error {
category;
httpStatus;
retryStrategy;
timestamp;
correlationId;
validationDetails;
serverError;
responseData;
cause;
constructor(message, category, retryStrategy, httpStatus) {
super(message);
this.name = "BCError";
this.category = category;
this.retryStrategy = retryStrategy;
this.httpStatus = httpStatus;
this.timestamp = new Date();
if (Error.captureStackTrace) {
Error.captureStackTrace(this, BCError);
}
}
isRetryable() {
return this.retryStrategy !== "NO_RETRY";
}
isSchemaMismatch() {
return this.category === "SCHEMA_MISMATCH";
}
hasValidationDetails() {
return Boolean(this.validationDetails?.length);
}
getValidationFields() {
return this.validationDetails?.map((detail) => detail.path) || [];
}
toLogObject() {
return {
name: this.name,
message: this.message,
category: this.category,
httpStatus: this.httpStatus,
retryStrategy: this.retryStrategy,
correlationId: this.correlationId,
timestamp: this.timestamp.toISOString(),
validationDetails: this.validationDetails,
validationCount: this.validationDetails?.length,
responseData: this.responseData,
serverError: this.serverError,
};
}
toSpanAttributes() {
return {
"bc.error.category": this.category,
"bc.error.retryable": this.isRetryable(),
"bc.request.correlation_id": this.correlationId || "",
};
}
static fromHttpResponse(status, data, correlationId) {
let serverError;
try {
serverError = parseErrorResponse(data);
}
catch {
return BCError.fromUnexpectedResponse(data, status, correlationId);
}
const { category, retryStrategy } = categorizeError(serverError.code);
const bcError = new BCError(serverError.message, category, retryStrategy, status);
if (correlationId)
bcError.correlationId = correlationId;
bcError.serverError = serverError;
return bcError;
}
static fromSchemaValidation(issues, httpStatus = 200) {
const bcError = new BCError("Schema validation failed. The provided schema does not match Business Central's response format.", "SCHEMA_MISMATCH", "NO_RETRY", httpStatus);
bcError.validationDetails = issues;
return bcError;
}
static fromUnexpectedResponse(data, httpStatus, correlationId, cause) {
const bcError = new BCError("Business Central returned an unexpected response format", "UNEXPECTED_RESPONSE", "NO_RETRY", httpStatus);
if (correlationId)
bcError.correlationId = correlationId;
bcError.responseData = data;
bcError.cause = cause;
return bcError;
}
static fromGetToken(err) {
let message = "Failed to retrieve authentication token.";
let cause = new Error(message);
if (typeof err === "string") {
message = `${message}: ${err}`;
cause = new Error(err);
}
if (err instanceof Error) {
message = `${message}: ${err.message}`;
cause = err;
}
const bcError = new BCError(message, "AUTHENTICATION", "REFRESH_TOKEN", 401);
bcError.cause = cause;
return bcError;
}
static fromNetworkError(networkError) {
const nodeError = networkError;
const errorMessage = nodeError.code
? `Network error (${nodeError.code}): ${networkError.message}`
: `Network error: ${networkError.message}`;
const bcError = new BCError(errorMessage, "NETWORK_ERROR", "EXPONENTIAL_BACKOFF", 0);
bcError.cause = networkError;
return bcError;
}
}
//# sourceMappingURL=error.js.map