Skip to content

Commit 62a7567

Browse files
committed
Merge branch 'main' into vincent-and-the-doctor
2 parents 6688d44 + f47b5a3 commit 62a7567

File tree

16 files changed

+492
-29
lines changed

16 files changed

+492
-29
lines changed

.changeset/cold-bottles-watch.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@clerk/clerk-js': patch
3+
'@clerk/shared': patch
4+
---
5+
6+
Propagate locale from ClerkProvider to PaymentElement

.changeset/heavy-badgers-beam.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@clerk/clerk-js': patch
3+
---
4+
5+
Remove last used badge from rendering on sign-up.

.changeset/modern-cars-fall.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@clerk/clerk-js': patch
3+
---
4+
5+
Optimize Session.#hydrateCache to only cache token if it's new/different

.changeset/silly-jars-shave.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
---
2+
---

.typedoc/custom-theme.mjs

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ class ClerkMarkdownThemeContext extends MarkdownThemeContext {
4444

4545
const superPartials = this.partials;
4646

47+
this._insideFunctionSignature = false;
48+
4749
this.partials = {
4850
...superPartials,
4951
/**
@@ -153,10 +155,17 @@ class ClerkMarkdownThemeContext extends MarkdownThemeContext {
153155
);
154156
}
155157

158+
const prevInsideParams = this._insideFunctionSignature;
159+
this._insideFunctionSignature = true;
156160
md.push(this.partials.signatureParameters(model.parameters || []));
161+
this._insideFunctionSignature = prevInsideParams;
157162

158163
if (model.type) {
159-
md.push(`: ${this.partials.someType(model.type)}`);
164+
const prevInsideType = this._insideFunctionSignature;
165+
this._insideFunctionSignature = true;
166+
const typeOutput = this.partials.someType(model.type);
167+
this._insideFunctionSignature = prevInsideType;
168+
md.push(`: ${typeOutput}`);
160169
}
161170

162171
const result = md.join('');
@@ -353,6 +362,11 @@ class ClerkMarkdownThemeContext extends MarkdownThemeContext {
353362
.replace(/<code>/g, '')
354363
.replace(/<\/code>/g, '');
355364

365+
// Only wrap in <code> if NOT inside a function signature
366+
if (this._insideFunctionSignature) {
367+
return output;
368+
}
369+
356370
return `<code>${output}</code>`;
357371
},
358372
/**
@@ -371,6 +385,11 @@ class ClerkMarkdownThemeContext extends MarkdownThemeContext {
371385
.replace(/<code>/g, '')
372386
.replace(/<\/code>/g, '');
373387

388+
// Only wrap in <code> if NOT inside a function signature
389+
if (this._insideFunctionSignature) {
390+
return output;
391+
}
392+
374393
return `<code>${output}</code>`;
375394
},
376395
/**
@@ -394,6 +413,11 @@ class ClerkMarkdownThemeContext extends MarkdownThemeContext {
394413
)
395414
.join(delimiter);
396415

416+
// Only wrap in <code> if NOT inside a function signature
417+
if (this._insideFunctionSignature) {
418+
return output;
419+
}
420+
397421
return `<code>${output}</code>`;
398422
},
399423
/**
@@ -492,6 +516,32 @@ ${tabs}
492516
.replace(/<code>/g, '')
493517
.replace(/<\/code>/g, '');
494518

519+
// Only wrap in <code> if NOT inside a function signature
520+
if (this._insideFunctionSignature) {
521+
return output;
522+
}
523+
524+
return `<code>${output}</code>`;
525+
},
526+
/**
527+
* Ensures that reflection types (like Simplify wrapped types) are wrapped in a single codeblock
528+
* @param {import('typedoc').ReflectionType} model
529+
*/
530+
reflectionType: model => {
531+
const defaultOutput = superPartials.reflectionType(model);
532+
533+
const output = defaultOutput
534+
// Remove any backticks
535+
.replace(/`/g, '')
536+
// Remove any `<code>` and `</code>` tags
537+
.replace(/<code>/g, '')
538+
.replace(/<\/code>/g, '');
539+
540+
// Only wrap in <code> if NOT inside a function signature
541+
if (this._insideFunctionSignature) {
542+
return output;
543+
}
544+
495545
return `<code>${output}</code>`;
496546
},
497547
/**

integration/tests/last-authentication-strategy.test.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,5 +115,18 @@ testAgainstRunningApps({ withEnv: [appConfigs.envs.withEmailCodes] })(
115115
await expect(socialButtonContainers).toHaveCount(1);
116116
await expect(socialButtonContainers.first().locator('.cl-button')).toHaveCount(3);
117117
});
118+
119+
test('should not show "Last used" badge on sign-up even when lastAuthenticationStrategy is set', async ({
120+
page,
121+
context,
122+
}) => {
123+
const u = createTestUtils({ app, page, context });
124+
await mockLastAuthenticationStrategyResponse(page, 'oauth_google');
125+
126+
await u.po.signUp.goTo();
127+
await u.po.signUp.waitForMounted();
128+
129+
await expect(page.locator('.cl-lastAuthenticationStrategyBadge')).toHaveCount(0);
130+
});
118131
},
119132
);

packages/backend/src/tokens/verify.ts

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -39,22 +39,11 @@ export type VerifyTokenOptions = Simplify<
3939
* Verifies a Clerk-generated token signature. Networkless if the `jwtKey` is provided. Otherwise, performs a network call to retrieve the JWKS from the [Backend API](https://clerk.com/docs/reference/backend-api/tag/JWKS#operation/GetJWKS){{ target: '_blank' }}.
4040
*
4141
* @param token - The token to verify.
42-
* @param options - Options for verifying the token.
42+
* @param options - Options for verifying the token. It is recommended to set these options as [environment variables](/docs/guides/development/clerk-environment-variables#api-and-sdk-configuration) where possible, and then pass them to the function. For example, you can set the `secretKey` option using the `CLERK_SECRET_KEY` environment variable, and then pass it to the function like this: `verifyToken(token, { secretKey: process.env.CLERK_SECRET_KEY })`.
4343
*
4444
* @displayFunctionSignature
4545
* @hideReturns
4646
*
47-
* @paramExtension
48-
*
49-
* ### `VerifyTokenOptions`
50-
*
51-
* It is recommended to set these options as [environment variables](/docs/guides/development/clerk-environment-variables#api-and-sdk-configuration) where possible, and then pass them to the function. For example, you can set the `secretKey` option using the `CLERK_SECRET_KEY` environment variable, and then pass it to the function like this: `createClerkClient({ secretKey: process.env.CLERK_SECRET_KEY })`.
52-
*
53-
* > [!WARNING]
54-
* You must provide either `jwtKey` or `secretKey`.
55-
*
56-
* <Typedoc src="backend/verify-token-options" />
57-
*
5847
* @example
5948
*
6049
* The following example demonstrates how to use the [JavaScript Backend SDK](https://clerk.com/docs/reference/backend/overview) to verify the token signature.

packages/clerk-js/src/core/__tests__/tokenCache.test.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,41 @@ describe('SessionTokenCache', () => {
277277
// Critical: postMessage should NOT be called when handling a broadcast
278278
expect(mockBroadcastChannel.postMessage).not.toHaveBeenCalled();
279279
});
280+
281+
it('always broadcasts regardless of cache state', async () => {
282+
mockBroadcastChannel.postMessage.mockClear();
283+
284+
const tokenId = 'sess_2GbDB4enNdCa5vS1zpC3Xzg9tK9';
285+
const tokenResolver = Promise.resolve(
286+
new Token({
287+
id: tokenId,
288+
jwt: mockJwt,
289+
object: 'token',
290+
}) as TokenResource,
291+
);
292+
293+
SessionTokenCache.set({ tokenId, tokenResolver });
294+
await tokenResolver;
295+
296+
expect(mockBroadcastChannel.postMessage).toHaveBeenCalledTimes(1);
297+
const firstCall = mockBroadcastChannel.postMessage.mock.calls[0][0];
298+
expect(firstCall.tokenId).toBe(tokenId);
299+
300+
mockBroadcastChannel.postMessage.mockClear();
301+
302+
const tokenResolver2 = Promise.resolve(
303+
new Token({
304+
id: tokenId,
305+
jwt: mockJwt,
306+
object: 'token',
307+
}) as TokenResource,
308+
);
309+
310+
SessionTokenCache.set({ tokenId, tokenResolver: tokenResolver2 });
311+
await tokenResolver2;
312+
313+
expect(mockBroadcastChannel.postMessage).toHaveBeenCalledTimes(1);
314+
});
280315
});
281316

282317
describe('token expiration with absolute time', () => {

packages/clerk-js/src/core/clerk.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2420,6 +2420,7 @@ export class Clerk implements ClerkInterface {
24202420
..._props,
24212421
options: this.#initOptions({ ...this.#options, ..._props.options }),
24222422
};
2423+
24232424
return this.#componentControls?.ensureMounted().then(controls => controls.updateProps(props));
24242425
};
24252426

packages/clerk-js/src/core/resources/Session.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,9 +131,15 @@ export class Session extends BaseResource implements SessionResource {
131131
};
132132

133133
#hydrateCache = (token: TokenResource | null) => {
134-
if (token) {
134+
if (!token) {
135+
return;
136+
}
137+
138+
const tokenId = this.#getCacheId();
139+
const existing = SessionTokenCache.get({ tokenId });
140+
if (!existing) {
135141
SessionTokenCache.set({
136-
tokenId: this.#getCacheId(),
142+
tokenId,
137143
tokenResolver: Promise.resolve(token),
138144
});
139145
}

0 commit comments

Comments
 (0)