Skip to content

Commit

Permalink
Merge pull request #1806 from clerkinc/revert-1767
Browse files Browse the repository at this point in the history
fix(nextjs,shared): Revert "Use `use client` directive to support sha…
  • Loading branch information
nikosdouvlis authored Sep 29, 2023
2 parents d1ad5ac + cecf74d commit d2dd6e1
Show file tree
Hide file tree
Showing 29 changed files with 14,415 additions and 11,011 deletions.
7 changes: 7 additions & 0 deletions .changeset/fair-cobras-explain.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@clerk/backend': patch
'@clerk/shared': patch
'@clerk/nextjs': patch
---

Temporarily revert internal change to resolve RSC-related errors
25,075 changes: 14,202 additions & 10,873 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion packages/backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@
"test:cloudflare-workerd": "tests/cloudflare-workerd/run.sh"
},
"dependencies": {
"@clerk/shared": "^0.24.0",
"@clerk/types": "^3.53.0",
"@peculiar/webcrypto": "1.4.1",
"@types/node": "16.18.6",
Expand Down
7 changes: 1 addition & 6 deletions packages/backend/src/api/endpoints/InterstitialApi.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
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<string>({
path: 'internal/interstitial',
method: 'GET',
Expand Down
3 changes: 0 additions & 3 deletions packages/backend/src/api/endpoints/OrganizationApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import type {
} from '../resources';
import type { OrganizationMembershipRole } from '../resources/Enums';
import { AbstractAPI } from './AbstractApi';
import { deprecated } from '@clerk/shared';

const basePath = '/organizations';

Expand Down Expand Up @@ -256,8 +255,6 @@ export class OrganizationAPI extends AbstractAPI {
* @deprecated Use `getOrganizationInvitationList` instead along with the status parameter.
*/
public async getPendingOrganizationInvitationList(params: GetPendingOrganizationInvitationListParams) {
deprecated('getPendingOrganizationInvitationList', 'Use `getOrganizationInvitationList` instead.');

const { organizationId, limit, offset } = params;
this.requireId(organizationId);

Expand Down
20 changes: 2 additions & 18 deletions packages/backend/src/api/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ 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';

Expand Down Expand Up @@ -51,11 +50,6 @@ type LegacyRequestFunction = <T>(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<T>(...args);
if (errors === null) {
Expand All @@ -73,21 +67,11 @@ 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;

Expand Down Expand Up @@ -135,7 +119,7 @@ export function buildRequest(options: CreateBackendApiOptions) {

res = await runtime.fetch(
finalUrl.href,
deepmerge(httpOptions || {}, {
deepmerge(httpOptions, {
method,
headers,
...body,
Expand Down
3 changes: 0 additions & 3 deletions packages/backend/src/api/resources/ExternalAccount.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { deprecatedProperty } from '../../util/shared';
import type { ExternalAccountJSON } from './JSON';
import { Verification } from './Verification';

Expand Down Expand Up @@ -42,5 +41,3 @@ export class ExternalAccount {
);
}
}

deprecatedProperty(ExternalAccount, 'picture', 'Use `imageUrl` instead.');
3 changes: 0 additions & 3 deletions packages/backend/src/api/resources/Organization.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { deprecatedProperty } from '../../util/shared';
import type { OrganizationJSON } from './JSON';

export class Organization {
Expand Down Expand Up @@ -41,5 +40,3 @@ export class Organization {
);
}
}

deprecatedProperty(Organization, 'logoUrl', 'Use `imageUrl` instead.');
3 changes: 0 additions & 3 deletions packages/backend/src/api/resources/OrganizationMembership.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { deprecatedProperty } from '../../util/shared';
import { Organization } from '../resources';
import type { OrganizationMembershipRole } from './Enums';
import type { OrganizationMembershipJSON, OrganizationMembershipPublicUserDataJSON } from './JSON';
Expand Down Expand Up @@ -55,5 +54,3 @@ export class OrganizationMembershipPublicUserData {
);
}
}

deprecatedProperty(OrganizationMembershipPublicUserData, 'profileImageUrl', 'Use `imageUrl` instead.');
3 changes: 0 additions & 3 deletions packages/backend/src/api/resources/User.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { deprecatedProperty } from '../../util/shared';
import { EmailAddress } from './EmailAddress';
import { ExternalAccount } from './ExternalAccount';
import type { ExternalAccountJSON, UserJSON } from './JSON';
Expand Down Expand Up @@ -73,5 +72,3 @@ export class User {
);
}
}

deprecatedProperty(User, 'profileImageUrl', 'Use `imageUrl` instead.');
14 changes: 1 addition & 13 deletions packages/backend/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { deprecatedObjectProperty } from '@clerk/shared';

import type { CreateBackendApiOptions } from './api';
import { createBackendApiClient } from './api';
import type { CreateAuthenticateRequestOptions } from './tokens';
Expand Down Expand Up @@ -28,22 +26,12 @@ export function Clerk(options: ClerkOptions) {
const apiClient = createBackendApiClient(opts);
const requestState = createAuthenticateRequest({ options: opts, apiClient });

const clerkInstance = {
return {
...apiClient,
...requestState,
/**
* @deprecated This prop has been deprecated and will be removed in the next major release.
*/
__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;
}
4 changes: 2 additions & 2 deletions packages/backend/src/redirections.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export default (QUnit: QUnit) => {
assert.raises(
() => redirectToSignIn({ returnBackUrl }),
new Error(
'@clerk/backend: Missing publishableKey. You can get your key at https://dashboard.clerk.com/last-active?path=api-keys.',
'Missing publishableKey. You can get your key at https://dashboard.clerk.com/last-active?path=api-keys.',
),
);
});
Expand Down Expand Up @@ -221,7 +221,7 @@ export default (QUnit: QUnit) => {
assert.raises(
() => redirectToSignUp({ returnBackUrl }),
new Error(
'@clerk/backend: Missing publishableKey. You can get your key at https://dashboard.clerk.com/last-active?path=api-keys.',
'Missing publishableKey. You can get your key at https://dashboard.clerk.com/last-active?path=api-keys.',
),
);
});
Expand Down
9 changes: 4 additions & 5 deletions packages/backend/src/redirections.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { deprecated, errorThrower, parsePublishableKey } from './util/shared';
import { missingPublishableKeyErrorMessage } from './shared';
import { parsePublishableKey } from './shared';

type RedirectAdapter = (url: string) => any;

Expand Down Expand Up @@ -39,15 +40,13 @@ 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);

const redirectToSignUp = ({ returnBackUrl }: SignUpParams = {}) => {
if (!signUpUrl && !accountsBaseUrl) {
errorThrower.throwMissingPublishableKeyError();
throw new Error(missingPublishableKeyErrorMessage);
}

const accountsSignUpUrl = `${accountsBaseUrl}/sign-up`;
Expand All @@ -56,7 +55,7 @@ export function redirect({ redirectAdapter, signUpUrl, signInUrl, frontendApi, p

const redirectToSignIn = ({ returnBackUrl }: SignInParams = {}) => {
if (!signInUrl && !accountsBaseUrl) {
errorThrower.throwMissingPublishableKeyError();
throw new Error(missingPublishableKeyErrorMessage);
}

const accountsSignInUrl = `${accountsBaseUrl}/sign-in`;
Expand Down
23 changes: 23 additions & 0 deletions packages/backend/src/shared/callWithRetry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
function wait(ms: number) {
return new Promise(res => setTimeout(res, ms));
}

const MAX_NUMBER_OF_RETRIES = 5;

// TODO: Move this to @clerk/shared and reuse it with @clerk/clerk-js
export async function callWithRetry<T>(
fn: (...args: unknown[]) => Promise<T>,
attempt = 1,
maxAttempts = MAX_NUMBER_OF_RETRIES,
): Promise<T> {
try {
return await fn();
} catch (e) {
if (attempt >= maxAttempts) {
throw e;
}
await wait(2 ** attempt * 100);

return callWithRetry(fn, attempt + 1);
}
}
15 changes: 15 additions & 0 deletions packages/backend/src/shared/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
* This module will contain functionality that will be copied
* from @clerk/shared and will be replaced by imports when the
* bundling issue is fixed.
*/
export { isDevelopmentFromApiKey, isProductionFromApiKey, isStaging } from './instance';

export { addClerkPrefix, getScriptUrl, getClerkJsMajorVersionOrTag } from './url';
export { callWithRetry } from './callWithRetry';

// TODO: replace it with @clerk/shared errorThrower.throwMissingPublishableKeyError()
export const missingPublishableKeyErrorMessage = `Missing publishableKey. You can get your key at https://dashboard.clerk.com/last-active?path=api-keys.`;

export { isDevOrStagingUrl } from './isDevOrStagingUrl';
export { buildPublishableKey, isPublishableKey, parsePublishableKey } from './parsePublishableKey';
16 changes: 16 additions & 0 deletions packages/backend/src/shared/instance.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export function isDevelopmentFromApiKey(apiKey: string): boolean {
return apiKey.startsWith('test_') || apiKey.startsWith('sk_test_');
}

export function isProductionFromApiKey(apiKey: string): boolean {
return apiKey.startsWith('live_') || apiKey.startsWith('sk_live_');
}

export function isStaging(frontendApi: string): boolean {
return (
frontendApi.endsWith('.lclstage.dev') ||
frontendApi.endsWith('.stgstage.dev') ||
frontendApi.endsWith('.clerkstage.dev') ||
frontendApi.endsWith('.accountsstage.dev')
);
}
35 changes: 35 additions & 0 deletions packages/backend/src/shared/isDevOrStagingUrl.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// TODO: use the same function from @clerk/shared once treeshakable
function createDevOrStagingUrlCache() {
const DEV_OR_STAGING_SUFFIXES = [
'.lcl.dev',
'.stg.dev',
'.lclstage.dev',
'.stgstage.dev',
'.dev.lclclerk.com',
'.stg.lclclerk.com',
'.accounts.lclclerk.com',
'accountsstage.dev',
'accounts.dev',
];

const devOrStagingUrlCache = new Map<string, boolean>();

return {
isDevOrStagingUrl: (url: string | URL): boolean => {
if (!url) {
return false;
}

const hostname = typeof url === 'string' ? url : url.hostname;
let res = devOrStagingUrlCache.get(hostname);
if (res === undefined) {
res = DEV_OR_STAGING_SUFFIXES.some(s => hostname.endsWith(s));
devOrStagingUrlCache.set(hostname, res);
}
return res;
},
};
}

const { isDevOrStagingUrl } = createDevOrStagingUrlCache();
export { isDevOrStagingUrl };
56 changes: 56 additions & 0 deletions packages/backend/src/shared/parsePublishableKey.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import type { PublishableKey } from '@clerk/types';

const PUBLISHABLE_KEY_LIVE_PREFIX = 'pk_live_';
const PUBLISHABLE_KEY_TEST_PREFIX = 'pk_test_';

// This regex matches the publishable like frontend API keys (e.g. foo-bar-13.clerk.accounts.dev)
const PUBLISHABLE_FRONTEND_API_DEV_REGEX = /^(([a-z]+)-){2}([0-9]{1,2})\.clerk\.accounts([a-z.]*)(dev|com)$/i;

export function buildPublishableKey(frontendApi: string): string {
const keyPrefix = PUBLISHABLE_FRONTEND_API_DEV_REGEX.test(frontendApi)
? PUBLISHABLE_KEY_TEST_PREFIX
: PUBLISHABLE_KEY_LIVE_PREFIX;
return `${keyPrefix}${btoa(`${frontendApi}$`)}`;
}

export function parsePublishableKey(key: string | undefined): PublishableKey | null {
key = key || '';

if (!isPublishableKey(key)) {
return null;
}

const instanceType = key.startsWith(PUBLISHABLE_KEY_LIVE_PREFIX) ? 'production' : 'development';

let frontendApi = isomorphicAtob(key.split('_')[2]);

if (!frontendApi.endsWith('$')) {
return null;
}

frontendApi = frontendApi.slice(0, -1);

return {
instanceType,
frontendApi,
};
}

export function isPublishableKey(key: string) {
key = key || '';

const hasValidPrefix = key.startsWith(PUBLISHABLE_KEY_LIVE_PREFIX) || key.startsWith(PUBLISHABLE_KEY_TEST_PREFIX);

const hasValidFrontendApiPostfix = isomorphicAtob(key.split('_')[2] || '').endsWith('$');

return hasValidPrefix && hasValidFrontendApiPostfix;
}

const isomorphicAtob = (data: string) => {
if (typeof atob !== 'undefined' && typeof atob === 'function') {
return atob(data);
} else if (typeof globalThis !== 'undefined' && globalThis.Buffer) {
return new globalThis.Buffer(data, 'base64').toString();
}
return data;
};
Loading

0 comments on commit d2dd6e1

Please sign in to comment.