Skip to content

Commit

Permalink
chore(clerk-js): Split email link types and types for __clerk_status (
Browse files Browse the repository at this point in the history
  • Loading branch information
panteliselef authored Feb 21, 2025
1 parent 3345667 commit 2191755
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 28 deletions.
2 changes: 2 additions & 0 deletions .changeset/witty-penguins-end.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
---
14 changes: 8 additions & 6 deletions packages/clerk-js/src/ui/common/EmailLinkStatusCard.tsx
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -9,21 +9,23 @@ 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<Exclude<VerificationStatus, 'loading'>, React.ComponentType> = {
const StatusToIcon: Record<Exclude<EmailLinkUIStatus, 'loading'>, React.ComponentType> = {
verified: TickShield,
verified_switch_tab: SwitchArrows,
expired: ExclamationTriangle,
failed: ExclamationTriangle,
client_mismatch: ExclamationTriangle,
};

const statusToColor = (theme: InternalTheme, status: Exclude<VerificationStatus, 'loading'>) =>
const statusToColor = (theme: InternalTheme, status: Exclude<EmailLinkUIStatus, 'loading'>) =>
({
verified: theme.colors.$success500,
verified_switch_tab: theme.colors.$primary500,
Expand Down Expand Up @@ -53,7 +55,7 @@ export const EmailLinkStatusCard = (props: EmailLinkStatusCardProps) => {
);
};

const StatusRow = (props: { status: VerificationStatus }) => {
const StatusRow = (props: { status: EmailLinkUIStatus }) => {
return (
<Flex
elementDescriptor={descriptors.verificationLinkStatusBox}
Expand Down Expand Up @@ -82,7 +84,7 @@ const StatusRow = (props: { status: VerificationStatus }) => {
);
};

const StatusIcon = (props: { status: Exclude<VerificationStatus, 'loading'> }) => {
const StatusIcon = (props: { status: Exclude<EmailLinkUIStatus, 'loading'> }) => {
const { status } = props;

return (
Expand Down
23 changes: 12 additions & 11 deletions packages/clerk-js/src/ui/common/EmailLinkVerify.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand All @@ -16,15 +16,15 @@ export type EmailLinkVerifyProps = {
verifyEmailPath?: string;
verifyPhonePath?: string;
continuePath?: string;
texts: Record<VerificationStatus, { title: LocalizationKey; subtitle: LocalizationKey }>;
texts: Record<EmailLinkUIStatus, { title: LocalizationKey; subtitle: LocalizationKey }>;
};

export const EmailLinkVerify = (props: EmailLinkVerifyProps) => {
const { redirectUrl, redirectUrlComplete, verifyEmailPath, verifyPhonePath, continuePath } = props;
const { handleEmailLinkVerification } = useClerk();
const { navigate } = useRouter();
const signUp = useCoreSignUp();
const [verificationStatus, setVerificationStatus] = React.useState<VerificationStatus>('loading');
const [verificationStatus, setVerificationStatus] = React.useState<EmailLinkUIStatus>('loading');

const startVerification = async () => {
try {
Expand All @@ -33,22 +33,23 @@ export const EmailLinkVerify = (props: EmailLinkVerifyProps) => {
await handleEmailLinkVerification({ redirectUrlComplete, redirectUrl }, navigate);
setVerificationStatus('verified_switch_tab');
await sleep(750);
return completeSignUpFlow({
await completeSignUpFlow({
signUp,
verifyEmailPath,
verifyPhonePath,
continuePath,
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);
}
};

Expand Down
24 changes: 13 additions & 11 deletions packages/clerk-js/src/utils/getClerkQueryParam.ts
Original file line number Diff line number Diff line change
@@ -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 = [
Expand All @@ -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<T extends ClerkQueryParam>(param: T): ClerkQueryParamsToValuesMap[T] | null {
const val = new URL(window.location.href).searchParams.get(param);
Expand Down

0 comments on commit 2191755

Please sign in to comment.