Skip to content

Commit 5e1a09d

Browse files
committed
feat(clerk-js,types): Introduce UserOrganizationInvitation
+ UserOrganizationInvitationResource + UserOrganizationInvitationJSON + ClerkPaginatedResponse that handles FAPI paginated responses
1 parent aad6351 commit 5e1a09d

File tree

9 files changed

+141
-0
lines changed

9 files changed

+141
-0
lines changed

.changeset/shaggy-vans-relax.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
'@clerk/clerk-js': patch
3+
'@clerk/types': patch
4+
---
5+
6+
Introduces a new internal class `UserOrganizationInvitation` that represents and invitation to join an organization with the organization data populated
7+
Additions to support the above
8+
- UserOrganizationInvitationResource
9+
- UserOrganizationInvitationJSON
10+
- ClerkPaginatedResponse
11+
12+
ClerkPaginatedResponse represents a paginated FAPI response

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import type {
1010
EmailAddressResource,
1111
ExternalAccountJSON,
1212
ExternalAccountResource,
13+
GetUserOrganizationInvitationsParams,
1314
ImageResource,
1415
OrganizationMembershipResource,
1516
PhoneNumberResource,
@@ -42,6 +43,7 @@ import {
4243
SamlAccount,
4344
SessionWithActivities,
4445
TOTP,
46+
UserOrganizationInvitation,
4547
Web3Wallet,
4648
} from './internal';
4749

@@ -250,6 +252,10 @@ export class User extends BaseResource implements UserResource {
250252
});
251253
};
252254

