npm package: @linzjs/lambda
Description: - Automatically chooses the correct HTTP output event format based on input event (API Gateway, ALB, FunctionURL or Cloudfront) - Generates a request id for every request using a [ULID](https://github.com/ulid/spec) - Automatically Logs the correlationId 
Author: Land Information New Zealand
Latest version: 4.2.0

# Lambda wrapper @linzjs/lambda

### _A minimal lambda wrapper for LINZ Javascript lambda function development_

- Automatically chooses the correct HTTP output event format based on input event (API Gateway, ALB, FunctionURL or Cloudfront)
- Generates a request id for every request using a [ULID](https://github.com/ulid/spec)
- Automatically Logs the correlationId if one is provided to the function.
- Logs a meta log at the end of the request `@type: "report"`
- Tracks performance and logs request `duration` & metrics using [@linzjs/metrics](https://www.npmjs.com/package/@linzjs/metrics)

## Why?

This repository wraps the default lambda handler so it can be invoked by ALB, API Gateway or Cloudfront without requiring code changes, while also apply a opinionated set of lambda defaults

#### Http

```typescript
import { lf, LambdaHttpResponse } from '@linzjs/lambda';

// This works for Cloudfront, FunctionURL, ALB or API Gateway events
export const handler = lf.http();

handler.router.get('/v1/ping', () => new LambdaHttpResponse(200, 'Ok'));
handler.router.get<{ Params: { style: string } }>(
  '/v1/style/:style.json',
  (req) => new LambdaHttpResponse(200, 'Style: ' + req.params.style),
);

// Handle all requests
handler.router.get('*', () => new LambdaHttpResponse(404, 'Not found'));

// create middleware to validate api key on all requests
handler.router.hook('request', (req) => {
  const isApiValid = validateApiKey(req.query.get('api'));
  // Bail early
  if (!isApiValid) return new LambdaHttpResponse(400, 'Invalid api key');

  // Continue
  return;
});
```

#### Lambda

```typescript
import { lf } from '@linzjs/lambda';

export const handler = lf.handler<S3Event>(async (req) => {
  if (req.event.Records.length === 0) throw new Error('No records provided');
  for (const evt of req.event.Records) {
    req.log.info({ key: evt.key }, 'Request s3');
  }
});
```

### Request ID generation

A [ULID](https://github.com/ulid/spec) is generated for every request and can be accessed at `req.id`

every log message generated by `req.log` will by include the request id.

### Metrics

Simple timing events can be tracked with `timer` see [@linzjs/metrics](https://www.npmjs.com/package/@linzjs/metrics)

```typescript
req.timer.start('some:event');
// Do Work
const duration = req.timer.end('some:event');
```

TODO: this should eventually be replaced by open telemetry spans

### Metalog

At the end of every request a metalog is logged with use information for monitoring and alerting in something like elasticsearch, to add additional keys to the metatalog use `req.set()`

```typescript
req.set('xyz', { x, y, z });
req.set('location', { lat, lon });
```

### Pino logging

Automatically includes a configured [pino](https://github.com/pinojs/pino) logger

```typescript
function doRequest(req) {
  req.log.info('Some Log line'); // Includes useful information like requestId
}
```

This can be overridden at either the wrapper

```typescript
export const handler = lf.wrap(doRequest, myOwnLogger);
```

of set a different default logger

```typescript
lf.logger = myOwnLogger;
export const handler = lf.wrap(doRequest);
```