A 7KB and 0 dependencies AWS Lambda library which supports middleware and easy debug.
MIT License
throw
or return
anythinghttpResponse()
/ success()
(200)httpError()
/ badRequest()
(400) / internalError()
(500)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.
before
and after
stage in one function.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.
npm install micro-aws-lambda
import { lambdas } from 'micro-aws-lambda';
const handler = lambdas([() => ({ message: 'it works' })]);
// call the API, you will get json response: { message: "it works" }
import { lambdas, Middleware, HttpResponse } from 'micro-aws-lambda';
interface Shared {
user: { id: string; group: string };
}
interface Response {
isPassing: boolean;
}
const extractUserFromEvent: Middleware<Shared, Response> = async ({
event,
shared,
}) => {
const user = JSON.parse(event.body);
if (!user) {
throw HttpResponse.badRequest({ isPassing: false });
}
shared.user = user;
};
const parseUserData: Middleware<Shared, Response> = ({ shared }) => {
if (shared.user.id === 'bad-user-id') {
throw HttpResponse.badRequest({ isPassing: false });
}
return HttpResponse.success({ isPassing: true });
};
export const handler = lambdas([extractUserFromEvent, parseUserData]);
And later on, if there are any lambda handler needs that extractUserFromEvent
, you just reuse that piece anywhere you want!
the default
Middleware
is forAPIGatewayProxyHandlerV2
from@types/aws-lambda
. If you are using the Lambda Proxy mode, please importMiddlewareLegacy
, otherwise,
How to control the flow?
return
anything that is not null
or undefined
will STOP the executionthrow
will STOP the executionreturn
/ return null
/ return undefined
will NOT stop the execution, unless it's the last middlewareMiddleware
will just be executed one by onelambdas([m1, m2])
, if m1
is returning something, it will be used as the http response and m2 will not be executed.What can you return
HttpResponse.response()
HttpResponse.success()
(just a HttpResponse.response()
with status code set to 200, you can still change it)HttpResponse.success()
in the end)What can you throw
HttpResponse.error()
HttpResponse.badRequest()
HttpResponse.unauthorized()
HttpResponse.forbidden()
HttpResponse.notFound()
HttpResponse.methodNotAllowed()
HttpResponse.notAcceptable()
HttpResponse.conflict()
HttpResponse.internalError()
HttpResponse.notImplemented()
HttpResponse.badGateway()
HttpResponse.serviceUnavailable()
HttpResponse.gatewayTimeout()
HttpResponse.networkAuthenticationRequire()
Hover over the function will get a tooltip of the status code for this helper, also, you can pass a 2nd parameter to change the statusCode or headers as well
How to pass something down the chain,
shared
from the parametershared.myValue = 123
, myValue
could be any nameDo I have to return something in the middleware
if (wrong) {throw badRequest()}
return
a plain object
| string
| number
=== (200) responsethrow
a plain object
| string
| number
=== (400) responsestatusCode
propertyimport {HttpResponse} from 'micro-aws-lambda'
, then HttpResponse.success({body:{message:'wow'}})
It will add debug info into the response object
{
debug: {
endpoint: "",
requestBody: "",
requestMethod: "",
country: "",
lambdaRequestId: "",
logStreamName: "",
logGroupName: "",
apiGatewayId: ""
}
}
It will console.log
:
event
context
Aws-Api-Gateway-Request-Id
Identity-Source-Ip
passDownObj
has renamed to shared
return
STOPS the execution now, like throw
, makes the flow easier to reason about!http
helpers can be used under HttpResponse
, just import this one alone