From 2191755ebb0207836ae974b81350c8ef2d031388 Mon Sep 17 00:00:00 2001 From: panteliselef Date: Fri, 21 Feb 2025 13:11:19 +0200 Subject: [PATCH] chore(clerk-js): Split email link types and types for `__clerk_status` (#5200) --- .changeset/witty-penguins-end.md | 2 ++ .../src/ui/common/EmailLinkStatusCard.tsx | 14 ++++++----- .../src/ui/common/EmailLinkVerify.tsx | 23 +++++++++--------- .../clerk-js/src/utils/getClerkQueryParam.ts | 24 ++++++++++--------- 4 files changed, 35 insertions(+), 28 deletions(-) create mode 100644 .changeset/witty-penguins-end.md diff --git a/.changeset/witty-penguins-end.md b/.changeset/witty-penguins-end.md new file mode 100644 index 00000000000..a845151cc84 --- /dev/null +++ b/.changeset/witty-penguins-end.md @@ -0,0 +1,2 @@ +--- +--- diff --git a/packages/clerk-js/src/ui/common/EmailLinkStatusCard.tsx b/packages/clerk-js/src/ui/common/EmailLinkStatusCard.tsx index 9579562e07b..1dbf5282fec 100644 --- a/packages/clerk-js/src/ui/common/EmailLinkStatusCard.tsx +++ b/packages/clerk-js/src/ui/common/EmailLinkStatusCard.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import type { VerificationStatus } from '../../utils/getClerkQueryParam'; +import type { VerifyTokenStatus } from '../../utils/getClerkQueryParam'; import type { LocalizationKey } from '../customizables'; import { Col, descriptors, Flex, Flow, Icon, localizationKeys, Spinner, Text } from '../customizables'; import { Card, Header } from '../elements'; @@ -9,13 +9,15 @@ import { ExclamationTriangle, SwitchArrows, TickShield } from '../icons'; import type { InternalTheme } from '../styledSystem'; import { animations } from '../styledSystem'; +export type EmailLinkUIStatus = VerifyTokenStatus | 'verified_switch_tab' | 'loading'; + type EmailLinkStatusCardProps = React.PropsWithChildren<{ title: LocalizationKey; subtitle: LocalizationKey; - status: VerificationStatus; + status: EmailLinkUIStatus; }>; -const StatusToIcon: Record, React.ComponentType> = { +const StatusToIcon: Record, React.ComponentType> = { verified: TickShield, verified_switch_tab: SwitchArrows, expired: ExclamationTriangle, @@ -23,7 +25,7 @@ const StatusToIcon: Record, React.Compone client_mismatch: ExclamationTriangle, }; -const statusToColor = (theme: InternalTheme, status: Exclude) => +const statusToColor = (theme: InternalTheme, status: Exclude) => ({ verified: theme.colors.$success500, verified_switch_tab: theme.colors.$primary500, @@ -53,7 +55,7 @@ export const EmailLinkStatusCard = (props: EmailLinkStatusCardProps) => { ); }; -const StatusRow = (props: { status: VerificationStatus }) => { +const StatusRow = (props: { status: EmailLinkUIStatus }) => { return ( { ); }; -const StatusIcon = (props: { status: Exclude }) => { +const StatusIcon = (props: { status: Exclude }) => { const { status } = props; return ( diff --git a/packages/clerk-js/src/ui/common/EmailLinkVerify.tsx b/packages/clerk-js/src/ui/common/EmailLinkVerify.tsx index b4f1edf9fb5..6915bc49a59 100644 --- a/packages/clerk-js/src/ui/common/EmailLinkVerify.tsx +++ b/packages/clerk-js/src/ui/common/EmailLinkVerify.tsx @@ -2,12 +2,12 @@ import { EmailLinkErrorCodeStatus, isEmailLinkError } from '@clerk/shared/error' import { useClerk } from '@clerk/shared/react'; import React from 'react'; -import type { VerificationStatus } from '../../utils'; import { completeSignUpFlow } from '../../utils'; import { useCoreSignUp } from '../contexts'; import type { LocalizationKey } from '../localization'; import { useRouter } from '../router'; import { sleep } from '../utils'; +import type { EmailLinkUIStatus } from './EmailLinkStatusCard'; import { EmailLinkStatusCard } from './EmailLinkStatusCard'; export type EmailLinkVerifyProps = { @@ -16,7 +16,7 @@ export type EmailLinkVerifyProps = { verifyEmailPath?: string; verifyPhonePath?: string; continuePath?: string; - texts: Record; + texts: Record; }; export const EmailLinkVerify = (props: EmailLinkVerifyProps) => { @@ -24,7 +24,7 @@ export const EmailLinkVerify = (props: EmailLinkVerifyProps) => { const { handleEmailLinkVerification } = useClerk(); const { navigate } = useRouter(); const signUp = useCoreSignUp(); - const [verificationStatus, setVerificationStatus] = React.useState('loading'); + const [verificationStatus, setVerificationStatus] = React.useState('loading'); const startVerification = async () => { try { @@ -33,7 +33,7 @@ export const EmailLinkVerify = (props: EmailLinkVerifyProps) => { await handleEmailLinkVerification({ redirectUrlComplete, redirectUrl }, navigate); setVerificationStatus('verified_switch_tab'); await sleep(750); - return completeSignUpFlow({ + await completeSignUpFlow({ signUp, verifyEmailPath, verifyPhonePath, @@ -41,14 +41,15 @@ export const EmailLinkVerify = (props: EmailLinkVerifyProps) => { navigate, }); } catch (err) { - let status: VerificationStatus = 'failed'; - if (isEmailLinkError(err) && err.code === EmailLinkErrorCodeStatus.Expired) { - status = 'expired'; + if ( + isEmailLinkError(err) && + (err.code === EmailLinkErrorCodeStatus.Expired || err.code === EmailLinkErrorCodeStatus.ClientMismatch) + ) { + setVerificationStatus(err.code); + return; } - if (isEmailLinkError(err) && err.code === EmailLinkErrorCodeStatus.ClientMismatch) { - status = 'client_mismatch'; - } - setVerificationStatus(status); + + setVerificationStatus(EmailLinkErrorCodeStatus.Failed); } }; diff --git a/packages/clerk-js/src/utils/getClerkQueryParam.ts b/packages/clerk-js/src/utils/getClerkQueryParam.ts index 6dc99098368..0eddb5025d2 100644 --- a/packages/clerk-js/src/utils/getClerkQueryParam.ts +++ b/packages/clerk-js/src/utils/getClerkQueryParam.ts @@ -1,3 +1,5 @@ +import type { EmailLinkErrorCodeStatus } from '@clerk/shared/error'; + import { CLERK_SATELLITE_URL, CLERK_SUFFIXED_COOKIES, CLERK_SYNCED } from '../core/constants'; const _ClerkQueryParams = [ @@ -15,19 +17,19 @@ const _ClerkQueryParams = [ type ClerkQueryParam = (typeof _ClerkQueryParams)[number]; -type ClerkQueryParamsToValuesMap = { - __clerk_status: VerificationStatus | TicketStatus; -} & Record<(typeof _ClerkQueryParams)[number], string>; +/** + * Used for email link verification + */ +export type VerifyTokenStatus = 'verified' | (typeof EmailLinkErrorCodeStatus)[keyof typeof EmailLinkErrorCodeStatus]; -export type VerificationStatus = - | 'expired' - | 'failed' - | 'loading' - | 'verified' - | 'verified_switch_tab' - | 'client_mismatch'; +/** + * Used for instance invitations and organization invitations + */ +type TicketStatus = 'sign_in' | 'sign_up' | 'complete'; -type TicketStatus = 'sign_in' | 'sign_up'; +type ClerkQueryParamsToValuesMap = { + __clerk_status: TicketStatus | VerifyTokenStatus; +} & Record<(typeof _ClerkQueryParams)[number], string>; export function getClerkQueryParam(param: T): ClerkQueryParamsToValuesMap[T] | null { const val = new URL(window.location.href).searchParams.get(param);