Skip to content

Commit 7ced9f8

Browse files
committed
Introduce root route to resolve tasks
1 parent a8a6526 commit 7ced9f8

18 files changed

+119
-90
lines changed

packages/clerk-js/bundlewatch.config.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,6 @@
2222
{ "path": "./dist/pricingTable*.js", "maxSize": "5KB" },
2323
{ "path": "./dist/checkout*.js", "maxSize": "9KB" },
2424
{ "path": "./dist/up-billing-page*.js", "maxSize": "1KB" },
25-
{ "path": "./dist/session-tasks*.js", "maxSize": "1KB" }
25+
{ "path": "./dist/sessionTasks*.js", "maxSize": "1KB" }
2626
]
2727
}

packages/clerk-js/src/core/__tests__/clerk.test.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -486,14 +486,14 @@ describe('Clerk singleton', () => {
486486
getToken: jest.fn(),
487487
lastActiveToken: { getRawString: () => 'mocked-token' },
488488
tasks: [{ key: 'org' }],
489-
currentTask: { key: 'org', __internal_getUrl: () => 'https://foocorp.com/add-organization' },
489+
currentTask: { key: 'org', __internal_getUrl: () => 'https://sut/tasks/add-organization' },
490490
reload: jest.fn(() =>
491491
Promise.resolve({
492492
id: '1',
493493
status: 'pending',
494494
user: {},
495495
tasks: [{ key: 'org' }],
496-
currentTask: { key: 'org', __internal_getUrl: () => 'https://foocorp.com/add-organization' },
496+
currentTask: { key: 'org', __internal_getUrl: () => 'https://sut/tasks/add-organization' },
497497
}),
498498
),
499499
};
@@ -2276,7 +2276,7 @@ describe('Clerk singleton', () => {
22762276
status: 'pending',
22772277
user: {},
22782278
tasks: [{ key: 'org' }],
2279-
currentTask: { key: 'org', __internal_getUrl: () => 'https://foocorp.com/add-organization' },
2279+
currentTask: { key: 'org', __internal_getUrl: () => 'https://sut/tasks/add-organization' },
22802280
lastActiveToken: { getRawString: () => 'mocked-token' },
22812281
};
22822282

@@ -2305,7 +2305,7 @@ describe('Clerk singleton', () => {
23052305
await sut.setActive({ session: mockResource as any as PendingSessionResource });
23062306
await sut.__experimental_nextTask();
23072307

2308-
expect(mockNavigate.mock.calls[0][0]).toBe('/sign-in#/add-organization');
2308+
expect(mockNavigate.mock.calls[0][0]).toBe('/sign-in#/tasks/add-organization');
23092309
});
23102310
});
23112311

packages/clerk-js/src/core/sessionTasks.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export function navigateToTask(
3030
const taskRoute = `/tasks/${SESSION_TASK_ROUTE_BY_KEY[routeKey]}`;
3131

3232
if (componentNavigationContext) {
33-
return componentNavigationContext.navigate(componentNavigationContext.indexPath + routeKey);
33+
return componentNavigationContext.navigate(componentNavigationContext.indexPath + taskRoute);
3434
}
3535

3636
const signInUrl = options['signInUrl'] || environment.displayConfig.signInUrl;

packages/clerk-js/src/ui/common/redirects.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { SessionTask } from '@clerk/types';
22

3+
import { SESSION_TASK_ROUTE_BY_KEY } from '../../core/sessionTasks';
34
import { buildURL } from '../../utils/url';
45
import type { SignInContextType, SignUpContextType, UserProfileContextType } from './../contexts';
56

@@ -44,7 +45,7 @@ export function buildSessionTaskRedirectUrl({
4445
routing,
4546
baseUrl,
4647
path,
47-
endpoint: '/tasks',
48+
endpoint: `/tasks/${SESSION_TASK_ROUTE_BY_KEY[task.key]}`,
4849
authQueryString: null,
4950
});
5051
}

packages/clerk-js/src/ui/components/OrganizationList/OrganizationListPage.tsx

+5-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { useOrganizationList, useUser } from '@clerk/shared/react';
22
import { useContext, useState } from 'react';
33

