Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support additional generic for typing incoming body & query #129

Closed
1 task
danielroe opened this issue Jun 4, 2022 · 13 comments · Fixed by #417
Closed
1 task

support additional generic for typing incoming body & query #129

danielroe opened this issue Jun 4, 2022 · 13 comments · Fixed by #417
Assignees
Labels
enhancement New feature or request

Comments

@danielroe
Copy link
Member

would support something like this:

export default defineEventHandler<{ result: string }, { foo: string }>(async event => {
  const { foo } = await useBody(event)
  return {
    result: foo
  }
})

const result = await $fetch('/api/test', {
  body: {
    // auto-completing body, requiring 
  }
})

Follow-up tasks

  • add support for typing query/body in Nitro generated types & ohmyfetch (via options)

possibly could also consider params?

@kevinmarrec
Copy link
Contributor

kevinmarrec commented Jun 4, 2022

@danielroe Does useQuery & useBody already provides generic type ?

I also had schema validation Idea that could be implemented within the composables, like useBody handling bad requests using JSON schema type builder like https://github.com/sinclairzx81/typebox . useBody could then infer type from schema

@pi0
Copy link
Member

pi0 commented Jun 4, 2022

Love the ideas!

useBody accepts type generic (useParams doesn't. PR welcome to add!)

We can introduce request validation with an external package like h3-typebox exposing useValidatedBody(event) with type inference and wrapping useBody. Later we might introduce a built-in util based on ajv/untyped or more h3 tailored DX.

I guess would be safer if we namespace second genetic for extensibility like { body: {}, query: {} }. But how do you plan to type useBody call within defineEventHandler without explicitly giving generic to it @danielroe

@kevinmarrec
Copy link
Contributor

Will be glad to help you guys on this stuff 🚀

@pi0
Copy link
Member

pi0 commented Jun 4, 2022

Feel free to initiate h3-typebox @kevinmarrec ❤️ You can use unjs/template for starter.

@wobsoriano
Copy link
Contributor

wobsoriano commented Jun 9, 2022

Now, this is awesome! With express and zod for example, you can type the body like this:

import { Request, RequestHandler, Response } from 'express';

export const validateRequestBody: <TBody>(
  zodSchema: ZodSchema<TBody>,
) => RequestHandler<ParamsDictionary, any, TBody, any> = (schema) => (req, res, next) => {
  const parsed = schema.safeParse(req.body);
  if (parsed.success) {
    return next();
  } else {
    return res.status(400).send(parsed.error)
  }
};
import { validateRequestBody } from './validation'
import { z } from 'zod';

app.get("/", validateRequestBody(
    z.object({
      name: z.string(),
      age: z.number(),
    })
  ), (req, res) => {
    // req.body is now strictly-typed and confirms to the zod schema above.
    // req.body: { name: string, age: number };
  }
);

I think we should accept any TypeScript schema validator (zod,typebox,yup). I'm thinking something like:

import { z } from 'zod'
import { someResolverFn } from 'your-library'

const schema = z.object({
  name: z.string(),
  age: z.number(),
})

useValidatedBody(event, {
  resolver: someResolverFn(schema)
})
import { object, string, number } from 'yup'
import { someResolverFn } from 'your-library'

const schema = object({
  name: string().required(),
  age: number().required().positive().integer()
})

useValidatedBody(event, {
  resolver: someResolverFn(schema)
})

@kevinmarrec
Copy link
Contributor

kevinmarrec commented Jun 12, 2022

I just released h3-typebox (source) 🚀

Feedbacks are welcome !

@pi0
Copy link
Member

pi0 commented Aug 3, 2022

I just forgot this issue. @kevinmarrec Do you mind to open a PR to add your nice package to the readme?

@atinux
Copy link
Member

atinux commented Aug 4, 2022

I would personnaly rename it to h3-validator (but fine with h3-typebox if listed in Readme as validator options) and support the new event object @kevinmarrec 😊

Awesome work so far ❤️

@kevinmarrec
Copy link
Contributor

@pi0 I opened the PR :)

@pi0
Copy link
Member

pi0 commented Aug 4, 2022

I would personnaly rename it to h3-validator (but fine with h3-typebox if listed in Readme as validator options) and support the new event object @kevinmarrec 😊

This issue is still open for a built-in validation. Conventionally, by using the integration name in h3-[integration] we can support other possible validators from community.

@septatrix
Copy link

But how do you plan to type useBody call within defineEventHandler without explicitly giving generic to it @danielroe

It might be possible by passing down the annotations to the event parameter which could then allow readBody to infer it from there.

@aspitrine
Copy link

Hi,

I see this issue as close but the $fetch typed part was not working (in nuxt) and i can't find any issue in the nuxt repository about this.

In the h3 repo it's ok, we have the generic and readBody was working.

What's the actual state for this ?

Thank's for all your hard work 🙏🏻

@septatrix
Copy link

In the PR closing this it is explicitly stated that using this for $fetch within nuxt is something which still has to be done. It is likely best if you create a new issue in the nuxt repository for tracking that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants