Skip to content

Commit 68b9078

Browse files
committed
wip
1 parent be35c47 commit 68b9078

File tree

9 files changed

+88
-49
lines changed

9 files changed

+88
-49
lines changed
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
---
2-
import { Protect } from '@clerk/astro/components';
2+
import { Show } from '@clerk/astro/components';
33
import Layout from '../layouts/Layout.astro';
44
---
55

66
<Layout title='Page is only accessible by members'>
77
<div class='w-full flex justify-center flex-col'>
8-
<Protect role='org:admin'>
8+
<Show when={{ role: 'org:admin' }}>
9+
<h1 class='text-2xl text-center'>I'm an admin</h1>
910
<Fragment slot='fallback'>
1011
<h1 class='text-2xl text-center'>Not an admin</h1>
1112
<a
@@ -14,7 +15,6 @@ import Layout from '../layouts/Layout.astro';
1415
>Go to Members Page</a
1516
>
1617
</Fragment>
17-
<h1 class='text-2xl text-center'>I'm an admin</h1>
18-
</Protect>
18+
</Show>
1919
</div>
2020
</Layout>
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
---
2-
import { Protect } from '@clerk/astro/components';
2+
import { Show } from '@clerk/astro/components';
33
import Layout from '../layouts/Layout.astro';
44
---
55

66
<Layout title='Page is only accessible by members'>
77
<div class='w-full flex justify-center flex-col'>
8-
<Protect role='basic_member'>
8+
<Show when={{ role: 'basic_member' }}>
9+
<h1 class='text-2xl text-center'>I'm a member</h1>
910
<Fragment slot='fallback'>
1011
<h1 class='text-2xl text-center'>Not a member</h1>
1112
<a
@@ -14,7 +15,6 @@ import Layout from '../layouts/Layout.astro';
1415
>Go to Admin Page</a
1516
>
1617
</Fragment>
17-
<h1 class='text-2xl text-center'>I'm a member</h1>
18-
</Protect>
18+
</Show>
1919
</div>
2020
</Layout>
Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
11
---
2-
import { Protect, PricingTable } from '@clerk/astro/components';
2+
import { Show, PricingTable } from '@clerk/astro/components';
33
import Layout from '../layouts/Layout.astro';
44
55
const newSubscriptionRedirectUrl = Astro.url.searchParams.get('newSubscriptionRedirectUrl');
66
---
77

88
<Layout title='Pricing Table'>
99
<div class='w-full flex justify-center'>
10-
<Protect plan='free_user'>
10+
<Show when={{ plan: 'free_user' }}>
1111
<p>user in free</p>
12-
</Protect>
13-
<Protect plan='pro'>
12+
</Show>
13+
<Show when={{ plan: 'pro' }}>
1414
<p>user in pro</p>
15-
</Protect>
16-
<Protect plan='plus'>
15+
</Show>
16+
<Show when={{ plan: 'plus' }}>
1717
<p>user in plus</p>
18-
</Protect>
18+
</Show>
1919
<PricingTable newSubscriptionRedirectUrl={newSubscriptionRedirectUrl} />
2020
</div>
2121
</Layout>
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
11
---
2-
import { Protect } from '@clerk/astro/components';
2+
import { Show } from '@clerk/astro/components';
33
import Layout from '../layouts/Layout.astro';
44
---
55

66
<Layout title='Page is only accessible by members'>
77
<div class='w-full flex justify-center flex-col'>
8-
<Protect
8+
<Show
99
server:defer
10-
role='org:admin'
10+
when={{ role: 'org:admin' }}
1111
>
1212
<p slot='fallback'>Loading</p>
13-
<Fragment slot='protect-fallback'>
13+
<h1 class='text-2xl text-center'>I'm an admin</h1>
14+
<Fragment slot='show-fallback'>
1415
<h1 class='text-2xl text-center'>Not an admin</h1>
1516
<a
1617
class='text-sm text-center text-gray-100 transition hover:text-gray-400'
1718
href='/only-members'
1819
>Go to Members Page</a
1920
>
2021
</Fragment>
21-
<h1 class='text-2xl text-center'>I'm an admin</h1>
22-
</Protect>
22+
</Show>
2323
</div>
2424
</Layout>

