|
| 1 | +import type { ClerkAPIErrorJSON, ClerkAPIResponseError as ClerkAPIResponseErrorInterface } from '@clerk/types'; |
| 2 | + |
| 3 | +import { ClerkAPIError } from './clerkApiError'; |
| 4 | +import type { ClerkErrorParams } from './clerkError'; |
| 5 | +import { ClerkError } from './clerkError'; |
| 6 | +import { createErrorTypeGuard } from './createErrorTypeGuard'; |
| 7 | + |
| 8 | +interface ClerkAPIResponseOptions extends Omit<ClerkErrorParams, 'message' | 'code'> { |
| 9 | + data: ClerkAPIErrorJSON[]; |
| 10 | + status: number; |
| 11 | + clerkTraceId?: string; |
| 12 | + retryAfter?: number; |
| 13 | +} |
| 14 | + |
| 15 | +export class ClerkAPIResponseError extends ClerkError implements ClerkAPIResponseErrorInterface { |
| 16 | + static name = 'ClerkAPIResponseError'; |
| 17 | + status: number; |
| 18 | + clerkTraceId?: string; |
| 19 | + retryAfter?: number; |
| 20 | + errors: ClerkAPIError[]; |
| 21 | + |
| 22 | + constructor(message: string, options: ClerkAPIResponseOptions) { |
| 23 | + const { data: errorsJson, status, clerkTraceId, retryAfter } = options; |
| 24 | + super({ ...options, message, code: 'api_response_error' }); |
| 25 | + Object.setPrototypeOf(this, ClerkAPIResponseError.prototype); |
| 26 | + this.status = status; |
| 27 | + this.clerkTraceId = clerkTraceId; |
| 28 | + this.retryAfter = retryAfter; |
| 29 | + this.errors = (errorsJson || []).map(e => new ClerkAPIError(e)); |
| 30 | + } |
| 31 | + |
| 32 | + public toString() { |
| 33 | + let message = `[${this.name}]\nMessage:${this.message}\nStatus:${this.status}\nSerialized errors: ${this.errors.map( |
| 34 | + e => JSON.stringify(e), |
| 35 | + )}`; |
| 36 | + |
| 37 | + if (this.clerkTraceId) { |
| 38 | + message += `\nClerk Trace ID: ${this.clerkTraceId}`; |
| 39 | + } |
| 40 | + |
| 41 | + return message; |
| 42 | + } |
| 43 | + |
| 44 | + // Override formatMessage to keep it unformatted for backward compatibility |
| 45 | + protected static override formatMessage(name: string, msg: string, _: string, __: string | undefined) { |
| 46 | + return msg; |
| 47 | + } |
| 48 | +} |
| 49 | + |
| 50 | +/** |
| 51 | + * Type guard to check if an error is a ClerkApiResponseError. |
| 52 | + * Can be called as a standalone function or as a method on an error object. |
| 53 | + * |
| 54 | + * @example |
| 55 | + * // As a standalone function |
| 56 | + * if (isClerkApiResponseError(error)) { ... } |
| 57 | + * |
| 58 | + * // As a method (when attached to error object) |
| 59 | + * if (error.isClerkApiResponseError()) { ... } |
| 60 | + */ |
| 61 | +export const isClerkApiResponseError = createErrorTypeGuard(ClerkAPIResponseError); |
0 commit comments