UNPKG

@clerk/shared

Version:

Internal package utils used by the Clerk SDKs

631 lines (620 loc) • 18 kB
const require_clerkRuntimeError = require('./clerkRuntimeError-CYZdTZ_x.js'); //#region src/errors/clerkApiError.ts /** * This error contains the specific error message, code, and any additional metadata that was returned by the Clerk API. */ var ClerkAPIError = class { static kind = "ClerkAPIError"; code; message; longMessage; meta; constructor(json) { const parsedError = { code: json.code, message: json.message, longMessage: json.long_message, meta: { paramName: json.meta?.param_name, sessionId: json.meta?.session_id, emailAddresses: json.meta?.email_addresses, identifiers: json.meta?.identifiers, zxcvbn: json.meta?.zxcvbn, plan: json.meta?.plan, isPlanUpgradePossible: json.meta?.is_plan_upgrade_possible, seatsQuantityToAdd: json.meta?.seats_quantity_to_add, seatsQuantity: json.meta?.seats_quantity } }; this.code = parsedError.code; this.message = parsedError.message; this.longMessage = parsedError.longMessage; this.meta = parsedError.meta; } }; /** * Type guard to check if a value is a ClerkAPIError instance. */ const isClerkAPIError = require_clerkRuntimeError.createErrorTypeGuard(ClerkAPIError); //#endregion //#region src/errors/parseError.ts /** * Parses an array of ClerkAPIErrorJSON objects into an array of ClerkAPIError objects. * * @internal */ function parseErrors(data = []) { return data.length > 0 ? data.map((e) => new ClerkAPIError(e)) : []; } /** * Parses a ClerkAPIErrorJSON object into a ClerkAPIError object. * * @deprecated Use `ClerkAPIError` class instead * * @internal */ function parseError(error) { return new ClerkAPIError(error); } /** * Converts a ClerkAPIError object into a ClerkAPIErrorJSON object. * * @internal */ function errorToJSON(error) { return { code: error?.code || "", message: error?.message || "", long_message: error?.longMessage, meta: { param_name: error?.meta?.paramName, session_id: error?.meta?.sessionId, email_addresses: error?.meta?.emailAddresses, identifiers: error?.meta?.identifiers, zxcvbn: error?.meta?.zxcvbn, plan: error?.meta?.plan, is_plan_upgrade_possible: error?.meta?.isPlanUpgradePossible, seats_quantity_to_add: error?.meta?.seatsQuantityToAdd, seats_quantity: error?.meta?.seatsQuantity } }; } //#endregion //#region src/errors/clerkApiResponseError.ts var ClerkAPIResponseError = class ClerkAPIResponseError extends require_clerkRuntimeError.ClerkError { static kind = "ClerkAPIResponseError"; status; clerkTraceId; retryAfter; errors; constructor(message, options) { const { data: errorsJson, status, clerkTraceId, retryAfter } = options; super({ ...options, message, code: "api_response_error" }); Object.setPrototypeOf(this, ClerkAPIResponseError.prototype); this.status = status; this.clerkTraceId = clerkTraceId; this.retryAfter = retryAfter; this.errors = (errorsJson || []).map((e) => new ClerkAPIError(e)); } toString() { let message = `[${this.name}]\nMessage:${this.message}\nStatus:${this.status}\nSerialized errors: ${this.errors.map((e) => JSON.stringify(e))}`; if (this.clerkTraceId) message += `\nClerk Trace ID: ${this.clerkTraceId}`; return message; } static formatMessage(name, msg, _, __) { return msg; } }; /** * Type guard to check if an error is a ClerkAPIResponseError. * Can be called as a standalone function or as a method on an error object. * * @example * // As a standalone function * if (isClerkAPIResponseError(error)) { ... } * * // As a method (when attached to error object) * if (error.isClerkAPIResponseError()) { ... } */ const isClerkAPIResponseError = require_clerkRuntimeError.createErrorTypeGuard(ClerkAPIResponseError); //#endregion //#region src/errors/missingExpiredTokenError.ts /** * Error class representing a missing expired token error from the API. * This error occurs when the server requires an expired token to mint a new session token. * * Use the static `is` method to check if a ClerkAPIResponseError matches this error type. * * @example * ```typescript * if (MissingExpiredTokenError.is(error)) { * // Handle the missing expired token error * } * ``` */ var MissingExpiredTokenError = class MissingExpiredTokenError extends ClerkAPIResponseError { static kind = "MissingExpiredTokenError"; static ERROR_CODE = "missing_expired_token"; static STATUS = 422; /** * Type guard to check if an error is a MissingExpiredTokenError. * This checks the error's properties (status and error code) rather than instanceof, * allowing it to work with ClerkAPIResponseError instances thrown from the API layer. * * @example * ```typescript * try { * await someApiCall(); * } catch (e) { * if (MissingExpiredTokenError.is(e)) { * // e is typed as ClerkAPIResponseError with the specific error properties * } * } * ``` */ static is(err) { return isClerkAPIResponseError(err) && err.status === MissingExpiredTokenError.STATUS && err.errors.length > 0 && err.errors[0].code === MissingExpiredTokenError.ERROR_CODE; } }; //#endregion //#region src/errors/clerkOfflineError.ts /** * Error thrown when a network request fails due to the client being offline. * * This error is thrown instead of returning `null` to make it explicit that * the failure was due to network conditions, not authentication state. * * @example * ```typescript * try { * const token = await session.getToken(); * } catch (error) { * if (ClerkOfflineError.is(error)) { * // Handle offline scenario * showOfflineScreen(); * } * } * ``` */ var ClerkOfflineError = class ClerkOfflineError extends require_clerkRuntimeError.ClerkRuntimeError { static kind = "ClerkOfflineError"; static ERROR_CODE = "clerk_offline"; constructor(message) { super(message, { code: ClerkOfflineError.ERROR_CODE }); Object.setPrototypeOf(this, ClerkOfflineError.prototype); } /** * Type guard to check if an error is a ClerkOfflineError. * This checks both instanceof and the error code to support cross-bundle/cross-realm errors * * @example * ```typescript * try { * const token = await session.getToken(); * } catch (error) { * if (ClerkOfflineError.is(error)) { * // error is typed as ClerkOfflineError * console.log('User is offline'); * } * } * ``` */ static is(error) { if (error === null || error === void 0) return false; return error instanceof ClerkOfflineError || require_clerkRuntimeError.isClerkRuntimeError(error) && error.code === ClerkOfflineError.ERROR_CODE; } }; //#endregion //#region src/errors/errorThrower.ts const DefaultMessages = Object.freeze({ 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}})`, 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}})`, MissingPublishableKeyErrorMessage: `Missing publishableKey. You can get your key at https://dashboard.clerk.com/last-active?path=api-keys.`, MissingSecretKeyErrorMessage: `Missing secretKey. You can get your key at https://dashboard.clerk.com/last-active?path=api-keys.`, MissingClerkProvider: `{{source}} can only be used within the <ClerkProvider /> component. Learn more: https://clerk.com/docs/components/clerk-provider` }); /** * Builds an error thrower. * * @internal */ function buildErrorThrower({ packageName, customMessages }) { let pkg = packageName; /** * Builds a message from a raw message and replacements. * * @internal */ function buildMessage(rawMessage, replacements) { if (!replacements) return `${pkg}: ${rawMessage}`; let msg = rawMessage; const matches = rawMessage.matchAll(/{{([a-zA-Z0-9-_]+)}}/g); for (const match of matches) { const replacement = (replacements[match[1]] || "").toString(); msg = msg.replace(`{{${match[1]}}}`, replacement); } return `${pkg}: ${msg}`; } const messages = { ...DefaultMessages, ...customMessages }; return { setPackageName({ packageName }) { if (typeof packageName === "string") pkg = packageName; return this; }, setMessages({ customMessages }) { Object.assign(messages, customMessages || {}); return this; }, throwInvalidPublishableKeyError(params) { throw new Error(buildMessage(messages.InvalidPublishableKeyErrorMessage, params)); }, throwInvalidProxyUrl(params) { throw new Error(buildMessage(messages.InvalidProxyUrlErrorMessage, params)); }, throwMissingPublishableKeyError() { throw new Error(buildMessage(messages.MissingPublishableKeyErrorMessage)); }, throwMissingSecretKeyError() { throw new Error(buildMessage(messages.MissingSecretKeyErrorMessage)); }, throwMissingClerkProviderError(params) { throw new Error(buildMessage(messages.MissingClerkProvider, params)); }, throw(message) { throw new Error(buildMessage(message)); } }; } //#endregion //#region src/errors/emailLinkError.ts var EmailLinkError = class EmailLinkError extends Error { code; constructor(code) { super(code); this.code = code; this.name = "EmailLinkError"; Object.setPrototypeOf(this, EmailLinkError.prototype); } }; /** * @deprecated Use `EmailLinkErrorCodeStatus` instead. * * @internal */ const EmailLinkErrorCode = { Expired: "expired", Failed: "failed", ClientMismatch: "client_mismatch" }; const EmailLinkErrorCodeStatus = { Expired: "expired", Failed: "failed", ClientMismatch: "client_mismatch" }; //#endregion //#region src/errors/webAuthNError.ts var ClerkWebAuthnError = class extends require_clerkRuntimeError.ClerkRuntimeError { /** * A unique code identifying the error, can be used for localization. */ code; constructor(message, options) { super(message, options); this.code = options.code; } }; //#endregion //#region src/errors/helpers.ts /** * Checks if the provided error object is an unauthorized error. * * @internal * * @deprecated This is no longer used, and will be removed in the next major version. */ function isUnauthorizedError(e) { const status = e?.status; return e?.errors?.[0]?.code === "authentication_invalid" && status === 401; } /** * Checks if the provided error object is a captcha error. * * @internal */ function isCaptchaError(e) { return [ "captcha_invalid", "captcha_not_enabled", "captcha_missing_token" ].includes(e.errors[0].code); } /** * Checks if the provided error is a 4xx error. * * @internal */ function is4xxError(e) { const status = e?.status; return !!status && status >= 400 && status < 500; } /** * Checks if the provided error is a 429 (Too Many Requests) error. * * @internal */ function is429Error(e) { return e?.status === 429; } const unauthenticated403ErrorCodes = new Set(["user_banned", "user_deactivated"]); /** * Checks if the provided error indicates the user's session is no longer valid * and should trigger the unauthenticated flow (e.g. sign-out / redirect to sign-in). * * Only matches explicit authentication failure status codes: * - 401: session is invalid or expired * - 422: invalid session state (e.g. missing_expired_token) * - 403: terminal user state (e.g. user_banned, user_deactivated) * * 404 is intentionally excluded despite being returned for "session not found", * because it's also returned for unrelated resources (org not found, JWT template * not found) and shares the same `resource_not_found` error code, making it * impossible to distinguish. Session-not-found 401s are already handled directly * by Base._fetch. * * @internal */ function isUnauthenticatedError(e) { const status = e?.status; const hasTerminalUserErrorCode = Array.isArray(e?.errors) && e.errors.some((error) => unauthenticated403ErrorCodes.has(error?.code)); return status === 401 || status === 422 || status === 403 && hasTerminalUserErrorCode; } /** * Checks if the provided error is a network error. * * @internal */ function isNetworkError(e) { return (`${e.message}${e.name}` || "").toLowerCase().replace(/\s+/g, "").includes("networkerror"); } /** * Checks if the provided error is either a ClerkAPIResponseError, a ClerkRuntimeError, or a MetamaskError. */ function isKnownError(error) { return isClerkAPIResponseError(error) || isMetamaskError(error) || require_clerkRuntimeError.isClerkRuntimeError(error); } /** * Checks if the provided error is a Clerk runtime error indicating a reverification was cancelled. */ function isReverificationCancelledError(err) { return require_clerkRuntimeError.isClerkRuntimeError(err) && err.code === "reverification_cancelled"; } /** * Checks if the provided error is a Metamask error. */ function isMetamaskError(err) { return "code" in err && [ 4001, 32602, 32603 ].includes(err.code) && "message" in err; } /** * Checks if the provided error is clerk api response error indicating a user is locked. */ function isUserLockedError(err) { return isClerkAPIResponseError(err) && err.errors?.[0]?.code === "user_locked"; } /** * Checks if the provided error is a clerk api response error indicating a password was pwned. * * @internal */ function isPasswordPwnedError(err) { return isClerkAPIResponseError(err) && err.errors?.[0]?.code === "form_password_pwned"; } /** * Checks if the provided error is a clerk api response error indicating a password was compromised. * * @internal */ function isPasswordCompromisedError(err) { return isClerkAPIResponseError(err) && err.errors?.[0]?.code === "form_password_compromised"; } /** * Checks if the provided error is an EmailLinkError. */ function isEmailLinkError(err) { return err.name === "EmailLinkError"; } //#endregion //#region src/errors/globalHookError.ts /** * Creates a ClerkGlobalHookError object from a ClerkError instance. * It's a wrapper for all the different instances of Clerk errors that can * be returned when using Clerk hooks. */ function createClerkGlobalHookError(error) { const predicates = { isClerkAPIResponseError, isClerkRuntimeError: require_clerkRuntimeError.isClerkRuntimeError }; for (const [name, fn] of Object.entries(predicates)) Object.assign(error, { [name]: fn }); return error; } //#endregion Object.defineProperty(exports, 'ClerkAPIError', { enumerable: true, get: function () { return ClerkAPIError; } }); Object.defineProperty(exports, 'ClerkAPIResponseError', { enumerable: true, get: function () { return ClerkAPIResponseError; } }); Object.defineProperty(exports, 'ClerkOfflineError', { enumerable: true, get: function () { return ClerkOfflineError; } }); Object.defineProperty(exports, 'ClerkWebAuthnError', { enumerable: true, get: function () { return ClerkWebAuthnError; } }); Object.defineProperty(exports, 'EmailLinkError', { enumerable: true, get: function () { return EmailLinkError; } }); Object.defineProperty(exports, 'EmailLinkErrorCode', { enumerable: true, get: function () { return EmailLinkErrorCode; } }); Object.defineProperty(exports, 'EmailLinkErrorCodeStatus', { enumerable: true, get: function () { return EmailLinkErrorCodeStatus; } }); Object.defineProperty(exports, 'MissingExpiredTokenError', { enumerable: true, get: function () { return MissingExpiredTokenError; } }); Object.defineProperty(exports, 'buildErrorThrower', { enumerable: true, get: function () { return buildErrorThrower; } }); Object.defineProperty(exports, 'createClerkGlobalHookError', { enumerable: true, get: function () { return createClerkGlobalHookError; } }); Object.defineProperty(exports, 'errorToJSON', { enumerable: true, get: function () { return errorToJSON; } }); Object.defineProperty(exports, 'is429Error', { enumerable: true, get: function () { return is429Error; } }); Object.defineProperty(exports, 'is4xxError', { enumerable: true, get: function () { return is4xxError; } }); Object.defineProperty(exports, 'isCaptchaError', { enumerable: true, get: function () { return isCaptchaError; } }); Object.defineProperty(exports, 'isClerkAPIError', { enumerable: true, get: function () { return isClerkAPIError; } }); Object.defineProperty(exports, 'isClerkAPIResponseError', { enumerable: true, get: function () { return isClerkAPIResponseError; } }); Object.defineProperty(exports, 'isEmailLinkError', { enumerable: true, get: function () { return isEmailLinkError; } }); Object.defineProperty(exports, 'isKnownError', { enumerable: true, get: function () { return isKnownError; } }); Object.defineProperty(exports, 'isMetamaskError', { enumerable: true, get: function () { return isMetamaskError; } }); Object.defineProperty(exports, 'isNetworkError', { enumerable: true, get: function () { return isNetworkError; } }); Object.defineProperty(exports, 'isPasswordCompromisedError', { enumerable: true, get: function () { return isPasswordCompromisedError; } }); Object.defineProperty(exports, 'isPasswordPwnedError', { enumerable: true, get: function () { return isPasswordPwnedError; } }); Object.defineProperty(exports, 'isReverificationCancelledError', { enumerable: true, get: function () { return isReverificationCancelledError; } }); Object.defineProperty(exports, 'isUnauthenticatedError', { enumerable: true, get: function () { return isUnauthenticatedError; } }); Object.defineProperty(exports, 'isUnauthorizedError', { enumerable: true, get: function () { return isUnauthorizedError; } }); Object.defineProperty(exports, 'isUserLockedError', { enumerable: true, get: function () { return isUserLockedError; } }); Object.defineProperty(exports, 'parseError', { enumerable: true, get: function () { return parseError; } }); Object.defineProperty(exports, 'parseErrors', { enumerable: true, get: function () { return parseErrors; } }); //# sourceMappingURL=error-rHNfstgh.js.map