| export type ErrorType = |
| | 'bad_request' |
| | 'unauthorized' |
| | 'forbidden' |
| | 'not_found' |
| | 'rate_limit' |
| | 'offline'; |
|
|
| export type Surface = |
| | 'chat' |
| | 'auth' |
| | 'api' |
| | 'stream' |
| | 'database' |
| | 'history' |
| | 'vote' |
| | 'document' |
| | 'suggestions'; |
|
|
| export type ErrorCode = `${ErrorType}:${Surface}`; |
|
|
| export type ErrorVisibility = 'response' | 'log' | 'none'; |
|
|
| export const visibilityBySurface: Record<Surface, ErrorVisibility> = { |
| database: 'log', |
| chat: 'response', |
| auth: 'response', |
| stream: 'response', |
| api: 'response', |
| history: 'response', |
| vote: 'response', |
| document: 'response', |
| suggestions: 'response', |
| }; |
|
|
| export class ChatSDKError extends Error { |
| public type: ErrorType; |
| public surface: Surface; |
| public statusCode: number; |
|
|
| constructor(errorCode: ErrorCode, cause?: string) { |
| super(); |
|
|
| const [type, surface] = errorCode.split(':'); |
|
|
| this.type = type as ErrorType; |
| this.cause = cause; |
| this.surface = surface as Surface; |
| this.message = getMessageByErrorCode(errorCode); |
| this.statusCode = getStatusCodeByType(this.type); |
| } |
|
|
| public toResponse() { |
| const code: ErrorCode = `${this.type}:${this.surface}`; |
| const visibility = visibilityBySurface[this.surface]; |
|
|
| const { message, cause, statusCode } = this; |
|
|
| if (visibility === 'log') { |
| console.error({ |
| code, |
| message, |
| cause, |
| }); |
|
|
| return Response.json( |
| { code: '', message: 'Something went wrong. Please try again later.' }, |
| { status: statusCode }, |
| ); |
| } |
|
|
| return Response.json({ code, message, cause }, { status: statusCode }); |
| } |
| } |
|
|
| export function getMessageByErrorCode(errorCode: ErrorCode): string { |
| if (errorCode.includes('database')) { |
| return 'An error occurred while executing a database query.'; |
| } |
|
|
| switch (errorCode) { |
| case 'bad_request:api': |
| return "The request couldn't be processed. Please check your input and try again."; |
|
|
| case 'unauthorized:auth': |
| return 'You need to sign in before continuing.'; |
| case 'forbidden:auth': |
| return 'Your account does not have access to this feature.'; |
|
|
| case 'rate_limit:chat': |
| return 'You have exceeded your maximum number of messages for the day. Please try again later.'; |
| case 'not_found:chat': |
| return 'The requested chat was not found. Please check the chat ID and try again.'; |
| case 'forbidden:chat': |
| return 'This chat belongs to another user. Please check the chat ID and try again.'; |
| case 'unauthorized:chat': |
| return 'You need to sign in to view this chat. Please sign in and try again.'; |
| case 'offline:chat': |
| return "We're having trouble sending your message. Please check your internet connection and try again."; |
|
|
| case 'not_found:document': |
| return 'The requested document was not found. Please check the document ID and try again.'; |
| case 'forbidden:document': |
| return 'This document belongs to another user. Please check the document ID and try again.'; |
| case 'unauthorized:document': |
| return 'You need to sign in to view this document. Please sign in and try again.'; |
| case 'bad_request:document': |
| return 'The request to create or update the document was invalid. Please check your input and try again.'; |
|
|
| default: |
| return 'Something went wrong. Please try again later.'; |
| } |
| } |
|
|
| function getStatusCodeByType(type: ErrorType) { |
| switch (type) { |
| case 'bad_request': |
| return 400; |
| case 'unauthorized': |
| return 401; |
| case 'forbidden': |
| return 403; |
| case 'not_found': |
| return 404; |
| case 'rate_limit': |
| return 429; |
| case 'offline': |
| return 503; |
| default: |
| return 500; |
| } |
| } |
|
|