72 lines
2.4 KiB
JavaScript
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
|
|
}
|
|
}
|