DylanDev
DylanDev2d ago

Deleting Users from Backend Function that are Synced with Clerk

I have a users table that is updated by Clerk sending webhooks with the users over to convex. Now I want to implement a feature where admins on my site can delete users. However, I am running into an error when I run npx convex dev as seen in the screenshot. This is my backend function that is triggering the error, more specifically, when I imported clerkClient.
import { clerkClient } from "@clerk/nextjs/server";

export const deleteUserAdministrativeAction = mutation({
args: {
userToDeleteUsername: v.string(),
},
async handler(ctx, args) {
const userToDelete = await getUserByUsername(ctx, { username: args.userToDeleteUsername });
const callUser = await getCurrentUser(ctx);

if(userToDelete && callUser) {
if(await hasRole(ctx, { clerkId: callUser.clerkId, role: "developer" })) {
try {
await clerkClient.users.deleteUser(userToDelete.clerkId);
} catch (error) {
console.log(error);
}
}
}
},
});
import { clerkClient } from "@clerk/nextjs/server";

export const deleteUserAdministrativeAction = mutation({
args: {
userToDeleteUsername: v.string(),
},
async handler(ctx, args) {
const userToDelete = await getUserByUsername(ctx, { username: args.userToDeleteUsername });
const callUser = await getCurrentUser(ctx);

if(userToDelete && callUser) {
if(await hasRole(ctx, { clerkId: callUser.clerkId, role: "developer" })) {
try {
await clerkClient.users.deleteUser(userToDelete.clerkId);
} catch (error) {
console.log(error);
}
}
}
},
});
The error is not a runtime error but rather a compilation error when npx convex dev is ran. I can't just delete the user entry in the users table cause that won't wipe it from clerk. How do I fix this issue?
No description
Solution:
@Tom thank you tom! I ended up splitting the code into a mutation and an action. That way I could use the third party call inside of the backend!
Jump to solution
7 Replies
ballingt
ballingt2d ago
it looks like clerkMiddleware requires Node.js, but you're importing that file from a convex function somewhere or a file from the convex directory imports a file that imports a file that imports a file etc. that imports this clerkMiddleware Oh reading your code, this isn't so complicated. You're trying to use a library that requires Node.js from the file where you defined deleteUserAdministrativeAction
ballingt
ballingt2d ago
To do that you need to write this code in a "use node" file, so it will use Node.js instead of the COnvex JavaScript runtime. See https://docs.convex.dev/functions/actions#calling-third-party-apis-and-using-npm-packages
Actions | Convex Developer Hub
Actions can call third party services to do things such as processing a payment
ampp
ampp2d ago
i use clerk/backend without 'useNode to do this - basically:
import { createClerkClient } from '@clerk/backend'
const clerkClientInstance = createClerkClient({
secretKey: process.env.CLERK_SECRET_KEY,
})

export const deleteUser = internalAction({
args: { userId: v.string() },
handler: async (ctx, args) => {
const result = await clerkClientInstance.users.deleteUser(args.userId)
return true
},
})
import { createClerkClient } from '@clerk/backend'
const clerkClientInstance = createClerkClient({
secretKey: process.env.CLERK_SECRET_KEY,
})

export const deleteUser = internalAction({
args: { userId: v.string() },
handler: async (ctx, args) => {
const result = await clerkClientInstance.users.deleteUser(args.userId)
return true
},
})
ballingt
ballingt2d ago
Ah yeah, apparently it's just import { clerkClient } from "@clerk/nextjs/server"; that needs Node.js, but '@clerk/backend' works in the normal convex js runtime
Solution
DylanDev
DylanDev11h ago
@Tom thank you tom! I ended up splitting the code into a mutation and an action. That way I could use the third party call inside of the backend!
DylanDev
DylanDevOP11h ago
Thank you for your help!
DylanDev
DylanDevOP10h ago
Are you supposed to declare a clerkClientInstance inside of every action or should I declare that at the very top of the .ts file to be used everywhere