packages/astro/src/astro-components/control/Show.astro

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ import ShowCSR from './ShowCSR.astro';
33
import ShowSSR from './ShowSSR.astro';
44
55
import { isStaticOutput } from 'virtual:@clerk/astro/config';
6+
import type { ShowWhenCondition } from '@clerk/shared/types';
67
78
type Props = {
8-
when: 'signedIn' | 'signedOut';
9+
when: ShowWhenCondition;
910
isStatic?: boolean;
1011
/**
1112
* The class name to apply to the outermost element of the component.
@@ -24,4 +25,5 @@ const ShowComponent = isStaticOutput(isStatic) ? ShowCSR : ShowSSR;
2425
class={className}
2526
>
2627
<slot />
28+
<slot name='fallback' slot='fallback' />
2729
</ShowComponent>
Lines changed: 44 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,73 @@
11
---
2+
import type { ShowWhenCondition } from '@clerk/shared/types';
3+
24
type Props = {
3-
when: 'signedIn' | 'signedOut';
5+
when: ShowWhenCondition;
46
class?: string;
57
};
68
79
const { when, class: className } = Astro.props;
10+
11+
// Serialize when prop for client-side use
12+
const whenAttr = typeof when === 'string' ? when : JSON.stringify(when);
813
---
914

1015
<clerk-show
1116
class={className}
12-
when={when}
17+
data-when={whenAttr}
1318
hidden
1419
>
15-
<slot />
20+
<div data-clerk-control-slot-default hidden>
21+
<slot />
22+
</div>
23+
<div data-clerk-control-slot-fallback hidden>
24+
<slot name='fallback' />
25+
</div>
1626
</clerk-show>
1727

1828
<script>
29+
import { $authStore, $sessionStore } from '@clerk/astro/client';
1930
import { type AuthState, BaseClerkControlElement } from './BaseClerkControlElement';
2031

2132
class ClerkShow extends BaseClerkControlElement {
33+
private defaultSlot: HTMLDivElement | null = null;
34+
private fallbackSlot: HTMLDivElement | null = null;
35+
2236
protected onAuthStateChange(state: AuthState): void {
23-
const when = this.getAttribute('when');
37+
this.defaultSlot = this.querySelector('[data-clerk-control-slot-default]');
38+
this.fallbackSlot = this.querySelector('[data-clerk-control-slot-fallback]');
39+
40+
const whenAttr = this.dataset.when;
41+
if (!whenAttr) return;
2442

25-
if (when === 'signedIn') {
26-
if (state.userId) {
27-
this.removeAttribute('hidden');
28-
} else {
29-
this.setAttribute('hidden', '');
43+
let isAuthorized = false;
44+
45+
if (whenAttr === 'signedIn') {
46+
isAuthorized = !!state.userId;
47+
} else if (whenAttr === 'signedOut') {
48+
isAuthorized = !state.userId;
49+
} else {
50+
// Try to parse as JSON (object-based conditions)
51+
try {
52+
const when = JSON.parse(whenAttr);
53+
const session = $sessionStore.get();
54+
if (state.userId && session?.checkAuthorization) {
55+
isAuthorized = session.checkAuthorization(when);
56+
}
57+
} catch {
58+
// Invalid JSON, treat as unauthorized
3059
}
31-
return;
3260
}
3361

34-
if (when === 'signedOut') {
35-
if (state.userId) {
36-
this.setAttribute('hidden', '');
37-
} else {
38-
this.removeAttribute('hidden');
39-
}
40-
return;
62+
if (this.defaultSlot) {
63+
isAuthorized ? this.defaultSlot.removeAttribute('hidden') : this.defaultSlot.setAttribute('hidden', '');
4164
}
4265

43-
// Unknown state; be conservative.
44-
this.setAttribute('hidden', '');
66+
if (this.fallbackSlot) {
67+
isAuthorized ? this.fallbackSlot.setAttribute('hidden', '') : this.fallbackSlot.removeAttribute('hidden');
68+
}
4569
}
4670
}
4771

48-
if (!customElements.get('clerk-show')) {
49-
customElements.define('clerk-show', ClerkShow);
50-
}
72+
customElements.define('clerk-show', ClerkShow);
5173
</script>
Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,24 @@
11
---
2+
import type { ShowWhenCondition } from '@clerk/shared/types';
3+
24
type Props = {
3-
when: 'signedIn' | 'signedOut';
5+
when: ShowWhenCondition;
46
};
57
68
const { when } = Astro.props;
7-
const { userId } = Astro.locals.auth();
9+
const { userId, has } = Astro.locals.auth();
10+
11+
const isAuthorized = (() => {
12+
if (when === 'signedIn') return !!userId;
13+
if (when === 'signedOut') return !userId;
14+
if (typeof when === 'function') return userId && when(has);
15+
// Object-based conditions (role, permission, feature, plan)
16+
if (typeof when === 'object' && when !== null) {
17+
if (!userId) return false;
18+
return has(when);
19+
}
20+
return false;
21+
})();
822
---
923

10-
{when === 'signedIn' ? userId ? <slot /> : null : null}
11-
{when === 'signedOut' ? !userId ? <slot /> : null : null}
24+
{isAuthorized ? <slot /> : <slot name='fallback' />}

packages/astro/src/astro-components/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
* Control Components
33
*/
44
export { default as Show } from './control/Show.astro';
5-
export { default as Protect } from './control/Protect.astro';
65
export { default as AuthenticateWithRedirectCallback } from './control/AuthenticateWithRedirectCallback.astro';
76

87
/**

packages/astro/src/types.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ declare global {
6464

6565
export type { AstroClerkUpdateOptions, AstroClerkIntegrationParams, AstroClerkCreateInstanceParams, ProtectParams };
6666

67+
// Backward compatibility alias
68+
export type ProtectProps = ProtectParams;
69+
6770
export type ButtonProps<Tag> = {
6871
/**
6972
* @deprecated The `'as'` prop will be removed in a future version.

0 commit comments

Comments
 (0)