diff --git a/.changeset/eighty-swans-trade.md b/.changeset/eighty-swans-trade.md index addb3926466..cd5cd110725 100644 --- a/.changeset/eighty-swans-trade.md +++ b/.changeset/eighty-swans-trade.md @@ -2,7 +2,7 @@ '@clerk/shared': patch --- -Apply deprecation warnings: +Apply deprecation warnings for `@clerk/shared`: - `OrganizationContext` - `organizationList` - `useOrganizations` diff --git a/.changeset/late-carrots-notice.md b/.changeset/late-carrots-notice.md index a051c9607da..a0c75d9d571 100644 --- a/.changeset/late-carrots-notice.md +++ b/.changeset/late-carrots-notice.md @@ -1,5 +1,5 @@ --- '@clerk/clerk-react': patch --- - -Warn about `setSession` deprecation. +Apply deprecation warnings for `@clerk/clerk-react`: +- `setSession` diff --git a/.changeset/silent-fishes-change.md b/.changeset/silent-fishes-change.md index ed10e1ea9b4..172c0e2c479 100644 --- a/.changeset/silent-fishes-change.md +++ b/.changeset/silent-fishes-change.md @@ -2,4 +2,4 @@ '@clerk/backend': minor --- -Replace utilities with @clerk/shared exports +Replace utilities with `@clerk/shared` exports diff --git a/.changeset/spicy-toys-change.md b/.changeset/spicy-toys-change.md index e79bd7a4cb4..c3a0649afb5 100644 --- a/.changeset/spicy-toys-change.md +++ b/.changeset/spicy-toys-change.md @@ -2,4 +2,9 @@ '@clerk/nextjs': patch --- -Warn about deprecations that will be dropped in next major version +Apply deprecation warnings for `@clerk/nextjs`: +- `CLERK_JS_VERSION` environment variable +- `CLERK_API_KEY` environment variable +- `NEXT_PUBLIC_CLERK_FRONTEND_API` environment variable +- `withClerkMiddleware` +- `withServerSideAuth` \ No newline at end of file diff --git a/.changeset/two-ads-type.md b/.changeset/two-ads-type.md new file mode 100644 index 00000000000..e2500803378 --- /dev/null +++ b/.changeset/two-ads-type.md @@ -0,0 +1,14 @@ +--- +"@clerk/backend": patch +--- + +Apply deprecation warnings for `@clerk/backend`: +- backend api return format +- `clockSkewInSeconds` +- `pkgVersion` +- `picture`/`logoUrl`/`profileImageUrl` +- `InterstitialAPI` +- `httpOptions` +- `apiKey` +- `frontendApi` +- `__unstable_options` diff --git a/packages/backend/src/api/endpoints/InterstitialApi.ts b/packages/backend/src/api/endpoints/InterstitialApi.ts index 49bae182153..2ce6cc967c3 100644 --- a/packages/backend/src/api/endpoints/InterstitialApi.ts +++ b/packages/backend/src/api/endpoints/InterstitialApi.ts @@ -1,10 +1,15 @@ +import { deprecated } from '../../util/shared'; import { AbstractAPI } from './AbstractApi'; - /** * @deprecated Switch to the public interstitial endpoint from Clerk Backend API. */ export class InterstitialAPI extends AbstractAPI { public async getInterstitial() { + deprecated( + 'getInterstitial()', + 'Switch to `Clerk(...).localInterstitial(...)` from `import { Clerk } from "@clerk/backend"`.', + ); + return this.request({ path: 'internal/interstitial', method: 'GET', diff --git a/packages/backend/src/api/request.ts b/packages/backend/src/api/request.ts index 130d47c0596..e7ed19bc0b9 100644 --- a/packages/backend/src/api/request.ts +++ b/packages/backend/src/api/request.ts @@ -8,6 +8,7 @@ import { API_URL, API_VERSION, constants, USER_AGENT } from '../constants'; import runtime from '../runtime'; import { assertValidSecretKey } from '../util/assertValidSecretKey'; import { joinPaths } from '../util/path'; +import { deprecated } from '../util/shared'; import type { CreateBackendApiOptions } from './factory'; import { deserialize } from './resources/Deserializer'; @@ -50,6 +51,11 @@ type LegacyRequestFunction = (requestOptions: ClerkBackendApiRequestOptions) const withLegacyReturn = (cb: any): LegacyRequestFunction => async (...args) => { + deprecated( + '', + 'Resources return format will switch to `{ data: any, errors: ClerkAPIError[] }` from `data | never` the next major version.', + 'resources-legacy-return', + ); // @ts-ignore const { data, errors, status, statusText } = await cb(...args); if (errors === null) { @@ -67,11 +73,21 @@ export function buildRequest(options: CreateBackendApiOptions) { const { apiKey, secretKey, + httpOptions, apiUrl = API_URL, apiVersion = API_VERSION, userAgent = USER_AGENT, - httpOptions = {}, } = options; + if (apiKey) { + deprecated('apiKey', 'Use `secretKey` instead.'); + } + if (httpOptions) { + deprecated( + 'httpOptions', + 'This option has been deprecated and will be removed with the next major release.\nA RequestInit init object used by the `request` method.', + ); + } + const { path, method, queryParams, headerParams, bodyParams, formData } = requestOptions; const key = secretKey || apiKey; @@ -119,7 +135,7 @@ export function buildRequest(options: CreateBackendApiOptions) { res = await runtime.fetch( finalUrl.href, - deepmerge(httpOptions, { + deepmerge(httpOptions || {}, { method, headers, ...body, diff --git a/packages/backend/src/api/resources/ExternalAccount.ts b/packages/backend/src/api/resources/ExternalAccount.ts index 24de8f99a46..e1baa47b24d 100644 --- a/packages/backend/src/api/resources/ExternalAccount.ts +++ b/packages/backend/src/api/resources/ExternalAccount.ts @@ -1,3 +1,4 @@ +import { deprecatedProperty } from '../../util/shared'; import type { ExternalAccountJSON } from './JSON'; import { Verification } from './Verification'; @@ -41,3 +42,5 @@ export class ExternalAccount { ); } } + +deprecatedProperty(ExternalAccount, 'picture', 'Use `imageUrl` instead.'); diff --git a/packages/backend/src/api/resources/Organization.ts b/packages/backend/src/api/resources/Organization.ts index ac1dcdc7c1f..8766520f1e7 100644 --- a/packages/backend/src/api/resources/Organization.ts +++ b/packages/backend/src/api/resources/Organization.ts @@ -1,3 +1,4 @@ +import { deprecatedProperty } from '../../util/shared'; import type { OrganizationJSON } from './JSON'; export class Organization { @@ -40,3 +41,5 @@ export class Organization { ); } } + +deprecatedProperty(Organization, 'logoUrl', 'Use `imageUrl` instead.'); diff --git a/packages/backend/src/api/resources/OrganizationMembership.ts b/packages/backend/src/api/resources/OrganizationMembership.ts index a318bb4a9c0..d3b9ed0dd49 100644 --- a/packages/backend/src/api/resources/OrganizationMembership.ts +++ b/packages/backend/src/api/resources/OrganizationMembership.ts @@ -1,3 +1,4 @@ +import { deprecatedProperty } from '../../util/shared'; import { Organization } from '../resources'; import type { OrganizationMembershipRole } from './Enums'; import type { OrganizationMembershipJSON, OrganizationMembershipPublicUserDataJSON } from './JSON'; @@ -54,3 +55,5 @@ export class OrganizationMembershipPublicUserData { ); } } + +deprecatedProperty(OrganizationMembershipPublicUserData, 'profileImageUrl', 'Use `imageUrl` instead.'); diff --git a/packages/backend/src/api/resources/User.ts b/packages/backend/src/api/resources/User.ts index a3c5b4ea7b8..937cd170767 100644 --- a/packages/backend/src/api/resources/User.ts +++ b/packages/backend/src/api/resources/User.ts @@ -1,3 +1,4 @@ +import { deprecatedProperty } from '../../util/shared'; import { EmailAddress } from './EmailAddress'; import { ExternalAccount } from './ExternalAccount'; import type { ExternalAccountJSON, UserJSON } from './JSON'; @@ -72,3 +73,5 @@ export class User { ); } } + +deprecatedProperty(User, 'profileImageUrl', 'Use `imageUrl` instead.'); diff --git a/packages/backend/src/index.ts b/packages/backend/src/index.ts index f7e28f3fb4b..9879546c9e3 100644 --- a/packages/backend/src/index.ts +++ b/packages/backend/src/index.ts @@ -1,3 +1,5 @@ +import { deprecatedObjectProperty } from '@clerk/shared'; + import type { CreateBackendApiOptions } from './api'; import { createBackendApiClient } from './api'; import type { CreateAuthenticateRequestOptions } from './tokens'; @@ -26,7 +28,7 @@ export function Clerk(options: ClerkOptions) { const apiClient = createBackendApiClient(opts); const requestState = createAuthenticateRequest({ options: opts, apiClient }); - return { + const clerkInstance = { ...apiClient, ...requestState, /** @@ -34,4 +36,14 @@ export function Clerk(options: ClerkOptions) { */ __unstable_options: opts, }; + + // The __unstable_options is not being used internally and + // it's only being set in packages/sdk-node/src/clerkClient.ts#L86 + deprecatedObjectProperty( + clerkInstance, + '__unstable_options', + 'Use `createClerkClient({...})` to create a new clerk instance instead.', + ); + + return clerkInstance; } diff --git a/packages/backend/src/redirections.ts b/packages/backend/src/redirections.ts index 76f96b7c12b..d5a96877774 100644 --- a/packages/backend/src/redirections.ts +++ b/packages/backend/src/redirections.ts @@ -1,4 +1,4 @@ -import { errorThrower, parsePublishableKey } from './util/shared'; +import { deprecated, errorThrower, parsePublishableKey } from './util/shared'; type RedirectAdapter = (url: string) => any; @@ -39,6 +39,8 @@ type RedirectParams = { export function redirect({ redirectAdapter, signUpUrl, signInUrl, frontendApi, publishableKey }: RedirectParams) { if (!frontendApi) { frontendApi = parsePublishableKey(publishableKey)?.frontendApi; + } else { + deprecated('frontentApi', 'Use `publishableKey` instead.'); } const accountsBaseUrl = buildAccountsBaseUrl(frontendApi); diff --git a/packages/backend/src/tokens/interstitial.ts b/packages/backend/src/tokens/interstitial.ts index b5d434fbddb..64721a06db8 100644 --- a/packages/backend/src/tokens/interstitial.ts +++ b/packages/backend/src/tokens/interstitial.ts @@ -8,6 +8,7 @@ import { joinPaths } from '../util/path'; import { addClerkPrefix, callWithRetry, + deprecated, getClerkJsMajorVersionOrTag, getScriptUrl, isDevOrStagingUrl, @@ -33,6 +34,13 @@ export type LoadInterstitialOptions = { } & MultiDomainAndOrProxyPrimitives; export function loadInterstitialFromLocal(options: Omit) { + if (options.frontendApi) { + deprecated('frontentApi', 'Use `publishableKey` instead.'); + } + if (options.pkgVersion) { + deprecated('pkgVersion', 'Use `clerkJSVersion` instead.'); + } + options.frontendApi = parsePublishableKey(options.publishableKey)?.frontendApi || options.frontendApi || ''; const domainOnlyInProd = !isDevOrStagingUrl(options.frontendApi) ? addClerkPrefix(options.domain) : ''; const { @@ -126,6 +134,12 @@ export function loadInterstitialFromLocal(options: Omit @@ -149,6 +163,10 @@ export async function loadInterstitialFromBAPI(options: LoadInterstitialOptions) } export function buildPublicInterstitialUrl(options: LoadInterstitialOptions) { + if (options.frontendApi) { + deprecated('frontentApi', 'Use `publishableKey` instead.'); + } + options.frontendApi = parsePublishableKey(options.publishableKey)?.frontendApi || options.frontendApi || ''; const { apiUrl, frontendApi, pkgVersion, clerkJSVersion, publishableKey, proxyUrl, isSatellite, domain, signInUrl } = options; diff --git a/packages/backend/src/tokens/jwt/verifyJwt.ts b/packages/backend/src/tokens/jwt/verifyJwt.ts index ca7bcec6e63..c22321f2606 100644 --- a/packages/backend/src/tokens/jwt/verifyJwt.ts +++ b/packages/backend/src/tokens/jwt/verifyJwt.ts @@ -4,6 +4,7 @@ import type { Jwt, JwtPayload } from '@clerk/types'; // For more information refer to https://sinonjs.org/how-to/stub-dependency/ import runtime from '../../runtime'; import { base64url } from '../../util/rfc4648'; +import { deprecated } from '../../util/shared'; import { TokenVerificationError, TokenVerificationErrorAction, TokenVerificationErrorReason } from '../errors'; import type { IssuerResolver } from './assertions'; import { @@ -114,6 +115,10 @@ export async function verifyJwt( token: string, { audience, authorizedParties, clockSkewInSeconds, clockSkewInMs, issuer, key }: VerifyJwtOptions, ): Promise { + if (clockSkewInSeconds) { + deprecated('clockSkewInSeconds', 'Use `clockSkewInMs` instead.'); + } + const clockSkew = clockSkewInMs || clockSkewInSeconds || DEFAULT_CLOCK_SKEW_IN_SECONDS; const decoded = decodeJwt(token); diff --git a/packages/backend/src/tokens/request.ts b/packages/backend/src/tokens/request.ts index 991677b2700..45ef18b409b 100644 --- a/packages/backend/src/tokens/request.ts +++ b/packages/backend/src/tokens/request.ts @@ -1,7 +1,7 @@ import { API_URL, API_VERSION, constants } from '../constants'; import { assertValidSecretKey } from '../util/assertValidSecretKey'; import { buildRequest, stripAuthorizationHeader } from '../util/IsomorphicRequest'; -import { isDevelopmentFromApiKey, parsePublishableKey } from '../util/shared'; +import { deprecated, isDevelopmentFromApiKey, parsePublishableKey } from '../util/shared'; import type { RequestState } from './authStatus'; import { AuthErrorReason, interstitial, signedOut, unknownState } from './authStatus'; import type { TokenCarrier } from './errors'; @@ -120,6 +120,14 @@ function assertProxyUrlOrDomain(proxyUrlOrDomain: string | undefined) { export async function authenticateRequest(options: AuthenticateRequestOptions): Promise { const { cookies, headers, searchParams } = buildRequest(options?.request); + if (options.frontendApi) { + deprecated('frontentApi', 'Use `publishableKey` instead.'); + } + + if (options.apiKey) { + deprecated('apiKey', 'Use `secretKey` instead.'); + } + options = { ...options, frontendApi: parsePublishableKey(options.publishableKey)?.frontendApi || options.frontendApi, diff --git a/packages/backend/src/tokens/verify.ts b/packages/backend/src/tokens/verify.ts index 96290c11648..eaa565306c8 100644 --- a/packages/backend/src/tokens/verify.ts +++ b/packages/backend/src/tokens/verify.ts @@ -1,5 +1,6 @@ import type { JwtPayload } from '@clerk/types'; +import { deprecated } from '../util/shared'; import { TokenVerificationError, TokenVerificationErrorAction, TokenVerificationErrorReason } from './errors'; import type { VerifyJwtOptions } from './jwt'; import { decodeJwt, verifyJwt } from './jwt'; @@ -33,6 +34,10 @@ export async function verifyToken(token: string, options: VerifyTokenOptions): P skipJwksCache, } = options; + if (options.apiKey) { + deprecated('apiKey', 'Use `secretKey` instead.'); + } + const { header } = decodeJwt(token); const { kid } = header; diff --git a/packages/backend/src/util/shared.ts b/packages/backend/src/util/shared.ts index 0da270edba0..de2bd9a6ae5 100644 --- a/packages/backend/src/util/shared.ts +++ b/packages/backend/src/util/shared.ts @@ -6,6 +6,8 @@ export { isDevelopmentFromApiKey, isProductionFromApiKey, parsePublishableKey, + deprecated, + deprecatedProperty, } from '@clerk/shared'; import { buildErrorThrower } from '@clerk/shared';