@@ -17,9 +17,10 @@ import {
1717import { convexTest } from "convex-test" ;
1818import { assertType , describe , expect , expectTypeOf , test } from "vitest" ;
1919import { modules } from "./setup.test.js" ;
20- import { zCustomQuery , zCustomMutation , zCustomAction } from "./zod4.js" ;
20+ import { zCustomQuery , zCustomMutation , zCustomAction , zid } from "./zod4.js" ;
2121import { z } from "zod/v4" ;
2222import { v } from "convex/values" ;
23+ import { NoOp } from "./customFunctions.js" ;
2324
2425const schema = defineSchema ( {
2526 users : defineTable ( {
@@ -186,13 +187,52 @@ export const codec = zQuery({
186187 } ) ,
187188} ) ;
188189
190+ // The example from README.md
191+ const zodQuery = zCustomQuery ( query , NoOp ) ;
192+ export const myComplexQuery = zodQuery ( {
193+ args : {
194+ userId : zid ( "users" ) ,
195+ email : z . email ( ) ,
196+ num : z . number ( ) . min ( 0 ) ,
197+ nullableBigint : z . nullable ( z . bigint ( ) ) ,
198+ boolWithDefault : z . boolean ( ) . default ( true ) ,
199+ null : z . null ( ) ,
200+ array : z . array ( z . string ( ) ) ,
201+ optionalObject : z . object ( { a : z . string ( ) , b : z . number ( ) } ) . optional ( ) ,
202+ union : z . union ( [ z . string ( ) , z . number ( ) ] ) ,
203+ discriminatedUnion : z . discriminatedUnion ( "kind" , [
204+ z . object ( { kind : z . literal ( "a" ) , a : z . string ( ) } ) ,
205+ z . object ( { kind : z . literal ( "b" ) , b : z . number ( ) } ) ,
206+ ] ) ,
207+ literal : z . literal ( "hi" ) ,
208+ enum : z . enum ( [ "a" , "b" ] ) ,
209+ readonly : z . object ( { a : z . string ( ) , b : z . number ( ) } ) . readonly ( ) ,
210+ pipeline : z . number ( ) . pipe ( z . coerce . string ( ) ) ,
211+ } ,
212+ handler : async ( _ctx , args ) => {
213+ //... args at this point has been validated and has the types of what
214+ // zod parses the values into.
215+ // e.g. boolWithDefault is `bool` but has an input type `bool | undefined`.
216+
217+ return args ;
218+ } ,
219+ } ) ;
220+ export const generateUserId = mutation ( {
221+ args : { } ,
222+ handler : async ( { db } ) => {
223+ return db . insert ( "users" , { name : "Nicolas" } ) ;
224+ } ,
225+ } ) ;
226+
189227const testApi : ApiFromModules < {
190228 fns : {
191229 testQuery : typeof testQuery ;
192230 testMutation : typeof testMutation ;
193231 testAction : typeof testAction ;
194232 transform : typeof transform ;
195233 codec : typeof codec ;
234+ myComplexQuery : typeof myComplexQuery ;
235+ generateUserId : typeof generateUserId ;
196236 } ;
197237} > [ "fns" ] = anyApi [ "zod4.functions.test" ] as any ;
198238
@@ -259,6 +299,42 @@ describe("zCustomQuery, zCustomMutation, zCustomAction", () => {
259299 >
260300 > ( ) ;
261301 } ) ;
302+
303+ test ( "README example" , async ( ) => {
304+ const t = convexTest ( schema , modules ) ;
305+ const userId = await t . mutation ( testApi . generateUserId ) ;
306+ const response = await t . query ( testApi . myComplexQuery , {
307+ userId,
308+ 309+ num : 42 ,
310+ nullableBigint : 123n ,
311+ null : null ,
312+ array : [ "foo" , "bar" ] ,
313+ optionalObject : { a : "test" , b : 1 } ,
314+ union : "hello" ,
315+ discriminatedUnion : { kind : "a" , a : "value" } ,
316+ literal : "hi" ,
317+ enum : "a" ,
318+ readonly : { a : "readonly" , b : 2 } ,
319+ pipeline : 100 ,
320+ } ) ;
321+ expect ( response ) . toMatchObject ( {
322+ userId,
323+ 324+ num : 42 ,
325+ nullableBigint : 123n ,
326+ boolWithDefault : true ,
327+ null : null ,
328+ array : [ "foo" , "bar" ] ,
329+ optionalObject : { a : "test" , b : 1 } ,
330+ union : "hello" ,
331+ discriminatedUnion : { kind : "a" , a : "value" } ,
332+ literal : "hi" ,
333+ enum : "a" ,
334+ readonly : { a : "readonly" , b : 2 } ,
335+ pipeline : "100" ,
336+ } ) ;
337+ } ) ;
262338 } ) ;
263339
264340 describe ( "transform" , ( ) => {
0 commit comments