From 4cf61fc48f1415cf70b509c2de2f3740b1706708 Mon Sep 17 00:00:00 2001 From: sualko Date: Mon, 24 Jan 2022 10:26:41 +0100 Subject: [PATCH 1/2] add config to pass validation options --- src/index.ts | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/index.ts b/src/index.ts index 54f9017..3384d48 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,10 +19,18 @@ 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(); +export default function withJoi(userConfig: Configuration = {}): ValidationFunction { + const config = { ...defaultConfig, ...userConfig }; + const onValidationError: OnValidationError = config.onValidationError; return (schemas, handler) => { return (req: NextApiRequest, res: NextApiResponse, next?: NextHandler) => { @@ -35,7 +43,7 @@ export default function withJoi(config?: Configuration): ValidationFunction { const schema = schemas[field]; - return schema && schema.required().validate(req[field]).error; + return schema && schema.required().validate(req[field], config.validationOptions).error; }, undefined); if (undefined !== validationError) { From c134678ea713c850f2eaac71034e3fa5b259c2fd Mon Sep 17 00:00:00 2001 From: sualko Date: Mon, 24 Jan 2022 10:56:55 +0100 Subject: [PATCH 2/2] convert fields according to schema --- src/index.ts | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/src/index.ts b/src/index.ts index 3384d48..8b5581e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -28,26 +28,39 @@ const defaultConfig = { onValidationError: ((_, res) => res.status(400).end()) as OnValidationError, } +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); - const schema = schemas[field]; + if (result.error) { + throw result.error; + } - return schema && schema.required().validate(req[field], config.validationOptions).error; - }, undefined); + return [field, result.value] as [keyof ValidableRequestFields, any]; + }); + + 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) {