Skip to content

Commit

Permalink
chore(*): Improve @clerk/backend DX [Part 4 - Jwt subpath exports] (#…
Browse files Browse the repository at this point in the history
…2364)

* chore(backend): Expose /jwt subpath export for jwt related utils

* chore(backend): Move /tokens/jwt to top-level and replace jwt.ts

* chore(repo): Add changeset
  • Loading branch information
dimkl committed Dec 15, 2023
1 parent 0ec3a14 commit f58a994
Show file tree
Hide file tree
Showing 25 changed files with 73 additions and 39 deletions.
23 changes: 23 additions & 0 deletions .changeset/slimy-ties-approve.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
'@clerk/clerk-sdk-node': major
'@clerk/backend': major
'@clerk/nextjs': major
---

Changes in exports of `@clerk/backend`:
- Expose the following helpers and enums from `@clerk/backend/jwt`:
```typescript
import {
decodeJwt,
hasValidSignature,
signJwt,
verifyJwt } from '@clerk/backend/jwt';
```
- Drop the above exports from the top-level api:
```typescript
// Before
import { decodeJwt, ... } from '@clerk/backend';
// After
import { decodeJwt, ... } from '@clerk/backend/jwt';
```
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 @@ -55,6 +55,16 @@
"default": "./dist/internal.js"
}
},
"./jwt": {
"import": {
"types": "./dist/jwt/index.d.ts",
"default": "./dist/jwt/index.mjs"
},
"require": {
"types": "./dist/jwt/index.d.ts",
"default": "./dist/jwt/index.js"
}
},
"./package.json": "./package.json"
},
"main": "./dist/index.js",
Expand Down
12 changes: 8 additions & 4 deletions packages/backend/src/__tests__/exports.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type QUnit from 'qunit';
import * as errorExports from '../errors';
import * as publicExports from '../index';
import * as internalExports from '../internal';
import * as jwtExports from '../jwt';

export default (QUnit: QUnit) => {
const { module, test } = QUnit;
Expand Down Expand Up @@ -33,10 +34,6 @@ export default (QUnit: QUnit) => {
'User',
'Verification',
'createClerkClient',
'decodeJwt',
'hasValidSignature',
'signJwt',
'verifyJwt',
'verifyToken',
];
assert.deepEqual(Object.keys(publicExports).sort(), exportedApiKeys);
Expand Down Expand Up @@ -74,4 +71,11 @@ export default (QUnit: QUnit) => {
assert.deepEqual(Object.keys(internalExports).sort(), exportedApiKeys);
});
});

module('subpath /jwt exports', () => {
test('should not include a breaking change', assert => {
const exportedApiKeys = ['decodeJwt', 'hasValidSignature', 'signJwt', 'verifyJwt'];
assert.deepEqual(Object.keys(jwtExports).sort(), exportedApiKeys);
});
});
};
File renamed without changes.
4 changes: 2 additions & 2 deletions packages/backend/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import type { CreateAuthenticateRequestOptions } from './tokens/factory';
import { createAuthenticateRequest } from './tokens/factory';

export * from './api/resources';
export * from './tokens/jwt';
export * from './tokens/verify';
export type { VerifyTokenOptions } from './tokens/verify';
export { verifyToken } from './tokens/verify';

export type ClerkOptions = CreateBackendApiOptions &
Partial<
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { TokenVerificationError, TokenVerificationErrorAction, TokenVerificationErrorReason } from '../../errors';
import { TokenVerificationError, TokenVerificationErrorAction, TokenVerificationErrorReason } from '../errors';
import { algs } from './algorithms';

export type IssuerResolver = string | ((iss: string) => boolean);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { isomorphicAtob } from '@clerk/shared/isomorphicAtob';

import runtime from '../../runtime';
import runtime from '../runtime';

