#I want to call this from a server side function. How can I do that?

7 messages · Page 1 of 1 (latest)

worn gardenBOT
#

Hi @crystal nymph. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:

#

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.runQuery when calling from actions (Option 2)
  • Use internalQuery when 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.

crystal nymph
#

if i use the first approach: can I simply call the function in a regular server component (api/route.ts) @worn garden in nextjs

worn gardenBOT
#

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 });
}

Remember that you need to configure your Convex deployment URL either through the NEXT_PUBLIC_CONVEX_URL environment variable or by passing the url option to the fetch functions as mentioned in the configuration documentation.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: