From 049d537a0ac84f2f57786d95a08449f2faa4545f Mon Sep 17 00:00:00 2001 From: panteliselef Date: Thu, 8 Aug 2024 22:21:48 +0300 Subject: [PATCH 1/2] chore(astro,clerk-js): Inject `windowNavigate` through router functions In some cases (like in Astro) we want to reconstruct the original windowNavigate functionality, that is because the framework might not have a router. --- .changeset/sixty-bikes-visit.md | 7 +++++++ .../astro/src/internal/create-clerk-instance.ts | 17 ++++------------- packages/clerk-js/src/core/clerk.ts | 2 +- packages/types/src/clerk.ts | 5 ++++- 4 files changed, 16 insertions(+), 15 deletions(-) create mode 100644 .changeset/sixty-bikes-visit.md diff --git a/.changeset/sixty-bikes-visit.md b/.changeset/sixty-bikes-visit.md new file mode 100644 index 00000000000..49586676fc8 --- /dev/null +++ b/.changeset/sixty-bikes-visit.md @@ -0,0 +1,7 @@ +--- +"@clerk/clerk-js": minor +"@clerk/astro": minor +"@clerk/types": minor +--- + +Inject `windowNavigate` through router functions. diff --git a/packages/astro/src/internal/create-clerk-instance.ts b/packages/astro/src/internal/create-clerk-instance.ts index 8e449ceabc3..0bf3c631ff6 100644 --- a/packages/astro/src/internal/create-clerk-instance.ts +++ b/packages/astro/src/internal/create-clerk-instance.ts @@ -9,29 +9,20 @@ import { waitForClerkScript } from './utils/loadClerkJSScript'; let initOptions: ClerkOptions | undefined; -// TODO-SHARED: copied from `clerk-js` -export const CLERK_BEFORE_UNLOAD_EVENT = 'clerk:beforeunload'; - -function windowNavigate(to: URL | string): void { - const toURL = new URL(to, window.location.href); - window.dispatchEvent(new CustomEvent(CLERK_BEFORE_UNLOAD_EVENT)); - window.location.href = toURL.href; -} - function createNavigationHandler( windowNav: typeof window.history.pushState | typeof window.history.replaceState, ): Exclude | Exclude { - return (to, metadata) => { - if (metadata?.__internal_metadata?.navigationType === 'internal') { + return (to, opts) => { + if (opts?.__internal_metadata?.navigationType === 'internal') { windowNav(history.state, '', to); } else { - windowNavigate(to); + opts?.windowNavigate(to); } }; } /** - * Prevents firing clerk.load multiple times + * Prevents firing clerk.load() multiple times */ const createClerkInstance = runOnce(createClerkInstanceInternal); diff --git a/packages/clerk-js/src/core/clerk.ts b/packages/clerk-js/src/core/clerk.ts index 4b0ca388918..a22c718ead8 100644 --- a/packages/clerk-js/src/core/clerk.ts +++ b/packages/clerk-js/src/core/clerk.ts @@ -820,7 +820,7 @@ export class Clerk implements ClerkInterface { return; } - const metadata = options?.metadata ? { __internal_metadata: options?.metadata } : undefined; + const metadata = { __internal_metadata: options?.metadata, windowNavigate }; // React router only wants the path, search or hash portion. return await customNavigate(stripOrigin(toURL), metadata); }; diff --git a/packages/types/src/clerk.ts b/packages/types/src/clerk.ts index b7478735c78..2b03f2b6735 100644 --- a/packages/types/src/clerk.ts +++ b/packages/types/src/clerk.ts @@ -641,7 +641,10 @@ type NavigationType = type RouterMetadata = { routing?: RoutingStrategy; navigationType?: NavigationType }; -type RouterFn = (to: string, metadata?: { __internal_metadata?: RouterMetadata }) => Promise | unknown; +type RouterFn = ( + to: string, + metadata?: { __internal_metadata?: RouterMetadata; windowNavigate: (to: URL | string) => void }, +) => Promise | unknown; export type WithoutRouting = Omit; From d2df7f57dcf0be8dde21f06d8f39a2292dd40ce1 Mon Sep 17 00:00:00 2001 From: panteliselef Date: Fri, 9 Aug 2024 10:43:59 +0300 Subject: [PATCH 2/2] chore(astro,clerk-js): Update unit tests --- .../core/__tests__/clerk.redirects.test.ts | 28 ++++++++----------- .../clerk-js/src/core/__tests__/clerk.test.ts | 4 ++- packages/clerk-js/src/core/clerk.ts | 5 +++- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/packages/clerk-js/src/core/__tests__/clerk.redirects.test.ts b/packages/clerk-js/src/core/__tests__/clerk.redirects.test.ts index 0f6dad0113a..3d8bd184130 100644 --- a/packages/clerk-js/src/core/__tests__/clerk.redirects.test.ts +++ b/packages/clerk-js/src/core/__tests__/clerk.redirects.test.ts @@ -124,34 +124,30 @@ describe('Clerk singleton - Redirects', () => { it('redirects to signInUrl for development instance', async () => { await clerkForDevelopmentInstance.redirectToSignIn({ redirectUrl: '/example' }); - expect(mockNavigate).toHaveBeenCalledWith( - '/sign-in#/?redirect_url=http%3A%2F%2Ftest.host%2Fexample', - undefined, - ); + expect(mockNavigate).toHaveBeenCalledWith('/sign-in#/?redirect_url=http%3A%2F%2Ftest.host%2Fexample', { + windowNavigate: expect.any(Function), + }); }); it('redirects to signInUrl for production instance', async () => { await clerkForProductionInstance.redirectToSignIn({ redirectUrl: '/example' }); - expect(mockNavigate).toHaveBeenCalledWith( - '/sign-in#/?redirect_url=http%3A%2F%2Ftest.host%2Fexample', - undefined, - ); + expect(mockNavigate).toHaveBeenCalledWith('/sign-in#/?redirect_url=http%3A%2F%2Ftest.host%2Fexample', { + windowNavigate: expect.any(Function), + }); }); it('redirects to signUpUrl for development instance', async () => { await clerkForDevelopmentInstance.redirectToSignUp({ redirectUrl: '/example' }); - expect(mockNavigate).toHaveBeenCalledWith( - '/sign-up#/?redirect_url=http%3A%2F%2Ftest.host%2Fexample', - undefined, - ); + expect(mockNavigate).toHaveBeenCalledWith('/sign-up#/?redirect_url=http%3A%2F%2Ftest.host%2Fexample', { + windowNavigate: expect.any(Function), + }); }); it('redirects to signUpUrl for production instance', async () => { await clerkForProductionInstance.redirectToSignUp({ redirectUrl: '/example' }); - expect(mockNavigate).toHaveBeenCalledWith( - '/sign-up#/?redirect_url=http%3A%2F%2Ftest.host%2Fexample', - undefined, - ); + expect(mockNavigate).toHaveBeenCalledWith('/sign-up#/?redirect_url=http%3A%2F%2Ftest.host%2Fexample', { + windowNavigate: expect.any(Function), + }); }); it('redirects to userProfileUrl', async () => { diff --git a/packages/clerk-js/src/core/__tests__/clerk.test.ts b/packages/clerk-js/src/core/__tests__/clerk.test.ts index 442f8d73bc5..fd6777fdba7 100644 --- a/packages/clerk-js/src/core/__tests__/clerk.test.ts +++ b/packages/clerk-js/src/core/__tests__/clerk.test.ts @@ -784,7 +784,9 @@ describe('Clerk singleton', () => { await waitFor(() => { expect(mockSignUpCreate).not.toHaveBeenCalledWith({ transfer: true }); expect(mockSetActive).not.toHaveBeenCalled(); - expect(mockNavigate).toHaveBeenCalledWith('/sign-in', undefined); + expect(mockNavigate).toHaveBeenCalledWith('/sign-in', { + windowNavigate: expect.any(Function), + }); }); }); diff --git a/packages/clerk-js/src/core/clerk.ts b/packages/clerk-js/src/core/clerk.ts index a22c718ead8..8591b33def2 100644 --- a/packages/clerk-js/src/core/clerk.ts +++ b/packages/clerk-js/src/core/clerk.ts @@ -820,7 +820,10 @@ export class Clerk implements ClerkInterface { return; } - const metadata = { __internal_metadata: options?.metadata, windowNavigate }; + const metadata = { + ...(options?.metadata ? { __internal_metadata: options?.metadata } : {}), + windowNavigate, + }; // React router only wants the path, search or hash portion. return await customNavigate(stripOrigin(toURL), metadata); };