Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions .changeset/red-suns-perform.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
'gatsby-plugin-clerk': major
'@clerk/clerk-sdk-node': major
'@clerk/backend': major
'@clerk/fastify': major
'@clerk/nextjs': major
'@clerk/remix': major
---

Changes in exports of `@clerk/backend`:
- Expose the following helpers and enums from `@clerk/backend/internal`:
```typescript
import {
AuthStatus,
buildRequestUrl,
constants,
createAuthenticateRequest,
createIsomorphicRequest,
debugRequestState,
makeAuthObjectSerializable,
prunePrivateMetadata,
redirect,
sanitizeAuthObject,
signedInAuthObject,
signedOutAuthObject } from '@clerk/backend/internal';
```
- Drop the above exports from the top-level api:
```typescript
// Before
import { AuthStatus, ... } from '@clerk/backend';
// After
import { AuthStatus, ... } from '@clerk/backend/internal';
```
Dropping those exports results in also dropping the exports from `gatsby-plugin-clerk`, `@clerk/clerk-sdk-node`, `@clerk/backend`, `@clerk/fastify`, `@clerk/nextjs`, `@clerk/remix` packages.
10 changes: 10 additions & 0 deletions packages/backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,16 @@
"default": "./dist/errors.js"
}
},
"./internal": {
"import": {
"types": "./dist/internal.d.ts",
"default": "./dist/internal.mjs"
},
"require": {
"types": "./dist/internal.d.ts",
"default": "./dist/internal.js"
}
},
"./package.json": "./package.json"
},
"main": "./dist/index.js",
Expand Down
33 changes: 21 additions & 12 deletions packages/backend/src/__tests__/exports.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type QUnit from 'qunit';

import * as errorExports from '../errors';
import * as publicExports from '../index';
import * as internalExports from '../internal';

