anmot.
anmot.9mo ago

zod return validator in convex-helpers?

Are there any plans to add return validator in convex-helpers/server/zod?
16 Replies
ian
ian9mo ago
I added that when I originally introduced the zod helpers - it's called "output" since we hadn't landed on the name "returns" yet. I'm hesitant to change the name as it'd be a breaking change, but it would be more symmetric... what would have made this more discoverable? Where could I drop a comment pointing people to use "output"? https://stack.convex.dev/typescript-zod-function-validation#output-validation
Stack
Zod with TypeScript for Server-side Validation and End-to-End Types
Use Zod with TypeScript for argument validation on your server functions allows you to both protect against invalid data, and define TypeScript types ...
anmot.
anmot.OP9mo ago
Thanks for pointing out. Rather than removing "output", can we consider keeping it and adding "returns" to prevent any confusion in the future. Also they follow different syntax for defining schema.
output: z.object({
id: z.string(),
}),

returns: {
id: z.string()
},
output: z.object({
id: z.string(),
}),

returns: {
id: z.string()
},
ian
ian9mo ago
Interesting - I assumed people would want to use Zod for both input & output, but would you prefer to use Convex validators for the return validators? The types will likely get pretty gnarly, but maybe I could get it to work specifying either if there's a lot of interest. Out of curiosity, what is your usecase for the return validators? Just an extra sanity check? Also feel free to fork & submit a PR if you get it working - I won't have bandwidth to dig in here for a while
anmot.
anmot.OP9mo ago
Edited my comment (changed v to z). It would be nice to use similar syntax for both the input and output validators but shouldn’t be a major concern as we have atleast output validator to work with.
ian
ian9mo ago
The returns type actually isn't always an object. you can pass v.null() (z.null()) or any valid Convex value. So you could do returns: z.string() or z.object({ id: z.string() }) but passing an object directly would require the library assuming you want to turn that into a z.object right?
anmot.
anmot.OP9mo ago
It might work with convex values but I think zod validators (args and output) are not flexible IMO. Please correct me if my understanding is incorrect. z.object doesn't work on args, it only takes {}
args: z.object({
id: z.string(),
}),

Type 'ZodObject<{ id: ZodString; }, "strip", ZodTypeAny, { id: string; }, { id: string; }>' is not assignable to type 'void | ZodValidator | undefined
args: z.object({
id: z.string(),
}),

Type 'ZodObject<{ id: ZodString; }, "strip", ZodTypeAny, { id: string; }, { id: string; }>' is not assignable to type 'void | ZodValidator | undefined
{} doesn't work on output, it only takes zod type
output: {
id: z.string(),
},

Object literal may only specify known properties, and 'id' does not exist in type 'ZodTypeAny'.ts(2353)
output: {
id: z.string(),
},

Object literal may only specify known properties, and 'id' does not exist in type 'ZodTypeAny'.ts(2353)
ian
ian9mo ago
That is because args has to be an object and the output doesn’t, as that’s how convex functions are defined (named arguments). So anything you can do with Convex you can do with the zod validators too. I’m not sure I’m understanding. To return {} you use z.object. To have z.object as args you just don’t include the z.object part. Would it be better if args accepted z.object explicitly?
anmot.
anmot.OP9mo ago
I understand now. Thanks for the clarification.
ian
ian2mo ago
@anmot. FYI in convex-helpers@0.1.72-alpha.1 you can pass output as an object, instead of wrapping them in z.object 🎉 I finally came around on the ergonomic benefit 😅
anmot.
anmot.OP2mo ago
Thanks Ian for supporting this.
ian
ian2mo ago
Happy to help! And you can try out convex-helpers@0.1.72-alpha.2 which also has pasing a z.object as args. If they work for you I can push them in the next version 🌈
anmot.
anmot.OP5w ago
Unable to deploy convex when migrating from convex-helpers 0.1.71 to 0.1.72* / 0.1.73 type inference is not working in the latest versions, atleast in my case.
const getOrdersByParentOrderId: RegisteredQuery<"internal", {
parentOrderId: string;
xRequestId?: string | undefined;
xSessionId?: string | undefined;
}, any>
const getOrdersByParentOrderId: RegisteredQuery<"internal", {
parentOrderId: string;
xRequestId?: string | undefined;
xSessionId?: string | undefined;
}, any>
No description
anmot.
anmot.OP5w ago
No description
ian
ian5w ago
So 0.1.73 doesn't work but 0.1.71 does? Rats. I can't take a look today so you might want to stick with 0.1.71 for now and manually patch the types for the ts-api-spec (or use 0.1.73 to generate spec, then 0.1.71 at runtime). Sorry! I cut convex-helpers@0.1.74 which should fix it when not specifying output/returns. lmk if it works for you. Btw I also added a way to extract the ctx type for custom zod functions: ZCustomCtx<typeof internalQuery> (where internalQuery is your version)
anmot.
anmot.OP5w ago
is it 0.1.74 or 0.1.74-alpha.1? 0.1.74-alpha.1 seems to be working fine.
ian
ian5w ago
Either. the naming conventions are a bit confusing, but 0.1.74 actually comes after 0.1.74-alpha.1 . Alphas are the "pre-relase" version, with the version that will come out. I decided to just ship it as the official version.

Did you find this page helpful?