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
12 changes: 12 additions & 0 deletions .changeset/fifty-snakes-accept.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
'@clerk/clerk-sdk-node': major
---

Drop all pre-instantiated Backend API resources (`allowlistIdentifiers`, `clients`, `emailAddresses`, `emails`, `invitations`, `organizations`, `phoneNumbers`, `redirectUrls`, `sessions`, `signInTokens`, `users`, `domains`). Use the `clerkClient` import instead.
```typescript
// Before
import { users } from "@clerk/clerk-sdk-node"
// After
import { clerkClient } from "@clerk/clerk-sdk-node"
clerkClient.users
```
23 changes: 23 additions & 0 deletions .changeset/tasty-terms-fly.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 `@clerk/backend` exports:
- Drop Internal `deserialize` helper
Comment thread
dimkl marked this conversation as resolved.
- Introduce `/errors` subpath export, eg:
```typescript
import {
TokenVerificationError,
TokenVerificationErrorAction,
TokenVerificationErrorCode,
TokenVerificationErrorReason } from '@clerk/backend/errors';
```
- Drop errors from top-level export
```typescript
// Before
import { TokenVerificationError, TokenVerificationErrorReason } from '@clerk/backend';
// After
import { TokenVerificationError, TokenVerificationErrorReason } from '@clerk/backend/errors';
```
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,11 @@ jobs:

- name: Lint types using attw
timeout-minutes: ${{ fromJSON(vars.TIMEOUT_MINUTES_SHORT) }}
run: npx turbo lint:attw $TURBO_ARGS --filter=!nextjs --only
run: npx turbo lint:attw $TURBO_ARGS --filter=!nextjs --filter=!backend --only

- name: Lint types using attw [Errors Allowed]
timeout-minutes: ${{ fromJSON(vars.TIMEOUT_MINUTES_SHORT) }}
run: npx turbo lint:attw $TURBO_ARGS --filter=nextjs --continue --only
run: npx turbo lint:attw $TURBO_ARGS --filter=nextjs --filter=backend --continue --only
continue-on-error: true # TODO: Remove this when all related errors are fixed

- name: Run lint
Expand Down
25 changes: 23 additions & 2 deletions packages/backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,30 @@
"default": "./dist/runtime/browser/crypto.mjs"
}
},
"exports": {
".": {
"import": {
"types": "./dist/index.d.ts",
"default": "./dist/index.mjs"
},
"require": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
}
},
"./errors": {
"import": {
"types": "./dist/errors.d.ts",
"default": "./dist/errors.mjs"
},
"require": {
"types": "./dist/errors.d.ts",
"default": "./dist/errors.js"
}
},
"./package.json": "./package.json"
},
"main": "./dist/index.js",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's drop main but keep types since TS configs with moduleResolution set to node will not be able to resolve the types otherwise.

TS will use the exports field only if moduleResolution is set to node16, nodenext or bundler. Many projects still use node though, so let's not be disruptive.

Extra context: https://www.typescriptlang.org/tsconfig#moduleResolution

@dimkl dimkl Dec 15, 2023

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i will apply it as part of: #2365

"module": "./dist/esm/index.js",
"types": "./dist/types/index.d.ts",
"files": [
"dist"
],
Expand Down
16 changes: 13 additions & 3 deletions packages/backend/src/__tests__/exports.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type QUnit from 'qunit';

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

export default (QUnit: QUnit) => {
Expand Down Expand Up @@ -29,8 +30,6 @@ export default (QUnit: QUnit) => {
'Session',
'SignInToken',
'Token',
'TokenVerificationError',
'TokenVerificationErrorReason',
'User',
'Verification',
'buildRequestUrl',
Expand All @@ -40,7 +39,6 @@ export default (QUnit: QUnit) => {
'createIsomorphicRequest',
'debugRequestState',
'decodeJwt',
'deserialize',
'hasValidSignature',
'makeAuthObjectSerializable',
'prunePrivateMetadata',
Expand All @@ -55,4 +53,16 @@ export default (QUnit: QUnit) => {
assert.deepEqual(Object.keys(publicExports).sort(), exportedApiKeys);
});
});

module('subpath /errors exports', () => {
test('should not include a breaking change', assert => {
const exportedApiKeys = [
'TokenVerificationError',
'TokenVerificationErrorAction',
'TokenVerificationErrorCode',
'TokenVerificationErrorReason',
];
assert.deepEqual(Object.keys(errorExports).sort(), exportedApiKeys);
});
});
};
1 change: 0 additions & 1 deletion packages/backend/src/api/resources/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
export * from './AllowlistIdentifier';
export * from './Client';
export * from './DeletedObject';
export * from './Deserializer';
export * from './Email';
export * from './EmailAddress';

