Skip to content

Commit e7cb503

Browse files
authored
fix(backend): correct createOrganizationInvitationBulk return type to PaginatedResourceResponse (#8751)
1 parent 0c854c3 commit e7cb503

3 files changed

Lines changed: 79 additions & 1 deletion

File tree

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+
Fix the return type of `clerkClient.organizations.createOrganizationInvitationBulk()` to `PaginatedResourceResponse<OrganizationInvitation[]>`. The Backend API returns the bulk-created invitations in a `{ data, totalCount }` envelope (the same shape as `getOrganizationInvitationList()`), but the method was typed as `OrganizationInvitation[]`, which did not match the value returned at runtime.
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { http, HttpResponse } from 'msw';
2+
import { describe, expect, expectTypeOf, it } from 'vitest';
3+
4+
import { server, validateHeaders } from '../../mock-server';
5+
import { createBackendApiClient } from '../factory';
6+
import type { PaginatedResourceResponse } from '../resources/Deserializer';
7+
import type { OrganizationInvitation } from '../resources/OrganizationInvitation';
8+
9+
describe('OrganizationAPI', () => {
10+
const apiClient = createBackendApiClient({
11+
apiUrl: 'https://api.clerk.test',
12+
secretKey: 'deadbeef',
13+
});
14+
15+
const organizationId = 'org_123';
16+
17+
const mockInvitation = {
18+
object: 'organization_invitation',
19+
id: 'orginv_1',
20+
email_address: 'one@example.com',
21+
role: 'org:member',
22+
role_name: 'Member',
23+
organization_id: organizationId,
24+
status: 'pending',
25+
public_metadata: {},
26+
private_metadata: {},
27+
url: null,
28+
created_at: 1640995200,
29+
updated_at: 1640995200,
30+
expires_at: 1643673600,
31+
};
32+
33+
describe('createOrganizationInvitationBulk', () => {
34+
it('returns a paginated { data, totalCount } response matching the Backend API shape', async () => {
35+
server.use(
36+
http.post(
37+
`https://api.clerk.test/v1/organizations/${organizationId}/invitations/bulk`,
38+
validateHeaders(async ({ request }) => {
39+
// The SDK should forward the invitations as a snake_cased array body.
40+
const body = (await request.json()) as Array<Record<string, unknown>>;
41+
expect(body).toHaveLength(2);
42+
expect(body[0]).toMatchObject({
43+
email_address: 'one@example.com',
44+
role: 'org:member',
45+
inviter_user_id: 'user_1',
46+
});
47+
48+
return HttpResponse.json({
49+
data: [mockInvitation, { ...mockInvitation, id: 'orginv_2', email_address: 'two@example.com' }],
50+
total_count: 2,
51+
});
52+
}),
53+
),
54+
);
55+
56+
const response = await apiClient.organizations.createOrganizationInvitationBulk(organizationId, [
57+
{ emailAddress: 'one@example.com', role: 'org:member', inviterUserId: 'user_1' },
58+
{ emailAddress: 'two@example.com', role: 'org:member', inviterUserId: 'user_1' },
59+
]);
60+
61+
// The Backend API wraps bulk results in a paginated envelope, and the
62+
// deserializer surfaces it as `{ data, totalCount }`.
63+
expect(response.data).toHaveLength(2);
64+
expect(response.data[0].emailAddress).toBe('one@example.com');
65+
expect(response.data[0].organizationId).toBe(organizationId);
66+
expect(response.totalCount).toBe(2);
67+
68+
// The declared return type must reflect that paginated shape, the same
69+
// way the sibling `getOrganizationInvitationList` does.
70+
expectTypeOf(response).toEqualTypeOf<PaginatedResourceResponse<OrganizationInvitation[]>>();
71+
});
72+
});
73+
});

packages/backend/src/api/endpoints/OrganizationApi.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,7 @@ export class OrganizationAPI extends AbstractAPI {
394394
) {
395395
this.requireId(organizationId);
396396

397-
return this.request<OrganizationInvitation[]>({
397+
return this.request<PaginatedResourceResponse<OrganizationInvitation[]>>({
398398
method: 'POST',
399399
path: joinPaths(basePath, organizationId, 'invitations', 'bulk'),
400400
bodyParams: params,

0 commit comments

Comments
 (0)