UNPKG

burger-api

Version:

<p align="center"> <img src="https://github.com/user-attachments/assets/0d9b376e-1d89-479a-aa7f-e7ee3c6b2342" alt="BurgerAPI logo"/> </p>

111 lines (110 loc) 4.32 kB
export function createValidationMiddleware(schema) { return async (req) => { // If the request has been validated, continue. if (req.validated) { return undefined; // Proceed to the next middleware or handler } // Determine the HTTP method (in lowercase) to match the schema. const method = req.method.toLowerCase(); // Get the schema for the current method. const methodSchema = schema[method]; // If there's no schema for this method, continue. if (!methodSchema) { return undefined; // Proceed to the next middleware or handler } // Get the schemas for the current method. const paramsSchema = methodSchema.params; const querySchema = methodSchema.query; const bodySchema = methodSchema.body; /** * Array to collect validation errors. * Each error contains a `field` indicating the part of the request that failed validation, * and an `error` providing details about the validation failure. */ const errors = new Array(3); // Pre-allocate for params, query, body let errorCount = 0; /** * Object to store validated request data. This will be attached to the * request object if validation is successful. The object will contain * validated data for the following fields: * * - `params`: Validated URL parameters. * - `query`: Validated query parameters. * - `body`: Validated request body (if JSON). */ const validated = {}; // Validate URL parameters (if available and schema provided). if (paramsSchema && req.params) { try { const result = paramsSchema.safeParse(req.params); if (result.success) { validated.params = result.data; } else { errors[errorCount++] = { field: 'params', error: result.error, }; } } catch (e) { errors[errorCount++] = { field: 'params', error: e.errors }; } } // Validate query parameters. const url = new URL(req.url); const queryParams = Object.fromEntries(url.searchParams.entries()); if (querySchema) { try { const result = querySchema.safeParse(queryParams); if (result.success) { validated.query = result.data; } else { errors[errorCount++] = { field: 'query', error: result.error, }; } } catch (e) { errors[errorCount++] = { field: 'query', error: e.errors }; } } // Validate request body. if (bodySchema && req.headers.get('Content-Type')?.includes('application/json')) { try { // Attempt to parse the JSON body. const bodyData = await req.json(); const result = bodySchema.safeParse(bodyData); if (result.success) { // Set the validated body. validated.body = result.data; // Set the json method to return the validated body. req.json = () => result.data; } else { errors[errorCount++] = { field: 'body', error: result.error, }; } } catch (e) { errors[errorCount++] = { field: 'body', error: e.errors || e.message, }; } } if (errorCount > 0) { // If validation fails, return a 400 response with error details. return Response.json({ errors }, { status: 400 }); } // Attach validated data to the request. req.validated = validated; // Continue to the next middleware or handler. return undefined; // Proceed }; }