w-aura/src/api/errors.ts
2024-04-18 21:54:57 +00:00

81 lines
2.3 KiB
TypeScript

export interface FullDomainError {
title: string
message?: string
detail?: string
source?: {
pointer: string
parameter: string
}
}
export type ShortDomainError = FullDomainError['title']
export interface BaseDomainError {
base: ShortDomainError[]
}
export interface ErrorListResponse {
errors: BaseDomainError | FullDomainError[] | ShortDomainError[]
}
export interface SingleErrorResponse {
error: ShortDomainError
}
export type ErrorResponse = ErrorListResponse | SingleErrorResponse
export type ErrorPayload<T = unknown> = {
body: ErrorResponse
statusCode: number
responseData?: T | null
}
export type MaybeError = ShortDomainError | FullDomainError | undefined
export const buildUnknownError = (statusCode: number) => `Unknown Error occurred from Server with status code ${statusCode}`
export class ApiError<T = unknown> extends Error {
readonly body: ErrorResponse
readonly statusCode: number
readonly responseData: T | null
constructor(payload: ErrorPayload<T>) {
super('Caught an error while fetching the API Server endpoint...')
this.name = 'ApiError'
this.body = payload.body
this.statusCode = payload.statusCode
this.responseData = payload?.responseData || null
}
}
export function isErrorResponse<R>(data: R | ErrorResponse): data is ErrorResponse {
return isSingleErrorResponse<R>(data) || isErrorListResponse<R>(data)
}
export function isSingleErrorResponse<R>(data: R | ErrorResponse): data is SingleErrorResponse {
return typeof data === 'object' && data !== null && 'error' in data
}
export function isErrorListResponse<R>(data: R | ErrorResponse): data is ErrorListResponse {
return typeof data === 'object' && data !== null && 'errors' in data
}
export function isShortDomainError(error: MaybeError): error is ShortDomainError {
return typeof error === 'string'
}
export function extractErrorMessage(apiError: ApiError): string {
const body = isSingleErrorResponse(apiError.body) ? [apiError.body.error] : apiError.body.errors
const errors = Array.isArray(body) ? body : body.base
const firstError = errors.at(0)
if (firstError === undefined) {
return buildUnknownError(apiError.statusCode)
}
if (isShortDomainError(firstError)) {
return firstError
}
if ('message' in firstError && firstError.message) {
return firstError.message
}
return firstError.title
}