HR-ATS-Portal/frontend/src/lib/errors.js

72 lines
2.4 KiB
JavaScript

/* ============================================================
errors.js — the API error type and FastAPI `detail` unwrapping.
Lifted verbatim from the original src/api.js. FastAPI returns errors as
{detail: ...} where `detail` is a string for HTTPException and an array of
{loc, msg, type} objects for request-validation failures — parseDetail
already handles both shapes, so it moves unchanged.
============================================================ */
export class ApiError extends Error {
constructor(message, status, body) {
super(message)
this.name = 'ApiError'
this.status = status
this.body = body
}
}
/** Raised when the refresh token itself is rejected — the session is over. */
export class SessionExpiredError extends Error {
constructor(message = 'Your session has expired. Please sign in again.') {
super(message)
this.name = 'SessionExpiredError'
}
}
export function parseDetail(detail) {
if (detail == null || detail === '') return null
if (typeof detail === 'string') return detail
if (Array.isArray(detail)) {
return detail
.map((item) => {
if (typeof item === 'string') return item
if (item && typeof item === 'object') {
return item.msg || item.message || JSON.stringify(item)
}
return String(item)
})
.filter(Boolean)
.join('; ')
}
if (typeof detail === 'object') {
return detail.msg || detail.message || JSON.stringify(detail)
}
return String(detail)
}
export function friendlyAuthError(err, fallback = 'Something went wrong. Please try again.') {
if (!(err instanceof ApiError)) {
return err?.message || fallback
}
const fromServer = parseDetail(err.body?.detail)
switch (err.status) {
case 429:
return fromServer || 'Too many attempts. Please wait a moment and try again.'
case 404:
return fromServer || 'No account found for that email.'
case 400:
return fromServer || 'Please check your details and try again.'
case 401:
return fromServer || 'Incorrect email or password.'
case 403:
return fromServer || 'Your Approval is at Pending'
case 409:
return fromServer || 'An account with that email already exists.'
case 502:
return fromServer || 'Email service is temporarily unavailable. Please try again later.'
default:
return fromServer || err.message || fallback
}
}