diff --git a/packages/auth/src/lib/accept-invitation-endpoint.ts b/packages/auth/src/lib/accept-invitation-endpoint.ts index cf92258f113..d9b0f95e135 100644 --- a/packages/auth/src/lib/accept-invitation-endpoint.ts +++ b/packages/auth/src/lib/accept-invitation-endpoint.ts @@ -133,10 +133,18 @@ export const acceptInvitationEndpoint = { }); if (!existingMember) { - await db.insert(members).values({ - organizationId: invitation.organization.id, - userId: user.id, - role: invitation.role ?? "member", + // Dynamic import: this plugin needs to call the organization plugin's + // addMember API to trigger billing hooks (beforeAddMember/afterAddMember). + // server.ts imports this file as a plugin, so a static import would be circular. + // The import resolves at request time when all modules are fully initialized. + const { auth } = await import("../server"); + await auth.api.addMember({ + body: { + organizationId: invitation.organization.id, + userId: user.id, + role: + (invitation.role as "member" | "owner" | "admin") ?? "member", + }, }); } diff --git a/packages/trpc/src/router/organization/organization.ts b/packages/trpc/src/router/organization/organization.ts index 2409981e16b..baf4b1f19ea 100644 --- a/packages/trpc/src/router/organization/organization.ts +++ b/packages/trpc/src/router/organization/organization.ts @@ -320,15 +320,15 @@ export const organizationRouter = { userId: z.string().uuid(), }), ) - .mutation(async ({ input }) => { - const [member] = await db - .insert(members) - .values({ + .mutation(async ({ ctx, input }) => { + const member = await ctx.auth.api.addMember({ + body: { organizationId: input.organizationId, userId: input.userId, role: "member", - }) - .returning(); + }, + headers: ctx.headers, + }); return member; }),