#I want to call this from a server side function. How can I do that?
7 messages · Page 1 of 1 (latest)
To call the get function from another server-side function, you have several options depending on your specific use case:
Option 1: Use a helper function (Recommended)
The best practice is to extract the handler logic into a helper function that can be reused:
// Helper function
export async function getUserHelper(ctx) {
const userId = await getAuthUserId(ctx);
console.log("getting user", { userId });
return await ctx.db
.query("users")
.filter((q) => q.eq(q.field("_id"), userId))
.first();
}
// Public query
export const get = query({
args: {},
handler: getUserHelper
});
Then you can call this helper function directly from other server-side functions:
import { getUserHelper } from "./path/to/helper";
export const anotherFunction = query({
args: {},
handler: async (ctx) => {
const user = await getUserHelper(ctx);
// Do something with user
}
});
This approach is recommended as it avoids the overhead of creating a new transaction and performing argument validation, as mentioned in the best practices documentation.
Option 2: Use ctx.runQuery
If you need to call the function from an action (which has a different context), you'll need to use ctx.runQuery:
import { api } from "../convex/_generated/api";
export const myAction = action({
args: {},
handler: async (ctx) => {
const user = await ctx.runQuery(api.path.to.get);
// Do something with user
}
});
Option 3: Use internalQuery
If you want to make the function accessible only to other Convex functions but not to clients, use internalQuery:
export const getInternal = internalQuery({
args: {},
handler: async (ctx) => {
const userId = await getAuthUserId(ctx);
console.log("getting user", { userId });
return await ctx.db
.query("users")
.filter((q) => q.eq(q.field("_id"), userId))
.first();
}
});
Then call it using ctx.runQuery from other functions:
import { api } from "../convex/_generated/api";
export const anotherFunction = query({
args: {},
handler: async (ctx) => {
const user = await ctx.runQuery(api.path.to.getInternal);
// Do something with user
}
});
Summary
- Use helper functions when sharing code between queries/mutations (Option 1)
- Use
ctx.runQuerywhen calling from actions (Option 2) - Use
internalQuerywhen you want to hide the function from clients (Option 3)
The helper function approach is generally preferred for performance reasons, as noted in the Discord support thread and best practices documentation.
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
@crystal nymph Kapa.ai is still learning and improving, please let me know how I did by reacting below.
if i use the first approach: can I simply call the function in a regular server component (api/route.ts) @worn garden in nextjs
Let me check the knowledge base for you again. One moment! :books:
No, you cannot directly call a Convex helper function from a Next.js server component or route handler. Helper functions are only accessible within Convex functions because they require the Convex context (ctx).
For Next.js server components or route handlers, you need to use the fetchQuery, fetchMutation, or fetchAction functions from the Convex Next.js integration. Here's how you would do it:
import { api } from "@/convex/_generated/api";
import { fetchQuery } from "convex/nextjs";
// In a Next.js Route Handler (app/api/route.ts)
export async function GET() {
const user = await fetchQuery(api.path.to.get);
return Response.json({ user });
}
This is documented in the Next.js Server Rendering documentation, which shows how to use Convex from Server Actions and Route Handlers.
For example, here's how you would call a Convex query from a Route Handler:
import { NextResponse } from "next/server";
// Hack for TypeScript before 5.2
const Response = NextResponse;
import { api } from "@/convex/_generated/api";
import { fetchQuery } from "convex/nextjs";
export async function GET() {
const tasks = await fetchQuery(api.tasks.list, { list: "default" });
return Response.json({ tasks });
}