255+
getOrganizationInvitations = (params?: GetUserOrganizationInvitationsParams) => {
256+
return UserOrganizationInvitation.retrieve(params);
257+
};
258+
253259
getOrganizationMemberships = async (
254260
retrieveMembership: RetrieveMembershipsParams,
255261
): Promise<OrganizationMembership[]> => {
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import type {
2+
ClerkPaginatedResponse,
3+
GetUserOrganizationInvitationsParams,
4+
MembershipRole,
5+
OrganizationInvitationStatus,
6+
OrganizationResource,
7+
UserOrganizationInvitationJSON,
8+
UserOrganizationInvitationResource,
9+
} from '@clerk/types';
10+
11+
import { unixEpochToDate } from '../../utils/date';
12+
import { BaseResource, Organization } from './internal';
13+
14+
export class UserOrganizationInvitation extends BaseResource implements UserOrganizationInvitationResource {
15+
id!: string;
16+
emailAddress!: string;
17+
organization!: OrganizationResource;
18+
publicMetadata: OrganizationInvitationPublicMetadata = {};
19+
status!: OrganizationInvitationStatus;
20+
role!: MembershipRole;
21+
createdAt!: Date;
22+
updatedAt!: Date;
23+
24+
static async retrieve(
25+
params?: GetUserOrganizationInvitationsParams,
26+
): Promise<ClerkPaginatedResponse<UserOrganizationInvitation>> {
27+
return await BaseResource._fetch({
28+
path: '/me/organization_invitations',
29+
method: 'GET',
30+
search: params as any,
31+
})
32+
.then(res => {
33+
const { data: invites, total_count } =
34+
res?.response as unknown as ClerkPaginatedResponse<UserOrganizationInvitationJSON>;
35+
36+
return {
37+
total_count,
38+
data: invites.map(invitation => new UserOrganizationInvitation(invitation)),
39+
};
40+
})
41+
.catch(() => ({
42+
total_count: 0,
43+
data: [],
44+
}));
45+
}
46+
47+
constructor(data: UserOrganizationInvitationJSON) {
48+
super();
49+
this.fromJSON(data);
50+
}
51+
protected fromJSON(data: UserOrganizationInvitationJSON | null): this {
52+
if (data) {
53+
this.id = data.id;
54+
this.emailAddress = data.email_address;
55+
this.organization = new Organization(data.organization);
56+
this.publicMetadata = data.public_metadata;
57+
this.role = data.role;
58+
this.status = data.status;
59+
this.createdAt = unixEpochToDate(data.created_at);
60+
this.updatedAt = unixEpochToDate(data.updated_at);
61+
}
62+
return this;
63+
}
64+
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,6 @@ export * from './SignUp';
2323
export * from './Token';
2424
export * from './TOTP';
2525
export * from './User';
26+
export * from './UserOrganizationInvitation';
2627
export * from './Verification';
2728
export * from './Web3Wallet';

packages/types/src/api.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,11 @@ export interface ClerkPaginationParams {
2525
limit?: number;
2626
offset?: number;
2727
}
28+
29+
/**
30+
* Pagination params
31+
*/
32+
export interface ClerkPaginatedResponse<T> {
33+
data: T[];
34+
total_count: number;
35+
}

packages/types/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ export * from './theme';
3939
export * from './token';
4040
export * from './totp';
4141
export * from './user';
42+
export * from './userOrganizationInvitation';
4243
export * from './userSettings';
4344
export * from './utils';
4445
export * from './verification';

packages/types/src/json.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,18 @@ export interface OrganizationInvitationJSON extends ClerkResourceJSON {
340340
updated_at: number;
341341
}
342342

343+
export interface UserOrganizationInvitationJSON extends ClerkResourceJSON {
344+
object: 'organization_invitation';
345+
id: string;
346+
email_address: string;
347+
organization: OrganizationJSON;
348+
public_metadata: OrganizationInvitationPublicMetadata;
349+
status: OrganizationInvitationStatus;
350+
role: MembershipRole;
351+
created_at: number;
352+
updated_at: number;
353+
}
354+
343355
export interface UserDataJSON {
344356
first_name?: string;
345357
last_name?: string;

packages/types/src/user.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import type { ClerkPaginatedResponse, ClerkPaginationParams } from './api';
12
import type { BackupCodeResource } from './backupCode';
23
import type { DeletedObjectResource } from './deletedObject';
34
import type { EmailAddressResource } from './emailAddress';
@@ -12,6 +13,7 @@ import type { SamlAccountResource } from './samlAccount';
1213
import type { SessionWithActivitiesResource } from './session';
1314
import type { OAuthStrategy } from './strategies';
1415
import type { TOTPResource } from './totp';
16+
import type { UserOrganizationInvitationResource } from './userOrganizationInvitation';
1517
import type { SnakeToCamel } from './utils';
1618
import type { Web3WalletResource } from './web3Wallet';
1719

@@ -93,6 +95,9 @@ export interface UserResource extends ClerkResource {
9395
getSessions: () => Promise<SessionWithActivitiesResource[]>;
9496
setProfileImage: (params: SetProfileImageParams) => Promise<ImageResource>;
9597
createExternalAccount: (params: CreateExternalAccountParams) => Promise<ExternalAccountResource>;
98+
getOrganizationInvitations: (
99+
params?: GetUserOrganizationInvitationsParams,
100+
) => Promise<ClerkPaginatedResponse<UserOrganizationInvitationResource>>;
96101
createTOTP: () => Promise<TOTPResource>;
97102
verifyTOTP: (params: VerifyTOTPParams) => Promise<TOTPResource>;
98103
disableTOTP: () => Promise<DeletedObjectResource>;
@@ -150,3 +155,5 @@ export type UpdateUserPasswordParams = {
150155
};
151156

152157
export type RemoveUserPasswordParams = Pick<UpdateUserPasswordParams, 'currentPassword'>;
158+
159+
export type GetUserOrganizationInvitationsParams = ClerkPaginationParams;
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import type { OrganizationResource } from './organization';
2+
import type { OrganizationInvitationStatus } from './organizationInvitation';
3+
import type { MembershipRole } from './organizationMembership';
4+
import type { ClerkResource } from './resource';
5+
6+
declare global {
7+
/**
8+
* If you want to provide custom types for the organizationInvitation.publicMetadata
9+
* object, simply redeclare this rule in the global namespace.
10+
* Every organizationInvitation object will use the provided type.
11+
*/
12+
interface UserOrganizationInvitationPublicMetadata {
13+
[k: string]: unknown;
14+
}
15+
16+
interface UserOrganizationInvitationPrivateMetadata {
17+
[k: string]: unknown;
18+
}
19+
}
20+
21+
export interface UserOrganizationInvitationResource extends ClerkResource {
22+
id: string;
23+
emailAddress: string;
24+
organization: OrganizationResource;
25+
publicMetadata: UserOrganizationInvitationPublicMetadata;
26+
role: MembershipRole;
27+
status: OrganizationInvitationStatus;
28+
createdAt: Date;
29+
updatedAt: Date;
30+
}

0 commit comments

Comments
 (0)