or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

core-parsing.mdenvelopes.mderrors.mdhelpers.mdindex.mdmiddleware.mdparser-decorator.mdschemas.md
tile.json

envelopes.mddocs/

Envelopes

Envelopes extract nested payloads from AWS event wrappers and validate the inner data.

Why Envelopes

AWS events wrap business data in service-specific metadata. Envelopes automatically extract and validate the nested payload.

Example: SQS event has data in Records[].body, EventBridge in detail, API Gateway in body.

Envelope Types

TypeReturnsUse Case
ObjectEnvelopeSingle objectEvents with one payload (API Gateway, EventBridge)
ArrayEnvelopeArray of objectsEvents with multiple records (SQS, Kinesis, SNS)
DynamoDBArrayEnvelopeArray with NewImage/OldImageDynamoDB Streams with before/after snapshots

Available Envelopes

EnvelopeTypeExtracts FromReturnsCommon With
ApiGatewayEnvelopeObjectevent.bodyTJSONStringified
ApiGatewayV2EnvelopeObjectevent.bodyTJSONStringified
CloudWatchEnvelopeArrayevent.awslogs.data.logEvents[].messageT[]JSONStringified
DynamoDBStreamEnvelopeDynamoDBevent.Records[].dynamodb.{NewImage,OldImage}{NewImage?: T, OldImage?: T}[]DynamoDBMarshalled
EventBridgeEnvelopeObjectevent.detailT-
KafkaEnvelopeArrayevent.records[topic][].valueT[]JSONStringified
KinesisEnvelopeArrayevent.Records[].kinesis.dataT[]Base64Encoded, JSONStringified
KinesisFirehoseEnvelopeArrayevent.records[].dataT[]Base64Encoded, JSONStringified
LambdaFunctionUrlEnvelopeObjectevent.bodyTJSONStringified
SnsEnvelopeArrayevent.Records[].Sns.MessageT[]JSONStringified
SnsSqsEnvelopeArrayJSON.parse(event.Records[].body).MessageT[]JSONStringified
SqsEnvelopeArrayevent.Records[].bodyT[]JSONStringified
VpcLatticeEnvelopeObjectevent.bodyTJSONStringified
VpcLatticeV2EnvelopeObjectevent.bodyTJSONStringified

Usage

With parse()

import { parse } from '@aws-lambda-powertools/parser';
import { EventBridgeEnvelope } from '@aws-lambda-powertools/parser/envelopes';
import { z } from 'zod';

const schema = z.object({ orderId: z.string(), amount: z.number() });

// Throws on error
const order = parse(event, EventBridgeEnvelope, schema);

// Safe parsing
const result = parse(event, EventBridgeEnvelope, schema, true);
if (result.success) console.log(result.data);

With @parser decorator

import { parser } from '@aws-lambda-powertools/parser';
import { SqsEnvelope } from '@aws-lambda-powertools/parser/envelopes';

class Handler {
  @parser({ schema: taskSchema, envelope: SqsEnvelope })
  async handler(event: Task[], _context: Context) {
    // event is Array<Task> (extracted from SQS records)
    event.forEach(task => console.log(task.taskId));
  }
}

With middleware

import { parser } from '@aws-lambda-powertools/parser/middleware';
import { EventBridgeEnvelope } from '@aws-lambda-powertools/parser/envelopes';
import middy from '@middy/core';

export const handler = middy()
  .use(parser({ schema: orderSchema, envelope: EventBridgeEnvelope }))
  .handler(async (event) => {
    // event is Order (extracted from EventBridge detail)
    console.log(event.orderId);
  });

Direct envelope methods

import { SqsEnvelope } from '@aws-lambda-powertools/parser/envelopes';
import { JSONStringified } from '@aws-lambda-powertools/parser/helpers';

// Throws on error
const tasks = SqsEnvelope.parse(event, JSONStringified(taskSchema));

// Safe parsing
const result = SqsEnvelope.safeParse(event, JSONStringified(taskSchema));
if (result.success) {
  console.log(`Parsed ${result.data.length} tasks`);
} else {
  console.error(result.error.message);
}

Combining with Helpers

JSON in SQS

import { SqsEnvelope } from '@aws-lambda-powertools/parser/envelopes';
import { JSONStringified } from '@aws-lambda-powertools/parser/helpers';

const tasks = SqsEnvelope.parse(event, JSONStringified(taskSchema));

Base64 + JSON in Kinesis

import { KinesisEnvelope } from '@aws-lambda-powertools/parser/envelopes';
import { Base64Encoded, JSONStringified } from '@aws-lambda-powertools/parser/helpers';

const clicks = KinesisEnvelope.parse(
  event,
  Base64Encoded(JSONStringified(clickSchema))
);

DynamoDB Marshalled Data

import { DynamoDBStreamEnvelope } from '@aws-lambda-powertools/parser/envelopes';
import { DynamoDBMarshalled } from '@aws-lambda-powertools/parser/helpers/dynamodb';

const records = DynamoDBStreamEnvelope.parse(
  event,
  DynamoDBMarshalled(productSchema)
);

records.forEach(record => {
  if (record.NewImage) console.log('New:', record.NewImage);
  if (record.OldImage) console.log('Old:', record.OldImage);
});

SNS via SQS (double-nested)

import { SnsSqsEnvelope } from '@aws-lambda-powertools/parser/envelopes';
import { JSONStringified } from '@aws-lambda-powertools/parser/helpers';

// Handles JSON.parse(sqs.body).Message
const alerts = SnsSqsEnvelope.parse(event, JSONStringified(alertSchema));

Error Handling

const result = SqsEnvelope.safeParse(event, JSONStringified(schema));

if (!result.success) {
  console.error('Parse error:', result.error.message);
  console.error('Error cause:', result.error.cause);
  console.error('Original event:', result.originalEvent);
}

Types

interface ArrayEnvelope {
  parse<T>(data: unknown, schema: ZodType<T>): T[];
  safeParse<T>(data: unknown, schema: ZodType<T>): ParsedResult<unknown, T[]>;
}

interface ObjectEnvelope {
  parse<T>(data: unknown, schema: ZodType<T>): T;
  safeParse<T>(data: unknown, schema: ZodType<T>): ParsedResult<unknown, T>;
}

interface DynamoDBArrayEnvelope {
  parse<T>(data: unknown, schema: ZodType<T>): DynamoDBStreamEnvelopeResponse<T>[];
  safeParse<T>(data: unknown, schema: ZodType<T>): ParsedResult<unknown, DynamoDBStreamEnvelopeResponse<T>[]>;
}

interface DynamoDBStreamEnvelopeResponse<T> {
  NewImage?: T;
  OldImage?: T;
}