@aws-lambda-powertools/parser
Version:
The parser package for the Powertools for AWS Lambda (TypeScript) library.
256 lines (255 loc) • 8.6 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.UserIdentity = exports.DynamoDBStreamChangeRecordBase = exports.DynamoDBStreamChangeRecord = exports.DynamoDBStreamRecord = exports.DynamoDBStreamSchema = exports.DynamoDBStreamToKinesisChangeRecord = exports.DynamoDBStreamToKinesisRecord = void 0;
const unmarshallDynamoDB_1 = require("@aws-lambda-powertools/commons/utils/unmarshallDynamoDB");
const zod_1 = require("zod");
const DynamoDBStreamChangeRecordBase = zod_1.z.object({
ApproximateCreationDateTime: zod_1.z.number().optional(),
Keys: zod_1.z.record(zod_1.z.string(), zod_1.z.record(zod_1.z.string(), zod_1.z.any())),
NewImage: zod_1.z.record(zod_1.z.string(), zod_1.z.any()).optional(),
OldImage: zod_1.z.record(zod_1.z.string(), zod_1.z.any()).optional(),
SequenceNumber: zod_1.z.string(),
SizeBytes: zod_1.z.number(),
StreamViewType: zod_1.z.enum([
'NEW_IMAGE',
'OLD_IMAGE',
'NEW_AND_OLD_IMAGES',
'KEYS_ONLY',
]),
});
exports.DynamoDBStreamChangeRecordBase = DynamoDBStreamChangeRecordBase;
const DynamoDBStreamToKinesisChangeRecord = DynamoDBStreamChangeRecordBase.omit({
SequenceNumber: true,
StreamViewType: true,
});
exports.DynamoDBStreamToKinesisChangeRecord = DynamoDBStreamToKinesisChangeRecord;
const unmarshallDynamoDBTransform = (object, ctx) => {
const result = { ...object };
const unmarshallAttributeValue = (imageName, image) => {
try {
// @ts-expect-error
return (0, unmarshallDynamoDB_1.unmarshallDynamoDB)(image);
}
catch {
ctx.addIssue({
code: 'custom',
message: `Could not unmarshall ${imageName} in DynamoDB stream record`,
fatal: true,
path: [imageName],
});
return zod_1.z.NEVER;
}
};
const unmarshalledKeys = unmarshallAttributeValue('Keys', object.Keys);
if (unmarshalledKeys === zod_1.z.NEVER)
return zod_1.z.NEVER;
// @ts-expect-error - We are intentionally mutating the object
result.Keys = unmarshalledKeys;
if (object.NewImage) {
const unmarshalled = unmarshallAttributeValue('NewImage', object.NewImage);
if (unmarshalled === zod_1.z.NEVER)
return zod_1.z.NEVER;
result.NewImage = unmarshalled;
}
if (object.OldImage) {
const unmarshalled = unmarshallAttributeValue('OldImage', object.OldImage);
if (unmarshalled === zod_1.z.NEVER)
return zod_1.z.NEVER;
result.OldImage = unmarshalled;
}
return result;
};
const DynamoDBStreamChangeRecord = DynamoDBStreamChangeRecordBase.transform(unmarshallDynamoDBTransform);
exports.DynamoDBStreamChangeRecord = DynamoDBStreamChangeRecord;
const UserIdentity = zod_1.z.object({
type: zod_1.z.enum(['Service']),
principalId: zod_1.z.literal('dynamodb.amazonaws.com'),
});
exports.UserIdentity = UserIdentity;
const DynamoDBStreamRecord = zod_1.z.object({
eventID: zod_1.z.string(),
eventName: zod_1.z.enum(['INSERT', 'MODIFY', 'REMOVE']),
eventVersion: zod_1.z.string(),
eventSource: zod_1.z.literal('aws:dynamodb'),
awsRegion: zod_1.z.string(),
eventSourceARN: zod_1.z.string(),
dynamodb: DynamoDBStreamChangeRecord,
userIdentity: UserIdentity.optional(),
});
exports.DynamoDBStreamRecord = DynamoDBStreamRecord;
/**
* Zod schema for Amazon DynamoDB Stream event sent to an Amazon Kinesis Stream.
*
* This schema is best used in conjunction with the {@link KinesisEnvelope | `KinesisEnvelope`} when
* you want to work with the DynamoDB stream event coming from an Amazon Kinesis Stream.
*
* By default, we unmarshall the `dynamodb.Keys`, `dynamodb.NewImage`, and `dynamodb.OldImage` fields
* for you.
*
* If you want to extend the schema and provide your own Zod schema for any of these fields,
* you can use the {@link DynamoDBMarshalled | `DynamoDBMarshalled`} helper. In that case, we won't unmarshall the other fields.
*
* To extend the schema, you can use the {@link DynamoDBStreamToKinesisRecord | `DynamoDBStreamToKinesisRecord`} child schema and the {@link DynamoDBMarshalled | `DynamoDBMarshalled`}
* helper together.
*
* @example
* ```ts
* import {
* DynamoDBStreamToKinesisRecord,
* DynamoDBStreamToKinesisChangeRecord,
* } from '@aws-lambda-powertools/parser/schemas/dynamodb';
* import { KinesisEnvelope } from '@aws-lambda-powertools/parser/envelopes/dynamodb';
* import { DynamoDBMarshalled } from '@aws-lambda-powertools/parser/helpers/dynamodb';
*
* const CustomSchema = DynamoDBStreamToKinesisRecord.extend({
* dynamodb: DynamoDBStreamToKinesisChangeRecord.extend({
* NewImage: DynamoDBMarshalled(
* z.object({
* id: z.string(),
* attribute: z.number(),
* stuff: z.array(z.string()),
* })
* ),
* // Add the lines below only if you want these keys to be unmarshalled
* Keys: DynamoDBMarshalled(z.unknown()),
* OldImage: DynamoDBMarshalled(z.unknown()),
* }),
* });
*
* type CustomEvent = z.infer<typeof CustomSchema>;
* ```
*/
const DynamoDBStreamToKinesisRecord = DynamoDBStreamRecord.extend({
recordFormat: zod_1.z.literal('application/json'),
tableName: zod_1.z.string(),
userIdentity: UserIdentity.nullish(),
dynamodb: DynamoDBStreamToKinesisChangeRecord.transform(unmarshallDynamoDBTransform),
}).omit({
eventVersion: true,
eventSourceARN: true,
});
exports.DynamoDBStreamToKinesisRecord = DynamoDBStreamToKinesisRecord;
/**
* Zod schema for Amazon DynamoDB Stream event.
*
* @example
* ```json
* {
* "Records":[{
* "eventID":"1",
* "eventName":"INSERT",
* "eventVersion":"1.0",
* "eventSource":"aws:dynamodb",
* "awsRegion":"us-east-1",
* "dynamodb":{
* "Keys":{
* "Id":{
* "N":"101"
* }
* },
* "NewImage":{
* "Message":{
* "S":"New item!"
* },
* "Id":{
* "N":"101"
* }
* },
* "SequenceNumber":"111",
* "SizeBytes":26,
* "StreamViewType":"NEW_AND_OLD_IMAGES"
* },
* "eventSourceARN":"stream-ARN"
* },
* {
* "eventID":"2",
* "eventName":"MODIFY",
* "eventVersion":"1.0",
* "eventSource":"aws:dynamodb",
* "awsRegion":"us-east-1",
* "dynamodb":{
* "Keys":{
* "Id":{
* "N":"101"
* }
* },
* "NewImage":{
* "Message":{
* "S":"This item has changed"
* },
* "Id":{
* "N":"101"
* }
* },
* "OldImage":{
* "Message":{
* "S":"New item!"
* },
* "Id":{
* "N":"101"
* }
* },
* "SequenceNumber":"222",
* "SizeBytes":59,
* "StreamViewType":"NEW_AND_OLD_IMAGES"
* },
* "eventSourceARN":"stream-ARN"
* },
* {
* "eventID":"3",
* "eventName":"REMOVE",
* "eventVersion":"1.0",
* "eventSource":"aws:dynamodb",
* "awsRegion":"us-east-1",
* "dynamodb":{
* "Keys":{
* "Id":{
* "N":"101"
* }
* },
* "OldImage":{
* "Message":{
* "S":"This item has changed"
* },
* "Id":{
* "N":"101"
* }
* },
* "SequenceNumber":"333",
* "SizeBytes":38,
* "StreamViewType":"NEW_AND_OLD_IMAGES"
* },
* "eventSourceARN":"stream-ARN"
* }],
* "window": {
* "start": "2020-07-30T17:00:00Z",
* "end": "2020-07-30T17:05:00Z"
* },
* "state": {
* "1": "state1"
* },
* "shardId": "shard123456789",
* "eventSourceARN": "stream-ARN",
* "isFinalInvokeForWindow": false,
* "isWindowTerminatedEarly": false
* }
* ```
*
* @see {@link DynamoDBStreamEvent | DynamoDBStreamEvent}
* @see {@link https://docs.aws.amazon.com/lambda/latest/dg/with-ddb.html}
*/
const DynamoDBStreamSchema = zod_1.z.object({
Records: zod_1.z.array(DynamoDBStreamRecord).nonempty(),
window: zod_1.z
.object({
start: zod_1.z.iso.datetime(),
end: zod_1.z.iso.datetime(),
})
.optional(),
state: zod_1.z.record(zod_1.z.string(), zod_1.z.string()).optional(),
shardId: zod_1.z.string().optional(),
eventSourceARN: zod_1.z.string().optional(),
isFinalInvokeForWindow: zod_1.z.boolean().optional(),
isWindowTerminatedEarly: zod_1.z.boolean().optional(),
});
exports.DynamoDBStreamSchema = DynamoDBStreamSchema;