Advanced Clerk Stuff in Convex

I assume if you want to createUsers, validate if a user exists in Clerk etc. inside of Convex you have to use the clerk-sdk-node. Right?
11 Replies
Michal Srb
Michal Srb•11mo ago
Yes, I would assume so.
FleetAdmiralJakob 🗕 🗗 🗙
Ok, I just wanted to make sure that convex does not have its own implementation of that.
FleetAdmiralJakob 🗕 🗗 🗙
Hi, I tried both the @clerk/backend and @clerk/clerk-sdk-node and both give me this error if I call my (ent) mutation
No description
FleetAdmiralJakob 🗕 🗗 🗙
Code:
import { clerkClient } from "@clerk/clerk-sdk-node";

export const createChat = mutation({
args: { friendsUsername: v.string(), friendsUsernameId: v.number() },
handler: async (ctx, args) => {
const identity = await ctx.auth.getUserIdentity();
if (identity === null) {
throw new Error("Unauthenticated call to mutation");
}

const user = await clerkClient.users.getUserList({
username: [args.friendsUsername + args.friendsUsernameId],
limit: 1,
});

if (!user?.[0]) {
throw new Error("User not found");
}

await ctx
.table("privateChats")
.insert({ memberIds: [identity.tokenIdentifier, user[0].id] });
},
});
import { clerkClient } from "@clerk/clerk-sdk-node";

export const createChat = mutation({
args: { friendsUsername: v.string(), friendsUsernameId: v.number() },
handler: async (ctx, args) => {
const identity = await ctx.auth.getUserIdentity();
if (identity === null) {
throw new Error("Unauthenticated call to mutation");
}

const user = await clerkClient.users.getUserList({
username: [args.friendsUsername + args.friendsUsernameId],
limit: 1,
});

if (!user?.[0]) {
throw new Error("User not found");
}

await ctx
.table("privateChats")
.insert({ memberIds: [identity.tokenIdentifier, user[0].id] });
},
});
and code for @clerk/backend:
import { Clerk } from "@clerk/backend";

const clerkClient = Clerk({secretKey: process.env.CLERK_SECRET_KEY})

export const createChat = mutation({
args: { friendsUsername: v.string(), friendsUsernameId: v.number() },
handler: async (ctx, args) => {
const identity = await ctx.auth.getUserIdentity();
if (identity === null) {
throw new Error("Unauthenticated call to mutation");
}

const user = await clerkClient.users.getUserList({
username: [args.friendsUsername + args.friendsUsernameId],
limit: 1,
});

if (!user?.[0]) {
throw new Error("User not found");
}

await ctx
.table("privateChats")
.insert({ memberIds: [identity.tokenIdentifier, user[0].id] });
},
});
import { Clerk } from "@clerk/backend";

const clerkClient = Clerk({secretKey: process.env.CLERK_SECRET_KEY})

export const createChat = mutation({
args: { friendsUsername: v.string(), friendsUsernameId: v.number() },
handler: async (ctx, args) => {
const identity = await ctx.auth.getUserIdentity();
if (identity === null) {
throw new Error("Unauthenticated call to mutation");
}

const user = await clerkClient.users.getUserList({
username: [args.friendsUsername + args.friendsUsernameId],
limit: 1,
});

if (!user?.[0]) {
throw new Error("User not found");
}

await ctx
.table("privateChats")
.insert({ memberIds: [identity.tokenIdentifier, user[0].id] });
},
});
erquhart
erquhart•11mo ago
Those clerk sdk functions are trying to make network calls, which can only be made through actions (not queries or mutations).
FleetAdmiralJakob 🗕 🗗 🗙
oh, thank you Would be nice to have an error for that. Something like Error: Tried to make a network request inside the mutation. Try to use an action.
erquhart
erquhart•11mo ago
Yeah I agree - if you open another support post with that request and add the Feature Request label the team can track it
FleetAdmiralJakob 🗕 🗗 🗙
Is it the right way to use the scheduler for outsourcing the clerk code to an action?
erquhart
erquhart•11mo ago
You're using the data returned from Clerk in your mutation so you would need to kick this off with an action that gets the data from clerk and then uses ctx.runMutation() to run the mutation, passing in the received data. That said, actions are not as reliable as queries or mutations, so the recommended approach is to maintain a users table in your Convex db and sync data to it from Clerk. That will allow you to do all of this in Convex with using an action.
FleetAdmiralJakob 🗕 🗗 🗙
"with using an action?" if I maintain the users also in convex i don't need the action anymore, right?
erquhart
erquhart•11mo ago
oh sorry, I meant "without using an action" right, wouldn't be needed

Did you find this page helpful?