blomqma / next-rest-framework

Type-safe, self-documenting APIs for Next.js
https://next-rest-framework.vercel.app
Other
155 stars 20 forks source link

Allow query object to transform inputs #116

Closed crummy closed 7 months ago

crummy commented 9 months ago

I have an API endpoint that takes some numbers as inputs. I know they are handled as strings, but I would like to use Zod to transform them to numbers for easier handling later.

This works:

.input({
      query: z.object({
        total: z.string()
      })

However, if I try to transform it I get an error:

.input({
      query: z.object({
        total: z.string().transform((data) => Number(data))
      })

Here's the error:

TS2322: Type
ZodObject<{   foo: ZodEffects<ZodString, number, string>; }, 'strip', ZodTypeAny, {   foo: number; }, {   foo: string; }>
is not assignable to type ZodType<BaseQuery, ZodTypeDef, BaseQuery>
Types of property _type are incompatible.
Type { foo: number; } is not assignable to type BaseQuery
Property foo is incompatible with index signature.
Type number is not assignable to type string | string[]

I understand why query is typed as Record<string, string | string[]> as that's what they come in as - but is there no way to transform this input to a different type?

blomqma commented 9 months ago

In your API handler you would access the query parameters from the request object which is an abstraction on top of NextRequest (App Router) and NextApiRequest (Page Router) objects. I believe these objects do not by default support providing the query parameters as non-string values and this would essentially break the way those objects are supposed to work with Next.js. Instead, I would narrow the BaseQuery type to allow only string values for the query parameters for now to better document how the query schema is meant to be defined.

This leads me to another observation that the usage of Zod transforms in general is problematic as neither the query parameters nor the request body are parsed values using the Zod schema but they are untouched from the original request, so they are only validated, not parsed. However, I see the benefit of using Zod transforms so this needs to be further investigated if we could pass through the actual parsed values instead of just validating the request bodies and query parameters. For now I suggest doing the string transformation in your handler function.

blomqma commented 7 months ago

Hey, v6.0.0-beta.1 is now released that should address your issue. Zod transforms are now supported as the Zod-parsed results from the query parameters, search parameters and request bodies are now injected into a cloned request object, passed into the API handler.

markedwards commented 5 months ago

I still hit this on v6.0.0.

I see the parsed type injected into the hander, however I still get the type error described in the original description above.