Best way to add types to middleware
I'm taking a look at articles like this: https://stack.convex.dev/wrappers-middleware-e2b related to middleware, but I'm having trouble coming up with a typed Auth middleware that works for everything.
Would love to some help here if possible.
Edge to Butt: Wrappers as "Middleware"
Convex middleware serves many purposes. Sometimes authentication, sometimes i18n. This time? Making sense (or nonsense) of emerging technology industr...
26 Replies
hey @Chad Maycumber ... did you see this thread? https://discord.com/channels/1019350475847499849/1100163345077764230
Ian is actually working on the middleware approaches for 0.13... good chance the same exploration will shed some light on validation
Okay cool this is awesome thanks!
In terms of validation as well, is there anyway to merge zod w/ convex validation? Like not too separate instances?
Yup I’m working on this today.
As for unifying z / v, what would your ideal solution be? A function to turn zod types into our types? The reverse? Us just using zod? Each solution has some gotchas, since we do the validation at the Rust layer so can’t execute arbitrary JS (e.g. a custom zod validator)
Oh man that would be amazing
Either would be fine with me. I mainly use Zod types for form validation on the frontend and a tRPC api on the backend (slowly migrating what I can to convex), which is also turned into a series of OpenAPI rest endpoints. Unifying these would be the best thing in the world.
Honestly if you guys used Zod that would be amazing especially for the TS/JS ecosystem, I understand there's more to support.
https://discord.com/channels/1019350475847499849/1100163345077764230/1100697925081903114 for an update on middleware for 0.13.0.
As for transforming frontend zod validation into types, one issue I see is that even if we map the zod types to convex validators, the convex validator would only be checking the type. We wouldn't support all of zod's functionality out of the gate (e.g. don't support arbitrary types, custom validation functions, etc). We may change this in the future, but as-is, would you still want something that made the convex validators out of zod ones? I'd fear someone would assume they're going to do the full validation.
I do see what you mean! I'd still find it useful regardless, it'd save a lot of duplicate code. Would it be possible to test an incoming "args" key as a Zod object, and then just use that for validation?
Yeah that would be great. We're discussing internally, so this is good feedback. If we end up prioritizing it, I'll update here. But it likely won't happen immediately, so I don't think we'll be able to save you the duplicated effort this time. You can still use my zod wrapper for validation though:
I have a version updated for 0.13 at https://github.com/get-convex/convex-helpers/tree/0.13.0/convex
GitHub
convex-helpers/convex at 0.13.0 · get-convex/convex-helpers
A collection of useful code to complement the official packages. - convex-helpers/convex at 0.13.0 · get-convex/convex-helpers
It just isn't the built-in validation, and you'd still need to define schemas with
v
In fact, I think that withZod
wrapper should be updated to mimic the arg validation params (just take an object with args
and handler
)Thanks! It seems like you guys move fast so looking forward to reducing my duplicates when these features do get shipped, in the meantime this will work great thanks
Would this work also with actions so we have a ActionWithUser?
I'm trying to protect actions that call to openAi. Maybe I'm approaching this wrong.
Yes you should be able to follow a similar pattern for Actions as well.
The middleware may be a bit different, because actions cannot call
db.query
directly to check auth. But the middleware can call an internal query to get the user. Or the queries and mutations called by the action can do their own auth checks. Let us know if you have trouble writing the middleware.I tried but I gave up... Yeah I discoverd that it doesn't have access to db.query
One thing to do is to just use
ctx.runQuery
to call a query that uses the queryWithUser
wrapper to fetch data from the DB (or just authorizes the call)I seem to lose my autocomple of my args on the front end with the wrappers.

You can add a type annotation and see if that helps?
helper: async (ctx): Doc<"users"> => {
Okay, great thank you
@ian So I'm trying this again but this time using the convex-helpers
In a similar spot where I want to use actionWithUser
but my user table looks like this

I can run this fine when it's called in the convex actions


I get this error when trying to use it with the actionWithUser
"Type instantiation is excessively deep and possibly infinite.ts(2589)"
For those sorts of errors try adding return type annotations to the functions. Like for currentUser handler
async (ctx): Promise<Doc<"users"> | null> =>
Thanks again, at first the error didn't go away but on reloading my IDE it came right
