Skip to content

Commit 1f13b1a

Browse files
authored
Merge branch 'jrad/ui-prop-cleanup' into jrad/js-prop-bundling
2 parents a7cd2f8 + 04b6512 commit 1f13b1a

69 files changed

Lines changed: 1394 additions & 255 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.changeset/forty-months-appear.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
'@clerk/shared': major
3+
'@clerk/react': patch
4+
'@clerk/ui': patch
5+
---
6+
7+
Remove `useUserContext`, `useOrganizationContext`, `useSessionContext` and `useClientContext` from the `shared/react` package.
8+
9+
These hooks have never been meant for public use and have been replaced with internal hooks that do not rely on context.
10+
11+
If you need access to these resources, use the `useUser`, `useOrganization` and `useSession` hooks instead.
12+
13+
If you are building a React SDK and need direct access to the `client`, get in touch with us to discuss!
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@clerk/upgrade": patch
3+
---
4+
5+
Improve `generate-guide` script to support generating guides for all SDKs at once and output MDX format compatible with clerk-docs
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@clerk/backend": patch
3+
---
4+
5+
Improve token type validation in authentication requests
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+
Add support for Next.js 16 cache components by improving error detection and providing helpful error messages when `auth()` or `currentUser()` are called inside a `"use cache"` function.

.changeset/silly-peaches-march.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+
'@clerk/shared': patch
4+
'@clerk/react': patch
5+
---

.changeset/tangy-sides-crash.md

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

.changeset/tough-taxis-care.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@clerk/backend': minor
3+
---
4+
5+
Add `createBulk()` method to `WaitlistEntryAPI` for bulk creating waitlist entries
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { auth } from '@clerk/nextjs/server';
2+
3+
// This function deliberately calls auth() inside "use cache" to trigger the error
4+
async function getCachedAuthData() {
5+
'use cache';
6+
// This WILL throw an error because auth() uses headers() internally
7+
const { userId } = await auth();
8+
return { userId };
9+
}
10+
11+
export async function GET() {
12+
try {
13+
const data = await getCachedAuthData();
14+
return Response.json(data);
15+
} catch (e: any) {
16+
// Return the error message so we can verify it in tests
17+
return Response.json({ error: e.message }, { status: 500 });
18+
}
19+
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import { Suspense } from 'react';
2+
import { currentUser, clerkClient } from '@clerk/nextjs/server';
3+
4+
// Simulated cached operation that fetches additional user data
5+
async function getCachedUserProfile(userId: string) {
6+
'use cache';
7+
// This is the CORRECT pattern:
8+
// - currentUser() is called OUTSIDE the cache function
9+
// - Only the userId is passed into the cache function
10+
// - The cache function uses clerkClient() which is allowed in cache contexts
11+
const client = await clerkClient();
12+
const user = await client.users.getUser(userId);
13+
14+
return {
15+
userId,
16+
cachedAt: new Date().toISOString(),
17+
profile: {
18+
fullName: [user.firstName, user.lastName].filter(Boolean).join(' ') || 'Unknown',
19+
emailCount: user.emailAddresses?.length ?? 0,
20+
},
21+
};
22+
}
23+
24+
async function CurrentUserCacheContent() {
25+
// Step 1: Call currentUser() OUTSIDE the cache function
26+
const user = await currentUser();
27+
28+
if (!user) {
29+
return (
30+
<>
31+
<p>Please sign in to test the caching pattern with currentUser().</p>
32+
<div data-testid='signed-out'>Not signed in</div>
33+
</>
34+
);
35+
}
36+
37+
// Step 2: Pass userId INTO the cache function
38+
const cachedProfile = await getCachedUserProfile(user.id);
39+
40+
return (
41+
<>
42+
<p>
43+
This demonstrates the correct way to use <code>&quot;use cache&quot;</code> with currentUser():
44+
</p>
45+
<ol>
46+
<li>
47+
Call <code>currentUser()</code> <strong>outside</strong> the cache function
48+
</li>
49+
<li>
50+
Pass the <code>userId</code> <strong>into</strong> the cache function
51+
</li>
52+
<li>
53+
Use <code>clerkClient()</code> inside the cache function (allowed)
54+
</li>
55+
</ol>
56+
57+
<div className='test-result success'>
58+
<h3>Cached Profile Data:</h3>
59+
<pre data-testid='cached-profile'>{JSON.stringify(cachedProfile, null, 2)}</pre>
60+
</div>
61+
62+
<div data-testid='current-user-id'>{user.id}</div>
63+
64+
<pre>
65+
{`
66+
// Correct pattern:
67+
const user = await currentUser(); // Outside cache
68+
if (user) {
69+
const profile = await getCachedProfile(user.id); // Pass userId in
70+
}
71+
72+
async function getCachedProfile(userId: string) {
73+
'use cache';
74+
const client = await clerkClient();
75+
return client.users.getUser(userId);
76+
}
77+
`}
78+
</pre>
79+
</>
80+
);
81+
}
82+
83+
export default function CurrentUserCacheCorrectPage() {
84+
return (
85+
<main>
86+
<h1>currentUser() with &quot;use cache&quot; Correct Pattern</h1>
87+
88+
<Suspense fallback={<div>Loading...</div>}>
89+
<CurrentUserCacheContent />
90+
</Suspense>
91+
</main>
92+
);
93+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { Suspense } from 'react';
2+
import { currentUser } from '@clerk/nextjs/server';
3+
4+
async function CurrentUserContent() {
5+
const user = await currentUser();
6+
7+
return (
8+
<>
9+
<div className={`test-result ${user ? 'success' : ''}`}>
10+
<h3>Current User Result:</h3>
11+
<pre>
12+
{JSON.stringify(
13+
{
14+
id: user?.id ?? null,
15+
firstName: user?.firstName ?? null,
16+
lastName: user?.lastName ?? null,
17+
primaryEmailAddress: user?.primaryEmailAddress?.emailAddress ?? null,
18+
isSignedIn: !!user,
19+
},
20+
null,
21+
2,
22+
)}
23+
</pre>
24+
</div>
25+
26+
<div data-testid='current-user-id'>{user?.id ?? 'Not signed in'}</div>
27+
<div data-testid='current-user-email'>{user?.primaryEmailAddress?.emailAddress ?? 'No email'}</div>
28+
</>
29+
);
30+
}
31+
32+
export default function CurrentUserServerComponentPage() {
33+
return (
34+
<main>
35+
<h1>currentUser() in Server Component</h1>
36+
<p>This page tests using currentUser() in a standard React Server Component.</p>
37+
38+
<Suspense fallback={<div>Loading user...</div>}>
39+
<CurrentUserContent />
40+
</Suspense>
41+
</main>
42+
);
43+
}

0 commit comments

Comments
 (0)