44
import { useEnvironment, useOrganizationListContext } from '../../contexts';
5-
import { SessionTaskContext } from '../../contexts/components/SessionTask';
5+
import { SessionTasksContext } from '../../contexts/components/SessionTasks';
66
import { Box, Col, descriptors, Flex, localizationKeys, Spinner } from '../../customizables';
77
import { Action, Actions, Card, Header, useCardState, withCardStateProvider } from '../../elements';
88
import { useInView } from '../../hooks';
@@ -17,6 +17,8 @@ import { organizationListParams } from './utils';
1717
const useOrganizationListInView = () => {
1818
const { userMemberships, userInvitations, userSuggestions } = useOrganizationList(organizationListParams);
1919

20+
console.log({ userMemberships });
21+
2022
const { ref } = useInView({
2123
threshold: 0,
2224
onChange: inView => {
@@ -112,7 +114,7 @@ export const OrganizationListPage = withCardStateProvider(() => {
112114
const OrganizationListFlows = ({ showListInitially }: { showListInitially: boolean }) => {
113115
const { navigateAfterCreateOrganization, skipInvitationScreen, hideSlug } = useOrganizationListContext();
114116
const [isCreateOrganizationFlow, setCreateOrganizationFlow] = useState(!showListInitially);
115-
const sessionTaskContext = useContext(SessionTaskContext);
117+
const sessionTasksContext = useContext(SessionTasksContext);
116118
return (
117119
<>
118120
{!isCreateOrganizationFlow && (
@@ -127,7 +129,7 @@ const OrganizationListFlows = ({ showListInitially }: { showListInitially: boole
127129
>
128130
<CreateOrganizationForm
129131
flow='organizationList'
130-
onComplete={sessionTaskContext?.nextTask}
132+
onComplete={sessionTasksContext?.nextTask}
131133
startPage={{ headerTitle: localizationKeys('organizationList.createOrganization') }}
132134
skipInvitationScreen={skipInvitationScreen}
133135
navigateAfterCreateOrganization={org =>

packages/clerk-js/src/ui/components/OrganizationList/UserMembershipList.tsx

+4-4
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import type { OrganizationResource } from '@clerk/types';
33
import { useContext } from 'react';
44

55
import { useOrganizationListContext } from '../../contexts';
6-
import { SessionTaskContext } from '../../contexts/components/SessionTask';
6+
import { SessionTasksContext } from '../../contexts/components/SessionTasks';
77
import { OrganizationPreview, PersonalWorkspacePreview, useCardState, withCardStateProvider } from '../../elements';
88
import { localizationKeys } from '../../localization';
99
import { OrganizationListPreviewButton, sharedMainIdentifierSx } from './shared';
@@ -12,7 +12,7 @@ export const MembershipPreview = withCardStateProvider((props: { organization: O
1212
const card = useCardState();
1313
const { navigateAfterSelectOrganization } = useOrganizationListContext();
1414
const { isLoaded, setActive } = useOrganizationList();
15-
const sessionTaskContext = useContext(SessionTaskContext);
15+
const sessionTasksContext = useContext(SessionTasksContext);
1616

1717
if (!isLoaded) {
1818
return null;
@@ -23,8 +23,8 @@ export const MembershipPreview = withCardStateProvider((props: { organization: O
2323
organization,
2424
});
2525

26-
if (sessionTaskContext?.nextTask) {
27-
return sessionTaskContext?.nextTask();
26+
if (sessionTasksContext?.nextTask) {
27+
return sessionTasksContext?.nextTask();
2828
}
2929

3030
await navigateAfterSelectOrganization(organization);

packages/clerk-js/src/ui/components/SessionTasks/OrganizationSelectionTask.tsx

-18
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,58 @@
11
import { useClerk } from '@clerk/shared/react';
22
import { eventComponentMounted } from '@clerk/shared/telemetry';
33
import type { SessionTask } from '@clerk/types';
4-
import { useCallback, useEffect } from 'react';
4+
import { useCallback, useContext, useEffect } from 'react';
55

66
import { SESSION_TASK_ROUTE_BY_KEY } from '../../../core/sessionTasks';
7-
import { SessionTaskContext as SessionTaskContext } from '../../contexts/components/SessionTask';
7+
import { OrganizationListContext, SignInContext, SignUpContext } from '../../../ui/contexts';
8+
import { Card, LoadingCardContainer, withCardStateProvider } from '../../../ui/elements';
9+
import { SessionTasksContext as SessionTasksContext } from '../../contexts/components/SessionTasks';
810
import { Route, Switch, useRouter } from '../../router';
9-
import { LazyOrganizationSelectionTask } from './lazyTasks';
10-
import { usePreloadTasks } from './usePreloadTasks';
11+
import { OrganizationList } from '../OrganizationList';
12+
13+
const SessionTasksStart = withCardStateProvider(() => {
14+
const clerk = useClerk();
15+
const { navigate } = useRouter();
16+
17+
useEffect(() => {
18+
const timeoutId = setTimeout(() => {
19+
void clerk.session?.reload().then(session => {
20+
if (!session.currentTask?.key) {
21+
void navigate(clerk.buildAfterSignInUrl());
22+
return;
23+
}
24+
25+
void navigate(SESSION_TASK_ROUTE_BY_KEY[session.currentTask?.key]);
26+
});
27+
}, 1000);
28+
return () => clearTimeout(timeoutId);
29+
}, [navigate, clerk]);
30+
31+
return (
32+
<Card.Root>
33+
<Card.Content>
34+
<LoadingCardContainer />
35+
</Card.Content>
36+
<Card.Footer />
37+
</Card.Root>
38+
);
39+
});
1140

1241
function SessionTaskRoutes(): JSX.Element {
1342
return (
1443
<Switch>
1544
<Route path={SESSION_TASK_ROUTE_BY_KEY['org']}>
16-
<LazyOrganizationSelectionTask />
45+
<OrganizationListContext.Provider
46+
value={{
47+
componentName: 'OrganizationList',
48+
skipInvitationScreen: true,
49+
}}
50+
>
51+
<OrganizationList />
52+
</OrganizationListContext.Provider>
53+
</Route>
54+
<Route index>
55+
<SessionTasksStart />
1756
</Route>
1857
</Switch>
1958
);
@@ -22,31 +61,34 @@ function SessionTaskRoutes(): JSX.Element {
2261
/**
2362
* @internal
2463
*/
25-
export function SessionTask({ redirectUrlComplete }: { redirectUrlComplete: string }): JSX.Element {
26-
usePreloadTasks();
27-
28-
const { __experimental_nextTask, session, telemetry } = useClerk();
64+
export function SessionTask(): JSX.Element {
65+
const clerk = useClerk();
2966
const { navigate } = useRouter();
67+
const signInContext = useContext(SignInContext);
68+
const signUpContext = useContext(SignUpContext);
3069

31-
const task = session?.currentTask;
70+
const redirectUrlComplete =
71+
signInContext?.afterSignInUrl ?? signUpContext?.afterSignUpUrl ?? clerk?.buildAfterSignInUrl();
3272

3373
useEffect(() => {
34-
if (task) {
35-
telemetry?.record(eventComponentMounted('SessionTask', { task: task.key }));
74+
const task = clerk.session?.currentTask;
75+
76+
if (!task) {
77+
void navigate(redirectUrlComplete);
3678
return;
3779
}
3880

39-
void navigate(redirectUrlComplete);
40-
}, [task, telemetry, navigate, redirectUrlComplete]);
81+
clerk.telemetry?.record(eventComponentMounted('SessionTask', { task: task.key }));
82+
}, [clerk, navigate, redirectUrlComplete]);
4183

4284
const nextTask = useCallback(
43-
() => __experimental_nextTask({ redirectUrlComplete }),
44-
[__experimental_nextTask, redirectUrlComplete],
85+
() => clerk.__experimental_nextTask({ redirectUrlComplete: redirectUrlComplete }),
86+
[clerk, redirectUrlComplete],
4587
);
4688

4789
return (
48-
<SessionTaskContext.Provider value={{ nextTask }}>
90+
<SessionTasksContext.Provider value={{ nextTask }}>
4991
<SessionTaskRoutes />
50-
</SessionTaskContext.Provider>
92+
</SessionTasksContext.Provider>
5193
);
5294
}

packages/clerk-js/src/ui/components/SessionTasks/lazyTasks.ts

-12
This file was deleted.

packages/clerk-js/src/ui/components/SessionTasks/usePreloadTasks.ts

-15
This file was deleted.

packages/clerk-js/src/ui/components/SignIn/SignIn.tsx

+6-3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { useClerk } from '@clerk/shared/react';
22
import type { SignInModalProps, SignInProps } from '@clerk/types';
33
import React from 'react';
44

5+
import { SessionTasks } from '../../../ui/lazyModules/components';
56
import { normalizeRoutingOptions } from '../../../utils/normalizeRoutingOptions';
67
import { SignInEmailLinkFlowComplete, SignUpEmailLinkFlowComplete } from '../../common/EmailLinkCompleteFlowCard';
78
import type { SignUpContextType } from '../../contexts';
@@ -14,7 +15,7 @@ import {
1415
} from '../../contexts';
1516
import { Flow } from '../../customizables';
1617
import { useFetch } from '../../hooks';
17-
import { SessionTasks } from '../../lazyModules/components';
18+
import { usePreloadTasks } from '../../hooks/usePreloadTasks';
1819
import { Route, Switch, useRouter, VIRTUAL_ROUTER_BASE_PATH } from '../../router';
1920
import {
2021
LazySignUpContinue,
@@ -130,7 +131,7 @@ function SignInRoutes(): JSX.Element {
130131
<LazySignUpVerifyPhone />
131132
</Route>
132133
<Route path='tasks'>
133-
<SessionTasks redirectUrlComplete={signInContext.afterSignInUrl} />
134+
<SessionTasks />
134135
</Route>
135136
<Route index>
136137
<LazySignUpContinue />
@@ -142,7 +143,7 @@ function SignInRoutes(): JSX.Element {
142143
</Route>
143144
)}
144145
<Route path='tasks'>
145-
<SessionTasks redirectUrlComplete={signInContext.afterSignInUrl} />
146+
<SessionTasks />
146147
</Route>
147148
<Route index>
148149
<SignInStart />
@@ -179,6 +180,8 @@ function SignInRoot() {
179180
*/
180181
usePreloadSignUp(signInContext.isCombinedFlow);
181182

183+
usePreloadTasks();
184+
182185
React.useEffect(() => {
183186
return __internal_setComponentNavigationContext?.({ indexPath, navigate });
184187
}, [indexPath, navigate]);

packages/clerk-js/src/ui/components/SignUp/SignUp.tsx

+5-2
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ import { useClerk } from '@clerk/shared/react';
22
import type { SignUpModalProps, SignUpProps } from '@clerk/types';
33
import React from 'react';
44

5+
import { SessionTasks } from '../../../ui/lazyModules/components';
56
import { SignUpEmailLinkFlowComplete } from '../../common/EmailLinkCompleteFlowCard';
67
import { SignUpContext, useSignUpContext, withCoreSessionSwitchGuard } from '../../contexts';
78
import { Flow } from '../../customizables';
8-
import { SessionTasks } from '../../lazyModules/components';
9+
import { usePreloadTasks } from '../../hooks/usePreloadTasks';
910
import { Route, Switch, useRouter, VIRTUAL_ROUTER_BASE_PATH } from '../../router';
1011
import { SignUpContinue } from './SignUpContinue';
1112
import { SignUpSSOCallback } from './SignUpSSOCallback';
@@ -22,6 +23,8 @@ function RedirectToSignUp() {
2223
}
2324

2425
function SignUpRoutes(): JSX.Element {
26+
usePreloadTasks();
27+
2528
const { __internal_setComponentNavigationContext } = useClerk();
2629
const { navigate, indexPath } = useRouter();
2730
const signUpContext = useSignUpContext();
@@ -82,7 +85,7 @@ function SignUpRoutes(): JSX.Element {
8285
</Route>
8386
</Route>
8487
<Route path='tasks'>
85-
<SessionTasks redirectUrlComplete={signUpContext.afterSignUpUrl} />
88+
<SessionTasks />
8689
</Route>
8790
<Route index>
8891
<SignUpStart />

packages/clerk-js/src/ui/contexts/components/SessionTask.ts

-5
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { createContext } from 'react';
2+
3+
import type { SessionTasksCtx } from '../../types';
4+
5+
export const SessionTasksContext = createContext<SessionTasksCtx | null>(null);

0 commit comments

Comments
 (0)