Skip to content

Commit edc0bfd

Browse files
authored
chore(types,clerk-react,astro,vue): Share Protect component prop type between SDKs (#6197)
1 parent c2247c0 commit edc0bfd

File tree

7 files changed

+85
-149
lines changed

7 files changed

+85
-149
lines changed

.changeset/wet-foxes-attend.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
"@clerk/astro": patch
3+
"@clerk/clerk-react": patch
4+
"@clerk/types": patch
5+
"@clerk/vue": patch
6+
---
7+
8+
Extract internal `ProtectProps` type to shared types to eliminate duplication across SDKs

.typedoc/__tests__/__snapshots__/file-structure.test.ts.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ exports[`Typedoc output > should have a deliberate file structure 1`] = `
4545
"types/path-value.mdx",
4646
"types/pending-session-options.mdx",
4747
"types/pending-session-resource.mdx",
48+
"types/protect-props.mdx",
4849
"types/record-to-path.mdx",
4950
"types/redirect-options.mdx",
5051
"types/reverification-config.mdx",

packages/astro/src/types.ts

Lines changed: 1 addition & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
import type {
2-
Autocomplete,
3-
CheckAuthorizationWithCustomPermissions,
42
Clerk,
53
ClerkOptions,
64
ClientResource,
75
MultiDomainAndOrProxyPrimitives,
8-
OrganizationCustomPermissionKey,
9-
OrganizationCustomRoleKey,
6+
ProtectProps,
107
Without,
118
} from '@clerk/types';
129

@@ -48,50 +45,6 @@ declare global {
4845
}
4946
}
5047

51-
type ProtectProps =
52-
| {
53-
condition?: never;
54-
role: OrganizationCustomRoleKey;
55-
permission?: never;
56-
feature?: never;
57-
plan?: never;
58-
}
59-
| {
60-
condition?: never;
61-
role?: never;
62-
feature?: never;
63-
plan?: never;
64-
permission: OrganizationCustomPermissionKey;
65-
}
66-
| {
67-
condition: (has: CheckAuthorizationWithCustomPermissions) => boolean;
68-
role?: never;
69-
permission?: never;
70-
feature?: never;
71-
plan?: never;
72-
}
73-
| {
74-
condition?: never;
75-
role?: never;
76-
permission?: never;
77-
feature: Autocomplete<`user:${string}` | `org:${string}`>;
78-
plan?: never;
79-
}
80-
| {
81-
condition?: never;
82-
role?: never;
83-
permission?: never;
84-
feature?: never;
85-
plan: Autocomplete<`user:${string}` | `org:${string}`>;
86-
}
87-
| {
88-
condition?: never;
89-
role?: never;
90-
permission?: never;
91-
feature?: never;
92-
plan?: never;
93-
};
94-
9548
export type { AstroClerkUpdateOptions, AstroClerkIntegrationParams, AstroClerkCreateInstanceParams, ProtectProps };
9649

9750
export type ButtonProps<Tag> = {

packages/react/src/components/controlComponents.tsx

Lines changed: 2 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,5 @@
11
import { deprecated } from '@clerk/shared/deprecated';
2-
import type {
3-
Autocomplete,
4-
CheckAuthorizationWithCustomPermissions,
5-
HandleOAuthCallbackParams,
6-
OrganizationCustomPermissionKey,
7-
OrganizationCustomRoleKey,
8-
PendingSessionOptions,
9-
} from '@clerk/types';
2+
import type { HandleOAuthCallbackParams, PendingSessionOptions, ProtectProps as _ProtectProps } from '@clerk/types';
103
import React from 'react';
114

125
import { useIsomorphicClerkContext } from '../contexts/IsomorphicClerkContext';
@@ -77,50 +70,7 @@ export const ClerkDegraded = ({ children }: React.PropsWithChildren<unknown>) =>
7770
};
7871

7972
export type ProtectProps = React.PropsWithChildren<
80-
(
81-
| {
82-
condition?: never;
83-
role: OrganizationCustomRoleKey;
84-
permission?: never;
85-
feature?: never;
86-
plan?: never;
87-
}
88-
| {
89-
condition?: never;
90-
role?: never;
91-
feature?: never;
92-
plan?: never;
93-
permission: OrganizationCustomPermissionKey;
94-
}
95-
| {
96-
condition: (has: CheckAuthorizationWithCustomPermissions) => boolean;
97-
role?: never;
98-
permission?: never;
99-
feature?: never;
100-
plan?: never;
101-
}
102-
| {
103-
condition?: never;
104-
role?: never;
105-
permission?: never;
106-
feature: Autocomplete<`user:${string}` | `org:${string}`>;
107-
plan?: never;
108-
}
109-
| {
110-
condition?: never;
111-
role?: never;
112-
permission?: never;
113-
feature?: never;
114-
plan: Autocomplete<`user:${string}` | `org:${string}`>;
115-
}
116-
| {
117-
condition?: never;
118-
role?: never;
119-
permission?: never;
120-
feature?: never;
121-
plan?: never;
122-
}
123-
) & {
73+
_ProtectProps & {
12474
fallback?: React.ReactNode;
12575
} & PendingSessionOptions
12676
>;

packages/types/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ export * from './organizationSuggestion';
3737
export * from './passwords';
3838
export * from './permission';
3939
export * from './phoneNumber';
40+
export * from './protect';
4041
export * from './redirects';
4142
export * from './resource';
4243
export * from './role';

packages/types/src/protect.ts

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import type { OrganizationCustomPermissionKey, OrganizationCustomRoleKey } from './organizationMembership';
2+
import type { CheckAuthorizationWithCustomPermissions } from './session';
3+
import type { Autocomplete } from './utils';
4+
5+
/**
6+
* Props for the `<Protect />` component, which restricts access to its children based on authentication and authorization.
7+
*
8+
* Use `ProtectProps` to specify the required role, permission, feature, or plan for access.
9+
*
10+
* @example
11+
* ```tsx
12+
* // Require a specific permission
13+
* <Protect permission="a_permission_key" />
14+
*
15+
* // Require a specific role
16+
* <Protect role="a_role_key" />
17+
*
18+
* // Use a custom condition callback
19+
* <Protect condition={(has) => has({ permission: "a_permission_key" })} />
20+
*
21+
* // Require a specific feature
22+
* <Protect feature="a_feature_key" />
23+
*
24+
* // Require a specific plan
25+
* <Protect plan=a_plan_key" />
26+
* ```
27+
*/
28+
export type ProtectProps =
29+
| {
30+
condition?: never;
31+
role: OrganizationCustomRoleKey;
32+
permission?: never;
33+
feature?: never;
34+
plan?: never;
35+
}
36+
| {
37+
condition?: never;
38+
role?: never;
39+
feature?: never;
40+
plan?: never;
41+
permission: OrganizationCustomPermissionKey;
42+
}
43+
| {
44+
condition: (has: CheckAuthorizationWithCustomPermissions) => boolean;
45+
role?: never;
46+
permission?: never;
47+
feature?: never;
48+
plan?: never;
49+
}
50+
| {
51+
condition?: never;
52+
role?: never;
53+
permission?: never;
54+
feature: Autocomplete<`user:${string}` | `org:${string}`>;
55+
plan?: never;
56+
}
57+
| {
58+
condition?: never;
59+
role?: never;
60+
permission?: never;
61+
feature?: never;
62+
plan: Autocomplete<`user:${string}` | `org:${string}`>;
63+
}
64+
| {
65+
condition?: never;
66+
role?: never;
67+
permission?: never;
68+
feature?: never;
69+
plan?: never;
70+
};

packages/vue/src/components/controlComponents.ts

Lines changed: 2 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
11
import { deprecated } from '@clerk/shared/deprecated';
22
import type {
3-
Autocomplete,
4-
CheckAuthorizationWithCustomPermissions,
53
HandleOAuthCallbackParams,
6-
OrganizationCustomPermissionKey,
7-
OrganizationCustomRoleKey,
84
PendingSessionOptions,
5+
ProtectProps as _ProtectProps,
96
RedirectOptions,
107
} from '@clerk/types';
118
import { defineComponent } from 'vue';
@@ -107,51 +104,7 @@ export const AuthenticateWithRedirectCallback = defineComponent((props: HandleOA
107104
return () => null;
108105
});
109106

110-
export type ProtectProps = (
111-
| {
112-
condition?: never;
113-
role: OrganizationCustomRoleKey;
114-
permission?: never;
115-
feature?: never;
116-
plan?: never;
117-
}
118-
| {
119-
condition?: never;
120-
role?: never;
121-
feature?: never;
122-
plan?: never;
123-
permission: OrganizationCustomPermissionKey;
124-
}
125-
| {
126-
condition: (has: CheckAuthorizationWithCustomPermissions) => boolean;
127-
role?: never;
128-
permission?: never;
129-
feature?: never;
130-
plan?: never;
131-
}
132-
| {
133-
condition?: never;
134-
role?: never;
135-
permission?: never;
136-
feature: Autocomplete<`user:${string}` | `org:${string}`>;
137-
plan?: never;
138-
}
139-
| {
140-
condition?: never;
141-
role?: never;
142-
permission?: never;
143-
feature?: never;
144-
plan: Autocomplete<`user:${string}` | `org:${string}`>;
145-
}
146-
| {
147-
condition?: never;
148-
role?: never;
149-
permission?: never;
150-
feature?: never;
151-
plan?: never;
152-
}
153-
) &
154-
PendingSessionOptions;
107+
export type ProtectProps = _ProtectProps & PendingSessionOptions;
155108

156109
export const Protect = defineComponent((props: ProtectProps, { slots }) => {
157110
const { isLoaded, has, userId } = useAuth({ treatPendingAsSignedOut: props.treatPendingAsSignedOut });

0 commit comments

Comments
 (0)