diff --git a/.changeset/hungry-lies-burn.md b/.changeset/hungry-lies-burn.md new file mode 100644 index 00000000000..cb11797310e --- /dev/null +++ b/.changeset/hungry-lies-burn.md @@ -0,0 +1,16 @@ +--- +"@clerk/nextjs": patch +--- + +Introduce `createRouteMatcher` which is designed to generate and return a function that evaluates whether a given Request object matches a set of predefined routes. It provides flexibility in defining these routes through various patterns, including glob patterns, regular expressions, and custom functions. This composable helper can be used in combination with the `clerkMiddleware` helper to easily protect specific routes, eg: +```ts +import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server'; + +const isProtectedRoute = createRouteMatcher(['/dashboard(.*)']); + +export default clerkMiddleware((auth, request) => { + if (isProtectedRoute(request)) { + auth().protect(); + } +}); +``` diff --git a/packages/nextjs/src/server/__tests__/__snapshots__/exports.test.ts.snap b/packages/nextjs/src/server/__tests__/__snapshots__/exports.test.ts.snap index db01c5c1eb8..127181d0aad 100644 --- a/packages/nextjs/src/server/__tests__/__snapshots__/exports.test.ts.snap +++ b/packages/nextjs/src/server/__tests__/__snapshots__/exports.test.ts.snap @@ -8,8 +8,8 @@ exports[`/server public exports should not include a breaking change 1`] = ` "clerkClient", "clerkMiddleware", "createClerkClient", + "createRouteMatcher", "currentUser", - "experimental_createRouteMatcher", "getAuth", "redirectToSignIn", "redirectToSignUp", diff --git a/packages/nextjs/src/server/index.ts b/packages/nextjs/src/server/index.ts index 58aa59ae55e..798b7e0bb1b 100644 --- a/packages/nextjs/src/server/index.ts +++ b/packages/nextjs/src/server/index.ts @@ -1,7 +1,7 @@ /** * Generic exports */ -import { createRouteMatcher } from './routeMatcher'; +export { createRouteMatcher } from './routeMatcher'; export { verifyToken, createClerkClient } from '@clerk/backend'; export type { WebhookEvent, WebhookEventType } from '@clerk/backend'; @@ -16,13 +16,3 @@ export { auth } from '../app-router/server/auth'; export { currentUser } from '../app-router/server/currentUser'; export { authMiddleware } from './authMiddleware'; export { clerkMiddleware } from './clerkMiddleware'; - -/** - * Returns a function that accepts a `Request` object and returns whether the request matches the list of - * predefined routes that can be passed in as the first argument. - * - * You can use glob patterns to match multiple routes or a function to match against the request object. - * Path patterns and regular expressions are supported, for example: `['/foo', '/bar(.*)'] or `[/^\/foo\/.*$/]` - * For more information, see: https://clerk.com/docs - */ -export const experimental_createRouteMatcher = createRouteMatcher; diff --git a/packages/nextjs/src/server/routeMatcher.ts b/packages/nextjs/src/server/routeMatcher.ts index c52216b9c82..304811d64a3 100644 --- a/packages/nextjs/src/server/routeMatcher.ts +++ b/packages/nextjs/src/server/routeMatcher.ts @@ -7,12 +7,7 @@ import { paths } from '../utils'; type WithPathPatternWildcard = `${T & string}(.*)`; type NextTypedRoute['0']['href']> = T extends string ? T : never; -// For extra safety, we won't recommend using a `/(.*)` route matcher. -type ExcludeRootPath = T extends '/' ? never : T; - -type RouteMatcherWithNextTypedRoutes = Autocomplete< - WithPathPatternWildcard> | NextTypedRoute ->; +type RouteMatcherWithNextTypedRoutes = Autocomplete | NextTypedRoute>; export type RouteMatcherParam = | Array @@ -21,9 +16,12 @@ export type RouteMatcherParam = | ((req: NextRequest) => boolean); /** - * Create a function that matches a request against the specified routes. - * Precomputes the glob matchers for the public routes, so we don't have to - * recompile the regular expressions on every request. + * Returns a function that accepts a `Request` object and returns whether the request matches the list of + * predefined routes that can be passed in as the first argument. + * + * You can use glob patterns to match multiple routes or a function to match against the request object. + * Path patterns and regular expressions are supported, for example: `['/foo', '/bar(.*)'] or `[/^\/foo\/.*$/]` + * For more information, see: https://clerk.com/docs */ export const createRouteMatcher = (routes: RouteMatcherParam) => { if (typeof routes === 'function') {