From 2b63137e590b366ca11d3429d56155c670e64c14 Mon Sep 17 00:00:00 2001 From: Alex Carpenter Date: Wed, 22 Jan 2025 15:44:08 -0500 Subject: [PATCH 1/8] refactor(clerk-js,types): Remove virtual routing option --- .../OrganizationProfile.tsx | 10 ++- .../src/ui/components/SignIn/SignIn.tsx | 6 +- .../src/ui/components/SignUp/SignUp.tsx | 6 +- .../ui/components/UserProfile/UserProfile.tsx | 11 +-- .../ui/components/UserVerification/index.tsx | 6 +- packages/clerk-js/src/ui/types.ts | 69 +++++++++++-------- packages/types/src/clerk.ts | 7 +- 7 files changed, 72 insertions(+), 43 deletions(-) diff --git a/packages/clerk-js/src/ui/components/OrganizationProfile/OrganizationProfile.tsx b/packages/clerk-js/src/ui/components/OrganizationProfile/OrganizationProfile.tsx index 116eb1f5d4b..8e0c05bcf97 100644 --- a/packages/clerk-js/src/ui/components/OrganizationProfile/OrganizationProfile.tsx +++ b/packages/clerk-js/src/ui/components/OrganizationProfile/OrganizationProfile.tsx @@ -1,16 +1,16 @@ import { useOrganization } from '@clerk/shared/react'; import type { OrganizationProfileModalProps, OrganizationProfileProps } from '@clerk/types'; import React from 'react'; +import type { __internal_RoutingOptions, OrganizationProfileCtx } from 'ui/types'; import { OrganizationProfileContext, withCoreUserGuard } from '../../contexts'; import { Flow, localizationKeys } from '../../customizables'; import { NavbarMenuButtonRow, ProfileCard, withCardStateProvider } from '../../elements'; import { Route, Switch } from '../../router'; -import type { OrganizationProfileCtx } from '../../types'; import { OrganizationProfileNavbar } from './OrganizationProfileNavbar'; import { OrganizationProfileRoutes } from './OrganizationProfileRoutes'; -const _OrganizationProfile = (_: OrganizationProfileProps) => { +const _OrganizationProfile = () => { const { organization } = useOrganization(); if (!organization) { @@ -48,6 +48,10 @@ const AuthenticatedRoutes = withCoreUserGuard(() => { export const OrganizationProfile = withCardStateProvider(_OrganizationProfile); +const InternalOrganizationProfile: React.ComponentType< + Omit & __internal_RoutingOptions +> = withCardStateProvider(_OrganizationProfile); + export const OrganizationProfileModal = (props: OrganizationProfileModalProps): JSX.Element => { const organizationProfileProps: OrganizationProfileCtx = { ...props, @@ -61,7 +65,7 @@ export const OrganizationProfileModal = (props: OrganizationProfileModalProps): {/*TODO: Used by InvisibleRootBox, can we simplify? */}
- +
diff --git a/packages/clerk-js/src/ui/components/SignIn/SignIn.tsx b/packages/clerk-js/src/ui/components/SignIn/SignIn.tsx index cd26298bd7f..f2550da5278 100644 --- a/packages/clerk-js/src/ui/components/SignIn/SignIn.tsx +++ b/packages/clerk-js/src/ui/components/SignIn/SignIn.tsx @@ -1,6 +1,7 @@ import { useClerk } from '@clerk/shared/react'; import type { SignInModalProps, SignInProps } from '@clerk/types'; import React from 'react'; +import type { __internal_RoutingOptions } from 'ui/types'; import { normalizeRoutingOptions } from '../../../utils/normalizeRoutingOptions'; import { SignInEmailLinkFlowComplete, SignUpEmailLinkFlowComplete } from '../../common/EmailLinkCompleteFlowCard'; @@ -165,6 +166,9 @@ SignInRoutes.displayName = 'SignIn'; export const SignIn: React.ComponentType = withCoreSessionSwitchGuard(SignInRoot); +const InternalSignIn: React.ComponentType & __internal_RoutingOptions> = + withCoreSessionSwitchGuard(SignInRoot); + export const SignInModal = (props: SignInModalProps): JSX.Element => { const signInProps = { signUpUrl: `/${VIRTUAL_ROUTER_BASE_PATH}/sign-up`, @@ -184,7 +188,7 @@ export const SignInModal = (props: SignInModalProps): JSX.Element => { > {/*TODO: Used by InvisibleRootBox, can we simplify? */}
- diff --git a/packages/clerk-js/src/ui/components/SignUp/SignUp.tsx b/packages/clerk-js/src/ui/components/SignUp/SignUp.tsx index 430ae2f53a9..59e7cc73480 100644 --- a/packages/clerk-js/src/ui/components/SignUp/SignUp.tsx +++ b/packages/clerk-js/src/ui/components/SignUp/SignUp.tsx @@ -1,6 +1,7 @@ import { useClerk } from '@clerk/shared/react'; import type { SignUpModalProps, SignUpProps } from '@clerk/types'; import React from 'react'; +import type { __internal_RoutingOptions } from 'ui/types'; import { SignUpEmailLinkFlowComplete } from '../../common/EmailLinkCompleteFlowCard'; import { SignUpContext, useSignUpContext, withCoreSessionSwitchGuard } from '../../contexts'; @@ -89,6 +90,9 @@ SignUpRoutes.displayName = 'SignUp'; export const SignUp: React.ComponentType = withCoreSessionSwitchGuard(SignUpRoutes); +const InternalSignUp: React.ComponentType & __internal_RoutingOptions> = + withCoreSessionSwitchGuard(SignUpRoutes); + export const SignUpModal = (props: SignUpModalProps): JSX.Element => { const signUpProps = { signInUrl: `/${VIRTUAL_ROUTER_BASE_PATH}/sign-in`, @@ -108,7 +112,7 @@ export const SignUpModal = (props: SignUpModalProps): JSX.Element => { > {/*TODO: Used by InvisibleRootBox, can we simplify? */}
- diff --git a/packages/clerk-js/src/ui/components/UserProfile/UserProfile.tsx b/packages/clerk-js/src/ui/components/UserProfile/UserProfile.tsx index ad641d35a5a..f5d166878e0 100644 --- a/packages/clerk-js/src/ui/components/UserProfile/UserProfile.tsx +++ b/packages/clerk-js/src/ui/components/UserProfile/UserProfile.tsx @@ -5,12 +5,12 @@ import { UserProfileContext, withCoreUserGuard } from '../../contexts'; import { Flow, localizationKeys } from '../../customizables'; import { NavbarMenuButtonRow, ProfileCard, withCardStateProvider } from '../../elements'; import { Route, Switch } from '../../router'; -import type { UserProfileCtx } from '../../types'; +import type { __internal_RoutingOptions, UserProfileCtx } from '../../types'; import { UserProfileNavbar } from './UserProfileNavbar'; import { UserProfileRoutes } from './UserProfileRoutes'; import { VerificationSuccessPage } from './VerifyWithLink'; -const _UserProfile = (_: UserProfileProps) => { +const _UserProfile = () => { return ( @@ -42,7 +42,10 @@ const AuthenticatedRoutes = withCoreUserGuard(() => { ); }); -export const UserProfile = withCardStateProvider(_UserProfile); +export const UserProfile: React.ComponentType = withCardStateProvider(_UserProfile); + +const InternalUserProfile: React.ComponentType & __internal_RoutingOptions> = + withCardStateProvider(_UserProfile); export const UserProfileModal = (props: UserProfileModalProps): JSX.Element => { const userProfileProps: UserProfileCtx = { @@ -57,7 +60,7 @@ export const UserProfileModal = (props: UserProfileModalProps): JSX.Element => { {/*TODO: Used by InvisibleRootBox, can we simplify? */}
- +
diff --git a/packages/clerk-js/src/ui/components/UserVerification/index.tsx b/packages/clerk-js/src/ui/components/UserVerification/index.tsx index f00cd57fae9..f5ee62274eb 100644 --- a/packages/clerk-js/src/ui/components/UserVerification/index.tsx +++ b/packages/clerk-js/src/ui/components/UserVerification/index.tsx @@ -1,5 +1,6 @@ import type { __internal_UserVerificationModalProps, __internal_UserVerificationProps } from '@clerk/types'; import React, { useEffect } from 'react'; +import type { __internal_RoutingOptions } from 'ui/types'; import { UserVerificationContext, withCoreSessionSwitchGuard } from '../../contexts'; import { Flow } from '../../customizables'; @@ -31,8 +32,9 @@ function UserVerificationRoutes(): JSX.Element { UserVerificationRoutes.displayName = 'UserVerification'; -const UserVerification: React.ComponentType<__internal_UserVerificationProps> = - withCoreSessionSwitchGuard(UserVerificationRoutes); +const UserVerification: React.ComponentType< + Omit<__internal_UserVerificationProps, 'routing'> & __internal_RoutingOptions +> = withCoreSessionSwitchGuard(UserVerificationRoutes); const UserVerificationModal = (props: __internal_UserVerificationModalProps): JSX.Element => { return ( diff --git a/packages/clerk-js/src/ui/types.ts b/packages/clerk-js/src/ui/types.ts index e90ebfff249..f50a81e01f9 100644 --- a/packages/clerk-js/src/ui/types.ts +++ b/packages/clerk-js/src/ui/types.ts @@ -5,6 +5,7 @@ import type { OrganizationListProps, OrganizationProfileProps, OrganizationSwitcherProps, + RoutingStrategy, SignInProps, SignUpProps, UserButtonProps, @@ -40,42 +41,48 @@ export type AvailableComponentProps = type ComponentMode = 'modal' | 'mounted'; -export type SignInCtx = SignInProps & { - componentName: 'SignIn'; - mode?: ComponentMode; -}; - -export type UserVerificationCtx = __internal_UserVerificationProps & { - componentName: 'UserVerification'; - mode?: ComponentMode; -}; - -export type UserProfileCtx = UserProfileProps & { - componentName: 'UserProfile'; - mode?: ComponentMode; -}; - -export type SignUpCtx = SignUpProps & { - componentName: 'SignUp'; - mode?: ComponentMode; - emailLinkRedirectUrl?: string; - ssoCallbackUrl?: string; -}; +export type SignInCtx = Omit & + __internal_RoutingOptions & { + componentName: 'SignIn'; + mode?: ComponentMode; + }; + +export type UserVerificationCtx = Omit<__internal_UserVerificationProps, 'routing'> & + __internal_RoutingOptions & { + componentName: 'UserVerification'; + mode?: ComponentMode; + }; + +export type UserProfileCtx = Omit & + __internal_RoutingOptions & { + componentName: 'UserProfile'; + mode?: ComponentMode; + }; + +export type SignUpCtx = Omit & + __internal_RoutingOptions & { + componentName: 'SignUp'; + mode?: ComponentMode; + emailLinkRedirectUrl?: string; + ssoCallbackUrl?: string; + }; export type UserButtonCtx = UserButtonProps & { componentName: 'UserButton'; mode?: ComponentMode; }; -export type OrganizationProfileCtx = OrganizationProfileProps & { - componentName: 'OrganizationProfile'; - mode?: ComponentMode; -}; +export type OrganizationProfileCtx = Omit & + __internal_RoutingOptions & { + componentName: 'OrganizationProfile'; + mode?: ComponentMode; + }; -export type CreateOrganizationCtx = CreateOrganizationProps & { - componentName: 'CreateOrganization'; - mode?: ComponentMode; -}; +export type CreateOrganizationCtx = Omit & + __internal_RoutingOptions & { + componentName: 'CreateOrganization'; + mode?: ComponentMode; + }; export type OrganizationSwitcherCtx = OrganizationSwitcherProps & { componentName: 'OrganizationSwitcher'; @@ -110,3 +117,7 @@ export type AvailableComponentCtx = | WaitlistCtx; export type AvailableComponentName = AvailableComponentCtx['componentName']; + +export type __internal_RoutingOptions = { + routing?: RoutingStrategy; +}; diff --git a/packages/types/src/clerk.ts b/packages/types/src/clerk.ts index b874ec82a1a..69c834a8f87 100644 --- a/packages/types/src/clerk.ts +++ b/packages/types/src/clerk.ts @@ -890,9 +890,10 @@ export type SetActiveParams = { export type SetActive = (params: SetActiveParams) => Promise; -export type RoutingOptions = - | { path: string | undefined; routing?: Extract } - | { path?: never; routing?: Extract }; +export type RoutingOptions = { + path?: string; + routing?: Exclude; +}; export type SignInProps = RoutingOptions & { /** From 414a5237fd497f22b40c5d8153f7dc1ecb159b02 Mon Sep 17 00:00:00 2001 From: Alex Carpenter Date: Wed, 22 Jan 2025 15:50:12 -0500 Subject: [PATCH 2/8] add changeset --- .changeset/silent-ducks-wait.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changeset/silent-ducks-wait.md diff --git a/.changeset/silent-ducks-wait.md b/.changeset/silent-ducks-wait.md new file mode 100644 index 00000000000..34197c11f18 --- /dev/null +++ b/.changeset/silent-ducks-wait.md @@ -0,0 +1,7 @@ +--- +'@clerk/clerk-js': patch +'@clerk/clerk-react': patch +'@clerk/types': patch +--- + +Remove `virtual` routing option from components. From c3e725145105314e6b4f4bc3e213c3b3dd121741 Mon Sep 17 00:00:00 2001 From: Alex Carpenter Date: Wed, 22 Jan 2025 15:54:40 -0500 Subject: [PATCH 3/8] cleanup tests --- .../__tests__/OrganizationProfile.test.tsx | 12 ------------ .../react/src/components/__tests__/SignIn.test.tsx | 12 ------------ .../react/src/components/__tests__/SignUp.test.tsx | 12 ------------ .../src/components/__tests__/UserProfile.test.tsx | 12 ------------ 4 files changed, 48 deletions(-) diff --git a/packages/react/src/components/__tests__/OrganizationProfile.test.tsx b/packages/react/src/components/__tests__/OrganizationProfile.test.tsx index 6fbeeb3e56e..35a44f739bf 100644 --- a/packages/react/src/components/__tests__/OrganizationProfile.test.tsx +++ b/packages/react/src/components/__tests__/OrganizationProfile.test.tsx @@ -19,18 +19,6 @@ describe('', () => { }).toMatchTypeOf(); }); - test('when path is filled, routing must only have path as value', () => { - expectTypeOf({ - path: '/org', - routing: 'virtual' as const, - }).not.toMatchTypeOf(); - - expectTypeOf({ - path: '/org', - routing: 'hash' as const, - }).not.toMatchTypeOf(); - }); - test('when routing is hash or virtual path must be present', () => { expectTypeOf({ routing: 'hash' as const, diff --git a/packages/react/src/components/__tests__/SignIn.test.tsx b/packages/react/src/components/__tests__/SignIn.test.tsx index 84e67fbf0ac..96d52b55718 100644 --- a/packages/react/src/components/__tests__/SignIn.test.tsx +++ b/packages/react/src/components/__tests__/SignIn.test.tsx @@ -19,18 +19,6 @@ describe('', () => { }).toMatchTypeOf(); }); - test('when path is filled, routing must only have path as value', () => { - expectTypeOf({ - path: '/sign-in', - routing: 'virtual' as const, - }).not.toMatchTypeOf(); - - expectTypeOf({ - path: '/sign-in', - routing: 'hash' as const, - }).not.toMatchTypeOf(); - }); - test('when routing is hash or virtual path must be present', () => { expectTypeOf({ routing: 'hash' as const, diff --git a/packages/react/src/components/__tests__/SignUp.test.tsx b/packages/react/src/components/__tests__/SignUp.test.tsx index 82afcddeec3..d2e4218ae68 100644 --- a/packages/react/src/components/__tests__/SignUp.test.tsx +++ b/packages/react/src/components/__tests__/SignUp.test.tsx @@ -19,18 +19,6 @@ describe('', () => { }).toMatchTypeOf(); }); - test('when path is filled, routing must only have path as value', () => { - expectTypeOf({ - path: '/sign-up', - routing: 'virtual' as const, - }).not.toMatchTypeOf(); - - expectTypeOf({ - path: '/sign-up', - routing: 'hash' as const, - }).not.toMatchTypeOf(); - }); - test('when routing is hash or virtual path must be present', () => { expectTypeOf({ routing: 'hash' as const, diff --git a/packages/react/src/components/__tests__/UserProfile.test.tsx b/packages/react/src/components/__tests__/UserProfile.test.tsx index a68bb336efa..79a8a37bd78 100644 --- a/packages/react/src/components/__tests__/UserProfile.test.tsx +++ b/packages/react/src/components/__tests__/UserProfile.test.tsx @@ -19,18 +19,6 @@ describe('', () => { }).toMatchTypeOf(); }); - test('when path is filled, routing must only have path as value', () => { - expectTypeOf({ - path: '/profile', - routing: 'virtual' as const, - }).not.toMatchTypeOf(); - - expectTypeOf({ - path: '/profile', - routing: 'hash' as const, - }).not.toMatchTypeOf(); - }); - test('when routing is hash or virtual path must be present', () => { expectTypeOf({ routing: 'hash' as const, From ea98b886cd1b130839ff8a1c1605f5eadb85898c Mon Sep 17 00:00:00 2001 From: Alex Carpenter Date: Wed, 22 Jan 2025 16:47:27 -0500 Subject: [PATCH 4/8] extract WithInternalRouting util --- .../components/OrganizationProfile/OrganizationProfile.tsx | 7 +++---- packages/clerk-js/src/ui/components/SignIn/SignIn.tsx | 5 ++--- packages/clerk-js/src/ui/components/SignUp/SignUp.tsx | 5 ++--- .../clerk-js/src/ui/components/UserProfile/UserProfile.tsx | 4 ++-- .../clerk-js/src/ui/components/UserVerification/index.tsx | 7 +++---- packages/clerk-js/src/ui/types.ts | 2 +- 6 files changed, 13 insertions(+), 17 deletions(-) diff --git a/packages/clerk-js/src/ui/components/OrganizationProfile/OrganizationProfile.tsx b/packages/clerk-js/src/ui/components/OrganizationProfile/OrganizationProfile.tsx index 8e0c05bcf97..93b3f33aaa3 100644 --- a/packages/clerk-js/src/ui/components/OrganizationProfile/OrganizationProfile.tsx +++ b/packages/clerk-js/src/ui/components/OrganizationProfile/OrganizationProfile.tsx @@ -1,7 +1,7 @@ import { useOrganization } from '@clerk/shared/react'; import type { OrganizationProfileModalProps, OrganizationProfileProps } from '@clerk/types'; import React from 'react'; -import type { __internal_RoutingOptions, OrganizationProfileCtx } from 'ui/types'; +import type { OrganizationProfileCtx, WithInternalRouting } from 'ui/types'; import { OrganizationProfileContext, withCoreUserGuard } from '../../contexts'; import { Flow, localizationKeys } from '../../customizables'; @@ -48,9 +48,8 @@ const AuthenticatedRoutes = withCoreUserGuard(() => { export const OrganizationProfile = withCardStateProvider(_OrganizationProfile); -const InternalOrganizationProfile: React.ComponentType< - Omit & __internal_RoutingOptions -> = withCardStateProvider(_OrganizationProfile); +const InternalOrganizationProfile: React.ComponentType> = + withCardStateProvider(_OrganizationProfile); export const OrganizationProfileModal = (props: OrganizationProfileModalProps): JSX.Element => { const organizationProfileProps: OrganizationProfileCtx = { diff --git a/packages/clerk-js/src/ui/components/SignIn/SignIn.tsx b/packages/clerk-js/src/ui/components/SignIn/SignIn.tsx index f2550da5278..d4662aa9473 100644 --- a/packages/clerk-js/src/ui/components/SignIn/SignIn.tsx +++ b/packages/clerk-js/src/ui/components/SignIn/SignIn.tsx @@ -1,7 +1,7 @@ import { useClerk } from '@clerk/shared/react'; import type { SignInModalProps, SignInProps } from '@clerk/types'; import React from 'react'; -import type { __internal_RoutingOptions } from 'ui/types'; +import type { WithInternalRouting } from 'ui/types'; import { normalizeRoutingOptions } from '../../../utils/normalizeRoutingOptions'; import { SignInEmailLinkFlowComplete, SignUpEmailLinkFlowComplete } from '../../common/EmailLinkCompleteFlowCard'; @@ -166,8 +166,7 @@ SignInRoutes.displayName = 'SignIn'; export const SignIn: React.ComponentType = withCoreSessionSwitchGuard(SignInRoot); -const InternalSignIn: React.ComponentType & __internal_RoutingOptions> = - withCoreSessionSwitchGuard(SignInRoot); +const InternalSignIn: React.ComponentType> = withCoreSessionSwitchGuard(SignInRoot); export const SignInModal = (props: SignInModalProps): JSX.Element => { const signInProps = { diff --git a/packages/clerk-js/src/ui/components/SignUp/SignUp.tsx b/packages/clerk-js/src/ui/components/SignUp/SignUp.tsx index 59e7cc73480..642a4442b56 100644 --- a/packages/clerk-js/src/ui/components/SignUp/SignUp.tsx +++ b/packages/clerk-js/src/ui/components/SignUp/SignUp.tsx @@ -1,7 +1,7 @@ import { useClerk } from '@clerk/shared/react'; import type { SignUpModalProps, SignUpProps } from '@clerk/types'; import React from 'react'; -import type { __internal_RoutingOptions } from 'ui/types'; +import type { WithInternalRouting } from 'ui/types'; import { SignUpEmailLinkFlowComplete } from '../../common/EmailLinkCompleteFlowCard'; import { SignUpContext, useSignUpContext, withCoreSessionSwitchGuard } from '../../contexts'; @@ -90,8 +90,7 @@ SignUpRoutes.displayName = 'SignUp'; export const SignUp: React.ComponentType = withCoreSessionSwitchGuard(SignUpRoutes); -const InternalSignUp: React.ComponentType & __internal_RoutingOptions> = - withCoreSessionSwitchGuard(SignUpRoutes); +const InternalSignUp: React.ComponentType> = withCoreSessionSwitchGuard(SignUpRoutes); export const SignUpModal = (props: SignUpModalProps): JSX.Element => { const signUpProps = { diff --git a/packages/clerk-js/src/ui/components/UserProfile/UserProfile.tsx b/packages/clerk-js/src/ui/components/UserProfile/UserProfile.tsx index f5d166878e0..a6e12dd4f38 100644 --- a/packages/clerk-js/src/ui/components/UserProfile/UserProfile.tsx +++ b/packages/clerk-js/src/ui/components/UserProfile/UserProfile.tsx @@ -5,7 +5,7 @@ import { UserProfileContext, withCoreUserGuard } from '../../contexts'; import { Flow, localizationKeys } from '../../customizables'; import { NavbarMenuButtonRow, ProfileCard, withCardStateProvider } from '../../elements'; import { Route, Switch } from '../../router'; -import type { __internal_RoutingOptions, UserProfileCtx } from '../../types'; +import type { UserProfileCtx, WithInternalRouting } from '../../types'; import { UserProfileNavbar } from './UserProfileNavbar'; import { UserProfileRoutes } from './UserProfileRoutes'; import { VerificationSuccessPage } from './VerifyWithLink'; @@ -44,7 +44,7 @@ const AuthenticatedRoutes = withCoreUserGuard(() => { export const UserProfile: React.ComponentType = withCardStateProvider(_UserProfile); -const InternalUserProfile: React.ComponentType & __internal_RoutingOptions> = +const InternalUserProfile: React.ComponentType> = withCardStateProvider(_UserProfile); export const UserProfileModal = (props: UserProfileModalProps): JSX.Element => { diff --git a/packages/clerk-js/src/ui/components/UserVerification/index.tsx b/packages/clerk-js/src/ui/components/UserVerification/index.tsx index f5ee62274eb..0c38f4c19f6 100644 --- a/packages/clerk-js/src/ui/components/UserVerification/index.tsx +++ b/packages/clerk-js/src/ui/components/UserVerification/index.tsx @@ -1,6 +1,6 @@ import type { __internal_UserVerificationModalProps, __internal_UserVerificationProps } from '@clerk/types'; import React, { useEffect } from 'react'; -import type { __internal_RoutingOptions } from 'ui/types'; +import type { WithInternalRouting } from 'ui/types'; import { UserVerificationContext, withCoreSessionSwitchGuard } from '../../contexts'; import { Flow } from '../../customizables'; @@ -32,9 +32,8 @@ function UserVerificationRoutes(): JSX.Element { UserVerificationRoutes.displayName = 'UserVerification'; -const UserVerification: React.ComponentType< - Omit<__internal_UserVerificationProps, 'routing'> & __internal_RoutingOptions -> = withCoreSessionSwitchGuard(UserVerificationRoutes); +const UserVerification: React.ComponentType> = + withCoreSessionSwitchGuard(UserVerificationRoutes); const UserVerificationModal = (props: __internal_UserVerificationModalProps): JSX.Element => { return ( diff --git a/packages/clerk-js/src/ui/types.ts b/packages/clerk-js/src/ui/types.ts index f50a81e01f9..37057b8a38d 100644 --- a/packages/clerk-js/src/ui/types.ts +++ b/packages/clerk-js/src/ui/types.ts @@ -118,6 +118,6 @@ export type AvailableComponentCtx = export type AvailableComponentName = AvailableComponentCtx['componentName']; -export type __internal_RoutingOptions = { +export type WithInternalRouting = Omit & { routing?: RoutingStrategy; }; From 6c61fd1809105213c476db06b921deb84131098a Mon Sep 17 00:00:00 2001 From: Alex Carpenter Date: Wed, 22 Jan 2025 18:59:23 -0500 Subject: [PATCH 5/8] bring back discriminated union --- .../OrganizationProfile.tsx | 4 +- .../src/ui/components/SignIn/SignIn.tsx | 3 +- .../src/ui/components/SignUp/SignUp.tsx | 3 +- .../ui/components/UserProfile/UserProfile.tsx | 4 +- .../ui/components/UserVerification/index.tsx | 7 +- packages/clerk-js/src/ui/types.ts | 70 ++++++++----------- packages/types/src/clerk.ts | 11 +-- 7 files changed, 48 insertions(+), 54 deletions(-) diff --git a/packages/clerk-js/src/ui/components/OrganizationProfile/OrganizationProfile.tsx b/packages/clerk-js/src/ui/components/OrganizationProfile/OrganizationProfile.tsx index 93b3f33aaa3..488d5979ffd 100644 --- a/packages/clerk-js/src/ui/components/OrganizationProfile/OrganizationProfile.tsx +++ b/packages/clerk-js/src/ui/components/OrganizationProfile/OrganizationProfile.tsx @@ -1,7 +1,7 @@ import { useOrganization } from '@clerk/shared/react'; -import type { OrganizationProfileModalProps, OrganizationProfileProps } from '@clerk/types'; +import type { OrganizationProfileModalProps, OrganizationProfileProps, WithInternalRouting } from '@clerk/types'; import React from 'react'; -import type { OrganizationProfileCtx, WithInternalRouting } from 'ui/types'; +import type { OrganizationProfileCtx } from 'ui/types'; import { OrganizationProfileContext, withCoreUserGuard } from '../../contexts'; import { Flow, localizationKeys } from '../../customizables'; diff --git a/packages/clerk-js/src/ui/components/SignIn/SignIn.tsx b/packages/clerk-js/src/ui/components/SignIn/SignIn.tsx index d4662aa9473..34964fad25c 100644 --- a/packages/clerk-js/src/ui/components/SignIn/SignIn.tsx +++ b/packages/clerk-js/src/ui/components/SignIn/SignIn.tsx @@ -1,7 +1,6 @@ import { useClerk } from '@clerk/shared/react'; -import type { SignInModalProps, SignInProps } from '@clerk/types'; +import type { SignInModalProps, SignInProps, WithInternalRouting } from '@clerk/types'; import React from 'react'; -import type { WithInternalRouting } from 'ui/types'; import { normalizeRoutingOptions } from '../../../utils/normalizeRoutingOptions'; import { SignInEmailLinkFlowComplete, SignUpEmailLinkFlowComplete } from '../../common/EmailLinkCompleteFlowCard'; diff --git a/packages/clerk-js/src/ui/components/SignUp/SignUp.tsx b/packages/clerk-js/src/ui/components/SignUp/SignUp.tsx index 642a4442b56..d4961f92f9e 100644 --- a/packages/clerk-js/src/ui/components/SignUp/SignUp.tsx +++ b/packages/clerk-js/src/ui/components/SignUp/SignUp.tsx @@ -1,7 +1,6 @@ import { useClerk } from '@clerk/shared/react'; -import type { SignUpModalProps, SignUpProps } from '@clerk/types'; +import type { SignUpModalProps, SignUpProps, WithInternalRouting } from '@clerk/types'; import React from 'react'; -import type { WithInternalRouting } from 'ui/types'; import { SignUpEmailLinkFlowComplete } from '../../common/EmailLinkCompleteFlowCard'; import { SignUpContext, useSignUpContext, withCoreSessionSwitchGuard } from '../../contexts'; diff --git a/packages/clerk-js/src/ui/components/UserProfile/UserProfile.tsx b/packages/clerk-js/src/ui/components/UserProfile/UserProfile.tsx index a6e12dd4f38..767329334ba 100644 --- a/packages/clerk-js/src/ui/components/UserProfile/UserProfile.tsx +++ b/packages/clerk-js/src/ui/components/UserProfile/UserProfile.tsx @@ -1,11 +1,11 @@ -import type { UserProfileModalProps, UserProfileProps } from '@clerk/types'; +import type { UserProfileModalProps, UserProfileProps, WithInternalRouting } from '@clerk/types'; import React from 'react'; import { UserProfileContext, withCoreUserGuard } from '../../contexts'; import { Flow, localizationKeys } from '../../customizables'; import { NavbarMenuButtonRow, ProfileCard, withCardStateProvider } from '../../elements'; import { Route, Switch } from '../../router'; -import type { UserProfileCtx, WithInternalRouting } from '../../types'; +import type { UserProfileCtx } from '../../types'; import { UserProfileNavbar } from './UserProfileNavbar'; import { UserProfileRoutes } from './UserProfileRoutes'; import { VerificationSuccessPage } from './VerifyWithLink'; diff --git a/packages/clerk-js/src/ui/components/UserVerification/index.tsx b/packages/clerk-js/src/ui/components/UserVerification/index.tsx index 0c38f4c19f6..36524300a43 100644 --- a/packages/clerk-js/src/ui/components/UserVerification/index.tsx +++ b/packages/clerk-js/src/ui/components/UserVerification/index.tsx @@ -1,6 +1,9 @@ -import type { __internal_UserVerificationModalProps, __internal_UserVerificationProps } from '@clerk/types'; +import type { + __internal_UserVerificationModalProps, + __internal_UserVerificationProps, + WithInternalRouting, +} from '@clerk/types'; import React, { useEffect } from 'react'; -import type { WithInternalRouting } from 'ui/types'; import { UserVerificationContext, withCoreSessionSwitchGuard } from '../../contexts'; import { Flow } from '../../customizables'; diff --git a/packages/clerk-js/src/ui/types.ts b/packages/clerk-js/src/ui/types.ts index 37057b8a38d..5923047e840 100644 --- a/packages/clerk-js/src/ui/types.ts +++ b/packages/clerk-js/src/ui/types.ts @@ -5,12 +5,12 @@ import type { OrganizationListProps, OrganizationProfileProps, OrganizationSwitcherProps, - RoutingStrategy, SignInProps, SignUpProps, UserButtonProps, UserProfileProps, WaitlistProps, + WithInternalRouting, } from '@clerk/types'; export type { @@ -41,48 +41,42 @@ export type AvailableComponentProps = type ComponentMode = 'modal' | 'mounted'; -export type SignInCtx = Omit & - __internal_RoutingOptions & { - componentName: 'SignIn'; - mode?: ComponentMode; - }; - -export type UserVerificationCtx = Omit<__internal_UserVerificationProps, 'routing'> & - __internal_RoutingOptions & { - componentName: 'UserVerification'; - mode?: ComponentMode; - }; - -export type UserProfileCtx = Omit & - __internal_RoutingOptions & { - componentName: 'UserProfile'; - mode?: ComponentMode; - }; - -export type SignUpCtx = Omit & - __internal_RoutingOptions & { - componentName: 'SignUp'; - mode?: ComponentMode; - emailLinkRedirectUrl?: string; - ssoCallbackUrl?: string; - }; +export type SignInCtx = WithInternalRouting & { + componentName: 'SignIn'; + mode?: ComponentMode; +}; + +export type UserVerificationCtx = WithInternalRouting<__internal_UserVerificationProps> & { + componentName: 'UserVerification'; + mode?: ComponentMode; +}; + +export type UserProfileCtx = WithInternalRouting & { + componentName: 'UserProfile'; + mode?: ComponentMode; +}; + +export type SignUpCtx = WithInternalRouting & { + componentName: 'SignUp'; + mode?: ComponentMode; + emailLinkRedirectUrl?: string; + ssoCallbackUrl?: string; +}; export type UserButtonCtx = UserButtonProps & { componentName: 'UserButton'; mode?: ComponentMode; }; -export type OrganizationProfileCtx = Omit & - __internal_RoutingOptions & { - componentName: 'OrganizationProfile'; - mode?: ComponentMode; - }; +export type OrganizationProfileCtx = WithInternalRouting & { + componentName: 'OrganizationProfile'; + mode?: ComponentMode; +}; -export type CreateOrganizationCtx = Omit & - __internal_RoutingOptions & { - componentName: 'CreateOrganization'; - mode?: ComponentMode; - }; +export type CreateOrganizationCtx = WithInternalRouting & { + componentName: 'CreateOrganization'; + mode?: ComponentMode; +}; export type OrganizationSwitcherCtx = OrganizationSwitcherProps & { componentName: 'OrganizationSwitcher'; @@ -117,7 +111,3 @@ export type AvailableComponentCtx = | WaitlistCtx; export type AvailableComponentName = AvailableComponentCtx['componentName']; - -export type WithInternalRouting = Omit & { - routing?: RoutingStrategy; -}; diff --git a/packages/types/src/clerk.ts b/packages/types/src/clerk.ts index 69c834a8f87..3bfd1740a55 100644 --- a/packages/types/src/clerk.ts +++ b/packages/types/src/clerk.ts @@ -831,6 +831,10 @@ type RouterFn = ( export type WithoutRouting = Omit; +export type WithInternalRouting = + | (Omit & { path: string | undefined; routing?: Extract }) + | (Omit & { path?: never; routing?: Extract }); + export type SignInInitialValues = { emailAddress?: string; phoneNumber?: string; @@ -890,10 +894,9 @@ export type SetActiveParams = { export type SetActive = (params: SetActiveParams) => Promise; -export type RoutingOptions = { - path?: string; - routing?: Exclude; -}; +export type RoutingOptions = + | { path: string | undefined; routing?: Extract } + | { path?: never; routing?: Extract }; export type SignInProps = RoutingOptions & { /** From fcc1ba6a6fb3695ef14f4254a96e0ec9c49f7616 Mon Sep 17 00:00:00 2001 From: Alex Carpenter Date: Wed, 22 Jan 2025 19:07:23 -0500 Subject: [PATCH 6/8] bring back type assertions --- .../__tests__/OrganizationProfile.test.tsx | 12 ++++++++++++ .../react/src/components/__tests__/SignIn.test.tsx | 12 ++++++++++++ .../react/src/components/__tests__/SignUp.test.tsx | 12 ++++++++++++ .../src/components/__tests__/UserProfile.test.tsx | 12 ++++++++++++ 4 files changed, 48 insertions(+) diff --git a/packages/react/src/components/__tests__/OrganizationProfile.test.tsx b/packages/react/src/components/__tests__/OrganizationProfile.test.tsx index 35a44f739bf..6fbeeb3e56e 100644 --- a/packages/react/src/components/__tests__/OrganizationProfile.test.tsx +++ b/packages/react/src/components/__tests__/OrganizationProfile.test.tsx @@ -19,6 +19,18 @@ describe('', () => { }).toMatchTypeOf(); }); + test('when path is filled, routing must only have path as value', () => { + expectTypeOf({ + path: '/org', + routing: 'virtual' as const, + }).not.toMatchTypeOf(); + + expectTypeOf({ + path: '/org', + routing: 'hash' as const, + }).not.toMatchTypeOf(); + }); + test('when routing is hash or virtual path must be present', () => { expectTypeOf({ routing: 'hash' as const, diff --git a/packages/react/src/components/__tests__/SignIn.test.tsx b/packages/react/src/components/__tests__/SignIn.test.tsx index 96d52b55718..84e67fbf0ac 100644 --- a/packages/react/src/components/__tests__/SignIn.test.tsx +++ b/packages/react/src/components/__tests__/SignIn.test.tsx @@ -19,6 +19,18 @@ describe('', () => { }).toMatchTypeOf(); }); + test('when path is filled, routing must only have path as value', () => { + expectTypeOf({ + path: '/sign-in', + routing: 'virtual' as const, + }).not.toMatchTypeOf(); + + expectTypeOf({ + path: '/sign-in', + routing: 'hash' as const, + }).not.toMatchTypeOf(); + }); + test('when routing is hash or virtual path must be present', () => { expectTypeOf({ routing: 'hash' as const, diff --git a/packages/react/src/components/__tests__/SignUp.test.tsx b/packages/react/src/components/__tests__/SignUp.test.tsx index d2e4218ae68..82afcddeec3 100644 --- a/packages/react/src/components/__tests__/SignUp.test.tsx +++ b/packages/react/src/components/__tests__/SignUp.test.tsx @@ -19,6 +19,18 @@ describe('', () => { }).toMatchTypeOf(); }); + test('when path is filled, routing must only have path as value', () => { + expectTypeOf({ + path: '/sign-up', + routing: 'virtual' as const, + }).not.toMatchTypeOf(); + + expectTypeOf({ + path: '/sign-up', + routing: 'hash' as const, + }).not.toMatchTypeOf(); + }); + test('when routing is hash or virtual path must be present', () => { expectTypeOf({ routing: 'hash' as const, diff --git a/packages/react/src/components/__tests__/UserProfile.test.tsx b/packages/react/src/components/__tests__/UserProfile.test.tsx index 79a8a37bd78..a68bb336efa 100644 --- a/packages/react/src/components/__tests__/UserProfile.test.tsx +++ b/packages/react/src/components/__tests__/UserProfile.test.tsx @@ -19,6 +19,18 @@ describe('', () => { }).toMatchTypeOf(); }); + test('when path is filled, routing must only have path as value', () => { + expectTypeOf({ + path: '/profile', + routing: 'virtual' as const, + }).not.toMatchTypeOf(); + + expectTypeOf({ + path: '/profile', + routing: 'hash' as const, + }).not.toMatchTypeOf(); + }); + test('when routing is hash or virtual path must be present', () => { expectTypeOf({ routing: 'hash' as const, From 11ef086d437ce0042bef48c39fedf91a9f7102da Mon Sep 17 00:00:00 2001 From: Alex Carpenter Date: Wed, 22 Jan 2025 19:08:57 -0500 Subject: [PATCH 7/8] Update silent-ducks-wait.md --- .changeset/silent-ducks-wait.md | 1 - 1 file changed, 1 deletion(-) diff --git a/.changeset/silent-ducks-wait.md b/.changeset/silent-ducks-wait.md index 34197c11f18..9fa46713a99 100644 --- a/.changeset/silent-ducks-wait.md +++ b/.changeset/silent-ducks-wait.md @@ -1,6 +1,5 @@ --- '@clerk/clerk-js': patch -'@clerk/clerk-react': patch '@clerk/types': patch --- From ae915ef58dd912f6b9e267dd4430b1db82a99164 Mon Sep 17 00:00:00 2001 From: Alex Carpenter Date: Thu, 23 Jan 2025 09:58:41 -0500 Subject: [PATCH 8/8] Update .changeset/silent-ducks-wait.md Co-authored-by: Lennart --- .changeset/silent-ducks-wait.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/silent-ducks-wait.md b/.changeset/silent-ducks-wait.md index 9fa46713a99..1a27e3401a8 100644 --- a/.changeset/silent-ducks-wait.md +++ b/.changeset/silent-ducks-wait.md @@ -3,4 +3,4 @@ '@clerk/types': patch --- -Remove `virtual` routing option from components. +Remove `'virtual'` from the `routing` option. The `'virtual'` value is only used internally and should not be part of the public API.