Skip to content

API reference / @backpack/aws-lambda

@backpack/aws-lambda️ 👩‍💻

A package containing all sorts of utilities for writing AWS Lambda functions.

Installing

First, ensure you have set up Nexus as private registry needed to use Backpack.

Then, install the package using npm:

bash
npm install @backpack/aws-lambda

defineLambda() helpers

Helps to define correct AWS Lambda function handlers, by enabling type inference and enforcing the correct type definitions for your specific Lambda integration.

For example:

ts
import { 
defineRestLambda
} from "@backpack/aws-lambda";
export const
handler
=
defineRestLambda
(async (
event
,
context
) => {
// ... return {
statusCode
: 200,
body
: "OK" };
// ^ should return a `APIGatewayProxyResult` });

The following helper functions are currently provided by Backpack:

Helper functionLambda integration
defineLambda()(none or irrelevant)
defineRestLambda()API Gateway (REST)
defineSnsLambda()SNS
defineSqsLambda()SQS
defineS3Lambda()S3
defineS3BatchLambda()S3 Batch

REST event utilities

If your AWS Lambda integrates with API Gateway for REST APIs, you can use the following utilities for your APIGatewayProxyEvent event.

parseHeaders()

Parses request headers. Provides type-completion, performs normalization, and includes some validation utilities.

ts
import { APIGatewayProxyResult, 
APIGatewayProxyEvent
} from "aws-lambda";
import {
z
} from "zod";
import {
defineRestLambda
,
parseHeaders
,
jsonOk
} from "@backpack/aws-lambda/rest";
const
handler
=
defineRestLambda
(async (
event
) => {
const
headers
=
parseHeaders
(
event
);
// returns an optional header by default: const
callerId
=
headers
.
get
("X-Caller-Id");
// specifying `required: true` will always return a `string`, // and throws a `RequestValidationError` if not present const
contentType
=
headers
.
get
("Content-Type", {
required
: true });
// specifying `multi: true` will return an array instead const
acceptHeaders
=
headers
.
get
("Accept", {
multi
: true });
// specifying the `validated` option, it will validate the value against a Zod schema, // and throws a `RequestValidationError` if invalid const
Locale
=
z
.
enum
(["nl", "en"]);
const
locale
=
headers
.
get
("Accept-Language", {
validated
:
Locale
});
return
jsonOk
("OK")
})

parsePathParameters() and parseQueryParameters()

Both helper functions improve type-safety and include some validation utilities for parsing parameters.

ts
import { APIGatewayProxyResult } from "aws-lambda";
import { 
z
} from "zod";
import {
defineRestLambda
,
parsePathParameters
,
parseQueryParameters
,
jsonOk
,
} from "@backpack/aws-lambda/rest"; const
handler
=
defineRestLambda
(async (
event
) => {
const
pathParameters
=
parsePathParameters
(
event
);
const
queryParameters
=
parseQueryParameters
(
event
);
// returns an required header by default, // and throws a `RequestValidationError` if not present const
artistId
=
pathParameters
.
get
("artistId");
// specifying `required: false` will return a `string | undefined` instead const
departmentId
=
pathParameters
.
get
("departmentId", {
required
: false });
// specifying the `validated` option, it will validate the value against a Zod schema, // and throws a `RequestValidationError` if invalid const
SortDirection
=
z
.
enum
(["asc", "desc"]);
const
sortDirection
=
queryParameters
.
get
("sort", {
validated
:
SortDirection
});
return
jsonOk
("OK")
});

parseBody()

Parses a request body. Supports both plain text and JSON, and provides built-in validation utilities.

ts
import { APIGatewayProxyResult } from "aws-lambda";
import { 
z
} from "zod";
import {
defineRestLambda
,
parseBody
,
jsonOk
} from "@backpack/aws-lambda/rest";
const
handler
=
defineRestLambda
(async (
event
) => {
const
body
=
parseBody
(
event
);
const
text
=
body
.
text
();
const
json
=
body
.
json
();
// you can also type-cast a JSON object (unsafe) const
unsafeJson
=
body
.
json
<
MySchema
>();
// you can also validate your JSON against a Zod schema (safe) // throws a `RequestValidationError` if invalid const
MySchema
=
z
.
object
({
foo
:
z
.
string
(),
bar
:
z
.
string
().
optional
() })
const
safeJson
=
body
.
json
({
validated
:
MySchema
});
return
jsonOk
("OK")
}); type
MySchema
= {
foo
: string;
bar
?: string;
}

parseRequest() - all of the above

The function parseRequest() returns an object that include all utilities mentioned above:

  • getHeader()
  • getQueryParameter()
  • getPathParameter()
  • getBody()

REST result utilities

If your AWS Lambda integrates with API Gateway for REST APIs, you can use the following utilities for returning an APIGatewayProxyResult object.

result()

This function can be used to wrap your result object, adding additional type-completion.

For example: it hints to use the HttpStatus enum from Backpack:

aws-lambda-http-status.png

it also adds type-completion for HTTP headers:

aws-lambda-http-headers.png

jsonResult()

Creates a result with a JSON body. Accepts any object, and converts it to JSON. It also sets the Content-Type header to application/json.

ts
import { 
defineRestLambda
,
jsonResult
,
HttpStatus
} from "@backpack/aws-lambda/rest";
export const
handler
=
defineRestLambda
(async () => {
// ... return
jsonResult
({ /* ... */ }, {
statusCode
:
HttpStatus
.
OK
});
});

jsonOk()

Same as jsonResult(), but with the status code set to HTTP 200 (OK).

ts
import { 
defineRestLambda
,
jsonOk
} from "@backpack/aws-lambda/rest";
export const
handler
=
defineRestLambda
(async () => {
// ... return
jsonOk
({ /* ... */ });
});

problemResult()

Creates an RFC-9457 compliant problem result, to return an explicitly documented error.

ts
import {
  
defineRestLambda
,
jsonOk
,
problemResult
,
RequestValidationError
,
} from "@backpack/aws-lambda/rest"; import {
AsyncResult
} from "@backpack/error-handling/async-result";
export const
handler
=
defineRestLambda
(() =>
AsyncResult
.
try
(() => {
/* ... */ }) .
map
((
it
) =>
jsonOk
(
it
))
.
recoverIfInstanceOf
(
RequestValidationError
, () =>
problemResult
({
type
: "/problems/validation-error",
title
: "Validation error",
status
: 400,
}), ) );

Error handling

Combining the error handling utilities from @backpack/error-handling with the default error handler from @backpack/aws-lambda/rest allows you to easily set up proper error handling for REST endpoints.

The example below demonstrates three ways to set it up:

  1. Using the @catchErrors() decorator
  2. Using AsyncResult<T>
  3. Using Promise<T>
ts
import type { APIGatewayProxyResult } from "aws-lambda";
import { 
catchErrors
,
onFailure
,
recoverIfInstanceOf
,
orElseGet
} from "@backpack/error-handling/promises";
import {
jsonOk
,
jsonResult
,
defaultErrorHandler
,
ProblemError
} from "@backpack/aws-lambda/rest";
export class
MyLambda
{
@
catchErrors
(
onFailure
(
myErrorLogger
()),
recoverIfInstanceOf
(
MyCustomError
,
myErrorConverter
()),
orElseGet
(
defaultErrorHandler
()),
) public async
handle
():
Promise
<APIGatewayProxyResult> {
await this.
someOperation
();
return
jsonOk
("Done!");
} private async
someOperation
():
Promise
<void> {
// ... } } class
MyCustomError
extends
Error
{ /* ... */ }
function
myErrorLogger
() {
return async (
error
: unknown) =>
console
.
error
(
error
);
} function
myErrorConverter
() {
return (
error
:
MyCustomError
) =>
jsonResult
(
{
message
: `My custom error ${
error
.
message
}!` },
{
statusCode
: 500 },
); }
ts
import type { APIGatewayProxyResult } from "aws-lambda";
import { 
AsyncResult
} from "@backpack/error-handling/async-result";
import {
jsonOk
,
jsonResult
,
defaultErrorHandler
,
ProblemError
} from "@backpack/aws-lambda/rest";
export class
MyLambda
{
public
handle
():
Promise
<APIGatewayProxyResult> {
return
AsyncResult
.
try
(() => this.
someOperation
())
.
map
(() =>
jsonOk
("Done!"))
.
onFailure
(
myErrorLogger
())
.
recoverIfInstanceOf
(
MyCustomError
,
myErrorConverter
())
.
orElseGet
(
defaultErrorHandler
());
} private async
someOperation
():
Promise
<void> {
// ... throw new
ProblemError
({
type
: "/problems/foo-not-found",
status
: 404,
title
: "Foo not found!",
detail
: "Foo 123 could not be found!",
}); // ... } } class
MyCustomError
extends
Error
{ /* ... */ }
function
myErrorLogger
() {
return (
error
: unknown) =>
console
.
error
(
error
);
} function
myErrorConverter
() {
return (
error
:
MyCustomError
) =>
jsonResult
(
{
message
: `My custom error ${
error
.
message
}!` },
{
statusCode
: 500 },
); }
ts
import type { APIGatewayProxyResult } from "aws-lambda";
import { 
promiseTry
,
map
,
onFailure
,
recoverIfInstanceOf
} from "@backpack/error-handling/promises";
import {
jsonOk
,
jsonResult
,
defaultErrorHandler
,
ProblemError
} from "@backpack/aws-lambda/rest";
export class
MyLambda
{
public
handle
():
Promise
<APIGatewayProxyResult> {
return
promiseTry
(() => this.
someOperation
())
.
then
(
map
(() =>
jsonOk
("Done!")))
.
catch
(
onFailure
(
myErrorLogger
()))
.
catch
(
recoverIfInstanceOf
(
MyCustomError
,
myErrorConverter
()))
.
catch
(
defaultErrorHandler
());
} private async
someOperation
():
Promise
<void> {
// ... throw new
ProblemError
({
type
: "/problems/foo-not-found",
status
: 404,
title
: "Foo not found!",
detail
: "Foo 123 could not be found!",
}); // ... } } class
MyCustomError
extends
Error
{ /* ... */ }
function
myErrorLogger
() {
return (
error
: unknown) =>
console
.
error
(
error
);
} function
myErrorConverter
() {
return (
error
:
MyCustomError
) =>
jsonResult
(
{
message
: `My custom error ${
error
.
message
}!` },
{
statusCode
: 500 },
); }

Check the full API reference for more information.

Modules