export default (QUnit: QUnit) => {
const { module, test } = QUnit;
Expand All @@ -10,7 +11,6 @@ export default (QUnit: QUnit) => {
test('should not include a breaking change', assert => {
const exportedApiKeys = [
'AllowlistIdentifier',
'AuthStatus',
'Client',
'DeletedObject',
'Email',
Expand All @@ -32,21 +32,10 @@ export default (QUnit: QUnit) => {
'Token',
'User',
'Verification',
'buildRequestUrl',
'constants',
'createAuthenticateRequest',
'createClerkClient',
'createIsomorphicRequest',
'debugRequestState',
'decodeJwt',
'hasValidSignature',
'makeAuthObjectSerializable',
'prunePrivateMetadata',
'redirect',
'sanitizeAuthObject',
'signJwt',
'signedInAuthObject',
'signedOutAuthObject',
'verifyJwt',
'verifyToken',
];
Expand All @@ -65,4 +54,24 @@ export default (QUnit: QUnit) => {
assert.deepEqual(Object.keys(errorExports).sort(), exportedApiKeys);
});
});

module('subpath /internal exports', () => {
test('should not include a breaking change', assert => {
const exportedApiKeys = [
'AuthStatus',
'buildRequestUrl',
'constants',
'createAuthenticateRequest',
'createIsomorphicRequest',
'debugRequestState',
'makeAuthObjectSerializable',
'prunePrivateMetadata',
'redirect',
'sanitizeAuthObject',
'signedInAuthObject',
'signedOutAuthObject',
];
assert.deepEqual(Object.keys(internalExports).sort(), exportedApiKeys);
});
});
};
3 changes: 3 additions & 0 deletions packages/backend/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ const ContentTypes = {
Json: 'application/json',
} as const;

/**
* @internal
*/
export const constants = {
Attributes,
Cookies,
Expand Down
10 changes: 2 additions & 8 deletions packages/backend/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,12 @@ import type { SDKMetadata } from '@clerk/types';

import type { ApiClient, CreateBackendApiOptions } from './api';
import { createBackendApiClient } from './api';
import type { CreateAuthenticateRequestOptions } from './tokens';
import { createAuthenticateRequest } from './tokens';

export { createIsomorphicRequest } from './util/IsomorphicRequest';
import type { CreateAuthenticateRequestOptions } from './tokens/factory';
import { createAuthenticateRequest } from './tokens/factory';

export * from './api/resources';
export * from './tokens';
export * from './tokens/jwt';
export * from './tokens/verify';
export { constants } from './constants';
export { redirect } from './redirections';
export { buildRequestUrl } from './utils';

export type ClerkOptions = CreateBackendApiOptions &
Partial<
Expand Down
28 changes: 28 additions & 0 deletions packages/backend/src/internal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
export { constants } from './constants';
export { redirect } from './redirections';
export { buildRequestUrl } from './utils';

export type { CreateAuthenticateRequestOptions } from './tokens/factory';
export { createAuthenticateRequest } from './tokens/factory';

export { debugRequestState } from './tokens/request';

export type { AuthenticateRequestOptions, OptionalVerifyTokenOptions } from './tokens/request';

export type {
SignedInAuthObjectOptions,
SignedInAuthObject,
SignedOutAuthObject,
AuthObject,
} from './tokens/authObjects';
export {
makeAuthObjectSerializable,
sanitizeAuthObject,
prunePrivateMetadata,
signedOutAuthObject,
signedInAuthObject,
} from './tokens/authObjects';
export { createIsomorphicRequest } from './util/IsomorphicRequest';

export { AuthStatus } from './tokens/authStatus';
export type { RequestState } from './tokens/authStatus';
3 changes: 3 additions & 0 deletions packages/backend/src/redirections.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ type RedirectParams = {
publishableKey?: string;
};

/**
* @internal
*/
export function redirect({ redirectAdapter, signUpUrl, signInUrl, publishableKey }: RedirectParams) {
const frontendApi = parsePublishableKey(publishableKey)?.frontendApi;
const accountsBaseUrl = buildAccountsBaseUrl(frontendApi);
Expand Down
25 changes: 25 additions & 0 deletions packages/backend/src/tokens/authObjects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,19 @@ type AuthObjectDebugData = Record<string, any>;
type CreateAuthObjectDebug = (data?: AuthObjectDebugData) => AuthObjectDebug;
type AuthObjectDebug = () => AuthObjectDebugData;

/**
* @internal
*/
export type SignedInAuthObjectOptions = CreateBackendApiOptions & {
token: string;
session?: Session;
user?: User;
organization?: Organization;
};

/**
* @internal
*/
export type SignedInAuthObject = {
sessionClaims: JwtPayload;
sessionId: string;
Expand All @@ -39,6 +45,9 @@ export type SignedInAuthObject = {
debug: AuthObjectDebug;
};

/**
* @internal
*/
export type SignedOutAuthObject = {
sessionClaims: null;
sessionId: null;
Expand All @@ -56,6 +65,9 @@ export type SignedOutAuthObject = {
debug: AuthObjectDebug;
};

/**
* @internal
*/
export type AuthObject = SignedInAuthObject | SignedOutAuthObject;

const createDebug: CreateAuthObjectDebug = data => {
Expand All @@ -67,6 +79,9 @@ const createDebug: CreateAuthObjectDebug = data => {
};
};

/**
* @internal
*/
export function signedInAuthObject(
sessionClaims: JwtPayload,
options: SignedInAuthObjectOptions,
Expand Down Expand Up @@ -112,6 +127,9 @@ export function signedInAuthObject(
};
}

/**
* @internal
*/
export function signedOutAuthObject(debugData?: AuthObjectDebugData): SignedOutAuthObject {
return {
sessionClaims: null,
Expand All @@ -131,6 +149,9 @@ export function signedOutAuthObject(debugData?: AuthObjectDebugData): SignedOutA
};
}

/**
* @internal
*/
export function prunePrivateMetadata(
resource?:
| {
Expand All @@ -152,6 +173,9 @@ export function prunePrivateMetadata(
return resource;
}

/**
* @internal
*/
export function sanitizeAuthObject<T extends Record<any, any>>(authObject: T): T {
const user = authObject.user ? { ...authObject.user } : authObject.user;
const organization = authObject.organization ? { ...authObject.organization } : authObject.organization;
Expand All @@ -168,6 +192,7 @@ export function sanitizeAuthObject<T extends Record<any, any>>(authObject: T): T
* Some frameworks like Remix or Next (/pages dir only) handle this serialization by simply
* ignoring any non-serializable keys, however Nextjs /app directory is stricter and
* throws an error if a non-serializable value is found.
* @internal
*/
export const makeAuthObjectSerializable = <T extends Record<string, unknown>>(obj: T): T => {
// remove any non-serializable props from the returned object
Expand Down
6 changes: 6 additions & 0 deletions packages/backend/src/tokens/authStatus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import type { TokenVerificationErrorReason } from '../errors';
import type { SignedInAuthObject, SignedInAuthObjectOptions, SignedOutAuthObject } from './authObjects';
import { signedInAuthObject, signedOutAuthObject } from './authObjects';

/**
* @internal
*/
export enum AuthStatus {
SignedIn = 'signed-in',
SignedOut = 'signed-out',
Expand Down Expand Up @@ -66,6 +69,9 @@ export enum AuthErrorReason {

export type AuthReason = AuthErrorReason | TokenVerificationErrorReason;

/**
* @internal
*/
export type RequestState = SignedInState | SignedOutState | HandshakeState;

type LoadResourcesOptions = {
Expand Down
6 changes: 6 additions & 0 deletions packages/backend/src/tokens/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,17 @@ const defaultOptions = {
audience: '',
} satisfies BuildTimeOptions;

/**
* @internal
*/
export type CreateAuthenticateRequestOptions = {
options: BuildTimeOptions;
apiClient: ApiClient;
};

/**
* @internal
*/
export function createAuthenticateRequest(params: CreateAuthenticateRequestOptions) {
const buildTimeOptions = mergePreDefinedOptions(defaultOptions, params.options);

Expand Down
6 changes: 0 additions & 6 deletions packages/backend/src/tokens/index.ts

This file was deleted.

9 changes: 9 additions & 0 deletions packages/backend/src/tokens/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,19 @@ import { verifyHandshakeToken } from './handshake';
import { decodeJwt } from './jwt';
import { verifyToken, type VerifyTokenOptions } from './verify';

/**
* @internal
*/
export type OptionalVerifyTokenOptions = Partial<
Pick<
VerifyTokenOptions,
'audience' | 'authorizedParties' | 'clockSkewInMs' | 'jwksCacheTtlInMs' | 'skipJwksCache' | 'jwtKey'
>
>;

/**
* @internal
*/
export type AuthenticateRequestOptions = AuthStatusOptionsType & OptionalVerifyTokenOptions;

function assertSignInUrlExists(signInUrl: string | undefined, key: string): asserts signInUrl is string {
Expand Down Expand Up @@ -303,6 +309,9 @@ ${err.getFullMessage()}`,
return authenticateRequestWithTokenInCookie();
}

/**
* @internal
*/
export const debugRequestState = (params: RequestState) => {
const { isSignedIn, proxyUrl, reason, message, publishableKey, isSatellite, domain } = params;
return { isSignedIn, proxyUrl, reason, message, publishableKey, isSatellite, domain };
Expand Down
3 changes: 3 additions & 0 deletions packages/backend/src/util/IsomorphicRequest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import runtime from '../runtime';
import { buildRequestUrl } from '../utils';

type IsomorphicRequestOptions = (Request: typeof runtime.Request, Headers: typeof runtime.Headers) => Request;
/**
* @internal
*/
export const createIsomorphicRequest = (cb: IsomorphicRequestOptions): Request => {
const req = cb(runtime.Request, runtime.Headers);
// Used to fix request.url using the x-forwarded-* headers
Expand Down
6 changes: 6 additions & 0 deletions packages/backend/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ const getHeader = (req: Request, key: string) => req.headers.get(key);
const getFirstValueFromHeader = (value?: string | null) => value?.split(',')[0];

type BuildRequestUrl = (request: Request) => URL;
/**
* @internal
*/
export const buildRequestUrl: BuildRequestUrl = request => {
const initialUrl = new URL(request.url);

Expand All @@ -25,6 +28,9 @@ type BuildOriginParams = {
host?: string | null;
};
type BuildOrigin = (params: BuildOriginParams) => string;
/**
* @internal
*/
export const buildOrigin: BuildOrigin = ({ protocol, forwardedProto, forwardedHost, host }) => {
const resolvedHost = getFirstValueFromHeader(forwardedHost) ?? host;
const resolvedProtocol = getFirstValueFromHeader(forwardedProto) ?? protocol?.replace(/[:/]/, '');
Expand Down
2 changes: 1 addition & 1 deletion packages/backend/tsup.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export default defineConfig(overrideOptions => {
const shouldPublish = !!overrideOptions.env?.publish;

const common: Options = {
entry: ['src/index.ts', 'src/errors.ts'],
entry: ['src/index.ts', 'src/errors.ts', 'src/internal.ts'],
onSuccess: `cpy 'src/runtime/**/*.{mjs,js,cjs}' dist/runtime`,
sourcemap: true,
define: {
Expand Down
2 changes: 1 addition & 1 deletion packages/fastify/src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { constants } from '@clerk/backend';
import { constants } from '@clerk/backend/internal';
import { apiUrlFromPublishableKey } from '@clerk/shared/apiUrlFromPublishableKey';

export const API_VERSION = process.env.CLERK_API_VERSION || 'v1';
Expand Down
2 changes: 1 addition & 1 deletion packages/fastify/src/getAuth.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { AuthObject } from '@clerk/backend';
import type { AuthObject } from '@clerk/backend/internal';
import type { FastifyRequest } from 'fastify';

import { pluginRegistrationRequired } from './errors';
Expand Down
Loading