# CardX Lambda Handler Library

Wrapper function that
provides some basic logging,
adds some diagnostic headers,
and catches fatal errors.
Also exposes some helpful dependencies,
namely `log` (`@cardx/logger`)
and `Sentry` (`@sentry/node`).

## Installation

``` shell
npm --save install @cardx/lambda-handler
```

## Usage

``` typescript
handler(handlerName: String, handlerFunction: function, options: object = {})
```

### Wrapping a Function in the Handler

``` javascript
import handler from "@cardx/lambda-handler";

export const successHandler = handler("Success", async event => {
  return {
    statusCode: 200,
    body: JSON.stringify({ msg: "Success!" })
  };
});
```

### Using the CardX logger

The handler also wraps CardX logger to
provide automatic integration with Sentry.
Sentry expects the `SENTRY_DSN` variable
to be present in the environment
(i.e., put it in your `template.yaml`).
A guide to "[Using Sentry with the @cardx/lambda-handler](https://cardx.atlassian.net/wiki/spaces/dev/pages/70746139/Using+Sentry+with+the+cardx+lambda-handler)"
can be found in Confluence.

``` javascript
import { log } from "@cardx/lambda-handler";

// Standard messages
log.info("This is an informational message");
log.notice("This is an informational message"); // "warning" level WITHOUT notification (for things that should stand out in the logs but not trigger an email in Sentry)

// Debug messages
log.debug("This is a debug message");
log.trace("This is a trace message");

// Messages that also log to Sentry
log.notify("This is an informational message"); // "info" level plus notification
log.warning("This is a warning message");
log.error("This is a error message");

// You probably won't use this, but
log.fatal("This is a fatal message");
```

`log.fatal` should be reserved for unrecoverable errors
and the handler usually catches those cases for you.
You might catch your own from time to time,
but in those cases the call to `log.fatal` should
be the last thing you do before the `return`

### Using the Notify Handler

The notify handler will use log.notice() to send a verification message to Sentry.  This is useful to make sure you have Sentry configured properly in the pipeline.

``` javascript
export { notifyHandler } from "@cardx/lambda-handler";
```

### Accessing the @sentry/node Object

``` javascript
import { Sentry } from "@cardx/lambda-handler";
```

You probably won't need this
since the logger sends messages to Sentry
on `warn`, `error`, and `fatal`,
but it's here for convenience.
Per above, `SENTRY_DSN` must be available.
If you find yourself accessing `Sentry` a lot
that is probably a sign that
the logger provided by this library
needs to be extended.

### Exposing the Echo Handler

The echo handler simply responds with the `event` and `context`.

``` javascript
export { echoHandler } from "@cardx/lambda-handler";
```

### Arcane Options Parameter

The optional third parameter can include a number of keys with additional effects.

| Option                      | Type     | Default     | Effect                                                                                                                                                                 |
| --------------------------- | -------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `api`                       | boolean  | `true`      | By default the handler assumes it is being used in an API Gateway.  Setting `api` to `false` prevents the handler from decorating the response with additional headers |
| `allowHeadersResponse`      | string   | `undefined` | Value for `Access-Control-Allow-Headers` CORS header.  Also checks `process.env.HANDLER_ALLOW_HEADERS_RESPONSE` for value                                              |
| `allowMethodsResponse`      | string   | `undefined` | Value for `Access-Control-Allow-Methods` CORS header.  Also checks `process.env.HANDLER_ALLOW_METHODS_RESPONSE` for value                                              |
| `allowOriginResponse`       | string   | `undefined` | Value for `Access-Control-Allow-Origin` CORS header.  Also checks `process.env.HANDLER_ALLOW_ORIGIN_RESPONSE` for value                                                |
| `autoRespondToOptions`      | boolean  | `false`     | Whether the handler should skip execution on an options request                                                                                                        |
| `discardRequestFunction`    | function | `undefined` | Will be called with `event` object, may return `true` or other permitted values to omit execution (see below)                                                            |
| `logMetaFromEventFunction`  | function | `undefined` | Will be called with `event` object, must return object.  Any keys in return object will be logged as meta data                                                         |
| `logMetaFromRequestHeaders` | object   | (see below) | Picks up special headers and logs them for inclusion in Datadog                                                                                                        |

#### Discard Request Function

* Supported response values are listed below.
* Any response not listed will be ignored and the handler will execute as normal.
* The default rejection message defined in jaypie-errors 1.4.0 is "The request was rejected prior to processing."
* Any thrown errors, except Jaypie errors, are logged and ignored

| Type                     | Value   | Effect                                                                                                                 |
| ------------------------ | ------- | ---------------------------------------------------------------------------------------------------------------------- |
| Boolean                  | `false` | Handler proceeds as normal                                                                                             |
| Boolean                  | `true`  | Returns 403 Forbidden with a rejection message defined in jaypie-errors.  This is the standard, preferred response     |
| Number (HTTP error code) | `4XX`   | Returns that status code with a rejection message                                                                      |
| Number (HTTP no content) | `204`   | Returns HTTP status `204` with no content                                                                              |
| Object                   | *       | If the object contains a numeric status code, the object as a whole will be returned (to fully customize the response) |
| Jaypie error             | *       | Formats and returns that error.  This also works if the error is thrown instead of returned                            |

#### Log Meta From Request Headers

Object with static keys that map to variables that will output in Datadog

| Key              | Default Value                                            |
| ---------------- | -------------------------------------------------------- |
| `merchant`       | `HTTP.HEADER.GATEWAY.ACCOUNT` (from @cardx/common)       |
| `postman`        | `HTTP.HEADER.POSTMAN.TOKEN` (from @cardx/common)         |
| `rootInvocation` | `HTTP.HEADER.CARDX.ROOT_INVOCATION` (from @cardx/common) |
| `session`        | `HTTP.HEADER.CARDX.SESSION` (from @cardx/common)         |

#### Example

``` javascript
import handler from "@cardx/lambda-handler";

async function success() {
  return {
    message: "Success!"
  };
}

export const nonApiHandler = handler("Success", success, { api: false });
```

### Environment Options

| Option                 | Type   | Default | Effect                                                                                  |
| ---------------------- | ------ | ------- | --------------------------------------------------------------------------------------- |
| `SENTRY_CLOSE_TIMEOUT` | number | 2       | Number of seconds (or milliseconds) Sentry is given to complete the `close()` operation |

### Changelog

* 1.15.0: Adds `discardRequestFunction` option
* 1.14.4: Removes Sentry logging for Sandbox environment
* 1.14.2: Adds `SENTRY_CLOSE_TIMEOUT` env option
* 1.14: Adds `logMetaFromEventFunction` option
* 1.13: Handle @cardx/jaypie-errors natively
* 1.12: Doesn't send logs to Sentry in "test" mode (NODE_ENV)
* 1.11: Improves breadcrumbs in Sentry
* 1.10: Adds automatic CORS handling
* 1.9: Adds tagging to Sentry
* 1.8: Improves logging for Datadog

## License

© CardX. All rights reserved.
