Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .changeset/remove-deprecated-props.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
"@clerk/nextjs": major
"@clerk/clerk-react": major
"@clerk/clerk-js": major
"@clerk/shared": major
"@clerk/ui": major
"@clerk/react-router": major
"@clerk/tanstack-react-start": minor
---

Remove all previously deprecated UI props across the Next.js, React and clerk-js SDKs. The legacy `afterSign(In|Up)Url`/`redirectUrl` props, `UserButton` sign-out overrides, organization `hideSlug` flags, `OrganizationSwitcher`'s `afterSwitchOrganizationUrl`, `Client.activeSessions`, `setActive({ beforeEmit })`, and the `ClerkMiddlewareAuthObject` type alias are no longer exported. Components now rely solely on the new redirect options and server-side configuration.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { UserButton } from '@clerk/astro/components';
---

<UserButton afterSignOutUrl='/'>
<UserButton>
<UserButton.MenuItems>
<UserButton.Action label='signOut' />
<UserButton.Action label='manageAccount' />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,7 @@ import { LanguagePicker } from '../../components/LanguagePicker';
<LanguagePicker client:idle />

<SignedIn client:load>
<UserButton
client:load
afterSignOutUrl='/'
/>
<UserButton client:load />
</SignedIn>

<SignedOut client:load>
Expand Down
2 changes: 1 addition & 1 deletion integration/templates/react-cra/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ function App() {
<SignIn />
</SignedOut>
<SignedIn>Signed In</SignedIn>
<UserButton afterSignOutUrl={'/'} />
<UserButton />
</main>
);
}
Expand Down
2 changes: 1 addition & 1 deletion integration/templates/react-vite/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { ClientId } from './client-id';
function App() {
return (
<main>
<UserButton afterSignOutUrl={'/'} />
<UserButton />
<OrganizationSwitcher fallback={<>Loading organization switcher</>} />
<ClientId />
<SignedOut>SignedOut</SignedOut>
Expand Down
2 changes: 1 addition & 1 deletion packages/astro/src/stores/external.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export const $organizationStore = computed([$authStore], auth => auth.organizati
* It is a nanostore, for instructions on how to use nanostores please review the [documentation](https://github.com/nanostores/nanostores)
*
* @example
* $clientStore.subscribe((client) => console.log(client.activeSessions))
* $clientStore.subscribe((client) => console.log(client?.signedInSessions?.length))
*/
export const $clientStore = computed([$csrState], csr => csr.client);

Expand Down
104 changes: 1 addition & 103 deletions packages/clerk-js/src/core/__tests__/clerk.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,100 +246,6 @@ describe('Clerk singleton', () => {
await sut.setActive({ session: mockSession as any as ActiveSessionResource });
});

it('calls __unstable__onAfterSetActive after beforeEmit and session.touch', async () => {
const beforeEmitMock = vi.fn();
mockSession.touch.mockReturnValueOnce(Promise.resolve());
mockClientFetch.mockReturnValue(Promise.resolve({ signedInSessions: [mockSession] }));

(window as any).__unstable__onAfterSetActive = () => {
expect(mockSession.touch).toHaveBeenCalled();
expect(beforeEmitMock).toHaveBeenCalled();
};

const sut = new Clerk(productionPublishableKey);
await sut.load();
await sut.setActive({ session: mockSession as any as ActiveSessionResource, beforeEmit: beforeEmitMock });
});

// TODO: @dimkl include set transitive state
it('calls session.touch -> set cookie -> before emit with touched session on session switch', async () => {
const mockSession2 = {
id: '2',
remove: vi.fn(),
status: 'active',
user: {},
touch: vi.fn(),
getToken: vi.fn(),
};
mockClientFetch.mockReturnValue(
Promise.resolve({
signedInSessions: [mockSession, mockSession2],
}),
);

const sut = new Clerk(productionPublishableKey);
await sut.load();

const executionOrder: string[] = [];
mockSession2.touch.mockImplementationOnce(() => {
sut.session = mockSession2 as any;
executionOrder.push('session.touch');
return Promise.resolve();
});
mockSession2.getToken.mockImplementation(() => {
executionOrder.push('set cookie');
return 'mocked-token-2';
});
const beforeEmitMock = vi.fn().mockImplementationOnce(() => {
executionOrder.push('before emit');
return Promise.resolve();
});

await sut.setActive({ session: mockSession2 as any as ActiveSessionResource, beforeEmit: beforeEmitMock });

await waitFor(() => {
expect(executionOrder).toEqual(['session.touch', 'set cookie', 'before emit']);
expect(mockSession2.touch).toHaveBeenCalled();
expect(mockSession2.getToken).toHaveBeenCalled();
expect(beforeEmitMock).toHaveBeenCalledWith(mockSession2);
expect(sut.session).toMatchObject(mockSession2);
});
});

// TODO: @dimkl include set transitive state
it('calls with lastActiveOrganizationId session.touch -> set cookie -> before emit -> set accessors with touched session on organization switch', async () => {
mockClientFetch.mockReturnValue(Promise.resolve({ signedInSessions: [mockSession] }));
const sut = new Clerk(productionPublishableKey);
await sut.load();

const executionOrder: string[] = [];
mockSession.touch.mockImplementationOnce(() => {
sut.session = mockSession as any;
executionOrder.push('session.touch');
return Promise.resolve();
});
mockSession.getToken.mockImplementation(() => {
executionOrder.push('set cookie');
return 'mocked-token';
});

const beforeEmitMock = vi.fn().mockImplementationOnce(() => {
executionOrder.push('before emit');
return Promise.resolve();
});

await sut.setActive({ organization: { id: 'org_id' } as Organization, beforeEmit: beforeEmitMock });

await waitFor(() => {
expect(executionOrder).toEqual(['session.touch', 'set cookie', 'before emit']);
expect(mockSession.touch).toHaveBeenCalled();
expect(mockSession.getToken).toHaveBeenCalled();
expect((mockSession as any as ActiveSessionResource)?.lastActiveOrganizationId).toEqual('org_id');
expect(beforeEmitMock).toHaveBeenCalledWith(mockSession);
expect(sut.session).toMatchObject(mockSession);
});
});

it('sets active organization by slug', async () => {
const mockSession2 = {
id: '1',
Expand Down Expand Up @@ -465,24 +371,16 @@ describe('Clerk singleton', () => {
const sut = new Clerk(productionPublishableKey);
await sut.load({ standardBrowser: false });

const executionOrder: string[] = [];
mockSession.touch.mockImplementationOnce(() => {
sut.session = mockSession as any;
executionOrder.push('session.touch');
return Promise.resolve();
});
const beforeEmitMock = vi.fn().mockImplementationOnce(() => {
executionOrder.push('before emit');
return Promise.resolve();
});

await sut.setActive({ organization: { id: 'org_id' } as Organization, beforeEmit: beforeEmitMock });
await sut.setActive({ organization: { id: 'org_id' } as Organization });

expect(executionOrder).toEqual(['session.touch', 'before emit']);
expect(mockSession.touch).toHaveBeenCalled();
expect((mockSession as any as ActiveSessionResource)?.lastActiveOrganizationId).toEqual('org_id');
expect(mockSession.getToken).toHaveBeenCalled();
expect(beforeEmitMock).toHaveBeenCalledWith(mockSession);
expect(sut.session).toMatchObject(mockSession);
});
});
Expand Down
23 changes: 4 additions & 19 deletions packages/clerk-js/src/core/clerk.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { inBrowser as inClientSide, isValidBrowserOnline } from '@clerk/shared/browser';
import { clerkEvents, createClerkEventBus } from '@clerk/shared/clerkEventBus';
import { deprecated } from '@clerk/shared/deprecated';
import {
ClerkRuntimeError,
EmailLinkError,
Expand All @@ -9,7 +8,6 @@ import {
isClerkAPIResponseError,
isClerkRuntimeError,
} from '@clerk/shared/error';
import { assertNoLegacyProp } from '@clerk/shared/internal/clerk-js/assertNoLegacyProp';
import {
disabledAllAPIKeysFeatures,
disabledAllBillingFeatures,
Expand Down Expand Up @@ -496,8 +494,6 @@ export class Clerk implements ClerkInterface {
this.#emit();
});

assertNoLegacyProp(this.#options);

if (this.#options.sdkMetadata) {
Clerk.sdkMetadata = this.#options.sdkMetadata;
}
Expand Down Expand Up @@ -1300,7 +1296,7 @@ export class Clerk implements ClerkInterface {
* `setActive` can be used to set the active session and/or organization.
*/
public setActive = async (params: SetActiveParams): Promise<void> => {
const { organization, beforeEmit, redirectUrl, navigate: setActiveNavigate } = params;
const { organization, redirectUrl, navigate: setActiveNavigate } = params;
let { session } = params;
this.__internal_setActiveInProgress = true;
debugLogger.debug(
Expand Down Expand Up @@ -1405,29 +1401,18 @@ export class Clerk implements ClerkInterface {
eventBus.emit(events.TokenUpdate, { token: null });
}

//2. If there's a beforeEmit, typically we're navigating. Emit the session as
// undefined, then wait for beforeEmit to complete before emitting the new session.
//2. When navigation is required we emit the session as undefined,
// then wait for navigation to finish before emitting the new session.
// When undefined, neither SignedIn nor SignedOut renders, which avoids flickers or
// automatic reloading when reloading shouldn't be happening.
const tracker = createBeforeUnloadTracker(this.#options.standardBrowser);

if (beforeEmit) {
deprecated(
'Clerk.setActive({beforeEmit})',
'Use the `redirectUrl` property instead. Example `Clerk.setActive({redirectUrl:"/"})`',
);
await tracker.track(async () => {
this.#setTransitiveState();
await beforeEmit(newSession);
});
}

const taskUrl =
newSession?.status === 'pending' &&
newSession?.currentTask &&
this.#options.taskUrls?.[newSession?.currentTask.key];

if (!beforeEmit && (redirectUrl || taskUrl || setActiveNavigate)) {
if (redirectUrl || taskUrl || setActiveNavigate) {
await tracker.track(async () => {
if (!this.client) {
// Typescript is not happy because since thinks this.client might have changed to undefined because the function is asynchronous.
Expand Down
8 changes: 0 additions & 8 deletions packages/clerk-js/src/core/resources/Client.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import type {
ActiveSessionResource,
ClientJSON,
ClientJSONSnapshot,
ClientResource,
Expand Down Expand Up @@ -57,13 +56,6 @@ export class Client extends BaseResource implements ClientResource {
return this.signIn;
}

/**
* @deprecated Use `signedInSessions()` instead.
*/
get activeSessions(): ActiveSessionResource[] {
return this.sessions.filter(s => s.status === 'active') as ActiveSessionResource[];
}

get signedInSessions(): SignedInSessionResource[] {
return this.sessions.filter(s => s.status === 'active' || s.status === 'pending') as SignedInSessionResource[];
}
Expand Down
5 changes: 0 additions & 5 deletions packages/nextjs/src/server/clerkMiddleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,6 @@ export type ClerkMiddlewareSessionAuthObject = (SignedInAuthObject | SignedOutAu
redirectToSignUp: RedirectFun<Response>;
};

/**
* @deprecated Use `ClerkMiddlewareSessionAuthObject` instead.
*/
export type ClerkMiddlewareAuthObject = ClerkMiddlewareSessionAuthObject;

export type ClerkMiddlewareAuth = AuthFn;

type ClerkMiddlewareHandler = (
Expand Down
7 changes: 1 addition & 6 deletions packages/nextjs/src/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,7 @@ export { buildClerkProps } from './buildClerkProps';
export { auth } from '../app-router/server/auth';
export { currentUser } from '../app-router/server/currentUser';
export { clerkMiddleware } from './clerkMiddleware';
export type {
ClerkMiddlewareAuth,
ClerkMiddlewareSessionAuthObject,
ClerkMiddlewareAuthObject,
ClerkMiddlewareOptions,
} from './clerkMiddleware';
export type { ClerkMiddlewareAuth, ClerkMiddlewareSessionAuthObject, ClerkMiddlewareOptions } from './clerkMiddleware';

/**
* Re-export resource types from @clerk/backend
Expand Down
2 changes: 0 additions & 2 deletions packages/nextjs/src/utils/mergeNextClerkPropsWithEnv.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ export const mergeNextClerkPropsWithEnv = (props: Omit<NextClerkProviderProps, '
props.signInFallbackRedirectUrl || process.env.NEXT_PUBLIC_CLERK_SIGN_IN_FALLBACK_REDIRECT_URL || '',
signUpFallbackRedirectUrl:
props.signUpFallbackRedirectUrl || process.env.NEXT_PUBLIC_CLERK_SIGN_UP_FALLBACK_REDIRECT_URL || '',
afterSignInUrl: props.afterSignInUrl || process.env.NEXT_PUBLIC_CLERK_AFTER_SIGN_IN_URL || '',
afterSignUpUrl: props.afterSignUpUrl || process.env.NEXT_PUBLIC_CLERK_AFTER_SIGN_UP_URL || '',
newSubscriptionRedirectUrl:
props.newSubscriptionRedirectUrl || process.env.NEXT_PUBLIC_CLERK_CHECKOUT_CONTINUE_URL || '',
telemetry: props.telemetry ?? {
Expand Down
4 changes: 0 additions & 4 deletions packages/react-router/src/client/ReactRouterClerkProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,6 @@ function ClerkProviderBase({ children, ...rest }: ClerkProviderPropsWithState) {
__clerk_debug,
__signInUrl,
__signUpUrl,
__afterSignInUrl,
__afterSignUpUrl,
__signInForceRedirectUrl,
__signUpForceRedirectUrl,
__signInFallbackRedirectUrl,
Expand Down Expand Up @@ -86,8 +84,6 @@ function ClerkProviderBase({ children, ...rest }: ClerkProviderPropsWithState) {
isSatellite: __isSatellite,
signInUrl: __signInUrl,
signUpUrl: __signUpUrl,
afterSignInUrl: __afterSignInUrl,
afterSignUpUrl: __afterSignUpUrl,
signInForceRedirectUrl: __signInForceRedirectUrl,
signUpForceRedirectUrl: __signUpForceRedirectUrl,
signInFallbackRedirectUrl: __signInFallbackRedirectUrl,
Expand Down
2 changes: 0 additions & 2 deletions packages/react-router/src/client/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ export type ClerkState = {
__isSatellite: boolean;
__signInUrl: string | undefined;
__signUpUrl: string | undefined;
__afterSignInUrl: string | undefined;
__afterSignUpUrl: string | undefined;
__signInForceRedirectUrl: string | undefined;
__signUpForceRedirectUrl: string | undefined;
__signInFallbackRedirectUrl: string | undefined;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ describe('clerkMiddleware', () => {
authorizedParties: [],
signInUrl: '',
signUpUrl: '',
afterSignInUrl: '',
afterSignUpUrl: '',
secretKey: 'sk_test_...',
publishableKey: 'pk_test_...',
} as unknown as ReturnType<typeof loadOptions>);
Expand Down Expand Up @@ -77,8 +75,6 @@ describe('clerkMiddleware', () => {
authorizedParties: [],
signInUrl: '',
signUpUrl: '',
afterSignInUrl: '',
afterSignUpUrl: '',
acceptsToken: 'any',
});

Expand Down Expand Up @@ -107,8 +103,6 @@ describe('clerkMiddleware', () => {
authorizedParties: ['https://example.com'],
signInUrl: '/sign-in',
signUpUrl: '/sign-up',
afterSignInUrl: '/dashboard',
afterSignUpUrl: '/welcome',
};

const middleware = clerkMiddleware(options);
Expand Down
4 changes: 0 additions & 4 deletions packages/react-router/src/server/clerkMiddleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,6 @@ export const clerkMiddleware = (options?: ClerkMiddlewareOptions): MiddlewareFun
authorizedParties,
signInUrl,
signUpUrl,
afterSignInUrl,
afterSignUpUrl,
organizationSyncOptions,
} = loadedOptions;

Expand All @@ -69,8 +67,6 @@ export const clerkMiddleware = (options?: ClerkMiddlewareOptions): MiddlewareFun
organizationSyncOptions,
signInUrl,
signUpUrl,
afterSignInUrl,
afterSignUpUrl,
acceptsToken: 'any',
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export async function legacyAuthenticateRequest(
const { audience, authorizedParties } = opts;

const { apiUrl, secretKey, jwtKey, proxyUrl, isSatellite, domain, publishableKey, machineSecretKey } = opts;
const { signInUrl, signUpUrl, afterSignInUrl, afterSignUpUrl } = opts;
const { signInUrl, signUpUrl } = opts;

const requestState = await clerkClient(args).authenticateRequest(patchRequest(request), {
apiUrl,
Expand All @@ -29,8 +29,6 @@ export async function legacyAuthenticateRequest(
authorizedParties,
signInUrl,
signUpUrl,
afterSignInUrl,
afterSignUpUrl,
});

const locationHeader = requestState.headers.get(constants.Headers.Location);
Expand Down
Loading
Loading