diff --git a/.changeset/spicy-toys-change.md b/.changeset/spicy-toys-change.md new file mode 100644 index 00000000000..e79bd7a4cb4 --- /dev/null +++ b/.changeset/spicy-toys-change.md @@ -0,0 +1,5 @@ +--- +'@clerk/nextjs': patch +--- + +Warn about deprecations that will be dropped in next major version diff --git a/.changeset/unlucky-emus-greet.md b/.changeset/unlucky-emus-greet.md new file mode 100644 index 00000000000..19c0b0b439f --- /dev/null +++ b/.changeset/unlucky-emus-greet.md @@ -0,0 +1,7 @@ +--- +'@clerk/nextjs': minor +'@clerk/shared': minor +--- + +Add the `use client` directive in `@clerk/shared` to make the package compatible with an RSC environment. +Remove several helpers from `@clerk/nextjs` and import them from `@clerk/shared` instead. diff --git a/packages/nextjs/src/server/clerkClient.ts b/packages/nextjs/src/server/clerkClient.ts index 2891ec5e132..5ec9ca27118 100644 --- a/packages/nextjs/src/server/clerkClient.ts +++ b/packages/nextjs/src/server/clerkClient.ts @@ -1,23 +1,7 @@ /* eslint-disable turbo/no-undeclared-env-vars */ import { Clerk } from '@clerk/backend'; -/** - * @deprecated - */ -export const JS_VERSION = process.env.CLERK_JS_VERSION || ''; -export const CLERK_JS_VERSION = process.env.NEXT_PUBLIC_CLERK_JS_VERSION || ''; -export const CLERK_JS_URL = process.env.NEXT_PUBLIC_CLERK_JS || ''; -export const API_URL = process.env.CLERK_API_URL || 'https://api.clerk.dev'; -export const API_VERSION = process.env.CLERK_API_VERSION || 'v1'; -export const API_KEY = process.env.CLERK_API_KEY || ''; -export const SECRET_KEY = process.env.CLERK_SECRET_KEY || ''; -export const FRONTEND_API = process.env.NEXT_PUBLIC_CLERK_FRONTEND_API || ''; -export const PUBLISHABLE_KEY = process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY || ''; -export const DOMAIN = process.env.NEXT_PUBLIC_CLERK_DOMAIN || ''; -export const PROXY_URL = process.env.NEXT_PUBLIC_CLERK_PROXY_URL || ''; -export const IS_SATELLITE = process.env.NEXT_PUBLIC_CLERK_IS_SATELLITE === 'true' || false; -export const SIGN_IN_URL = process.env.NEXT_PUBLIC_CLERK_SIGN_IN_URL || ''; -export const SIGN_UP_URL = process.env.NEXT_PUBLIC_CLERK_SIGN_UP_URL || ''; +import { API_KEY, API_URL, API_VERSION, DOMAIN, IS_SATELLITE, PROXY_URL, SECRET_KEY } from './constants'; const clerkClient = Clerk({ apiKey: API_KEY, @@ -36,3 +20,8 @@ const createClerkClient = Clerk; export { clerkClient, createClerkClient, Clerk }; export * from '@clerk/backend'; + +/** + * @deprecated Don't export the constants. Should be marked as internal + */ +export * from './constants'; diff --git a/packages/nextjs/src/server/constants.ts b/packages/nextjs/src/server/constants.ts new file mode 100644 index 00000000000..c5c3eb71159 --- /dev/null +++ b/packages/nextjs/src/server/constants.ts @@ -0,0 +1,34 @@ +import { deprecated } from '@clerk/shared'; + +/** + * @deprecated Use `CLERK_JS_VERSION` instead. + */ +export const JS_VERSION = process.env.CLERK_JS_VERSION || ''; +if (JS_VERSION) { + deprecated('CLERK_JS_VERSION', 'Use `NEXT_PUBLIC_CLERK_JS_VERSION` environment variable instead.'); +} +export const CLERK_JS_VERSION = process.env.NEXT_PUBLIC_CLERK_JS_VERSION || ''; +export const CLERK_JS_URL = process.env.NEXT_PUBLIC_CLERK_JS || ''; +export const API_URL = process.env.CLERK_API_URL || 'https://api.clerk.dev'; +export const API_VERSION = process.env.CLERK_API_VERSION || 'v1'; +/** + * @deprecated Use `CLERK_SECRET_KEY` instead. + */ +export const API_KEY = process.env.CLERK_API_KEY || ''; +if (API_KEY) { + deprecated('CLERK_API_KEY', 'Use `CLERK_SECRET_KEY` environment variable instead.'); +} +export const SECRET_KEY = process.env.CLERK_SECRET_KEY || ''; +/** + * @deprecated Use `PUBLISHABLE_KEY` instead. + */ +export const FRONTEND_API = process.env.NEXT_PUBLIC_CLERK_FRONTEND_API || ''; +if (FRONTEND_API) { + deprecated('NEXT_PUBLIC_CLERK_FRONTEND_API', 'Use `NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY` environment variable instead.'); +} +export const PUBLISHABLE_KEY = process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY || ''; +export const DOMAIN = process.env.NEXT_PUBLIC_CLERK_DOMAIN || ''; +export const PROXY_URL = process.env.NEXT_PUBLIC_CLERK_PROXY_URL || ''; +export const IS_SATELLITE = process.env.NEXT_PUBLIC_CLERK_IS_SATELLITE === 'true' || false; +export const SIGN_IN_URL = process.env.NEXT_PUBLIC_CLERK_SIGN_IN_URL || ''; +export const SIGN_UP_URL = process.env.NEXT_PUBLIC_CLERK_SIGN_UP_URL || ''; diff --git a/packages/nextjs/src/server/utils.ts b/packages/nextjs/src/server/utils.ts index 6f239d007ca..14df666c6b6 100644 --- a/packages/nextjs/src/server/utils.ts +++ b/packages/nextjs/src/server/utils.ts @@ -1,5 +1,6 @@ import type { RequestState } from '@clerk/backend'; import { buildRequestUrl, constants } from '@clerk/backend'; +import { handleValueOrFn, isHttpOrHttps } from '@clerk/shared'; import type { NextRequest } from 'next/server'; import { NextResponse } from 'next/server'; @@ -147,32 +148,6 @@ export const injectSSRStateIntoObject = (obj: O, authObject: T) => { return { ...obj, __clerk_ssr_state }; }; -// TODO: Use the same function defined in @clerk/shared once the package is tree shakeable -type VOrFnReturnsV = T | undefined | ((v: URL) => T); - -export function handleValueOrFn(value: VOrFnReturnsV, url: URL): T | undefined; -export function handleValueOrFn(value: VOrFnReturnsV, url: URL, defaultValue: T): T; -export function handleValueOrFn(value: VOrFnReturnsV, url: URL, defaultValue?: unknown): unknown { - if (typeof value === 'function') { - return (value as (v: URL) => T)(url); - } - - if (typeof value !== 'undefined') { - return value; - } - - if (typeof defaultValue !== 'undefined') { - return defaultValue; - } - - return undefined; -} - -// TODO: use @clerk/shared once it is tree-shakeable -export function isHttpOrHttps(key: string | undefined) { - return /^http(s)?:\/\//.test(key || ''); -} - export function isDevelopmentFromApiKey(apiKey: string): boolean { return apiKey.startsWith('test_') || apiKey.startsWith('sk_test_'); } diff --git a/packages/nextjs/src/server/withClerkMiddleware.ts b/packages/nextjs/src/server/withClerkMiddleware.ts index 656f7901302..0beca065c5b 100644 --- a/packages/nextjs/src/server/withClerkMiddleware.ts +++ b/packages/nextjs/src/server/withClerkMiddleware.ts @@ -1,5 +1,6 @@ import type { RequestState } from '@clerk/backend'; import { constants, debugRequestState } from '@clerk/backend'; +import { deprecated } from '@clerk/shared'; import type { NextFetchEvent, NextMiddleware, NextRequest } from 'next/server'; import { NextResponse } from 'next/server'; @@ -36,6 +37,11 @@ export const withClerkMiddleware: WithClerkMiddleware = (...args: unknown[]) => const noop = () => undefined; const [handler = noop, opts = {}] = args as [NextMiddleware, WithAuthOptions] | []; + deprecated( + 'withClerkMiddleware', + 'Use `authMiddleware` instead.\nFor more details, consult the middleware documentation: https://clerk.com/docs/nextjs/middleware', + ); + return async (req: NextRequest, event: NextFetchEvent) => { const { isSatellite, domain, signInUrl, proxyUrl } = handleMultiDomainAndProxy(req, opts); diff --git a/packages/nextjs/src/ssr/withServerSideAuth.ts b/packages/nextjs/src/ssr/withServerSideAuth.ts index e6d710314fd..409e47ba497 100644 --- a/packages/nextjs/src/ssr/withServerSideAuth.ts +++ b/packages/nextjs/src/ssr/withServerSideAuth.ts @@ -1,5 +1,6 @@ import type { RequestState } from '@clerk/backend'; import { constants, debugRequestState } from '@clerk/backend'; +import { deprecated } from '@clerk/shared'; import type { ServerResponse } from 'http'; import type { GetServerSidePropsContext, GetServerSidePropsResult } from 'next'; @@ -43,6 +44,10 @@ const decorateResponseWithObservabilityHeaders = (res: ServerResponse, requestSt export const withServerSideAuth: WithServerSideAuth = (cbOrOptions: any, options?: any): any => { const cb = typeof cbOrOptions === 'function' ? cbOrOptions : undefined; const opts = (options ? options : typeof cbOrOptions !== 'function' ? cbOrOptions : {}) || {}; + deprecated( + 'withServerSideAuth', + 'Use `authMiddleware` instead.\nFor more details, consult the middleware documentation: https://clerk.com/docs/nextjs/middleware', + ); // Support both loadOrganization and the older loadOrg option without breaking changes // TODO: Remove pre v5 diff --git a/packages/shared/src/hooks/clerk-swr.ts b/packages/shared/src/hooks/clerk-swr.ts index c54d7d48495..060ecc68653 100644 --- a/packages/shared/src/hooks/clerk-swr.ts +++ b/packages/shared/src/hooks/clerk-swr.ts @@ -1,3 +1,4 @@ +'use client'; export * from 'swr'; export { default as useSWR } from 'swr'; export { default as useSWRInfinite } from 'swr/infinite'; diff --git a/packages/shared/src/hooks/usePagesOrInfinite.ts b/packages/shared/src/hooks/usePagesOrInfinite.ts index 3f7d64c6d16..1af2afa0233 100644 --- a/packages/shared/src/hooks/usePagesOrInfinite.ts +++ b/packages/shared/src/hooks/usePagesOrInfinite.ts @@ -1,3 +1,5 @@ +'use client'; + import { useCallback, useMemo, useRef, useState } from 'react'; import { useSWR, useSWRInfinite } from './clerk-swr'; diff --git a/turbo.json b/turbo.json index 2ea2227a0c0..db1a2977d24 100644 --- a/turbo.json +++ b/turbo.json @@ -11,7 +11,26 @@ "tsconfig.json", "tsconfig.*.json" ], - "globalEnv": ["NODE_VERSION", "NPM_VERSION", "NODE_ENV", "VERCEL"], + "globalEnv": [ + "NODE_VERSION", + "NPM_VERSION", + "NODE_ENV", + "VERCEL", + "CLERK_JS_VERSION", + "CLERK_API_URL", + "CLERK_API_VERSION", + "CLERK_API_KEY", + "CLERK_SECRET_KEY", + "NEXT_PUBLIC_CLERK_JS_VERSION", + "NEXT_PUBLIC_CLERK_JS", + "NEXT_PUBLIC_CLERK_FRONTEND_API", + "NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY", + "NEXT_PUBLIC_CLERK_DOMAIN", + "NEXT_PUBLIC_CLERK_PROXY_URL", + "NEXT_PUBLIC_CLERK_IS_SATELLITE", + "NEXT_PUBLIC_CLERK_SIGN_IN_URL", + "NEXT_PUBLIC_CLERK_SIGN_UP_URL" + ], "pipeline": { "build": { "dependsOn": ["^build"],