// https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/importKey#pkcs_8_import
function pemToBuffer(secret: string): ArrayBuffer {
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import runtime from '../../runtime';
import { base64url } from '../../util/rfc4648';
import runtime from '../runtime';
import { base64url } from '../util/rfc4648';
import { getCryptoAlgorithm } from './algorithms';
import { importKey } from './cryptoKeys';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import type { Jwt, JwtPayload } from '@clerk/types';

import { TokenVerificationError, TokenVerificationErrorAction, TokenVerificationErrorReason } from '../../errors';
import { TokenVerificationError, TokenVerificationErrorAction, TokenVerificationErrorReason } from '../errors';
// DO NOT CHANGE: Runtime needs to be imported as a default export so that we can stub its dependencies with Sinon.js
// For more information refer to https://sinonjs.org/how-to/stub-dependency/
import runtime from '../../runtime';
import { base64url } from '../../util/rfc4648';
import runtime from '../runtime';
import { base64url } from '../util/rfc4648';
import { getCryptoAlgorithm } from './algorithms';
import {
assertActivationClaim,
Expand Down
6 changes: 3 additions & 3 deletions packages/backend/src/tokens/__tests__/keys.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ import type QUnit from 'qunit';
import sinon from 'sinon';

import { TokenVerificationError, TokenVerificationErrorAction, TokenVerificationErrorReason } from '../../errors';
import runtime from '../../runtime';
import { jsonError, jsonOk } from '../../util/testUtils';
import {
mockJwks,
mockJwtPayload,
Expand All @@ -12,7 +10,9 @@ import {
mockPEMKey,
mockRsaJwk,
mockRsaJwkKid,
} from '../fixtures';
} from '../../fixtures';
import runtime from '../../runtime';
import { jsonError, jsonOk } from '../../util/testUtils';
import { loadClerkJWKFromLocal, loadClerkJWKFromRemote } from '../keys';

export default (QUnit: QUnit) => {
Expand Down
2 changes: 1 addition & 1 deletion packages/backend/src/tokens/__tests__/request.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import type QUnit from 'qunit';
import sinon from 'sinon';

import { TokenVerificationErrorReason } from '../../errors';
import { mockInvalidSignatureJwt, mockJwks, mockJwt, mockJwtPayload, mockMalformedJwt } from '../../fixtures';
import runtime from '../../runtime';
import { jsonOk } from '../../util/testUtils';
import { AuthErrorReason, type AuthReason, AuthStatus, type RequestState } from '../authStatus';
import { mockInvalidSignatureJwt, mockJwks, mockJwt, mockJwtPayload, mockMalformedJwt } from '../fixtures';
import type { AuthenticateRequestOptions } from '../request';
import { authenticateRequest, loadOptionsFromHeaders } from '../request';

Expand Down
2 changes: 1 addition & 1 deletion packages/backend/src/tokens/__tests__/verify.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import type QUnit from 'qunit';
import sinon from 'sinon';

import { mockJwks, mockJwt, mockJwtPayload } from '../../fixtures';
import runtime from '../../runtime';
import { jsonOk } from '../../util/testUtils';
import { mockJwks, mockJwt, mockJwtPayload } from '../fixtures';
import { verifyToken } from '../verify';

export default (QUnit: QUnit) => {
Expand Down
5 changes: 3 additions & 2 deletions packages/backend/src/tokens/handshake.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { TokenVerificationError, TokenVerificationErrorAction, TokenVerificationErrorReason } from '../errors';
import { decodeJwt, hasValidSignature, type VerifyJwtOptions } from './jwt';
import { assertHeaderAlgorithm, assertHeaderType } from './jwt/assertions';
import type { VerifyJwtOptions } from '../jwt';
import { decodeJwt, hasValidSignature } from '../jwt';
import { assertHeaderAlgorithm, assertHeaderType } from '../jwt/assertions';
import { loadClerkJWKFromLocal, loadClerkJWKFromRemote } from './keys';
import type { VerifyTokenOptions } from './verify';

Expand Down
2 changes: 1 addition & 1 deletion packages/backend/src/tokens/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ import type { JwtPayload } from '@clerk/types';
import { constants } from '../constants';
import type { TokenCarrier } from '../errors';
import { TokenVerificationError, TokenVerificationErrorReason } from '../errors';
import { decodeJwt } from '../jwt';
import { assertValidSecretKey } from '../util/assertValidSecretKey';
import { buildRequest, stripAuthorizationHeader } from '../util/IsomorphicRequest';
import { isDevelopmentFromSecretKey } from '../util/shared';
import type { AuthStatusOptionsType, RequestState } from './authStatus';
import { AuthErrorReason, handshake, signedIn, signedOut } from './authStatus';
import { verifyHandshakeToken } from './handshake';
import { decodeJwt } from './jwt';
import { verifyToken, type VerifyTokenOptions } from './verify';

/**
Expand Down
4 changes: 2 additions & 2 deletions packages/backend/src/tokens/verify.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import type { JwtPayload } from '@clerk/types';

import { TokenVerificationError, TokenVerificationErrorAction, TokenVerificationErrorReason } from '../errors';
import type { VerifyJwtOptions } from './jwt';
import { decodeJwt, verifyJwt } from './jwt';
import type { VerifyJwtOptions } from '../jwt';
import { decodeJwt, verifyJwt } from '../jwt';
import type { LoadClerkJWKFromRemoteOptions } from './keys';
import { loadClerkJWKFromLocal, loadClerkJWKFromRemote } from './keys';

Expand Down
20 changes: 10 additions & 10 deletions packages/backend/tests/suites.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
// Import all suites
// TODO: Automate this step using dynamic imports

import authObjectsTest from './dist/tokens/__tests__/authObjects.test.js';
import cryptoKeysTest from './dist/tokens/jwt/__tests__/cryptoKeys.test.js';
import exportsTest from './dist/__tests__/exports.test.js';
import redirectTest from './dist/__tests__/redirections.test.js';
import utilsTest from './dist/__tests__/utils.test.js';
import factoryTest from './dist/api/__tests__/factory.test.js';
import jwtAssertionsTest from './dist/tokens/jwt/__tests__/assertions.test.js';
import jwtAssertionsTest from './dist/jwt/__tests__/assertions.test.js';
import cryptoKeysTest from './dist/jwt/__tests__/cryptoKeys.test.js';
import signJwtTest from './dist/jwt/__tests__/signJwt.test.js';
import verifyJwtTest from './dist/jwt/__tests__/verifyJwt.test.js';
import authObjectsTest from './dist/tokens/__tests__/authObjects.test.js';
import tokenFactoryTest from './dist/tokens/__tests__/factory.test.js';
import keysTest from './dist/tokens/__tests__/keys.test.js';
import pathTest from './dist/util/__tests__/path.test.js';
import redirectTest from './dist/__tests__/redirections.test.js';
import requestTest from './dist/tokens/__tests__/request.test.js';
import signJwtTest from './dist/tokens/jwt/__tests__/signJwt.test.js';
import tokenFactoryTest from './dist/tokens/__tests__/factory.test.js';
import utilRequestTest from './dist/util/__tests__/request.test.js';
import utilsTest from './dist/__tests__/utils.test.js';
import verifyJwtTest from './dist/tokens/jwt/__tests__/verifyJwt.test.js';
import verifyTest from './dist/tokens/__tests__/verify.test.js';
import pathTest from './dist/util/__tests__/path.test.js';
import utilRequestTest from './dist/util/__tests__/request.test.js';

// Add them to the suite array
const suites = [
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', 'src/internal.ts'],
entry: ['src/index.ts', 'src/errors.ts', 'src/internal.ts', 'src/jwt/index.ts'],
onSuccess: `cpy 'src/runtime/**/*.{mjs,js,cjs}' dist/runtime`,
sourcemap: true,
define: {
Expand Down
2 changes: 1 addition & 1 deletion packages/nextjs/src/server/getAuth.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import type { Organization, Session, User } from '@clerk/backend';
import { decodeJwt } from '@clerk/backend';
import type { SignedInAuthObject, SignedOutAuthObject } from '@clerk/backend/internal';
import {
AuthStatus,
Expand All @@ -9,6 +8,7 @@ import {
signedInAuthObject,
signedOutAuthObject,
} from '@clerk/backend/internal';
import { decodeJwt } from '@clerk/backend/jwt';

import { withLogger } from '../utils/debugLogger';
import { API_URL, API_VERSION, SECRET_KEY } from './constants';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,7 @@ exports[`module exports should not change unless explicitly set 1`] = `
"createClerkClient",
"createClerkExpressRequireAuth",
"createClerkExpressWithAuth",
"decodeJwt",
"hasValidSignature",
"requireAuth",
"signJwt",
"verifyJwt",
"verifyToken",
"withAuth",
]
Expand Down

0 comments on commit f58a994

Please sign in to comment.