Skip to content

Commit

Permalink
chore(backend): Expose /internal subpath export
Browse files Browse the repository at this point in the history
  • Loading branch information
dimkl committed Dec 15, 2023
1 parent 637d245 commit 3821d39
Show file tree
Hide file tree
Showing 40 changed files with 194 additions and 72 deletions.
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

0 comments on commit 3821d39

Please sign in to comment.