uploadthing icon indicating copy to clipboard operation
uploadthing copied to clipboard

Add Convex adapter

Open sujayakar opened this issue 5 months ago • 2 comments

This PR adds a Convex adapter as a sibling to Express, Fastify, etc. It was pretty straightforward to add a new adapter!

Here's what it looks like for wiring it in to a Convex app. First, call createUploadthing as always:

// convex/http.ts
import { addUploadthingRoutes, convexCtx, createUploadthing, type FileRouter } from "uploadthing/convex"
import schema from "./schema"

const f = createUploadthing({
  errorFormatter: (err) => {
    console.log("Error uploading file", err.message);
    console.log("  - Above error caused by:", err.cause);

    return { message: err.message };
  },
  schema,
});

Note that the developer can optionally pass in their Convex schema here for more type-safety within their handlers.

Then, define the router, using the convexCtx function to access the request's current ctx value. This is necessary for calling into other Convex functions, accessing auth and the database, etc. Under the hood, this uses a hack where we stash the ctx when starting a request.

export const uploadRouter = {
  imageUploader: f({ image: { maxFileSize: "4MB" } })
    .middleware(async (args) => {
      const ctx = convexCtx(f);      
      const identity = await ctx.auth.getUserIdentity();
      ...
      return { userId: identity?.subject ?? "nothing" }
    })
    .onUploadComplete(async (args) => {      
      const ctx = convexCtx(f);
      ...      
      return { uploadedBy: args.metadata.userId };
    }),
} satisfies FileRouter;
export type OurFileRouter = typeof uploadRouter;

Finally, install the routes into Convex's HTTP router with addUploadthingRoutes:

const http = httpRouter();
addUploadthingRoutes(http, f, { router: uploadRouter })
export default http;    

Questions

  • The hack to sneak in ctx via a "global" with convexCtx is a bit ugly. Is there a better way to pass values to the middleware and completion callbacks?
  • Where should I add Convex to the docs? Would another entry next to https://docs.uploadthing.com/backend-adapters/express be the right spot?
  • Should I add my Uploadthing+Convex example app from the snippets above as a new directory under examples/? It'll require setting up a Convex account (or self hosting Convex) to actually run the demo.
  • Are there any tests, etc., that I should also be updating?

sujayakar avatar Sep 03 '24 04:09 sujayakar