Expand Down
File renamed without changes.
11 changes: 9 additions & 2 deletions packages/backend/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { TelemetryCollectorOptions } from '@clerk/shared/telemetry';
import { TelemetryCollector } from '@clerk/shared/telemetry';
import type { SDKMetadata } from '@clerk/types';

import type { CreateBackendApiOptions } from './api';
import type { ApiClient, CreateBackendApiOptions } from './api';
import { createBackendApiClient } from './api';
import type { CreateAuthenticateRequestOptions } from './tokens';
import { createAuthenticateRequest } from './tokens';
Expand All @@ -25,7 +25,14 @@ export type ClerkOptions = CreateBackendApiOptions &
>
> & { sdkMetadata?: SDKMetadata; telemetry?: Pick<TelemetryCollectorOptions, 'disabled' | 'debug'> };

export function createClerkClient(options: ClerkOptions) {
// The current exported type resolves the following issue in packages importing createClerkClient
// TS4023: Exported variable 'clerkClient' has or is using name 'AuthErrorReason' from external module "/packages/backend/dist/index" but cannot be named.
export type ClerkClient = {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discussed offline, problematic area with types and type inference, will come back to this after v5 or next week.

telemetry: TelemetryCollector;
} & ApiClient &
ReturnType<typeof createAuthenticateRequest>;

export function createClerkClient(options: ClerkOptions): ClerkClient {
const opts = { ...options };
const apiClient = createBackendApiClient(opts);
const requestState = createAuthenticateRequest({ options: opts, apiClient });
Expand Down
2 changes: 1 addition & 1 deletion packages/backend/src/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
*/

// @ts-ignore - These are package subpaths
import crypto from '#crypto';
import { webcrypto as crypto } from '#crypto';

type Runtime = {
crypto: Crypto;
Expand Down
2 changes: 1 addition & 1 deletion packages/backend/src/runtime/browser/crypto.mjs
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export default crypto;
export const webcrypto = crypto;
12 changes: 1 addition & 11 deletions packages/backend/src/runtime/node/crypto.js
Original file line number Diff line number Diff line change
@@ -1,11 +1 @@
let webcrypto;
try {
webcrypto = require('node:crypto').webcrypto;
if (!webcrypto) {
webcrypto = global.crypto;
}
} catch (e) {
webcrypto = global.crypto;
}

module.exports = webcrypto;
module.exports.webcrypto = require('node:crypto').webcrypto;
2 changes: 1 addition & 1 deletion packages/backend/src/tokens/__tests__/keys.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 { TokenVerificationError, TokenVerificationErrorAction, TokenVerificationErrorReason } from '../../errors';
import runtime from '../../runtime';
import { jsonError, jsonOk } from '../../util/testUtils';
import { TokenVerificationError, TokenVerificationErrorAction, TokenVerificationErrorReason } from '../errors';
import {
mockJwks,
mockJwtPayload,
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
@@ -1,10 +1,10 @@
import type QUnit from 'qunit';
import sinon from 'sinon';

import { TokenVerificationErrorReason } from '../../errors';
import runtime from '../../runtime';
import { jsonOk } from '../../util/testUtils';
import { AuthErrorReason, type AuthReason, AuthStatus, type RequestState } from '../authStatus';
import { TokenVerificationErrorReason } from '../errors';
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/authStatus.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import type { JwtPayload } from '@clerk/types';

import { createBackendApiClient } from '../api';
import type { TokenVerificationErrorReason } from '../errors';
import type { SignedInAuthObject, SignedInAuthObjectOptions, SignedOutAuthObject } from './authObjects';
import { signedInAuthObject, signedOutAuthObject } from './authObjects';
import type { TokenVerificationErrorReason } from './errors';

export enum AuthStatus {
SignedIn = 'signed-in',
Expand Down
2 changes: 1 addition & 1 deletion packages/backend/src/tokens/handshake.ts
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 { decodeJwt, hasValidSignature, type VerifyJwtOptions } from './jwt';
import { assertHeaderAlgorithm, assertHeaderType } from './jwt/assertions';
import { loadClerkJWKFromLocal, loadClerkJWKFromRemote } from './keys';
Expand Down
1 change: 0 additions & 1 deletion packages/backend/src/tokens/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
export * from './authObjects';
export { AuthStatus } from './authStatus';
export type { RequestState } from './authStatus';
export { TokenVerificationError, TokenVerificationErrorReason } from './errors';
export * from './factory';
export { debugRequestState } from './request';
export type { AuthenticateRequestOptions, OptionalVerifyTokenOptions } from './request';
2 changes: 1 addition & 1 deletion packages/backend/src/tokens/jwt/assertions.ts
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
2 changes: 1 addition & 1 deletion packages/backend/src/tokens/jwt/verifyJwt.ts
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';
// 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 { TokenVerificationError, TokenVerificationErrorAction, TokenVerificationErrorReason } from '../errors';
import { getCryptoAlgorithm } from './algorithms';
import {
assertActivationClaim,
Expand Down
12 changes: 6 additions & 6 deletions packages/backend/src/tokens/keys.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { API_URL, API_VERSION, JWKS_CACHE_TTL_MS, MAX_CACHE_LAST_UPDATED_AT_SECONDS } from '../constants';
import {
TokenVerificationError,
TokenVerificationErrorAction,
TokenVerificationErrorCode,
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 { joinPaths } from '../util/path';
import { getErrorObjectByCode } from '../util/request';
import { callWithRetry } from '../util/shared';
import {
TokenVerificationError,
TokenVerificationErrorAction,
TokenVerificationErrorCode,
TokenVerificationErrorReason,
} from './errors';

type JsonWebKeyWithKid = JsonWebKey & { kid: string };

Expand Down
4 changes: 2 additions & 2 deletions packages/backend/src/tokens/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ import { parsePublishableKey } from '@clerk/shared/keys';
import type { JwtPayload } from '@clerk/types';

import { constants } from '../constants';
import type { TokenCarrier } from '../errors';
import { TokenVerificationError, TokenVerificationErrorReason } from '../errors';
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 type { TokenCarrier } from './errors';
import { TokenVerificationError, TokenVerificationErrorReason } from './errors';
import { verifyHandshakeToken } from './handshake';
import { decodeJwt } from './jwt';
import { verifyToken, type VerifyTokenOptions } from './verify';
Expand Down
2 changes: 1 addition & 1 deletion packages/backend/src/tokens/verify.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { JwtPayload } from '@clerk/types';

import { TokenVerificationError, TokenVerificationErrorAction, TokenVerificationErrorReason } from './errors';
import { TokenVerificationError, TokenVerificationErrorAction, TokenVerificationErrorReason } from '../errors';
import type { VerifyJwtOptions } from './jwt';
import { decodeJwt, verifyJwt } from './jwt';
import type { LoadClerkJWKFromRemoteOptions } from './keys';
Expand Down
2 changes: 1 addition & 1 deletion packages/backend/tsconfig.declarations.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
"emitDeclarationOnly": true,
"declarationMap": true,
"sourceMap": false,
"declarationDir": "./dist/types"
"declarationDir": "./dist"
}
}
3 changes: 1 addition & 2 deletions 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'],
entry: ['src/index.ts', 'src/errors.ts'],
onSuccess: `cpy 'src/runtime/**/*.{mjs,js,cjs}' dist/runtime`,
sourcemap: true,
define: {
Expand All @@ -19,7 +19,6 @@ export default defineConfig(overrideOptions => {
__DEV__: `${isWatch}`,
},
external: ['#crypto'],
legacyOutput: true,
bundle: true,
clean: true,
minify: false,
Expand Down
13 changes: 0 additions & 13 deletions packages/sdk-node/src/__tests__/__snapshots__/exports.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,10 @@ exports[`module exports should not change unless explicitly set 1`] = `
"Session",
"SignInToken",
"Token",
"TokenVerificationError",
"TokenVerificationErrorReason",
"User",
"Verification",
"allowlistIdentifiers",
"buildRequestUrl",
"clerkClient",
"clients",
"constants",
"createAuthenticateRequest",
"createClerkClient",
Expand All @@ -41,24 +37,15 @@ exports[`module exports should not change unless explicitly set 1`] = `
"createIsomorphicRequest",
"debugRequestState",
"decodeJwt",
"deserialize",
"domains",
"emailAddresses",
"emails",
"hasValidSignature",
"invitations",
"makeAuthObjectSerializable",
"organizations",
"phoneNumbers",
"prunePrivateMetadata",
"redirect",
"requireAuth",
"sanitizeAuthObject",
"sessions",
"signJwt",
"signedInAuthObject",
"signedOutAuthObject",
"users",
"verifyJwt",
"verifyToken",
"withAuth",
Expand Down
Loading