Package Exports
- @compeon/lambda-helpers
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@compeon/lambda-helpers) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
COMPEON Lambda Helpers
Useful functions that will probably be used across all Lambda functions. Mainly by using the wrapper compeonHandler and log.
Note: Type definitions in this README are meant as a help and do not strictly follow TypeScript or Flow conventions.
compeonHandler
compeonHandler(
handler: func,
inputMiddleware?: func[],
outputMiddleware?: func[]
): Promise<AWS response>`
params:
handler: (event, context, callback) => any
inputMiddleware: ({ event, context, callback }) => ({ event, context, callback })
outputMiddleware: ({ body|statusCode|headers }) => ({ body|statusCode|headers })The main function of this package. It...
- expects an event handler, sync or async
- passes your result to the AWS
lambda_handler - catches and logs (see
log) errors thrown inside your event handler - accepts
inputMiddlewaresto modify incoming parameters (note the single object with keysevent,context, andcallback) - accepts
outputMiddlewaresto modify outgoing response, e.g. to transform it to an AWS-conform lambda response (with at least one ofbody|statusCode|headers)
Note: requires Node 8.10 or above
Example:
exports.lambda_handler = compeonHandler(event =>
const { testString } = event.queryStringParameters
// the following gets caught and logged
if (!testString) throw new CompeonError('I need a test string', 422)
// this works as well, but error stack would be missing:
if (!testString) throw 'I need a test string'
// the following gets returned as promise
return {
body: 'my result'
}
)The response, in error case, would be:
{
"body": {
"errors": [{
"code": "Unprocessible Entity",
"detail": "I need a testString",
"status": 422,
"title": "422 (Unprocessable Entity)"
}]
},
"statusCode": 422,
}Note that this example uses the CompeonError (see CompeonError) to set a status.
CompeonError
Error class that allows saving status (as well as the message).
Example
if (errorCondition) throw new CompeonError('I need a test string', 422)If thrown inside a compeonHandler, the error gets logged and passed as the lambda's response. Note that error responses, just like normal ones, pass through the outputMiddleware (see using middleware).
using middleware
The compeonHandler accepts the two parameters inputMiddleware and outputMiddleware.
inputMiddleware
Can be used to transform the lambda input. Accepts and must return objects of the form { event, context?, callback? }.
outputMiddleware
Can be used to transform outgoing responses of your handler. Accepts and must return objects of the AWS lambda resposne form, meaning at least one of the keys body, statusCode, and headers must be present.
ready-to-use middleware
This package provides some useful outputMiddleware for convenience.
awsResponseMiddleware
Transforms any object to an AWS response (by wrapping your result into the key body).
Example:
exports.lambda_handler = compeonHandler(
// your handler
event => ({ test: event.inputKey, resultKey: 'resultValue' })
// add a key in inputMiddleware for demonstration purposes
[({ event }) => ({ event: { inputKey: 'from inputMiddleware' } })],
// transform result of your handler to be json-api and AWS conform
[awsResponseMiddleware],
)This would result in the following response:
{
"body": {
"test": "from inputMiddleware",
"resultKey": "resultValue"
},
"statusCode": 200
}kebabMiddleware
Transforms keys of objects in your body of the AWS response.
Example:
exports.lambda_handler = compeonHandler(
// your handler
event => ({ test: event.inputKey, resultKey: 'resultValue' })
// add a key in inputMiddleware for demonstration purposes
[({ event }) => ({ event: { inputKey: 'from inputMiddleware' } })],
// transform result of your handler to be json-api and AWS conform
[kebabMiddleware, awsResponseMiddleware],
)This would result in the following response, note that it only transforms the body, not touching the AWS statusCode:
{
"body": {
"test": "from inputMiddleware",
"result-key": "resultValue"
},
"statusCode": 200
}Logging
This section covers functions for logging functionality.
log
`log(data: any): void`Log data in a JSON-stringified, formatted way. Use it the same way you would use console.log, but note that calls with multiple arguments are not supported.
Example:
log(myTestObject)toJsonString
`toJsonString(data: Object): void`Just a convenience method. Calls JSON.stringify(data, null, 2).
Deep Object transformation
This package also includes three functions to transform object keys: for kebab-case, camelCase, and a generic one with custom transformator.
deepCamelTransform
deepCamelTransform(data: any): anyDeeply transforms object keys of data to camelCase keys. Also transforms arrays if they contain any objects.
Example:
deepCamelTransform(
{ PascalCaseKey: 'value', nested_object: { 'kebab-case': 'value' } }
)
// { pascalCaseKey: 'value', nestedObject: { kebabCase: 'value' } }deepKebabTransform
deepKebabTransform(data: any): anySame as deepCamelTransform, but with kebab-case:
Example:
deepKebabTransform(
{ PascalCaseKey: 'value', nested_object: { 'kebab-case': 'value' } }
)
// { "pascal-case-key": 'value', "nested-object": { "kebab-case": 'value' } }deepKeyTransformer
deepKeyTransformer(transformFunc: (string) => (string)): (Array|Object) => (Array|Object)Creates a deepKeyTransformer with the given transformer. Example:
deepKeyTransformer(kebabCase)
// returns a function equal to deepKebabTransformresponses
The following functions turn some input into AWS Lambda responses of the form:
{
"body": someBody,
"statusCode": number,
"headers": optionalHeaders
}Transforms that can directly be used on axios responses are provided as well.
handleAxiosError
handleAxiosError(axiosResponse: Object): ObjectMostly used inside catch of an axios request. Extracts error from the response and calls handleError with it.
Note: Will only work with responses that follow the structure of an axios response.
Example:
axios.get(apiUrl)
.then(someResponseHandler)
.catch(handleAxiosError)handleAxiosOk
handleAxiosOk(body: Object): ObjectCan be used to chain the data of an axios request directly as the Lambda response. Expects a data attribute
exports.lambda_handler = (event) => {
return axios.get('https://jsonplaceholder.typicode.com/todos/1')
.then(handleAxiosOk)
}
// the lambda returns {"userId":1,"id":1,"title":"delectus aut autem","completed":false}handleEmptyOk
handleEmptyOk(): ObjectIf an empty 200 response is wanted (Still contains the string 'ok').
exports.lambda_handler = (event) => {
// omitted ...
return axios.get(apiUrl)
.then(someResponseHandler) // Can provide anything, handleEmptyOk has no expectations
.then(handleEmptyOk)
}handleError
handleError(error: any, status?: number): ObjectUsed to log the provided error to cloudwatch. Returns AWS Lambda conform response object. If error is not a string, it gets JSON-stringified.
status defaults to 500.
Example:
handleError('not found', 404)
// => logs 'not found' to cloudwatch console
// => { body: 'not found', statusCode: 404 }handleOk
handleOk(body?: string|object, headers?: object, statusCode?: number): ObjectReturns an AWS Lambda conform response object with the preferred body. statusCode defaults to 200. Can be used to chain a previous response to the Lambda output.
Example:
handleOk()
// => { "body": "ok", "statusCode": 200 }
// May also be used as a last handler in a promise chain to directly transform the previous' handlers response as the response of the Lambda itself:
exports.lambda_handler = (event) => {
return axios.get(apiUrl)
.then(someResponseHandler) // => Must provide json-parsable object
.then(handleOk)
}handleRedirect
handleRedirect(url: string, statusCode?: 302): ObjectCan be used to quickly generate HTTP redirections. Example:
handleRedirect('www.example.com')
// => { "headers": { "Location": "www.example.com" }, "statusCode": 322 }