Ali MadooeiA
Convex Community14mo ago
4 replies
Ali Madooei

Internal queries/mutations/actions vs helper functions

Hi everyone! I'm trying to understand the difference between internal queries/mutations/actions and regular helper functions. I'm going to write down my thoughts here, in a contrived example., and I hope you can help me understand it better. Thanks!

// convex/somefile.ts
import { internalQuery, query } from "./_generated/server";
import { internal } from "./_generated/api";
import { v } from "convex/values";

// Do we have to `export` it? Or the 'query' factory will make it public irrespective?
export const myPublicQuery = query({
  args: {
    a: v.string(), // some argument; it will be validated
  },
  handler: async (ctx, args) => {
    
    // I can call `myPrivateQuery` here
    await ctx.runQuery(internal.somefile.myPrivateQuery, args);

    // I can also directly call `myPrivateQuery` here like a regular function
    await myPrivateQuery(ctx, args);

    // So, should I use `runQuery` or call the internal query directly?

    // I can call `myHelper` here as well
    await myHelper(ctx, args);

    // So, why when would I want a helper to be internal query/mutation/action?
    // Is the difference only in the arguments validation?
  },
});


// Do we need the `export` here? Even in other files it can be accessed through 
// `internal.somefile.myPrivateQuery` as long as it is an `internalQuery`, right?
export const myPrivateQuery = internalQuery({
  args: {
    a: v.string(), // This argument will be validated
  },
  handler: async (ctx, args) => {
    // Do something
  },
});


// Doesn't have to be exported, but can be if you want to use it in other files
export const myHelper = (ctx: QueryCtx, { a }: { a: string }) => {
  // Do the exact same thins as in `myPrivateQuery`
  // If I want to validate the arguments, I must do it myself using e.g. Zod
};
Was this page helpful?