diff --git a/.changeset/sour-pears-drop.md b/.changeset/sour-pears-drop.md
new file mode 100644
index 00000000000..436d85fbc93
--- /dev/null
+++ b/.changeset/sour-pears-drop.md
@@ -0,0 +1,6 @@
+---
+'@clerk/backend': patch
+'@clerk/nextjs': patch
+---
+
+Improve JSDoc comments to provide you with better IntelliSense information in your IDE
diff --git a/package.json b/package.json
index aa36fbc7a7f..3cc7a14cad5 100644
--- a/package.json
+++ b/package.json
@@ -105,6 +105,7 @@
"turbo": "^2.0.14",
"turbo-ignore": "^2.0.6",
"typedoc": "0.27.6",
+ "typedoc-plugin-missing-exports": "3.1.0",
"typescript": "catalog:repo",
"verdaccio": "^5.26.3",
"vitest": "3.0.2",
diff --git a/packages/backend/src/jwt/verifyJwt.ts b/packages/backend/src/jwt/verifyJwt.ts
index 8ceb2476c5b..4eabd424581 100644
--- a/packages/backend/src/jwt/verifyJwt.ts
+++ b/packages/backend/src/jwt/verifyJwt.ts
@@ -94,9 +94,25 @@ export function decodeJwt(token: string): JwtReturnType`](https://clerk.com/docs/components/organization/organization-switcher).
*
- * Common examples:
- * - ["/orgs/:slug", "/orgs/:slug/(.*)"]
- * - ["/orgs/:id", "/orgs/:id/(.*)"]
- * - ["/app/:any/orgs/:slug", "/app/:any/orgs/:slug/(.*)"]
+ * @example
+ * ["/orgs/:slug", "/orgs/:slug/(.*)"]
+ * @example
+ * ["/orgs/:id", "/orgs/:id/(.*)"]
+ * @example
+ * ["/app/:any/orgs/:slug", "/app/:any/orgs/:slug/(.*)"]
*/
organizationPatterns?: Pattern[];
/**
- * URL patterns for resources in the context of a clerk personal account (user-specific, outside any organization).
- * If the route also matches the organizationPattern, the organizationPatterns takes precedence.
+ * URL patterns for resources that exist within the context of a [Clerk Personal Account](https://clerk.com/docs/organizations/organization-workspaces#organization-workspaces-in-the-clerk-dashboard:~:text=Personal%20account) (user-specific, outside any organization).
*
- * Common examples:
- * - ["/user", "/user/(.*)"]
- * - ["/user/:any", "/user/:any/(.*)"]
+ * If the route also matches the `organizationPattern` prop, the `organizationPattern` prop takes precedence.
+ *
+ * @example
+ * ["/user", "/user/(.*)"]
+ * @example
+ * ["/user/:any", "/user/:any/(.*)"]
*/
personalAccountPatterns?: Pattern[];
};
/**
- * A pattern representing the structure of a URL path.
- * In addition to a valid URL, may include:
- * - Named path tokens prefixed with a colon (e.g., ":id", ":slug", ":any")
- * - Wildcard token (e.g., ".(*)"), which will match the remainder of the path
- * Examples: "/orgs/:slug", "/app/:any/orgs/:id", "/personal-account/(.*)"
+ * A `Pattern` is a `string` that represents the structure of a URL path. In addition to any valid URL, it may include:
+ * - Named path parameters prefixed with a colon (e.g., `:id`, `:slug`, `:any`).
+ * - Wildcard token, `(.*)`, which matches the remainder of the path.
+ *
+ * @example
+ * /orgs/:slug
+ *
+ * ```ts
+ * '/orgs/acmecorp' // matches (`:slug` value: acmecorp)
+ * '/orgs' // does not match
+ * '/orgs/acmecorp/settings' // does not match
+ * ```
+ *
+ * @example
+ * /app/:any/orgs/:id
+ *
+ * ```ts
+ * '/app/petstore/orgs/org_123' // matches (`:id` value: org_123)
+ * '/app/dogstore/v2/orgs/org_123' // does not match
+ * ```
+ *
+ * @example
+ * /personal-account/(.*)
+ *
+ * ```ts
+ * '/personal-account/settings' // matches
+ * '/personal-account' // does not match
+ * ```
*/
type Pattern = string;
diff --git a/packages/backend/src/tokens/verify.ts b/packages/backend/src/tokens/verify.ts
index 523cee883be..30b149e7b72 100644
--- a/packages/backend/src/tokens/verify.ts
+++ b/packages/backend/src/tokens/verify.ts
@@ -8,7 +8,12 @@ import type { LoadClerkJWKFromRemoteOptions } from './keys';
import { loadClerkJWKFromLocal, loadClerkJWKFromRemote } from './keys';
export type VerifyTokenOptions = Omit &
- Omit & { jwtKey?: string };
+ Omit & {
+ /**
+ * Used to verify the session token in a networkless manner. Supply the PEM public key from the **[**API keys**](https://dashboard.clerk.com/last-active?path=api-keys) page -> Show JWT public key -> PEM Public Key** section in the Clerk Dashboard. **It's recommended to use [the environment variable](https://clerk.com/docs/deployments/clerk-environment-variables) instead.** For more information, refer to [Manual JWT verification](https://clerk.com/docs/backend-requests/handling/manual-jwt).
+ */
+ jwtKey?: string;
+ };
export async function verifyToken(
token: string,
diff --git a/packages/nextjs/src/app-router/server/auth.ts b/packages/nextjs/src/app-router/server/auth.ts
index 403dbf2710c..12e1acd30ec 100644
--- a/packages/nextjs/src/app-router/server/auth.ts
+++ b/packages/nextjs/src/app-router/server/auth.ts
@@ -11,13 +11,50 @@ import { createProtect } from '../../server/protect';
import { decryptClerkRequestData } from '../../server/utils';
import { buildRequestLike } from './utils';
-type Auth = AuthObject & { redirectToSignIn: RedirectFun> };
-
+/**
+ * `Auth` object of the currently active user and the `redirectToSignIn()` method.
+ */
+type Auth = AuthObject & {
+ /**
+ * The `auth()` helper returns the `redirectToSignIn()` method, which you can use to redirect the user to the sign-in page.
+ *
+ * @param [returnBackUrl] {string | URL} - The URL to redirect the user back to after they sign in.
+ *
+ * @note
+ * `auth()` on the server-side can only access redirect URLs defined via [environment variables](https://clerk.com/docs/deployments/clerk-environment-variables#sign-in-and-sign-up-redirects) or [`clerkMiddleware` dynamic keys](https://clerk.com/docs/references/nextjs/clerk-middleware#dynamic-keys).
+ */
+ redirectToSignIn: RedirectFun>;
+};
export interface AuthFn {
(): Promise;
+ /**
+ * `auth` includes a single property, the `protect()` method, which you can use in two ways:
+ * - to check if a user is authenticated (signed in)
+ * - to check if a user is authorized (has the correct roles or permissions) to access something, such as a component or a route handler
+ *
+ * The following table describes how auth.protect() behaves based on user authentication or authorization status:
+ *
+ * | Authenticated | Authorized | `auth.protect()` will |
+ * | - | - | - |
+ * | Yes | Yes | Return the [`Auth`](https://clerk.com/docs/references/backend/types/auth-object) object. |
+ * | Yes | No | Return a `404` error. |
+ * | No | No | Redirect the user to the sign-in page\*. |
+ *
+ * @important
+ * \*For non-document requests, such as API requests, `auth.protect()` returns a `404` error to users who aren't authenticated.
+ *
+ * `auth.protect()` can be used to check if a user is authenticated or authorized to access certain parts of your application or even entire routes. See detailed examples in the [dedicated guide](https://clerk.com/docs/organizations/verify-user-permissions).
+ */
protect: AuthProtect;
}
+/**
+ * The `auth()` helper returns the [`Auth`](https://clerk.com/docs/references/backend/types/auth-object) object of the currently active user, as well as the [`redirectToSignIn()`](https://clerk.com/docs/references/nextjs/auth#redirect-to-sign-in) method.
+ *
+ * - Only available for App Router.
+ * - Only works on the server-side, such as in Server Components, Route Handlers, and Server Actions.
+ * - Requires [`clerkMiddleware()`](https://clerk.com/docs/references/nextjs/clerk-middleware) to be configured.
+ */
export const auth: AuthFn = async () => {
require('server-only');
diff --git a/packages/nextjs/src/app-router/server/currentUser.ts b/packages/nextjs/src/app-router/server/currentUser.ts
index 1e7426843c6..073e2f35888 100644
--- a/packages/nextjs/src/app-router/server/currentUser.ts
+++ b/packages/nextjs/src/app-router/server/currentUser.ts
@@ -3,6 +3,29 @@ import type { User } from '@clerk/backend';
import { clerkClient } from '../../server/clerkClient';
import { auth } from './auth';
+/**
+ * The `currentUser` helper returns the [Backend User](https://clerk.com/docs/references/backend/types/backend-user) object of the currently active user. It can be used in Server Components, Route Handlers, and Server Actions.
+ *
+ * Under the hood, this helper:
+ * - calls `fetch()`, so it is automatically deduped per request.
+ * - uses the [`GET /v1/users/{user_id}`](https://clerk.com/docs/reference/backend-api/tag/Users#operation/GetUser) endpoint.
+ * - counts towards the [Backend API request rate limit](https://clerk.com/docs/backend-requests/resources/rate-limits#rate-limits).
+ *
+ * @example
+ * ```tsx
+ * // app/page.tsx
+ *
+ * import { currentUser } from '@clerk/nextjs/server'
+ *
+ * export default async function Page() {
+ * const user = await currentUser()
+ *
+ * if (!user) return Not signed in
+ *
+ * return Hello {user?.firstName}
+ * }
+ * ```
+ */
export async function currentUser(): Promise {
require('server-only');
diff --git a/packages/nextjs/src/server/buildClerkProps.ts b/packages/nextjs/src/server/buildClerkProps.ts
index a6f51aa068c..5017f750680 100644
--- a/packages/nextjs/src/server/buildClerkProps.ts
+++ b/packages/nextjs/src/server/buildClerkProps.ts
@@ -6,24 +6,52 @@ import type { RequestLike } from './types';
type BuildClerkPropsInitState = { user?: User | null; session?: Session | null; organization?: Organization | null };
+type BuildClerkProps = (req: RequestLike, authState?: BuildClerkPropsInitState) => Record;
+
/**
- * To enable Clerk SSR support, include this object to the `props`
- * returned from `getServerSideProps`. This will automatically make the auth state available to
- * the Clerk components and hooks during SSR, the hydration phase and CSR.
+ * Clerk uses `buildClerkProps` to inform the client-side helpers of the authentication state of the user. This function is used SSR in the `getServerSideProps` function of your Next.js application.
+ *
+ * @example
+ * **Basic usage**
+ *
+ * ```tsx
+ * // pages/myServerSidePage.tsx
+ *
+ * import { getAuth, buildClerkProps } from '@clerk/nextjs/server'
+ * import { GetServerSideProps } from 'next'
+ *
+ * export const getServerSideProps: GetServerSideProps = async (ctx) => {
+ * const { userId } = getAuth(ctx.req)
+ *
+ * if (!userId) {
+ * // handle user is not signed in.
+ * }
+ *
+ * // Load any data your application needs for the page using the userId
+ * return { props: { ...buildClerkProps(ctx.req) } }
+ * }
+ * ```
+ *
* @example
- * import { getAuth } from '@clerk/nextjs/server';
+ * **Usage with `clerkClient`**
+ *
+ * The `clerkClient` allows you to access the Clerk API. You can use this to retrieve or update data.
+ *
+ * ```tsx
+ * // pages/api/example.ts
*
- * export const getServerSideProps = ({ req }) => {
- * const { authServerSideProps } = getAuth(req);
- * const myData = getMyData();
+ * import { getAuth, buildClerkProps, clerkClient } from '@clerk/nextjs/server'
+ * import { GetServerSideProps } from 'next'
*
- * return {
- * props: { myData, authServerSideProps },
- * };
- * };
+ * export const getServerSideProps: GetServerSideProps = async (ctx) => {
+ * const { userId } = getAuth(ctx.req)
+ *
+ * const user = userId ? await clerkClient().users.getUser(userId) : undefined
+ *
+ * return { props: { ...buildClerkProps(ctx.req, { user }) } }
+ * }
+ * ```
*/
-type BuildClerkProps = (req: RequestLike, authState?: BuildClerkPropsInitState) => Record;
-
export const buildClerkProps: BuildClerkProps = (req, initialState = {}) => {
const sanitizedAuthObject = getDynamicAuthData(req, initialState);
diff --git a/packages/nextjs/src/server/clerkMiddleware.ts b/packages/nextjs/src/server/clerkMiddleware.ts
index 271e7f6e86d..32593989f71 100644
--- a/packages/nextjs/src/server/clerkMiddleware.ts
+++ b/packages/nextjs/src/server/clerkMiddleware.ts
@@ -48,7 +48,14 @@ type ClerkMiddlewareHandler = (
event: NextMiddlewareEvtParam,
) => NextMiddlewareReturn;
+/**
+ * The `clerkMiddleware()` function accepts an optional object. The following options are available.
+ * @interface
+ */
export type ClerkMiddlewareOptions = AuthenticateRequestOptions & {
+ /**
+ * If true, additional debug information will be logged to the console.
+ */
debug?: boolean;
};
@@ -84,6 +91,9 @@ interface ClerkMiddleware {
(request: NextMiddlewareRequestParam, event: NextMiddlewareEvtParam): NextMiddlewareReturn;
}
+/**
+ * The `clerkMiddleware()` helper integrates Clerk authentication into your Next.js application through Middleware. `clerkMiddleware()` is compatible with both the App and Pages routers.
+ */
// @ts-expect-error TS is not happy here. Will dig into it
export const clerkMiddleware: ClerkMiddleware = (...args: unknown[]) => {
const [request, event] = parseRequestAndEvent(args);
diff --git a/packages/nextjs/src/server/createGetAuth.ts b/packages/nextjs/src/server/createGetAuth.ts
index 1f6106faeb9..09a3bd74cca 100644
--- a/packages/nextjs/src/server/createGetAuth.ts
+++ b/packages/nextjs/src/server/createGetAuth.ts
@@ -29,6 +29,85 @@ export const createGetAuth = ({
};
});
+/**
+ * The `getAuth()` helper retrieves authentication state from the request object.
+ *
+ * @note
+ * If you are using App Router, use the [`auth()` helper](https://clerk.com/docs/references/nextjs/auth) instead.
+ *
+ * @param req - The Next.js request object.
+ * @param [options] - An optional object that can be used to configure the behavior of the `getAuth()` function.
+ * @param [options.secretKey] - A string that represents the Secret Key used to sign the session token. If not provided, the Secret Key is retrieved from the environment variable `CLERK_SECRET_KEY`.
+ * @returns The `Auth` object. See the [Auth reference](https://clerk.com/docs/references/backend/types/auth-object) for more information.
+ *
+ * @example
+ * **Protect API routes**
+ *
+ * The following example demonstrates how to protect an API route by checking if the `userId` is present in the `getAuth()` response.
+ *
+ * ```tsx
+ * // app/api/example/route.ts
+ * import { getAuth } from '@clerk/nextjs/server'
+ * import type { NextApiRequest, NextApiResponse } from 'next'
+ *
+ * export default async function handler(req: NextApiRequest, res: NextApiResponse) {
+ * const { userId } = getAuth(req)
+ *
+ * if (!userId) {
+ * return res.status(401).json({ error: 'Not authenticated' })
+ * }
+ *
+ * // Add logic that retrieves the data for the API route
+ *
+ * return res.status(200).json({ userId: userId })
+ * }
+ * ```
+ *
+ * @example
+ * **Usage with `getToken()`**
+ *
+ * `getAuth()` returns [`getToken()`](https://clerk.com/docs/references/backend/types/auth-object#get-token), which is a method that returns the current user's session token or a custom JWT template.
+ *
+ * ```tsx
+ * // app/api/example/route.ts
+ *
+ * import { getAuth } from '@clerk/nextjs/server'
+ * import type { NextApiRequest, NextApiResponse } from 'next'
+ *
+ * export default async function handler(req: NextApiRequest, res: NextApiResponse) {
+ * const { getToken } = getAuth(req)
+ *
+ * const token = await getToken({ template: 'supabase' })
+ *
+ * // Add logic that retrieves the data
+ * // from your database using the token
+ *
+ * return res.status(200).json({})
+ * }
+ * ```
+ *
+ * @example
+ * **Usage with `clerkClient`**
+ *
+ * `clerkClient` is used to access the [Backend SDK](https://clerk.com/docs/references/backend/overview), which exposes Clerk's Backend API resources. You can use `getAuth()` to pass authentication information that many of the Backend SDK methods require, like the user's ID.
+ *
+ * ```tsx
+ * // app/api/example/route.ts
+ *
+ * import { clerkClient, getAuth } from '@clerk/nextjs/server'
+ * import type { NextApiRequest, NextApiResponse } from 'next'
+ *
+ * export default async function handler(req: NextApiRequest, res: NextApiResponse) {
+ * const { userId } = getAuth(req)
+ *
+ * const client = await clerkClient()
+ *
+ * const user = userId ? await client.users.getUser(userId) : null
+ *
+ * return res.status(200).json({})
+ * }
+ * ```
+ */
export const getAuth = createGetAuth({
debugLoggerName: 'getAuth()',
noAuthStatusMessage: getAuthAuthHeaderMissing(),
diff --git a/packages/nextjs/src/server/protect.ts b/packages/nextjs/src/server/protect.ts
index 3c683b42216..ad601de804f 100644
--- a/packages/nextjs/src/server/protect.ts
+++ b/packages/nextjs/src/server/protect.ts
@@ -12,7 +12,16 @@ import type {
import { constants as nextConstants } from '../constants';
import { isNextFetcher } from './nextFetcher';
-type AuthProtectOptions = { unauthorizedUrl?: string; unauthenticatedUrl?: string };
+type AuthProtectOptions = {
+ /**
+ * The URL to redirect the user to if they are not authorized.
+ */
+ unauthorizedUrl?: string;
+ /**
+ * The URL to redirect the user to if they are not authenticated.
+ */
+ unauthenticatedUrl?: string;
+};
/**
* Throws a Nextjs notFound error if user is not authenticated or authorized.
diff --git a/packages/nextjs/typedoc.json b/packages/nextjs/typedoc.json
new file mode 100644
index 00000000000..c09039e578b
--- /dev/null
+++ b/packages/nextjs/typedoc.json
@@ -0,0 +1,10 @@
+{
+ "$schema": "https://typedoc.org/schema.json",
+ "entryPoints": [
+ "./src/server/clerkMiddleware.ts",
+ "./src/app-router/server/currentUser.ts",
+ "./src/app-router/server/auth.ts",
+ "./src/server/buildClerkProps.ts",
+ "./src/server/createGetAuth.ts"
+ ]
+}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 135803c7aef..f22b665b3df 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -214,6 +214,9 @@ importers:
typedoc:
specifier: 0.27.6
version: 0.27.6(typescript@5.6.3)
+ typedoc-plugin-missing-exports:
+ specifier: 3.1.0
+ version: 3.1.0(typedoc@0.27.6(typescript@5.6.3))
typescript:
specifier: catalog:repo
version: 5.6.3
@@ -10448,6 +10451,7 @@ packages:
lodash.isequal@4.5.0:
resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==}
+ deprecated: This package is deprecated. Use require('node:util').isDeepStrictEqual instead.
lodash.isinteger@4.0.4:
resolution: {integrity: sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==}
@@ -14062,6 +14066,11 @@ packages:
resolution: {integrity: sha512-q7QNVDGTdl702bVFiI5eY4l/HkgCM6at9KhcFbgUAzezHFbOVy4+0O/lCjsABEQwbZPravVfBIiBVGo89yzHFg==}
engines: {node: '>= 0.4'}
+ typedoc-plugin-missing-exports@3.1.0:
+ resolution: {integrity: sha512-Sogbaj+qDa21NjB3SlIw4JXSwmcl/WOjwiPNaVEcPhpNG/MiRTtpwV81cT7h1cbu9StpONFPbddYWR0KV/fTWA==}
+ peerDependencies:
+ typedoc: 0.26.x || 0.27.x
+
typedoc@0.27.6:
resolution: {integrity: sha512-oBFRoh2Px6jFx366db0lLlihcalq/JzyCVp7Vaq1yphL/tbgx2e+bkpkCgJPunaPvPwoTOXSwasfklWHm7GfAw==}
engines: {node: '>= 18'}
@@ -31741,6 +31750,10 @@ snapshots:
typed-array-buffer: 1.0.3
typed-array-byte-offset: 1.0.4
+ typedoc-plugin-missing-exports@3.1.0(typedoc@0.27.6(typescript@5.6.3)):
+ dependencies:
+ typedoc: 0.27.6(typescript@5.6.3)
+
typedoc@0.27.6(typescript@5.6.3):
dependencies:
'@gerrit0/mini-shiki': 1.27.2
diff --git a/typedoc.config.mjs b/typedoc.config.mjs
index c5f6540c7a2..c86624b0847 100644
--- a/typedoc.config.mjs
+++ b/typedoc.config.mjs
@@ -1,5 +1,6 @@
import path from 'node:path';
import fs from 'node:fs';
+import { OptionDefaults } from 'typedoc';
const IGNORE_LIST = [
'.DS_Store',
@@ -30,14 +31,18 @@ const config = {
json: './.typedoc/output.json',
entryPointStrategy: 'packages',
excludePrivate: true,
- blockTags: ['@param', '@returns'],
- modifierTags: ['@alpha', '@beta', '@experimental', '@deprecated'],
+ blockTags: [...OptionDefaults.blockTags, '@warning', '@note', '@important'],
+ modifierTags: [...OptionDefaults.modifierTags],
+ exclude: ['**/*+(.spec|.test).ts'],
+ plugin: ['typedoc-plugin-missing-exports'],
packageOptions: {
includeVersion: false,
excludePrivate: true,
sortEntryPoints: true,
sort: 'alphabetical',
excludeExternals: true,
+ excludeInternal: true,
+ excludeNotDocumented: true,
gitRevision: 'main',
},
entryPoints: getPackages(),