diff --git a/src/index.ts b/src/index.ts index 54f9017..8b5581e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,4 @@ -import { Schema, ValidationError } from "joi"; +import { Schema, ValidationError, ValidationOptions } from "joi"; import { NextApiHandler, NextApiRequest, NextApiResponse } from "next"; import { NextHandler, RequestHandler } from "next-connect"; @@ -19,27 +19,48 @@ export type OnValidationError = ( error: ValidationError ) => void | Promise; -export type Configuration = { onValidationError: OnValidationError }; +export type Configuration = { + onValidationError?: OnValidationError, + validationOptions?: ValidationOptions, +}; + +const defaultConfig = { + onValidationError: ((_, res) => res.status(400).end()) as OnValidationError, +} -export default function withJoi(config?: Configuration): ValidationFunction { - const onValidationError: OnValidationError = config ? config.onValidationError : (_, res) => res.status(400).end(); +const supportedFields: (keyof ValidableRequestFields)[] = ["body", "headers", "query"]; + +export default function withJoi(userConfig: Configuration = {}): ValidationFunction { + const config = { ...defaultConfig, ...userConfig }; + const onValidationError: OnValidationError = config.onValidationError; return (schemas, handler) => { + const keys = Object.keys(schemas) as (keyof ValidableRequestFields)[]; + const fieldsToValidate = keys.filter(field => supportedFields.includes(field)); + return (req: NextApiRequest, res: NextApiResponse, next?: NextHandler) => { - const fields: (keyof ValidableRequestFields)[] = ["body", "headers", "query"]; + try { + const values = fieldsToValidate.map((field) => { + const schema = schemas[field] as Schema; - const validationError = fields.reduce((error, field) => { - if (undefined !== error) { - return error; - } + const result = schema.required().validate(req[field], config.validationOptions); + + if (result.error) { + throw result.error; + } - const schema = schemas[field]; + return [field, result.value] as [keyof ValidableRequestFields, any]; + }); - return schema && schema.required().validate(req[field]).error; - }, undefined); + if (config.validationOptions?.convert !== false) { + values.forEach(([field, value]) => req[field] = value); + } + } catch (error) { + if (error instanceof ValidationError) { + return onValidationError(req, res, error); + } - if (undefined !== validationError) { - return onValidationError(req, res, validationError); + throw error; } if (undefined !== next) {