koa-zod-router
Advanced tools
Comparing version 1.2.0-beta.0 to 1.2.0
# koa-zod-router | ||
## 1.2.0 | ||
### Minor Changes | ||
- 12e0a9c: Add continueOnError flag for custom validation error handling support | ||
## 1.1.4 | ||
@@ -4,0 +10,0 @@ |
@@ -9,2 +9,14 @@ import KoaRouter, { LayerOptions, RouterOptions } from '@koa/router'; | ||
type Method = 'acl' | 'bind' | 'checkout' | 'connect' | 'copy' | 'delete' | 'get' | 'head' | 'link' | 'lock' | 'm-search' | 'merge' | 'mkactivity' | 'mkcalendar' | 'mkcol' | 'move' | 'notify' | 'options' | 'patch' | 'post' | 'propfind' | 'proppatch' | 'purge' | 'put' | 'rebind' | 'report' | 'search' | 'source' | 'subscribe' | 'trace' | 'unbind' | 'unlink' | 'unlock' | 'unsubscribe'; | ||
interface ZodRouterInvalid { | ||
body?: ZodError[]; | ||
headers?: ZodError[]; | ||
params?: ZodError[]; | ||
query?: ZodError[]; | ||
files?: ZodError[]; | ||
error?: boolean; | ||
} | ||
type ZodValidationError<T> = { | ||
requestParameter: 'body' | 'headers' | 'params' | 'query' | 'files'; | ||
error: ZodError<T>[]; | ||
}; | ||
interface ZodContext<Headers, Params, Query, Body, Files> { | ||
@@ -17,4 +29,4 @@ request: { | ||
files: Files; | ||
validationErrors?: ZodError[]; | ||
}; | ||
invalid: ZodRouterInvalid; | ||
} | ||
@@ -240,2 +252,2 @@ type ValidationOptions<Headers, Params, Query, Body, Files, Response> = { | ||
export { Method, RegisterSpec, RouteSpec, RouterMethod, RouterMethods, RouterOpts, Spec, UseSpec, ValidationOptions, ZodContext, ZodMiddleware, ZodRouter, createRouteSpec, createUseSpec, zodRouter as default, routerSpecFactory, zFile, zodRouter }; | ||
export { Method, RegisterSpec, RouteSpec, RouterMethod, RouterMethods, RouterOpts, Spec, UseSpec, ValidationOptions, ZodContext, ZodMiddleware, ZodRouter, ZodRouterInvalid, ZodValidationError, createRouteSpec, createUseSpec, zodRouter as default, routerSpecFactory, zFile, zodRouter }; |
@@ -65,3 +65,3 @@ "use strict"; | ||
}; | ||
async function noopMiddleware(ctx, next) { | ||
async function noopMiddleware(_ctx, next) { | ||
await next(); | ||
@@ -122,2 +122,8 @@ } | ||
}; | ||
var assertZodValidationError = (val) => { | ||
if (val?.error instanceof import_zod.ZodError) { | ||
return true; | ||
} | ||
return false; | ||
}; | ||
var createRouteSpec = (spec) => { | ||
@@ -185,3 +191,3 @@ return spec; | ||
}; | ||
var validate = async (data, schema, name) => { | ||
var validate = async (data, schema, requestParameter) => { | ||
if (!schema) { | ||
@@ -192,4 +198,6 @@ return void 0; | ||
if (!parsed.success) { | ||
parsed.error.name = name; | ||
return parsed.error; | ||
return { | ||
requestParameter, | ||
error: parsed.error | ||
}; | ||
} | ||
@@ -218,18 +226,17 @@ return parsed.data; | ||
const inputErrors = validated.reduce((acc, curr) => { | ||
if (curr instanceof import_zod2.ZodError) { | ||
acc.push(curr); | ||
if (assertZodValidationError(curr)) { | ||
acc[curr.requestParameter] = curr.error; | ||
} | ||
return acc; | ||
}, []); | ||
if (inputErrors.length) { | ||
const errorObject = inputErrors.reduce((acc, curr) => { | ||
acc[curr.name] = curr.issues; | ||
return acc; | ||
}, {}); | ||
}, {}); | ||
if (inputErrors.body || inputErrors.files || inputErrors.headers || inputErrors.params || inputErrors.query) { | ||
if (opts?.continueOnError) { | ||
ctx.request.validationErrors = errorObject; | ||
inputErrors.error = true; | ||
ctx.invalid = inputErrors; | ||
await next(); | ||
return; | ||
} else if (opts?.exposeRequestErrors) { | ||
ctx.response.status = 400; | ||
ctx.type = "json"; | ||
ctx.body = { error: errorObject }; | ||
ctx.body = { error: inputErrors }; | ||
ctx.app.emit("error", new ValidationError({ inputErrors }), ctx); | ||
@@ -241,2 +248,3 @@ return; | ||
} | ||
ctx.invalid = { error: false }; | ||
const [headers, params, query, body, files] = validated; | ||
@@ -253,7 +261,7 @@ addParsedProps(ctx.request.headers, headers); | ||
} | ||
if (output instanceof import_zod2.ZodError) { | ||
if (output.error instanceof import_zod2.ZodError) { | ||
if (opts?.exposeResponseErrors) { | ||
ctx.status = 500; | ||
ctx.type = "json"; | ||
ctx.body = { error: { response: output.issues } }; | ||
ctx.body = { error: { response: output.error } }; | ||
ctx.app.emit("error", new ValidationError({ output }), ctx); | ||
@@ -265,3 +273,2 @@ return; | ||
ctx.body = output; | ||
ctx.response.body = output; | ||
} | ||
@@ -268,0 +275,0 @@ }; |
{ | ||
"name": "koa-zod-router", | ||
"version": "1.2.0-beta.0", | ||
"version": "1.2.0", | ||
"description": "", | ||
@@ -48,6 +48,6 @@ "main": "dist/index.js", | ||
"@types/koa": "^2.13.6", | ||
"@types/node": "^18.15.11", | ||
"@types/node": "^18.15.12", | ||
"@types/supertest": "^2.0.12", | ||
"@typescript-eslint/eslint-plugin": "^5.58.0", | ||
"@typescript-eslint/parser": "^5.58.0", | ||
"@typescript-eslint/eslint-plugin": "^5.59.0", | ||
"@typescript-eslint/parser": "^5.59.0", | ||
"coveralls": "^3.1.1", | ||
@@ -67,3 +67,3 @@ "eslint": "^8.38.0", | ||
"tsup": "^6.7.0", | ||
"turbo": "^1.9.1", | ||
"turbo": "^1.9.3", | ||
"typescript": "5.0.4" | ||
@@ -73,3 +73,3 @@ }, | ||
"koa": ">=2.14.1 <3.x", | ||
"zod": ">=3.20.2 <4.x" | ||
"zod": ">=3.21.4 <4.x" | ||
}, | ||
@@ -76,0 +76,0 @@ "keywords": [ |
@@ -21,2 +21,3 @@ # ⚡ koa-zod-router ⚡ | ||
- Wraps [@koa/router][], providing the same API but with typesafety and validation. | ||
- Custom validation error handling support | ||
- CJS and ESM support | ||
@@ -268,2 +269,31 @@ | ||
### Custom Validation Error Handling | ||
By enabling `continueOnError` you can bypass the default error handling done by the router's validation middleware and handle the errors the way you see fit. | ||
Simply add a middleware to detect if `ctx.invalid.error` is set to `true`, and then retrieve any ZodErrors from the `ctx.invalid` object as shown in the following example: | ||
```js | ||
import zodRouter from 'koa-zod-router'; | ||
import { z } from 'zod'; | ||
const router = zodRouter({ continueOnError: true }); | ||
//... create a custom error handling middleware | ||
router.use(async (ctx, next) => { | ||
// check if an error was thrown | ||
if (ctx.invalid?.error) { | ||
// deconstruct all of the ZodErrors from ctx.invalid | ||
const { body, headers, query, params, files } = ctx.invalid; | ||
//... handle ZodErrors | ||
} else { | ||
await next(); | ||
} | ||
}); | ||
//... your routes | ||
``` | ||
## API Reference | ||
@@ -270,0 +300,0 @@ |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
54370
1047
1
311