Git Product home page Git Product logo

h3-zod's Introduction

h3-zod

npm (tag) npm bundle size NPM

Validate h3 and Nuxt requests with zod.

Important

Starting with h3 version 1.8.0, built-in runtime + type-safe request utilities are included, so you might not need this module.

Install

npm install zod h3-zod

Usage

Import it like:

import { zh } from 'h3-zod';

// Or

import { useSafeValidatedQuery, useSafeValidatedBody } from 'h3-zod';

Helpers that don't throw when parsing fails:

export default defineEventHandler(async (event) => {
  const query = zh.useSafeValidatedQuery(event, z.object({
    required: z.string()
  }))

  const body = await zh.useSafeValidatedBody(event, z.object({
    optional: z.string().optional(),
    required: z.boolean()
  }))

  const params = zh.useSafeValidatedParams(event, {
    id: z.number()
  })

  if (!params.success) {
    // params.error
  }
})

Helpers that throw error 400 when parsing fails:

export default defineEventHandler(async (event) => {
  const query = zh.useValidatedQuery(event, z.object({
    required: z.string()
  }))

  const body = await zh.useValidatedBody(event, z.object({
    optional: z.string().optional(),
    required: z.boolean()
  }))

  const params = await zh.useValidatedParams(event, {
    id: z.number()
  })
})

You can also pass an object schema:

export default defineEventHandler(async (event) => {
  const body = await zh.useValidatedBody(event, {
    optional: z.string().optional(),
    required: z.boolean()
  })
})

Helper Zod Schemas

zh.boolAsString

  • "true"true
  • "false"false
  • "notboolean" → throws ZodError

zh.checkboxAsString

  • "on"true
  • undefinedfalse
  • "anythingbuton" → throws ZodError

zh.intAsString

  • "3"3
  • "3.14" → throws ZodError
  • "notanumber" → throws ZodError

zh.numAsString

  • "3"3
  • "3.14"3.14
  • "notanumber" → throws ZodError

Usage

const Schema = z.object({
  isAdmin: zh.boolAsString,
  agreedToTerms: zh.checkboxAsString,
  age: zh.intAsString,
  cost: zh.numAsString,
});

const parsed = Schema.parse({
  isAdmin: 'true',
  agreedToTerms: 'on',
  age: '38',
  cost: '10.99'
});

console.log(parsed)
// {
//   isAdmin: true,
//   agreedToTerms: true,
//   age: 38,
//   cost: 10.99
// }

Related

License

MIT

h3-zod's People

Contributors

barbapapazes avatar madebyfabian avatar noook avatar wobsoriano avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

h3-zod's Issues

the validate body don't throw a 400

I am using what you are saying in your doc. The one says should send a 400 status code.

But nothing happened when using it. Is the doc missing something ?

Type Errors due to H3 version missmatch

H3 version: 1.8.2
h3-zod's H3 version: 1.8.1

import { useSafeValidatedQuery } from "h3-zod";
import { z } from "zod";

export default defineEventHandler((event) => {
  const querySchema = z.object({ s: z.string() });
  const query = await useSafeValidatedQuery(event, querySchema);
                                              ^ Here

  if (!query.success)
    throw createError({ status: 400, message: "search_bad_query" });

  return query.data.s;
});

Validating nested ZodEffects throws TS error

First of all big thanks for actively maintaining this package.

Zod schema can use multiple refine validations, which produces type with nested ZodEffects.

Passing this schema to h3-zod gives TS error.

Reproduction:
https://codesandbox.io/s/ecstatic-surf-0u8wo2?file=/server/api/submit.post.ts

Tried this with [email protected], which handled this case OK, but further improvements were made down the line, changing the behaviour.

EDIT: Also the resulting body type is unknown,

Validate cookie

Hi Thanks for you great job

It can be interesting to have a dedicated method to parse cookie content.

With the usage of getCookie() method if data is stored as json

zodSchema.parse(JSON.stringify(getCookie(event, 'cookie_name')))

Validate ZodEffects schema

First of all thanks for this very useful library.

The issue I'd like to report deals with using schema with type ZodEffects. Such schema can be produced by using z.refine on z.object as shown in example below.
This produces a TS error. See https://codesandbox.io/s/morning-bash-oi6h35?file=/server/api/submit.post.ts

import { useValidatedBody, z } from "h3-zod";
import { defineEventHandler } from "h3";
import dayjs from "dayjs";

const bodySchema = z
  .object({
    fromDate: z.string().optional(),
    toDate: z.string().optional()
  })
  .refine(
    (schema) =>
      !!schema.fromDate && !!schema.toDate
        ? dayjs(schema.fromDate).isBefore(schema.toDate)
        : true,
    "'fromDate' has to be before 'toDate'"
  );

export default defineEventHandler(async (event) => {
  const body = await useValidatedBody(event, bodySchema);
  return;
});

The solution would be to extend TQuery type like so:

type TQuery<U extends UnknownKeysParam = any> =
  | z.ZodObject<any, U>
  | z.ZodUnion<[TQuery<U>, ...TQuery<U>[]]>
  | z.ZodIntersection<TQuery<U>, TQuery<U>>
  | z.ZodDiscriminatedUnion<string, z.Primitive, z.ZodObject<any, U>>
  | z.ZodEffects<z.ZodTypeAny>; // <-- add this line

Would you like me to open a PR?

Missing type SafeParseError when there is error

zod: 3.21.4
h3-zod: 0.4.0

Property 'error' does not exist on type 'SafeParseReturnType<ZodObject<{ email: ZodString; password: ZodString; firstName: ZodOptional; lastName: ZodOptional; name: ZodOptional<...>; tags: ZodArray<...>; }, UnknownKeysParam, ZodTypeAny, { ...; }, { ...; }>, { ...; }>'.   Property 'error' does not exist on type 'SafeParseSuccess<{ email?: string; password?: string; firstName?: string; lastName?: string; name?: string; tags?: string[]; }>'.

When doing a wrong body request, the router below return an status and error property, but typescript give us an error

export default defineEventHandler(async (event) => {
    const body = await zh.useSafeValidatedBody(event, {
        email: z.string().email(),
        password: z.string().min(8),
        firstName: z.string().optional(),
        lastName: z.string().optional(),
        name: z.string().optional(),
        tags: z.array(z.string()).min(1)
    });

    // typescript warning here
    console.log('body', body.error);

    return body;

});

what advantage does this package have over using zod directly?

sorry for this is not an issue but a question, but I am new to zod and I've been trying to use formkit with the zod plugin in nuxt and wanted to use zod in the backend for validation. but I felt like using zod directly does the job.

so I was wondering what advantages does this package offer to my codebase and is it worth adding another dependency to my project?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.