Skip to content

Commit 71e971a

Browse files
authored
chore(nextjs): Decrease frequency of logs related to Keyless (#4953)
1 parent 3c0de05 commit 71e971a

File tree

6 files changed

+86
-16
lines changed

6 files changed

+86
-16
lines changed

.changeset/eighty-clocks-dance.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@clerk/nextjs': patch
3+
---
4+
5+
Decrease frequency of logs related to Keyless.

packages/nextjs/src/app-router/keyless-actions.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,16 @@ export async function createOrReadKeylessAction(): Promise<null | Omit<Accountle
4141
return null;
4242
}
4343

44+
const { keylessLogger, createKeylessModeMessage } = await import('../server/keyless-log-cache.js');
45+
46+
/**
47+
* Notify developers.
48+
*/
49+
keylessLogger?.log({
50+
cacheKey: result.publishableKey,
51+
msg: createKeylessModeMessage(result),
52+
});
53+
4454
const { claimUrl, publishableKey, secretKey, apiKeysUrl } = result;
4555

4656
void (await cookies()).set(getKeylessCookieName(), JSON.stringify({ claimUrl, publishableKey, secretKey }), {

packages/nextjs/src/app-router/server/ClerkProvider.tsx

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,11 @@ export async function ClerkProvider(
7777
if (shouldRunAsKeyless) {
7878
// NOTE: Create or read keys on every render. Usually this means only on hard refresh or hard navigations.
7979
const newOrReadKeys = await import('../../server/keyless-node.js').then(mod => mod.createOrReadKeyless());
80+
const { keylessLogger, createConfirmationMessage, createKeylessModeMessage } = await import(
81+
'../../server/keyless-log-cache.js'
82+
);
8083

8184
if (newOrReadKeys) {
82-
const KeylessCookieSync = await import('../client/keyless-cookie-sync.js').then(mod => mod.KeylessCookieSync);
8385
const clientProvider = (
8486
<ClientClerkProvider
8587
{...mergeNextClerkPropsWithEnv({
@@ -97,8 +99,26 @@ export async function ClerkProvider(
9799
);
98100

99101
if (runningWithClaimedKeys) {
102+
/**
103+
* Notify developers.
104+
*/
105+
keylessLogger?.log({
106+
cacheKey: `${newOrReadKeys.publishableKey}_claimed`,
107+
msg: createConfirmationMessage(),
108+
});
109+
100110
output = clientProvider;
101111
} else {
112+
const KeylessCookieSync = await import('../client/keyless-cookie-sync.js').then(mod => mod.KeylessCookieSync);
113+
114+
/**
115+
* Notify developers.
116+
*/
117+
keylessLogger?.log({
118+
cacheKey: newOrReadKeys.publishableKey,
119+
msg: createKeylessModeMessage(newOrReadKeys),
120+
});
121+
102122
output = <KeylessCookieSync {...newOrReadKeys}>{clientProvider}</KeylessCookieSync>;
103123
}
104124
}

packages/nextjs/src/global.d.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,13 @@ interface Window {
2121

2222
declare const PACKAGE_NAME: string;
2323
declare const PACKAGE_VERSION: string;
24+
25+
declare module globalThis {
26+
// eslint-disable-next-line no-var
27+
var __clerk_internal_keyless_logger:
28+
| {
29+
__cache: Map<string, { expiresAt: number }>;
30+
log: (param: { cacheKey: string; msg: string }) => void;
31+
}
32+
| undefined;
33+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import type { AccountlessApplication } from '@clerk/backend';
2+
import { isDevelopmentEnvironment } from '@clerk/shared/utils';
3+
// 10 minutes in milliseconds
4+
const THROTTLE_DURATION_MS = 10 * 60 * 1000;
5+
6+
function createClerkDevLogger() {
7+
if (!isDevelopmentEnvironment()) {
8+
return;
9+
}
10+
11+
if (!global.__clerk_internal_keyless_logger) {
12+
global.__clerk_internal_keyless_logger = {
13+
__cache: new Map<string, { expiresAt: number }>(),
14+
15+
log: function ({ cacheKey, msg }: { cacheKey: string; msg: string }) {
16+
if (this.__cache.has(cacheKey) && Date.now() < (this.__cache.get(cacheKey)?.expiresAt || 0)) {
17+
return;
18+
}
19+
20+
console.log(msg);
21+
22+
this.__cache.set(cacheKey, {
23+
expiresAt: Date.now() + THROTTLE_DURATION_MS,
24+
});
25+
},
26+
};
27+
}
28+
29+
return globalThis.__clerk_internal_keyless_logger;
30+
}
31+
32+
export const createKeylessModeMessage = (keys: AccountlessApplication) => {
33+
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`;
34+
};
35+
36+
export const createConfirmationMessage = () => {
37+
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`;
38+
};
39+
40+
export const keylessLogger = createClerkDevLogger();

packages/nextjs/src/server/keyless-node.ts

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import type { AccountlessApplication } from '@clerk/backend';
2-
import { logger } from '@clerk/shared/logger';
32

43
/**
54
* Attention: Only import this module when the node runtime is used.
@@ -87,10 +86,6 @@ export function safeParseClerkFile(): AccountlessApplication | undefined {
8786
}
8887
}
8988

90-
const createMessage = (keys: AccountlessApplication) => {
91-
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`;
92-
};
93-
9489
/**
9590
* Using both an in-memory and file system lock seems to be the most effective solution.
9691
*/
@@ -154,11 +149,6 @@ async function createOrReadKeyless(): Promise<AccountlessApplication | undefined
154149
if (envVarsMap?.publishableKey && envVarsMap?.secretKey) {
155150
unlockFileWriting();
156151

157-
/**
158-
* Notify developers.
159-
*/
160-
logger.logOnce(createMessage(envVarsMap));
161-
162152
return envVarsMap;
163153
}
164154

@@ -168,11 +158,6 @@ async function createOrReadKeyless(): Promise<AccountlessApplication | undefined
168158
const client = createClerkClientWithOptions({});
169159
const accountlessApplication = await client.__experimental_accountlessApplications.createAccountlessApplication();
170160

171-
/**
172-
* Notify developers.
173-
*/
174-
logger.logOnce(createMessage(accountlessApplication));
175-
176161
writeFileSync(CONFIG_PATH, JSON.stringify(accountlessApplication), {
177162
encoding: 'utf8',
178163
mode: '0777',

0 commit comments

Comments
 (0)