dbartholomae / lambda-middleware

A collection of middleware for AWS lambda functions.
https://dbartholomae.github.io/lambda-middleware/
MIT License
151 stars 18 forks source link

Add io-ts validator middleware #55

Closed matt-jenner closed 2 years ago

matt-jenner commented 3 years ago

Is your feature request related to a problem? Please describe. I spend a lot of time writing and rewriting deserialization and type validation code in my lambdas. I've just started a project where we have a large number of endpoints (roughly 40 of them) and I really didn't fancy rewriting this code again and again.

As a result, I've written two middlewares compatible with your lambda-middleware library and I'd like to see if you'd like them as part of the main package before I publish them as separate packages, this feature request is for the io-ts validator.

Would you be willing to help with a PR?

Describe the solution you'd like

The io-ts validator is loosely based on ideas from the class validator middleware, I decided to build it as I wanted to type validate a payload without having to add it a class and I didn't want to have to enable experimental typescript features.

It takes an io-ts codec and a type alias (to report errors in a human-readable fashion) and returns the middleware that will validate that specific type of object.

It replaces the body of the incoming event for the wrapped handler with the typed object (much like the JSON Deserializer middleware).

Describe alternatives you've considered

Additional implementation notes

Why io-ts? (or rather.... why not Zod or Class Validator?)

Class validator requires classes, and I've already written validators in io-ts. Why io-ts vs zod? I have experience with both, but zod explicitly does NOT map the validated object meaning that you have to write a separate mapper and it clutters things up a bit more than you might otherwise need. Passing io-ts codecs in seemed like a nice clean solution (despite all the annoying functional programming shenanigans in using io-ts).

Dependencies on other Middlewares (ordering)

Currently, in my app's implementation of this middleware, it expects the body to already be an object (as I control the middleware order and I didn't need to deserialize as part of this middleware) - if this is ok, I can make this an expectation of using the middleware, or I could add deserialization to make it a bit more generic but it would mean we have some repeated functionality with the JSON Deserializer middleware.

Changing Properties vs Adding New Properties to the APIGatewayProxyEvent

Currently I'm stripping the body and replacing it with the typed object, this does mean it could have negative effects on a downstream middleware, but I think it is cleaner for my code and reflects the object being transformed into something my handler will want to work with.

If you don't want that, I could add another distinct property in addition to the original body but seeing as you used a similar method in the class-validator middleware, I hope you don't have any issues with this? :)

Error Handling

I like the idea of "typed" errors, as such my middleware will probably throw a distinct ValidationError which will contain validation information that can be returned to the user in a BadRequest output.

I extend Error and add any relevant properties to the extended error class (so if it's logged out I would get useful semantic logging).

You can then use these with http-error-handler middleware (switching on error name) or you could use an app-specific error handler middleware at the top level (as I'm doing in my code at-present).

dbartholomae commented 3 years ago

Thanks! Happy to help with the PR, feel free to open it early.

github-actions[bot] commented 3 years ago

This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days.

matt-jenner commented 3 years ago

This issue not stale - merely delayed a bit due to work, unfortunately I've not had much time for personal coding recently but I'm still slowly making progress and it is still very much on my radar, once we can merge #57 I can start to work on this, thanks.

dbartholomae commented 3 years ago

Thanks! I'm on vacation and will only be able to check in August, unfortunately.

github-actions[bot] commented 2 years ago

This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days.