Skip to content

Commit

Permalink
feat: add param validator
Browse files Browse the repository at this point in the history
  • Loading branch information
wobsoriano committed Nov 12, 2022
1 parent 12659ea commit dfbdfb6
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 18 deletions.
15 changes: 14 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,12 @@ npm install h3-zod
Helpers that don't throw when parsing fails:

```ts
import { useSafeValidatedBody, useSafeValidatedQuery, z } from 'h3-zod'
import {
useSafeValidatedBody,
useSafeValidatedParams,
useSafeValidatedQuery,
z
} from 'h3-zod'

export default defineEventHandler(async (event) => {
const query = useSafeValidatedQuery(event, z.object({
Expand All @@ -26,6 +31,10 @@ export default defineEventHandler(async (event) => {
optional: z.string().optional(),
required: z.boolean()
}))

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

Expand All @@ -43,6 +52,10 @@ export default defineEventHandler(async (event) => {
optional: z.string().optional(),
required: z.boolean()
}))

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

Expand Down
59 changes: 44 additions & 15 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { H3Event } from 'h3'
import { createError, getQuery, readBody } from 'h3'
import { createError, getQuery, getRouterParams, readBody } from 'h3'
import { z } from 'zod'

type UnknownKeysParam = 'passthrough' | 'strict' | 'strip'
Expand All @@ -24,6 +24,14 @@ type ParsedData<T extends Schema | z.ZodRawShape> = T extends Schema
const DEFAULT_ERROR_MESSAGE = 'Bad Request'
const DEFAULT_ERROR_STATUS = 400

function createBadRequest(error: any) {
return createError({
statusCode: DEFAULT_ERROR_STATUS,
statusText: DEFAULT_ERROR_MESSAGE,
data: JSON.stringify(error),
})
}

/**
* Parse and validate request query from event handler. Throws an error if validation fails.
* @param event - A H3 event object.
Expand All @@ -39,13 +47,7 @@ export function useValidatedQuery<T extends Schema | z.ZodRawShape>(
return finalSchema.parse(query)
}
catch (error) {
throw createError({
statusCode: DEFAULT_ERROR_STATUS,
statusText: DEFAULT_ERROR_MESSAGE,
data: JSON.stringify({
errors: error as any,
}),
})
throw createBadRequest(error)
}
}

Expand Down Expand Up @@ -84,13 +86,7 @@ export async function useValidatedBody<T extends Schema | z.ZodRawShape>(
return finalSchema.parse(body)
}
catch (error) {
throw createError({
statusCode: DEFAULT_ERROR_STATUS,
statusText: DEFAULT_ERROR_MESSAGE,
data: JSON.stringify({
errors: error as any,
}),
})
throw createBadRequest(error)
}
}

Expand All @@ -108,6 +104,39 @@ export async function useSafeValidatedBody<T extends Schema | z.ZodRawShape>(
return finalSchema.safeParse(body) as SafeParsedData<T>
}

/**
* Parse and validate params from event handler. Throws an error if validation fails.
* @param event - A H3 event object.
* @param schema - A Zod object shape or object schema to validate.
*/
export function useValidatedParams<T extends Schema | z.ZodRawShape>(
event: H3Event,
schema: T,
): Promise<ParsedData<T>> {
try {
const params = getRouterParams(event)
const finalSchema = schema instanceof z.ZodType ? schema : z.object(schema)
return finalSchema.parse(params)
}
catch (error) {
throw createBadRequest(error)
}
}

/**
* Parse and validate params from event handler. Doesn't throw if validation fails.
* @param event - A H3 event object.
* @param schema - A Zod object shape or object schema to validate.
*/
export function useSafeValidatedParams<T extends Schema | z.ZodRawShape>(
event: H3Event,
schema: T,
): SafeParsedData<T> {
const params = getRouterParams(event)
const finalSchema = schema instanceof z.ZodType ? schema : z.object(schema)
return finalSchema.safeParse(params) as SafeParsedData<T>
}

export {
z,
}
2 changes: 1 addition & 1 deletion test/__snapshots__/body.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ exports[`useValidatedBody > returns 200 OK if body matches validation schema 1`]

exports[`useValidatedBody > throws 400 Bad Request if body does not match validation schema 1`] = `
{
"data": "{\\"errors\\":{\\"issues\\":[{\\"code\\":\\"invalid_type\\",\\"expected\\":\\"boolean\\",\\"received\\":\\"undefined\\",\\"path\\":[\\"required\\"],\\"message\\":\\"Required\\"}],\\"name\\":\\"ZodError\\"}}",
"data": "{\\"issues\\":[{\\"code\\":\\"invalid_type\\",\\"expected\\":\\"boolean\\",\\"received\\":\\"undefined\\",\\"path\\":[\\"required\\"],\\"message\\":\\"Required\\"}],\\"name\\":\\"ZodError\\"}",
"stack": [],
"statusCode": 400,
"statusMessage": "Bad Request",
Expand Down
2 changes: 1 addition & 1 deletion test/__snapshots__/query.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ exports[`useValidatedQuery > returns 200 OK if query matches validation schema 1

exports[`useValidatedQuery > throws 400 Bad Request if query does not match validation schema 1`] = `
{
"data": "{\\"errors\\":{\\"issues\\":[{\\"code\\":\\"invalid_type\\",\\"expected\\":\\"string\\",\\"received\\":\\"undefined\\",\\"path\\":[\\"required\\"],\\"message\\":\\"Required\\"}],\\"name\\":\\"ZodError\\"}}",
"data": "{\\"issues\\":[{\\"code\\":\\"invalid_type\\",\\"expected\\":\\"string\\",\\"received\\":\\"undefined\\",\\"path\\":[\\"required\\"],\\"message\\":\\"Required\\"}],\\"name\\":\\"ZodError\\"}",
"stack": [],
"statusCode": 400,
"statusMessage": "Bad Request",
Expand Down

0 comments on commit dfbdfb6

Please sign in to comment.