From 9fc30a8eb8779c5f6929d69be56d028b033c9e01 Mon Sep 17 00:00:00 2001 From: Laura Beatris <48022589+LauraBeatris@users.noreply.github.com> Date: Fri, 21 Mar 2025 18:51:50 -0300 Subject: [PATCH 1/7] Remove `experimental` flag with routing refactoring --- .../next-app-router/src/app/layout.tsx | 2 - packages/clerk-js/src/core/clerk.ts | 4 +- packages/clerk-js/src/core/sessionTasks.ts | 6 +-- .../src/ui/components/SessionTask/index.ts | 1 - .../SessionTasks.tsx} | 47 +++++++++---------- .../src/ui/components/SessionTasks/index.ts | 1 + .../src/ui/components/SignIn/SignIn.tsx | 32 +++++-------- .../src/ui/components/SignUp/SignUp.tsx | 19 ++------ .../src/ui/contexts/components/SignIn.ts | 2 - .../src/ui/contexts/components/SignUp.ts | 2 - .../clerk-js/src/ui/lazyModules/components.ts | 8 ++-- packages/types/src/clerk.ts | 2 - 12 files changed, 49 insertions(+), 77 deletions(-) delete mode 100644 packages/clerk-js/src/ui/components/SessionTask/index.ts rename packages/clerk-js/src/ui/components/{SessionTask/SessionTask.tsx => SessionTasks/SessionTasks.tsx} (50%) create mode 100644 packages/clerk-js/src/ui/components/SessionTasks/index.ts diff --git a/integration/templates/next-app-router/src/app/layout.tsx b/integration/templates/next-app-router/src/app/layout.tsx index e598334db2..2e56184f39 100644 --- a/integration/templates/next-app-router/src/app/layout.tsx +++ b/integration/templates/next-app-router/src/app/layout.tsx @@ -24,8 +24,6 @@ export default function RootLayout({ children }: { children: React.ReactNode }) persistClient: process.env.NEXT_PUBLIC_EXPERIMENTAL_PERSIST_CLIENT ? process.env.NEXT_PUBLIC_EXPERIMENTAL_PERSIST_CLIENT === 'true' : undefined, - // `experimental.withSessionTasks` will be removed soon in favor of checking via environment response - withSessionTasks: true, }} > diff --git a/packages/clerk-js/src/core/clerk.ts b/packages/clerk-js/src/core/clerk.ts index 65cd4c2e92..b1c129f43e 100644 --- a/packages/clerk-js/src/core/clerk.ts +++ b/packages/clerk-js/src/core/clerk.ts @@ -1086,7 +1086,7 @@ export class Clerk implements ClerkInterface { } if (newSession?.currentTask) { - await navigateToTask(session.currentTask, { + await navigateToTask(session.currentTask.key, { globalNavigate: this.navigate, componentNavigationContext: this.#componentNavigationContext, options: this.#options, @@ -1109,7 +1109,7 @@ export class Clerk implements ClerkInterface { } if (session.status === 'pending') { - await navigateToTask(session.currentTask, { + await navigateToTask(session.currentTask.key, { options: this.#options, environment: this.environment, globalNavigate: this.navigate, diff --git a/packages/clerk-js/src/core/sessionTasks.ts b/packages/clerk-js/src/core/sessionTasks.ts index aeef4fc5b8..f620508a50 100644 --- a/packages/clerk-js/src/core/sessionTasks.ts +++ b/packages/clerk-js/src/core/sessionTasks.ts @@ -24,13 +24,13 @@ interface NavigateToTaskOptions { * @internal */ export function navigateToTask( - task: SessionTask, + routeKey: keyof typeof SESSION_TASK_ROUTE_BY_KEY, { componentNavigationContext, globalNavigate, options, environment }: NavigateToTaskOptions, ) { - const taskRoute = `/${SESSION_TASK_ROUTE_BY_KEY[task.key]}`; + const taskRoute = `/${SESSION_TASK_ROUTE_BY_KEY[routeKey]}`; if (componentNavigationContext) { - return componentNavigationContext.navigate(componentNavigationContext.indexPath + taskRoute); + return componentNavigationContext.navigate(componentNavigationContext.indexPath + routeKey); } const signInUrl = options['signInUrl'] || environment.displayConfig.signInUrl; diff --git a/packages/clerk-js/src/ui/components/SessionTask/index.ts b/packages/clerk-js/src/ui/components/SessionTask/index.ts deleted file mode 100644 index ddae613a6e..0000000000 --- a/packages/clerk-js/src/ui/components/SessionTask/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './SessionTask'; diff --git a/packages/clerk-js/src/ui/components/SessionTask/SessionTask.tsx b/packages/clerk-js/src/ui/components/SessionTasks/SessionTasks.tsx similarity index 50% rename from packages/clerk-js/src/ui/components/SessionTask/SessionTask.tsx rename to packages/clerk-js/src/ui/components/SessionTasks/SessionTasks.tsx index 03710860ed..6ef656357f 100644 --- a/packages/clerk-js/src/ui/components/SessionTask/SessionTask.tsx +++ b/packages/clerk-js/src/ui/components/SessionTasks/SessionTasks.tsx @@ -3,36 +3,39 @@ import { eventComponentMounted } from '@clerk/shared/telemetry'; import type { SessionTask } from '@clerk/types'; import { useCallback, useEffect } from 'react'; +import { SESSION_TASK_ROUTE_BY_KEY } from '../../../core/sessionTasks'; import { OrganizationListContext } from '../../contexts'; import { SessionTaskContext as SessionTaskContext } from '../../contexts/components/SessionTask'; -import { useRouter } from '../../router'; +import { Route, Switch, useRouter } from '../../router'; import { OrganizationList } from '../OrganizationList'; -interface SessionTaskProps { - task: SessionTask['key']; - redirectUrlComplete: string; +// TODO -> Lazy load individual routes per environment config +function SessionTaskRoutes(): JSX.Element { + return ( + + + + + + + + ); } -const ContentRegistry: Record = { - org: () => ( - - - - ), -}; - /** * @internal */ -export function SessionTask({ task, redirectUrlComplete }: SessionTaskProps): React.ReactNode { - const { session, telemetry, __experimental_nextTask } = useClerk(); +export function SessionTask({ redirectUrlComplete }: { redirectUrlComplete: string }): JSX.Element { + const { __experimental_nextTask, session, telemetry } = useClerk(); const { navigate } = useRouter(); + telemetry?.record(eventComponentMounted('SessionTask', { task: session?.currentTask?.key as string })); + useEffect(() => { if (session?.currentTask) { return; @@ -41,18 +44,14 @@ export function SessionTask({ task, redirectUrlComplete }: SessionTaskProps): Re void navigate(redirectUrlComplete); }, [session?.currentTask, navigate, redirectUrlComplete]); - telemetry?.record(eventComponentMounted('SessionTask', { task })); - const nextTask = useCallback( () => __experimental_nextTask({ redirectUrlComplete }), [__experimental_nextTask, redirectUrlComplete], ); - const Content = ContentRegistry[task]; - return ( - + ); } diff --git a/packages/clerk-js/src/ui/components/SessionTasks/index.ts b/packages/clerk-js/src/ui/components/SessionTasks/index.ts new file mode 100644 index 0000000000..f5840ac701 --- /dev/null +++ b/packages/clerk-js/src/ui/components/SessionTasks/index.ts @@ -0,0 +1 @@ +export * from './SessionTasks'; diff --git a/packages/clerk-js/src/ui/components/SignIn/SignIn.tsx b/packages/clerk-js/src/ui/components/SignIn/SignIn.tsx index 08416ec915..1bede25f8f 100644 --- a/packages/clerk-js/src/ui/components/SignIn/SignIn.tsx +++ b/packages/clerk-js/src/ui/components/SignIn/SignIn.tsx @@ -15,7 +15,7 @@ import { } from '../../contexts'; import { Flow } from '../../customizables'; import { useFetch } from '../../hooks'; -import { preloadSessionTask, SessionTask } from '../../lazyModules/components'; +import { preloadSessionTasks, SessionTasks } from '../../lazyModules/components'; import { Route, Switch, useRouter, VIRTUAL_ROUTER_BASE_PATH } from '../../router'; import { LazySignUpContinue, @@ -130,14 +130,12 @@ function SignInRoutes(): JSX.Element { > - {signInContext.withSessionTasks && ( - - - - )} + + + @@ -147,14 +145,9 @@ function SignInRoutes(): JSX.Element { )} - {signInContext.withSessionTasks && ( - - - - )} + + + @@ -170,7 +163,7 @@ const usePreloadSignUp = (enabled = false) => useFetch(enabled ? preloadSignUp : undefined, 'preloadComponent', { staleTime: Infinity }); const usePreloadSessionTask = (enabled = false) => - useFetch(enabled ? preloadSessionTask : undefined, 'preloadComponent', { staleTime: Infinity }); + useFetch(enabled ? preloadSessionTasks : undefined, 'preloadComponent', { staleTime: Infinity }); function SignInRoot() { const { __internal_setComponentNavigationContext } = useClerk(); @@ -193,9 +186,6 @@ function SignInRoot() { */ usePreloadSignUp(signInContext.isCombinedFlow); - // `experimental.withSessionTasks` will be removed soon in favor of checking via environment response - usePreloadSessionTask(signInContext.withSessionTasks); - React.useEffect(() => { return __internal_setComponentNavigationContext?.({ indexPath, navigate }); }, [indexPath, navigate]); diff --git a/packages/clerk-js/src/ui/components/SignUp/SignUp.tsx b/packages/clerk-js/src/ui/components/SignUp/SignUp.tsx index b883386727..283a8b8018 100644 --- a/packages/clerk-js/src/ui/components/SignUp/SignUp.tsx +++ b/packages/clerk-js/src/ui/components/SignUp/SignUp.tsx @@ -2,12 +2,11 @@ import { useClerk } from '@clerk/shared/react'; import type { SignUpModalProps, SignUpProps } from '@clerk/types'; import React from 'react'; -import { SESSION_TASK_ROUTE_BY_KEY } from '../../../core/sessionTasks'; import { SignUpEmailLinkFlowComplete } from '../../common/EmailLinkCompleteFlowCard'; import { SignUpContext, useSignUpContext, withCoreSessionSwitchGuard } from '../../contexts'; import { Flow } from '../../customizables'; import { useFetch } from '../../hooks'; -import { preloadSessionTask, SessionTask } from '../../lazyModules/components'; +import { preloadSessionTasks, SessionTasks } from '../../lazyModules/components'; import { Route, Switch, useRouter, VIRTUAL_ROUTER_BASE_PATH } from '../../router'; import { SignUpContinue } from './SignUpContinue'; import { SignUpSSOCallback } from './SignUpSSOCallback'; @@ -16,7 +15,7 @@ import { SignUpVerifyEmail } from './SignUpVerifyEmail'; import { SignUpVerifyPhone } from './SignUpVerifyPhone'; const usePreloadSessionTask = (enabled = false) => - useFetch(enabled ? preloadSessionTask : undefined, 'preloadComponent', { staleTime: Infinity }); + useFetch(enabled ? preloadSessionTasks : undefined, 'preloadComponent', { staleTime: Infinity }); function RedirectToSignUp() { const clerk = useClerk(); @@ -31,9 +30,6 @@ function SignUpRoutes(): JSX.Element { const { navigate, indexPath } = useRouter(); const signUpContext = useSignUpContext(); - // `experimental.withSessionTasks` will be removed soon in favor of checking via environment response - usePreloadSessionTask(signUpContext.withSessionTasks); - React.useEffect(() => { return __internal_setComponentNavigationContext?.({ indexPath, navigate }); }, [indexPath, navigate]); @@ -89,14 +85,9 @@ function SignUpRoutes(): JSX.Element { - {signUpContext.withSessionTasks && ( - - - - )} + + + diff --git a/packages/clerk-js/src/ui/contexts/components/SignIn.ts b/packages/clerk-js/src/ui/contexts/components/SignIn.ts index 3d5e77f50d..aa6603ce78 100644 --- a/packages/clerk-js/src/ui/contexts/components/SignIn.ts +++ b/packages/clerk-js/src/ui/contexts/components/SignIn.ts @@ -32,7 +32,6 @@ export type SignInContextType = SignInCtx & { emailLinkRedirectUrl: string; ssoCallbackUrl: string; isCombinedFlow: boolean; - withSessionTasks: boolean; }; export const SignInContext = createContext(null); @@ -145,6 +144,5 @@ export const useSignInContext = (): SignInContextType => { initialValues: { ...ctx.initialValues, ...initialValuesFromQueryParams }, authQueryString, isCombinedFlow, - withSessionTasks: !!options.experimental?.withSessionTasks, }; }; diff --git a/packages/clerk-js/src/ui/contexts/components/SignUp.ts b/packages/clerk-js/src/ui/contexts/components/SignUp.ts index 7d1d58f6f8..5f9be1727a 100644 --- a/packages/clerk-js/src/ui/contexts/components/SignUp.ts +++ b/packages/clerk-js/src/ui/contexts/components/SignUp.ts @@ -31,7 +31,6 @@ export type SignUpContextType = SignUpCtx & { isCombinedFlow: boolean; emailLinkRedirectUrl: string; ssoCallbackUrl: string; - withSessionTasks: boolean; }; export const SignUpContext = createContext(null); @@ -139,6 +138,5 @@ export const useSignUpContext = (): SignUpContextType => { initialValues: { ...ctx.initialValues, ...initialValuesFromQueryParams }, authQueryString, isCombinedFlow, - withSessionTasks: !!options.experimental?.withSessionTasks, }; }; diff --git a/packages/clerk-js/src/ui/lazyModules/components.ts b/packages/clerk-js/src/ui/lazyModules/components.ts index 6182576c71..d48c29e941 100644 --- a/packages/clerk-js/src/ui/lazyModules/components.ts +++ b/packages/clerk-js/src/ui/lazyModules/components.ts @@ -19,7 +19,7 @@ const componentImportPaths = { KeylessPrompt: () => import(/* webpackChunkName: "keylessPrompt" */ '../components/KeylessPrompt'), PricingTable: () => import(/* webpackChunkName: "pricingTable" */ '../components/PricingTable'), Checkout: () => import(/* webpackChunkName: "checkout" */ '../components/Checkout'), - SessionTask: () => import(/* webpackChunkName: "sessionTask" */ '../components/SessionTask'), + SessionTasks: () => import(/* webpackChunkName: "sessionTasks" */ '../components/SessionTasks'), } as const; export const SignIn = lazy(() => componentImportPaths.SignIn().then(module => ({ default: module.SignIn }))); @@ -95,9 +95,9 @@ export const PricingTable = lazy(() => componentImportPaths.PricingTable().then(module => ({ default: module.__experimental_PricingTable })), ); -export const preloadSessionTask = () => import(/* webpackChunkName: "sessionTask" */ '../components/SessionTask'); -export const SessionTask = lazy(() => - componentImportPaths.SessionTask().then(module => ({ default: module.SessionTask })), +export const preloadSessionTasks = () => import(/* webpackChunkName: "sessionTasks" */ '../components/SessionTasks'); +export const SessionTasks = lazy(() => + componentImportPaths.SessionTasks().then(module => ({ default: module.SessionTask })), ); export const preloadComponent = async (component: unknown) => { diff --git a/packages/types/src/clerk.ts b/packages/types/src/clerk.ts index ff19882dd3..5ff1e100ad 100644 --- a/packages/types/src/clerk.ts +++ b/packages/types/src/clerk.ts @@ -821,8 +821,6 @@ export type ClerkOptions = ClerkOptionsNavigation & */ rethrowOfflineNetworkErrors: boolean; commerce: boolean; - // `experimental.withSessionTasks` will be removed soon in favor of checking via environment response - withSessionTasks: boolean; }, Record >; From cd1f130e48465d3724fd88b3b5d5da2e17a7f506 Mon Sep 17 00:00:00 2001 From: Laura Beatris <48022589+LauraBeatris@users.noreply.github.com> Date: Fri, 21 Mar 2025 19:12:10 -0300 Subject: [PATCH 2/7] Extract tasks under `/tasks` root path --- .../SessionTasks/OrganizationSelectionTask.tsx | 18 ++++++++++++++++++ .../src/ui/components/SessionTasks/index.ts | 1 - .../{SessionTasks.tsx => index.tsx} | 15 ++++----------- .../SessionTasks/lazySessionTasks.ts | 12 ++++++++++++ .../components/SessionTasks/usePreloadTasks.ts | 14 ++++++++++++++ .../src/ui/components/SignIn/SignIn.tsx | 13 +++---------- .../src/ui/components/SignUp/SignUp.tsx | 6 +----- 7 files changed, 52 insertions(+), 27 deletions(-) create mode 100644 packages/clerk-js/src/ui/components/SessionTasks/OrganizationSelectionTask.tsx delete mode 100644 packages/clerk-js/src/ui/components/SessionTasks/index.ts rename packages/clerk-js/src/ui/components/SessionTasks/{SessionTasks.tsx => index.tsx} (76%) create mode 100644 packages/clerk-js/src/ui/components/SessionTasks/lazySessionTasks.ts create mode 100644 packages/clerk-js/src/ui/components/SessionTasks/usePreloadTasks.ts diff --git a/packages/clerk-js/src/ui/components/SessionTasks/OrganizationSelectionTask.tsx b/packages/clerk-js/src/ui/components/SessionTasks/OrganizationSelectionTask.tsx new file mode 100644 index 0000000000..2022e3b69b --- /dev/null +++ b/packages/clerk-js/src/ui/components/SessionTasks/OrganizationSelectionTask.tsx @@ -0,0 +1,18 @@ +import { OrganizationListContext } from '../../contexts'; +import { OrganizationList } from '../OrganizationList'; + +/** + * @internal + */ +export function OrganizationSelectionTask() { + return ( + + + + ); +} diff --git a/packages/clerk-js/src/ui/components/SessionTasks/index.ts b/packages/clerk-js/src/ui/components/SessionTasks/index.ts deleted file mode 100644 index f5840ac701..0000000000 --- a/packages/clerk-js/src/ui/components/SessionTasks/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './SessionTasks'; diff --git a/packages/clerk-js/src/ui/components/SessionTasks/SessionTasks.tsx b/packages/clerk-js/src/ui/components/SessionTasks/index.tsx similarity index 76% rename from packages/clerk-js/src/ui/components/SessionTasks/SessionTasks.tsx rename to packages/clerk-js/src/ui/components/SessionTasks/index.tsx index 6ef656357f..3f732effd7 100644 --- a/packages/clerk-js/src/ui/components/SessionTasks/SessionTasks.tsx +++ b/packages/clerk-js/src/ui/components/SessionTasks/index.tsx @@ -4,24 +4,16 @@ import type { SessionTask } from '@clerk/types'; import { useCallback, useEffect } from 'react'; import { SESSION_TASK_ROUTE_BY_KEY } from '../../../core/sessionTasks'; -import { OrganizationListContext } from '../../contexts'; import { SessionTaskContext as SessionTaskContext } from '../../contexts/components/SessionTask'; import { Route, Switch, useRouter } from '../../router'; -import { OrganizationList } from '../OrganizationList'; +import { LazyOrganizationSelectionTask } from './lazySessionTasks'; +import { usePreloadTasks } from './usePreloadTasks'; -// TODO -> Lazy load individual routes per environment config function SessionTaskRoutes(): JSX.Element { return ( - - - + ); @@ -31,6 +23,7 @@ function SessionTaskRoutes(): JSX.Element { * @internal */ export function SessionTask({ redirectUrlComplete }: { redirectUrlComplete: string }): JSX.Element { + usePreloadTasks(); const { __experimental_nextTask, session, telemetry } = useClerk(); const { navigate } = useRouter(); diff --git a/packages/clerk-js/src/ui/components/SessionTasks/lazySessionTasks.ts b/packages/clerk-js/src/ui/components/SessionTasks/lazySessionTasks.ts new file mode 100644 index 0000000000..75eb431c8e --- /dev/null +++ b/packages/clerk-js/src/ui/components/SessionTasks/lazySessionTasks.ts @@ -0,0 +1,12 @@ +import { lazy } from 'react'; + +export const preloadOrganizationSelectionTask = () => + import(/* webpackChunkName: "session-tasks"*/ './OrganizationSelectionTask'); + +const LazyOrganizationSelectionTask = lazy(() => + import(/* webpackChunkName: "session-tasks"*/ './OrganizationSelectionTask').then(module => ({ + default: module.OrganizationSelectionTask, + })), +); + +export { LazyOrganizationSelectionTask }; diff --git a/packages/clerk-js/src/ui/components/SessionTasks/usePreloadTasks.ts b/packages/clerk-js/src/ui/components/SessionTasks/usePreloadTasks.ts new file mode 100644 index 0000000000..4b9626094d --- /dev/null +++ b/packages/clerk-js/src/ui/components/SessionTasks/usePreloadTasks.ts @@ -0,0 +1,14 @@ +import { useEnvironment } from '../../../ui/contexts'; +import { preloadOrganizationSelectionTask } from './lazySessionTasks'; + +/** + * Preloads tasks based on the environment settings + * @internal + */ +export function usePreloadTasks() { + const { organizationSettings } = useEnvironment(); + + if (organizationSettings.forceOrganizationSelection) { + void preloadOrganizationSelectionTask(); + } +} diff --git a/packages/clerk-js/src/ui/components/SignIn/SignIn.tsx b/packages/clerk-js/src/ui/components/SignIn/SignIn.tsx index 1bede25f8f..0e6b2f5e5f 100644 --- a/packages/clerk-js/src/ui/components/SignIn/SignIn.tsx +++ b/packages/clerk-js/src/ui/components/SignIn/SignIn.tsx @@ -2,7 +2,6 @@ import { useClerk } from '@clerk/shared/react'; import type { SignInModalProps, SignInProps } from '@clerk/types'; import React from 'react'; -import { SESSION_TASK_ROUTE_BY_KEY } from '../../../core/sessionTasks'; import { normalizeRoutingOptions } from '../../../utils/normalizeRoutingOptions'; import { SignInEmailLinkFlowComplete, SignUpEmailLinkFlowComplete } from '../../common/EmailLinkCompleteFlowCard'; import type { SignUpContextType } from '../../contexts'; @@ -15,7 +14,7 @@ import { } from '../../contexts'; import { Flow } from '../../customizables'; import { useFetch } from '../../hooks'; -import { preloadSessionTasks, SessionTasks } from '../../lazyModules/components'; +import { SessionTasks } from '../../lazyModules/components'; import { Route, Switch, useRouter, VIRTUAL_ROUTER_BASE_PATH } from '../../router'; import { LazySignUpContinue, @@ -130,11 +129,8 @@ function SignInRoutes(): JSX.Element { > - - + + @@ -162,9 +158,6 @@ function SignInRoutes(): JSX.Element { const usePreloadSignUp = (enabled = false) => useFetch(enabled ? preloadSignUp : undefined, 'preloadComponent', { staleTime: Infinity }); -const usePreloadSessionTask = (enabled = false) => - useFetch(enabled ? preloadSessionTasks : undefined, 'preloadComponent', { staleTime: Infinity }); - function SignInRoot() { const { __internal_setComponentNavigationContext } = useClerk(); const { navigate, indexPath } = useRouter(); diff --git a/packages/clerk-js/src/ui/components/SignUp/SignUp.tsx b/packages/clerk-js/src/ui/components/SignUp/SignUp.tsx index 283a8b8018..c928c39a0e 100644 --- a/packages/clerk-js/src/ui/components/SignUp/SignUp.tsx +++ b/packages/clerk-js/src/ui/components/SignUp/SignUp.tsx @@ -5,8 +5,7 @@ import React from 'react'; import { SignUpEmailLinkFlowComplete } from '../../common/EmailLinkCompleteFlowCard'; import { SignUpContext, useSignUpContext, withCoreSessionSwitchGuard } from '../../contexts'; import { Flow } from '../../customizables'; -import { useFetch } from '../../hooks'; -import { preloadSessionTasks, SessionTasks } from '../../lazyModules/components'; +import { SessionTasks } from '../../lazyModules/components'; import { Route, Switch, useRouter, VIRTUAL_ROUTER_BASE_PATH } from '../../router'; import { SignUpContinue } from './SignUpContinue'; import { SignUpSSOCallback } from './SignUpSSOCallback'; @@ -14,9 +13,6 @@ import { SignUpStart } from './SignUpStart'; import { SignUpVerifyEmail } from './SignUpVerifyEmail'; import { SignUpVerifyPhone } from './SignUpVerifyPhone'; -const usePreloadSessionTask = (enabled = false) => - useFetch(enabled ? preloadSessionTasks : undefined, 'preloadComponent', { staleTime: Infinity }); - function RedirectToSignUp() { const clerk = useClerk(); React.useEffect(() => { From 0ca95f9484f96c2c7b8b5a3001ae37ed7ab72397 Mon Sep 17 00:00:00 2001 From: Laura Beatris <48022589+LauraBeatris@users.noreply.github.com> Date: Fri, 21 Mar 2025 19:16:01 -0300 Subject: [PATCH 3/7] Introduce bundle on `bundlewatch` --- packages/clerk-js/bundlewatch.config.json | 3 ++- packages/clerk-js/src/core/sessionTasks.ts | 2 +- packages/clerk-js/src/ui/common/redirects.ts | 3 +-- .../clerk-js/src/ui/components/SessionTasks/index.tsx | 10 ++++++---- .../SessionTasks/{lazySessionTasks.ts => lazyTasks.ts} | 2 +- .../src/ui/components/SessionTasks/usePreloadTasks.ts | 5 +++-- 6 files changed, 14 insertions(+), 11 deletions(-) rename packages/clerk-js/src/ui/components/SessionTasks/{lazySessionTasks.ts => lazyTasks.ts} (80%) diff --git a/packages/clerk-js/bundlewatch.config.json b/packages/clerk-js/bundlewatch.config.json index 659c6c18e7..8c26334f24 100644 --- a/packages/clerk-js/bundlewatch.config.json +++ b/packages/clerk-js/bundlewatch.config.json @@ -21,6 +21,7 @@ { "path": "./dist/keylessPrompt*.js", "maxSize": "5.9KB" }, { "path": "./dist/pricingTable*.js", "maxSize": "5KB" }, { "path": "./dist/checkout*.js", "maxSize": "9KB" }, - { "path": "./dist/up-billing-page*.js", "maxSize": "1KB" } + { "path": "./dist/up-billing-page*.js", "maxSize": "1KB" }, + { "path": "./dist/session-tasks*.js", "maxSize": "1KB" } ] } diff --git a/packages/clerk-js/src/core/sessionTasks.ts b/packages/clerk-js/src/core/sessionTasks.ts index f620508a50..ff0bb13b45 100644 --- a/packages/clerk-js/src/core/sessionTasks.ts +++ b/packages/clerk-js/src/core/sessionTasks.ts @@ -27,7 +27,7 @@ export function navigateToTask( routeKey: keyof typeof SESSION_TASK_ROUTE_BY_KEY, { componentNavigationContext, globalNavigate, options, environment }: NavigateToTaskOptions, ) { - const taskRoute = `/${SESSION_TASK_ROUTE_BY_KEY[routeKey]}`; + const taskRoute = `/tasks/${SESSION_TASK_ROUTE_BY_KEY[routeKey]}`; if (componentNavigationContext) { return componentNavigationContext.navigate(componentNavigationContext.indexPath + routeKey); diff --git a/packages/clerk-js/src/ui/common/redirects.ts b/packages/clerk-js/src/ui/common/redirects.ts index 6b785c9d69..763809bc7d 100644 --- a/packages/clerk-js/src/ui/common/redirects.ts +++ b/packages/clerk-js/src/ui/common/redirects.ts @@ -1,6 +1,5 @@ import type { SessionTask } from '@clerk/types'; -import { SESSION_TASK_ROUTE_BY_KEY } from '../../core/sessionTasks'; import { buildURL } from '../../utils/url'; import type { SignInContextType, SignUpContextType, UserProfileContextType } from './../contexts'; @@ -45,7 +44,7 @@ export function buildSessionTaskRedirectUrl({ routing, baseUrl, path, - endpoint: `/${SESSION_TASK_ROUTE_BY_KEY[task.key]}`, + endpoint: '/tasks', authQueryString: null, }); } diff --git a/packages/clerk-js/src/ui/components/SessionTasks/index.tsx b/packages/clerk-js/src/ui/components/SessionTasks/index.tsx index 3f732effd7..227b4a050c 100644 --- a/packages/clerk-js/src/ui/components/SessionTasks/index.tsx +++ b/packages/clerk-js/src/ui/components/SessionTasks/index.tsx @@ -6,7 +6,7 @@ import { useCallback, useEffect } from 'react'; import { SESSION_TASK_ROUTE_BY_KEY } from '../../../core/sessionTasks'; import { SessionTaskContext as SessionTaskContext } from '../../contexts/components/SessionTask'; import { Route, Switch, useRouter } from '../../router'; -import { LazyOrganizationSelectionTask } from './lazySessionTasks'; +import { LazyOrganizationSelectionTask } from './lazyTasks'; import { usePreloadTasks } from './usePreloadTasks'; function SessionTaskRoutes(): JSX.Element { @@ -24,18 +24,20 @@ function SessionTaskRoutes(): JSX.Element { */ export function SessionTask({ redirectUrlComplete }: { redirectUrlComplete: string }): JSX.Element { usePreloadTasks(); + const { __experimental_nextTask, session, telemetry } = useClerk(); const { navigate } = useRouter(); - telemetry?.record(eventComponentMounted('SessionTask', { task: session?.currentTask?.key as string })); + const task = session?.currentTask; useEffect(() => { - if (session?.currentTask) { + if (task) { + telemetry?.record(eventComponentMounted('SessionTask', { task: task.key })); return; } void navigate(redirectUrlComplete); - }, [session?.currentTask, navigate, redirectUrlComplete]); + }, [task, telemetry, navigate, redirectUrlComplete]); const nextTask = useCallback( () => __experimental_nextTask({ redirectUrlComplete }), diff --git a/packages/clerk-js/src/ui/components/SessionTasks/lazySessionTasks.ts b/packages/clerk-js/src/ui/components/SessionTasks/lazyTasks.ts similarity index 80% rename from packages/clerk-js/src/ui/components/SessionTasks/lazySessionTasks.ts rename to packages/clerk-js/src/ui/components/SessionTasks/lazyTasks.ts index 75eb431c8e..990e47b4d9 100644 --- a/packages/clerk-js/src/ui/components/SessionTasks/lazySessionTasks.ts +++ b/packages/clerk-js/src/ui/components/SessionTasks/lazyTasks.ts @@ -1,7 +1,7 @@ import { lazy } from 'react'; export const preloadOrganizationSelectionTask = () => - import(/* webpackChunkName: "session-tasks"*/ './OrganizationSelectionTask'); + import(/* webpackChunkName: "session-tasks"*/ './OrganizationSelectionTask'); const LazyOrganizationSelectionTask = lazy(() => import(/* webpackChunkName: "session-tasks"*/ './OrganizationSelectionTask').then(module => ({ diff --git a/packages/clerk-js/src/ui/components/SessionTasks/usePreloadTasks.ts b/packages/clerk-js/src/ui/components/SessionTasks/usePreloadTasks.ts index 4b9626094d..b9c46279e6 100644 --- a/packages/clerk-js/src/ui/components/SessionTasks/usePreloadTasks.ts +++ b/packages/clerk-js/src/ui/components/SessionTasks/usePreloadTasks.ts @@ -1,5 +1,6 @@ import { useEnvironment } from '../../../ui/contexts'; -import { preloadOrganizationSelectionTask } from './lazySessionTasks'; +import { useFetch } from '../../../ui/hooks'; +import { preloadOrganizationSelectionTask } from './lazyTasks'; /** * Preloads tasks based on the environment settings @@ -9,6 +10,6 @@ export function usePreloadTasks() { const { organizationSettings } = useEnvironment(); if (organizationSettings.forceOrganizationSelection) { - void preloadOrganizationSelectionTask(); + void useFetch(preloadOrganizationSelectionTask, 'preloadComponent', { staleTime: Infinity }); } } From 4abb96d90f5c32b3516f95ff64ab847f65018d33 Mon Sep 17 00:00:00 2001 From: Laura Beatris <48022589+LauraBeatris@users.noreply.github.com> Date: Sun, 23 Mar 2025 14:05:28 -0300 Subject: [PATCH 4/7] Introduce root route to resolve tasks --- packages/clerk-js/bundlewatch.config.json | 2 +- .../clerk-js/src/core/__tests__/clerk.test.ts | 8 +- packages/clerk-js/src/core/sessionTasks.ts | 2 +- packages/clerk-js/src/ui/common/redirects.ts | 3 +- .../OrganizationList/OrganizationListPage.tsx | 8 +- .../OrganizationList/UserMembershipList.tsx | 8 +- .../OrganizationSelectionTask.tsx | 18 ----- .../src/ui/components/SessionTasks/index.tsx | 78 ++++++++++++++----- .../ui/components/SessionTasks/lazyTasks.ts | 12 --- .../SessionTasks/usePreloadTasks.ts | 15 ---- .../src/ui/components/SignIn/SignIn.tsx | 9 ++- .../src/ui/components/SignUp/SignUp.tsx | 7 +- .../src/ui/contexts/components/SessionTask.ts | 5 -- .../ui/contexts/components/SessionTasks.ts | 5 ++ .../clerk-js/src/ui/hooks/usePreloadTasks.ts | 20 +++++ .../clerk-js/src/ui/lazyModules/components.ts | 1 - packages/clerk-js/src/ui/types.ts | 4 +- .../clerk-js/src/utils/componentGuards.ts | 4 + 18 files changed, 119 insertions(+), 90 deletions(-) delete mode 100644 packages/clerk-js/src/ui/components/SessionTasks/OrganizationSelectionTask.tsx delete mode 100644 packages/clerk-js/src/ui/components/SessionTasks/lazyTasks.ts delete mode 100644 packages/clerk-js/src/ui/components/SessionTasks/usePreloadTasks.ts delete mode 100644 packages/clerk-js/src/ui/contexts/components/SessionTask.ts create mode 100644 packages/clerk-js/src/ui/contexts/components/SessionTasks.ts create mode 100644 packages/clerk-js/src/ui/hooks/usePreloadTasks.ts diff --git a/packages/clerk-js/bundlewatch.config.json b/packages/clerk-js/bundlewatch.config.json index 8c26334f24..6785631e12 100644 --- a/packages/clerk-js/bundlewatch.config.json +++ b/packages/clerk-js/bundlewatch.config.json @@ -22,6 +22,6 @@ { "path": "./dist/pricingTable*.js", "maxSize": "5KB" }, { "path": "./dist/checkout*.js", "maxSize": "9KB" }, { "path": "./dist/up-billing-page*.js", "maxSize": "1KB" }, - { "path": "./dist/session-tasks*.js", "maxSize": "1KB" } + { "path": "./dist/sessionTasks*.js", "maxSize": "1KB" } ] } diff --git a/packages/clerk-js/src/core/__tests__/clerk.test.ts b/packages/clerk-js/src/core/__tests__/clerk.test.ts index 50c34e563d..c2f550c3db 100644 --- a/packages/clerk-js/src/core/__tests__/clerk.test.ts +++ b/packages/clerk-js/src/core/__tests__/clerk.test.ts @@ -486,14 +486,14 @@ describe('Clerk singleton', () => { getToken: jest.fn(), lastActiveToken: { getRawString: () => 'mocked-token' }, tasks: [{ key: 'org' }], - currentTask: { key: 'org', __internal_getUrl: () => 'https://foocorp.com/add-organization' }, + currentTask: { key: 'org', __internal_getUrl: () => 'https://sut/tasks/add-organization' }, reload: jest.fn(() => Promise.resolve({ id: '1', status: 'pending', user: {}, tasks: [{ key: 'org' }], - currentTask: { key: 'org', __internal_getUrl: () => 'https://foocorp.com/add-organization' }, + currentTask: { key: 'org', __internal_getUrl: () => 'https://sut/tasks/add-organization' }, }), ), }; @@ -2287,7 +2287,7 @@ describe('Clerk singleton', () => { status: 'pending', user: {}, tasks: [{ key: 'org' }], - currentTask: { key: 'org', __internal_getUrl: () => 'https://foocorp.com/add-organization' }, + currentTask: { key: 'org', __internal_getUrl: () => 'https://sut/tasks/add-organization' }, lastActiveToken: { getRawString: () => 'mocked-token' }, }; @@ -2316,7 +2316,7 @@ describe('Clerk singleton', () => { await sut.setActive({ session: mockResource as any as PendingSessionResource }); await sut.__experimental_nextTask(); - expect(mockNavigate.mock.calls[0][0]).toBe('/sign-in#/add-organization'); + expect(mockNavigate.mock.calls[0][0]).toBe('/sign-in#/tasks/add-organization'); }); }); diff --git a/packages/clerk-js/src/core/sessionTasks.ts b/packages/clerk-js/src/core/sessionTasks.ts index ff0bb13b45..1971d68e87 100644 --- a/packages/clerk-js/src/core/sessionTasks.ts +++ b/packages/clerk-js/src/core/sessionTasks.ts @@ -30,7 +30,7 @@ export function navigateToTask( const taskRoute = `/tasks/${SESSION_TASK_ROUTE_BY_KEY[routeKey]}`; if (componentNavigationContext) { - return componentNavigationContext.navigate(componentNavigationContext.indexPath + routeKey); + return componentNavigationContext.navigate(componentNavigationContext.indexPath + taskRoute); } const signInUrl = options['signInUrl'] || environment.displayConfig.signInUrl; diff --git a/packages/clerk-js/src/ui/common/redirects.ts b/packages/clerk-js/src/ui/common/redirects.ts index 763809bc7d..088a02a023 100644 --- a/packages/clerk-js/src/ui/common/redirects.ts +++ b/packages/clerk-js/src/ui/common/redirects.ts @@ -1,5 +1,6 @@ import type { SessionTask } from '@clerk/types'; +import { SESSION_TASK_ROUTE_BY_KEY } from '../../core/sessionTasks'; import { buildURL } from '../../utils/url'; import type { SignInContextType, SignUpContextType, UserProfileContextType } from './../contexts'; @@ -44,7 +45,7 @@ export function buildSessionTaskRedirectUrl({ routing, baseUrl, path, - endpoint: '/tasks', + endpoint: `/tasks/${SESSION_TASK_ROUTE_BY_KEY[task.key]}`, authQueryString: null, }); } diff --git a/packages/clerk-js/src/ui/components/OrganizationList/OrganizationListPage.tsx b/packages/clerk-js/src/ui/components/OrganizationList/OrganizationListPage.tsx index d932090e52..4a5963fc20 100644 --- a/packages/clerk-js/src/ui/components/OrganizationList/OrganizationListPage.tsx +++ b/packages/clerk-js/src/ui/components/OrganizationList/OrganizationListPage.tsx @@ -2,7 +2,7 @@ import { useOrganizationList, useUser } from '@clerk/shared/react'; import { useContext, useState } from 'react'; import { useEnvironment, useOrganizationListContext } from '../../contexts'; -import { SessionTaskContext } from '../../contexts/components/SessionTask'; +import { SessionTasksContext } from '../../contexts/components/SessionTasks'; import { Box, Col, descriptors, Flex, localizationKeys, Spinner } from '../../customizables'; import { Action, Actions, Card, Header, useCardState, withCardStateProvider } from '../../elements'; import { useInView } from '../../hooks'; @@ -17,6 +17,8 @@ import { organizationListParams } from './utils'; const useOrganizationListInView = () => { const { userMemberships, userInvitations, userSuggestions } = useOrganizationList(organizationListParams); + console.log({ userMemberships }); + const { ref } = useInView({ threshold: 0, onChange: inView => { @@ -112,7 +114,7 @@ export const OrganizationListPage = withCardStateProvider(() => { const OrganizationListFlows = ({ showListInitially }: { showListInitially: boolean }) => { const { navigateAfterCreateOrganization, skipInvitationScreen, hideSlug } = useOrganizationListContext(); const [isCreateOrganizationFlow, setCreateOrganizationFlow] = useState(!showListInitially); - const sessionTaskContext = useContext(SessionTaskContext); + const sessionTasksContext = useContext(SessionTasksContext); return ( <> {!isCreateOrganizationFlow && ( @@ -127,7 +129,7 @@ const OrganizationListFlows = ({ showListInitially }: { showListInitially: boole > diff --git a/packages/clerk-js/src/ui/components/OrganizationList/UserMembershipList.tsx b/packages/clerk-js/src/ui/components/OrganizationList/UserMembershipList.tsx index fa4e36e73d..f2861af17a 100644 --- a/packages/clerk-js/src/ui/components/OrganizationList/UserMembershipList.tsx +++ b/packages/clerk-js/src/ui/components/OrganizationList/UserMembershipList.tsx @@ -3,7 +3,7 @@ import type { OrganizationResource } from '@clerk/types'; import { useContext } from 'react'; import { useOrganizationListContext } from '../../contexts'; -import { SessionTaskContext } from '../../contexts/components/SessionTask'; +import { SessionTasksContext } from '../../contexts/components/SessionTasks'; import { OrganizationPreview, PersonalWorkspacePreview, useCardState, withCardStateProvider } from '../../elements'; import { localizationKeys } from '../../localization'; import { OrganizationListPreviewButton, sharedMainIdentifierSx } from './shared'; @@ -12,7 +12,7 @@ export const MembershipPreview = withCardStateProvider((props: { organization: O const card = useCardState(); const { navigateAfterSelectOrganization } = useOrganizationListContext(); const { isLoaded, setActive } = useOrganizationList(); - const sessionTaskContext = useContext(SessionTaskContext); + const sessionTasksContext = useContext(SessionTasksContext); if (!isLoaded) { return null; @@ -23,8 +23,8 @@ export const MembershipPreview = withCardStateProvider((props: { organization: O organization, }); - if (sessionTaskContext?.nextTask) { - return sessionTaskContext?.nextTask(); + if (sessionTasksContext?.nextTask) { + return sessionTasksContext?.nextTask(); } await navigateAfterSelectOrganization(organization); diff --git a/packages/clerk-js/src/ui/components/SessionTasks/OrganizationSelectionTask.tsx b/packages/clerk-js/src/ui/components/SessionTasks/OrganizationSelectionTask.tsx deleted file mode 100644 index 2022e3b69b..0000000000 --- a/packages/clerk-js/src/ui/components/SessionTasks/OrganizationSelectionTask.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { OrganizationListContext } from '../../contexts'; -import { OrganizationList } from '../OrganizationList'; - -/** - * @internal - */ -export function OrganizationSelectionTask() { - return ( - - - - ); -} diff --git a/packages/clerk-js/src/ui/components/SessionTasks/index.tsx b/packages/clerk-js/src/ui/components/SessionTasks/index.tsx index 227b4a050c..5dbb574c00 100644 --- a/packages/clerk-js/src/ui/components/SessionTasks/index.tsx +++ b/packages/clerk-js/src/ui/components/SessionTasks/index.tsx @@ -1,19 +1,58 @@ import { useClerk } from '@clerk/shared/react'; import { eventComponentMounted } from '@clerk/shared/telemetry'; import type { SessionTask } from '@clerk/types'; -import { useCallback, useEffect } from 'react'; +import { useCallback, useContext, useEffect } from 'react'; import { SESSION_TASK_ROUTE_BY_KEY } from '../../../core/sessionTasks'; -import { SessionTaskContext as SessionTaskContext } from '../../contexts/components/SessionTask'; +import { OrganizationListContext, SignInContext, SignUpContext } from '../../../ui/contexts'; +import { Card, LoadingCardContainer, withCardStateProvider } from '../../../ui/elements'; +import { SessionTasksContext as SessionTasksContext } from '../../contexts/components/SessionTasks'; import { Route, Switch, useRouter } from '../../router'; -import { LazyOrganizationSelectionTask } from './lazyTasks'; -import { usePreloadTasks } from './usePreloadTasks'; +import { OrganizationList } from '../OrganizationList'; + +const SessionTasksStart = withCardStateProvider(() => { + const clerk = useClerk(); + const { navigate } = useRouter(); + + useEffect(() => { + const timeoutId = setTimeout(() => { + void clerk.session?.reload().then(session => { + if (!session.currentTask?.key) { + void navigate(clerk.buildAfterSignInUrl()); + return; + } + + void navigate(SESSION_TASK_ROUTE_BY_KEY[session.currentTask?.key]); + }); + }, 1000); + return () => clearTimeout(timeoutId); + }, [navigate, clerk]); + + return ( + + + + + + + ); +}); function SessionTaskRoutes(): JSX.Element { return ( - + + + + + + ); @@ -22,31 +61,34 @@ function SessionTaskRoutes(): JSX.Element { /** * @internal */ -export function SessionTask({ redirectUrlComplete }: { redirectUrlComplete: string }): JSX.Element { - usePreloadTasks(); - - const { __experimental_nextTask, session, telemetry } = useClerk(); +export function SessionTask(): JSX.Element { + const clerk = useClerk(); const { navigate } = useRouter(); + const signInContext = useContext(SignInContext); + const signUpContext = useContext(SignUpContext); - const task = session?.currentTask; + const redirectUrlComplete = + signInContext?.afterSignInUrl ?? signUpContext?.afterSignUpUrl ?? clerk?.buildAfterSignInUrl(); useEffect(() => { - if (task) { - telemetry?.record(eventComponentMounted('SessionTask', { task: task.key })); + const task = clerk.session?.currentTask; + + if (!task) { + void navigate(redirectUrlComplete); return; } - void navigate(redirectUrlComplete); - }, [task, telemetry, navigate, redirectUrlComplete]); + clerk.telemetry?.record(eventComponentMounted('SessionTask', { task: task.key })); + }, [clerk, navigate, redirectUrlComplete]); const nextTask = useCallback( - () => __experimental_nextTask({ redirectUrlComplete }), - [__experimental_nextTask, redirectUrlComplete], + () => clerk.__experimental_nextTask({ redirectUrlComplete: redirectUrlComplete }), + [clerk, redirectUrlComplete], ); return ( - + - + ); } diff --git a/packages/clerk-js/src/ui/components/SessionTasks/lazyTasks.ts b/packages/clerk-js/src/ui/components/SessionTasks/lazyTasks.ts deleted file mode 100644 index 990e47b4d9..0000000000 --- a/packages/clerk-js/src/ui/components/SessionTasks/lazyTasks.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { lazy } from 'react'; - -export const preloadOrganizationSelectionTask = () => - import(/* webpackChunkName: "session-tasks"*/ './OrganizationSelectionTask'); - -const LazyOrganizationSelectionTask = lazy(() => - import(/* webpackChunkName: "session-tasks"*/ './OrganizationSelectionTask').then(module => ({ - default: module.OrganizationSelectionTask, - })), -); - -export { LazyOrganizationSelectionTask }; diff --git a/packages/clerk-js/src/ui/components/SessionTasks/usePreloadTasks.ts b/packages/clerk-js/src/ui/components/SessionTasks/usePreloadTasks.ts deleted file mode 100644 index b9c46279e6..0000000000 --- a/packages/clerk-js/src/ui/components/SessionTasks/usePreloadTasks.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { useEnvironment } from '../../../ui/contexts'; -import { useFetch } from '../../../ui/hooks'; -import { preloadOrganizationSelectionTask } from './lazyTasks'; - -/** - * Preloads tasks based on the environment settings - * @internal - */ -export function usePreloadTasks() { - const { organizationSettings } = useEnvironment(); - - if (organizationSettings.forceOrganizationSelection) { - void useFetch(preloadOrganizationSelectionTask, 'preloadComponent', { staleTime: Infinity }); - } -} diff --git a/packages/clerk-js/src/ui/components/SignIn/SignIn.tsx b/packages/clerk-js/src/ui/components/SignIn/SignIn.tsx index 0e6b2f5e5f..c2aaa0442b 100644 --- a/packages/clerk-js/src/ui/components/SignIn/SignIn.tsx +++ b/packages/clerk-js/src/ui/components/SignIn/SignIn.tsx @@ -2,6 +2,7 @@ import { useClerk } from '@clerk/shared/react'; import type { SignInModalProps, SignInProps } from '@clerk/types'; import React from 'react'; +import { SessionTasks } from '../../../ui/lazyModules/components'; import { normalizeRoutingOptions } from '../../../utils/normalizeRoutingOptions'; import { SignInEmailLinkFlowComplete, SignUpEmailLinkFlowComplete } from '../../common/EmailLinkCompleteFlowCard'; import type { SignUpContextType } from '../../contexts'; @@ -14,7 +15,7 @@ import { } from '../../contexts'; import { Flow } from '../../customizables'; import { useFetch } from '../../hooks'; -import { SessionTasks } from '../../lazyModules/components'; +import { usePreloadTasks } from '../../hooks/usePreloadTasks'; import { Route, Switch, useRouter, VIRTUAL_ROUTER_BASE_PATH } from '../../router'; import { LazySignUpContinue, @@ -130,7 +131,7 @@ function SignInRoutes(): JSX.Element { - + @@ -142,7 +143,7 @@ function SignInRoutes(): JSX.Element { )} - + @@ -179,6 +180,8 @@ function SignInRoot() { */ usePreloadSignUp(signInContext.isCombinedFlow); + usePreloadTasks(); + React.useEffect(() => { return __internal_setComponentNavigationContext?.({ indexPath, navigate }); }, [indexPath, navigate]); diff --git a/packages/clerk-js/src/ui/components/SignUp/SignUp.tsx b/packages/clerk-js/src/ui/components/SignUp/SignUp.tsx index c928c39a0e..7d2259ddd5 100644 --- a/packages/clerk-js/src/ui/components/SignUp/SignUp.tsx +++ b/packages/clerk-js/src/ui/components/SignUp/SignUp.tsx @@ -2,10 +2,11 @@ import { useClerk } from '@clerk/shared/react'; import type { SignUpModalProps, SignUpProps } from '@clerk/types'; import React from 'react'; +import { SessionTasks } from '../../../ui/lazyModules/components'; import { SignUpEmailLinkFlowComplete } from '../../common/EmailLinkCompleteFlowCard'; import { SignUpContext, useSignUpContext, withCoreSessionSwitchGuard } from '../../contexts'; import { Flow } from '../../customizables'; -import { SessionTasks } from '../../lazyModules/components'; +import { usePreloadTasks } from '../../hooks/usePreloadTasks'; import { Route, Switch, useRouter, VIRTUAL_ROUTER_BASE_PATH } from '../../router'; import { SignUpContinue } from './SignUpContinue'; import { SignUpSSOCallback } from './SignUpSSOCallback'; @@ -22,6 +23,8 @@ function RedirectToSignUp() { } function SignUpRoutes(): JSX.Element { + usePreloadTasks(); + const { __internal_setComponentNavigationContext } = useClerk(); const { navigate, indexPath } = useRouter(); const signUpContext = useSignUpContext(); @@ -82,7 +85,7 @@ function SignUpRoutes(): JSX.Element { - + diff --git a/packages/clerk-js/src/ui/contexts/components/SessionTask.ts b/packages/clerk-js/src/ui/contexts/components/SessionTask.ts deleted file mode 100644 index c2b0afa4f2..0000000000 --- a/packages/clerk-js/src/ui/contexts/components/SessionTask.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { createContext } from 'react'; - -import type { SessionTaskCtx } from '../../types'; - -export const SessionTaskContext = createContext(null); diff --git a/packages/clerk-js/src/ui/contexts/components/SessionTasks.ts b/packages/clerk-js/src/ui/contexts/components/SessionTasks.ts new file mode 100644 index 0000000000..02f5d38a51 --- /dev/null +++ b/packages/clerk-js/src/ui/contexts/components/SessionTasks.ts @@ -0,0 +1,5 @@ +import { createContext } from 'react'; + +import type { SessionTasksCtx } from '../../types'; + +export const SessionTasksContext = createContext(null); diff --git a/packages/clerk-js/src/ui/hooks/usePreloadTasks.ts b/packages/clerk-js/src/ui/hooks/usePreloadTasks.ts new file mode 100644 index 0000000000..d43a98eded --- /dev/null +++ b/packages/clerk-js/src/ui/hooks/usePreloadTasks.ts @@ -0,0 +1,20 @@ +import { useEnvironment } from '../contexts'; +import { useFetch } from '.'; + +/** + * Preloads tasks based on the environment settings + * @internal + */ +export function usePreloadTasks() { + const { organizationSettings } = useEnvironment(); + + const hasTasks = organizationSettings.forceOrganizationSelection; + + void useFetch( + hasTasks ? () => import(/* webpackChunkName: "sessionTasks" */ '../components/SessionTasks') : undefined, + 'preloadComponent', + { + staleTime: Infinity, + }, + ); +} diff --git a/packages/clerk-js/src/ui/lazyModules/components.ts b/packages/clerk-js/src/ui/lazyModules/components.ts index d48c29e941..4ce33dc78c 100644 --- a/packages/clerk-js/src/ui/lazyModules/components.ts +++ b/packages/clerk-js/src/ui/lazyModules/components.ts @@ -95,7 +95,6 @@ export const PricingTable = lazy(() => componentImportPaths.PricingTable().then(module => ({ default: module.__experimental_PricingTable })), ); -export const preloadSessionTasks = () => import(/* webpackChunkName: "sessionTasks" */ '../components/SessionTasks'); export const SessionTasks = lazy(() => componentImportPaths.SessionTasks().then(module => ({ default: module.SessionTask })), ); diff --git a/packages/clerk-js/src/ui/types.ts b/packages/clerk-js/src/ui/types.ts index 338b9d0ed8..0d7d028ef7 100644 --- a/packages/clerk-js/src/ui/types.ts +++ b/packages/clerk-js/src/ui/types.ts @@ -112,8 +112,8 @@ export type __experimental_CheckoutCtx = __experimental_CheckoutProps & { setIsOpen?: (open: boolean) => void; }; -export type SessionTaskCtx = { - nextTask: () => void; +export type SessionTasksCtx = { + nextTask: () => Promise; }; export type AvailableComponentCtx = diff --git a/packages/clerk-js/src/utils/componentGuards.ts b/packages/clerk-js/src/utils/componentGuards.ts index f0084a6a47..4af36e16d5 100644 --- a/packages/clerk-js/src/utils/componentGuards.ts +++ b/packages/clerk-js/src/utils/componentGuards.ts @@ -10,6 +10,10 @@ export const sessionExistsAndSingleSessionModeEnabled: ComponentGuard = (clerk, return !!(clerk.session && environment?.authConfig.singleSessionMode); }; +export const noSessionExists: ComponentGuard = clerk => { + return !clerk.isSignedIn; +}; + export const noUserExists: ComponentGuard = clerk => { return !clerk.user; }; From 6e7d003dc084fca88c558445e1323a68a3f3fb47 Mon Sep 17 00:00:00 2001 From: Laura Beatris <48022589+LauraBeatris@users.noreply.github.com> Date: Sun, 23 Mar 2025 19:53:59 -0300 Subject: [PATCH 5/7] Add changeset --- .changeset/lazy-impalas-clean.md | 6 +++++ .../OrganizationList/OrganizationListPage.tsx | 2 -- .../src/ui/components/SessionTasks/index.tsx | 24 +++++++++---------- .../ui/contexts/components/SessionTasks.ts | 12 +++++++++- packages/clerk-js/src/ui/types.ts | 1 + .../clerk-js/src/utils/componentGuards.ts | 4 ---- packages/types/src/clerk.ts | 2 +- 7 files changed, 30 insertions(+), 21 deletions(-) create mode 100644 .changeset/lazy-impalas-clean.md diff --git a/.changeset/lazy-impalas-clean.md b/.changeset/lazy-impalas-clean.md new file mode 100644 index 0000000000..9aab34ce78 --- /dev/null +++ b/.changeset/lazy-impalas-clean.md @@ -0,0 +1,6 @@ +--- +'@clerk/clerk-js': patch +'@clerk/types': patch +--- + +Load tasks based on environment settings diff --git a/packages/clerk-js/src/ui/components/OrganizationList/OrganizationListPage.tsx b/packages/clerk-js/src/ui/components/OrganizationList/OrganizationListPage.tsx index 4a5963fc20..d8d2404dbc 100644 --- a/packages/clerk-js/src/ui/components/OrganizationList/OrganizationListPage.tsx +++ b/packages/clerk-js/src/ui/components/OrganizationList/OrganizationListPage.tsx @@ -17,8 +17,6 @@ import { organizationListParams } from './utils'; const useOrganizationListInView = () => { const { userMemberships, userInvitations, userSuggestions } = useOrganizationList(organizationListParams); - console.log({ userMemberships }); - const { ref } = useInView({ threshold: 0, onChange: inView => { diff --git a/packages/clerk-js/src/ui/components/SessionTasks/index.tsx b/packages/clerk-js/src/ui/components/SessionTasks/index.tsx index 5dbb574c00..dc97a5cb0f 100644 --- a/packages/clerk-js/src/ui/components/SessionTasks/index.tsx +++ b/packages/clerk-js/src/ui/components/SessionTasks/index.tsx @@ -6,27 +6,25 @@ import { useCallback, useContext, useEffect } from 'react'; import { SESSION_TASK_ROUTE_BY_KEY } from '../../../core/sessionTasks'; import { OrganizationListContext, SignInContext, SignUpContext } from '../../../ui/contexts'; import { Card, LoadingCardContainer, withCardStateProvider } from '../../../ui/elements'; -import { SessionTasksContext as SessionTasksContext } from '../../contexts/components/SessionTasks'; +import { + SessionTasksContext as SessionTasksContext, + useSessionTasksContext, +} from '../../contexts/components/SessionTasks'; import { Route, Switch, useRouter } from '../../router'; import { OrganizationList } from '../OrganizationList'; const SessionTasksStart = withCardStateProvider(() => { const clerk = useClerk(); const { navigate } = useRouter(); + const { redirectUrlComplete } = useSessionTasksContext(); useEffect(() => { + // Simulates additional latency to avoid a abrupt UI transition when navigating to the next task const timeoutId = setTimeout(() => { - void clerk.session?.reload().then(session => { - if (!session.currentTask?.key) { - void navigate(clerk.buildAfterSignInUrl()); - return; - } - - void navigate(SESSION_TASK_ROUTE_BY_KEY[session.currentTask?.key]); - }); - }, 1000); + void clerk.__experimental_nextTask({ redirectUrlComplete }); + }, 500); return () => clearTimeout(timeoutId); - }, [navigate, clerk]); + }, [navigate, clerk, redirectUrlComplete]); return ( @@ -82,12 +80,12 @@ export function SessionTask(): JSX.Element { }, [clerk, navigate, redirectUrlComplete]); const nextTask = useCallback( - () => clerk.__experimental_nextTask({ redirectUrlComplete: redirectUrlComplete }), + () => clerk.__experimental_nextTask({ redirectUrlComplete }), [clerk, redirectUrlComplete], ); return ( - + ); diff --git a/packages/clerk-js/src/ui/contexts/components/SessionTasks.ts b/packages/clerk-js/src/ui/contexts/components/SessionTasks.ts index 02f5d38a51..1c9e0be6c5 100644 --- a/packages/clerk-js/src/ui/contexts/components/SessionTasks.ts +++ b/packages/clerk-js/src/ui/contexts/components/SessionTasks.ts @@ -1,5 +1,15 @@ -import { createContext } from 'react'; +import { createContext, useContext } from 'react'; import type { SessionTasksCtx } from '../../types'; export const SessionTasksContext = createContext(null); + +export const useSessionTasksContext = () => { + const context = useContext(SessionTasksContext); + + if (context === null) { + throw new Error('Clerk: useSessionTasksContext called outside of the mounted SessionTasks component.'); + } + + return context; +}; diff --git a/packages/clerk-js/src/ui/types.ts b/packages/clerk-js/src/ui/types.ts index 0d7d028ef7..feac0ee05f 100644 --- a/packages/clerk-js/src/ui/types.ts +++ b/packages/clerk-js/src/ui/types.ts @@ -114,6 +114,7 @@ export type __experimental_CheckoutCtx = __experimental_CheckoutProps & { export type SessionTasksCtx = { nextTask: () => Promise; + redirectUrlComplete?: string; }; export type AvailableComponentCtx = diff --git a/packages/clerk-js/src/utils/componentGuards.ts b/packages/clerk-js/src/utils/componentGuards.ts index 4af36e16d5..f0084a6a47 100644 --- a/packages/clerk-js/src/utils/componentGuards.ts +++ b/packages/clerk-js/src/utils/componentGuards.ts @@ -10,10 +10,6 @@ export const sessionExistsAndSingleSessionModeEnabled: ComponentGuard = (clerk, return !!(clerk.session && environment?.authConfig.singleSessionMode); }; -export const noSessionExists: ComponentGuard = clerk => { - return !clerk.isSignedIn; -}; - export const noUserExists: ComponentGuard = clerk => { return !clerk.user; }; diff --git a/packages/types/src/clerk.ts b/packages/types/src/clerk.ts index 5ff1e100ad..844fac0794 100644 --- a/packages/types/src/clerk.ts +++ b/packages/types/src/clerk.ts @@ -644,7 +644,7 @@ export interface Clerk { * If all tasks are complete, it navigates to the provided completion URL. * @experimental */ - __experimental_nextTask: (params: NextTaskParams) => Promise; + __experimental_nextTask: (params?: NextTaskParams) => Promise; /** * This is an optional function. From 3f7f80b0c87a34e967edf252ff2a986517870697 Mon Sep 17 00:00:00 2001 From: Laura Beatris <48022589+LauraBeatris@users.noreply.github.com> Date: Wed, 26 Mar 2025 12:45:53 -0300 Subject: [PATCH 6/7] Rename `SessionTasks` imports to `LazySessionTasks` --- packages/clerk-js/src/ui/components/SignIn/SignIn.tsx | 6 +++--- packages/clerk-js/src/ui/components/SignUp/SignUp.tsx | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/clerk-js/src/ui/components/SignIn/SignIn.tsx b/packages/clerk-js/src/ui/components/SignIn/SignIn.tsx index c2aaa0442b..7bb9a3316a 100644 --- a/packages/clerk-js/src/ui/components/SignIn/SignIn.tsx +++ b/packages/clerk-js/src/ui/components/SignIn/SignIn.tsx @@ -2,7 +2,7 @@ import { useClerk } from '@clerk/shared/react'; import type { SignInModalProps, SignInProps } from '@clerk/types'; import React from 'react'; -import { SessionTasks } from '../../../ui/lazyModules/components'; +import { SessionTasks as LazySessionTasks } from '../../../ui/lazyModules/components'; import { normalizeRoutingOptions } from '../../../utils/normalizeRoutingOptions'; import { SignInEmailLinkFlowComplete, SignUpEmailLinkFlowComplete } from '../../common/EmailLinkCompleteFlowCard'; import type { SignUpContextType } from '../../contexts'; @@ -131,7 +131,7 @@ function SignInRoutes(): JSX.Element { - + @@ -143,7 +143,7 @@ function SignInRoutes(): JSX.Element { )} - + diff --git a/packages/clerk-js/src/ui/components/SignUp/SignUp.tsx b/packages/clerk-js/src/ui/components/SignUp/SignUp.tsx index 7d2259ddd5..8668ee07dc 100644 --- a/packages/clerk-js/src/ui/components/SignUp/SignUp.tsx +++ b/packages/clerk-js/src/ui/components/SignUp/SignUp.tsx @@ -2,7 +2,7 @@ import { useClerk } from '@clerk/shared/react'; import type { SignUpModalProps, SignUpProps } from '@clerk/types'; import React from 'react'; -import { SessionTasks } from '../../../ui/lazyModules/components'; +import { SessionTasks as LazySessionTasks } from '../../../ui/lazyModules/components'; import { SignUpEmailLinkFlowComplete } from '../../common/EmailLinkCompleteFlowCard'; import { SignUpContext, useSignUpContext, withCoreSessionSwitchGuard } from '../../contexts'; import { Flow } from '../../customizables'; @@ -85,7 +85,7 @@ function SignUpRoutes(): JSX.Element { - + From d772acf0cec25236db24b0793307d8956ed7d3ee Mon Sep 17 00:00:00 2001 From: Laura Beatris <48022589+LauraBeatris@users.noreply.github.com> Date: Wed, 26 Mar 2025 12:49:57 -0300 Subject: [PATCH 7/7] Update bundle max size --- packages/clerk-js/bundlewatch.config.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/clerk-js/bundlewatch.config.json b/packages/clerk-js/bundlewatch.config.json index 6785631e12..f747ecd60b 100644 --- a/packages/clerk-js/bundlewatch.config.json +++ b/packages/clerk-js/bundlewatch.config.json @@ -1,9 +1,9 @@ { "files": [ - { "path": "./dist/clerk.js", "maxSize": "580.5kB" }, + { "path": "./dist/clerk.js", "maxSize": "580.7kB" }, { "path": "./dist/clerk.browser.js", "maxSize": "79.25kB" }, { "path": "./dist/clerk.headless.js", "maxSize": "55KB" }, - { "path": "./dist/ui-common*.js", "maxSize": "94KB" }, + { "path": "./dist/ui-common*.js", "maxSize": "96KB" }, { "path": "./dist/vendors*.js", "maxSize": "30KB" }, { "path": "./dist/coinbase*.js", "maxSize": "35.5KB" }, { "path": "./dist/createorganization*.js", "maxSize": "5KB" },