JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 15
  • Score
    100M100P100Q50112F
  • License ISC

helper functions for lambdas

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 inputMiddlewares to modify incoming parameters (note the single object with keys event, context, and callback)
  • accepts outputMiddlewares to modify outgoing response, e.g. to transform it to an AWS-conform lambda response (with at least one of body|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): any

Deeply 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): any

Same 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 deepKebabTransform

responses

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): Object

Mostly 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): Object

Can 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(): Object

If 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): Object

Used 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): Object

Returns 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): Object

Can be used to quickly generate HTTP redirections. Example:

handleRedirect('www.example.com')
// => { "headers": { "Location": "www.example.com" }, "statusCode": 322 }