diff --git a/.changeset/warm-steaks-count.md b/.changeset/warm-steaks-count.md new file mode 100644 index 00000000000..e93dc1b6137 --- /dev/null +++ b/.changeset/warm-steaks-count.md @@ -0,0 +1,5 @@ +--- +'@clerk/backend': minor +--- + +Export missing Billing types diff --git a/packages/backend/src/index.ts b/packages/backend/src/index.ts index e8215708399..4a65fe0096b 100644 --- a/packages/backend/src/index.ts +++ b/packages/backend/src/index.ts @@ -100,9 +100,13 @@ export type { PaginatedResponseJSON, TestingTokenJSON, WebhooksSvixJSON, + BillingPayerJSON, BillingPlanJSON, BillingSubscriptionJSON, BillingSubscriptionItemJSON, + BillingPaymentAttemptWebhookEventJSON, + BillingSubscriptionItemWebhookEventJSON, + BillingSubscriptionWebhookEventJSON, } from './api/resources/JSON'; /** diff --git a/packages/clerk-js/src/core/resources/SignIn.ts b/packages/clerk-js/src/core/resources/SignIn.ts index cb7832dbb90..8ff288a3e1a 100644 --- a/packages/clerk-js/src/core/resources/SignIn.ts +++ b/packages/clerk-js/src/core/resources/SignIn.ts @@ -1,6 +1,24 @@ import { inBrowser } from '@clerk/shared/browser'; import { ClerkWebAuthnError } from '@clerk/shared/error'; import { Poller } from '@clerk/shared/poller'; +import type { + SignInFutureBackupCodeVerifyParams, + SignInFutureCreateParams, + SignInFutureEmailCodeSendParams, + SignInFutureEmailCodeVerifyParams, + SignInFutureEmailLinkSendParams, + SignInFutureFinalizeParams, + SignInFutureMFAPhoneCodeVerifyParams, + SignInFuturePasswordParams, + SignInFuturePhoneCodeSendParams, + SignInFuturePhoneCodeVerifyParams, + SignInFutureResetPasswordSubmitParams, + SignInFutureResource, + SignInFutureSSOParams, + SignInFutureTicketParams, + SignInFutureTOTPVerifyParams, + SignInFutureWeb3Params, +} from '@clerk/shared/types'; import { deepCamelToSnake, deepSnakeToCamel } from '@clerk/shared/underscore'; import { isWebAuthnAutofillSupported as isWebAuthnAutofillSupportedOnWindow, @@ -31,22 +49,6 @@ import type { SamlConfig, SignInCreateParams, SignInFirstFactor, - SignInFutureBackupCodeVerifyParams, - SignInFutureCreateParams, - SignInFutureEmailCodeSendParams, - SignInFutureEmailCodeVerifyParams, - SignInFutureEmailLinkSendParams, - SignInFutureFinalizeParams, - SignInFutureMFAPhoneCodeVerifyParams, - SignInFuturePasswordParams, - SignInFuturePhoneCodeSendParams, - SignInFuturePhoneCodeVerifyParams, - SignInFutureResetPasswordSubmitParams, - SignInFutureResource, - SignInFutureSSOParams, - SignInFutureTicketParams, - SignInFutureTOTPVerifyParams, - SignInFutureWeb3Params, SignInIdentifier, SignInJSON, SignInJSONSnapshot, diff --git a/packages/clerk-js/src/core/signals.ts b/packages/clerk-js/src/core/signals.ts index 815cfb7acff..85dbae75ef2 100644 --- a/packages/clerk-js/src/core/signals.ts +++ b/packages/clerk-js/src/core/signals.ts @@ -1,6 +1,7 @@ import { isClerkAPIResponseError } from '@clerk/shared/error'; +import { createClerkGlobalHookError } from '@clerk/shared/experimental-error'; +import type { Errors, SignInSignal, SignUpSignal } from '@clerk/shared/types'; import { snakeToCamel } from '@clerk/shared/underscore'; -import type { Errors, SignInSignal, SignUpSignal } from '@clerk/types'; import { computed, signal } from 'alien-signals'; import type { SignIn } from './resources/SignIn'; @@ -62,7 +63,7 @@ function errorsToParsedErrors(error: unknown): Errors { if (!isClerkAPIResponseError(error)) { parsedErrors.raw = [error]; - parsedErrors.global = [error]; + parsedErrors.global = [createClerkGlobalHookError(error)]; return parsedErrors; } @@ -80,9 +81,9 @@ function errorsToParsedErrors(error: unknown): Errors { } if (parsedErrors.global) { - parsedErrors.global.push(error); + parsedErrors.global.push(createClerkGlobalHookError(error)); } else { - parsedErrors.global = [error]; + parsedErrors.global = [createClerkGlobalHookError(error)]; } }); diff --git a/packages/clerk-js/src/core/state.ts b/packages/clerk-js/src/core/state.ts index 5746ed17d98..82fed3485ac 100644 --- a/packages/clerk-js/src/core/state.ts +++ b/packages/clerk-js/src/core/state.ts @@ -1,4 +1,4 @@ -import type { State as StateInterface } from '@clerk/types'; +import type { State as StateInterface } from '@clerk/shared/types'; import { computed, effect } from 'alien-signals'; import { eventBus } from './events'; diff --git a/packages/react/src/hooks/useClerkSignal.ts b/packages/react/src/hooks/useClerkSignal.ts index 3be64283c53..0dae7d8c563 100644 --- a/packages/react/src/hooks/useClerkSignal.ts +++ b/packages/react/src/hooks/useClerkSignal.ts @@ -1,4 +1,4 @@ -import type { SignInSignalValue, SignUpSignalValue } from '@clerk/types'; +import type { SignInSignalValue, SignUpSignalValue } from '@clerk/shared/types'; import { useCallback, useSyncExternalStore } from 'react'; import { useIsomorphicClerkContext } from '../contexts/IsomorphicClerkContext'; diff --git a/packages/shared/package.json b/packages/shared/package.json index ae12bc4087b..67addd7654e 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -70,6 +70,24 @@ "default": "./dist/dom/index.js" } }, + "./experimental-error": { + "import": { + "types": "./dist/experimental-error/index.d.mts", + "default": "./dist/experimental-error/index.mjs" + }, + "require": { + "types": "./dist/experimental-error/index.d.ts", + "default": "./dist/experimental-error/index.js" + } + }, + "./types": { + "import": { + "types": "./dist/types/index.d.mts" + }, + "require": { + "types": "./dist/types/index.d.ts" + } + }, "./package.json": "./package.json" }, "main": "./dist/index.js", @@ -87,6 +105,7 @@ "deriveState", "dom", "error", + "experimental-error", "file", "globs", "handleValueOrFn", @@ -123,7 +142,8 @@ "eventBus", "netlifyCacheHandler", "clerkEventBus", - "phoneCodeChannel" + "phoneCodeChannel", + "types" ], "scripts": { "build": "tsup", diff --git a/packages/shared/src/errors/apiResponseError.ts b/packages/shared/src/errors/apiResponseError.ts index e3541649735..e60d15b7cc5 100644 --- a/packages/shared/src/errors/apiResponseError.ts +++ b/packages/shared/src/errors/apiResponseError.ts @@ -6,7 +6,7 @@ import type { import { parseErrors } from './parseError'; -interface ClerkAPIResponseOptions { +export interface ClerkAPIResponseOptions { data: ClerkAPIErrorJSON[]; status: number; clerkTraceId?: string; diff --git a/packages/shared/src/errors/parseError.ts b/packages/shared/src/errors/parseError.ts index ee343bbbb5a..9191c58683c 100644 --- a/packages/shared/src/errors/parseError.ts +++ b/packages/shared/src/errors/parseError.ts @@ -19,6 +19,7 @@ export function parseError(error: ClerkAPIErrorJSON): ClerkAPIError { code: error.code, message: error.message, longMessage: error.long_message, + clerkTraceId: error.clerk_trace_id, meta: { paramName: error?.meta?.param_name, sessionId: error?.meta?.session_id, diff --git a/packages/shared/src/experimental-error/clerkApiError.ts b/packages/shared/src/experimental-error/clerkApiError.ts new file mode 100644 index 00000000000..261ebf192a9 --- /dev/null +++ b/packages/shared/src/experimental-error/clerkApiError.ts @@ -0,0 +1,31 @@ +import type { ClerkAPIErrorJSON } from '@clerk/types'; + +import { parseError } from '../errors/parseError'; + +export type ClerkApiErrorMeta = Record | undefined; + +/** + * This error contains the specific error message, code, and any additional metadata that was returned by the Clerk API. + */ +export class ClerkApiError { + readonly name = 'ClerkApiError'; + readonly code: string; + readonly message: string; + readonly longMessage: string | undefined; + readonly meta: Meta; + + constructor(json: ClerkAPIErrorJSON) { + const parsedError = parseError(json); + this.code = parsedError.code; + this.message = parsedError.message; + this.longMessage = parsedError.longMessage; + this.meta = json.meta as Meta; + } +} + +/** + * Type guard to check if a value is a ClerkApiError instance. + */ +export function isClerkApiError(error: Error): error is ClerkApiError { + return error instanceof ClerkApiError; +} diff --git a/packages/shared/src/experimental-error/clerkApiErrorResponse.ts b/packages/shared/src/experimental-error/clerkApiErrorResponse.ts new file mode 100644 index 00000000000..2aa9b5f8e42 --- /dev/null +++ b/packages/shared/src/experimental-error/clerkApiErrorResponse.ts @@ -0,0 +1,50 @@ +/* eslint-disable jsdoc/require-jsdoc */ +import type { ClerkApiErrorResponseJSON } from '@clerk/types'; + +import { ClerkApiError } from './clerkApiError'; +import { ClerkError } from './clerkError'; + +type ClerkApiResponseErrorParams = ClerkApiErrorResponseJSON & { + retryAfter?: number; +}; + +/** + * A ClerkError subclass that represents the shell response of a Clerk API error. + * This error contains an array of ClerkApiError instances, each representing a specific error that occurred. + */ +export class ClerkApiResponseError extends ClerkError { + readonly name = 'ClerkApiResponseError'; + readonly retryAfter?: number; + readonly errors: E[]; + readonly clerkTraceId: string | undefined; + + constructor(data: ClerkApiResponseErrorParams) { + const errorMesages = data.errors.map(e => e.message).join(', '); + const message = `Api errors occurred: ${errorMesages}. Check the \`errors\` property for more details about the specific errors.`; + super({ message, code: 'clerk_api_error' }); + this.errors = data.errors.map(e => new ClerkApiError(e)) as E[]; + this.clerkTraceId = data.clerk_trace_id; + this.retryAfter = data.retryAfter; + } +} + +/** + * 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()) { ... } + */ +export function isClerkApiResponseError(error: Error): error is ClerkApiResponseError; +export function isClerkApiResponseError(this: Error): this is ClerkApiResponseError; +export function isClerkApiResponseError(this: Error | void, error?: Error): error is ClerkApiResponseError { + const target = error ?? this; + if (!target) { + throw new TypeError('isClerkApiResponseError requires an error object'); + } + return target instanceof ClerkApiResponseError; +} diff --git a/packages/shared/src/experimental-error/clerkApiErrors.ts b/packages/shared/src/experimental-error/clerkApiErrors.ts new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/shared/src/experimental-error/clerkError.ts b/packages/shared/src/experimental-error/clerkError.ts new file mode 100644 index 00000000000..761c8d58e3d --- /dev/null +++ b/packages/shared/src/experimental-error/clerkError.ts @@ -0,0 +1,64 @@ +export interface ClerkErrorParams { + /** + * A message that describes the error. This is typically intented to be showed to the developers. + * It should not be shown to the user or parsed directly as the message contents are not guaranteed + * to be stable - use the `code` property instead. + */ + message: string; + /** + * A machine-stable code that identifies the error. + */ + code: string; + /** + * A user-friendly message that describes the error and can be displayed to the user. + * This message defaults to English but can be usually translated to the user's language + * by matching the `code` property to a localized message. + */ + longMessage?: string; + /** + * The cause of the error, typically an `Error` instance that was caught and wrapped by the Clerk error handler. + */ + cause?: Error; + /** + * A URL to the documentation for the error. + */ + docsUrl?: string; +} + +/** + * A temporary placeholder, this will eventually be replaced with a + * build-time flag that will actually perform DCE. + */ +const __DEV__ = true; + +export class ClerkError extends Error { + readonly clerkError = true as const; + readonly name: string = 'ClerkError'; + readonly code: string; + readonly longMessage: string | undefined; + readonly docsUrl: string | undefined; + readonly cause: Error | undefined; + + constructor(opts: ClerkErrorParams) { + const formatMessage = (msg: string, code: string, docsUrl: string | undefined) => { + msg = `${this.name}: ${msg.trim()}\n\n(code="${code}")\n\n`; + if (__DEV__) { + msg += `\n\nDocs: ${docsUrl}`; + } + return msg; + }; + + super(formatMessage(opts.message, opts.code, opts.docsUrl), { cause: opts.cause }); + Object.setPrototypeOf(this, ClerkError.prototype); + + this.code = opts.code; + this.docsUrl = opts.docsUrl; + } +} + +/** + * Type guard to check if a value is a ClerkError instance. + */ +export function isClerkError(val: unknown): val is ClerkError { + return !!val && typeof val === 'object' && 'clerkError' in val && val.clerkError === true; +} diff --git a/packages/shared/src/experimental-error/clerkRuntimeError.ts b/packages/shared/src/experimental-error/clerkRuntimeError.ts new file mode 100644 index 00000000000..317f9127332 --- /dev/null +++ b/packages/shared/src/experimental-error/clerkRuntimeError.ts @@ -0,0 +1,32 @@ +/* eslint-disable jsdoc/require-jsdoc */ +import type { ClerkErrorParams } from './clerkError'; +import { ClerkError } from './clerkError'; + +export class ClerkRuntimeError extends ClerkError { + readonly name = 'ClerkRuntimeError'; + + constructor(params: ClerkErrorParams) { + super(params); + } +} + +/** + * Type guard to check if an error is a ClerkRuntimeError. + * Can be called as a standalone function or as a method on an error object. + * + * @example + * // As a standalone function + * if (isClerkRuntimeError(error)) { ... } + * + * // As a method (when attached to error object) + * if (error.isClerkRuntimeError()) { ... } + */ +export function isClerkRuntimeError(error: Error): error is ClerkRuntimeError; +export function isClerkRuntimeError(this: Error): this is ClerkRuntimeError; +export function isClerkRuntimeError(this: Error | void, error?: Error): error is ClerkRuntimeError { + const target = error ?? this; + if (!target) { + throw new TypeError('isClerkRuntimeError requires an error object'); + } + return target instanceof ClerkRuntimeError; +} diff --git a/packages/shared/src/experimental-error/globalHookError.ts b/packages/shared/src/experimental-error/globalHookError.ts new file mode 100644 index 00000000000..825bd464059 --- /dev/null +++ b/packages/shared/src/experimental-error/globalHookError.ts @@ -0,0 +1,23 @@ +import { isClerkApiResponseError } from './clerkApiErrorResponse'; +import type { ClerkError } from './clerkError'; +import { isClerkRuntimeError } from './clerkRuntimeError'; + +/** + * 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. + */ +export function createClerkGlobalHookError(error: ClerkError) { + const predicates = { + isClerkApiResponseError, + isClerkRuntimeError, + } as const; + + for (const [name, fn] of Object.entries(predicates)) { + Object.assign(error, { [name]: fn }); + } + + return error as ClerkError & typeof predicates; +} + +export type ClerkGlobalHookError = ReturnType; diff --git a/packages/shared/src/experimental-error/index.ts b/packages/shared/src/experimental-error/index.ts new file mode 100644 index 00000000000..71da1d6701d --- /dev/null +++ b/packages/shared/src/experimental-error/index.ts @@ -0,0 +1,7 @@ +export { ClerkApiError, isClerkApiError } from './clerkApiError'; +export type { ClerkApiErrorMeta } from './clerkApiError'; +export { ClerkApiResponseError, isClerkApiResponseError } from './clerkApiErrorResponse'; +export { ClerkError, isClerkError, type ClerkErrorParams } from './clerkError'; +export { ClerkRuntimeError, isClerkRuntimeError } from './clerkRuntimeError'; +export { createClerkGlobalHookError } from './globalHookError'; +export type { ClerkGlobalHookError } from './globalHookError'; diff --git a/packages/shared/src/types/index.ts b/packages/shared/src/types/index.ts new file mode 100644 index 00000000000..dd385989ef4 --- /dev/null +++ b/packages/shared/src/types/index.ts @@ -0,0 +1,31 @@ +export type { + Errors, + FieldError, + FieldErrors, + NullableSignInSignal, + NullableSignUpSignal, + SignInSignal, + SignInSignalValue, + SignUpSignal, + SignUpSignalValue, + State, +} from './state'; + +export type { + SignInFutureBackupCodeVerifyParams, + SignInFutureCreateParams, + SignInFutureEmailCodeSendParams, + SignInFutureEmailCodeVerifyParams, + SignInFutureEmailLinkSendParams, + SignInFutureFinalizeParams, + SignInFutureMFAPhoneCodeVerifyParams, + SignInFuturePasswordParams, + SignInFuturePhoneCodeSendParams, + SignInFuturePhoneCodeVerifyParams, + SignInFutureResetPasswordSubmitParams, + SignInFutureResource, + SignInFutureSSOParams, + SignInFutureTicketParams, + SignInFutureTOTPVerifyParams, + SignInFutureWeb3Params, +} from './signInResource'; diff --git a/packages/types/src/signInFuture.ts b/packages/shared/src/types/signInResource.ts similarity index 94% rename from packages/types/src/signInFuture.ts rename to packages/shared/src/types/signInResource.ts index 90d76506880..e02e06ababb 100644 --- a/packages/types/src/signInFuture.ts +++ b/packages/shared/src/types/signInResource.ts @@ -1,8 +1,14 @@ -import type { SetActiveNavigate } from './clerk'; -import type { PhoneCodeChannel } from './phoneCodeChannel'; -import type { SignInFirstFactor, SignInSecondFactor, SignInStatus, UserData } from './signInCommon'; -import type { OAuthStrategy, Web3Strategy } from './strategies'; -import type { VerificationResource } from './verification'; +import type { + OAuthStrategy, + PhoneCodeChannel, + SetActiveNavigate, + SignInFirstFactor, + SignInSecondFactor, + SignInStatus, + UserData, + VerificationResource, + Web3Strategy, +} from '@clerk/types'; export interface SignInFutureCreateParams { identifier?: string; @@ -123,9 +129,6 @@ export interface SignInFutureFinalizeParams { navigate?: SetActiveNavigate; } -/** - * The current active `SignIn` instance, for use in custom flows. - */ export interface SignInFutureResource { /** * The unique identifier for the current sign-in attempt. diff --git a/packages/types/src/state.ts b/packages/shared/src/types/state.ts similarity index 91% rename from packages/types/src/state.ts rename to packages/shared/src/types/state.ts index 4438d92fe57..da8ff241c57 100644 --- a/packages/types/src/state.ts +++ b/packages/shared/src/types/state.ts @@ -1,5 +1,7 @@ -import type { SignInFutureResource } from './signInFuture'; -import type { SignUpFutureResource } from './signUpFuture'; +import type { SignUpFutureResource } from '@clerk/types'; + +import type { ClerkGlobalHookError } from '../experimental-error'; +import type { SignInFutureResource } from './signInResource'; /** * Represents an error on a specific field. @@ -80,7 +82,7 @@ export interface Errors { /** * Parsed errors that are not related to any specific field. */ - global: unknown[] | null; // does not include any errors that could be parsed as a field error + global: ClerkGlobalHookError[] | null; // does not include any errors that could be parsed as a field error } /** @@ -143,7 +145,6 @@ export interface State { * An alias for `effect()` from `alien-signals`, which can be used to subscribe to changes from Signals. * * @see https://github.com/stackblitz/alien-signals#usage - * @experimental This experimental API is subject to change. */ __internal_effect: (callback: () => void) => () => void; @@ -152,7 +153,6 @@ export interface State { * its dependencies change. * * @see https://github.com/stackblitz/alien-signals#usage - * @experimental This experimental API is subject to change. */ __internal_computed: (getter: (previousValue?: T) => T) => () => T; } diff --git a/packages/shared/subpaths.mjs b/packages/shared/subpaths.mjs index da0b2fe9664..9327c9bc1ae 100644 --- a/packages/shared/subpaths.mjs +++ b/packages/shared/subpaths.mjs @@ -7,7 +7,7 @@ import packageJson from './package.json' with { type: 'json' }; * When you add an entry to the package.json "files" field, a subfolder will be automatically created with a package.json pointing to that file */ -export const subpathFoldersBarrel = ['react', 'utils', 'workerTimers', 'dom']; +export const subpathFoldersBarrel = ['react', 'utils', 'workerTimers', 'dom', 'experimental-error', 'types']; export const subpathNames = packageJson.files.filter(k => !['dist', 'scripts', ...subpathFoldersBarrel].includes(k)); diff --git a/packages/shared/tsup.config.ts b/packages/shared/tsup.config.ts index 9d5b8e121c9..6aee96362a2 100644 --- a/packages/shared/tsup.config.ts +++ b/packages/shared/tsup.config.ts @@ -16,6 +16,8 @@ export default defineConfig(overrideOptions => { './src/utils/index.ts', './src/workerTimers/index.ts', './src/dom/*.ts', + './src/experimental-error/index.ts', + './src/types/index.ts', '!./src/**/*.test.{ts,tsx}', ], format: ['cjs', 'esm'], diff --git a/packages/types/src/clerk.ts b/packages/types/src/clerk.ts index 5140c03f27a..675eb275a31 100644 --- a/packages/types/src/clerk.ts +++ b/packages/types/src/clerk.ts @@ -1,4 +1,3 @@ -import type { ClerkAPIResponseError } from './api'; import type { APIKeysNamespace } from './apiKeys'; import type { APIKeysTheme, @@ -32,6 +31,7 @@ import type { import type { ClientResource } from './client'; import type { CustomMenuItem } from './customMenuItems'; import type { CustomPage } from './customPages'; +import type { ClerkAPIResponseError } from './errors'; import type { InstanceType } from './instance'; import type { DisplayThemeJSON } from './json'; import type { LocalizationResource } from './localization'; @@ -55,7 +55,6 @@ import type { SessionVerificationLevel } from './sessionVerification'; import type { SignInResource } from './signIn'; import type { SignUpResource } from './signUp'; import type { ClientJSONSnapshot, EnvironmentJSONSnapshot } from './snapshots'; -import type { State } from './state'; import type { Web3Strategy } from './strategies'; import type { TelemetryCollector } from './telemetry'; import type { UserResource } from './user'; @@ -236,7 +235,7 @@ export interface Clerk { * * @experimental This experimental API is subject to change. */ - __internal_state: State; + __internal_state: any; /** * @experimental This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. It is advised to [pin](https://clerk.com/docs/pinning) the SDK version and the clerk-js version to avoid breaking changes. diff --git a/packages/types/src/api.ts b/packages/types/src/errors.ts similarity index 56% rename from packages/types/src/api.ts rename to packages/types/src/errors.ts index bd1c3cfc3c7..37a1199be99 100644 --- a/packages/types/src/api.ts +++ b/packages/types/src/errors.ts @@ -1,3 +1,58 @@ +import type { ClientJSON } from './json'; + +// TODO: @nikos move this to shared +export interface ClerkApiErrorResponseJSON { + errors: ClerkAPIErrorJSON[]; + clerk_trace_id?: string; + meta?: { client?: ClientJSON }; +} + +// TODO: @nikos move this to shared +export interface ClerkAPIErrorJSON { + code: string; + message: string; + long_message?: string; + clerk_trace_id?: string; + meta?: { + param_name?: string; + session_id?: string; + email_addresses?: string[]; + identifiers?: string[]; + zxcvbn?: { + suggestions: { + code: string; + message: string; + }[]; + }; + plan?: { + amount_formatted: string; + annual_monthly_amount_formatted: string; + currency_symbol: string; + id: string; + name: string; + }; + is_plan_upgrade_possible?: boolean; + }; +} + +export interface ClerkRuntimeError { + code: string; + message: string; +} + +/** + * TODO: @nikos + * Interface representing a Clerk API Response Error. + */ +export interface ClerkAPIResponseError extends Error { + clerkError: true; + status: number; + message: string; + clerkTraceId?: string; + retryAfter?: number; + errors: ClerkAPIError[]; +} + /** * An interface that represents an error returned by the Clerk API. */ @@ -14,6 +69,10 @@ export interface ClerkAPIError { * A more detailed message that describes the error. */ longMessage?: string; + /** + * A trace ID that can be used to identify the error in the Clerk API logs. + */ + clerkTraceId?: string; /** * Additional information about the error. */ @@ -39,20 +98,3 @@ export interface ClerkAPIError { isPlanUpgradePossible?: boolean; }; } - -export interface ClerkRuntimeError { - code: string; - message: string; -} - -/** - * Interface representing a Clerk API Response Error. - */ -export interface ClerkAPIResponseError extends Error { - clerkError: true; - status: number; - message: string; - clerkTraceId?: string; - retryAfter?: number; - errors: ClerkAPIError[]; -} diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index b0f51eec6fc..0b52030e740 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -1,4 +1,3 @@ -export * from './api'; export * from './apiKeys'; export * from './apiKeysSettings'; export * from './appearance'; @@ -53,6 +52,7 @@ export * from './router'; /** * TODO @revamp-hooks: Drop this in the next major release. */ +export * from './errors'; export * from './runtime-values'; export * from './saml'; export * from './samlAccount'; @@ -61,13 +61,11 @@ export * from './session'; export * from './sessionVerification'; export * from './signIn'; export * from './signInCommon'; -export * from './signInFuture'; export * from './signUp'; export * from './signUpCommon'; export * from './signUpFuture'; export * from './snapshots'; export * from './ssr'; -export * from './state'; export * from './strategies'; export * from './telemetry'; export * from './theme'; diff --git a/packages/types/src/json.ts b/packages/types/src/json.ts index c3ba98e95ab..4a71431fb0a 100644 --- a/packages/types/src/json.ts +++ b/packages/types/src/json.ts @@ -15,6 +15,7 @@ import type { import type { CommerceSettingsJSON } from './commerceSettings'; import type { DisplayConfigJSON } from './displayConfig'; import type { EnterpriseProtocol, EnterpriseProvider } from './enterpriseAccount'; +import type { ClerkAPIErrorJSON } from './errors'; import type { EmailAddressIdentifier, UsernameIdentifier } from './identifiers'; import type { ActClaim } from './jwtv2'; import type { OAuthProvider } from './oauth'; @@ -373,32 +374,6 @@ export interface SignUpVerificationJSON extends VerificationJSON { channel?: PhoneCodeChannel; } -export interface ClerkAPIErrorJSON { - code: string; - message: string; - long_message?: string; - meta?: { - param_name?: string; - session_id?: string; - email_addresses?: string[]; - identifiers?: string[]; - zxcvbn?: { - suggestions: { - code: string; - message: string; - }[]; - }; - plan?: { - amount_formatted: string; - annual_monthly_amount_formatted: string; - currency_symbol: string; - id: string; - name: string; - }; - is_plan_upgrade_possible?: boolean; - }; -} - export interface TokenJSON extends ClerkResourceJSON { object: 'token'; jwt: string; diff --git a/packages/types/src/signIn.ts b/packages/types/src/signIn.ts index 6ffa69aa1fd..56ce7e7b8fd 100644 --- a/packages/types/src/signIn.ts +++ b/packages/types/src/signIn.ts @@ -23,7 +23,6 @@ import type { SignInStatus, UserData, } from './signInCommon'; -import type { SignInFutureResource } from './signInFuture'; import type { SignInJSONSnapshot } from './snapshots'; import type { CreateEmailLinkFlowReturn, VerificationResource } from './verification'; import type { AuthenticateWithWeb3Params } from './web3Wallet'; @@ -87,7 +86,7 @@ export interface SignInResource extends ClerkResource { /** * @internal */ - __internal_future: SignInFutureResource; + __internal_future: any; } export interface SignInJSON extends ClerkResourceJSON { diff --git a/packages/types/src/verification.ts b/packages/types/src/verification.ts index 2577bbf1b47..4f1d3fe0863 100644 --- a/packages/types/src/verification.ts +++ b/packages/types/src/verification.ts @@ -1,4 +1,4 @@ -import type { ClerkAPIError } from './api'; +import type { ClerkAPIError } from './errors'; import type { PublicKeyCredentialCreationOptionsWithoutExtensions } from './passkey'; import type { PhoneCodeChannel } from './phoneCodeChannel'; import type { ClerkResource } from './resource';