|
| 1 | +/* eslint-disable jsdoc/require-jsdoc */ |
| 2 | +import type { ClerkAPIErrorJSON, ClerkApiErrorResponseJSON } from '@clerk/types'; |
| 3 | + |
| 4 | +import { parseError } from '../parseError'; |
| 5 | +import { ClerkError } from './future'; |
| 6 | + |
| 7 | +/** |
| 8 | + * A ClerkError subclass that represents the shell response of a Clerk API error. |
| 9 | + * This error contains an array of ClerkApiError instances, each representing a specific error that occurred. |
| 10 | + */ |
| 11 | +export class ClerkApiResponseError extends ClerkError { |
| 12 | + readonly name = 'ClerkApiResponseError'; |
| 13 | + readonly retryAfter?: number; |
| 14 | + readonly errors: ClerkApiError[]; |
| 15 | + |
| 16 | + constructor(data: ClerkApiErrorResponseJSON) { |
| 17 | + const errorMesages = data.errors.map(e => e.message).join(', '); |
| 18 | + const message = `Api errors occurred: ${errorMesages}. Check the \`errors\` property for more details about the specific errors.`; |
| 19 | + super({ message, code: 'clerk_api_error', clerkTraceId: data.clerk_trace_id }); |
| 20 | + this.errors = data.errors.map(e => new ClerkApiError(e)); |
| 21 | + } |
| 22 | +} |
| 23 | + |
| 24 | +/** |
| 25 | + * Type guard to check if an error is a ClerkApiResponseError. |
| 26 | + * Can be called as a standalone function or as a method on an error object. |
| 27 | + * |
| 28 | + * @example |
| 29 | + * // As a standalone function |
| 30 | + * if (isClerkApiResponseError(error)) { ... } |
| 31 | + * |
| 32 | + * // As a method (when attached to error object) |
| 33 | + * if (error.isClerkApiResponseError()) { ... } |
| 34 | + */ |
| 35 | +export function isClerkApiResponseError(error: Error): error is ClerkApiResponseError; |
| 36 | +export function isClerkApiResponseError(this: Error): this is ClerkApiResponseError; |
| 37 | +export function isClerkApiResponseError(this: Error | void, error?: Error): error is ClerkApiResponseError { |
| 38 | + const target = error ?? this; |
| 39 | + if (!target) { |
| 40 | + throw new TypeError('isClerkApiResponseError requires an error object'); |
| 41 | + } |
| 42 | + return target instanceof ClerkApiResponseError; |
| 43 | +} |
| 44 | + |
| 45 | +/** |
| 46 | + * This error contains the specific error message, code, and any additional metadata that was returned by the Clerk API. |
| 47 | + */ |
| 48 | +export class ClerkApiError extends ClerkError { |
| 49 | + readonly name = 'ClerkApiError'; |
| 50 | + |
| 51 | + constructor(json: ClerkAPIErrorJSON) { |
| 52 | + const parsedError = parseError(json); |
| 53 | + super({ |
| 54 | + code: parsedError.code, |
| 55 | + message: parsedError.message, |
| 56 | + longMessage: parsedError.longMessage, |
| 57 | + }); |
| 58 | + } |
| 59 | +} |
| 60 | + |
| 61 | +/** |
| 62 | + * Type guard to check if a value is a ClerkApiError instance. |
| 63 | + */ |
| 64 | +export function isClerkApiError(error: Error): error is ClerkApiError { |
| 65 | + return error instanceof ClerkApiError; |
| 66 | +} |
0 commit comments