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
jamwt
jamwt2y ago
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
Chad Maycumber
Chad MaycumberOP2y ago
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?
ian
ian2y ago
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)
Chad Maycumber
Chad MaycumberOP2y ago
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.
ian
ian2y ago
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.
Chad Maycumber
Chad MaycumberOP2y ago
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?
ian
ian2y ago
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:
export const myQuery = query({
handler: withZod(
{ a: z.number(), b: z.string().max(4) }, // input
async ({db}, {a, b}) => {
... // a and b are automatically typed in here
},
z.string() // output
),
});
export const myQuery = query({
handler: withZod(
{ a: z.number(), b: z.string().max(4) }, // input
async ({db}, {a, b}) => {
... // a and b are automatically typed in here
},
z.string() // output
),
});
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
ian
ian2y ago
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)
Chad Maycumber
Chad MaycumberOP2y ago
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
Michael Rea
Michael Rea16mo ago
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.
Indy
Indy16mo ago
Yes you should be able to follow a similar pattern for Actions as well.
lee
lee16mo ago
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.
Michael Rea
Michael Rea16mo ago
I tried but I gave up... Yeah I discoverd that it doesn't have access to db.query
ian
ian16mo ago
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)
Michael Rea
Michael Rea16mo ago
I seem to lose my autocomple of my args on the front end with the wrappers.
Michael Rea
Michael Rea16mo ago
No description
ian
ian16mo ago
You can add a type annotation and see if that helps? helper: async (ctx): Doc<"users"> => {
Michael Rea
Michael Rea16mo ago
Okay, great thank you
Michael Rea
Michael Rea13mo ago
@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
No description
Michael Rea
Michael Rea13mo ago
I can run this fine when it's called in the convex actions
Michael Rea
Michael Rea13mo ago
No description
Michael Rea
Michael Rea13mo ago
No description
Michael Rea
Michael Rea13mo ago
I get this error when trying to use it with the actionWithUser "Type instantiation is excessively deep and possibly infinite.ts(2589)"
ian
ian13mo ago
For those sorts of errors try adding return type annotations to the functions. Like for currentUser handler async (ctx): Promise<Doc<"users"> | null> =>
Michael Rea
Michael Rea13mo ago
Thanks again, at first the error didn't go away but on reloading my IDE it came right
Michael Rea
Michael Rea13mo ago
No description

Did you find this page helpful?