Skip to content
Open
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
8 changes: 0 additions & 8 deletions packages/nextjs/src/app-router/client/ClerkProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import { ClerkScripts } from '../../utils/clerk-script';
import { canUseKeyless } from '../../utils/feature-flags';
import { mergeNextClerkPropsWithEnv } from '../../utils/mergeNextClerkPropsWithEnv';
import { RouterTelemetry } from '../../utils/router-telemetry';
import { detectKeylessEnvDriftAction } from '../keyless-actions';
import { invalidateCacheAction } from '../server-actions';
import { useAwaitablePush } from './useAwaitablePush';
import { useAwaitableReplace } from './useAwaitableReplace';
Expand All @@ -31,13 +30,6 @@ const NextClientClerkProvider = <TUi extends Ui = Ui>(props: NextClerkProviderPr
const push = useAwaitablePush();
const replace = useAwaitableReplace();

// Call drift detection on mount (client-side)
useSafeLayoutEffect(() => {
if (canUseKeyless) {
void detectKeylessEnvDriftAction();
}
}, []);

// Avoid rendering nested ClerkProviders by checking for the existence of the ClerkNextOptions context provider
const isNested = Boolean(useClerkNextOptions());
if (isNested) {
Expand Down
18 changes: 2 additions & 16 deletions packages/nextjs/src/app-router/keyless-actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ export async function syncKeylessConfigAction(args: AccountlessApplication & { r
* Force middleware to execute to read the new keys from the cookies and populate the authentication state correctly.
*/
redirect(`/clerk-sync-keyless?returnUrl=${returnUrl}`, RedirectType.replace);
return;
}

return;
Expand All @@ -54,7 +53,7 @@ export async function createOrReadKeylessAction(): Promise<null | Omit<Accountle
return null;
}

const result = await import('../server/keyless-node.js').then(m => m.createOrReadKeyless()).catch(() => null);
const result = await import('../server/keyless-node.js').then(m => m.keyless().getOrCreateKeys()).catch(() => null);

if (!result) {
errorThrower.throwMissingPublishableKeyError();
Expand Down Expand Up @@ -90,19 +89,6 @@ export async function deleteKeylessAction() {
return;
}

await import('../server/keyless-node.js').then(m => m.removeKeyless()).catch(() => {});
await import('../server/keyless-node.js').then(m => m.keyless().removeKeys()).catch(() => {});
return;
}

export async function detectKeylessEnvDriftAction() {
if (!canUseKeyless) {
return;
}

try {
const { detectKeylessEnvDrift } = await import('../server/keyless-telemetry.js');
await detectKeylessEnvDrift();
} catch {
// ignore
}
}
9 changes: 0 additions & 9 deletions packages/nextjs/src/app-router/server/ClerkProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,6 @@ export async function ClerkProvider<TUi extends Ui = Ui>(

let output: ReactNode;

try {
const detectKeylessEnvDrift = await import('../../server/keyless-telemetry.js').then(
mod => mod.detectKeylessEnvDrift,
);
await detectKeylessEnvDrift();
} catch {
// ignore
}

if (shouldRunAsKeyless) {
output = (
<KeylessProvider
Expand Down
17 changes: 4 additions & 13 deletions packages/nextjs/src/app-router/server/keyless-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import type { PropsWithChildren } from 'react';
import React from 'react';

import { createClerkClientWithOptions } from '../../server/createClerkClient';
import { collectKeylessMetadata, formatMetadataHeaders } from '../../server/keyless-custom-headers';
import type { NextClerkProviderProps } from '../../types';
import { canUseKeyless } from '../../utils/feature-flags';
import { mergeNextClerkPropsWithEnv } from '../../utils/mergeNextClerkPropsWithEnv';
Expand All @@ -19,7 +18,7 @@ export async function getKeylessStatus(
let [shouldRunAsKeyless, runningWithClaimedKeys, locallyStoredPublishableKey] = [false, false, ''];
if (canUseKeyless) {
locallyStoredPublishableKey = await import('../../server/keyless-node.js')
.then(mod => mod.safeParseClerkFile()?.publishableKey || '')
.then(mod => mod.keyless().readKeys()?.publishableKey || '')
.catch(() => '');

runningWithClaimedKeys = Boolean(params.publishableKey) && params.publishableKey === locallyStoredPublishableKey;
Expand All @@ -44,7 +43,7 @@ export const KeylessProvider = async (props: KeylessProviderProps) => {

// NOTE: Create or read keys on every render. Usually this means only on hard refresh or hard navigations.
const newOrReadKeys = await import('../../server/keyless-node.js')
.then(mod => mod.createOrReadKeyless())
.then(mod => mod.keyless().getOrCreateKeys())
.catch(() => null);

const { clerkDevelopmentCache, createConfirmationMessage, createKeylessModeMessage } = await import(
Expand Down Expand Up @@ -84,7 +83,7 @@ export const KeylessProvider = async (props: KeylessProviderProps) => {

if (runningWithClaimedKeys) {
try {
const secretKey = await import('../../server/keyless-node.js').then(mod => mod.safeParseClerkFile()?.secretKey);
const secretKey = await import('../../server/keyless-node.js').then(mod => mod.keyless().readKeys()?.secretKey);
if (!secretKey) {
// we will ignore it later
throw new Error('Missing secret key from `.clerk/`');
Expand All @@ -93,20 +92,12 @@ export const KeylessProvider = async (props: KeylessProviderProps) => {
secretKey,
});

// Collect metadata
const keylessHeaders = await collectKeylessMetadata()
.then(formatMetadataHeaders)
.catch(() => new Headers());

/**
* Notifying the dashboard the should runs once. We are controlling this behaviour by caching the result of the request.
* If the request fails, it will be considered stale after 10 minutes, otherwise it is cached for 24 hours.
*/
await clerkDevelopmentCache?.run(
() =>
client.__experimental_accountlessApplications.completeAccountlessApplicationOnboarding({
requestHeaders: keylessHeaders,
}),
() => client.__experimental_accountlessApplications.completeAccountlessApplicationOnboarding(),
{
cacheKey: `${newOrReadKeys.publishableKey}_complete`,
onSuccessStale: 24 * 60 * 60 * 1000, // 24 hours
Expand Down
150 changes: 0 additions & 150 deletions packages/nextjs/src/server/keyless-custom-headers.ts

This file was deleted.

74 changes: 10 additions & 64 deletions packages/nextjs/src/server/keyless-log-cache.ts
Original file line number Diff line number Diff line change
@@ -1,64 +1,10 @@
import type { AccountlessApplication } from '@clerk/backend';
import { isDevelopmentEnvironment } from '@clerk/shared/utils';
// 10 minutes in milliseconds
const THROTTLE_DURATION_MS = 10 * 60 * 1000;

function createClerkDevCache() {
if (!isDevelopmentEnvironment()) {
return;
}

if (!global.__clerk_internal_keyless_logger) {
global.__clerk_internal_keyless_logger = {
__cache: new Map<string, { expiresAt: number; data?: unknown }>(),

log: function ({ cacheKey, msg }) {
if (this.__cache.has(cacheKey) && Date.now() < (this.__cache.get(cacheKey)?.expiresAt || 0)) {
return;
}

console.log(msg);

this.__cache.set(cacheKey, {
expiresAt: Date.now() + THROTTLE_DURATION_MS,
});
},
run: async function (
callback,
{ cacheKey, onSuccessStale = THROTTLE_DURATION_MS, onErrorStale = THROTTLE_DURATION_MS },
) {
if (this.__cache.has(cacheKey) && Date.now() < (this.__cache.get(cacheKey)?.expiresAt || 0)) {
return this.__cache.get(cacheKey)?.data;
}

try {
const result = await callback();

this.__cache.set(cacheKey, {
expiresAt: Date.now() + onSuccessStale,
data: result,
});
return result;
} catch (e) {
this.__cache.set(cacheKey, {
expiresAt: Date.now() + onErrorStale,
});

throw e;
}
},
};
}

return globalThis.__clerk_internal_keyless_logger;
}

export const createKeylessModeMessage = (keys: AccountlessApplication) => {
return `\n\x1b[35m\n[Clerk]:\x1b[0m You are running in keyless mode.\nYou can \x1b[35mclaim your keys\x1b[0m by visiting ${keys.claimUrl}\n`;
};

export const createConfirmationMessage = () => {
return `\n\x1b[35m\n[Clerk]:\x1b[0m Your application is running with your claimed keys.\nYou can safely remove the \x1b[35m.clerk/\x1b[0m from your project.\n`;
};

export const clerkDevelopmentCache = createClerkDevCache();
/**
* Re-export keyless development cache utilities from shared.
* This maintains backward compatibility with existing imports.
*/
export {
clerkDevelopmentCache,
createClerkDevCache,
createConfirmationMessage,
createKeylessModeMessage,
} from '@clerk/shared/keyless';
Loading
Loading