@clerk/shared
Version:
Internal package utils used by the Clerk SDKs
1 lines • 12.4 kB
Source Map (JSON)
{"version":3,"sources":["../src/error.ts"],"sourcesContent":["import type { ClerkAPIError, ClerkAPIErrorJSON } from '@clerk/types';\n\nimport { deprecated } from './deprecated';\n\nexport function isUnauthorizedError(e: any): boolean {\n const status = e?.status;\n const code = e?.errors?.[0]?.code;\n return code === 'authentication_invalid' && status === 401;\n}\n\nexport function is4xxError(e: any): boolean {\n const status = e?.status;\n return !!status && status >= 400 && status < 500;\n}\n\nexport function isNetworkError(e: any): boolean {\n // TODO: revise during error handling epic\n const message = (`${e.message}${e.name}` || '').toLowerCase().replace(/\\s+/g, '');\n return message.includes('networkerror');\n}\n\ninterface ClerkAPIResponseOptions {\n data: ClerkAPIErrorJSON[];\n status: number;\n}\n\n// For a comprehensive Metamask error list, please see\n// https://docs.metamask.io/guide/ethereum-provider.html#errors\nexport interface MetamaskError extends Error {\n code: 4001 | 32602 | 32603;\n message: string;\n data?: unknown;\n}\n\nexport function isKnownError(error: any) {\n return isClerkAPIResponseError(error) || isMetamaskError(error) || isClerkRuntimeError(error);\n}\n\nexport function isClerkAPIResponseError(err: any): err is ClerkAPIResponseError {\n return 'clerkError' in err;\n}\n\n/**\n * Checks if the provided error object is an instance of ClerkRuntimeError.\n *\n * @param {any} err - The error object to check.\n * @returns {boolean} True if the error is a ClerkRuntimeError, false otherwise.\n *\n * @example\n * const error = new ClerkRuntimeError('An error occurred');\n * if (isClerkRuntimeError(error)) {\n * // Handle ClerkRuntimeError\n * console.error('ClerkRuntimeError:', error.message);\n * } else {\n * // Handle other errors\n * console.error('Other error:', error.message);\n * }\n */\nexport function isClerkRuntimeError(err: any): err is ClerkRuntimeError {\n return 'clerkRuntimeError' in err;\n}\n\nexport function isMetamaskError(err: any): err is MetamaskError {\n return 'code' in err && [4001, 32602, 32603].includes(err.code) && 'message' in err;\n}\n\nexport function parseErrors(data: ClerkAPIErrorJSON[] = []): ClerkAPIError[] {\n return data.length > 0 ? data.map(parseError) : [];\n}\n\nexport function parseError(error: ClerkAPIErrorJSON): ClerkAPIError {\n return {\n code: error.code,\n message: error.message,\n longMessage: error.long_message,\n meta: {\n paramName: error?.meta?.param_name,\n sessionId: error?.meta?.session_id,\n emailAddresses: error?.meta?.email_addresses,\n identifiers: error?.meta?.identifiers,\n zxcvbn: error?.meta?.zxcvbn,\n },\n };\n}\n\nexport class ClerkAPIResponseError extends Error {\n clerkError: true;\n\n status: number;\n message: string;\n\n errors: ClerkAPIError[];\n\n constructor(message: string, { data, status }: ClerkAPIResponseOptions) {\n super(message);\n\n Object.setPrototypeOf(this, ClerkAPIResponseError.prototype);\n\n this.status = status;\n this.message = message;\n this.clerkError = true;\n this.errors = parseErrors(data);\n }\n\n public toString = () => {\n return `[${this.name}]\\nMessage:${this.message}\\nStatus:${this.status}\\nSerialized errors: ${this.errors.map(e =>\n JSON.stringify(e),\n )}`;\n };\n}\n\n/**\n * Custom error class for representing Clerk runtime errors.\n *\n * @class ClerkRuntimeError\n * @example\n * throw new ClerkRuntimeError('An error occurred', { code: 'password_invalid' });\n */\nexport class ClerkRuntimeError extends Error {\n clerkRuntimeError: true;\n\n /**\n * The error message.\n *\n * @type {string}\n * @memberof ClerkRuntimeError\n */\n message: string;\n\n /**\n * A unique code identifying the error, used for localization\n *\n * @type {string}\n * @memberof ClerkRuntimeError\n */\n code: string;\n\n constructor(message: string, { code }: { code: string }) {\n super(message);\n\n Object.setPrototypeOf(this, ClerkRuntimeError.prototype);\n\n this.code = code;\n this.message = message;\n this.clerkRuntimeError = true;\n }\n\n /**\n * Returns a string representation of the error.\n *\n * @returns {string} A formatted string with the error name and message.\n * @memberof ClerkRuntimeError\n */\n public toString = () => {\n return `[${this.name}]\\nMessage:${this.message}`;\n };\n}\n\n/**\n * @deprecated Use `EmailLinkError` instead.\n */\nexport class MagicLinkError extends Error {\n code: string;\n\n constructor(code: string) {\n super(code);\n this.code = code;\n Object.setPrototypeOf(this, MagicLinkError.prototype);\n deprecated('MagicLinkError', 'Use `EmailLinkError` instead.');\n }\n}\n\nexport class EmailLinkError extends Error {\n code: string;\n\n constructor(code: string) {\n super(code);\n this.code = code;\n Object.setPrototypeOf(this, EmailLinkError.prototype);\n }\n}\n\n/**\n * Check if the error is a MagicLinkError.\n * @deprecated Use `isEmailLinkError` instead.\n */\nexport function isMagicLinkError(err: Error): err is MagicLinkError {\n deprecated('isMagicLinkError', 'Use `isEmailLinkError` instead.');\n return err instanceof MagicLinkError;\n}\n\nexport function isEmailLinkError(err: Error): err is EmailLinkError {\n return err instanceof EmailLinkError;\n}\n\nconst _MagicLinkErrorCode = {\n Expired: 'expired',\n Failed: 'failed',\n};\n\n/**\n * @deprecated Use `EmailLinkErrorCode` instead.\n */\nexport const MagicLinkErrorCode = new Proxy(_MagicLinkErrorCode, {\n get(target, prop, receiver) {\n deprecated('MagicLinkErrorCode', 'Use `EmailLinkErrorCode` instead.');\n return Reflect.get(target, prop, receiver);\n },\n});\n\nexport const EmailLinkErrorCode = {\n Expired: 'expired',\n Failed: 'failed',\n};\n\nconst DefaultMessages = Object.freeze({\n InvalidFrontendApiErrorMessage: `The frontendApi passed to Clerk is invalid. You can get your Frontend API key at https://dashboard.clerk.com/last-active?path=api-keys. (key={{key}})`,\n InvalidProxyUrlErrorMessage: `The proxyUrl passed to Clerk is invalid. The expected value for proxyUrl is an absolute URL or a relative path with a leading '/'. (key={{url}})`,\n InvalidPublishableKeyErrorMessage: `The publishableKey passed to Clerk is invalid. You can get your Publishable key at https://dashboard.clerk.com/last-active?path=api-keys. (key={{key}})`,\n MissingPublishableKeyErrorMessage: `Missing publishableKey. You can get your key at https://dashboard.clerk.com/last-active?path=api-keys.`,\n});\n\ntype MessageKeys = keyof typeof DefaultMessages;\n\ntype Messages = Record<MessageKeys, string>;\n\ntype CustomMessages = Partial<Messages>;\n\nexport type ErrorThrowerOptions = {\n packageName: string;\n customMessages?: CustomMessages;\n};\n\nexport interface ErrorThrower {\n setPackageName(options: ErrorThrowerOptions): ErrorThrower;\n setMessages(options: ErrorThrowerOptions): ErrorThrower;\n throwInvalidPublishableKeyError(params: { key?: string }): never;\n throwInvalidFrontendApiError(params: { key?: string }): never;\n throwInvalidProxyUrl(params: { url?: string }): never;\n throwMissingPublishableKeyError(): never;\n}\n\nexport function buildErrorThrower({ packageName, customMessages }: ErrorThrowerOptions): ErrorThrower {\n let pkg = packageName;\n\n const messages = {\n ...DefaultMessages,\n ...customMessages,\n };\n\n function buildMessage(rawMessage: string, replacements?: Record<string, string | number>) {\n if (!replacements) {\n return `${pkg}: ${rawMessage}`;\n }\n\n let msg = rawMessage;\n const matches = rawMessage.matchAll(/{{([a-zA-Z0-9-_]+)}}/g);\n\n for (const match of matches) {\n const replacement = (replacements[match[1]] || '').toString();\n msg = msg.replace(`{{${match[1]}}}`, replacement);\n }\n\n return `${pkg}: ${msg}`;\n }\n\n return {\n setPackageName({ packageName }: ErrorThrowerOptions): ErrorThrower {\n if (typeof packageName === 'string') {\n pkg = packageName;\n }\n return this;\n },\n\n setMessages({ customMessages }: ErrorThrowerOptions): ErrorThrower {\n Object.assign(messages, customMessages || {});\n return this;\n },\n\n throwInvalidPublishableKeyError(params: { key?: string }): never {\n throw new Error(buildMessage(messages.InvalidPublishableKeyErrorMessage, params));\n },\n\n throwInvalidFrontendApiError(params: { key?: string }): never {\n throw new Error(buildMessage(messages.InvalidFrontendApiErrorMessage, params));\n },\n\n throwInvalidProxyUrl(params: { url?: string }): never {\n throw new Error(buildMessage(messages.InvalidProxyUrlErrorMessage, params));\n },\n\n throwMissingPublishableKeyError(): never {\n throw new Error(buildMessage(messages.MissingPublishableKeyErrorMessage));\n },\n };\n}\n"],"mappings":"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","names":["packageName","customMessages"]}