diff --git a/.changeset/tiny-forks-sit.md b/.changeset/tiny-forks-sit.md new file mode 100644 index 0000000000..bd2899152d --- /dev/null +++ b/.changeset/tiny-forks-sit.md @@ -0,0 +1,6 @@ +--- +'@clerk/clerk-react': minor +'@clerk/types': minor +--- + +Update the TypeScript types of ``. If you use the `routerPush` prop you're now required to also provide the `routerReplace` prop (or other way around). You can also not provide them at all since both props are optional. diff --git a/.github/workflows/ui-retheme-changes-reminder.yml b/.github/workflows/ui-retheme-changes-reminder.yml index 0414f1056d..c78d12f76e 100644 --- a/.github/workflows/ui-retheme-changes-reminder.yml +++ b/.github/workflows/ui-retheme-changes-reminder.yml @@ -6,7 +6,13 @@ on: - main paths: - 'packages/clerk-js/src/ui/**' - + # files with matching `*.retheme.ts` retheme variant + - 'packages/localizations/src/en-US.ts' + - 'packages/localizations/src/index.ts' + - 'packages/types/src/appearance.ts' + - 'packages/types/src/clerk.ts' + - 'packages/types/src/index.ts' + - 'packages/types/src/localization.ts' jobs: check-changes: runs-on: ubuntu-latest diff --git a/.prettierignore b/.prettierignore index 1b91423549..b52b1aa940 100644 --- a/.prettierignore +++ b/.prettierignore @@ -15,4 +15,6 @@ dist examples node_modules package-lock.json -playground \ No newline at end of file +playground +packages/backend/tests/**/*.js +/**/CHANGELOG.md \ No newline at end of file diff --git a/packages/react/src/contexts/__tests__/ClerkProvider.test.tsx b/packages/react/src/contexts/__tests__/ClerkProvider.test.tsx index bd1814ee79..5b1662c8b0 100644 --- a/packages/react/src/contexts/__tests__/ClerkProvider.test.tsx +++ b/packages/react/src/contexts/__tests__/ClerkProvider.test.tsx @@ -224,4 +224,23 @@ describe('ClerkProvider', () => { expectTypeOf({ publishableKey: 'test' }).not.toMatchTypeOf(); }); }); + + describe('navigation options', () => { + it('expects both routerPush & routerReplace to pass', () => { + expectTypeOf({ + publishableKey: 'test', + children: '', + routerPush: () => {}, + routerReplace: () => {}, + }).toMatchTypeOf(); + }); + + it('errors if one of routerPush / routerReplace is passed', () => { + expectTypeOf({ + publishableKey: 'test', + children: '', + routerPush: () => {}, + }).not.toMatchTypeOf(); + }); + }); }); diff --git a/packages/react/src/types.ts b/packages/react/src/types.ts index 68b31e3ca0..d88e9fe0f3 100644 --- a/packages/react/src/types.ts +++ b/packages/react/src/types.ts @@ -11,6 +11,7 @@ import type { SignInRedirectOptions, SignUpRedirectOptions, UserResource, + Without, } from '@clerk/types'; import type React from 'react'; @@ -23,7 +24,7 @@ declare global { } } -export type IsomorphicClerkOptions = Omit & { +export type IsomorphicClerkOptions = Without & { Clerk?: ClerkProp; clerkJSUrl?: string; clerkJSVariant?: 'headless' | ''; @@ -37,19 +38,10 @@ export type ClerkProviderProps = IsomorphicClerkOptions & { initialState?: InitialState; }; -// TODO(@dimkl): replacing it with the following make nextjs type tests fail -// `Exclude & { publishableKey?: string }` -// find another way to reduce the duplication. -export type ClerkProviderOptionsWrapper = Omit & { - Clerk?: ClerkProp; - clerkJSUrl?: string; - clerkJSVariant?: 'headless' | ''; - clerkJSVersion?: string; - sdkMetadata?: SDKMetadata; +export type ClerkProviderOptionsWrapper = Without & { publishableKey?: string; -} & MultiDomainAndOrProxy & { - children: React.ReactNode; - }; + children: React.ReactNode; +}; export interface BrowserClerkConstructor { new (publishableKey: string, options?: DomainOrProxyUrl): BrowserClerk; @@ -75,7 +67,7 @@ export interface MountProps { } export interface HeadlessBrowserClerk extends Clerk { - load: (opts?: Omit) => Promise; + load: (opts?: Without) => Promise; updateClient: (client: ClientResource) => void; } diff --git a/packages/types/src/clerk.retheme.ts b/packages/types/src/clerk.retheme.ts index ee0b376398..691c180722 100644 --- a/packages/types/src/clerk.retheme.ts +++ b/packages/types/src/clerk.retheme.ts @@ -495,7 +495,25 @@ export type CustomNavigation = (to: string, options?: NavigateOptions) => Promis export type ClerkThemeOptions = DeepSnakeToCamel>; -export interface ClerkOptions { +/** + * Navigation options used to replace or push history changes. + * Both `routerPush` & `routerReplace` OR none options should be passed. + */ +type ClerkOptionsNavigationFn = + | { + routerPush?: never; + routerReplace?: never; + } + | { + routerPush: (to: string) => Promise | unknown; + routerReplace: (to: string) => Promise | unknown; + }; + +type ClerkOptionsNavigation = ClerkOptionsNavigationFn & { + routerDebug?: boolean; +}; + +export type ClerkOptions = ClerkOptionsNavigation & { appearance?: Appearance; localization?: LocalizationResource; /** @@ -535,7 +553,7 @@ export interface ClerkOptions { }; sdkMetadata?: SDKMetadata; -} +}; export interface NavigateOptions { replace?: boolean; diff --git a/packages/types/src/clerk.ts b/packages/types/src/clerk.ts index 1bf9181372..fca95e92fd 100644 --- a/packages/types/src/clerk.ts +++ b/packages/types/src/clerk.ts @@ -495,16 +495,27 @@ export type CustomNavigation = (to: string, options?: NavigateOptions) => Promis export type ClerkThemeOptions = DeepSnakeToCamel>; -export interface ClerkOptions { - appearance?: Appearance; - localization?: LocalizationResource; - /** - * Navigation - */ - routerPush?: (to: string) => Promise | unknown; - routerReplace?: (to: string) => Promise | unknown; +/** + * Navigation options used to replace or push history changes. + * Both `routerPush` & `routerReplace` OR none options should be passed. + */ +type ClerkOptionsNavigationFn = + | { + routerPush?: never; + routerReplace?: never; + } + | { + routerPush: (to: string) => Promise | unknown; + routerReplace: (to: string) => Promise | unknown; + }; + +type ClerkOptionsNavigation = ClerkOptionsNavigationFn & { routerDebug?: boolean; +}; +export type ClerkOptions = ClerkOptionsNavigation & { + appearance?: Appearance; + localization?: LocalizationResource; polling?: boolean; selectInitialSession?: (client: ClientResource) => ActiveSessionResource | null; /** Controls if ClerkJS will load with the standard browser setup using Clerk cookies */ @@ -536,7 +547,7 @@ export interface ClerkOptions { }; sdkMetadata?: SDKMetadata; -} +}; export interface NavigateOptions { replace?: boolean;