@jaypie/lambda
Prerequisites: npm install jaypie or npm install @jaypie/lambda
Overview
Section titled âOverviewâ@jaypie/lambda provides Lambda handler wrappers with lifecycle management, event parsing, and automatic error handling.
Installation
Section titled âInstallationânpm install jaypie# ornpm install @jaypie/lambdaQuick Reference
Section titled âQuick ReferenceâExports
Section titled âExportsâ| Export | Purpose |
|---|---|
lambdaHandler |
Standard Lambda handler wrapper |
lambdaStreamHandler |
Response streaming handler wrapper |
Event Helpers (from jaypie)
Section titled âEvent Helpers (from jaypie)â| Export | Purpose |
|---|---|
getMessages |
Parse SQS/SNS events into message bodies |
getSingletonMessage |
Get exactly one message or throw |
lambdaHandler
Section titled âlambdaHandlerâBasic Usage
Section titled âBasic Usageâimport { lambdaHandler } from "jaypie";
export const handler = lambdaHandler(async (event, context) => { return { processed: true };});With Options
Section titled âWith Optionsâimport { lambdaHandler, log } from "jaypie";
export const handler = lambdaHandler( async (event, context) => { log.trace("[process] handling event"); return { success: true }; }, { name: "processEvent", secrets: ["API_KEY", "MONGODB_URI"], validate: [(event) => event.Records?.length > 0], setup: [async () => await initializeResources()], teardown: [async () => await cleanupResources()], });Options Reference
Section titled âOptions Referenceâ| Option | Type | Description |
|---|---|---|
name |
string |
Handler name for logging |
secrets |
string[] |
Secrets to load from AWS Secrets Manager |
validate |
Function[] |
Validation functions |
setup |
Function[] |
Setup functions |
teardown |
Function[] |
Teardown functions (always run) |
Processing SQS Events
Section titled âProcessing SQS EventsâMultiple Messages
Section titled âMultiple Messagesâimport { lambdaHandler, getMessages, log } from "jaypie";
export const handler = lambdaHandler( async (event) => { const messages = getMessages(event);
for (const message of messages) { log.trace("[process] handling message"); log.var({ messageId: message.id }); await processMessage(message); }
return { processed: messages.length }; }, { name: "queueProcessor", });Single Message (Throw if Multiple)
Section titled âSingle Message (Throw if Multiple)âimport { lambdaHandler, getSingletonMessage } from "jaypie";
export const handler = lambdaHandler(async (event) => { // Throws BadGatewayError if not exactly one message const message = getSingletonMessage(event); return await processMessage(message);});Message Parsing
Section titled âMessage ParsingâgetMessages automatically parses:
| Event Type | Parsing |
|---|---|
| SQS | Parses Records[].body as JSON |
| SNS | Parses Records[].Sns.Message as JSON |
| Direct | Returns event as single-item array |
lambdaStreamHandler
Section titled âlambdaStreamHandlerâFor AWS Lambda Response Streaming:
import { lambdaStreamHandler } from "jaypie";
export const handler = awslambda.streamifyResponse( lambdaStreamHandler( async (event, context) => { context.responseStream.write("Starting...\n");
for (const item of items) { await processItem(item); context.responseStream.write(`Done: ${item.id}\n`); } }, { contentType: "text/plain", } ));SSE Streaming
Section titled âSSE Streamingâexport const handler = awslambda.streamifyResponse( lambdaStreamHandler( async (event, context) => { context.responseStream.write("event: start\ndata: {}\n\n");
for await (const data of dataStream) { const sse = `event: data\ndata: ${JSON.stringify(data)}\n\n`; context.responseStream.write(sse); }
context.responseStream.write("event: end\ndata: {}\n\n"); }, { contentType: "text/event-stream", } ));With LLM Streaming
Section titled âWith LLM Streamingâimport { lambdaStreamHandler } from "jaypie";import Llm from "@jaypie/llm";
export const handler = awslambda.streamifyResponse( lambdaStreamHandler( async (event, context) => { const { prompt } = JSON.parse(event.body);
for await (const chunk of Llm.stream(prompt)) { const content = chunk.content || ""; context.responseStream.write(`data: ${JSON.stringify({ content })}\n\n`); } }, { contentType: "text/event-stream", } ));S3 Event Processing
Section titled âS3 Event Processingâimport { lambdaHandler, log } from "jaypie";
export const handler = lambdaHandler(async (event) => { for (const record of event.Records) { const bucket = record.s3.bucket.name; const key = decodeURIComponent(record.s3.object.key);
log.trace("[process] processing S3 object"); log.var({ bucket }); log.var({ key });
await processS3Object(bucket, key); }});Error Handling
Section titled âError HandlingâErrors are logged and re-thrown (Lambda handles retry):
import { lambdaHandler, BadGatewayError, log } from "jaypie";
export const handler = lambdaHandler(async (event) => { try { return await externalService.call(event); } catch (error) { log.error("External service failed"); log.var({ error: error.message }); throw BadGatewayError(); }});Testing
Section titled âTestingâimport { describe, expect, it, vi } from "vitest";
vi.mock("jaypie", async () => { const testkit = await import("@jaypie/testkit/mock"); return testkit;});
import { handler } from "./index.js";
describe("Lambda Handler", () => { it("processes SQS event", async () => { const event = { Records: [ { body: JSON.stringify({ id: "123" }) }, ], };
const result = await handler(event, {});
expect(result).toEqual({ processed: 1 }); });
it("handles empty event", async () => { const event = { Records: [] }; const result = await handler(event, {}); expect(result).toEqual({ processed: 0 }); });});Build Configuration
Section titled âBuild ConfigurationâFor Lambda deployment with Rollup/Vite:
import { defineConfig } from "vite";
export default defineConfig({ build: { lib: { entry: "src/index.ts", formats: ["es"], fileName: "index", }, rollupOptions: { external: [ /^@aws-sdk/, /^jaypie/, /^@jaypie/, ], }, outDir: "dist", },});Related
Section titled âRelatedâ- Handler Lifecycle - Lifecycle phases
- Error Handling - Error types
- CDK Infrastructure - Lambda deployment
- Testing - Testing handlers