Architecture
The main purpose of this library is to allow the developer to add support for any cloud and as many event sources as he wants, without having to create an issue to request the feature or copy the library code because the library doesn't expose good APIs for you to extend its functionality
So I refactored @vendia/serverless-express with five extension layers: Framework, Network, Handler, Resolver and Adapter.
Framework
The FrameworkContract is responsible for forwarding to IncomingMessage and ServerResponse for your application instance.
With this abstraction you can implement any framework you want, they just need to accept both parameters and call end in ServerResponse, so the library knows when to continue and return the response.
Network
The NetworkContract is responsible for creating the IncomingMessage and ServerResponse objects sent to your framework, then extracting the collected body and headers after the framework finishes.
The default implementation is DEFAULT_NETWORK, a DefaultNetwork instance that uses ServerlessRequest and ServerlessResponse. Most users should keep it. Use setNetwork only when you need to tune DefaultNetwork, use custom Node.js request/response classes, or customize response body/header extraction. Handlers that receive platform-owned HTTP objects can use only the request part of the contract; Huawei keeps the real Node.js HTTP server request and response objects.
Handler
The HandlerContract is responsible to get the input from the serverless and then manage to call each layer of abstraction to return a response. Built-in adapter-driven handlers resolve an adapter, ask the network layer to create the framework request/response objects, forward them to the framework, and pass the extracted response data back to the adapter.
With this abstraction, you can implement different ways to receive input from your serverless environment.
They usually have the same structure, but if you need to deal with a very different cloud, you can use this abstraction to add support for that cloud.
Handler is a good choice for implementing (monsters) ways to receive input.
For example, we can create an http server as its handler to test our serverless code without having to launch the framework. Because? I don't know, but you can.
Resolver
The ResolverContract is responsible for waiting for the framework to handle the
request and then returning the response to the cloud. Using AWS for example, you have three ways to wait for the
response: returning a promise, calling the callback, and using in-context methods, each option has its own benefits,
but generally the promise option will be the better because any good cloud provider will support promises.
Adapter
Finally, the masterpiece of this library, the AdapterContract is responsible for handling the received event, transforming the request in a way that your application can understand and then transforming the response in a way your cloud can understand.
Well, with these five contracts, you'll be able to add support to any cloud that exists (no more excuses not to use cloud X with NodeJS).