Micro AWS Lambda

Intro

For Lambda Proxy / Http API mode

Written in Typescript

Zero runtime dependencies

Tiny: 7KB after minified

Rapid middlewares simple reasoning, just running one by one early exit with just throw httpError() or anything pass values among middlewares

Return response an object, it will be converted to a Lambda compatible response a customizable httpResponse() / success() (200) a customizable httpError() / badRequest() (400) / internalError() (500) or string, number, boolean

Easy debug: Adding debug info to response object console.log event / context



Why do you build this lib

AWS Lambda is making it a flash to creating an API endpoint. But that's just the infrastructure part. It doesn't mean your business logic can be simplified.

I need a middleware setup to decouple my business logic without installing a lib that has many dependencies and result in a bigger bundle size as well.

I want to deal with a simple interface, where the order is just one by one. I don't want to deal with a mental model where a middleware will be invoked twice for both stages, and handle both the before and after stage in one function.

What problems does it solve

Middleware is for decoupling logic. I learned the value of beforeHooks and afterHooks after adopting Feathers.JS. Which has a beautiful concept of 3 layers for every endpoint, and I found myself start the declarative programming for the backend. No more code for the repeating work. In micro-aws-lambda 's context, it is just an array of Middleware .

Let's say a simple return-a-user endpoint, what does it look like when you are using micro-aws-lambda

const handler = lambdas ( [ validateRequestBody ( GetUserSchema ) , isStillEmployed , verifyPaymentStatus , justReturnUserObjectDirectlyFromDB , removeFieldsFromResponse ( ' password ' , ' address ' ) , combineUserNames , transformResponseToClientSideStructure , ] ) ;

Ideally, you can just compose your future lambda without writing any code except for an integration test. The logic will be declarative. Every middleware here can be fully tested and ready to reuse.

Usage

1. Install

npm install micro-aws-lambda

2. Quick start

import { lambdas } from ' micro-aws-lambda ' ; ;

3. The type of the middleware

type Middleware < PassDownObjType = any , ReturnValueType = any > = ( { event , context , passDownObj , response , } : { ; ; ; ; } ) => ReturnValueType ;

4. Two minutes master

How to control the flow? return WON'T stop the execution throw will STOP the execution otherwise, the array of Middleware will just be executed one by one

What can you return a httpResponse() or a success() (just a httpResponse() with status code set to 200, you can still change it) or an plain object / string / number (which will be auto-wrapped with success() in the end) Any value return ed will be passed to the next middleware as the response parameter

What can you throw an httpError() an badRequest() an internalError() or anything else

How to check what will be returned as the Http response check the response from the parameter

How to change the response you just return a new one in your current middleware

How to pass something down the chain, use passDownObj from the parameter attach your value to it: passDownObj.myValue = 123 , myValue could be any name

Do I have to return something in the middleware No. For example, a validation middleware can only react to the wrong data without returning anything like if (wrong) {}

What is the rule of thumb when determine what will be returned is the end? the last returned value always wins. it's simply because you can replace the current response by return ing a new one. Which means: if every middleware is returning, the last one wins, if middleware A returns ResponseA, and middleware B is not return anything, ResponseA will be returned (Assume the order is A,B).



5. About the built-in responses

There are 2 types of response:

Built in

httpError() for throw

for httpResponse() for return

Plain JS type

return a plain object | string | number === (200) response

a plain | | === (200) response throw a plain object | string | number === (400) response

a plain | | === (400) response custom status code by adding statusCode property

The built-in one has some shortcuts to use.

All parameters are customizable.

import { httpError , httpResponse } from ' micro-aws-lambda ' ; ; ;

The commons headers are:

'Access-Control-Allow-Origin': '*',

'Access-Control-Allow-Credentials': true,

'Content-Type': 'application/json',

Supports multiValueHeaders and isBase64Encoded in case you need them.

5.1. Shortcuts

Compare to the above methods, the only difference is the shortcuts just sets the status code, you can still modify them if you want.

httpError : badRequest() : 400 internalRequest() : 500

: httpResponse : success() : 200

:

6. Config

6.1 addTraceInfoToResponse

It will add debug info into the response object

{ debug : { endpoint : " " , requestBody : " " , requestMethod : " " , country : " " , lambdaRequestId : " " , logStreamName : " " , logGroupName : " " , apiGatewayId : " " } }

6.2 logRequestInfo

It will console.log :

event

context

Aws-Api-Gateway-Request-Id

Identity-Source-Ip

7. Examples

7.1 Validation

In the following case, if the request name is 'albert', only validateRequest will be called.

import { badRequest , Middleware } from ' micro-aws-lambda ' ; ;

Or if you like me, you can write a simple validating middleware with the yup schema, you can then reuse from the client side.

import { Schema } from ' yup ' ; import { lambdas , Middleware , badRequest } from ' micro-aws-lambda ' ; ; ;

7.2 processing Response

import { badRequest } from ' micro-aws-lambda ' ; ; ;

Credits