UNPKG

4.81 kBJavaScriptView Raw
1import { jsonSafeParse } from '@middy/util';
2const defaults = {
3 wrapNumbers: undefined
4};
5let _wrapNumbers;
6const eventNormalizerMiddleware = (opts = {})=>{
7 const { wrapNumbers } = {
8 ...defaults,
9 ...opts
10 };
11 _wrapNumbers = wrapNumbers;
12 const eventNormalizerMiddlewareBefore = async (request)=>{
13 parseEvent(request.event);
14 };
15 return {
16 before: eventNormalizerMiddlewareBefore
17 };
18};
19const parseEvent = (event)=>{
20 let eventSource = event.eventSource ?? event.deliveryStreamArn;
21 const records = event.Records ?? event.records ?? event.messages ?? event.tasks ?? event.events;
22 if (!Array.isArray(records)) {
23 eventSource ??= (event.configRuleId && 'aws:config') ?? (event.awslogs && 'aws:cloudwatch') ?? (event['CodePipeline.job'] && 'aws:codepipeline');
24 if (eventSource) {
25 events[eventSource]?.(event);
26 }
27 return;
28 }
29 eventSource ??= records[0].eventSource ?? records[0].EventSource ?? (records[0].s3Key && 'aws:s3:batch');
30 for (const record of records){
31 events[eventSource]?.(record);
32 }
33};
34const normalizeS3KeyReplacePlus = /\+/g;
35const events = {
36 'aws:amq': (message)=>{
37 message.data = base64Parse(message.data);
38 },
39 'aws:cloudwatch': (event)=>{
40 event.awslogs.data = base64Parse(event.awslogs.data);
41 },
42 'aws:codepipeline': (event)=>{
43 event['CodePipeline.job'].data.actionConfiguration.configuration.UserParameters = jsonSafeParse(event['CodePipeline.job'].data.actionConfiguration.configuration.UserParameters);
44 },
45 'aws:config': (event)=>{
46 event.invokingEvent = jsonSafeParse(event.invokingEvent);
47 event.ruleParameters = jsonSafeParse(event.ruleParameters);
48 },
49 'aws:dynamodb': (record)=>{
50 record.dynamodb.Keys = unmarshall(record.dynamodb.Keys);
51 record.dynamodb.NewImage = unmarshall(record.dynamodb.NewImage);
52 record.dynamodb.OldImage = unmarshall(record.dynamodb.OldImage);
53 },
54 'aws:kafka': (event)=>{
55 for(const record in event.records){
56 for (const topic of event.records[record]){
57 topic.value &&= base64Parse(topic.value);
58 }
59 }
60 },
61 'aws:kinesis': (record)=>{
62 record.kinesis.data = base64Parse(record.kinesis.data);
63 },
64 'aws:lambda:events': (record)=>{
65 record.data = base64Parse(record.data);
66 },
67 'aws:s3': (record)=>{
68 record.s3.object.key = normalizeS3Key(record.s3.object.key);
69 },
70 'aws:s3:batch': (task)=>{
71 task.s3Key = normalizeS3Key(task.s3Key);
72 },
73 SelfManagedKafka: (event)=>{
74 events['aws:kafka'](event);
75 },
76 'aws:sns': (record)=>{
77 record.Sns.Message = jsonSafeParse(record.Sns.Message);
78 parseEvent(record.Sns.Message);
79 },
80 'aws:sns:sqs': (record)=>{
81 record.Message = jsonSafeParse(record.Message);
82 parseEvent(record.Message);
83 },
84 'aws:sqs': (record)=>{
85 record.body = jsonSafeParse(record.body);
86 if (record.body.Type === 'Notification') {
87 events['aws:sns:sqs'](record.body);
88 } else {
89 parseEvent(record.body);
90 }
91 }
92};
93const base64Parse = (data)=>jsonSafeParse(Buffer.from(data, 'base64').toString('utf-8'));
94const normalizeS3Key = (key)=>decodeURIComponent(key.replace(normalizeS3KeyReplacePlus, ' '));
95const unmarshall = (data)=>convertValue.M(data ?? {});
96const convertValue = {
97 NULL: ()=>null,
98 BOOL: Boolean,
99 N: (value)=>{
100 if (_wrapNumbers) {
101 return {
102 value
103 };
104 }
105 const num = Number(value);
106 if ((Number.MAX_SAFE_INTEGER < num || num < Number.MIN_SAFE_INTEGER) && num !== Number.NEGATIVE_INFINITY && num !== Number.POSITIVE_INFINITY) {
107 try {
108 return BigInt(value);
109 } catch (error) {
110 throw new Error(`${value} can't be converted to BigInt. Set options.wrapNumbers to get string value.`);
111 }
112 }
113 return num;
114 },
115 B: (value)=>value,
116 S: (value)=>value,
117 L: (value)=>value.map((item)=>convertToNative(item)),
118 M: (value)=>Object.entries(value).reduce((acc, [key, value])=>{
119 acc[key] = convertToNative(value);
120 return acc;
121 }, {}),
122 NS: (value)=>new Set(value.map(convertValue.N)),
123 BS: (value)=>new Set(value.map(convertValue.B)),
124 SS: (value)=>new Set(value.map(convertValue.S))
125};
126const convertToNative = (data)=>{
127 for (const [key, value] of Object.entries(data)){
128 if (!convertValue[key]) throw new Error(`Unsupported type passed: ${key}`);
129 if (typeof value === 'undefined') continue;
130 return convertValue[key](value);
131 }
132};
133export default eventNormalizerMiddleware;
134