Created
January 5, 2024 00:47
-
-
Save revmischa/3859f2b2ead79fae8b2b15a97b398378 to your computer and use it in GitHub Desktop.
Zod + middy + AWS lambda API Gateway
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import middy, { MiddlewareObj } from '@middy/core' | |
import httpErrorHandler from '@middy/http-error-handler' | |
import httpHeaderNormalizer from '@middy/http-header-normalizer' | |
import httpJsonBodyParser from '@middy/http-json-body-parser' | |
import { APIGatewayProxyEventV2, APIGatewayProxyStructuredResultV2, Handler } from 'aws-lambda' | |
import { zodValidator } from 'middy-zod-validator' | |
import { ZodSchema, z, infer as ZInfer } from 'zod' | |
import { isHttpError } from 'http-errors' | |
type ApiHandler = ( | |
event: import('aws-lambda').APIGatewayProxyEventV2, | |
context: import('aws-lambda').Context, | |
) => Promise<APIGatewayProxyStructuredResultV2> | |
export const restMiddleware = (handler: ApiHandler) => | |
middy(handler).use(httpHeaderNormalizer()).use(httpErrorHandler()) | |
export const restZodMiddleware = <T extends ZodSchema>( | |
schema: T, | |
// event.body JSON is parsed as T | |
handler: Handler<Omit<APIGatewayProxyEventV2, 'body'> & { body: ZInfer<T> }, APIGatewayProxyStructuredResultV2>, | |
) => | |
restMiddleware( | |
handler | |
) | |
.use(httpJsonBodyParser()) | |
.use(errorStringifier) | |
.use(zodBodyValidator(schema)) | |
.use(httpErrorHandler()) | |
export const bodySchema = (schema: ZodSchema) => | |
z.object({ | |
body: schema, | |
}) | |
export const zodBodyValidator = (schema: ZodSchema) => zodValidator(bodySchema(schema)) | |
/** | |
* If the error is not a string, stringify it. | |
* This fixes zod errors not being returned as JSON strings. | |
*/ | |
export const errorStringifier: MiddlewareObj = { | |
onError: async (handler) => { | |
if (isHttpError(handler.error) && handler.error && typeof handler.error !== 'string') { | |
handler.response = { | |
statusCode: handler.error.statusCode, | |
body: JSON.stringify(handler.error), | |
} | |
} | |
}, | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment