(
url: string,
options: RequestInit = {}
)
| 537 | |
| 538 | // API request interceptor |
| 539 | export const fetchWithErrorHandling = async ( |
| 540 | url: string, |
| 541 | options: RequestInit = {} |
| 542 | ) => { |
| 543 | try { |
| 544 | const response = await fetch(url, options); |
| 545 | |
| 546 | // Handle HTTP errors |
| 547 | if (!response.ok) { |
| 548 | // Try to parse JSON response for business error code first |
| 549 | let errorCode = response.status; |
| 550 | let errorMessage = `Request failed: ${response.status}`; |
| 551 | const errorText = await response.text(); |
| 552 | |
| 553 | let parsedErrorData = null; |
| 554 | try { |
| 555 | const errorData = JSON.parse(errorText); |
| 556 | if (errorData && errorData.code) { |
| 557 | parsedErrorData = errorData; |
| 558 | errorCode = errorData.code; |
| 559 | errorMessage = errorData.message || errorMessage; |
| 560 | } else { |
| 561 | errorMessage = errorText || errorMessage; |
| 562 | } |
| 563 | } catch { |
| 564 | // Not JSON, use text as message |
| 565 | errorMessage = errorText || errorMessage; |
| 566 | } |
| 567 | |
| 568 | // Check if it's a session expiration error based on business error code |
| 569 | // TOKEN_EXPIRED = "000203", TOKEN_INVALID = "000204" |
| 570 | const errorCodeStr = String(errorCode); |
| 571 | if ( |
| 572 | errorCodeStr === ErrorCode.TOKEN_EXPIRED || |
| 573 | errorCodeStr === ErrorCode.TOKEN_INVALID |
| 574 | ) { |
| 575 | handleSessionExpired(); |
| 576 | throw new ApiError(errorCode, errorMessage); |
| 577 | } |
| 578 | |
| 579 | // Handle HTTP 401 - trigger session expired modal for all unauthorized errors |
| 580 | if (response.status === 401) { |
| 581 | handleSessionExpired(); |
| 582 | throw new ApiError(errorCode, errorMessage); |
| 583 | } |
| 584 | |
| 585 | // Handle custom 499 error code (client closed connection) |
| 586 | if (response.status === 499) { |
| 587 | handleSessionExpired(); |
| 588 | throw new ApiError( |
| 589 | ErrorCode.TOKEN_EXPIRED, |
| 590 | "Connection disconnected, session may have expired" |
| 591 | ); |
| 592 | } |
| 593 | |
| 594 | // Handle request entity too large error (413) |
| 595 | if (response.status === 413) { |
| 596 | throw new ApiError( |
no test coverage detected