From aa66d8c55e054041554e71681e47eca7d492df9a Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Tue, 31 Oct 2023 14:09:31 +0100 Subject: [PATCH 01/48] add dynamodb schema --- package-lock.json | 12 +++--- packages/parser/jest.config.js | 1 - packages/parser/package.json | 6 +-- packages/parser/src/intex.ts | 1 + packages/parser/src/schemas/dynamodb.ts | 48 +++++++++++++++++++++ packages/parser/src/schemas/index.ts | 1 + packages/parser/tests/tsconfig.json | 11 +++++ packages/parser/tests/unit/dynamodb.test.ts | 34 +++++++++++++++ tsconfig.json | 3 ++ 9 files changed, 107 insertions(+), 10 deletions(-) create mode 100644 packages/parser/src/schemas/dynamodb.ts create mode 100644 packages/parser/src/schemas/index.ts create mode 100644 packages/parser/tests/tsconfig.json create mode 100644 packages/parser/tests/unit/dynamodb.test.ts diff --git a/package-lock.json b/package-lock.json index 6a5c80f7bb..14ca257550 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17785,10 +17785,10 @@ } }, "node_modules/zod": { - "version": "3.22.2", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.2.tgz", - "integrity": "sha512-wvWkphh5WQsJbVk1tbx1l1Ly4yg+XecD+Mq280uBGt9wa5BKSWf4Mhp6GmrkPixhMxmabYY7RbzlwVP32pbGCg==", - "dev": true, + "version": "3.22.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz", + "integrity": "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==", + "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } @@ -17930,8 +17930,8 @@ "name": "@aws-lambda-powertools/parser", "version": "0.0.0", "license": "MIT-0", - "devDependencies": { - "zod": "^3.22.2" + "peerDependencies": { + "zod": "^3.22.4" } }, "packages/testing": { diff --git a/packages/parser/jest.config.js b/packages/parser/jest.config.js index a4f984ae47..67a7ff2ac4 100644 --- a/packages/parser/jest.config.js +++ b/packages/parser/jest.config.js @@ -24,5 +24,4 @@ module.exports = { }, }, coverageReporters: ['json-summary', 'text', 'lcov'], - setupFiles: ['/tests/helpers/populateEnvironmentVariables.ts'], }; diff --git a/packages/parser/package.json b/packages/parser/package.json index c40d714f80..200f4a20ae 100644 --- a/packages/parser/package.json +++ b/packages/parser/package.json @@ -45,7 +45,7 @@ "publishConfig": { "access": "restricted" }, - "devDependencies": { - "zod": "^3.22.2" + "peerDependencies": { + "zod": "^3.22.4" } -} +} \ No newline at end of file diff --git a/packages/parser/src/intex.ts b/packages/parser/src/intex.ts index e69de29bb2..2715602891 100644 --- a/packages/parser/src/intex.ts +++ b/packages/parser/src/intex.ts @@ -0,0 +1 @@ +export * from './schemas'; \ No newline at end of file diff --git a/packages/parser/src/schemas/dynamodb.ts b/packages/parser/src/schemas/dynamodb.ts new file mode 100644 index 0000000000..bda9f83b45 --- /dev/null +++ b/packages/parser/src/schemas/dynamodb.ts @@ -0,0 +1,48 @@ +import {z} from 'zod'; + +const DynamoDBStreamChangeRecordSchema = z.object({ + ApproximateCreationDateTime: z.optional(z.number()), + Keys: z.record(z.string(), z.record(z.string(), z.any())), + NewImage: z.optional(z.record(z.string(), z.any())), + OldImage: z.optional(z.record(z.string(), z.any())), + SequenceNumber: z.string(), + SizeBytes: z.number(), + StreamViewType: z.enum([ + 'NEW_IMAGE', + 'OLD_IMAGE', + 'NEW_AND_OLD_IMAGES', + 'KEYS_ONLY', + ]), +}); + +const UserIdentitySchema = z.object({ + type: z.enum(['Service']), + principalId: z.literal('dynamodb.amazonaws.com'), +}); + +const DynamoDBStreamRecordSchema = z.object({ + eventID: z.string(), + eventName: z.enum(['INSERT', 'MODIFY', 'REMOVE']), + eventVersion: z.string(), + eventSource: z.literal('aws:dynamodb'), + awsRegion: z.string(), + eventSourceARN: z.string(), + dynamodb: DynamoDBStreamChangeRecordSchema, + userIdentity: z.optional(UserIdentitySchema), +}); + + +type DynamoDBStreamRecord = z.infer; +type DynamoDBStreamChangeRecord = z.infer< + typeof DynamoDBStreamChangeRecordSchema +>; +type UserIdentity = z.infer; + +export { + DynamoDBStreamRecord, + DynamoDBStreamChangeRecord, + UserIdentity, + DynamoDBStreamRecordSchema, + DynamoDBStreamChangeRecordSchema, + UserIdentitySchema, +}; \ No newline at end of file diff --git a/packages/parser/src/schemas/index.ts b/packages/parser/src/schemas/index.ts new file mode 100644 index 0000000000..12e53b3a6c --- /dev/null +++ b/packages/parser/src/schemas/index.ts @@ -0,0 +1 @@ +export * from './dynamodb'; \ No newline at end of file diff --git a/packages/parser/tests/tsconfig.json b/packages/parser/tests/tsconfig.json new file mode 100644 index 0000000000..5654b3e15f --- /dev/null +++ b/packages/parser/tests/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "rootDir": "../", + "noEmit": true + }, + "include": [ + "../src/**/*", + "./**/*", + ] +} \ No newline at end of file diff --git a/packages/parser/tests/unit/dynamodb.test.ts b/packages/parser/tests/unit/dynamodb.test.ts new file mode 100644 index 0000000000..531a88d27b --- /dev/null +++ b/packages/parser/tests/unit/dynamodb.test.ts @@ -0,0 +1,34 @@ +import {DynamoDBStreamRecordSchema} from '../../src/schemas/dynamodb'; + +describe('DynamoDB', () => { + it('should be able to parse a dynamodb table', () => { + DynamoDBStreamRecordSchema.parse({ + eventID: '500c3b0d1c4e9d661540d744ec6270a0', + eventName: 'INSERT', + eventVersion: '1.1', + eventSource: 'aws:dynamodb', + awsRegion: 'eu-west-1', + dynamodb: { + ApproximateCreationDateTime: 1696258322, + Keys: { + id: { + S: '11231', + }, + }, + NewImage: { + name: { + S: 'John Doe', + }, + id: { + S: '11231', + }, + }, + SequenceNumber: '300000000015609734923', + SizeBytes: 26, + StreamViewType: 'NEW_AND_OLD_IMAGES', + }, + eventSourceARN: + 'arn:aws:dynamodb:eu-west-1:770231343013:table/AwsEventsStack-TableCD117FA1-XT5WRCQNWMBQ/stream/2023-10-02T12:16:42.661', + }); + }); +}); \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 8e43c3b084..5724ef8541 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -49,5 +49,8 @@ { "path": "./packages/testing" }, + { + "path": "./packages/parser" + } ] } \ No newline at end of file From 64c3eb115168e77c314c78367d1feaa10e8df7bf Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Tue, 31 Oct 2023 17:42:12 +0100 Subject: [PATCH 02/48] add alb --- packages/parser/src/schemas/alb.ts | 19 ++++++ packages/parser/src/schemas/dynamodb.ts | 12 ++-- packages/parser/tests/unit/dynamodb.test.ts | 72 +++++++++++++++------ 3 files changed, 75 insertions(+), 28 deletions(-) create mode 100644 packages/parser/src/schemas/alb.ts diff --git a/packages/parser/src/schemas/alb.ts b/packages/parser/src/schemas/alb.ts new file mode 100644 index 0000000000..b5cbae4357 --- /dev/null +++ b/packages/parser/src/schemas/alb.ts @@ -0,0 +1,19 @@ +import {z} from 'zod'; + +const AlbSchema = z.object({ + httpMethod: z.string(), + path: z.string(), + body: z.string(), + isBase64Encoded: z.boolean(), + headers: z.record(z.string(), z.string()), + queryStringParameters: z.record(z.string(), z.string()), + requestContext: z.object({ + elb: z.object({ + targetGroupArn: z.string(), + }), + }), +}) + +export { + AlbSchema, +} \ No newline at end of file diff --git a/packages/parser/src/schemas/dynamodb.ts b/packages/parser/src/schemas/dynamodb.ts index bda9f83b45..4eec244e1f 100644 --- a/packages/parser/src/schemas/dynamodb.ts +++ b/packages/parser/src/schemas/dynamodb.ts @@ -31,17 +31,13 @@ const DynamoDBStreamRecordSchema = z.object({ userIdentity: z.optional(UserIdentitySchema), }); +const DynamoDBStreamSchema = z.object({ + Records: z.array(DynamoDBStreamRecordSchema), +}); -type DynamoDBStreamRecord = z.infer; -type DynamoDBStreamChangeRecord = z.infer< - typeof DynamoDBStreamChangeRecordSchema ->; -type UserIdentity = z.infer; export { - DynamoDBStreamRecord, - DynamoDBStreamChangeRecord, - UserIdentity, + DynamoDBStreamSchema, DynamoDBStreamRecordSchema, DynamoDBStreamChangeRecordSchema, UserIdentitySchema, diff --git a/packages/parser/tests/unit/dynamodb.test.ts b/packages/parser/tests/unit/dynamodb.test.ts index 531a88d27b..0801ed93aa 100644 --- a/packages/parser/tests/unit/dynamodb.test.ts +++ b/packages/parser/tests/unit/dynamodb.test.ts @@ -1,34 +1,66 @@ -import {DynamoDBStreamRecordSchema} from '../../src/schemas/dynamodb'; +import {DynamoDBStreamRecordSchema, DynamoDBStreamSchema} from '../../src/schemas/dynamodb'; describe('DynamoDB', () => { - it('should be able to parse a dynamodb table', () => { - DynamoDBStreamRecordSchema.parse({ + it('should parse a stream of records', () => { + DynamoDBStreamSchema.parse({ + Records: [ + { eventID: '500c3b0d1c4e9d661540d744ec6270a0', eventName: 'INSERT', eventVersion: '1.1', eventSource: 'aws:dynamodb', awsRegion: 'eu-west-1', dynamodb: { - ApproximateCreationDateTime: 1696258322, - Keys: { - id: { - S: '11231', - }, + ApproximateCreationDateTime: 1696258322, + Keys: { + id: { + S: '11231', }, - NewImage: { - name: { - S: 'John Doe', - }, - id: { - S: '11231', - }, + }, + NewImage: { + name: { + S: 'John Doe', }, - SequenceNumber: '300000000015609734923', - SizeBytes: 26, - StreamViewType: 'NEW_AND_OLD_IMAGES', + id: { + S: '11231', + }, + }, + SequenceNumber: '300000000015609734923', + SizeBytes: 26, + StreamViewType: 'NEW_AND_OLD_IMAGES', + }, + eventSourceARN: + 'arn:aws:dynamodb:eu-west-1:770231343013:table/AwsEventsStack-TableCD117FA1-XT5WRCQNWMBQ/stream/2023-10-02T12:16:42.661', + }, + { + eventID: '500c3b0d1c4e9d661540d744ec6270a0', + eventName: 'INSERT', + eventVersion: '1.1', + eventSource: 'aws:dynamodb', + awsRegion: 'eu-west-1', + dynamodb: { + ApproximateCreationDateTime: 1696258322, + Keys: { + id: { + S: '11231', + }, + }, + NewImage: { + name: { + S: 'John Doe', + }, + id: { + S: '11231', + }, + }, + SequenceNumber: '300000000015609734923', + SizeBytes: 26, + StreamViewType: 'NEW_AND_OLD_IMAGES', }, eventSourceARN: - 'arn:aws:dynamodb:eu-west-1:770231343013:table/AwsEventsStack-TableCD117FA1-XT5WRCQNWMBQ/stream/2023-10-02T12:16:42.661', - }); + 'arn:aws:dynamodb:eu-west-1:770231343013:table/AwsEventsStack-TableCD117FA1-XT5WRCQNWMBQ/stream/2023-10-02T12:16:42.661', + }, + ], + }) }); }); \ No newline at end of file From f0464ab0926c848956b5cb30f8642d4c2f1d60eb Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Thu, 2 Nov 2023 11:07:13 +0100 Subject: [PATCH 03/48] add parser to v2 build --- package-lock.json | 22 ++++++++++++++++++++++ packages/parser/tsconfig.esm.json | 12 ++++++++++++ tsconfig.json | 3 +++ 3 files changed, 37 insertions(+) create mode 100644 packages/parser/tsconfig.esm.json diff --git a/package-lock.json b/package-lock.json index 198ef2f485..2b28ed8c51 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,7 @@ "packages/idempotency", "packages/batch", "packages/testing", + "packages/parser", "docs/snippets", "layers", "examples/cdk", @@ -333,6 +334,10 @@ "resolved": "packages/parameters", "link": true }, + "node_modules/@aws-lambda-powertools/parser": { + "resolved": "packages/parser", + "link": true + }, "node_modules/@aws-lambda-powertools/testing-utils": { "resolved": "packages/testing", "link": true @@ -16605,6 +16610,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/zod": { + "version": "3.22.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz", + "integrity": "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==", + "peer": true, + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, "packages/batch": { "name": "@aws-lambda-powertools/batch", "version": "1.14.0", @@ -16745,6 +16759,14 @@ } } }, + "packages/parser": { + "name": "@aws-lambda-powertools/parser", + "version": "0.0.0", + "license": "MIT-0", + "peerDependencies": { + "zod": "^3.22.4" + } + }, "packages/testing": { "name": "@aws-lambda-powertools/testing-utils", "version": "1.14.0", diff --git a/packages/parser/tsconfig.esm.json b/packages/parser/tsconfig.esm.json new file mode 100644 index 0000000000..123291b0cf --- /dev/null +++ b/packages/parser/tsconfig.esm.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.esm.json", + "compilerOptions": { + "baseUrl": ".", + "outDir": "./lib/esm", + "rootDir": "./src", + "tsBuildInfoFile": ".tsbuildinfo/esm.json" + }, + "include": [ + "./src/**/*" + ] +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 08d5af9848..0042e92513 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -44,5 +44,8 @@ { "path": "./packages/testing" }, + { + "path": "./packages/parser" + } ] } \ No newline at end of file From f353c7f8e295c14108ef95894cce5ac088387793 Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Thu, 2 Nov 2023 11:08:16 +0100 Subject: [PATCH 04/48] fix test --- packages/parser/jest.config.js | 6 +- packages/parser/package.json | 31 +++++- packages/parser/src/intex.ts | 2 +- packages/parser/src/schemas/index.ts | 3 +- packages/parser/tests/unit/dynamodb.test.ts | 110 ++++++++++---------- packages/parser/tsconfig.json | 3 +- 6 files changed, 91 insertions(+), 64 deletions(-) diff --git a/packages/parser/jest.config.js b/packages/parser/jest.config.js index 67a7ff2ac4..6de7d228d2 100644 --- a/packages/parser/jest.config.js +++ b/packages/parser/jest.config.js @@ -4,7 +4,9 @@ module.exports = { color: 'blue', }, runner: 'groups', - preset: 'ts-jest', + moduleNameMapper: { + '^(\\.{1,2}/.*)\\.js$': '$1', + }, transform: { '^.+\\.ts?$': 'ts-jest', }, @@ -14,7 +16,7 @@ module.exports = { roots: ['/src', '/tests'], testPathIgnorePatterns: ['/node_modules/'], testEnvironment: 'node', - coveragePathIgnorePatterns: ['/node_modules/', '/types/'], + coveragePathIgnorePatterns: ['/node_modules/', 'src/types/index.ts'], coverageThreshold: { global: { statements: 100, diff --git a/packages/parser/package.json b/packages/parser/package.json index 200f4a20ae..38d2551402 100644 --- a/packages/parser/package.json +++ b/packages/parser/package.json @@ -5,11 +5,13 @@ "scripts": { "test": "npm run test:unit", "test:unit": "jest --group=unit --detectOpenHandles --coverage --verbose", + "jest": "jest --detectOpenHandles --coverage --verbose", "watch": "jest --watch", - "build": "tsc --build --force", + "build:cjs": "tsc --build tsconfig.json && echo '{ \"type\": \"commonjs\" }' > lib/cjs/package.json", + "build:esm": "tsc --build tsconfig.esm.json && echo '{ \"type\": \"module\" }' > lib/esm/package.json", + "build": "npm run build:esm & npm run build:cjs", "lint": "eslint --ext .ts,.js --no-error-on-unmatched-pattern .", "lint-fix": "eslint --fix --ext .ts,.js --no-error-on-unmatched-pattern .", - "prebuild": "rimraf ./lib", "prepack": "node ../../.github/scripts/release_patch_package_json.js ." }, "author": { @@ -21,8 +23,29 @@ }, "homepage": "https://github.com/aws-powertools/powertools-lambda-typescript/tree/main/packages/batch#readme", "license": "MIT-0", - "main": "./lib/index.js", - "types": "./lib/index.d.ts", + "type": "module", + "exports": { + ".": { + "require": { + "types": "./lib/cjs/index.d.ts", + "default": "./lib/cjs/index.js" + }, + "import": { + "types": "./lib/esm/index.d.ts", + "default": "./lib/esm/index.js" + } + } + }, + "typesVersions": { + "*": { + "types": [ + "./lib/esm/index.d.ts", + "./lib/cjs/index.d.ts" + ] + } + }, + "main": "./lib/cjs/index.js", + "types": "./lib/cjs/index.d.ts", "files": [ "lib" ], diff --git a/packages/parser/src/intex.ts b/packages/parser/src/intex.ts index 2715602891..5171121992 100644 --- a/packages/parser/src/intex.ts +++ b/packages/parser/src/intex.ts @@ -1 +1 @@ -export * from './schemas'; \ No newline at end of file +export * from './schemas/index.js'; diff --git a/packages/parser/src/schemas/index.ts b/packages/parser/src/schemas/index.ts index 12e53b3a6c..9e994db7dd 100644 --- a/packages/parser/src/schemas/index.ts +++ b/packages/parser/src/schemas/index.ts @@ -1 +1,2 @@ -export * from './dynamodb'; \ No newline at end of file +export * from './dynamodb.js'; +export * from './alb.js'; diff --git a/packages/parser/tests/unit/dynamodb.test.ts b/packages/parser/tests/unit/dynamodb.test.ts index 0801ed93aa..105bbd9ad0 100644 --- a/packages/parser/tests/unit/dynamodb.test.ts +++ b/packages/parser/tests/unit/dynamodb.test.ts @@ -1,66 +1,66 @@ -import {DynamoDBStreamRecordSchema, DynamoDBStreamSchema} from '../../src/schemas/dynamodb'; +import { DynamoDBStreamSchema } from '../../src/schemas/dynamodb'; describe('DynamoDB', () => { - it('should parse a stream of records', () => { - DynamoDBStreamSchema.parse({ - Records: [ - { - eventID: '500c3b0d1c4e9d661540d744ec6270a0', - eventName: 'INSERT', - eventVersion: '1.1', - eventSource: 'aws:dynamodb', - awsRegion: 'eu-west-1', - dynamodb: { - ApproximateCreationDateTime: 1696258322, - Keys: { - id: { - S: '11231', - }, + it('should parse a stream of records', () => { + DynamoDBStreamSchema.parse({ + Records: [ + { + eventID: '500c3b0d1c4e9d661540d744ec6270a0', + eventName: 'INSERT', + eventVersion: '1.1', + eventSource: 'aws:dynamodb', + awsRegion: 'eu-west-1', + dynamodb: { + ApproximateCreationDateTime: 1696258322, + Keys: { + id: { + S: '11231', }, - NewImage: { - name: { - S: 'John Doe', - }, - id: { - S: '11231', - }, + }, + NewImage: { + name: { + S: 'John Doe', + }, + id: { + S: '11231', }, - SequenceNumber: '300000000015609734923', - SizeBytes: 26, - StreamViewType: 'NEW_AND_OLD_IMAGES', }, - eventSourceARN: - 'arn:aws:dynamodb:eu-west-1:770231343013:table/AwsEventsStack-TableCD117FA1-XT5WRCQNWMBQ/stream/2023-10-02T12:16:42.661', + SequenceNumber: '300000000015609734923', + SizeBytes: 26, + StreamViewType: 'NEW_AND_OLD_IMAGES', }, - { - eventID: '500c3b0d1c4e9d661540d744ec6270a0', - eventName: 'INSERT', - eventVersion: '1.1', - eventSource: 'aws:dynamodb', - awsRegion: 'eu-west-1', - dynamodb: { - ApproximateCreationDateTime: 1696258322, - Keys: { - id: { - S: '11231', - }, + eventSourceARN: + 'arn:aws:dynamodb:eu-west-1:770231343013:table/AwsEventsStack-TableCD117FA1-XT5WRCQNWMBQ/stream/2023-10-02T12:16:42.661', + }, + { + eventID: '500c3b0d1c4e9d661540d744ec6270a0', + eventName: 'INSERT', + eventVersion: '1.1', + eventSource: 'aws:dynamodb', + awsRegion: 'eu-west-1', + dynamodb: { + ApproximateCreationDateTime: 1696258322, + Keys: { + id: { + S: '11231', + }, + }, + NewImage: { + name: { + S: 'John Doe', }, - NewImage: { - name: { - S: 'John Doe', - }, - id: { - S: '11231', - }, + id: { + S: '11231', }, - SequenceNumber: '300000000015609734923', - SizeBytes: 26, - StreamViewType: 'NEW_AND_OLD_IMAGES', }, - eventSourceARN: - 'arn:aws:dynamodb:eu-west-1:770231343013:table/AwsEventsStack-TableCD117FA1-XT5WRCQNWMBQ/stream/2023-10-02T12:16:42.661', + SequenceNumber: '300000000015609734923', + SizeBytes: 26, + StreamViewType: 'NEW_AND_OLD_IMAGES', }, - ], - }) + eventSourceARN: + 'arn:aws:dynamodb:eu-west-1:770231343013:table/AwsEventsStack-TableCD117FA1-XT5WRCQNWMBQ/stream/2023-10-02T12:16:42.661', + }, + ], }); -}); \ No newline at end of file + }); +}); diff --git a/packages/parser/tsconfig.json b/packages/parser/tsconfig.json index a62acd2a00..92aecd7c98 100644 --- a/packages/parser/tsconfig.json +++ b/packages/parser/tsconfig.json @@ -1,8 +1,9 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "./lib", + "outDir": "./lib/cjs/", "rootDir": "./src", + "tsBuildInfoFile": ".tsbuildinfo/cjs.json" }, "include": [ "./src/**/*" From 4a66dec568b737129d7de7cf05454c2bae49a183 Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Thu, 2 Nov 2023 11:08:45 +0100 Subject: [PATCH 05/48] add alb --- packages/parser/src/schemas/alb.ts | 8 +++----- packages/parser/src/schemas/dynamodb.ts | 5 ++--- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/packages/parser/src/schemas/alb.ts b/packages/parser/src/schemas/alb.ts index b5cbae4357..24b51c6786 100644 --- a/packages/parser/src/schemas/alb.ts +++ b/packages/parser/src/schemas/alb.ts @@ -1,4 +1,4 @@ -import {z} from 'zod'; +import { z } from 'zod'; const AlbSchema = z.object({ httpMethod: z.string(), @@ -12,8 +12,6 @@ const AlbSchema = z.object({ targetGroupArn: z.string(), }), }), -}) +}); -export { - AlbSchema, -} \ No newline at end of file +export { AlbSchema }; diff --git a/packages/parser/src/schemas/dynamodb.ts b/packages/parser/src/schemas/dynamodb.ts index 4eec244e1f..dd4cb24504 100644 --- a/packages/parser/src/schemas/dynamodb.ts +++ b/packages/parser/src/schemas/dynamodb.ts @@ -1,4 +1,4 @@ -import {z} from 'zod'; +import { z } from 'zod'; const DynamoDBStreamChangeRecordSchema = z.object({ ApproximateCreationDateTime: z.optional(z.number()), @@ -35,10 +35,9 @@ const DynamoDBStreamSchema = z.object({ Records: z.array(DynamoDBStreamRecordSchema), }); - export { DynamoDBStreamSchema, DynamoDBStreamRecordSchema, DynamoDBStreamChangeRecordSchema, UserIdentitySchema, -}; \ No newline at end of file +}; From 6078cb01c4cd111fbb3cb1f14d6cb69b528d7632 Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Fri, 10 Nov 2023 13:51:12 +0100 Subject: [PATCH 06/48] add built-in schema --- .npmignore | 5 +- .../{jest.config.js => jest.config.cjs} | 6 +- packages/parser/package.json | 17 ++- packages/parser/src/{intex.ts => index.ts} | 0 packages/parser/src/schemas/apigw.ts | 55 +++++++ packages/parser/src/schemas/apigwv2.ts | 62 ++++++++ .../schemas/cloudformation-custom-resource.ts | 34 +++++ packages/parser/src/schemas/dynamodb.ts | 24 +-- packages/parser/src/schemas/eventbridge.ts | 16 ++ packages/parser/src/schemas/index.ts | 8 + packages/parser/src/schemas/s3.ts | 142 ++++++++++++++++++ packages/parser/src/schemas/ses.ts | 63 ++++++++ packages/parser/src/schemas/sns.ts | 33 ++++ packages/parser/src/schemas/sqs.ts | 44 ++++++ .../parser/tests/events/activeMQEvent.json | 55 +++++++ packages/parser/tests/events/albEvent.json | 28 ++++ .../events/albEventPathTrailingSlash.json | 28 ++++ .../events/albMultiValueHeadersEvent.json | 35 +++++ .../apiGatewayAuthorizerRequestEvent.json | 69 +++++++++ .../apiGatewayAuthorizerTokenEvent.json | 5 + .../events/apiGatewayAuthorizerV2Event.json | 52 +++++++ .../tests/events/apiGatewayProxyEvent.json | 81 ++++++++++ .../apiGatewayProxyEventAnotherPath.json | 80 ++++++++++ ...apiGatewayProxyEventPathTrailingSlash.json | 80 ++++++++++ .../apiGatewayProxyEventPrincipalId.json | 13 ++ .../apiGatewayProxyEvent_noVersionAuth.json | 75 +++++++++ .../events/apiGatewayProxyOtherEvent.json | 81 ++++++++++ .../tests/events/apiGatewayProxyV2Event.json | 69 +++++++++ ...iGatewayProxyV2EventPathTrailingSlash.json | 69 +++++++++ .../events/apiGatewayProxyV2Event_GET.json | 68 +++++++++ .../events/apiGatewayProxyV2IamEvent.json | 62 ++++++++ ...piGatewayProxyV2LambdaAuthorizerEvent.json | 50 ++++++ .../apiGatewayProxyV2OtherGetEvent.json | 68 +++++++++ ...wayProxyV2SchemaMiddlwareInvalidEvent.json | 69 +++++++++ ...tewayProxyV2SchemaMiddlwareValidEvent.json | 69 +++++++++ ...pigatewayeSchemaMiddlwareInvalidEvent.json | 81 ++++++++++ .../apigatewayeSchemaMiddlwareValidEvent.json | 81 ++++++++++ .../tests/events/appSyncAuthorizerEvent.json | 13 ++ .../events/appSyncAuthorizerResponse.json | 9 ++ .../tests/events/appSyncDirectResolver.json | 74 +++++++++ .../tests/events/appSyncResolverEvent.json | 71 +++++++++ .../awsConfigRuleConfigurationChanged.json | 13 ++ .../awsConfigRuleOversizedConfiguration.json | 12 ++ .../tests/events/awsConfigRuleScheduled.json | 13 ++ .../tests/events/bedrockAgentEvent.json | 16 ++ .../tests/events/bedrockAgentPostEvent.json | 35 +++++ .../events/cloudWatchDashboardEvent.json | 38 +++++ .../tests/events/cloudWatchLogEvent.json | 5 + .../cloudformationCustomResourceCreate.json | 13 ++ .../cloudformationCustomResourceDelete.json | 13 ++ .../cloudformationCustomResourceUpdate.json | 17 +++ .../tests/events/codePipelineEvent.json | 34 +++++ .../tests/events/codePipelineEventData.json | 46 ++++++ .../codePipelineEventEmptyUserParameters.json | 32 ++++ .../codePipelineEventWithEncryptionKey.json | 38 +++++ .../cognitoCreateAuthChallengeEvent.json | 29 ++++ .../events/cognitoCustomMessageEvent.json | 20 +++ .../cognitoDefineAuthChallengeEvent.json | 32 ++++ .../cognitoPostAuthenticationEvent.json | 18 +++ .../events/cognitoPostConfirmationEvent.json | 18 +++ .../events/cognitoPreAuthenticationEvent.json | 20 +++ .../tests/events/cognitoPreSignUpEvent.json | 18 +++ .../cognitoPreTokenGenerationEvent.json | 25 +++ .../events/cognitoUserMigrationEvent.json | 15 ++ ...gnitoVerifyAuthChallengeResponseEvent.json | 28 ++++ .../events/connectContactFlowEventAll.json | 41 +++++ .../events/connectContactFlowEventMin.json | 27 ++++ .../tests/events/dynamoStreamEvent.json | 65 ++++++++ .../parser/tests/events/eventBridgeEvent.json | 17 +++ .../parser/tests/events/kafkaEventMsk.json | 35 +++++ .../tests/events/kafkaEventSelfManaged.json | 34 +++++ .../events/kinesisFirehoseKinesisEvent.json | 32 ++++ .../tests/events/kinesisFirehosePutEvent.json | 17 +++ .../tests/events/kinesisFirehoseSQSEvent.json | 12 ++ .../kinesisStreamCloudWatchLogsEvent.json | 36 +++++ .../tests/events/kinesisStreamEvent.json | 36 +++++ .../events/kinesisStreamEventOneRecord.json | 20 +++ .../tests/events/lambdaFunctionUrlEvent.json | 47 ++++++ ...mbdaFunctionUrlEventPathTrailingSlash.json | 52 +++++++ .../events/lambdaFunctionUrlIAMEvent.json | 52 +++++++ .../parser/tests/events/rabbitMQEvent.json | 51 +++++++ packages/parser/tests/events/s3Event.json | 38 +++++ ...tBridgeNotificationObjectCreatedEvent.json | 28 ++++ ...tBridgeNotificationObjectDeletedEvent.json | 29 ++++ ...tBridgeNotificationObjectExpiredEvent.json | 28 ++++ ...tificationObjectRestoreCompletedEvent.json | 28 ++++ .../tests/events/s3EventDecodedKey.json | 40 +++++ .../tests/events/s3EventDeleteObject.json | 36 +++++ .../parser/tests/events/s3EventGlacier.json | 44 ++++++ .../tests/events/s3ObjectEventIAMUser.json | 30 ++++ .../events/s3ObjectEventTempCredentials.json | 42 ++++++ packages/parser/tests/events/s3SqsEvent.json | 22 +++ .../tests/events/secretsManagerEvent.json | 5 + packages/parser/tests/events/sesEvent.json | 101 +++++++++++++ packages/parser/tests/events/snsEvent.json | 31 ++++ packages/parser/tests/events/snsSqsEvent.json | 20 +++ .../parser/tests/events/snsSqsFifoEvent.json | 23 +++ packages/parser/tests/events/sqsEvent.json | 42 ++++++ .../parser/tests/events/vpcLatticeEvent.json | 15 ++ .../vpcLatticeEventPathTrailingSlash.json | 15 ++ .../vpcLatticeEventV2PathTrailingSlash.json | 30 ++++ .../tests/events/vpcLatticeV2Event.json | 30 ++++ packages/parser/tests/tsconfig.json | 1 + packages/parser/tests/unit/dynamodb.test.ts | 66 -------- .../parser/tests/unit/schema/schema.test.ts | 82 ++++++++++ 105 files changed, 3902 insertions(+), 90 deletions(-) rename packages/parser/{jest.config.js => jest.config.cjs} (82%) rename packages/parser/src/{intex.ts => index.ts} (100%) create mode 100644 packages/parser/src/schemas/apigw.ts create mode 100644 packages/parser/src/schemas/apigwv2.ts create mode 100644 packages/parser/src/schemas/cloudformation-custom-resource.ts create mode 100644 packages/parser/src/schemas/eventbridge.ts create mode 100644 packages/parser/src/schemas/s3.ts create mode 100644 packages/parser/src/schemas/ses.ts create mode 100644 packages/parser/src/schemas/sns.ts create mode 100644 packages/parser/src/schemas/sqs.ts create mode 100644 packages/parser/tests/events/activeMQEvent.json create mode 100644 packages/parser/tests/events/albEvent.json create mode 100644 packages/parser/tests/events/albEventPathTrailingSlash.json create mode 100644 packages/parser/tests/events/albMultiValueHeadersEvent.json create mode 100644 packages/parser/tests/events/apiGatewayAuthorizerRequestEvent.json create mode 100644 packages/parser/tests/events/apiGatewayAuthorizerTokenEvent.json create mode 100644 packages/parser/tests/events/apiGatewayAuthorizerV2Event.json create mode 100644 packages/parser/tests/events/apiGatewayProxyEvent.json create mode 100644 packages/parser/tests/events/apiGatewayProxyEventAnotherPath.json create mode 100644 packages/parser/tests/events/apiGatewayProxyEventPathTrailingSlash.json create mode 100644 packages/parser/tests/events/apiGatewayProxyEventPrincipalId.json create mode 100644 packages/parser/tests/events/apiGatewayProxyEvent_noVersionAuth.json create mode 100644 packages/parser/tests/events/apiGatewayProxyOtherEvent.json create mode 100644 packages/parser/tests/events/apiGatewayProxyV2Event.json create mode 100644 packages/parser/tests/events/apiGatewayProxyV2EventPathTrailingSlash.json create mode 100644 packages/parser/tests/events/apiGatewayProxyV2Event_GET.json create mode 100644 packages/parser/tests/events/apiGatewayProxyV2IamEvent.json create mode 100644 packages/parser/tests/events/apiGatewayProxyV2LambdaAuthorizerEvent.json create mode 100644 packages/parser/tests/events/apiGatewayProxyV2OtherGetEvent.json create mode 100644 packages/parser/tests/events/apiGatewayProxyV2SchemaMiddlwareInvalidEvent.json create mode 100644 packages/parser/tests/events/apiGatewayProxyV2SchemaMiddlwareValidEvent.json create mode 100644 packages/parser/tests/events/apigatewayeSchemaMiddlwareInvalidEvent.json create mode 100644 packages/parser/tests/events/apigatewayeSchemaMiddlwareValidEvent.json create mode 100644 packages/parser/tests/events/appSyncAuthorizerEvent.json create mode 100644 packages/parser/tests/events/appSyncAuthorizerResponse.json create mode 100644 packages/parser/tests/events/appSyncDirectResolver.json create mode 100644 packages/parser/tests/events/appSyncResolverEvent.json create mode 100644 packages/parser/tests/events/awsConfigRuleConfigurationChanged.json create mode 100644 packages/parser/tests/events/awsConfigRuleOversizedConfiguration.json create mode 100644 packages/parser/tests/events/awsConfigRuleScheduled.json create mode 100644 packages/parser/tests/events/bedrockAgentEvent.json create mode 100644 packages/parser/tests/events/bedrockAgentPostEvent.json create mode 100644 packages/parser/tests/events/cloudWatchDashboardEvent.json create mode 100644 packages/parser/tests/events/cloudWatchLogEvent.json create mode 100644 packages/parser/tests/events/cloudformationCustomResourceCreate.json create mode 100644 packages/parser/tests/events/cloudformationCustomResourceDelete.json create mode 100644 packages/parser/tests/events/cloudformationCustomResourceUpdate.json create mode 100644 packages/parser/tests/events/codePipelineEvent.json create mode 100644 packages/parser/tests/events/codePipelineEventData.json create mode 100644 packages/parser/tests/events/codePipelineEventEmptyUserParameters.json create mode 100644 packages/parser/tests/events/codePipelineEventWithEncryptionKey.json create mode 100644 packages/parser/tests/events/cognitoCreateAuthChallengeEvent.json create mode 100644 packages/parser/tests/events/cognitoCustomMessageEvent.json create mode 100644 packages/parser/tests/events/cognitoDefineAuthChallengeEvent.json create mode 100644 packages/parser/tests/events/cognitoPostAuthenticationEvent.json create mode 100644 packages/parser/tests/events/cognitoPostConfirmationEvent.json create mode 100644 packages/parser/tests/events/cognitoPreAuthenticationEvent.json create mode 100644 packages/parser/tests/events/cognitoPreSignUpEvent.json create mode 100644 packages/parser/tests/events/cognitoPreTokenGenerationEvent.json create mode 100644 packages/parser/tests/events/cognitoUserMigrationEvent.json create mode 100644 packages/parser/tests/events/cognitoVerifyAuthChallengeResponseEvent.json create mode 100644 packages/parser/tests/events/connectContactFlowEventAll.json create mode 100644 packages/parser/tests/events/connectContactFlowEventMin.json create mode 100644 packages/parser/tests/events/dynamoStreamEvent.json create mode 100644 packages/parser/tests/events/eventBridgeEvent.json create mode 100644 packages/parser/tests/events/kafkaEventMsk.json create mode 100644 packages/parser/tests/events/kafkaEventSelfManaged.json create mode 100644 packages/parser/tests/events/kinesisFirehoseKinesisEvent.json create mode 100644 packages/parser/tests/events/kinesisFirehosePutEvent.json create mode 100644 packages/parser/tests/events/kinesisFirehoseSQSEvent.json create mode 100644 packages/parser/tests/events/kinesisStreamCloudWatchLogsEvent.json create mode 100644 packages/parser/tests/events/kinesisStreamEvent.json create mode 100644 packages/parser/tests/events/kinesisStreamEventOneRecord.json create mode 100644 packages/parser/tests/events/lambdaFunctionUrlEvent.json create mode 100644 packages/parser/tests/events/lambdaFunctionUrlEventPathTrailingSlash.json create mode 100644 packages/parser/tests/events/lambdaFunctionUrlIAMEvent.json create mode 100644 packages/parser/tests/events/rabbitMQEvent.json create mode 100644 packages/parser/tests/events/s3Event.json create mode 100644 packages/parser/tests/events/s3EventBridgeNotificationObjectCreatedEvent.json create mode 100644 packages/parser/tests/events/s3EventBridgeNotificationObjectDeletedEvent.json create mode 100644 packages/parser/tests/events/s3EventBridgeNotificationObjectExpiredEvent.json create mode 100644 packages/parser/tests/events/s3EventBridgeNotificationObjectRestoreCompletedEvent.json create mode 100644 packages/parser/tests/events/s3EventDecodedKey.json create mode 100644 packages/parser/tests/events/s3EventDeleteObject.json create mode 100644 packages/parser/tests/events/s3EventGlacier.json create mode 100644 packages/parser/tests/events/s3ObjectEventIAMUser.json create mode 100644 packages/parser/tests/events/s3ObjectEventTempCredentials.json create mode 100644 packages/parser/tests/events/s3SqsEvent.json create mode 100644 packages/parser/tests/events/secretsManagerEvent.json create mode 100644 packages/parser/tests/events/sesEvent.json create mode 100644 packages/parser/tests/events/snsEvent.json create mode 100644 packages/parser/tests/events/snsSqsEvent.json create mode 100644 packages/parser/tests/events/snsSqsFifoEvent.json create mode 100644 packages/parser/tests/events/sqsEvent.json create mode 100644 packages/parser/tests/events/vpcLatticeEvent.json create mode 100644 packages/parser/tests/events/vpcLatticeEventPathTrailingSlash.json create mode 100644 packages/parser/tests/events/vpcLatticeEventV2PathTrailingSlash.json create mode 100644 packages/parser/tests/events/vpcLatticeV2Event.json delete mode 100644 packages/parser/tests/unit/dynamodb.test.ts create mode 100644 packages/parser/tests/unit/schema/schema.test.ts diff --git a/.npmignore b/.npmignore index ec8c75c6f9..69d897e7af 100644 --- a/.npmignore +++ b/.npmignore @@ -1,6 +1,7 @@ src tests -jest.config.js +jest.config.cjs +jest.config.cjs tsconfig.json .vscode .github @@ -13,7 +14,7 @@ coverage tslint.json tsconfig.json MakeFile -jest.config.js +jest.config.cjs .npmignore .eslintignore .huskyrc.js diff --git a/packages/parser/jest.config.js b/packages/parser/jest.config.cjs similarity index 82% rename from packages/parser/jest.config.js rename to packages/parser/jest.config.cjs index 6de7d228d2..e1dca130b9 100644 --- a/packages/parser/jest.config.js +++ b/packages/parser/jest.config.cjs @@ -4,11 +4,13 @@ module.exports = { color: 'blue', }, runner: 'groups', + preset: 'ts-jest', moduleNameMapper: { '^(\\.{1,2}/.*)\\.js$': '$1', }, transform: { - '^.+\\.ts?$': 'ts-jest', + '^.+\\.ts?$': ['ts-jest', {tsconfig: './tests/tsconfig.json'}], + }, moduleFileExtensions: ['js', 'ts'], collectCoverageFrom: ['**/src/**/*.ts', '!**/node_modules/**'], @@ -16,7 +18,7 @@ module.exports = { roots: ['/src', '/tests'], testPathIgnorePatterns: ['/node_modules/'], testEnvironment: 'node', - coveragePathIgnorePatterns: ['/node_modules/', 'src/types/index.ts'], + coveragePathIgnorePatterns: ['/node_modules/', '/types'], coverageThreshold: { global: { statements: 100, diff --git a/packages/parser/package.json b/packages/parser/package.json index 38d2551402..ef8a820d7b 100644 --- a/packages/parser/package.json +++ b/packages/parser/package.json @@ -2,6 +2,13 @@ "name": "@aws-lambda-powertools/parser", "version": "0.0.0", "description": "The parser package for the Powertools for AWS Lambda (TypeScript) library.", + "author": { + "name": "Amazon Web Services", + "url": "https://aws.amazon.com" + }, + "publishConfig": { + "access": "restricted" + }, "scripts": { "test": "npm run test:unit", "test:unit": "jest --group=unit --detectOpenHandles --coverage --verbose", @@ -14,10 +21,6 @@ "lint-fix": "eslint --fix --ext .ts,.js --no-error-on-unmatched-pattern .", "prepack": "node ../../.github/scripts/release_patch_package_json.js ." }, - "author": { - "name": "Amazon Web Services", - "url": "https://aws.amazon.com" - }, "lint-staged": { "*.{js,ts}": "npm run lint-fix" }, @@ -32,7 +35,7 @@ }, "import": { "types": "./lib/esm/index.d.ts", - "default": "./lib/esm/index.js" + "default": "./lib/esm/index.js" } } }, @@ -65,9 +68,7 @@ "serverless", "nodejs" ], - "publishConfig": { - "access": "restricted" - }, + "peerDependencies": { "zod": "^3.22.4" } diff --git a/packages/parser/src/intex.ts b/packages/parser/src/index.ts similarity index 100% rename from packages/parser/src/intex.ts rename to packages/parser/src/index.ts diff --git a/packages/parser/src/schemas/apigw.ts b/packages/parser/src/schemas/apigw.ts new file mode 100644 index 0000000000..1ab89ebd27 --- /dev/null +++ b/packages/parser/src/schemas/apigw.ts @@ -0,0 +1,55 @@ +import { z } from 'zod'; + +const APIGatewayCert = z.object({ + clientCertPem: z.string(), + subjectDN: z.string(), + issuerDN: z.string(), + serialNumber: z.string(), + validity: z.object({ + notBefore: z.string(), + notAfter: z.string(), + }), +}); + +const APIGatewayEventRequestContext = z.object({ + accessKey: z.string().optional(), + accountId: z.string().optional(), + apiKey: z.string().optional(), + apiKeyId: z.string().optional(), + caller: z.string().optional(), + cognitoAuthenticationProvider: z.string().optional(), + cognitoAuthenticationType: z.string().optional(), + cognitoIdentityId: z.string().optional(), + cognitoIdentityPoolId: z.string().optional(), + principalOrgId: z.string().optional(), + sourceIp: z.string().ip().optional(), + user: z.string().optional(), + userAgent: z.string().optional(), + userArn: z.string().optional(), + clientCert: APIGatewayCert.optional(), +}); + +const APIGatewayProxyEventSchema = z.object({ + version: z.string().optional(), + resource: z.string(), + path: z.string(), + httpMethod: z.enum([ + 'GET', + 'POST', + 'PUT', + 'PATCH', + 'DELETE', + 'HEAD', + 'OPTIONS', + ]), + headers: z.record(z.string()), + multiValueHeaders: z.record(z.array(z.string())), + queryStringParameters: z.record(z.string()).optional(), + multiValueQueryStringParameters: z.record(z.array(z.string())).optional(), + requestContext: APIGatewayEventRequestContext, + pathParameters: z.record(z.string()).optional().nullish(), + stageVariables: z.record(z.string()).optional().nullish(), + body: z.string().optional(), +}); + +export { APIGatewayProxyEventSchema }; diff --git a/packages/parser/src/schemas/apigwv2.ts b/packages/parser/src/schemas/apigwv2.ts new file mode 100644 index 0000000000..5132c5d051 --- /dev/null +++ b/packages/parser/src/schemas/apigwv2.ts @@ -0,0 +1,62 @@ +import { z } from 'zod'; + +const RequestContextV2Authorizer = z.object({ + jwt: z.object({ + claims: z.record(z.string()), + scopes: z.array(z.string()), + }), + iam: z + .object({ + accessKey: z.string().optional(), + accountId: z.string().optional(), + callerId: z.string().optional(), + principalOrgId: z.string().optional(), + userArn: z.string().optional(), + user: z.string().optional(), + cognitoIdentity: z.object({ + amr: z.array(z.string()), + identityId: z.string(), + identityPoolId: z.string(), + }), + }) + .optional(), +}); + +const RequestContextV2Http = z.object({ + method: z.enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS']), + path: z.string(), + protocol: z.string(), + sourceIp: z.string().ip(), + userAgent: z.string(), +}); + +const RequestContextV2 = z.object({ + accountId: z.string(), + apiId: z.string(), + authorizer: RequestContextV2Authorizer.optional(), + domainName: z.string(), + domainPrefix: z.string(), + http: RequestContextV2Http, + requestId: z.string(), + routeKey: z.string(), + stage: z.string(), + time: z.string(), + timeEpoch: z.number(), +}); + +const APIGatewayProxyEventV2Schema = z.object({ + version: z.string(), + routeKey: z.string(), + rawPath: z.string(), + rawQueryString: z.string(), + cookies: z.array(z.string()).optional(), + headers: z.record(z.string()), + queryStringParameters: z.record(z.string()).optional(), + pathParameters: z.record(z.string()).optional().nullish(), + stageVariables: z.record(z.string()).optional().nullish(), + requestContext: RequestContextV2, + body: z.string().optional(), + isBase64Encoded: z.boolean(), +}); + +export { APIGatewayProxyEventV2Schema }; diff --git a/packages/parser/src/schemas/cloudformation-custom-resource.ts b/packages/parser/src/schemas/cloudformation-custom-resource.ts new file mode 100644 index 0000000000..a03e9d13b7 --- /dev/null +++ b/packages/parser/src/schemas/cloudformation-custom-resource.ts @@ -0,0 +1,34 @@ +import { z } from 'zod'; + +const CloudFormationCustomResourceBaseSchema = z.object({ + ServiceToken: z.string(), + ResponseURL: z.string().url(), + StackId: z.string(), + RequestId: z.string(), + LogicalResourceId: z.string(), + ResourceType: z.string(), + ResourceProperties: z.record(z.any()), +}); + +const CloudFormationCustomResourceCreateSchema = + CloudFormationCustomResourceBaseSchema.extend({ + RequestType: z.literal('Create'), + }); + +const CloudFormationCustomResourceDeleteSchema = + CloudFormationCustomResourceBaseSchema.extend({ + RequestType: z.literal('Delete'), + }); + +const CloudFormationCustomResourceUpdateSchema = + CloudFormationCustomResourceBaseSchema.extend({ + RequestType: z.literal('Update'), + OldResourceProperties: z.record(z.any()), + }); + +export { + CloudFormationCustomResourceCreateSchema, + CloudFormationCustomResourceDeleteSchema, + CloudFormationCustomResourceUpdateSchema, + CloudFormationCustomResourceBaseSchema, +}; diff --git a/packages/parser/src/schemas/dynamodb.ts b/packages/parser/src/schemas/dynamodb.ts index dd4cb24504..011ff85f8a 100644 --- a/packages/parser/src/schemas/dynamodb.ts +++ b/packages/parser/src/schemas/dynamodb.ts @@ -1,10 +1,10 @@ import { z } from 'zod'; -const DynamoDBStreamChangeRecordSchema = z.object({ - ApproximateCreationDateTime: z.optional(z.number()), +const DynamoDBStreamChangeRecord = z.object({ + ApproximateCreationDateTime: z.number().optional(), Keys: z.record(z.string(), z.record(z.string(), z.any())), - NewImage: z.optional(z.record(z.string(), z.any())), - OldImage: z.optional(z.record(z.string(), z.any())), + NewImage: z.record(z.string(), z.any()).optional(), + OldImage: z.record(z.string(), z.any()).optional(), SequenceNumber: z.string(), SizeBytes: z.number(), StreamViewType: z.enum([ @@ -15,29 +15,29 @@ const DynamoDBStreamChangeRecordSchema = z.object({ ]), }); -const UserIdentitySchema = z.object({ +const UserIdentity = z.object({ type: z.enum(['Service']), principalId: z.literal('dynamodb.amazonaws.com'), }); -const DynamoDBStreamRecordSchema = z.object({ +const DynamoDBStreamRecord = z.object({ eventID: z.string(), eventName: z.enum(['INSERT', 'MODIFY', 'REMOVE']), eventVersion: z.string(), eventSource: z.literal('aws:dynamodb'), awsRegion: z.string(), eventSourceARN: z.string(), - dynamodb: DynamoDBStreamChangeRecordSchema, - userIdentity: z.optional(UserIdentitySchema), + dynamodb: DynamoDBStreamChangeRecord, + userIdentity: UserIdentity.optional(), }); const DynamoDBStreamSchema = z.object({ - Records: z.array(DynamoDBStreamRecordSchema), + Records: z.array(DynamoDBStreamRecord), }); export { DynamoDBStreamSchema, - DynamoDBStreamRecordSchema, - DynamoDBStreamChangeRecordSchema, - UserIdentitySchema, + DynamoDBStreamRecord, + DynamoDBStreamChangeRecord, + UserIdentity, }; diff --git a/packages/parser/src/schemas/eventbridge.ts b/packages/parser/src/schemas/eventbridge.ts new file mode 100644 index 0000000000..99f90b7217 --- /dev/null +++ b/packages/parser/src/schemas/eventbridge.ts @@ -0,0 +1,16 @@ +import { z } from 'zod'; + +const EventBridgeSchema = z.object({ + version: z.string(), + id: z.string(), + source: z.string(), + account: z.string(), + time: z.string().datetime(), + region: z.string(), + resources: z.array(z.string()), + detail_type: z.string().optional(), + detail: z.object({}).optional(), + replay_name: z.string().optional(), +}); + +export { EventBridgeSchema }; diff --git a/packages/parser/src/schemas/index.ts b/packages/parser/src/schemas/index.ts index 9e994db7dd..a128fa1b9d 100644 --- a/packages/parser/src/schemas/index.ts +++ b/packages/parser/src/schemas/index.ts @@ -1,2 +1,10 @@ export * from './dynamodb.js'; export * from './alb.js'; +export * from './apigw.js'; +export * from './apigwv2.js'; +export * from './cloudformation-custom-resource.js'; +export * from './eventbridge.js'; +export * from './s3.js'; +export * from './sns.js'; +export * from './sqs.js'; +export * from './ses.js'; diff --git a/packages/parser/src/schemas/s3.ts b/packages/parser/src/schemas/s3.ts new file mode 100644 index 0000000000..614ccddade --- /dev/null +++ b/packages/parser/src/schemas/s3.ts @@ -0,0 +1,142 @@ +import { z } from 'zod'; + +const S3Identity = z.object({ + principalId: z.string(), +}); + +const S3RequestParameters = z.object({ + sourceIPAddress: z.string().ip(), +}); + +const S3ResponseElements = z.object({ + 'x-amz-request-id': z.string(), + 'x-amz-id-2': z.string(), +}); + +const S3Message = z.object({ + configurationId: z.string(), + object: z.object({ + key: z.string(), + size: z.number(), + eTag: z.string(), + sequencer: z.string(), + versionId: z.optional(z.string()), + }), + bucket: z.object({ + name: z.string(), + ownerIdentity: S3Identity, + arn: z.string(), + }), +}); + +const S3EventRecordGlacierEventData = z.object({ + restoreEventData: z.object({ + lifecycleRestorationExpiryTime: z.string(), + lifecycleRestoreStorageClass: z.string(), + }), +}); + +const S3Record = z.object({ + eventVersion: z.string(), + eventSource: z.literal('aws:s3'), + awsRegion: z.string(), + eventTime: z.string(), + eventName: z.string(), + userIdentity: S3Identity, + requestParameters: S3RequestParameters, + responseElements: S3ResponseElements, + s3: S3Message, + glacierEventData: z.optional(S3EventRecordGlacierEventData), +}); + +const S3EventNotificationEventBridgeSchema = z.object({ + version: z.string(), + bucket: z.object({ + name: z.string(), + }), + object: z.object({ + key: z.string(), + size: z.number().nonnegative().optional(), + etag: z.string(), + 'version-id': z.string(), + sequencer: z.string().optional(), + }), + 'request-id': z.string(), + requester: z.string(), + 'source-ip-address': z.string().ip(), + reason: z.string().optional(), + 'deletion-type': z.string().optional(), + 'restore-expiry-time': z.string().optional(), + 'source-storage-class': z.string().optional(), + 'destination-storage-class': z.string().optional(), + 'destination-access-tier': z.string().optional(), +}); + +const S3Schema = z.object({ + Records: z.array(S3Record), +}); + +const S3SqsEventNotificationRecordSchema = z.object({ + body: z.string(), +}); + +const S3SqsEventNotificationSchema = z.object({ + Records: z.array(S3SqsEventNotificationRecordSchema), +}); + +const S3ObjectContext = z.object({ + inputS3Url: z.string(), + outputRoute: z.string(), + outputToken: z.string(), +}); + +const S3ObjectConfiguration = z.object({ + accessPointArn: z.string(), + supportingAccessPointArn: z.string(), + payload: z.union([z.string(), z.object({})]), +}); + +const S3ObjectUserRequest = z.object({ + url: z.string(), + headers: z.record(z.string(), z.string()), +}); + +const S3ObjectSessionContext = z.object({ + sessionIssuer: z.object({ + type: z.string(), + userName: z.string().optional(), + principalId: z.string(), + arn: z.string(), + accountId: z.string(), + }), + attributes: z.object({ + creationDate: z.string(), + mfaAuthenticated: z.string(), + }), +}); + +const S3ObjectUserIdentity = z.object({ + type: z.string(), + accountId: z.string(), + accessKeyId: z.string(), + userName: z.string().optional(), + principalId: z.string(), + arn: z.string(), + sessionContext: S3ObjectSessionContext, +}); + +const S3ObjectLambdaEventSchema = z.object({ + xAmzRequestId: z.string(), + getObjectContext: S3ObjectContext, + configurationId: S3ObjectConfiguration, + userRequest: S3ObjectUserRequest, + userIdentity: S3ObjectUserIdentity, + protocolVersion: z.string(), +}); + +export { + S3Schema, + S3EventNotificationEventBridgeSchema, + S3SqsEventNotificationSchema, + S3ObjectLambdaEventSchema, +}; diff --git a/packages/parser/src/schemas/ses.ts b/packages/parser/src/schemas/ses.ts new file mode 100644 index 0000000000..96ca79388a --- /dev/null +++ b/packages/parser/src/schemas/ses.ts @@ -0,0 +1,63 @@ +import { z } from 'zod'; + +const SesReceiptVerdict = z.object({ + status: z.enum(['PASS', 'FAIL', 'GRAY', 'PROCESSING_FAILED']), +}); + +const SesReceipt = z.object({ + timestamp: z.string().datetime(), + processingTimeMillis: z.number().int().positive(), + recipients: z.array(z.string()), + spamVerdict: SesReceiptVerdict.optional(), + virusVerdict: SesReceiptVerdict.optional(), + spfVerdict: SesReceiptVerdict.optional(), + dmarcVerdict: SesReceiptVerdict.optional(), + action: z.object({ + type: z.enum(['Lambda']), + invocationType: z.literal('Event'), + functionArn: z.string(), + }), +}); + +const SesMail = z.object({ + timestamp: z.string().datetime(), + source: z.string(), + messageId: z.string(), + destination: z.array(z.string()), + headersTruncated: z.boolean(), + headers: z.array( + z.object({ + name: z.string(), + value: z.string(), + }) + ), + commonHeaders: z.object({ + from: z.array(z.string()), + to: z.array(z.string()), + cc: z.array(z.string()).optional(), + bcc: z.array(z.string()).optional(), + sender: z.array(z.string()).optional(), + 'reply-to': z.array(z.string()).optional(), + returnPath: z.string(), + messageId: z.string(), + date: z.string(), + subject: z.string(), + }), +}); + +const SesMessage = z.object({ + mail: SesMail, + receipt: SesReceipt, +}); + +const SesRecordSchema = z.object({ + eventSource: z.literal('aws:ses'), + eventVersion: z.string(), + ses: SesMessage, +}); + +const SesSchema = z.object({ + Records: z.array(SesRecordSchema), +}); + +export { SesSchema, SesRecordSchema }; diff --git a/packages/parser/src/schemas/sns.ts b/packages/parser/src/schemas/sns.ts new file mode 100644 index 0000000000..98d6752c99 --- /dev/null +++ b/packages/parser/src/schemas/sns.ts @@ -0,0 +1,33 @@ +import { z } from 'zod'; + +const SnsMsgAttribute = z.object({ + Type: z.string(), + Value: z.string(), +}); + +const SnsNotificationSchema = z.object({ + Subject: z.string().optional(), + TopicArn: z.string(), + UnsubscribeUrl: z.string().url(), + Type: z.literal('Notification'), + MessageAttributes: z.record(z.string(), SnsMsgAttribute).optional(), + Message: z.union([z.string(), z.object({})]), + MessageId: z.string(), + Signature: z.string().optional(), + SignatureVersion: z.string().optional(), + SigningCertUrl: z.string().url().optional(), + Timestamp: z.string(), +}); + +const SnsRecordSchema = z.object({ + EventSource: z.literal('aws:sns'), + EventVersion: z.string(), + EventSubscriptionArn: z.string(), + Sns: SnsNotificationSchema, +}); + +const SnsSchema = z.object({ + Records: z.array(SnsRecordSchema), +}); + +export { SnsSchema, SnsRecordSchema, SnsNotificationSchema, SnsMsgAttribute }; diff --git a/packages/parser/src/schemas/sqs.ts b/packages/parser/src/schemas/sqs.ts new file mode 100644 index 0000000000..a10f2bfb46 --- /dev/null +++ b/packages/parser/src/schemas/sqs.ts @@ -0,0 +1,44 @@ +import { z } from 'zod'; + +const SqsMsgAttributeSchema = z.object({ + stringValue: z.string().optional(), + binaryValue: z.string().optional(), + stringListValues: z.array(z.string()).optional(), + binaryListValues: z.array(z.string()).optional(), + dataType: z.string(), +}); + +const SqsAttributeSchema = z.object({ + ApproximateReceiveCount: z.string(), + ApproximateFirstReceiveTimestamp: z.string(), + MessageDeduplicationId: z.string().optional(), + MessageGroupId: z.string().optional(), + SenderId: z.string(), + SentTimestamp: z.string(), + SequenceNumber: z.string().optional(), + AWSTraceHeader: z.string().optional(), +}); + +const SqsRecordSchema = z.object({ + messageId: z.string(), + receiptHandle: z.string(), + body: z.string(), + attributes: SqsAttributeSchema, + messageAttributes: z.record(z.string(), SqsMsgAttributeSchema), + md5OfBody: z.string(), + md5OfMessageAttributes: z.string().optional(), + eventSource: z.literal('aws:sqs'), + eventSourceARN: z.string(), + awsRegion: z.string(), +}); + +const SqsSchema = z.object({ + Records: z.array(SqsRecordSchema), +}); + +export { + SqsSchema, + SqsRecordSchema, + SqsAttributeSchema, + SqsMsgAttributeSchema, +}; diff --git a/packages/parser/tests/events/activeMQEvent.json b/packages/parser/tests/events/activeMQEvent.json new file mode 100644 index 0000000000..57417cfd22 --- /dev/null +++ b/packages/parser/tests/events/activeMQEvent.json @@ -0,0 +1,55 @@ +{ + "eventSource": "aws:amq", + "eventSourceArn": "arn:aws:mq:us-west-2:112556298976:broker:test:b-9bcfa592-423a-4942-879d-eb284b418fc8", + "messages": [ + { + "messageID": "ID:b-9bcfa592-423a-4942-879d-eb284b418fc8-1.mq.us-west-2.amazonaws.com-37557-1234520418293-4:1:1:1:1", + "messageType": "jms/text-message", + "data": "QUJDOkFBQUE=", + "connectionId": "myJMSCoID", + "redelivered": false, + "destination": { + "physicalname": "testQueue" + }, + "timestamp": 1598827811958, + "brokerInTime": 1598827811958, + "brokerOutTime": 1598827811959, + "properties": { + "testKey": "testValue" + } + }, + { + "messageID": "ID:b-9bcfa592-423a-4942-879d-eb284b418fc8-1.mq.us-west-2.amazonaws.com-37557-1234520418293-4:1:1:1:1", + "messageType": "jms/text-message", + "data": "eyJ0aW1lb3V0IjowLCJkYXRhIjoiQ1pybWYwR3c4T3Y0YnFMUXhENEUifQ==", + "connectionId": "myJMSCoID2", + "redelivered": false, + "destination": { + "physicalname": "testQueue" + }, + "timestamp": 1598827811958, + "brokerInTime": 1598827811958, + "brokerOutTime": 1598827811959, + "properties": { + "testKey": "testValue" + } + + }, + { + "messageID": "ID:b-9bcfa592-423a-4942-879d-eb284b418fc8-1.mq.us-west-2.amazonaws.com-37557-1234520418293-4:1:1:1:1", + "messageType": "jms/bytes-message", + "data": "3DTOOW7crj51prgVLQaGQ82S48k=", + "connectionId": "myJMSCoID1", + "persistent": false, + "destination": { + "physicalname": "testQueue" + }, + "timestamp": 1598827811958, + "brokerInTime": 1598827811958, + "brokerOutTime": 1598827811959, + "properties": { + "testKey": "testValue" + } + } + ] +} diff --git a/packages/parser/tests/events/albEvent.json b/packages/parser/tests/events/albEvent.json new file mode 100644 index 0000000000..9328cb39e1 --- /dev/null +++ b/packages/parser/tests/events/albEvent.json @@ -0,0 +1,28 @@ +{ + "requestContext": { + "elb": { + "targetGroupArn": "arn:aws:elasticloadbalancing:us-east-2:123456789012:targetgroup/lambda-279XGJDqGZ5rsrHC2Fjr/49e9d65c45c6791a" + } + }, + "httpMethod": "GET", + "path": "/lambda", + "queryStringParameters": { + "query": "1234ABCD" + }, + "headers": { + "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8", + "accept-encoding": "gzip", + "accept-language": "en-US,en;q=0.9", + "connection": "keep-alive", + "host": "lambda-alb-123578498.us-east-2.elb.amazonaws.com", + "upgrade-insecure-requests": "1", + "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36", + "x-amzn-trace-id": "Root=1-5c536348-3d683b8b04734faae651f476", + "x-forwarded-for": "72.12.164.125", + "x-forwarded-port": "80", + "x-forwarded-proto": "http", + "x-imforwards": "20" + }, + "body": "Test", + "isBase64Encoded": false +} diff --git a/packages/parser/tests/events/albEventPathTrailingSlash.json b/packages/parser/tests/events/albEventPathTrailingSlash.json new file mode 100644 index 0000000000..c517a3f6b0 --- /dev/null +++ b/packages/parser/tests/events/albEventPathTrailingSlash.json @@ -0,0 +1,28 @@ +{ + "requestContext": { + "elb": { + "targetGroupArn": "arn:aws:elasticloadbalancing:us-east-2:123456789012:targetgroup/lambda-279XGJDqGZ5rsrHC2Fjr/49e9d65c45c6791a" + } + }, + "httpMethod": "GET", + "path": "/lambda/", + "queryStringParameters": { + "query": "1234ABCD" + }, + "headers": { + "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8", + "accept-encoding": "gzip", + "accept-language": "en-US,en;q=0.9", + "connection": "keep-alive", + "host": "lambda-alb-123578498.us-east-2.elb.amazonaws.com", + "upgrade-insecure-requests": "1", + "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36", + "x-amzn-trace-id": "Root=1-5c536348-3d683b8b04734faae651f476", + "x-forwarded-for": "72.12.164.125", + "x-forwarded-port": "80", + "x-forwarded-proto": "http", + "x-imforwards": "20" + }, + "body": "Test", + "isBase64Encoded": false + } \ No newline at end of file diff --git a/packages/parser/tests/events/albMultiValueHeadersEvent.json b/packages/parser/tests/events/albMultiValueHeadersEvent.json new file mode 100644 index 0000000000..6b34709605 --- /dev/null +++ b/packages/parser/tests/events/albMultiValueHeadersEvent.json @@ -0,0 +1,35 @@ +{ + "requestContext": { + "elb": { + "targetGroupArn": "arn:aws:elasticloadbalancing:eu-central-1:1234567890:targetgroup/alb-c-Targe-11GDXTPQ7663S/804a67588bfdc10f" + } + }, + "httpMethod": "GET", + "path": "/todos", + "multiValueQueryStringParameters": {}, + "multiValueHeaders": { + "accept": [ + "*/*" + ], + "host": [ + "alb-c-LoadB-14POFKYCLBNSF-1815800096.eu-central-1.elb.amazonaws.com" + ], + "user-agent": [ + "curl/7.79.1" + ], + "x-amzn-trace-id": [ + "Root=1-62fa9327-21cdd4da4c6db451490a5fb7" + ], + "x-forwarded-for": [ + "123.123.123.123" + ], + "x-forwarded-port": [ + "80" + ], + "x-forwarded-proto": [ + "http" + ] + }, + "body": "", + "isBase64Encoded": false +} diff --git a/packages/parser/tests/events/apiGatewayAuthorizerRequestEvent.json b/packages/parser/tests/events/apiGatewayAuthorizerRequestEvent.json new file mode 100644 index 0000000000..d8dfe3fecf --- /dev/null +++ b/packages/parser/tests/events/apiGatewayAuthorizerRequestEvent.json @@ -0,0 +1,69 @@ +{ + "version": "1.0", + "type": "REQUEST", + "methodArn": "arn:aws:execute-api:us-east-1:123456789012:abcdef123/test/GET/request", + "identitySource": "user1,123", + "authorizationToken": "user1,123", + "resource": "/request", + "path": "/request", + "httpMethod": "GET", + "headers": { + "X-AMZ-Date": "20170718T062915Z", + "Accept": "*/*", + "HeaderAuth1": "headerValue1", + "CloudFront-Viewer-Country": "US", + "CloudFront-Forwarded-Proto": "https", + "CloudFront-Is-Tablet-Viewer": "false", + "CloudFront-Is-Mobile-Viewer": "false", + "User-Agent": "..." + }, + "queryStringParameters": { + "QueryString1": "queryValue1" + }, + "pathParameters": {}, + "stageVariables": { + "StageVar1": "stageValue1" + }, + "requestContext": { + "accountId": "123456789012", + "apiId": "abcdef123", + "domainName": "3npb9j1tlk.execute-api.us-west-1.amazonaws.com", + "domainPrefix": "3npb9j1tlk", + "extendedRequestId": "EXqgWgXxSK4EJug=", + "httpMethod": "GET", + "identity": { + "accessKey": null, + "accountId": null, + "caller": null, + "cognitoAmr": null, + "cognitoAuthenticationProvider": null, + "cognitoAuthenticationType": null, + "cognitoIdentityId": null, + "cognitoIdentityPoolId": null, + "principalOrgId": null, + "apiKey": "...", + "sourceIp": "...", + "user": null, + "userAgent": "PostmanRuntime/7.28.3", + "userArn": null, + "clientCert": { + "clientCertPem": "CERT_CONTENT", + "subjectDN": "www.example.com", + "issuerDN": "Example issuer", + "serialNumber": "a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1", + "validity": { + "notBefore": "May 28 12:30:02 2019 GMT", + "notAfter": "Aug 5 09:36:04 2021 GMT" + } + } + }, + "path": "/request", + "protocol": "HTTP/1.1", + "requestId": "EXqgWgXxSK4EJug=", + "requestTime": "20/Aug/2021:14:36:50 +0000", + "requestTimeEpoch": 1629470210043, + "resourceId": "ANY /request", + "resourcePath": "/request", + "stage": "test" + } +} diff --git a/packages/parser/tests/events/apiGatewayAuthorizerTokenEvent.json b/packages/parser/tests/events/apiGatewayAuthorizerTokenEvent.json new file mode 100644 index 0000000000..f30f360f6d --- /dev/null +++ b/packages/parser/tests/events/apiGatewayAuthorizerTokenEvent.json @@ -0,0 +1,5 @@ +{ + "type": "TOKEN", + "authorizationToken": "allow", + "methodArn": "arn:aws:execute-api:us-west-2:123456789012:ymy8tbxw7b/*/GET/" +} diff --git a/packages/parser/tests/events/apiGatewayAuthorizerV2Event.json b/packages/parser/tests/events/apiGatewayAuthorizerV2Event.json new file mode 100644 index 0000000000..f0528080c9 --- /dev/null +++ b/packages/parser/tests/events/apiGatewayAuthorizerV2Event.json @@ -0,0 +1,52 @@ +{ + "version": "2.0", + "type": "REQUEST", + "routeArn": "arn:aws:execute-api:us-east-1:123456789012:abcdef123/test/GET/request", + "identitySource": ["user1", "123"], + "routeKey": "GET /merchants", + "rawPath": "/merchants", + "rawQueryString": "parameter1=value1¶meter1=value2¶meter2=value", + "cookies": ["cookie1", "cookie2"], + "headers": { + "x-amzn-trace-id": "Root=1-611cc4a7-0746ebee281cfd967db97b64", + "Header1": "value1", + "Header2": "value2", + "Authorization": "value" + }, + "queryStringParameters": { + "parameter1": "value1,value2", + "parameter2": "value" + }, + "requestContext": { + "accountId": "123456789012", + "apiId": "api-id", + "authentication": { + "clientCert": { + "clientCertPem": "CERT_CONTENT", + "subjectDN": "www.example.com", + "issuerDN": "Example issuer", + "serialNumber": "a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1", + "validity": { + "notBefore": "May 28 12:30:02 2019 GMT", + "notAfter": "Aug 5 09:36:04 2021 GMT" + } + } + }, + "domainName": "id.execute-api.us-east-1.amazonaws.com", + "domainPrefix": "id", + "http": { + "method": "POST", + "path": "/merchants", + "protocol": "HTTP/1.1", + "sourceIp": "IP", + "userAgent": "agent" + }, + "requestId": "id", + "routeKey": "GET /merchants", + "stage": "$default", + "time": "12/Mar/2020:19:03:58 +0000", + "timeEpoch": 1583348638390 + }, + "pathParameters": { "parameter1": "value1" }, + "stageVariables": { "stageVariable1": "value1", "stageVariable2": "value2" } +} diff --git a/packages/parser/tests/events/apiGatewayProxyEvent.json b/packages/parser/tests/events/apiGatewayProxyEvent.json new file mode 100644 index 0000000000..3f095e28e4 --- /dev/null +++ b/packages/parser/tests/events/apiGatewayProxyEvent.json @@ -0,0 +1,81 @@ +{ + "version": "1.0", + "resource": "/my/path", + "path": "/my/path", + "httpMethod": "GET", + "headers": { + "Header1": "value1", + "Header2": "value2", + "Origin": "https://aws.amazon.com" + }, + "multiValueHeaders": { + "Header1": [ + "value1" + ], + "Header2": [ + "value1", + "value2" + ] + }, + "queryStringParameters": { + "parameter1": "value1", + "parameter2": "value" + }, + "multiValueQueryStringParameters": { + "parameter1": [ + "value1", + "value2" + ], + "parameter2": [ + "value" + ] + }, + "requestContext": { + "accountId": "123456789012", + "apiId": "id", + "authorizer": { + "claims": null, + "scopes": null + }, + "domainName": "id.execute-api.us-east-1.amazonaws.com", + "domainPrefix": "id", + "extendedRequestId": "request-id", + "httpMethod": "GET", + "identity": { + "accessKey": null, + "accountId": null, + "caller": null, + "cognitoAuthenticationProvider": null, + "cognitoAuthenticationType": null, + "cognitoIdentityId": null, + "cognitoIdentityPoolId": null, + "principalOrgId": null, + "sourceIp": "192.168.0.1/32", + "user": null, + "userAgent": "user-agent", + "userArn": null, + "clientCert": { + "clientCertPem": "CERT_CONTENT", + "subjectDN": "www.example.com", + "issuerDN": "Example issuer", + "serialNumber": "a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1", + "validity": { + "notBefore": "May 28 12:30:02 2019 GMT", + "notAfter": "Aug 5 09:36:04 2021 GMT" + } + } + }, + "path": "/my/path", + "protocol": "HTTP/1.1", + "requestId": "id=", + "requestTime": "04/Mar/2020:19:15:17 +0000", + "requestTimeEpoch": 1583349317135, + "resourceId": null, + "resourcePath": "/my/path", + "stage": "$default" + }, + "pathParameters": null, + "stageVariables": null, + "body": "Hello from Lambda!", + "isBase64Encoded": false +} \ No newline at end of file diff --git a/packages/parser/tests/events/apiGatewayProxyEventAnotherPath.json b/packages/parser/tests/events/apiGatewayProxyEventAnotherPath.json new file mode 100644 index 0000000000..d8f43e4626 --- /dev/null +++ b/packages/parser/tests/events/apiGatewayProxyEventAnotherPath.json @@ -0,0 +1,80 @@ +{ + "version": "1.0", + "resource": "/my/anotherPath", + "path": "/my/anotherPath", + "httpMethod": "GET", + "headers": { + "Header1": "value1", + "Header2": "value2" + }, + "multiValueHeaders": { + "Header1": [ + "value1" + ], + "Header2": [ + "value1", + "value2" + ] + }, + "queryStringParameters": { + "parameter1": "value1", + "parameter2": "value" + }, + "multiValueQueryStringParameters": { + "parameter1": [ + "value1", + "value2" + ], + "parameter2": [ + "value" + ] + }, + "requestContext": { + "accountId": "123456789012", + "apiId": "id", + "authorizer": { + "claims": null, + "scopes": null + }, + "domainName": "id.execute-api.us-east-1.amazonaws.com", + "domainPrefix": "id", + "extendedRequestId": "request-id", + "httpMethod": "GET", + "identity": { + "accessKey": null, + "accountId": null, + "caller": null, + "cognitoAuthenticationProvider": null, + "cognitoAuthenticationType": null, + "cognitoIdentityId": null, + "cognitoIdentityPoolId": null, + "principalOrgId": null, + "sourceIp": "192.168.0.1/32", + "user": null, + "userAgent": "user-agent", + "userArn": null, + "clientCert": { + "clientCertPem": "CERT_CONTENT", + "subjectDN": "www.example.com", + "issuerDN": "Example issuer", + "serialNumber": "a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1", + "validity": { + "notBefore": "May 28 12:30:02 2019 GMT", + "notAfter": "Aug 5 09:36:04 2021 GMT" + } + } + }, + "path": "/my/anotherPath", + "protocol": "HTTP/1.1", + "requestId": "id=", + "requestTime": "04/Mar/2020:19:15:17 +0000", + "requestTimeEpoch": 1583349317135, + "resourceId": null, + "resourcePath": "/my/anotherPath", + "stage": "$default" + }, + "pathParameters": null, + "stageVariables": null, + "body": "Hello from Lambda!", + "isBase64Encoded": true +} \ No newline at end of file diff --git a/packages/parser/tests/events/apiGatewayProxyEventPathTrailingSlash.json b/packages/parser/tests/events/apiGatewayProxyEventPathTrailingSlash.json new file mode 100644 index 0000000000..8a321d96c8 --- /dev/null +++ b/packages/parser/tests/events/apiGatewayProxyEventPathTrailingSlash.json @@ -0,0 +1,80 @@ +{ + "version": "1.0", + "resource": "/my/path", + "path": "/my/path/", + "httpMethod": "GET", + "headers": { + "Header1": "value1", + "Header2": "value2" + }, + "multiValueHeaders": { + "Header1": [ + "value1" + ], + "Header2": [ + "value1", + "value2" + ] + }, + "queryStringParameters": { + "parameter1": "value1", + "parameter2": "value" + }, + "multiValueQueryStringParameters": { + "parameter1": [ + "value1", + "value2" + ], + "parameter2": [ + "value" + ] + }, + "requestContext": { + "accountId": "123456789012", + "apiId": "id", + "authorizer": { + "claims": null, + "scopes": null + }, + "domainName": "id.execute-api.us-east-1.amazonaws.com", + "domainPrefix": "id", + "extendedRequestId": "request-id", + "httpMethod": "GET", + "identity": { + "accessKey": null, + "accountId": null, + "caller": null, + "cognitoAuthenticationProvider": null, + "cognitoAuthenticationType": null, + "cognitoIdentityId": null, + "cognitoIdentityPoolId": null, + "principalOrgId": null, + "sourceIp": "192.168.0.1/32", + "user": null, + "userAgent": "user-agent", + "userArn": null, + "clientCert": { + "clientCertPem": "CERT_CONTENT", + "subjectDN": "www.example.com", + "issuerDN": "Example issuer", + "serialNumber": "a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1", + "validity": { + "notBefore": "May 28 12:30:02 2019 GMT", + "notAfter": "Aug 5 09:36:04 2021 GMT" + } + } + }, + "path": "/my/path", + "protocol": "HTTP/1.1", + "requestId": "id=", + "requestTime": "04/Mar/2020:19:15:17 +0000", + "requestTimeEpoch": 1583349317135, + "resourceId": null, + "resourcePath": "/my/path", + "stage": "$default" + }, + "pathParameters": null, + "stageVariables": null, + "body": "Hello from Lambda!", + "isBase64Encoded": true + } \ No newline at end of file diff --git a/packages/parser/tests/events/apiGatewayProxyEventPrincipalId.json b/packages/parser/tests/events/apiGatewayProxyEventPrincipalId.json new file mode 100644 index 0000000000..f18a2a44bb --- /dev/null +++ b/packages/parser/tests/events/apiGatewayProxyEventPrincipalId.json @@ -0,0 +1,13 @@ +{ + "resource": "/trip", + "path": "/trip", + "httpMethod": "POST", + "requestContext": { + "requestId": "34972478-2843-4ced-a657-253108738274", + "authorizer": { + "user_id": "fake_username", + "principalId": "fake", + "integrationLatency": 451 + } + } +} diff --git a/packages/parser/tests/events/apiGatewayProxyEvent_noVersionAuth.json b/packages/parser/tests/events/apiGatewayProxyEvent_noVersionAuth.json new file mode 100644 index 0000000000..055301f8f1 --- /dev/null +++ b/packages/parser/tests/events/apiGatewayProxyEvent_noVersionAuth.json @@ -0,0 +1,75 @@ +{ + "resource": "/my/path", + "path": "/my/path", + "httpMethod": "GET", + "headers": { + "Header1": "value1", + "Header2": "value2" + }, + "multiValueHeaders": { + "Header1": [ + "value1" + ], + "Header2": [ + "value1", + "value2" + ] + }, + "queryStringParameters": { + "parameter1": "value1", + "parameter2": "value" + }, + "multiValueQueryStringParameters": { + "parameter1": [ + "value1", + "value2" + ], + "parameter2": [ + "value" + ] + }, + "requestContext": { + "accountId": "123456789012", + "apiId": "id", + "domainName": "id.execute-api.us-east-1.amazonaws.com", + "domainPrefix": "id", + "extendedRequestId": "request-id", + "httpMethod": "GET", + "identity": { + "accessKey": null, + "accountId": null, + "caller": null, + "cognitoAuthenticationProvider": null, + "cognitoAuthenticationType": null, + "cognitoIdentityId": null, + "cognitoIdentityPoolId": null, + "principalOrgId": null, + "sourceIp": "192.168.0.1/32", + "user": null, + "userAgent": "user-agent", + "userArn": null, + "clientCert": { + "clientCertPem": "CERT_CONTENT", + "subjectDN": "www.example.com", + "issuerDN": "Example issuer", + "serialNumber": "a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1", + "validity": { + "notBefore": "May 28 12:30:02 2019 GMT", + "notAfter": "Aug 5 09:36:04 2021 GMT" + } + } + }, + "path": "/my/path", + "protocol": "HTTP/1.1", + "requestId": "id=", + "requestTime": "04/Mar/2020:19:15:17 +0000", + "requestTimeEpoch": 1583349317135, + "resourceId": null, + "resourcePath": "/my/path", + "stage": "$default" + }, + "pathParameters": null, + "stageVariables": null, + "body": "Hello from Lambda!", + "isBase64Encoded": true +} diff --git a/packages/parser/tests/events/apiGatewayProxyOtherEvent.json b/packages/parser/tests/events/apiGatewayProxyOtherEvent.json new file mode 100644 index 0000000000..5b9d09844a --- /dev/null +++ b/packages/parser/tests/events/apiGatewayProxyOtherEvent.json @@ -0,0 +1,81 @@ +{ + "version": "1.0", + "resource": "/other/path", + "path": "/other/path", + "httpMethod": "GET", + "headers": { + "Header1": "value1", + "Header2": "value2", + "Origin": "https://aws.amazon.com" + }, + "multiValueHeaders": { + "Header1": [ + "value1" + ], + "Header2": [ + "value1", + "value2" + ] + }, + "queryStringParameters": { + "parameter1": "value1", + "parameter2": "value" + }, + "multiValueQueryStringParameters": { + "parameter1": [ + "value1", + "value2" + ], + "parameter2": [ + "value" + ] + }, + "requestContext": { + "accountId": "123456789012", + "apiId": "id", + "authorizer": { + "claims": null, + "scopes": null + }, + "domainName": "id.execute-api.us-east-1.amazonaws.com", + "domainPrefix": "id", + "extendedRequestId": "request-id", + "httpMethod": "GET", + "identity": { + "accessKey": null, + "accountId": null, + "caller": null, + "cognitoAuthenticationProvider": null, + "cognitoAuthenticationType": null, + "cognitoIdentityId": null, + "cognitoIdentityPoolId": null, + "principalOrgId": null, + "sourceIp": "192.168.0.1/32", + "user": null, + "userAgent": "user-agent", + "userArn": null, + "clientCert": { + "clientCertPem": "CERT_CONTENT", + "subjectDN": "www.example.com", + "issuerDN": "Example issuer", + "serialNumber": "a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1", + "validity": { + "notBefore": "May 28 12:30:02 2019 GMT", + "notAfter": "Aug 5 09:36:04 2021 GMT" + } + } + }, + "path": "/other/path", + "protocol": "HTTP/1.1", + "requestId": "id=", + "requestTime": "04/Mar/2020:19:15:17 +0000", + "requestTimeEpoch": 1583349317135, + "resourceId": null, + "resourcePath": "/other/path", + "stage": "$default" + }, + "pathParameters": null, + "stageVariables": null, + "body": "Hello from Lambda!", + "isBase64Encoded": false +} diff --git a/packages/parser/tests/events/apiGatewayProxyV2Event.json b/packages/parser/tests/events/apiGatewayProxyV2Event.json new file mode 100644 index 0000000000..ac287d560a --- /dev/null +++ b/packages/parser/tests/events/apiGatewayProxyV2Event.json @@ -0,0 +1,69 @@ +{ + "version": "2.0", + "routeKey": "$default", + "rawPath": "/my/path", + "rawQueryString": "parameter1=value1¶meter1=value2¶meter2=value", + "cookies": [ + "cookie1", + "cookie2" + ], + "headers": { + "Header1": "value1", + "Header2": "value1,value2" + }, + "queryStringParameters": { + "parameter1": "value1,value2", + "parameter2": "value" + }, + "requestContext": { + "accountId": "123456789012", + "apiId": "api-id", + "authentication": { + "clientCert": { + "clientCertPem": "CERT_CONTENT", + "subjectDN": "www.example.com", + "issuerDN": "Example issuer", + "serialNumber": "a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1", + "validity": { + "notBefore": "May 28 12:30:02 2019 GMT", + "notAfter": "Aug 5 09:36:04 2021 GMT" + } + } + }, + "authorizer": { + "jwt": { + "claims": { + "claim1": "value1", + "claim2": "value2" + }, + "scopes": [ + "scope1", + "scope2" + ] + } + }, + "domainName": "id.execute-api.us-east-1.amazonaws.com", + "domainPrefix": "id", + "http": { + "method": "POST", + "path": "/my/path", + "protocol": "HTTP/1.1", + "sourceIp": "192.168.0.1", + "userAgent": "agent" + }, + "requestId": "id", + "routeKey": "$default", + "stage": "$default", + "time": "12/Mar/2020:19:03:58 +0000", + "timeEpoch": 1583348638390 + }, + "body": "{\"message\": \"hello world\", \"username\": \"tom\"}", + "pathParameters": { + "parameter1": "value1" + }, + "isBase64Encoded": false, + "stageVariables": { + "stageVariable1": "value1", + "stageVariable2": "value2" + } +} diff --git a/packages/parser/tests/events/apiGatewayProxyV2EventPathTrailingSlash.json b/packages/parser/tests/events/apiGatewayProxyV2EventPathTrailingSlash.json new file mode 100644 index 0000000000..dfb0d98f2e --- /dev/null +++ b/packages/parser/tests/events/apiGatewayProxyV2EventPathTrailingSlash.json @@ -0,0 +1,69 @@ +{ + "version": "2.0", + "routeKey": "$default", + "rawPath": "/my/path/", + "rawQueryString": "parameter1=value1¶meter1=value2¶meter2=value", + "cookies": [ + "cookie1", + "cookie2" + ], + "headers": { + "Header1": "value1", + "Header2": "value1,value2" + }, + "queryStringParameters": { + "parameter1": "value1,value2", + "parameter2": "value" + }, + "requestContext": { + "accountId": "123456789012", + "apiId": "api-id", + "authentication": { + "clientCert": { + "clientCertPem": "CERT_CONTENT", + "subjectDN": "www.example.com", + "issuerDN": "Example issuer", + "serialNumber": "a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1", + "validity": { + "notBefore": "May 28 12:30:02 2019 GMT", + "notAfter": "Aug 5 09:36:04 2021 GMT" + } + } + }, + "authorizer": { + "jwt": { + "claims": { + "claim1": "value1", + "claim2": "value2" + }, + "scopes": [ + "scope1", + "scope2" + ] + } + }, + "domainName": "id.execute-api.us-east-1.amazonaws.com", + "domainPrefix": "id", + "http": { + "method": "POST", + "path": "/my/path", + "protocol": "HTTP/1.1", + "sourceIp": "192.168.0.1/32", + "userAgent": "agent" + }, + "requestId": "id", + "routeKey": "$default", + "stage": "$default", + "time": "12/Mar/2020:19:03:58 +0000", + "timeEpoch": 1583348638390 + }, + "body": "{\"message\": \"hello world\", \"username\": \"tom\"}", + "pathParameters": { + "parameter1": "value1" + }, + "isBase64Encoded": false, + "stageVariables": { + "stageVariable1": "value1", + "stageVariable2": "value2" + } + } \ No newline at end of file diff --git a/packages/parser/tests/events/apiGatewayProxyV2Event_GET.json b/packages/parser/tests/events/apiGatewayProxyV2Event_GET.json new file mode 100644 index 0000000000..f411ea655d --- /dev/null +++ b/packages/parser/tests/events/apiGatewayProxyV2Event_GET.json @@ -0,0 +1,68 @@ +{ + "version": "2.0", + "routeKey": "$default", + "rawPath": "/my/path", + "rawQueryString": "parameter1=value1¶meter1=value2¶meter2=value", + "cookies": [ + "cookie1", + "cookie2" + ], + "headers": { + "Header1": "value1", + "Header2": "value1,value2" + }, + "queryStringParameters": { + "parameter1": "value1,value2", + "parameter2": "value" + }, + "requestContext": { + "accountId": "123456789012", + "apiId": "api-id", + "authentication": { + "clientCert": { + "clientCertPem": "CERT_CONTENT", + "subjectDN": "www.example.com", + "issuerDN": "Example issuer", + "serialNumber": "a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1", + "validity": { + "notBefore": "May 28 12:30:02 2019 GMT", + "notAfter": "Aug 5 09:36:04 2021 GMT" + } + } + }, + "authorizer": { + "jwt": { + "claims": { + "claim1": "value1", + "claim2": "value2" + }, + "scopes": [ + "scope1", + "scope2" + ] + } + }, + "domainName": "id.execute-api.us-east-1.amazonaws.com", + "domainPrefix": "id", + "http": { + "method": "GET", + "path": "/my/path", + "protocol": "HTTP/1.1", + "sourceIp": "192.168.0.1/32", + "userAgent": "agent" + }, + "requestId": "id", + "routeKey": "$default", + "stage": "$default", + "time": "12/Mar/2020:19:03:58 +0000", + "timeEpoch": 1583348638390 + }, + "pathParameters": { + "parameter1": "value1" + }, + "isBase64Encoded": false, + "stageVariables": { + "stageVariable1": "value1", + "stageVariable2": "value2" + } +} diff --git a/packages/parser/tests/events/apiGatewayProxyV2IamEvent.json b/packages/parser/tests/events/apiGatewayProxyV2IamEvent.json new file mode 100644 index 0000000000..43f33e1678 --- /dev/null +++ b/packages/parser/tests/events/apiGatewayProxyV2IamEvent.json @@ -0,0 +1,62 @@ +{ + "version": "2.0", + "routeKey": "$default", + "rawPath": "/my/path", + "rawQueryString": "parameter1=value1¶meter1=value2¶meter2=value", + "cookies": [ + "cookie1", + "cookie2" + ], + "headers": { + "Header1": "value1", + "Header2": "value2" + }, + "queryStringParameters": { + "parameter1": "value1,value2", + "parameter2": "value" + }, + "pathParameters": { + "proxy": "hello/world" + }, + "requestContext": { + "routeKey": "$default", + "accountId": "123456789012", + "stage": "$default", + "requestId": "id", + "authorizer": { + "iam": { + "accessKey": "ARIA2ZJZYVUEREEIHAKY", + "accountId": "1234567890", + "callerId": "AROA7ZJZYVRE7C3DUXHH6:CognitoIdentityCredentials", + "cognitoIdentity": { + "amr": [ + "foo" + ], + "identityId": "us-east-1:3f291106-8703-466b-8f2b-3ecee1ca56ce", + "identityPoolId": "us-east-1:4f291106-8703-466b-8f2b-3ecee1ca56ce" + }, + "principalOrgId": "AwsOrgId", + "userArn": "arn:aws:iam::1234567890:user/Admin", + "userId": "AROA2ZJZYVRE7Y3TUXHH6" + } + }, + "apiId": "api-id", + "domainName": "id.execute-api.us-east-1.amazonaws.com", + "domainPrefix": "id", + "time": "12/Mar/2020:19:03:58+0000", + "timeEpoch": 1583348638390, + "http": { + "method": "GET", + "path": "/my/path", + "protocol": "HTTP/1.1", + "sourceIp": "192.168.0.1/32", + "userAgent": "agent" + } + }, + "stageVariables": { + "stageVariable1": "value1", + "stageVariable2": "value2" + }, + "body": "{\r\n\t\"a\": 1\r\n}", + "isBase64Encoded": false +} \ No newline at end of file diff --git a/packages/parser/tests/events/apiGatewayProxyV2LambdaAuthorizerEvent.json b/packages/parser/tests/events/apiGatewayProxyV2LambdaAuthorizerEvent.json new file mode 100644 index 0000000000..cae3130de8 --- /dev/null +++ b/packages/parser/tests/events/apiGatewayProxyV2LambdaAuthorizerEvent.json @@ -0,0 +1,50 @@ +{ + "version": "2.0", + "routeKey": "$default", + "rawPath": "/my/path", + "rawQueryString": "parameter1=value1¶meter1=value2¶meter2=value", + "cookies": [ + "cookie1", + "cookie2" + ], + "headers": { + "Header1": "value1", + "Header2": "value2" + }, + "queryStringParameters": { + "parameter1": "value1,value2", + "parameter2": "value" + }, + "pathParameters": { + "proxy": "hello/world" + }, + "requestContext": { + "routeKey": "$default", + "accountId": "123456789012", + "stage": "$default", + "requestId": "id", + "authorizer": { + "lambda": { + "key": "value" + } + }, + "apiId": "api-id", + "domainName": "id.execute-api.us-east-1.amazonaws.com", + "domainPrefix": "id", + "time": "12/Mar/2020:19:03:58+0000", + "timeEpoch": 1583348638390, + "http": { + "method": "GET", + "path": "/my/path", + "protocol": "HTTP/1.1", + "sourceIp": "192.168.0.1/32", + "userAgent": "agent" + } + }, + "stageVariables": { + "stageVariable1": "value1", + "stageVariable2": "value2" + }, + "body": "{\r\n\t\"a\": 1\r\n}", + "isBase64Encoded": false +} \ No newline at end of file diff --git a/packages/parser/tests/events/apiGatewayProxyV2OtherGetEvent.json b/packages/parser/tests/events/apiGatewayProxyV2OtherGetEvent.json new file mode 100644 index 0000000000..b9bd88f1c2 --- /dev/null +++ b/packages/parser/tests/events/apiGatewayProxyV2OtherGetEvent.json @@ -0,0 +1,68 @@ +{ + "version": "2.0", + "routeKey": "$default", + "rawPath": "/other/path", + "rawQueryString": "parameter1=value1¶meter1=value2¶meter2=value", + "cookies": [ + "cookie1", + "cookie2" + ], + "headers": { + "Header1": "value1", + "Header2": "value1,value2" + }, + "queryStringParameters": { + "parameter1": "value1,value2", + "parameter2": "value" + }, + "requestContext": { + "accountId": "123456789012", + "apiId": "api-id", + "authentication": { + "clientCert": { + "clientCertPem": "CERT_CONTENT", + "subjectDN": "www.example.com", + "issuerDN": "Example issuer", + "serialNumber": "a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1", + "validity": { + "notBefore": "May 28 12:30:02 2019 GMT", + "notAfter": "Aug 5 09:36:04 2021 GMT" + } + } + }, + "authorizer": { + "jwt": { + "claims": { + "claim1": "value1", + "claim2": "value2" + }, + "scopes": [ + "scope1", + "scope2" + ] + } + }, + "domainName": "id.execute-api.us-east-1.amazonaws.com", + "domainPrefix": "id", + "http": { + "method": "GET", + "path": "/other/path", + "protocol": "HTTP/1.1", + "sourceIp": "192.168.0.1/32", + "userAgent": "agent" + }, + "requestId": "id", + "routeKey": "$default", + "stage": "$default", + "time": "12/Mar/2020:19:03:58 +0000", + "timeEpoch": 1583348638390 + }, + "pathParameters": { + "parameter1": "value1" + }, + "isBase64Encoded": false, + "stageVariables": { + "stageVariable1": "value1", + "stageVariable2": "value2" + } +} diff --git a/packages/parser/tests/events/apiGatewayProxyV2SchemaMiddlwareInvalidEvent.json b/packages/parser/tests/events/apiGatewayProxyV2SchemaMiddlwareInvalidEvent.json new file mode 100644 index 0000000000..d2f4c404c7 --- /dev/null +++ b/packages/parser/tests/events/apiGatewayProxyV2SchemaMiddlwareInvalidEvent.json @@ -0,0 +1,69 @@ +{ + "version": "2.0", + "routeKey": "$default", + "rawPath": "/my/path", + "rawQueryString": "parameter1=value1¶meter1=value2¶meter2=value", + "cookies": [ + "cookie1", + "cookie2" + ], + "headers": { + "Header1": "value1", + "Header2": "value1,value2" + }, + "queryStringParameters": { + "parameter1": "value1,value2", + "parameter2": "value" + }, + "requestContext": { + "accountId": "123456789012", + "apiId": "api-id", + "authentication": { + "clientCert": { + "clientCertPem": "CERT_CONTENT", + "subjectDN": "www.example.com", + "issuerDN": "Example issuer", + "serialNumber": "a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1", + "validity": { + "notBefore": "May 28 12:30:02 2019 GMT", + "notAfter": "Aug 5 09:36:04 2021 GMT" + } + } + }, + "authorizer": { + "jwt": { + "claims": { + "claim1": "value1", + "claim2": "value2" + }, + "scopes": [ + "scope1", + "scope2" + ] + } + }, + "domainName": "id.execute-api.us-east-1.amazonaws.com", + "domainPrefix": "id", + "http": { + "method": "POST", + "path": "/my/path", + "protocol": "HTTP/1.1", + "sourceIp": "192.168.0.1/32", + "userAgent": "agent" + }, + "requestId": "id", + "routeKey": "$default", + "stage": "$default", + "time": "12/Mar/2020:19:03:58 +0000", + "timeEpoch": 1583348638390 + }, + "body": "{\"username\": \"lessa\"}", + "pathParameters": { + "parameter1": "value1" + }, + "isBase64Encoded": false, + "stageVariables": { + "stageVariable1": "value1", + "stageVariable2": "value2" + } +} diff --git a/packages/parser/tests/events/apiGatewayProxyV2SchemaMiddlwareValidEvent.json b/packages/parser/tests/events/apiGatewayProxyV2SchemaMiddlwareValidEvent.json new file mode 100644 index 0000000000..7be3d1194d --- /dev/null +++ b/packages/parser/tests/events/apiGatewayProxyV2SchemaMiddlwareValidEvent.json @@ -0,0 +1,69 @@ +{ + "version": "2.0", + "routeKey": "$default", + "rawPath": "/my/path", + "rawQueryString": "parameter1=value1¶meter1=value2¶meter2=value", + "cookies": [ + "cookie1", + "cookie2" + ], + "headers": { + "Header1": "value1", + "Header2": "value1,value2" + }, + "queryStringParameters": { + "parameter1": "value1,value2", + "parameter2": "value" + }, + "requestContext": { + "accountId": "123456789012", + "apiId": "api-id", + "authentication": { + "clientCert": { + "clientCertPem": "CERT_CONTENT", + "subjectDN": "www.example.com", + "issuerDN": "Example issuer", + "serialNumber": "a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1", + "validity": { + "notBefore": "May 28 12:30:02 2019 GMT", + "notAfter": "Aug 5 09:36:04 2021 GMT" + } + } + }, + "authorizer": { + "jwt": { + "claims": { + "claim1": "value1", + "claim2": "value2" + }, + "scopes": [ + "scope1", + "scope2" + ] + } + }, + "domainName": "id.execute-api.us-east-1.amazonaws.com", + "domainPrefix": "id", + "http": { + "method": "POST", + "path": "/my/path", + "protocol": "HTTP/1.1", + "sourceIp": "192.168.0.1/32", + "userAgent": "agent" + }, + "requestId": "id", + "routeKey": "$default", + "stage": "$default", + "time": "12/Mar/2020:19:03:58 +0000", + "timeEpoch": 1583348638390 + }, + "body": "{\"message\": \"hello world\", \"username\": \"lessa\"}", + "pathParameters": { + "parameter1": "value1" + }, + "isBase64Encoded": false, + "stageVariables": { + "stageVariable1": "value1", + "stageVariable2": "value2" + } +} diff --git a/packages/parser/tests/events/apigatewayeSchemaMiddlwareInvalidEvent.json b/packages/parser/tests/events/apigatewayeSchemaMiddlwareInvalidEvent.json new file mode 100644 index 0000000000..13d810870e --- /dev/null +++ b/packages/parser/tests/events/apigatewayeSchemaMiddlwareInvalidEvent.json @@ -0,0 +1,81 @@ +{ + "version": "1.0", + "resource": "/my/path", + "path": "/my/path", + "httpMethod": "POST", + "headers": { + "Header1": "value1", + "Header2": "value2", + "Origin": "https://aws.amazon.com" + }, + "multiValueHeaders": { + "Header1": [ + "value1" + ], + "Header2": [ + "value1", + "value2" + ] + }, + "queryStringParameters": { + "parameter1": "value1", + "parameter2": "value" + }, + "multiValueQueryStringParameters": { + "parameter1": [ + "value1", + "value2" + ], + "parameter2": [ + "value" + ] + }, + "requestContext": { + "accountId": "123456789012", + "apiId": "id", + "authorizer": { + "claims": null, + "scopes": null + }, + "domainName": "id.execute-api.us-east-1.amazonaws.com", + "domainPrefix": "id", + "extendedRequestId": "request-id", + "httpMethod": "GET", + "identity": { + "accessKey": null, + "accountId": null, + "caller": null, + "cognitoAuthenticationProvider": null, + "cognitoAuthenticationType": null, + "cognitoIdentityId": null, + "cognitoIdentityPoolId": null, + "principalOrgId": null, + "sourceIp": "192.168.0.1/32", + "user": null, + "userAgent": "user-agent", + "userArn": null, + "clientCert": { + "clientCertPem": "CERT_CONTENT", + "subjectDN": "www.example.com", + "issuerDN": "Example issuer", + "serialNumber": "a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1", + "validity": { + "notBefore": "May 28 12:30:02 2019 GMT", + "notAfter": "Aug 5 09:36:04 2021 GMT" + } + } + }, + "path": "/my/path", + "protocol": "HTTP/1.1", + "requestId": "id=", + "requestTime": "04/Mar/2020:19:15:17 +0000", + "requestTimeEpoch": 1583349317135, + "resourceId": null, + "resourcePath": "/my/path", + "stage": "$default" + }, + "pathParameters": null, + "stageVariables": null, + "body": "{\"username\": \"lessa\"}", + "isBase64Encoded": false +} diff --git a/packages/parser/tests/events/apigatewayeSchemaMiddlwareValidEvent.json b/packages/parser/tests/events/apigatewayeSchemaMiddlwareValidEvent.json new file mode 100644 index 0000000000..454465b9a4 --- /dev/null +++ b/packages/parser/tests/events/apigatewayeSchemaMiddlwareValidEvent.json @@ -0,0 +1,81 @@ +{ + "version": "1.0", + "resource": "/my/path", + "path": "/my/path", + "httpMethod": "POST", + "headers": { + "Header1": "value1", + "Header2": "value2", + "Origin": "https://aws.amazon.com" + }, + "multiValueHeaders": { + "Header1": [ + "value1" + ], + "Header2": [ + "value1", + "value2" + ] + }, + "queryStringParameters": { + "parameter1": "value1", + "parameter2": "value" + }, + "multiValueQueryStringParameters": { + "parameter1": [ + "value1", + "value2" + ], + "parameter2": [ + "value" + ] + }, + "requestContext": { + "accountId": "123456789012", + "apiId": "id", + "authorizer": { + "claims": null, + "scopes": null + }, + "domainName": "id.execute-api.us-east-1.amazonaws.com", + "domainPrefix": "id", + "extendedRequestId": "request-id", + "httpMethod": "GET", + "identity": { + "accessKey": null, + "accountId": null, + "caller": null, + "cognitoAuthenticationProvider": null, + "cognitoAuthenticationType": null, + "cognitoIdentityId": null, + "cognitoIdentityPoolId": null, + "principalOrgId": null, + "sourceIp": "192.168.0.1/32", + "user": null, + "userAgent": "user-agent", + "userArn": null, + "clientCert": { + "clientCertPem": "CERT_CONTENT", + "subjectDN": "www.example.com", + "issuerDN": "Example issuer", + "serialNumber": "a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1", + "validity": { + "notBefore": "May 28 12:30:02 2019 GMT", + "notAfter": "Aug 5 09:36:04 2021 GMT" + } + } + }, + "path": "/my/path", + "protocol": "HTTP/1.1", + "requestId": "id=", + "requestTime": "04/Mar/2020:19:15:17 +0000", + "requestTimeEpoch": 1583349317135, + "resourceId": null, + "resourcePath": "/my/path", + "stage": "$default" + }, + "pathParameters": null, + "stageVariables": null, + "body": "{\"message\": \"hello world\", \"username\": \"lessa\"}", + "isBase64Encoded": false +} diff --git a/packages/parser/tests/events/appSyncAuthorizerEvent.json b/packages/parser/tests/events/appSyncAuthorizerEvent.json new file mode 100644 index 0000000000..a8264569bf --- /dev/null +++ b/packages/parser/tests/events/appSyncAuthorizerEvent.json @@ -0,0 +1,13 @@ +{ + "authorizationToken": "BE9DC5E3-D410-4733-AF76-70178092E681", + "requestContext": { + "apiId": "giy7kumfmvcqvbedntjwjvagii", + "accountId": "254688921111", + "requestId": "b80ed838-14c6-4500-b4c3-b694c7bef086", + "queryString": "mutation MyNewTask($desc: String!) {\n createTask(description: $desc, owner: \"ccc\", taskStatus: \"cc\", title: \"ccc\") {\n id\n }\n}\n", + "operationName": "MyNewTask", + "variables": { + "desc": "Foo" + } + } +} diff --git a/packages/parser/tests/events/appSyncAuthorizerResponse.json b/packages/parser/tests/events/appSyncAuthorizerResponse.json new file mode 100644 index 0000000000..7dd8234d2e --- /dev/null +++ b/packages/parser/tests/events/appSyncAuthorizerResponse.json @@ -0,0 +1,9 @@ +{ + "isAuthorized": true, + "resolverContext": { + "name": "Foo Man", + "balance": 100 + }, + "deniedFields": ["Mutation.createEvent"], + "ttlOverride": 15 +} diff --git a/packages/parser/tests/events/appSyncDirectResolver.json b/packages/parser/tests/events/appSyncDirectResolver.json new file mode 100644 index 0000000000..08c3d00b20 --- /dev/null +++ b/packages/parser/tests/events/appSyncDirectResolver.json @@ -0,0 +1,74 @@ +{ + "arguments": { + "id": "my identifier" + }, + "identity": { + "claims": { + "sub": "192879fc-a240-4bf1-ab5a-d6a00f3063f9", + "email_verified": true, + "iss": "https://cognito-idp.us-west-2.amazonaws.com/us-west-xxxxxxxxxxx", + "phone_number_verified": false, + "cognito:username": "jdoe", + "aud": "7471s60os7h0uu77i1tk27sp9n", + "event_id": "bc334ed8-a938-4474-b644-9547e304e606", + "token_use": "id", + "auth_time": 1599154213, + "phone_number": "+19999999999", + "exp": 1599157813, + "iat": 1599154213, + "email": "jdoe@email.com" + }, + "defaultAuthStrategy": "ALLOW", + "groups": null, + "issuer": "https://cognito-idp.us-west-2.amazonaws.com/us-west-xxxxxxxxxxx", + "sourceIp": [ + "1.1.1.1" + ], + "sub": "192879fc-a240-4bf1-ab5a-d6a00f3063f9", + "username": "jdoe" + }, + "source": null, + "request": { + "headers": { + "x-forwarded-for": "1.1.1.1, 2.2.2.2", + "cloudfront-viewer-country": "US", + "cloudfront-is-tablet-viewer": "false", + "via": "2.0 xxxxxxxxxxxxxxxx.cloudfront.net (CloudFront)", + "cloudfront-forwarded-proto": "https", + "origin": "https://us-west-1.console.aws.amazon.com", + "content-length": "217", + "accept-language": "en-US,en;q=0.9", + "host": "xxxxxxxxxxxxxxxx.appsync-api.us-west-1.amazonaws.com", + "x-forwarded-proto": "https", + "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36", + "accept": "*/*", + "cloudfront-is-mobile-viewer": "false", + "cloudfront-is-smarttv-viewer": "false", + "accept-encoding": "gzip, deflate, br", + "referer": "https://us-west-1.console.aws.amazon.com/appsync/home?region=us-west-1", + "content-type": "application/json", + "sec-fetch-mode": "cors", + "x-amz-cf-id": "3aykhqlUwQeANU-HGY7E_guV5EkNeMMtwyOgiA==", + "x-amzn-trace-id": "Root=1-5f512f51-fac632066c5e848ae714", + "authorization": "eyJraWQiOiJScWFCSlJqYVJlM0hrSnBTUFpIcVRXazNOW...", + "sec-fetch-dest": "empty", + "x-amz-user-agent": "AWS-Console-AppSync/", + "cloudfront-is-desktop-viewer": "true", + "sec-fetch-site": "cross-site", + "x-forwarded-port": "443" + } + }, + "prev": null, + "info": { + "selectionSetList": [ + "id", + "field1", + "field2" + ], + "selectionSetGraphQL": "{\n id\n field1\n field2\n}", + "parentTypeName": "Mutation", + "fieldName": "createSomething", + "variables": {} + }, + "stash": {} +} diff --git a/packages/parser/tests/events/appSyncResolverEvent.json b/packages/parser/tests/events/appSyncResolverEvent.json new file mode 100644 index 0000000000..84ac71951c --- /dev/null +++ b/packages/parser/tests/events/appSyncResolverEvent.json @@ -0,0 +1,71 @@ +{ + "typeName": "Merchant", + "fieldName": "locations", + "arguments": { + "page": 2, + "size": 1, + "name": "value" + }, + "identity": { + "claims": { + "sub": "07920713-4526-4642-9c88-2953512de441", + "iss": "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_POOL_ID", + "aud": "58rc9bf5kkti90ctmvioppukm9", + "event_id": "7f4c9383-abf6-48b7-b821-91643968b755", + "token_use": "id", + "auth_time": 1615366261, + "name": "Michael Brewer", + "exp": 1615369861, + "iat": 1615366261 + }, + "defaultAuthStrategy": "ALLOW", + "groups": null, + "issuer": "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_POOL_ID", + "sourceIp": [ + "11.215.2.22" + ], + "sub": "07920713-4526-4642-9c88-2953512de441", + "username": "mike" + }, + "source": { + "name": "Value", + "nested": { + "name": "value", + "list": [] + } + }, + "request": { + "headers": { + "x-forwarded-for": "11.215.2.22, 64.44.173.11", + "cloudfront-viewer-country": "US", + "cloudfront-is-tablet-viewer": "false", + "via": "2.0 SOMETHING.cloudfront.net (CloudFront)", + "cloudfront-forwarded-proto": "https", + "origin": "https://console.aws.amazon.com", + "content-length": "156", + "accept-language": "en-US,en;q=0.9", + "host": "SOMETHING.appsync-api.us-east-1.amazonaws.com", + "x-forwarded-proto": "https", + "sec-gpc": "1", + "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) etc.", + "accept": "*/*", + "cloudfront-is-mobile-viewer": "false", + "cloudfront-is-smarttv-viewer": "false", + "accept-encoding": "gzip, deflate, br", + "referer": "https://console.aws.amazon.com/", + "content-type": "application/json", + "sec-fetch-mode": "cors", + "x-amz-cf-id": "Fo5VIuvP6V6anIEt62WzFDCK45mzM4yEdpt5BYxOl9OFqafd-WR0cA==", + "x-amzn-trace-id": "Root=1-60488877-0b0c4e6727ab2a1c545babd0", + "authorization": "AUTH-HEADER", + "sec-fetch-dest": "empty", + "x-amz-user-agent": "AWS-Console-AppSync/", + "cloudfront-is-desktop-viewer": "true", + "sec-fetch-site": "cross-site", + "x-forwarded-port": "443" + } + }, + "prev": { + "result": {} + } +} diff --git a/packages/parser/tests/events/awsConfigRuleConfigurationChanged.json b/packages/parser/tests/events/awsConfigRuleConfigurationChanged.json new file mode 100644 index 0000000000..cbf7abf67a --- /dev/null +++ b/packages/parser/tests/events/awsConfigRuleConfigurationChanged.json @@ -0,0 +1,13 @@ +{ + "version":"1.0", + "invokingEvent":"{\"configurationItemDiff\":{\"changedProperties\":{\"Configuration.InstanceType\":{\"previousValue\":\"t2.micro\",\"updatedValue\":\"t2.medium\",\"changeType\":\"UPDATE\"},\"Configuration.State.Name\":{\"previousValue\":\"running\",\"updatedValue\":\"stopped\",\"changeType\":\"UPDATE\"},\"Configuration.StateTransitionReason\":{\"previousValue\":\"\",\"updatedValue\":\"User initiated (2023-04-27 15:01:07 GMT)\",\"changeType\":\"UPDATE\"},\"Configuration.StateReason\":{\"previousValue\":null,\"updatedValue\":{\"code\":\"Client.UserInitiatedShutdown\",\"message\":\"Client.UserInitiatedShutdown: User initiated shutdown\"},\"changeType\":\"CREATE\"},\"Configuration.CpuOptions.CoreCount\":{\"previousValue\":1,\"updatedValue\":2,\"changeType\":\"UPDATE\"}},\"changeType\":\"UPDATE\"},\"configurationItem\":{\"relatedEvents\":[],\"relationships\":[{\"resourceId\":\"eipalloc-0ebb4367662263cc1\",\"resourceName\":null,\"resourceType\":\"AWS::EC2::EIP\",\"name\":\"Is attached to ElasticIp\"},{\"resourceId\":\"eni-034dd31c4b17ada8c\",\"resourceName\":null,\"resourceType\":\"AWS::EC2::NetworkInterface\",\"name\":\"Contains NetworkInterface\"},{\"resourceId\":\"eni-09a604c0ec356b06f\",\"resourceName\":null,\"resourceType\":\"AWS::EC2::NetworkInterface\",\"name\":\"Contains NetworkInterface\"},{\"resourceId\":\"sg-0fb295a327d9b4835\",\"resourceName\":null,\"resourceType\":\"AWS::EC2::SecurityGroup\",\"name\":\"Is associated with SecurityGroup\"},{\"resourceId\":\"subnet-cad1f2f4\",\"resourceName\":null,\"resourceType\":\"AWS::EC2::Subnet\",\"name\":\"Is contained in Subnet\"},{\"resourceId\":\"vol-0a288b5eb9fea4b30\",\"resourceName\":null,\"resourceType\":\"AWS::EC2::Volume\",\"name\":\"Is attached to Volume\"},{\"resourceId\":\"vpc-2d96be57\",\"resourceName\":null,\"resourceType\":\"AWS::EC2::VPC\",\"name\":\"Is contained in Vpc\"}],\"configuration\":{\"amiLaunchIndex\":0,\"imageId\":\"ami-09d95fab7fff3776c\",\"instanceId\":\"i-042dd005362091826\",\"instanceType\":\"t2.medium\",\"kernelId\":null,\"keyName\":\"mihaec2\",\"launchTime\":\"2023-04-27T14:57:16.000Z\",\"monitoring\":{\"state\":\"disabled\"},\"placement\":{\"availabilityZone\":\"us-east-1e\",\"affinity\":null,\"groupName\":\"\",\"partitionNumber\":null,\"hostId\":null,\"tenancy\":\"default\",\"spreadDomain\":null,\"hostResourceGroupArn\":null},\"platform\":null,\"privateDnsName\":\"ip-172-31-78-41.ec2.internal\",\"privateIpAddress\":\"172.31.78.41\",\"productCodes\":[],\"publicDnsName\":\"ec2-3-232-229-57.compute-1.amazonaws.com\",\"publicIpAddress\":\"3.232.229.57\",\"ramdiskId\":null,\"state\":{\"code\":80,\"name\":\"stopped\"},\"stateTransitionReason\":\"User initiated (2023-04-27 15:01:07 GMT)\",\"subnetId\":\"subnet-cad1f2f4\",\"vpcId\":\"vpc-2d96be57\",\"architecture\":\"x86_64\",\"blockDeviceMappings\":[{\"deviceName\":\"/dev/xvda\",\"ebs\":{\"attachTime\":\"2020-05-30T15:21:58.000Z\",\"deleteOnTermination\":true,\"status\":\"attached\",\"volumeId\":\"vol-0a288b5eb9fea4b30\"}}],\"clientToken\":\"\",\"ebsOptimized\":false,\"enaSupport\":true,\"hypervisor\":\"xen\",\"iamInstanceProfile\":{\"arn\":\"arn:aws:iam::0123456789012:instance-profile/AmazonSSMRoleForInstancesQuickSetup\",\"id\":\"AIPAS5S4WFUBL72S3QXW5\"},\"instanceLifecycle\":null,\"elasticGpuAssociations\":[],\"elasticInferenceAcceleratorAssociations\":[],\"networkInterfaces\":[{\"association\":{\"carrierIp\":null,\"ipOwnerId\":\"0123456789012\",\"publicDnsName\":\"ec2-3-232-229-57.compute-1.amazonaws.com\",\"publicIp\":\"3.232.229.57\"},\"attachment\":{\"attachTime\":\"2020-05-30T15:21:57.000Z\",\"attachmentId\":\"eni-attach-0a7e75dc9c1c291a0\",\"deleteOnTermination\":true,\"deviceIndex\":0,\"status\":\"attached\",\"networkCardIndex\":0},\"description\":\"\",\"groups\":[{\"groupName\":\"minhaec2\",\"groupId\":\"sg-0fb295a327d9b4835\"}],\"ipv6Addresses\":[],\"macAddress\":\"06:cf:00:c2:17:db\",\"networkInterfaceId\":\"eni-034dd31c4b17ada8c\",\"ownerId\":\"0123456789012\",\"privateDnsName\":\"ip-172-31-78-41.ec2.internal\",\"privateIpAddress\":\"172.31.78.41\",\"privateIpAddresses\":[{\"association\":{\"carrierIp\":null,\"ipOwnerId\":\"0123456789012\",\"publicDnsName\":\"ec2-3-232-229-57.compute-1.amazonaws.com\",\"publicIp\":\"3.232.229.57\"},\"primary\":true,\"privateDnsName\":\"ip-172-31-78-41.ec2.internal\",\"privateIpAddress\":\"172.31.78.41\"}],\"sourceDestCheck\":true,\"status\":\"in-use\",\"subnetId\":\"subnet-cad1f2f4\",\"vpcId\":\"vpc-2d96be57\",\"interfaceType\":\"interface\"},{\"association\":null,\"attachment\":{\"attachTime\":\"2020-11-26T23:46:04.000Z\",\"attachmentId\":\"eni-attach-0e6d150ebbd19966e\",\"deleteOnTermination\":false,\"deviceIndex\":1,\"status\":\"attached\",\"networkCardIndex\":0},\"description\":\"MINHAEC2AAAAAA\",\"groups\":[{\"groupName\":\"minhaec2\",\"groupId\":\"sg-0fb295a327d9b4835\"},{\"groupName\":\"default\",\"groupId\":\"sg-88105fa0\"}],\"ipv6Addresses\":[],\"macAddress\":\"06:0a:62:00:64:5f\",\"networkInterfaceId\":\"eni-09a604c0ec356b06f\",\"ownerId\":\"0123456789012\",\"privateDnsName\":\"ip-172-31-70-9.ec2.internal\",\"privateIpAddress\":\"172.31.70.9\",\"privateIpAddresses\":[{\"association\":null,\"primary\":true,\"privateDnsName\":\"ip-172-31-70-9.ec2.internal\",\"privateIpAddress\":\"172.31.70.9\"}],\"sourceDestCheck\":true,\"status\":\"in-use\",\"subnetId\":\"subnet-cad1f2f4\",\"vpcId\":\"vpc-2d96be57\",\"interfaceType\":\"interface\"}],\"outpostArn\":null,\"rootDeviceName\":\"/dev/xvda\",\"rootDeviceType\":\"ebs\",\"securityGroups\":[{\"groupName\":\"minhaec2\",\"groupId\":\"sg-0fb295a327d9b4835\"}],\"sourceDestCheck\":true,\"spotInstanceRequestId\":null,\"sriovNetSupport\":null,\"stateReason\":{\"code\":\"Client.UserInitiatedShutdown\",\"message\":\"Client.UserInitiatedShutdown: User initiated shutdown\"},\"tags\":[{\"key\":\"projeto\",\"value\":\"meetup\"},{\"key\":\"Name\",\"value\":\"Minha\"},{\"key\":\"CentroCusto\",\"value\":\"TI\"},{\"key\":\"Setor\",\"value\":\"Desenvolvimento\"}],\"virtualizationType\":\"hvm\",\"cpuOptions\":{\"coreCount\":2,\"threadsPerCore\":1},\"capacityReservationId\":null,\"capacityReservationSpecification\":{\"capacityReservationPreference\":\"open\",\"capacityReservationTarget\":null},\"hibernationOptions\":{\"configured\":false},\"licenses\":[],\"metadataOptions\":{\"state\":\"applied\",\"httpTokens\":\"optional\",\"httpPutResponseHopLimit\":1,\"httpEndpoint\":\"enabled\"},\"enclaveOptions\":{\"enabled\":false},\"bootMode\":null},\"supplementaryConfiguration\":{},\"tags\":{\"projeto\":\"meetup\",\"Setor\":\"Desenvolvimento\",\"CentroCusto\":\"TI\",\"Name\":\"Minha\"},\"configurationItemVersion\":\"1.3\",\"configurationItemCaptureTime\":\"2023-04-27T15:03:11.636Z\",\"configurationStateId\":1682607791636,\"awsAccountId\":\"0123456789012\",\"configurationItemStatus\":\"OK\",\"resourceType\":\"AWS::EC2::Instance\",\"resourceId\":\"i-042dd005362091826\",\"resourceName\":null,\"ARN\":\"arn:aws:ec2:us-east-1:0123456789012:instance/i-042dd005362091826\",\"awsRegion\":\"us-east-1\",\"availabilityZone\":\"us-east-1e\",\"configurationStateMd5Hash\":\"\",\"resourceCreationTime\":\"2023-04-27T14:57:16.000Z\"},\"notificationCreationTime\":\"2023-04-27T15:03:13.332Z\",\"messageType\":\"ConfigurationItemChangeNotification\",\"recordVersion\":\"1.3\"}", + "ruleParameters":"{\"desiredInstanceType\": \"t2.micro\"}", + "resultToken":"eyJlbmNyeXB0ZWREYXRhIjpbLTQxLDEsLTU3LC0zMCwtMTIxLDUzLDUyLDQ1LC01NywtOCw3MywtODEsLTExNiwtMTAyLC01MiwxMTIsLTQ3LDU4LDY1LC0xMjcsMTAyLDUsLTY5LDQ0LC0xNSwxMTQsNDEsLTksMTExLC0zMCw2NSwtNzUsLTM1LDU0LDEwNSwtODksODYsNDAsLTEwNSw5OCw2NSwtMTE5LC02OSwyNCw2NiwtMjAsODAsLTExMiwtNzgsLTgwLDQzLC01NywzMCwtMjUsODIsLTEwLDMsLTQsLTg1LC01MywtMzcsLTkwLC04OCwtOTgsLTk4LC00MSwxOSwxMTYsNjIsLTIzLC0xMjEsLTEwOCw1NywtNTgsLTUyLDI5LDEwMSwxMjIsLTU2LC03MSwtODEsLTQ3LDc3LC0yMiwtMTI0LC0zLC04NiwtMTIyLC00MCwtODksLTEwMSw1NywtMTI3LC0zNywtMzcsLTMxLC05OCwtMzEsMTEsLTEyNSwwLDEwOCwtMzIsNjQsNjIsLTIyLDAsNDcsLTEwNiwtMTAwLDEwNCwxNCw1OCwxMjIsLTEwLC01MCwtOTAsLTgwLC01MCwtNSw2NSwwLC0yNSw4NSw4Miw3LDkzLDEyMiwtODIsLTExNiwtNzksLTQ0LDcyLC03MywtNjksMTQsLTU2LDk0LDkwLDExNCwtMjksLTExOSwtNzEsODgsMTA3LDEwNywxMTAsLTcsMTI3LC0xMjUsLTU3LC0xMjYsLTEyMCw2OSwtMTI3LC03NiwtMTE5LDcxLDEsLTY4LDEwNywxMTMsLTU2LDg3LC0xMDIsLTE2LDEwOCwtMTA3LC00MywtOTQsLTEwNiwzLDkwLDE0LDcyLC0xMiwtMTE2LC03Myw4MCwtMTIyLDQ0LC0xMDQsMTIsNzQsNTcsLTEwLC0xMDUsLTExMiwtMzYsMjgsLTQ1LDk3LDExLC00OSwtMTEsNjEsMzYsLTE3LC03NCw1MCw0LC0yNiwxMDQsLTI4LC0xMjUsMjQsNzAsLTg1LC00Niw5MiwtMTAzLC00MSwtMTA2LDY5LDEyMiwyMSwtMjUsODAsOTksLTkzLC01NiwtMjUsLTQ3LC0xMjMsLTU5LC0xMjQsLTUyLC0xNiwxMjcsLTM4LC0xNiwxMDEsMTE5LDEwNywyNywxMCwtNDYsLTg3LC0xMiwtMzksMTQsNDUsMiw3MCwxMDcsMTA0LC00LC02OSwtMTIsNTksLTEyNiwtOTEsMTI3LDU0LDEwNiwtMTI2LC0xMTYsLTEwMiw3Miw4MSw1MCw3NSwtNTEsMTA4LDQxLC0zLC02LC00NSwxMDMsLTg2LDM3LC00NiwtMzIsLTExMSwxMjQsMTExLDg3LDU0LC03NiwxMjIsLTUsLTM2LC04OCw5LC0xMTMsMTE2LC01OSw4Myw3NywyOCwxMiwtNjUsLTExMywtNzksLTEyOCw4MiwtMTE4LC04MywtMTI0LDMxLDk5LC05MCwtOTksMTYsLTEyMywyMSwtMTE0LC05OCwtMTE2LC0xMTksMiwtNzMsNDYsODIsLTEzLDU0LDcxLC00MiwyNSw3NCw3MywtODYsOTQsNDYsOTksOTMsLTgyLDU1LDY1LC05OCw0OSwtNjAsMTEyLDEwMSwyMiw2OSwtMTYsNzcsLTk0LC01OSwtNDYsMTE1LDMwLC00Myw5Myw4OCwtMjgsMzgsNiw4NCwzMSwtMTAxLDMyLC0yMiwtNjMsLTk1LDExNCwtNzUsMTE0LDM2LC04NCw0MCwtNDQsLTEzLDU5LDcyLC0xLC0xMDMsMzEsMTA1LDY5LDY5LDc3LC02NCwtNTYsMTE4LDEzLC0xMTQsODAsOTksLTUzLDI1LDQyLDk0LDczLC04MCwyNSwzOCwyNCwtMTcsNjYsLTExOCwtMjMsMTE5LDkwLDEyMSwxMTgsLTUxLDUxLC0xMiwtNzYsLTUxLDksLTIxLDExNCwtMzcsLTY0LC0yLC0xMjYsLTk1LDYzLDczLC00MSwtMzQsLTkwLC0yMiw1OSwtNzksMzAsLTQsLTEsLTUsMTIsMzksLTk5LC0xMDUsLTEwNCwtNjEsNjUsLTc0LDE5LC0xMywtNjAsLTI4LC04LDQsLTgsMTIxLC0xMTgsMTIyLC02NSwtMjEsMjMsMTcsLTg0LDQwLC05MiwxNCwtMTI2LC02MCwtNzksLTUzLDM3LC04Myw2NSwxMDQsLTM2LC02MCwtMTEwLC0zMywtMTE3LDYsMTA3LDEsLTMsOTMsNzgsLTk1LC0xMjIsNTMsMTA4LC00OSwtNDksMjQsLTY1LDgzLDEyNSwtNzcsLTE5LC04MSwzNCwtNjcsLTQzLC03MCwtMjYsMTgsMTA0LDY1LDQsLTEyNiw0NCwtMTE5LDUyLC00NiwyMiw2NywxMTMsMTE4LC0zMywzNCwtOTYsMTIxLDE5LC0yLC0zNSwwLC04MiwxNyw2NiwtMjcsNjksLTM2LC0xNCw1NiwtOTcsLTE2LDEyMywyOCwtOTUsLTMyLC02MywtNjksNzAsNjQsLTMzLC0xMDAsNDMsLTExMywxMDUsMTAwLDEwOCwtNjAsNDAsLTIsLTk2LC0xMjQsMzcsLTQ1LC0xMjQsLTY4LC02OSwtMTIzLDE3LC02LDg2LC01OSwtOTQsMTEwLDczLDU3LC0xMTYsMTA3LC00MSwtOTQsLTExOCwtMTI2LDEwLC04MCwtNzAsMTAyLDg4LC0xMjYsODcsLTI3LC0xMDEsLTk0LC0zNSwtMTA2LC02LC03MiwtODYsNTAsMTE2LC0yOCw5MCwxMywtMTIwLDYsMjcsOTIsNTYsLTkwLDM5LDQ5LC0xMywtODYsLTI1LC04NiwxMTMsLTEzLDQxLC0xMTksOTQsLTk0LC0xMDMsLTgzLC02MCwxMjcsLTE1LC0zOSwxMTksLTk1LDI3LDQ0LDExNiwxMDksNywtMTAyLC0xNyw0OCwtODIsLTMxLC04LC02OSwzNSw5NCw1NCwtNTUsMSwtMTE5LDU3LC0xMDgsLTMsLTkxLC0xMjIsLTUzLC04OCw0LC05NywtMzUsMTI2LDExOSw1OSwtMSw4NSw3MywtNTgsLTEyMCwtNjQsMTE5LC0xMTIsOTIsMTksOSwtNjYsLTkyLDEwOCwtMTEsLTQyLDExMSwtMTA0LC0xMjAsMjcsLTEwMywtNjksMTksMTExLDEyLDIzLDEwNyw1NCw0MSwtMjYsNjAsLTMxLC01XSwibWF0ZXJpYWxTZXRTZXJpYWxOdW1iZXIiOjEsIml2UGFyYW1ldGVyU3BlYyI6eyJpdiI6Wy05NSwzMiwxMDgsOTEsMzUsLTgyLC0zNywyNCwtNDQsLTExNSwtODIsLTEyOCwtMTIyLDMsNTMsLTI0XX19", + "eventLeftScope":false, + "executionRoleArn":"arn:aws:iam::0123456789012:role/aws-service-role/config.amazonaws.com/AWSServiceRoleForConfig", + "configRuleArn":"arn:aws:config:us-east-1:0123456789012:config-rule/config-rule-i9y8j9", + "configRuleName":"MyRule", + "configRuleId":"config-rule-i9y8j9", + "accountId":"0123456789012", + "evaluationMode":"DETECTIVE" + } diff --git a/packages/parser/tests/events/awsConfigRuleOversizedConfiguration.json b/packages/parser/tests/events/awsConfigRuleOversizedConfiguration.json new file mode 100644 index 0000000000..5eaef4e001 --- /dev/null +++ b/packages/parser/tests/events/awsConfigRuleOversizedConfiguration.json @@ -0,0 +1,12 @@ +{ + "invokingEvent": "{\"configurationItemSummary\": {\"changeType\": \"UPDATE\",\"configurationItemVersion\": \"1.2\",\"configurationItemCaptureTime\":\"2016-10-06T16:46:16.261Z\",\"configurationStateId\": 0,\"awsAccountId\":\"123456789012\",\"configurationItemStatus\": \"OK\",\"resourceType\": \"AWS::EC2::Instance\",\"resourceId\":\"i-00000000\",\"resourceName\":null,\"ARN\":\"arn:aws:ec2:us-west-2:123456789012:instance/i-00000000\",\"awsRegion\": \"us-west-2\",\"availabilityZone\":\"us-west-2a\",\"configurationStateMd5Hash\":\"8f1ee69b287895a0f8bc5753eca68e96\",\"resourceCreationTime\":\"2016-10-06T16:46:10.489Z\"},\"messageType\":\"OversizedConfigurationItemChangeNotification\", \"notificationCreationTime\": \"2016-10-06T16:46:16.261Z\", \"recordVersion\": \"1.0\"}", + "ruleParameters": "{\"myParameterKey\":\"myParameterValue\"}", + "resultToken": "myResultToken", + "eventLeftScope": false, + "executionRoleArn": "arn:aws:iam::123456789012:role/config-role", + "configRuleArn": "arn:aws:config:us-east-2:123456789012:config-rule/config-rule-ec2-managed-instance-inventory", + "configRuleName": "change-triggered-config-rule", + "configRuleId": "config-rule-0123456", + "accountId": "123456789012", + "version": "1.0" +} diff --git a/packages/parser/tests/events/awsConfigRuleScheduled.json b/packages/parser/tests/events/awsConfigRuleScheduled.json new file mode 100644 index 0000000000..02ce2a0700 --- /dev/null +++ b/packages/parser/tests/events/awsConfigRuleScheduled.json @@ -0,0 +1,13 @@ +{ + "version":"1.0", + "invokingEvent":"{\"awsAccountId\":\"0123456789012\",\"notificationCreationTime\":\"2023-04-27T13:26:17.741Z\",\"messageType\":\"ScheduledNotification\",\"recordVersion\":\"1.0\"}", + "ruleParameters":"{\"test\":\"x\"}", + "resultToken":"eyJlbmNyeXB0ZWREYXRhIjpbLTQyLDEyNiw1MiwtMzcsLTI5LDExNCwxMjYsLTk3LDcxLDIyLC0xMTAsMTEyLC0zMSwtOTMsLTQ5LC0xMDEsODIsMyw1NCw0OSwzLC02OSwtNzEsLTcyLDYyLDgxLC03MiwtODEsNTAsMzUsLTUwLC03NSwtMTE4LC0xMTgsNzcsMTIsLTEsMTQsMTIwLC03MCwxMTAsLTMsNTAsLTYwLDEwNSwtNTcsNDUsMTAyLC0xMDksLTYxLC0xMDEsLTYxLDQsNDcsLTg0LC0yNSwxMTIsNTQsLTcxLC0xMDksNDUsMTksMTIzLC0yNiwxMiwtOTYsLTczLDU0LC0xMDksOTIsNDgsLTU5LC04MywtMzIsODIsLTM2LC05MCwxOSw5OCw3Nyw3OCw0MCw4MCw3OCwtMTA1LDg3LC0xMTMsLTExNiwtNzIsMzAsLTY4LC00MCwtODksMTA5LC0xMDgsLTEyOCwyMiw3Miw3NywtMjEsNzYsODksOTQsLTU5LDgxLC0xMjEsLTEwNywtNjcsNjMsLTcsODIsLTg5LC00NiwtMzQsLTkyLDEyMiwtOTAsMTcsLTEyMywyMCwtODUsLTU5LC03MCw4MSwyNyw2Miw3NCwtODAsODAsMzcsNDAsMTE2LDkxLC0yNCw1MSwtNDEsLTc5LDI4LDEyMCw1MywtMTIyLC04MywxMjYsLTc4LDI1LC05OCwtMzYsMTMsMzIsODYsLTI1LDQ4LDMsLTEwMiwtMTYsMjQsLTMsODUsNDQsLTI4LDE0LDIyLDI3LC0xMjIsMTE4LDEwMSw3Myw1LDE4LDU4LC02NCwyMywtODYsLTExNCwyNCwwLDEwMCwyLDExNywtNjIsLTExOSwtMTI4LDE4LDY1LDkwLDE0LC0xMDIsMjEsODUsMTAwLDExNyw1NSwyOSwxMjcsNTQsNzcsNzIsNzQsMzIsNzgsMywtMTExLDExOCwtNzAsLTg2LDEyNywtNzQsNjAsMjIsNDgsMzcsODcsMTMsMCwtMTA1LDUsLTEyMiwtNzEsLTEwMCwxMDQsLTEyNiwtMTYsNzksLTMwLDEyMCw3NywtNzYsLTQxLC0xMDksMiw5NywtMTAxLC0xLDE1LDEyMywxMTksMTA4LDkxLC0yMCwtMTI1LC05NiwyLC05MiwtMTUsLTY3LC03NiwxMjEsMTA0LDEwNSw2NCwtNjIsMTAyLDgsNCwxMjEsLTQ1LC04MCwtODEsLTgsMTE4LDQ0LC04MiwtNDEsLTg0LDczLC0zNiwxMTcsODAsLTY5LC03MywxNCwtMTgsNzIsMzEsLTUsLTExMSwtMTI3LC00MywzNCwtOCw1NywxMDMsLTQyLDE4LC0zMywxMTcsLTI2LC0xMjQsLTEyNCwxNSw4OCwyMywxNiwtNTcsNTQsLTYsLTEwMiwxMTYsLTk5LC00NSwxMDAsLTM1LDg3LDM3LDYsOTgsMiwxMTIsNjAsLTMzLDE3LDI2LDk5LC0xMDUsNDgsLTEwNCwtMTE5LDc4LDYsLTU4LDk1LDksNDEsLTE2LDk2LDQxLC0yMiw5Niw3MiwxMTYsLTk1LC0xMDUsLTM2LC0xMjMsLTU1LDkxLC00NiwtNywtOTIsMzksNDUsODQsMTYsLTEyNCwtMTIyLC02OCwxLC0yOCwxMjIsLTYwLDgyLDEwMywtNTQsLTkyLDI3LC05OSwtMTI4LDY1LDcsLTcyLC0xMjcsNjIsLTIyLDIsLTExLDE4LC04OSwtMTA2LC03NCw3MSw4NiwtMTE2LC0yNSwtMTE1LC05Niw1NywtMzQsMjIsLTEyNCwtMTI1LC00LC00MSw0MiwtNTcsLTEwMyw0NSw3OCwxNCwtMTA2LDExMSw5OCwtOTQsLTcxLDUsNzUsMTksLTEyNCwtMzAsMzQsLTUwLDc1LC04NCwtNTAsLTU2LDUxLC0xNSwtMzYsNjEsLTk0LC03OSwtNDUsMTI2LC03NywtMTA1LC0yLC05MywtNiw4LC0zLDYsLTQyLDQ2LDEyNSw1LC05OCwxMyw2NywtMTAsLTEzLC05NCwtNzgsLTEyNywxMjEsLTI2LC04LC0xMDEsLTkxLDEyMSwtNDAsLTEyNCwtNjQsODQsLTcyLDYzLDE5LC04NF0sIm1hdGVyaWFsU2V0U2VyaWFsTnVtYmVyIjoxLCJpdlBhcmFtZXRlclNwZWMiOnsiaXYiOlszLC0xMCwtODUsMTE0LC05MCwxMTUsNzcsNTUsNTQsMTUsMzgsODQsLTExNiwxNCwtNDAsMjhdfX0=", + "eventLeftScope":false, + "executionRoleArn":"arn:aws:iam::0123456789012:role/aws-service-role/config.amazonaws.com/AWSServiceRoleForConfig", + "configRuleArn":"arn:aws:config:us-east-1:0123456789012:config-rule/config-rule-pdmyw1", + "configRuleName":"rule-ec2-test", + "configRuleId":"config-rule-pdmyw1", + "accountId":"0123456789012", + "evaluationMode":"DETECTIVE" + } diff --git a/packages/parser/tests/events/bedrockAgentEvent.json b/packages/parser/tests/events/bedrockAgentEvent.json new file mode 100644 index 0000000000..b7ad75b3c4 --- /dev/null +++ b/packages/parser/tests/events/bedrockAgentEvent.json @@ -0,0 +1,16 @@ +{ + "actionGroup": "ClaimManagementActionGroup", + "messageVersion": "1.0", + "sessionId": "12345678912345", + "sessionAttributes": {}, + "promptSessionAttributes": {}, + "inputText": "I want to claim my insurance", + "agent": { + "alias": "TSTALIASID", + "name": "test", + "version": "DRAFT", + "id": "8ZXY0W8P1H" + }, + "httpMethod": "GET", + "apiPath": "/claims" +} diff --git a/packages/parser/tests/events/bedrockAgentPostEvent.json b/packages/parser/tests/events/bedrockAgentPostEvent.json new file mode 100644 index 0000000000..f223bfcd51 --- /dev/null +++ b/packages/parser/tests/events/bedrockAgentPostEvent.json @@ -0,0 +1,35 @@ +{ + "actionGroup": "ClaimManagementActionGroup", + "messageVersion": "1.0", + "sessionId": "12345678912345", + "sessionAttributes": {}, + "promptSessionAttributes": {}, + "inputText": "Send reminders to all pending documents", + "agent": { + "alias": "TSTALIASID", + "name": "test", + "version": "DRAFT", + "id": "8ZXY0W8P1H" + }, + "httpMethod": "POST", + "apiPath": "/send-reminders", + "requestBody": { + "content": { + "application/json": { + "properties": [ + { + "name": "claimId", + "type": "string", + "value": "20" + }, + { + "name": "pendingDocuments", + "type": "string", + "value": "social number and vat" + } + ] + } + } + }, + "parameters": [] +} diff --git a/packages/parser/tests/events/cloudWatchDashboardEvent.json b/packages/parser/tests/events/cloudWatchDashboardEvent.json new file mode 100644 index 0000000000..fd2d3be62d --- /dev/null +++ b/packages/parser/tests/events/cloudWatchDashboardEvent.json @@ -0,0 +1,38 @@ +{ + "original": "param-to-widget", + "widgetContext": { + "dashboardName": "Name-of-current-dashboard", + "widgetId": "widget-16", + "domain": "https://us-east-1.console.aws.amazon.com", + "accountId": "123456789123", + "locale": "en", + "timezone": { + "label": "UTC", + "offsetISO": "+00:00", + "offsetInMinutes": 0 + }, + "period": 300, + "isAutoPeriod": true, + "timeRange": { + "mode": "relative", + "start": 1627236199729, + "end": 1627322599729, + "relativeStart": 86400012, + "zoom": { + "start": 1627276030434, + "end": 1627282956521 + } + }, + "theme": "light", + "linkCharts": true, + "title": "Tweets for Amazon website problem", + "forms": { + "all": {} + }, + "params": { + "original": "param-to-widget" + }, + "width": 588, + "height": 369 + } +} diff --git a/packages/parser/tests/events/cloudWatchLogEvent.json b/packages/parser/tests/events/cloudWatchLogEvent.json new file mode 100644 index 0000000000..aa184c1d01 --- /dev/null +++ b/packages/parser/tests/events/cloudWatchLogEvent.json @@ -0,0 +1,5 @@ +{ + "awslogs": { + "data": "H4sIAAAAAAAAAHWPwQqCQBCGX0Xm7EFtK+smZBEUgXoLCdMhFtKV3akI8d0bLYmibvPPN3wz00CJxmQnTO41whwWQRIctmEcB6sQbFC3CjW3XW8kxpOpP+OC22d1Wml1qZkQGtoMsScxaczKN3plG8zlaHIta5KqWsozoTYw3/djzwhpLwivWFGHGpAFe7DL68JlBUk+l7KSN7tCOEJ4M3/qOI49vMHj+zCKdlFqLaU2ZHV2a4Ct/an0/ivdX8oYc1UVX860fQDQiMdxRQEAAA==" + } +} diff --git a/packages/parser/tests/events/cloudformationCustomResourceCreate.json b/packages/parser/tests/events/cloudformationCustomResourceCreate.json new file mode 100644 index 0000000000..5c32d8c7aa --- /dev/null +++ b/packages/parser/tests/events/cloudformationCustomResourceCreate.json @@ -0,0 +1,13 @@ +{ + "RequestType": "Create", + "ServiceToken": "arn:aws:lambda:us-east-1:xxx:function:xxxx-CrbuiltinfunctionidProvi-2vKAalSppmKe", + "ResponseURL": "https://cloudformation-custom-resource-response-useast1.s3.amazonaws.com/7F%7Cb1f50fdfc25f3b", + "StackId": "arn:aws:cloudformation:us-east-1:xxxx:stack/xxxx/271845b0-f2e8-11ed-90ac-0eeb25b8ae21", + "RequestId": "xxxxx-d2a0-4dfb-ab1f-xxxxxx", + "LogicalResourceId": "xxxxxxxxx", + "ResourceType": "Custom::MyType", + "ResourceProperties": { + "ServiceToken": "arn:aws:lambda:us-east-1:xxxxx:function:xxxxx", + "MyProps": "ss" + } +} \ No newline at end of file diff --git a/packages/parser/tests/events/cloudformationCustomResourceDelete.json b/packages/parser/tests/events/cloudformationCustomResourceDelete.json new file mode 100644 index 0000000000..f26738133d --- /dev/null +++ b/packages/parser/tests/events/cloudformationCustomResourceDelete.json @@ -0,0 +1,13 @@ +{ + "RequestType": "Delete", + "ServiceToken": "arn:aws:lambda:us-east-1:xxx:function:xxxx-CrbuiltinfunctionidProvi-2vKAalSppmKe", + "ResponseURL": "https://cloudformation-custom-resource-response-useast1.s3.amazonaws.com/7F%7Cb1f50fdfc25f3b", + "StackId": "arn:aws:cloudformation:us-east-1:xxxx:stack/xxxx/271845b0-f2e8-11ed-90ac-0eeb25b8ae21", + "RequestId": "xxxxx-d2a0-4dfb-ab1f-xxxxxx", + "LogicalResourceId": "xxxxxxxxx", + "ResourceType": "Custom::MyType", + "ResourceProperties": { + "ServiceToken": "arn:aws:lambda:us-east-1:xxxxx:function:xxxxx", + "MyProps": "ss" + } +} \ No newline at end of file diff --git a/packages/parser/tests/events/cloudformationCustomResourceUpdate.json b/packages/parser/tests/events/cloudformationCustomResourceUpdate.json new file mode 100644 index 0000000000..5225746345 --- /dev/null +++ b/packages/parser/tests/events/cloudformationCustomResourceUpdate.json @@ -0,0 +1,17 @@ +{ + "RequestType": "Update", + "ServiceToken": "arn:aws:lambda:us-east-1:xxx:function:xxxx-CrbuiltinfunctionidProvi-2vKAalSppmKe", + "ResponseURL": "https://cloudformation-custom-resource-response-useast1.s3.amazonaws.com/7F%7Cb1f50fdfc25f3b", + "StackId": "arn:aws:cloudformation:us-east-1:xxxx:stack/xxxx/271845b0-f2e8-11ed-90ac-0eeb25b8ae21", + "RequestId": "xxxxx-d2a0-4dfb-ab1f-xxxxxx", + "LogicalResourceId": "xxxxxxxxx", + "ResourceType": "Custom::MyType", + "ResourceProperties": { + "ServiceToken": "arn:aws:lambda:us-east-1:xxxxx:function:xxxxx", + "MyProps": "new" + }, + "OldResourceProperties": { + "ServiceToken": "arn:aws:lambda:us-east-1:xxxxx:function:xxxxx-xxxx-xxx", + "MyProps": "old" + } +} \ No newline at end of file diff --git a/packages/parser/tests/events/codePipelineEvent.json b/packages/parser/tests/events/codePipelineEvent.json new file mode 100644 index 0000000000..d7abe51346 --- /dev/null +++ b/packages/parser/tests/events/codePipelineEvent.json @@ -0,0 +1,34 @@ +{ + "CodePipeline.job": { + "id": "11111111-abcd-1111-abcd-111111abcdef", + "accountId": "111111111111", + "data": { + "actionConfiguration": { + "configuration": { + "FunctionName": "MyLambdaFunctionForAWSCodePipeline", + "UserParameters": "some-input-such-as-a-URL" + } + }, + "inputArtifacts": [ + { + "name": "ArtifactName", + "revision": null, + "location": { + "type": "S3", + "s3Location": { + "bucketName": "the name of the bucket configured as the pipeline artifact store in Amazon S3, for example codepipeline-us-east-2-1234567890", + "objectKey": "the name of the application, for example CodePipelineDemoApplication.zip" + } + } + } + ], + "outputArtifacts": [], + "artifactCredentials": { + "accessKeyId": "AKIAIOSFODNN7EXAMPLE", + "secretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "sessionToken": "MIICiTCCAfICCQD6m7oRw0uXOjANBgkqhkiG9w0BAQUFADCBiDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAldBMRAwDgYDVQQHEwdTZWF0dGxlMQ8wDQYDVQQKEwZBbWF6b24xFDASBgNVBAsTC0lBTSBDb25zb2xlMRIwEAYDVQQDEwlUZXN0Q2lsYWMxHzAdBgkqhkiG9w0BCQEWEG5vb25lQGFtYXpvbi5jb20wHhcNMTEwNDI1MjA0NTIxWhcNMTIwNDI0MjA0NTIxWjCBiDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAldBMRAwDgYDVQQHEwdTZWF0dGxlMQ8wDQYDVQQKEwZBbWF6b24xFDASBgNVBAsTC0lBTSBDb25zb2xlMRIwEAYDVQQDEwlUZXN0Q2lsYWMxHzAdBgkqhkiG9w0BCQEWEG5vb25lQGFtYXpvbi5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMaK0dn+a4GmWIWJ21uUSfwfEvySWtC2XADZ4nB+BLYgVIk60CpiwsZ3G93vUEIO3IyNoH/f0wYK8m9TrDHudUZg3qX4waLG5M43q7Wgc/MbQITxOUSQv7c7ugFFDzQGBzZswY6786m86gpEIbb3OhjZnzcvQAaRHhdlQWIMm2nrAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAtCu4nUhVVxYUntneD9+h8Mg9q6q+auNKyExzyLwaxlAoo7TJHidbtS4J5iNmZgXL0FkbFFBjvSfpJIlJ00zbhNYS5f6GuoEDmFJl0ZxBHjJnyp378OD8uTs7fLvjx79LjSTbNYiytVbZPQUQ5Yaxu2jXnimvw3rrszlaEXAMPLE=" + }, + "continuationToken": "A continuation token if continuing job" + } + } +} diff --git a/packages/parser/tests/events/codePipelineEventData.json b/packages/parser/tests/events/codePipelineEventData.json new file mode 100644 index 0000000000..7552f19ca9 --- /dev/null +++ b/packages/parser/tests/events/codePipelineEventData.json @@ -0,0 +1,46 @@ +{ + "CodePipeline.job": { + "id": "c0d76431-b0e7-xmpl-97e3-e8ee786eb6f6", + "accountId": "123456789012", + "data": { + "actionConfiguration": { + "configuration": { + "FunctionName": "my-function", + "UserParameters": "{\"KEY\": \"VALUE\"}" + } + }, + "inputArtifacts": [ + { + "name": "my-pipeline-SourceArtifact", + "revision": "e0c7xmpl2308ca3071aa7bab414de234ab52eea", + "location": { + "type": "S3", + "s3Location": { + "bucketName": "us-west-2-123456789012-my-pipeline", + "objectKey": "my-pipeline/test-api-2/TdOSFRV" + } + } + } + ], + "outputArtifacts": [ + { + "name": "invokeOutput", + "revision": null, + "location": { + "type": "S3", + "s3Location": { + "bucketName": "us-west-2-123456789012-my-pipeline", + "objectKey": "my-pipeline/invokeOutp/D0YHsJn" + } + } + } + ], + "artifactCredentials": { + "accessKeyId": "AKIAIOSFODNN7EXAMPLE", + "secretAccessKey": "6CGtmAa3lzWtV7a...", + "sessionToken": "IQoJb3JpZ2luX2VjEA...", + "expirationTime": 1575493418000 + } + } + } +} diff --git a/packages/parser/tests/events/codePipelineEventEmptyUserParameters.json b/packages/parser/tests/events/codePipelineEventEmptyUserParameters.json new file mode 100644 index 0000000000..1a0dec6a15 --- /dev/null +++ b/packages/parser/tests/events/codePipelineEventEmptyUserParameters.json @@ -0,0 +1,32 @@ +{ + "CodePipeline.job": { + "id": "11111111-abcd-1111-abcd-111111abcdef", + "accountId": "111111111111", + "data": { + "actionConfiguration": { + "configuration": { + "FunctionName": "MyLambdaFunctionForAWSCodePipeline" + } + }, + "inputArtifacts": [ + { + "name": "ArtifactName", + "revision": null, + "location": { + "type": "S3", + "s3Location": { + "bucketName": "the name of the bucket configured as the pipeline artifact store in Amazon S3, for example codepipeline-us-east-2-1234567890", + "objectKey": "the name of the application, for example CodePipelineDemoApplication.zip" + } + } + } + ], + "outputArtifacts": [], + "artifactCredentials": { + "accessKeyId": "AKIAIOSFODNN7EXAMPLE", + "secretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "sessionToken": "MIICiTCCAfICCQD6m7oRw0uXOjANBgkqhkiG9w0BAQUFADCBiDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAldBMRAwDgYDVQQHEwdTZWF0dGxlMQ8wDQYDVQQKEwZBbWF6b24xFDASBgNVBAsTC0lBTSBDb25zb2xlMRIwEAYDVQQDEwlUZXN0Q2lsYWMxHzAdBgkqhkiG9w0BCQEWEG5vb25lQGFtYXpvbi5jb20wHhcNMTEwNDI1MjA0NTIxWhcNMTIwNDI0MjA0NTIxWjCBiDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAldBMRAwDgYDVQQHEwdTZWF0dGxlMQ8wDQYDVQQKEwZBbWF6b24xFDASBgNVBAsTC0lBTSBDb25zb2xlMRIwEAYDVQQDEwlUZXN0Q2lsYWMxHzAdBgkqhkiG9w0BCQEWEG5vb25lQGFtYXpvbi5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMaK0dn+a4GmWIWJ21uUSfwfEvySWtC2XADZ4nB+BLYgVIk60CpiwsZ3G93vUEIO3IyNoH/f0wYK8m9TrDHudUZg3qX4waLG5M43q7Wgc/MbQITxOUSQv7c7ugFFDzQGBzZswY6786m86gpEIbb3OhjZnzcvQAaRHhdlQWIMm2nrAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAtCu4nUhVVxYUntneD9+h8Mg9q6q+auNKyExzyLwaxlAoo7TJHidbtS4J5iNmZgXL0FkbFFBjvSfpJIlJ00zbhNYS5f6GuoEDmFJl0ZxBHjJnyp378OD8uTs7fLvjx79LjSTbNYiytVbZPQUQ5Yaxu2jXnimvw3rrszlaEXAMPLE=" + } + } + } +} diff --git a/packages/parser/tests/events/codePipelineEventWithEncryptionKey.json b/packages/parser/tests/events/codePipelineEventWithEncryptionKey.json new file mode 100644 index 0000000000..e4a8528e14 --- /dev/null +++ b/packages/parser/tests/events/codePipelineEventWithEncryptionKey.json @@ -0,0 +1,38 @@ +{ + "CodePipeline.job": { + "id": "11111111-abcd-1111-abcd-111111abcdef", + "accountId": "111111111111", + "data": { + "actionConfiguration": { + "configuration": { + "FunctionName": "MyLambdaFunctionForAWSCodePipeline", + "UserParameters": "some-input-such-as-a-URL" + } + }, + "inputArtifacts": [ + { + "name": "ArtifactName", + "revision": null, + "location": { + "type": "S3", + "s3Location": { + "bucketName": "the name of the bucket configured as the pipeline artifact store in Amazon S3, for example codepipeline-us-east-2-1234567890", + "objectKey": "the name of the application, for example CodePipelineDemoApplication.zip" + } + } + } + ], + "outputArtifacts": [], + "artifactCredentials": { + "accessKeyId": "AKIAIOSFODNN7EXAMPLE", + "secretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "sessionToken": "MIICiTCCAfICCQD6m7oRw0uXOjANBgkqhkiG9w0BAQUFADCBiDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAldBMRAwDgYDVQQHEwdTZWF0dGxlMQ8wDQYDVQQKEwZBbWF6b24xFDASBgNVBAsTC0lBTSBDb25zb2xlMRIwEAYDVQQDEwlUZXN0Q2lsYWMxHzAdBgkqhkiG9w0BCQEWEG5vb25lQGFtYXpvbi5jb20wHhcNMTEwNDI1MjA0NTIxWhcNMTIwNDI0MjA0NTIxWjCBiDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAldBMRAwDgYDVQQHEwdTZWF0dGxlMQ8wDQYDVQQKEwZBbWF6b24xFDASBgNVBAsTC0lBTSBDb25zb2xlMRIwEAYDVQQDEwlUZXN0Q2lsYWMxHzAdBgkqhkiG9w0BCQEWEG5vb25lQGFtYXpvbi5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMaK0dn+a4GmWIWJ21uUSfwfEvySWtC2XADZ4nB+BLYgVIk60CpiwsZ3G93vUEIO3IyNoH/f0wYK8m9TrDHudUZg3qX4waLG5M43q7Wgc/MbQITxOUSQv7c7ugFFDzQGBzZswY6786m86gpEIbb3OhjZnzcvQAaRHhdlQWIMm2nrAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAtCu4nUhVVxYUntneD9+h8Mg9q6q+auNKyExzyLwaxlAoo7TJHidbtS4J5iNmZgXL0FkbFFBjvSfpJIlJ00zbhNYS5f6GuoEDmFJl0ZxBHjJnyp378OD8uTs7fLvjx79LjSTbNYiytVbZPQUQ5Yaxu2jXnimvw3rrszlaEXAMPLE=" + }, + "continuationToken": "A continuation token if continuing job", + "encryptionKey": { + "id": "arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab", + "type": "KMS" + } + } + } +} diff --git a/packages/parser/tests/events/cognitoCreateAuthChallengeEvent.json b/packages/parser/tests/events/cognitoCreateAuthChallengeEvent.json new file mode 100644 index 0000000000..ad018ae082 --- /dev/null +++ b/packages/parser/tests/events/cognitoCreateAuthChallengeEvent.json @@ -0,0 +1,29 @@ +{ + "version": "1", + "region": "us-east-1", + "userPoolId": "us-east-1_example", + "userName": "UserName", + "callerContext": { + "awsSdkVersion": "awsSdkVersion", + "clientId": "clientId" + }, + "triggerSource": "CreateAuthChallenge_Authentication", + "request": { + "userAttributes": { + "sub": "4A709A36-7D63-4785-829D-4198EF10EBDA", + "email_verified": "true", + "name": "First Last", + "email": "create-auth@mail.com" + }, + "challengeName": "PASSWORD_VERIFIER", + "session" : [ + { + "challengeName": "CUSTOM_CHALLENGE", + "challengeResult": true, + "challengeMetadata": "CAPTCHA_CHALLENGE" + } + ], + "userNotFound": false + }, + "response": {} +} diff --git a/packages/parser/tests/events/cognitoCustomMessageEvent.json b/packages/parser/tests/events/cognitoCustomMessageEvent.json new file mode 100644 index 0000000000..8652c3bff4 --- /dev/null +++ b/packages/parser/tests/events/cognitoCustomMessageEvent.json @@ -0,0 +1,20 @@ +{ + "version": "1", + "triggerSource": "CustomMessage_AdminCreateUser", + "region": "region", + "userPoolId": "userPoolId", + "userName": "userName", + "callerContext": { + "awsSdk": "awsSdkVersion", + "clientId": "clientId" + }, + "request": { + "userAttributes": { + "phone_number_verified": false, + "email_verified": true + }, + "codeParameter": "####", + "usernameParameter": "username" + }, + "response": {} +} diff --git a/packages/parser/tests/events/cognitoDefineAuthChallengeEvent.json b/packages/parser/tests/events/cognitoDefineAuthChallengeEvent.json new file mode 100644 index 0000000000..80ea5ac2d9 --- /dev/null +++ b/packages/parser/tests/events/cognitoDefineAuthChallengeEvent.json @@ -0,0 +1,32 @@ +{ + "version": "1", + "region": "us-east-1", + "userPoolId": "us-east-1_example", + "userName": "UserName", + "callerContext": { + "awsSdkVersion": "awsSdkVersion", + "clientId": "clientId" + }, + "triggerSource": "DefineAuthChallenge_Authentication", + "request": { + "userAttributes": { + "sub": "4A709A36-7D63-4785-829D-4198EF10EBDA", + "email_verified": "true", + "name": "First Last", + "email": "define-auth@mail.com" + }, + "session" : [ + { + "challengeName": "PASSWORD_VERIFIER", + "challengeResult": true + }, + { + "challengeName": "CUSTOM_CHALLENGE", + "challengeResult": true, + "challengeMetadata": "CAPTCHA_CHALLENGE" + } + ], + "userNotFound": true + }, + "response": {} +} diff --git a/packages/parser/tests/events/cognitoPostAuthenticationEvent.json b/packages/parser/tests/events/cognitoPostAuthenticationEvent.json new file mode 100644 index 0000000000..d34b18eeba --- /dev/null +++ b/packages/parser/tests/events/cognitoPostAuthenticationEvent.json @@ -0,0 +1,18 @@ +{ + "version": "1", + "region": "us-east-1", + "userPoolId": "us-east-1_example", + "userName": "UserName", + "callerContext": { + "awsSdkVersion": "awsSdkVersion", + "clientId": "clientId" + }, + "triggerSource": "PostAuthentication_Authentication", + "request": { + "newDeviceUsed": true, + "userAttributes": { + "email": "post-auth@mail.com" + } + }, + "response": {} +} diff --git a/packages/parser/tests/events/cognitoPostConfirmationEvent.json b/packages/parser/tests/events/cognitoPostConfirmationEvent.json new file mode 100644 index 0000000000..e88f98150c --- /dev/null +++ b/packages/parser/tests/events/cognitoPostConfirmationEvent.json @@ -0,0 +1,18 @@ +{ + "version": "string", + "triggerSource": "PostConfirmation_ConfirmSignUp", + "region": "us-east-1", + "userPoolId": "string", + "userName": "userName", + "callerContext": { + "awsSdkVersion": "awsSdkVersion", + "clientId": "clientId" + }, + "request": { + "userAttributes": { + "email": "user@example.com", + "email_verified": true + } + }, + "response": {} +} diff --git a/packages/parser/tests/events/cognitoPreAuthenticationEvent.json b/packages/parser/tests/events/cognitoPreAuthenticationEvent.json new file mode 100644 index 0000000000..661fea6372 --- /dev/null +++ b/packages/parser/tests/events/cognitoPreAuthenticationEvent.json @@ -0,0 +1,20 @@ +{ + "version": "1", + "region": "us-east-1", + "userPoolId": "us-east-1_example", + "userName": "UserName", + "callerContext": { + "awsSdkVersion": "awsSdkVersion", + "clientId": "clientId" + }, + "triggerSource": "PreAuthentication_Authentication", + "request": { + "userAttributes": { + "sub": "4A709A36-7D63-4785-829D-4198EF10EBDA", + "email_verified": "true", + "name": "First Last", + "email": "pre-auth@mail.com" + } + }, + "response": {} +} diff --git a/packages/parser/tests/events/cognitoPreSignUpEvent.json b/packages/parser/tests/events/cognitoPreSignUpEvent.json new file mode 100644 index 0000000000..feb4eba25d --- /dev/null +++ b/packages/parser/tests/events/cognitoPreSignUpEvent.json @@ -0,0 +1,18 @@ +{ + "version": "string", + "triggerSource": "PreSignUp_SignUp", + "region": "us-east-1", + "userPoolId": "string", + "userName": "userName", + "callerContext": { + "awsSdkVersion": "awsSdkVersion", + "clientId": "clientId" + }, + "request": { + "userAttributes": { + "email": "user@example.com", + "phone_number": "+12065550100" + } + }, + "response": {} +} diff --git a/packages/parser/tests/events/cognitoPreTokenGenerationEvent.json b/packages/parser/tests/events/cognitoPreTokenGenerationEvent.json new file mode 100644 index 0000000000..f5ee69e0d2 --- /dev/null +++ b/packages/parser/tests/events/cognitoPreTokenGenerationEvent.json @@ -0,0 +1,25 @@ +{ + "version": "1", + "triggerSource": "TokenGeneration_Authentication", + "region": "us-west-2", + "userPoolId": "us-west-2_example", + "userName": "testqq", + "callerContext": { + "awsSdkVersion": "aws-sdk-unknown-unknown", + "clientId": "71ghuul37mresr7h373b704tua" + }, + "request": { + "userAttributes": { + "sub": "0b0a57c5-f013-426a-81a1-f8ffbfba21f0", + "email_verified": "true", + "cognito:user_status": "CONFIRMED", + "email": "test@mail.com" + }, + "groupConfiguration": { + "groupsToOverride": [], + "iamRolesToOverride": [], + "preferredRole": null + } + }, + "response": {} +} diff --git a/packages/parser/tests/events/cognitoUserMigrationEvent.json b/packages/parser/tests/events/cognitoUserMigrationEvent.json new file mode 100644 index 0000000000..2eae4e6618 --- /dev/null +++ b/packages/parser/tests/events/cognitoUserMigrationEvent.json @@ -0,0 +1,15 @@ +{ + "version": "string", + "triggerSource": "UserMigration_Authentication", + "region": "us-east-1", + "userPoolId": "string", + "userName": "userName", + "callerContext": { + "awsSdkVersion": "awsSdkVersion", + "clientId": "clientId" + }, + "request": { + "password": "password" + }, + "response": {} +} diff --git a/packages/parser/tests/events/cognitoVerifyAuthChallengeResponseEvent.json b/packages/parser/tests/events/cognitoVerifyAuthChallengeResponseEvent.json new file mode 100644 index 0000000000..2ebcdb5c27 --- /dev/null +++ b/packages/parser/tests/events/cognitoVerifyAuthChallengeResponseEvent.json @@ -0,0 +1,28 @@ +{ + "version": "1", + "region": "us-east-1", + "userPoolId": "us-east-1_example", + "userName": "UserName", + "callerContext": { + "awsSdkVersion": "awsSdkVersion", + "clientId": "clientId" + }, + "triggerSource": "VerifyAuthChallengeResponse_Authentication", + "request": { + "userAttributes": { + "sub": "4A709A36-7D63-4785-829D-4198EF10EBDA", + "email_verified": "true", + "name": "First Last", + "email": "verify-auth@mail.com" + }, + "privateChallengeParameters": { + "answer": "challengeAnswer" + }, + "clientMetadata" : { + "foo": "value" + }, + "challengeAnswer": "challengeAnswer", + "userNotFound": true + }, + "response": {} +} diff --git a/packages/parser/tests/events/connectContactFlowEventAll.json b/packages/parser/tests/events/connectContactFlowEventAll.json new file mode 100644 index 0000000000..5850649b6e --- /dev/null +++ b/packages/parser/tests/events/connectContactFlowEventAll.json @@ -0,0 +1,41 @@ +{ + "Name": "ContactFlowEvent", + "Details": { + "ContactData": { + "Attributes": { + "Language": "en-US" + }, + "Channel": "VOICE", + "ContactId": "5ca32fbd-8f92-46af-92a5-6b0f970f0efe", + "CustomerEndpoint": { + "Address": "+11234567890", + "Type": "TELEPHONE_NUMBER" + }, + "InitialContactId": "5ca32fbd-8f92-46af-92a5-6b0f970f0efe", + "InitiationMethod": "API", + "InstanceARN": "arn:aws:connect:eu-central-1:123456789012:instance/9308c2a1-9bc6-4cea-8290-6c0b4a6d38fa", + "MediaStreams": { + "Customer": { + "Audio": { + "StartFragmentNumber": "91343852333181432392682062622220590765191907586", + "StartTimestamp": "1565781909613", + "StreamARN": "arn:aws:kinesisvideo:eu-central-1:123456789012:stream/connect-contact-a3d73b84-ce0e-479a-a9dc-5637c9d30ac9/1565272947806" + } + } + }, + "PreviousContactId": "5ca32fbd-8f92-46af-92a5-6b0f970f0efe", + "Queue": { + "ARN": "arn:aws:connect:eu-central-1:123456789012:instance/9308c2a1-9bc6-4cea-8290-6c0b4a6d38fa/queue/5cba7cbf-1ecb-4b6d-b8bd-fe91079b3fc8", + "Name": "QueueOne" + }, + "SystemEndpoint": { + "Address": "+11234567890", + "Type": "TELEPHONE_NUMBER" + } + }, + "Parameters": { + "ParameterOne": "One", + "ParameterTwo": "Two" + } + } +} \ No newline at end of file diff --git a/packages/parser/tests/events/connectContactFlowEventMin.json b/packages/parser/tests/events/connectContactFlowEventMin.json new file mode 100644 index 0000000000..9cc22d59c3 --- /dev/null +++ b/packages/parser/tests/events/connectContactFlowEventMin.json @@ -0,0 +1,27 @@ +{ + "Name": "ContactFlowEvent", + "Details": { + "ContactData": { + "Attributes": {}, + "Channel": "VOICE", + "ContactId": "5ca32fbd-8f92-46af-92a5-6b0f970f0efe", + "CustomerEndpoint": null, + "InitialContactId": "5ca32fbd-8f92-46af-92a5-6b0f970f0efe", + "InitiationMethod": "API", + "InstanceARN": "arn:aws:connect:eu-central-1:123456789012:instance/9308c2a1-9bc6-4cea-8290-6c0b4a6d38fa", + "MediaStreams": { + "Customer": { + "Audio": { + "StartFragmentNumber": null, + "StartTimestamp": null, + "StreamARN": null + } + } + }, + "PreviousContactId": "5ca32fbd-8f92-46af-92a5-6b0f970f0efe", + "Queue": null, + "SystemEndpoint": null + }, + "Parameters": {} + } +} \ No newline at end of file diff --git a/packages/parser/tests/events/dynamoStreamEvent.json b/packages/parser/tests/events/dynamoStreamEvent.json new file mode 100644 index 0000000000..16009a7a95 --- /dev/null +++ b/packages/parser/tests/events/dynamoStreamEvent.json @@ -0,0 +1,65 @@ +{ + "Records": [ + { + "eventID": "1", + "eventVersion": "1.0", + "dynamodb": { + "ApproximateCreationDateTime": 1693997155.0, + "Keys": { + "Id": { + "N": "101" + } + }, + "NewImage": { + "Message": { + "S": "New item!" + }, + "Id": { + "N": "101" + } + }, + "StreamViewType": "NEW_AND_OLD_IMAGES", + "SequenceNumber": "111", + "SizeBytes": 26 + }, + "awsRegion": "us-west-2", + "eventName": "INSERT", + "eventSourceARN": "eventsource_arn", + "eventSource": "aws:dynamodb" + }, + { + "eventID": "2", + "eventVersion": "1.0", + "dynamodb": { + "OldImage": { + "Message": { + "S": "New item!" + }, + "Id": { + "N": "101" + } + }, + "SequenceNumber": "222", + "Keys": { + "Id": { + "N": "101" + } + }, + "SizeBytes": 59, + "NewImage": { + "Message": { + "S": "This item has changed" + }, + "Id": { + "N": "101" + } + }, + "StreamViewType": "NEW_AND_OLD_IMAGES" + }, + "awsRegion": "us-west-2", + "eventName": "MODIFY", + "eventSourceARN": "source_arn", + "eventSource": "aws:dynamodb" + } + ] +} diff --git a/packages/parser/tests/events/eventBridgeEvent.json b/packages/parser/tests/events/eventBridgeEvent.json new file mode 100644 index 0000000000..65872cf9a3 --- /dev/null +++ b/packages/parser/tests/events/eventBridgeEvent.json @@ -0,0 +1,17 @@ +{ + "version": "0", + "id": "6a7e8feb-b491-4cf7-a9f1-bf3703467718", + "detail-type": "EC2 Instance State-change Notification", + "source": "aws.ec2", + "account": "111122223333", + "time": "2017-12-22T18:43:48Z", + "region": "us-west-1", + "resources": [ + "arn:aws:ec2:us-west-1:123456789012:instance/i-1234567890abcdef0" + ], + "detail": { + "instance_id": "i-1234567890abcdef0", + "state": "terminated" + }, + "replay-name": "replay_archive" +} diff --git a/packages/parser/tests/events/kafkaEventMsk.json b/packages/parser/tests/events/kafkaEventMsk.json new file mode 100644 index 0000000000..5a35b89680 --- /dev/null +++ b/packages/parser/tests/events/kafkaEventMsk.json @@ -0,0 +1,35 @@ +{ + "eventSource":"aws:kafka", + "eventSourceArn":"arn:aws:kafka:us-east-1:0123456789019:cluster/SalesCluster/abcd1234-abcd-cafe-abab-9876543210ab-4", + "bootstrapServers":"b-2.demo-cluster-1.a1bcde.c1.kafka.us-east-1.amazonaws.com:9092,b-1.demo-cluster-1.a1bcde.c1.kafka.us-east-1.amazonaws.com:9092", + "records":{ + "mytopic-0":[ + { + "topic":"mytopic", + "partition":0, + "offset":15, + "timestamp":1545084650987, + "timestampType":"CREATE_TIME", + "key":"cmVjb3JkS2V5", + "value":"eyJrZXkiOiJ2YWx1ZSJ9", + "headers":[ + { + "headerKey":[ + 104, + 101, + 97, + 100, + 101, + 114, + 86, + 97, + 108, + 117, + 101 + ] + } + ] + } + ] + } +} diff --git a/packages/parser/tests/events/kafkaEventSelfManaged.json b/packages/parser/tests/events/kafkaEventSelfManaged.json new file mode 100644 index 0000000000..22985dd11d --- /dev/null +++ b/packages/parser/tests/events/kafkaEventSelfManaged.json @@ -0,0 +1,34 @@ +{ + "eventSource":"aws:SelfManagedKafka", + "bootstrapServers":"b-2.demo-cluster-1.a1bcde.c1.kafka.us-east-1.amazonaws.com:9092,b-1.demo-cluster-1.a1bcde.c1.kafka.us-east-1.amazonaws.com:9092", + "records":{ + "mytopic-0":[ + { + "topic":"mytopic", + "partition":0, + "offset":15, + "timestamp":1545084650987, + "timestampType":"CREATE_TIME", + "key":"cmVjb3JkS2V5", + "value":"eyJrZXkiOiJ2YWx1ZSJ9", + "headers":[ + { + "headerKey":[ + 104, + 101, + 97, + 100, + 101, + 114, + 86, + 97, + 108, + 117, + 101 + ] + } + ] + } + ] + } +} diff --git a/packages/parser/tests/events/kinesisFirehoseKinesisEvent.json b/packages/parser/tests/events/kinesisFirehoseKinesisEvent.json new file mode 100644 index 0000000000..6cdd8e8a5b --- /dev/null +++ b/packages/parser/tests/events/kinesisFirehoseKinesisEvent.json @@ -0,0 +1,32 @@ +{ + "invocationId": "2b4d1ad9-2f48-94bd-a088-767c317e994a", + "sourceKinesisStreamArn":"arn:aws:kinesis:us-east-1:123456789012:stream/kinesis-source", + "deliveryStreamArn": "arn:aws:firehose:us-east-2:123456789012:deliverystream/delivery-stream-name", + "region": "us-east-2", + "records": [ + { + "data": "SGVsbG8gV29ybGQ=", + "recordId": "record1", + "approximateArrivalTimestamp": 1664028820148, + "kinesisRecordMetadata": { + "shardId": "shardId-000000000000", + "partitionKey": "4d1ad2b9-24f8-4b9d-a088-76e9947c317a", + "approximateArrivalTimestamp": 1664028820148, + "sequenceNumber": "49546986683135544286507457936321625675700192471156785154", + "subsequenceNumber": 0 + } + }, + { + "data": "eyJIZWxsbyI6ICJXb3JsZCJ9", + "recordId": "record2", + "approximateArrivalTimestamp": 1664028793294, + "kinesisRecordMetadata": { + "shardId": "shardId-000000000001", + "partitionKey": "4d1ad2b9-24f8-4b9d-a088-76e9947c318a", + "approximateArrivalTimestamp": 1664028793294, + "sequenceNumber": "49546986683135544286507457936321625675700192471156785155", + "subsequenceNumber": 0 + } + } + ] +} diff --git a/packages/parser/tests/events/kinesisFirehosePutEvent.json b/packages/parser/tests/events/kinesisFirehosePutEvent.json new file mode 100644 index 0000000000..f3e0719071 --- /dev/null +++ b/packages/parser/tests/events/kinesisFirehosePutEvent.json @@ -0,0 +1,17 @@ +{ + "invocationId": "2b4d1ad9-2f48-94bd-a088-767c317e994a", + "deliveryStreamArn": "arn:aws:firehose:us-east-2:123456789012:deliverystream/delivery-stream-name", + "region": "us-east-2", + "records": [ + { + "recordId": "record1", + "approximateArrivalTimestamp": 1664029185290, + "data": "SGVsbG8gV29ybGQ=" + }, + { + "recordId": "record2", + "approximateArrivalTimestamp": 1664029186945, + "data": "eyJIZWxsbyI6ICJXb3JsZCJ9" + } + ] + } diff --git a/packages/parser/tests/events/kinesisFirehoseSQSEvent.json b/packages/parser/tests/events/kinesisFirehoseSQSEvent.json new file mode 100644 index 0000000000..bea267c420 --- /dev/null +++ b/packages/parser/tests/events/kinesisFirehoseSQSEvent.json @@ -0,0 +1,12 @@ +{ + "invocationId": "556b67a3-48fc-4385-af49-e133aade9cb9", + "deliveryStreamArn": "arn:aws:firehose:us-east-1:123456789012:deliverystream/PUT-S3-tdyyE", + "region": "us-east-1", + "records": [ + { + "recordId": "49640912821178817833517986466168945147170627572855734274000000", + "approximateArrivalTimestamp": 1684864917398, + "data": "eyJtZXNzYWdlSWQiOiI1YWI4MDdkNC01NjQ0LTRjNTUtOTdhMy00NzM5NjYzNWFjNzQiLCJyZWNlaXB0SGFuZGxlIjoiQVFFQndKbkt5ckhpZ1VNWmo2cllpZ0NneGxhUzNTTHkwYS4uLiIsImJvZHkiOiJUZXN0IG1lc3NhZ2UuIiwiYXR0cmlidXRlcyI6eyJBcHByb3hpbWF0ZVJlY2VpdmVDb3VudCI6IjEiLCJTZW50VGltZXN0YW1wIjoiMTY4NDg2NDg1MjQ5MSIsIlNlbmRlcklkIjoiQUlEQUlFTlFaSk9MTzIzWVZKNFZPIiwiQXBwcm94aW1hdGVGaXJzdFJlY2VpdmVUaW1lc3RhbXAiOiIxNjg0ODY0ODcyNDkxIn0sIm1lc3NhZ2VBdHRyaWJ1dGVzIjp7fSwibWQ1T2ZNZXNzYWdlQXR0cmlidXRlcyI6bnVsbCwibWQ1T2ZCb2R5IjoiYzhiNmJjNjBjOGI4YjNhOTA0ZTQ1YzFmYWJkZjUyM2QiLCJldmVudFNvdXJjZSI6ImF3czpzcXMiLCJldmVudFNvdXJjZUFSTiI6ImFybjphd3M6c3FzOnVzLWVhc3QtMToyMDA5ODQxMTIzODY6U05TIiwiYXdzUmVnaW9uIjoidXMtZWFzdC0xIn0K" + } + ] +} diff --git a/packages/parser/tests/events/kinesisStreamCloudWatchLogsEvent.json b/packages/parser/tests/events/kinesisStreamCloudWatchLogsEvent.json new file mode 100644 index 0000000000..a9a6959f90 --- /dev/null +++ b/packages/parser/tests/events/kinesisStreamCloudWatchLogsEvent.json @@ -0,0 +1,36 @@ +{ + "Records": [ + { + "kinesis": { + "kinesisSchemaVersion": "1.0", + "partitionKey": "da10bf66b1f54bff5d96eae99149ad1f", + "sequenceNumber": "49635052289529725553291405521504870233219489715332317186", + "data": "H4sIAAAAAAAAAK2Sa2vbMBSG/4ox+xg3Oror39IlvaztVmJv7WjCUGwl8+ZLZstts5L/vuOsZYUyWGEgJHiP9J7nvOghLF3b2rVLthsXjsLJOBl/uZjG8fh4Gg7C+q5yDcqUAWcSONHEoFzU6+Om7jZYGdq7dljYcpnZ4cZHwLWOJl1Zbs/r9cR6e9RVqc/rKlpXV9eXt+fy27vt8W+L2DfOlr07oXQIMAQyvHlzPk6mcbKgciktF5lQfMU5dZZqzrShLF2uFC60aLtlmzb5prc/ygvvmjYc3YRPFG+LusuurE+/Ikqb1Gd55dq8jV+8isT6+317Rk42J5PTcLFnm966yvd2D2GeISJTYIwCJSQ1BE9OtWZCABWaKMIJAMdDMyU5MYZLhmkxBhQxfY4Re1tiWiAlBsgIVQTE4Cl6tI+T8SwJZu5Hh1dPs1FApOMSDI9WVKmIC+4irTMWQZYpx7QkztrgE06MU4yCx9DmVbgbvABmQJTGtkYAB0NwEwyYQUBpqEFuSbkGrThTRKi/AlP+HHj6fvJa3P9Ap/+Rbja9/PD6POd+0jXW7xM1B8CDsp37w7woXBb8qQDZ6xeurJttEOc/HWpUBxeHKNr74LHwsXXYlsm9flrl/rmFIQeS7m3m1fVs/DlIGpu6nhMiyWQGXNKIMbcCIgkhElKbaZnZpYJUz33s1iV+z/6+StMlR3yphHNcCyxiNEXf2zed6xuEu8XuF2wb6krnAwAA", + "approximateArrivalTimestamp": 1668093033.744 + }, + "eventSource": "aws:kinesis", + "eventVersion": "1.0", + "eventID": "shardId-000000000000:49635052289529725553291405521504870233219489715332317186", + "eventName": "aws:kinesis:record", + "invokeIdentityArn": "arn:aws:iam::231436140809:role/pt-1488-CloudWatchKinesisLogsFunctionRole-1M4G2TIWIE49", + "awsRegion": "eu-west-1", + "eventSourceARN": "arn:aws:kinesis:eu-west-1:231436140809:stream/pt-1488-KinesisStreamCloudWatchLogs-D8tHs0im0aJG" + }, + { + "kinesis": { + "kinesisSchemaVersion": "1.0", + "partitionKey": "cf4c4c2c9a49bdfaf58d7dbbc2b06081", + "sequenceNumber": "49635052289529725553291405520881064510298312199003701250", + "data": "H4sIAAAAAAAAAK2SW2/TQBCF/4pl8ViTvc7u5i0laVraQhUbWtREaG1PgsGXYK/bhqr/nXVoBRIgUYnXc2bPfHO092GFXWc3mOy2GI7D6SSZfDyfxfFkPgsPwua2xtbLjFPBgQqiifFy2WzmbdNvvTOyt92otFWa29HWRVRoHU37qtqdNZupdfaorzNXNHW0qS+vLm7O4PPr3fxHROxatNWQThgbUTqiZHT94mySzOJkBUqYLOWY8ZQLbaTRkEvDciUYzWzKfETXp13WFtsh/qgoHbZdOL4OnyhelU2fX1qXffIoXdKcFjV2RRf/9iqSmy933Sk53h5PT8LVnm12g7Ub4u7DIveIXFFjFNGUKUlAaMY0EUJKLjkQbxhKGCWeknMKoAGUkYoJ7TFd4St2tvJtDRYxDAg3VB08Ve/j42SySIIFfu396Ek+DkS+xkwAiYhM00isgUV6jXmEMrM5EmMsh+C9v9hfMQ4eS1vW4cPBH4CZVpoTJkEIAp5RUMo8vGFae3JNCCdUccMVgPw7sP4VePZm+lzc/0AH/0i3mF28fX6fSzftW+v2jZKXRgVVt3SHRVliHvx06F4+x6ppd0FcfEMvMR2cH3rR3gWPxrsO/Vau9vqyvlpMPgRJazMcYGgEHHLKBhLGJaBA0JLxNc0JppoS9Cwxbir/B4d5QDBAQSnfFFGp8aa/vxw2uLbHYUH4sHr4Dj5RJxfMAwAA", + "approximateArrivalTimestamp": 1668092612.992 + }, + "eventSource": "aws:kinesis", + "eventVersion": "1.0", + "eventID": "shardId-000000000000:49635052289529725553291405520881064510298312199003701250", + "eventName": "aws:kinesis:record", + "invokeIdentityArn": "arn:aws:iam::231436140809:role/pt-1488-CloudWatchKinesisLogsFunctionRole-1M4G2TIWIE49", + "awsRegion": "eu-west-1", + "eventSourceARN": "arn:aws:kinesis:eu-west-1:231436140809:stream/pt-1488-KinesisStreamCloudWatchLogs-D8tHs0im0aJG" + } + ] +} \ No newline at end of file diff --git a/packages/parser/tests/events/kinesisStreamEvent.json b/packages/parser/tests/events/kinesisStreamEvent.json new file mode 100644 index 0000000000..ef8e209638 --- /dev/null +++ b/packages/parser/tests/events/kinesisStreamEvent.json @@ -0,0 +1,36 @@ +{ + "Records": [ + { + "kinesis": { + "kinesisSchemaVersion": "1.0", + "partitionKey": "1", + "sequenceNumber": "49590338271490256608559692538361571095921575989136588898", + "data": "SGVsbG8sIHRoaXMgaXMgYSB0ZXN0Lg==", + "approximateArrivalTimestamp": 1545084650.987 + }, + "eventSource": "aws:kinesis", + "eventVersion": "1.0", + "eventID": "shardId-000000000006:49590338271490256608559692538361571095921575989136588898", + "eventName": "aws:kinesis:record", + "invokeIdentityArn": "arn:aws:iam::123456789012:role/lambda-role", + "awsRegion": "us-east-2", + "eventSourceARN": "arn:aws:kinesis:us-east-2:123456789012:stream/lambda-stream" + }, + { + "kinesis": { + "kinesisSchemaVersion": "1.0", + "partitionKey": "1", + "sequenceNumber": "49590338271490256608559692540925702759324208523137515618", + "data": "VGhpcyBpcyBvbmx5IGEgdGVzdC4=", + "approximateArrivalTimestamp": 1545084711.166 + }, + "eventSource": "aws:kinesis", + "eventVersion": "1.0", + "eventID": "shardId-000000000006:49590338271490256608559692540925702759324208523137515618", + "eventName": "aws:kinesis:record", + "invokeIdentityArn": "arn:aws:iam::123456789012:role/lambda-role", + "awsRegion": "us-east-2", + "eventSourceARN": "arn:aws:kinesis:us-east-2:123456789012:stream/lambda-stream" + } + ] +} diff --git a/packages/parser/tests/events/kinesisStreamEventOneRecord.json b/packages/parser/tests/events/kinesisStreamEventOneRecord.json new file mode 100644 index 0000000000..05fe2d297a --- /dev/null +++ b/packages/parser/tests/events/kinesisStreamEventOneRecord.json @@ -0,0 +1,20 @@ +{ + "Records": [ + { + "kinesis": { + "kinesisSchemaVersion": "1.0", + "partitionKey": "1", + "sequenceNumber": "49590338271490256608559692538361571095921575989136588898", + "data": "eyJtZXNzYWdlIjogInRlc3QgbWVzc2FnZSIsICJ1c2VybmFtZSI6ICJ0ZXN0In0=", + "approximateArrivalTimestamp": 1545084650.987 + }, + "eventSource": "aws:kinesis", + "eventVersion": "1.0", + "eventID": "shardId-000000000006:49590338271490256608559692538361571095921575989136588898", + "eventName": "aws:kinesis:record", + "invokeIdentityArn": "arn:aws:iam::123456789012:role/lambda-role", + "awsRegion": "us-east-2", + "eventSourceARN": "arn:aws:kinesis:us-east-2:123456789012:stream/lambda-stream" + } + ] +} diff --git a/packages/parser/tests/events/lambdaFunctionUrlEvent.json b/packages/parser/tests/events/lambdaFunctionUrlEvent.json new file mode 100644 index 0000000000..da5c133e6f --- /dev/null +++ b/packages/parser/tests/events/lambdaFunctionUrlEvent.json @@ -0,0 +1,47 @@ +{ + "version":"2.0", + "routeKey":"$default", + "rawPath":"/", + "rawQueryString":"", + "headers":{ + "sec-fetch-mode":"navigate", + "x-amzn-tls-version":"TLSv1.2", + "sec-fetch-site":"cross-site", + "accept-language":"pt-BR,pt;q=0.9", + "x-forwarded-proto":"https", + "x-forwarded-port":"443", + "x-forwarded-for":"123.123.123.123", + "sec-fetch-user":"?1", + "accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", + "x-amzn-tls-cipher-suite":"ECDHE-RSA-AES128-GCM-SHA256", + "sec-ch-ua":"\" Not A;Brand\";v=\"99\", \"Chromium\";v=\"102\", \"Google Chrome\";v=\"102\"", + "sec-ch-ua-mobile":"?0", + "x-amzn-trace-id":"Root=1-62ecd163-5f302e550dcde3b12402207d", + "sec-ch-ua-platform":"\"Linux\"", + "host":".lambda-url.us-east-1.on.aws", + "upgrade-insecure-requests":"1", + "cache-control":"max-age=0", + "accept-encoding":"gzip, deflate, br", + "sec-fetch-dest":"document", + "user-agent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36" + }, + "requestContext":{ + "accountId":"anonymous", + "apiId":"", + "domainName":".lambda-url.us-east-1.on.aws", + "domainPrefix":"", + "http":{ + "method":"GET", + "path":"/", + "protocol":"HTTP/1.1", + "sourceIp":"123.123.123.123", + "userAgent":"agent" + }, + "requestId":"id", + "routeKey":"$default", + "stage":"$default", + "time":"05/Aug/2022:08:14:39 +0000", + "timeEpoch":1659687279885 + }, + "isBase64Encoded":false +} diff --git a/packages/parser/tests/events/lambdaFunctionUrlEventPathTrailingSlash.json b/packages/parser/tests/events/lambdaFunctionUrlEventPathTrailingSlash.json new file mode 100644 index 0000000000..b1f8226518 --- /dev/null +++ b/packages/parser/tests/events/lambdaFunctionUrlEventPathTrailingSlash.json @@ -0,0 +1,52 @@ +{ + "version": "2.0", + "routeKey": "$default", + "rawPath": "/my/path/", + "rawQueryString": "parameter1=value1¶meter1=value2¶meter2=value", + "cookies": [ + "cookie1", + "cookie2" + ], + "headers": { + "header1": "value1", + "header2": "value1,value2" + }, + "queryStringParameters": { + "parameter1": "value1,value2", + "parameter2": "value" + }, + "requestContext": { + "accountId": "123456789012", + "apiId": "", + "authentication": null, + "authorizer": { + "iam": { + "accessKey": "AKIA...", + "accountId": "111122223333", + "callerId": "AIDA...", + "cognitoIdentity": null, + "principalOrgId": null, + "userArn": "arn:aws:iam::111122223333:user/example-user", + "userId": "AIDA..." + } + }, + "domainName": ".lambda-url.us-west-2.on.aws", + "domainPrefix": "", + "http": { + "method": "POST", + "path": "/my/path", + "protocol": "HTTP/1.1", + "sourceIp": "123.123.123.123", + "userAgent": "agent" + }, + "requestId": "id", + "routeKey": "$default", + "stage": "$default", + "time": "12/Mar/2020:19:03:58 +0000", + "timeEpoch": 1583348638390 + }, + "body": "Hello from client!", + "pathParameters": null, + "isBase64Encoded": false, + "stageVariables": null + } \ No newline at end of file diff --git a/packages/parser/tests/events/lambdaFunctionUrlIAMEvent.json b/packages/parser/tests/events/lambdaFunctionUrlIAMEvent.json new file mode 100644 index 0000000000..bf52342b66 --- /dev/null +++ b/packages/parser/tests/events/lambdaFunctionUrlIAMEvent.json @@ -0,0 +1,52 @@ +{ + "version": "2.0", + "routeKey": "$default", + "rawPath": "/my/path", + "rawQueryString": "parameter1=value1¶meter1=value2¶meter2=value", + "cookies": [ + "cookie1", + "cookie2" + ], + "headers": { + "header1": "value1", + "header2": "value1,value2" + }, + "queryStringParameters": { + "parameter1": "value1,value2", + "parameter2": "value" + }, + "requestContext": { + "accountId": "123456789012", + "apiId": "", + "authentication": null, + "authorizer": { + "iam": { + "accessKey": "AKIA...", + "accountId": "111122223333", + "callerId": "AIDA...", + "cognitoIdentity": null, + "principalOrgId": null, + "userArn": "arn:aws:iam::111122223333:user/example-user", + "userId": "AIDA..." + } + }, + "domainName": ".lambda-url.us-west-2.on.aws", + "domainPrefix": "", + "http": { + "method": "POST", + "path": "/my/path", + "protocol": "HTTP/1.1", + "sourceIp": "123.123.123.123", + "userAgent": "agent" + }, + "requestId": "id", + "routeKey": "$default", + "stage": "$default", + "time": "12/Mar/2020:19:03:58 +0000", + "timeEpoch": 1583348638390 + }, + "body": "Hello from client!", + "pathParameters": null, + "isBase64Encoded": false, + "stageVariables": null +} diff --git a/packages/parser/tests/events/rabbitMQEvent.json b/packages/parser/tests/events/rabbitMQEvent.json new file mode 100644 index 0000000000..e4259555a8 --- /dev/null +++ b/packages/parser/tests/events/rabbitMQEvent.json @@ -0,0 +1,51 @@ +{ + "eventSource": "aws:rmq", + "eventSourceArn": "arn:aws:mq:us-west-2:112556298976:broker:pizzaBroker:b-9bcfa592-423a-4942-879d-eb284b418fc8", + "rmqMessagesByQueue": { + "pizzaQueue::/": [ + { + "basicProperties": { + "contentType": "text/plain", + "contentEncoding": null, + "headers": { + "header1": { + "bytes": [ + 118, + 97, + 108, + 117, + 101, + 49 + ] + }, + "header2": { + "bytes": [ + 118, + 97, + 108, + 117, + 101, + 50 + ] + }, + "numberInHeader": 10 + }, + "deliveryMode": 1, + "priority": 34, + "correlationId": null, + "replyTo": null, + "expiration": "60000", + "messageId": null, + "timestamp": "Jan 1, 1970, 12:33:41 AM", + "type": null, + "userId": "AIDACKCEVSQ6C2EXAMPLE", + "appId": null, + "clusterId": null, + "bodySize": 80 + }, + "redelivered": false, + "data": "eyJ0aW1lb3V0IjowLCJkYXRhIjoiQ1pybWYwR3c4T3Y0YnFMUXhENEUifQ==" + } + ] + } +} diff --git a/packages/parser/tests/events/s3Event.json b/packages/parser/tests/events/s3Event.json new file mode 100644 index 0000000000..4558dc3c9e --- /dev/null +++ b/packages/parser/tests/events/s3Event.json @@ -0,0 +1,38 @@ +{ + "Records": [ + { + "eventVersion": "2.1", + "eventSource": "aws:s3", + "awsRegion": "us-east-2", + "eventTime": "2019-09-03T19:37:27.192Z", + "eventName": "ObjectCreated:Put", + "userIdentity": { + "principalId": "AWS:AIDAINPONIXQXHT3IKHL2" + }, + "requestParameters": { + "sourceIPAddress": "205.255.255.255" + }, + "responseElements": { + "x-amz-request-id": "D82B88E5F771F645", + "x-amz-id-2": "vlR7PnpV2Ce81l0PRw6jlUpck7Jo5ZsQjryTjKlc5aLWGVHPZLj5NeC6qMa0emYBDXOo6QBU0Wo=" + }, + "s3": { + "s3SchemaVersion": "1.0", + "configurationId": "828aa6fc-f7b5-4305-8584-487c791949c1", + "bucket": { + "name": "lambda-artifacts-deafc19498e3f2df", + "ownerIdentity": { + "principalId": "A3I5XTEXAMAI3E" + }, + "arn": "arn:aws:s3:::lambda-artifacts-deafc19498e3f2df" + }, + "object": { + "key": "b21b84d653bb07b05b1e6b33684dc11b", + "size": 1305107, + "eTag": "b21b84d653bb07b05b1e6b33684dc11b", + "sequencer": "0C0F6F405D6ED209E1" + } + } + } + ] +} diff --git a/packages/parser/tests/events/s3EventBridgeNotificationObjectCreatedEvent.json b/packages/parser/tests/events/s3EventBridgeNotificationObjectCreatedEvent.json new file mode 100644 index 0000000000..5cc8f2f402 --- /dev/null +++ b/packages/parser/tests/events/s3EventBridgeNotificationObjectCreatedEvent.json @@ -0,0 +1,28 @@ +{ + "version": "0", + "id": "f5f1e65c-dc3a-93ca-6c1e-b1647eac7963", + "detail-type": "Object Created", + "source": "aws.s3", + "account": "123456789012", + "time": "2023-03-08T17:50:14Z", + "region": "eu-west-1", + "resources": [ + "arn:aws:s3:::example-bucket" + ], + "detail": { + "version": "0", + "bucket": { + "name": "example-bucket" + }, + "object": { + "key": "IMG_m7fzo3.jpg", + "size": 184662, + "etag": "4e68adba0abe2dc8653dc3354e14c01d", + "sequencer": "006408CAD69598B05E" + }, + "request-id": "57H08PA84AB1JZW0", + "requester": "123456789012", + "source-ip-address": "34.252.34.74", + "reason": "PutObject" + } +} \ No newline at end of file diff --git a/packages/parser/tests/events/s3EventBridgeNotificationObjectDeletedEvent.json b/packages/parser/tests/events/s3EventBridgeNotificationObjectDeletedEvent.json new file mode 100644 index 0000000000..af52ee2fef --- /dev/null +++ b/packages/parser/tests/events/s3EventBridgeNotificationObjectDeletedEvent.json @@ -0,0 +1,29 @@ +{ + "version": "0", + "id": "2ee9cc15-d022-99ea-1fb8-1b1bac4850f9", + "detail-type": "Object Deleted", + "source": "aws.s3", + "account": "111122223333", + "time": "2021-11-12T00:00:00Z", + "region": "ca-central-1", + "resources": [ + "arn:aws:s3:::example-bucket" + ], + "detail": { + "version": "0", + "bucket": { + "name": "example-bucket" + }, + "object": { + "key": "IMG_m7fzo3.jpg", + "size": 184662, + "etag": "4e68adba0abe2dc8653dc3354e14c01d", + "sequencer": "006408CAD69598B05E" + }, + "request-id": "0BH729840619AG5K", + "requester": "123456789012", + "source-ip-address": "34.252.34.74", + "reason": "DeleteObject", + "deletion-type": "Delete Marker Created" + } +} \ No newline at end of file diff --git a/packages/parser/tests/events/s3EventBridgeNotificationObjectExpiredEvent.json b/packages/parser/tests/events/s3EventBridgeNotificationObjectExpiredEvent.json new file mode 100644 index 0000000000..ef506cc355 --- /dev/null +++ b/packages/parser/tests/events/s3EventBridgeNotificationObjectExpiredEvent.json @@ -0,0 +1,28 @@ +{ + "version": "0", + "id": "ad1de317-e409-eba2-9552-30113f8d88e3", + "detail-type": "Object Deleted", + "source": "aws.s3", + "account": "111122223333", + "time": "2021-11-12T00:00:00Z", + "region": "ca-central-1", + "resources": [ + "arn:aws:s3:::example-bucket" + ], + "detail": { + "version": "0", + "bucket": { + "name": "example-bucket" + }, + "object": { + "key": "IMG_m7fzo3.jpg", + "size": 184662, + "etag": "4e68adba0abe2dc8653dc3354e14c01d", + "sequencer": "006408CAD69598B05E" + }, + "request-id": "20EB74C14654DC47", + "requester": "s3.amazonaws.com", + "reason": "Lifecycle Expiration", + "deletion-type": "Delete Marker Created" + } +} \ No newline at end of file diff --git a/packages/parser/tests/events/s3EventBridgeNotificationObjectRestoreCompletedEvent.json b/packages/parser/tests/events/s3EventBridgeNotificationObjectRestoreCompletedEvent.json new file mode 100644 index 0000000000..5a2e6a4f9e --- /dev/null +++ b/packages/parser/tests/events/s3EventBridgeNotificationObjectRestoreCompletedEvent.json @@ -0,0 +1,28 @@ +{ + "version": "0", + "id": "6924de0d-13e2-6bbf-c0c1-b903b753565e", + "detail-type": "Object Restore Completed", + "source": "aws.s3", + "account": "111122223333", + "time": "2021-11-12T00:00:00Z", + "region": "ca-central-1", + "resources": [ + "arn:aws:s3:::example-bucket" + ], + "detail": { + "version": "0", + "bucket": { + "name": "example-bucket" + }, + "object": { + "key": "IMG_m7fzo3.jpg", + "size": 184662, + "etag": "4e68adba0abe2dc8653dc3354e14c01d", + "sequencer": "006408CAD69598B05E" + }, + "request-id": "189F19CB7FB1B6A4", + "requester": "s3.amazonaws.com", + "restore-expiry-time": "2021-11-13T00:00:00Z", + "source-storage-class": "GLACIER" + } +} \ No newline at end of file diff --git a/packages/parser/tests/events/s3EventDecodedKey.json b/packages/parser/tests/events/s3EventDecodedKey.json new file mode 100644 index 0000000000..05f5ab5c4b --- /dev/null +++ b/packages/parser/tests/events/s3EventDecodedKey.json @@ -0,0 +1,40 @@ +{ + "Records": [ + { + "eventVersion": "2.0", + "eventSource": "aws:s3", + "awsRegion": "us-east-1", + "eventTime": "1970-01-01T00:00:00.123Z", + "eventName": "ObjectCreated:Put", + "userIdentity": { + "principalId": "EXAMPLE" + }, + "requestParameters": { + "sourceIPAddress": "127.0.0.1" + }, + "responseElements": { + "x-amz-request-id": "C3D13FE58DE4C810", + "x-amz-id-2": "FMyUVURIY8/IgAtTv8xRjskZQpcIZ9KG4V5Wp6S7S/JRWeUWerMUE5JgHvANOjpD" + }, + "s3": { + "s3SchemaVersion": "1.0", + "configurationId": "testConfigRule", + "bucket": { + "name": "sourcebucket", + "ownerIdentity": { + "principalId": "EXAMPLE" + }, + "arn": "arn:aws:s3:::mybucket" + }, + "object": { + "key": "Happy%20Face.jpg", + "urlDecodedKey": "Happy Face.jpg", + "size": 1024, + "versionId": "version", + "eTag": "d41d8cd98f00b204e9800998ecf8427e", + "sequencer": "Happy Sequencer" + } + } + } + ] +} diff --git a/packages/parser/tests/events/s3EventDeleteObject.json b/packages/parser/tests/events/s3EventDeleteObject.json new file mode 100644 index 0000000000..3a607242f0 --- /dev/null +++ b/packages/parser/tests/events/s3EventDeleteObject.json @@ -0,0 +1,36 @@ +{ + "Records": [ + { + "eventVersion": "2.1", + "eventSource": "aws:s3", + "awsRegion": "us-east-2", + "eventTime": "2019-09-03T19:37:27.192Z", + "eventName": "ObjectRemoved:Delete", + "userIdentity": { + "principalId": "AWS:AIDAINPONIXQXHT3IKHL2" + }, + "requestParameters": { + "sourceIPAddress": "205.255.255.255" + }, + "responseElements": { + "x-amz-request-id": "D82B88E5F771F645", + "x-amz-id-2": "vlR7PnpV2Ce81l0PRw6jlUpck7Jo5ZsQjryTjKlc5aLWGVHPZLj5NeC6qMa0emYBDXOo6QBU0Wo=" + }, + "s3": { + "s3SchemaVersion": "1.0", + "configurationId": "828aa6fc-f7b5-4305-8584-487c791949c1", + "bucket": { + "name": "lambda-artifacts-deafc19498e3f2df", + "ownerIdentity": { + "principalId": "A3I5XTEXAMAI3E" + }, + "arn": "arn:aws:s3:::lambda-artifacts-deafc19498e3f2df" + }, + "object": { + "key": "b21b84d653bb07b05b1e6b33684dc11b", + "sequencer": "0C0F6F405D6ED209E1" + } + } + } + ] +} \ No newline at end of file diff --git a/packages/parser/tests/events/s3EventGlacier.json b/packages/parser/tests/events/s3EventGlacier.json new file mode 100644 index 0000000000..2fbc447b30 --- /dev/null +++ b/packages/parser/tests/events/s3EventGlacier.json @@ -0,0 +1,44 @@ +{ + "Records": [ + { + "eventVersion": "2.1", + "eventSource": "aws:s3", + "awsRegion": "us-east-2", + "eventTime": "2019-09-03T19:37:27.192Z", + "eventName": "ObjectCreated:Put", + "userIdentity": { + "principalId": "AWS:AIDAINPONIXQXHT3IKHL2" + }, + "requestParameters": { + "sourceIPAddress": "205.255.255.255" + }, + "responseElements": { + "x-amz-request-id": "D82B88E5F771F645", + "x-amz-id-2": "vlR7PnpV2Ce81l0PRw6jlUpck7Jo5ZsQjryTjKlc5aLWGVHPZLj5NeC6qMa0emYBDXOo6QBU0Wo=" + }, + "s3": { + "s3SchemaVersion": "1.0", + "configurationId": "828aa6fc-f7b5-4305-8584-487c791949c1", + "bucket": { + "name": "lambda-artifacts-deafc19498e3f2df", + "ownerIdentity": { + "principalId": "A3I5XTEXAMAI3E" + }, + "arn": "arn:aws:s3:::lambda-artifacts-deafc19498e3f2df" + }, + "object": { + "key": "b21b84d653bb07b05b1e6b33684dc11b", + "size": 1305107, + "eTag": "b21b84d653bb07b05b1e6b33684dc11b", + "sequencer": "0C0F6F405D6ED209E1" + } + }, + "glacierEventData": { + "restoreEventData": { + "lifecycleRestorationExpiryTime": "1970-01-01T00:01:00.000Z", + "lifecycleRestoreStorageClass": "standard" + } + } + } + ] +} \ No newline at end of file diff --git a/packages/parser/tests/events/s3ObjectEventIAMUser.json b/packages/parser/tests/events/s3ObjectEventIAMUser.json new file mode 100644 index 0000000000..6be41c4352 --- /dev/null +++ b/packages/parser/tests/events/s3ObjectEventIAMUser.json @@ -0,0 +1,30 @@ +{ + "xAmzRequestId": "1a5ed718-5f53-471d-b6fe-5cf62d88d02a", + "getObjectContext": { + "inputS3Url": "https://myap-123412341234.s3-accesspoint.us-east-1.amazonaws.com/s3.txt?X-Amz-Security-Token=...", + "outputRoute": "io-iad-cell001", + "outputToken": "..." + }, + "configuration": { + "accessPointArn": "arn:aws:s3-object-lambda:us-east-1:123412341234:accesspoint/myolap", + "supportingAccessPointArn": "arn:aws:s3:us-east-1:123412341234:accesspoint/myap", + "payload": "test" + }, + "userRequest": { + "url": "/s3.txt", + "headers": { + "Host": "myolap-123412341234.s3-object-lambda.us-east-1.amazonaws.com", + "Accept-Encoding": "identity", + "X-Amz-Content-SHA256": "e3b0c44297fc1c149afbf4c8995fb92427ae41e4649b934ca495991b7852b855" + } + }, + "userIdentity": { + "type": "IAMUser", + "principalId": "...", + "arn": "arn:aws:iam::123412341234:user/myuser", + "accountId": "123412341234", + "accessKeyId": "...", + "userName": "Alice" + }, + "protocolVersion": "1.00" +} diff --git a/packages/parser/tests/events/s3ObjectEventTempCredentials.json b/packages/parser/tests/events/s3ObjectEventTempCredentials.json new file mode 100644 index 0000000000..30c70fe6df --- /dev/null +++ b/packages/parser/tests/events/s3ObjectEventTempCredentials.json @@ -0,0 +1,42 @@ +{ + "xAmzRequestId": "requestId", + "getObjectContext": { + "inputS3Url": "https://my-s3-ap-111122223333.s3-accesspoint.us-east-1.amazonaws.com/example?X-Amz-Security-Token=", + "outputRoute": "io-use1-001", + "outputToken": "OutputToken" + }, + "configuration": { + "accessPointArn": "arn:aws:s3-object-lambda:us-east-1:111122223333:accesspoint/example-object-lambda-ap", + "supportingAccessPointArn": "arn:aws:s3:us-east-1:111122223333:accesspoint/example-ap", + "payload": "{}" + }, + "userRequest": { + "url": "https://object-lambda-111122223333.s3-object-lambda.us-east-1.amazonaws.com/example", + "headers": { + "Host": "object-lambda-111122223333.s3-object-lambda.us-east-1.amazonaws.com", + "Accept-Encoding": "identity", + "X-Amz-Content-SHA256": "e3b0c44298fc1example" + } + }, + "userIdentity": { + "type": "AssumedRole", + "principalId": "principalId", + "arn": "arn:aws:sts::111122223333:assumed-role/Admin/example", + "accountId": "111122223333", + "accessKeyId": "accessKeyId", + "sessionContext": { + "attributes": { + "mfaAuthenticated": "false", + "creationDate": "Wed Mar 10 23:41:52 UTC 2021" + }, + "sessionIssuer": { + "type": "Role", + "principalId": "principalId", + "arn": "arn:aws:iam::111122223333:role/Admin", + "accountId": "111122223333", + "userName": "Admin" + } + } + }, + "protocolVersion": "1.00" +} diff --git a/packages/parser/tests/events/s3SqsEvent.json b/packages/parser/tests/events/s3SqsEvent.json new file mode 100644 index 0000000000..55863af12b --- /dev/null +++ b/packages/parser/tests/events/s3SqsEvent.json @@ -0,0 +1,22 @@ +{ + "Records":[ + { + "messageId":"ca3e7a89-c358-40e5-8aa0-5da01403c267", + "receiptHandle":"AQEBE7XoI7IQRLF7SrpiW9W4BanmOWe8UtVDbv6/CEZYKf/OktSNIb4j689tQfR4k44V/LY20lZ5VpxYt2GTYCsSLKTcBalTJaRX9CKu/hVqy/23sSNiKxnP56D+VLSn+hU275+AP1h4pUL0d9gLdRB2haX8xiM+LcGfis5Jl8BBXtoxKRF60O87O9/NvCmmXLeqkJuexfyEZNyed0fFCRXFXSjbmThG0OIQgcrGI8glBRGPA8htns58VtXFsSaPYNoqP3p5n6+ewKKVLD0lfm+0DlnLKRa+mjvFBaSer9KK1ff+Aq6zJ6HynPwADj+aF70Hwimc2zImYe51SLEF/E2csYlMNZYI/2qXW0m9R7wJ/XDTV4g2+h+BMTxsKnJQ6NQd", + "body":"{\"Records\":[{\"eventVersion\":\"2.1\",\"eventSource\":\"aws:s3\",\"awsRegion\":\"us-east-1\",\"eventTime\":\"2023-04-12T20:43:38.021Z\",\"eventName\":\"ObjectCreated:Put\",\"userIdentity\":{\"principalId\":\"A1YQ72UWCM96UF\"},\"requestParameters\":{\"sourceIPAddress\":\"93.108.161.96\"},\"responseElements\":{\"x-amz-request-id\":\"YMSSR8BZJ2Y99K6P\",\"x-amz-id-2\":\"6ASrUfj5xpn859fIq+6FXflOex/SKl/rjfiMd7wRzMg/zkHKR22PDpnh7KD3uq//cuOTbdX4DInN5eIs+cR0dY1z2Mc5NDP/\"},\"s3\":{\"s3SchemaVersion\":\"1.0\",\"configurationId\":\"SNS\",\"bucket\":{\"name\":\"xxx\",\"ownerIdentity\":{\"principalId\":\"A1YQ72UWCM96UF\"},\"arn\":\"arn:aws:s3:::xxx\"},\"object\":{\"key\":\"test.pdf\",\"size\":104681,\"eTag\":\"2e3ad1e983318bbd8e73b080e2997980\",\"versionId\":\"yd3d4HaWOT2zguDLvIQLU6ptDTwKBnQV\",\"sequencer\":\"00643717F9F8B85354\"}}}]}", + "attributes":{ + "ApproximateReceiveCount":"1", + "SentTimestamp":"1681332219270", + "SenderId":"AIDAJHIPRHEMV73VRJEBU", + "ApproximateFirstReceiveTimestamp":"1681332239270" + }, + "messageAttributes":{ + + }, + "md5OfBody":"16f4460f4477d8d693a5abe94fdbbd73", + "eventSource":"aws:sqs", + "eventSourceARN":"arn:aws:sqs:us-east-1:123456789012:SQS", + "awsRegion":"us-east-1" + } + ] + } diff --git a/packages/parser/tests/events/secretsManagerEvent.json b/packages/parser/tests/events/secretsManagerEvent.json new file mode 100644 index 0000000000..f07ea1e0b0 --- /dev/null +++ b/packages/parser/tests/events/secretsManagerEvent.json @@ -0,0 +1,5 @@ +{ + "SecretId":"arn:aws:secretsmanager:us-west-2:123456789012:secret:MyTestDatabaseSecret-a1b2c3", + "ClientRequestToken":"550e8400-e29b-41d4-a716-446655440000", + "Step":"createSecret" +} \ No newline at end of file diff --git a/packages/parser/tests/events/sesEvent.json b/packages/parser/tests/events/sesEvent.json new file mode 100644 index 0000000000..636ecad687 --- /dev/null +++ b/packages/parser/tests/events/sesEvent.json @@ -0,0 +1,101 @@ +{ + "Records": [ + { + "eventVersion": "1.0", + "ses": { + "mail": { + "commonHeaders": { + "from": [ + "Jane Doe " + ], + "to": [ + "johndoe@example.com" + ], + "returnPath": "janedoe@example.com", + "messageId": "<0123456789example.com>", + "date": "Wed, 7 Oct 2015 12:34:56 -0700", + "subject": "Test Subject" + }, + "source": "janedoe@example.com", + "timestamp": "1970-01-01T00:00:00.000Z", + "destination": [ + "johndoe@example.com" + ], + "headers": [ + { + "name": "Return-Path", + "value": "" + }, + { + "name": "Received", + "value": "from mailer.example.com (mailer.example.com [203.0.113.1]) by ..." + }, + { + "name": "DKIM-Signature", + "value": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=example.com; s=example; ..." + }, + { + "name": "MIME-Version", + "value": "1.0" + }, + { + "name": "From", + "value": "Jane Doe " + }, + { + "name": "Date", + "value": "Wed, 7 Oct 2015 12:34:56 -0700" + }, + { + "name": "Message-ID", + "value": "<0123456789example.com>" + }, + { + "name": "Subject", + "value": "Test Subject" + }, + { + "name": "To", + "value": "johndoe@example.com" + }, + { + "name": "Content-Type", + "value": "text/plain; charset=UTF-8" + } + ], + "headersTruncated": false, + "messageId": "o3vrnil0e2ic28tr" + }, + "receipt": { + "recipients": [ + "johndoe@example.com" + ], + "timestamp": "1970-01-01T00:00:00.000Z", + "spamVerdict": { + "status": "PASS" + }, + "dkimVerdict": { + "status": "PASS" + }, + "dmarcPolicy": "reject", + "processingTimeMillis": 574, + "action": { + "type": "Lambda", + "invocationType": "Event", + "functionArn": "arn:aws:lambda:us-west-2:012345678912:function:Example" + }, + "dmarcVerdict": { + "status": "PASS" + }, + "spfVerdict": { + "status": "PASS" + }, + "virusVerdict": { + "status": "PASS" + } + } + }, + "eventSource": "aws:ses" + } + ] +} diff --git a/packages/parser/tests/events/snsEvent.json b/packages/parser/tests/events/snsEvent.json new file mode 100644 index 0000000000..3d8a8ed443 --- /dev/null +++ b/packages/parser/tests/events/snsEvent.json @@ -0,0 +1,31 @@ +{ + "Records": [ + { + "EventVersion": "1.0", + "EventSubscriptionArn": "arn:aws:sns:us-east-2:123456789012:sns-la ...", + "EventSource": "aws:sns", + "Sns": { + "SignatureVersion": "1", + "Timestamp": "2019-01-02T12:45:07.000Z", + "Signature": "tcc6faL2yUC6dgZdmrwh1Y4cGa/ebXEkAi6RibDsvpi+tE/1+82j...65r==", + "SigningCertUrl": "https://sns.us-east-2.amazonaws.com/SimpleNotification", + "MessageId": "95df01b4-ee98-5cb9-9903-4c221d41eb5e", + "Message": "Hello from SNS!", + "MessageAttributes": { + "Test": { + "Type": "String", + "Value": "TestString" + }, + "TestBinary": { + "Type": "Binary", + "Value": "TestBinary" + } + }, + "Type": "Notification", + "UnsubscribeUrl": "https://sns.us-east-2.amazonaws.com/?Action=Unsubscribe", + "TopicArn": "arn:aws:sns:us-east-2:123456789012:sns-lambda", + "Subject": "TestInvoke" + } + } + ] +} \ No newline at end of file diff --git a/packages/parser/tests/events/snsSqsEvent.json b/packages/parser/tests/events/snsSqsEvent.json new file mode 100644 index 0000000000..ee440fc296 --- /dev/null +++ b/packages/parser/tests/events/snsSqsEvent.json @@ -0,0 +1,20 @@ +{ + "Records": [ + { + "messageId": "79406a00-bf15-46ca-978c-22c3613fcb30", + "receiptHandle": "AQEB3fkqlBqq239bMCAHIr5mZkxJYKtxsTTy1lMImmpY7zqpQdfcAE8zFiuRh7X5ciROy24taT2rRXfuJFN/yEUVcQ6d5CIOCEK4htmRJJOHIyGdZPAm2NUUG5nNn2aEzgfzVvrkPBsrCbr7XTzK5s6eUZNH/Nn9AJtHKHpzweRK34Bon9OU/mvyIT7EJbwHPsdhL14NrCp8pLWBiIhkaJkG2G6gPO89dwHtGVUARJL+zP70AuIu/f7QgmPtY2eeE4AVbcUT1qaIlSGHUXxoHq/VMHLd/c4zWl0EXQOo/90DbyCUMejTIKL7N15YfkHoQDHprvMiAr9S75cdMiNOduiHzZLg/qVcv4kxsksKLFMKjwlzmYuQYy2KslVGwoHMd4PD", + "body": "{\n \"Type\" : \"Notification\",\n \"MessageId\" : \"d88d4479-6ec0-54fe-b63f-1cf9df4bb16e\",\n \"TopicArn\" : \"arn:aws:sns:eu-west-1:231436140809:powertools265\",\n \"Message\" : \"{\\\"message\\\": \\\"hello world\\\", \\\"username\\\": \\\"lessa\\\"}\",\n \"Timestamp\" : \"2021-01-19T10:07:07.287Z\",\n \"SignatureVersion\" : \"1\",\n \"Signature\" : \"tEo2i6Lw6/Dr7Jdlulh0sXgnkF0idd3hqs8QZCorQpzkIWVOuu583NT0Gv0epuZD1Bo+tex6NgP5p6415yNVujGHJKnkrA9ztzXaVgFiol8rf8AFGQbmb7RsM9BqATQUJeg9nCTe0jksmWXmjxEFr8XKyyRuQBwSlRTngAvOw8jUnCe1vyYD5xPec1xpfOEGLi5BqSog+6tBtsry3oAtcENX8SV1tVuMpp6D+UrrU8xNT/5D70uRDppkPE3vq+t7rR0fVSdQRdUV9KmQD2bflA1Dyb2y37EzwJOMHDDQ82aOhj/JmPxvEAlV8RkZl6J0HIveraRy9wbNLbI7jpiOCw==\",\n \"SigningCertURL\" : \"https://sns.eu-west-1.amazonaws.com/SimpleNotificationService-010a507c1833636cd94bdb98bd93083a.pem\",\n \"UnsubscribeURL\" : \"https://sns.eu-west-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:eu-west-1:231436140809:powertools265:15189ad7-870e-40e5-a7dd-a48898cd9f86\"\n}", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1611050827340", + "SenderId": "AIDAISMY7JYY5F7RTT6AO", + "ApproximateFirstReceiveTimestamp": "1611050827344" + }, + "messageAttributes": {}, + "md5OfBody": "8910bdaaf9a30a607f7891037d4af0b0", + "eventSource": "aws:sqs", + "eventSourceARN": "arn:aws:sqs:eu-west-1:231436140809:powertools265", + "awsRegion": "eu-west-1" + } + ] +} diff --git a/packages/parser/tests/events/snsSqsFifoEvent.json b/packages/parser/tests/events/snsSqsFifoEvent.json new file mode 100644 index 0000000000..6c23ef6294 --- /dev/null +++ b/packages/parser/tests/events/snsSqsFifoEvent.json @@ -0,0 +1,23 @@ +{ + "Records": [ + { + "messageId": "69bc4bbd-ed69-4325-a434-85c3b428ceab", + "receiptHandle": "AQEBbfAqjhrgIdW3HGWYPz57mdDatG/dT9LZhRPAsNQ1pJmw495w4esDc8ZSbOwMZuPBol7wtiNWug8U25GpSQDDLY1qv//8/lfmdzXOiprG6xRVeiXSHj0j731rJQ3xo+GPdGjOzjIxI09CrE3HtZ4lpXY9NjjHzP8hdxkCLlbttumc8hDBUR365/Tk+GfV2nNP9qvZtLGEbKCdTm/GYdTSoAr+ML9HnnGrS9T25Md71ASiZMI4DZqptN6g7CYYojFPs1LVM9o1258ferA72zbNoQ==", + "body": "{\n \"Type\" : \"Notification\",\n \"MessageId\" : \"a7c9d2fa-77fa-5184-9de9-89391027cc7d\",\n \"SequenceNumber\" : \"10000000000000004000\",\n \"TopicArn\" : \"arn:aws:sns:eu-west-1:231436140809:Test.fifo\",\n \"Message\" : \"{\\\"message\\\": \\\"hello world\\\", \\\"username\\\": \\\"lessa\\\"}\",\n \"Timestamp\" : \"2022-10-14T13:35:25.419Z\",\n \"UnsubscribeURL\" : \"https://sns.eu-west-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:eu-west-1:231436140809:Test.fifo:bb81d3de-a0f9-46e4-b619-d3152a4d545f\"\n}", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1665754525442", + "SequenceNumber": "18873177232222703872", + "MessageGroupId": "powertools-test", + "SenderId": "AIDAWYJAWPFU7SUQGUJC6", + "MessageDeduplicationId": "4e0a0f61eed277a4b9e4c01d5722b07b0725e42fe782102abee5711adfac701f", + "ApproximateFirstReceiveTimestamp": "1665754525442" + }, + "messageAttributes": {}, + "md5OfBody": "f3c788e623445e3feb263e80c1bffc0b", + "eventSource": "aws:sqs", + "eventSourceARN": "arn:aws:sqs:eu-west-1:231436140809:Test.fifo", + "awsRegion": "eu-west-1" + } + ] +} \ No newline at end of file diff --git a/packages/parser/tests/events/sqsEvent.json b/packages/parser/tests/events/sqsEvent.json new file mode 100644 index 0000000000..2bfcd1c7b8 --- /dev/null +++ b/packages/parser/tests/events/sqsEvent.json @@ -0,0 +1,42 @@ +{ + "Records": [ + { + "messageId": "059f36b4-87a3-44ab-83d2-661975830a7d", + "receiptHandle": "AQEBwJnKyrHigUMZj6rYigCgxlaS3SLy0a...", + "body": "Test message.", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1545082649183", + "SenderId": "AIDAIENQZJOLO23YVJ4VO", + "ApproximateFirstReceiveTimestamp": "1545082649185" + }, + "messageAttributes": { + "testAttr": { + "stringValue": "100", + "binaryValue": "base64Str", + "dataType": "Number" + } + }, + "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", + "eventSource": "aws:sqs", + "eventSourceARN": "arn:aws:sqs:us-east-2:123456789012:my-queue", + "awsRegion": "us-east-2" + }, + { + "messageId": "2e1424d4-f796-459a-8184-9c92662be6da", + "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", + "body": "{\"message\": \"foo1\"}", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1545082650636", + "SenderId": "AIDAIENQZJOLO23YVJ4VO", + "ApproximateFirstReceiveTimestamp": "1545082650649" + }, + "messageAttributes": {}, + "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", + "eventSource": "aws:sqs", + "eventSourceARN": "arn:aws:sqs:us-east-2:123456789012:my-queue", + "awsRegion": "us-east-2" + } + ] +} diff --git a/packages/parser/tests/events/vpcLatticeEvent.json b/packages/parser/tests/events/vpcLatticeEvent.json new file mode 100644 index 0000000000..936bfb22d1 --- /dev/null +++ b/packages/parser/tests/events/vpcLatticeEvent.json @@ -0,0 +1,15 @@ +{ + "raw_path": "/testpath", + "method": "GET", + "headers": { + "user_agent": "curl/7.64.1", + "x-forwarded-for": "10.213.229.10", + "host": "test-lambda-service-3908sdf9u3u.dkfjd93.vpc-lattice-svcs.us-east-2.on.aws", + "accept": "*/*" + }, + "query_string_parameters": { + "order-id": "1" + }, + "body": "eyJ0ZXN0IjogImV2ZW50In0=", + "is_base64_encoded": true +} diff --git a/packages/parser/tests/events/vpcLatticeEventPathTrailingSlash.json b/packages/parser/tests/events/vpcLatticeEventPathTrailingSlash.json new file mode 100644 index 0000000000..7f6c0cfd9a --- /dev/null +++ b/packages/parser/tests/events/vpcLatticeEventPathTrailingSlash.json @@ -0,0 +1,15 @@ +{ + "raw_path": "/testpath/", + "method": "GET", + "headers": { + "user_agent": "curl/7.64.1", + "x-forwarded-for": "10.213.229.10", + "host": "test-lambda-service-3908sdf9u3u.dkfjd93.vpc-lattice-svcs.us-east-2.on.aws", + "accept": "*/*" + }, + "query_string_parameters": { + "order-id": "1" + }, + "body": "eyJ0ZXN0IjogImV2ZW50In0=", + "is_base64_encoded": true +} diff --git a/packages/parser/tests/events/vpcLatticeEventV2PathTrailingSlash.json b/packages/parser/tests/events/vpcLatticeEventV2PathTrailingSlash.json new file mode 100644 index 0000000000..5f5fa7edd7 --- /dev/null +++ b/packages/parser/tests/events/vpcLatticeEventV2PathTrailingSlash.json @@ -0,0 +1,30 @@ +{ + "version": "2.0", + "path": "/newpath/", + "method": "GET", + "headers": { + "user_agent": "curl/7.64.1", + "x-forwarded-for": "10.213.229.10", + "host": "test-lambda-service-3908sdf9u3u.dkfjd93.vpc-lattice-svcs.us-east-2.on.aws", + "accept": "*/*" + }, + "query_string_parameters": { + "order-id": "1" + }, + "body": "{\"message\": \"Hello from Lambda!\"}", + "isBase64Encoded": false, + "requestContext": { + "serviceNetworkArn": "arn:aws:vpc-lattice:us-east-2:123456789012:servicenetwork/sn-0bf3f2882e9cc805a", + "serviceArn": "arn:aws:vpc-lattice:us-east-2:123456789012:service/svc-0a40eebed65f8d69c", + "targetGroupArn": "arn:aws:vpc-lattice:us-east-2:123456789012:targetgroup/tg-6d0ecf831eec9f09", + "identity": { + "sourceVpcArn": "arn:aws:ec2:region:123456789012:vpc/vpc-0b8276c84697e7339", + "type" : "AWS_IAM", + "principal": "arn:aws:sts::123456789012:assumed-role/example-role/057d00f8b51257ba3c853a0f248943cf", + "sessionName": "057d00f8b51257ba3c853a0f248943cf", + "x509SanDns": "example.com" + }, + "region": "us-east-2", + "timeEpoch": "1696331543569073" + } +} diff --git a/packages/parser/tests/events/vpcLatticeV2Event.json b/packages/parser/tests/events/vpcLatticeV2Event.json new file mode 100644 index 0000000000..fe10d83a3a --- /dev/null +++ b/packages/parser/tests/events/vpcLatticeV2Event.json @@ -0,0 +1,30 @@ +{ + "version": "2.0", + "path": "/newpath", + "method": "GET", + "headers": { + "user_agent": "curl/7.64.1", + "x-forwarded-for": "10.213.229.10", + "host": "test-lambda-service-3908sdf9u3u.dkfjd93.vpc-lattice-svcs.us-east-2.on.aws", + "accept": "*/*" + }, + "queryStringParameters": { + "order-id": "1" + }, + "body": "{\"message\": \"Hello from Lambda!\"}", + "isBase64Encoded": false, + "requestContext": { + "serviceNetworkArn": "arn:aws:vpc-lattice:us-east-2:123456789012:servicenetwork/sn-0bf3f2882e9cc805a", + "serviceArn": "arn:aws:vpc-lattice:us-east-2:123456789012:service/svc-0a40eebed65f8d69c", + "targetGroupArn": "arn:aws:vpc-lattice:us-east-2:123456789012:targetgroup/tg-6d0ecf831eec9f09", + "identity": { + "sourceVpcArn": "arn:aws:ec2:region:123456789012:vpc/vpc-0b8276c84697e7339", + "type" : "AWS_IAM", + "principal": "arn:aws:sts::123456789012:assumed-role/example-role/057d00f8b51257ba3c853a0f248943cf", + "sessionName": "057d00f8b51257ba3c853a0f248943cf", + "x509SanDns": "example.com" + }, + "region": "us-east-2", + "timeEpoch": "1696331543569073" + } +} diff --git a/packages/parser/tests/tsconfig.json b/packages/parser/tests/tsconfig.json index 5654b3e15f..67322d5174 100644 --- a/packages/parser/tests/tsconfig.json +++ b/packages/parser/tests/tsconfig.json @@ -1,6 +1,7 @@ { "extends": "../tsconfig.json", "compilerOptions": { + "resolveJsonModule": true, "rootDir": "../", "noEmit": true }, diff --git a/packages/parser/tests/unit/dynamodb.test.ts b/packages/parser/tests/unit/dynamodb.test.ts deleted file mode 100644 index 105bbd9ad0..0000000000 --- a/packages/parser/tests/unit/dynamodb.test.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { DynamoDBStreamSchema } from '../../src/schemas/dynamodb'; - -describe('DynamoDB', () => { - it('should parse a stream of records', () => { - DynamoDBStreamSchema.parse({ - Records: [ - { - eventID: '500c3b0d1c4e9d661540d744ec6270a0', - eventName: 'INSERT', - eventVersion: '1.1', - eventSource: 'aws:dynamodb', - awsRegion: 'eu-west-1', - dynamodb: { - ApproximateCreationDateTime: 1696258322, - Keys: { - id: { - S: '11231', - }, - }, - NewImage: { - name: { - S: 'John Doe', - }, - id: { - S: '11231', - }, - }, - SequenceNumber: '300000000015609734923', - SizeBytes: 26, - StreamViewType: 'NEW_AND_OLD_IMAGES', - }, - eventSourceARN: - 'arn:aws:dynamodb:eu-west-1:770231343013:table/AwsEventsStack-TableCD117FA1-XT5WRCQNWMBQ/stream/2023-10-02T12:16:42.661', - }, - { - eventID: '500c3b0d1c4e9d661540d744ec6270a0', - eventName: 'INSERT', - eventVersion: '1.1', - eventSource: 'aws:dynamodb', - awsRegion: 'eu-west-1', - dynamodb: { - ApproximateCreationDateTime: 1696258322, - Keys: { - id: { - S: '11231', - }, - }, - NewImage: { - name: { - S: 'John Doe', - }, - id: { - S: '11231', - }, - }, - SequenceNumber: '300000000015609734923', - SizeBytes: 26, - StreamViewType: 'NEW_AND_OLD_IMAGES', - }, - eventSourceARN: - 'arn:aws:dynamodb:eu-west-1:770231343013:table/AwsEventsStack-TableCD117FA1-XT5WRCQNWMBQ/stream/2023-10-02T12:16:42.661', - }, - ], - }); - }); -}); diff --git a/packages/parser/tests/unit/schema/schema.test.ts b/packages/parser/tests/unit/schema/schema.test.ts new file mode 100644 index 0000000000..95b077f49e --- /dev/null +++ b/packages/parser/tests/unit/schema/schema.test.ts @@ -0,0 +1,82 @@ +/** + * Test built in schema + * + * @group unit/parser/schema/ + */ +import dynamodbStreamEvent from '../../events/dynamoStreamEvent.json'; +import albEvent from '../../events/albEvent.json'; +import apiGatewayProxyEvent from '../../events/apiGatewayProxyEvent.json'; +import apiGatewayProxyV2Event from '../../events/apiGatewayProxyV2Event.json'; +import cloudFormationCustomResourceCreateEvent from '../../events/cloudformationCustomResourceCreate.json'; +import cloudFormationCustomResourceUpdateEvent from '../../events/cloudformationCustomResourceUpdate.json'; +import cloudFormationCustomResourceDeleteEvent from '../../events/cloudformationCustomResourceDelete.json'; +import eventBridgeEvent from '../../events/eventBridgeEvent.json'; +import s3Event from '../../events/s3Event.json'; +import sesEvent from '../../events/sesEvent.json'; +import snsEvent from '../../events/snsEvent.json'; +import sqsEvent from '../../events/sqsEvent.json'; +import { + AlbSchema, + APIGatewayProxyEventSchema, + APIGatewayProxyEventV2Schema, + CloudFormationCustomResourceCreateSchema, + CloudFormationCustomResourceUpdateSchema, + CloudFormationCustomResourceDeleteSchema, + DynamoDBStreamSchema, + EventBridgeSchema, + S3Schema, + SesSchema, + SnsSchema, + SqsSchema, +} from '../../../src'; + +/** + * keep everything in one describe block for now. + * once we have more examples, we can break them out into their own describe blocks + */ +describe('Schema:', () => { + it('DynamoDB should parse a stream of records', () => { + DynamoDBStreamSchema.parse(dynamodbStreamEvent); + }); + it('ALB should parse alb event', () => { + AlbSchema.parse(albEvent); + }); + it('APIGateway should parse api gateway event', () => { + APIGatewayProxyEventSchema.parse(apiGatewayProxyEvent); + }); + it('APIGatewayV2 should parse api gateway v2 event', () => { + APIGatewayProxyEventV2Schema.parse(apiGatewayProxyV2Event); + }); + describe('CloudFormationCustomResource ', () => { + it('should parse create event', () => { + CloudFormationCustomResourceCreateSchema.parse( + cloudFormationCustomResourceCreateEvent + ); + }); + it('should parse update event', () => { + CloudFormationCustomResourceUpdateSchema.parse( + cloudFormationCustomResourceUpdateEvent + ); + }); + it('should parse delete event', () => { + CloudFormationCustomResourceDeleteSchema.parse( + cloudFormationCustomResourceDeleteEvent + ); + }); + }); + it('EventBridge should parse eventbridge event', () => { + EventBridgeSchema.parse(eventBridgeEvent); + }); + it('S3 should parse s3 event', () => { + S3Schema.parse(s3Event); + }); + it('SNS should parse sns event', () => { + SnsSchema.parse(snsEvent); + }); + it('SQS should parse sqs event', () => { + SqsSchema.parse(sqsEvent); + }); + it('SES should parse ses event', () => { + SesSchema.parse(sesEvent); + }); +}); From 5bcab2e169a86de38219bc25481855dc405c2311 Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Fri, 10 Nov 2023 15:56:01 +0100 Subject: [PATCH 07/48] add more tests for schemas --- packages/parser/src/schemas/alb.ts | 11 +++- packages/parser/src/schemas/apigw.ts | 4 +- packages/parser/src/schemas/s3.ts | 10 ++- packages/parser/tests/tsconfig.json | 1 + .../parser/tests/unit/schema/schema.test.ts | 64 ++++++++++++++++--- 5 files changed, 73 insertions(+), 17 deletions(-) diff --git a/packages/parser/src/schemas/alb.ts b/packages/parser/src/schemas/alb.ts index 24b51c6786..54d5de4fed 100644 --- a/packages/parser/src/schemas/alb.ts +++ b/packages/parser/src/schemas/alb.ts @@ -5,8 +5,8 @@ const AlbSchema = z.object({ path: z.string(), body: z.string(), isBase64Encoded: z.boolean(), - headers: z.record(z.string(), z.string()), - queryStringParameters: z.record(z.string(), z.string()), + headers: z.record(z.string(), z.string()).optional(), + queryStringParameters: z.record(z.string(), z.string()).optional(), requestContext: z.object({ elb: z.object({ targetGroupArn: z.string(), @@ -14,4 +14,9 @@ const AlbSchema = z.object({ }), }); -export { AlbSchema }; +const AlbMultiValueHeadersSchema = AlbSchema.extend({ + multiValueHeaders: z.record(z.string(), z.array(z.string())), + multiValueQueryStringParameters: z.record(z.string(), z.array(z.string())), +}); + +export { AlbSchema, AlbMultiValueHeadersSchema }; diff --git a/packages/parser/src/schemas/apigw.ts b/packages/parser/src/schemas/apigw.ts index 1ab89ebd27..db5c9981ec 100644 --- a/packages/parser/src/schemas/apigw.ts +++ b/packages/parser/src/schemas/apigw.ts @@ -42,9 +42,9 @@ const APIGatewayProxyEventSchema = z.object({ 'HEAD', 'OPTIONS', ]), - headers: z.record(z.string()), - multiValueHeaders: z.record(z.array(z.string())), + headers: z.record(z.string()).optional(), queryStringParameters: z.record(z.string()).optional(), + multiValueHeaders: z.record(z.array(z.string())).optional(), multiValueQueryStringParameters: z.record(z.array(z.string())).optional(), requestContext: APIGatewayEventRequestContext, pathParameters: z.record(z.string()).optional().nullish(), diff --git a/packages/parser/src/schemas/s3.ts b/packages/parser/src/schemas/s3.ts index 614ccddade..0a64a48395 100644 --- a/packages/parser/src/schemas/s3.ts +++ b/packages/parser/src/schemas/s3.ts @@ -49,7 +49,7 @@ const S3Record = z.object({ glacierEventData: z.optional(S3EventRecordGlacierEventData), }); -const S3EventNotificationEventBridgeSchema = z.object({ +const S3EventNotificationEventBridgeDetailSchema = z.object({ version: z.string(), bucket: z.object({ name: z.string(), @@ -58,12 +58,12 @@ const S3EventNotificationEventBridgeSchema = z.object({ key: z.string(), size: z.number().nonnegative().optional(), etag: z.string(), - 'version-id': z.string(), + 'version-id': z.string().optional(), sequencer: z.string().optional(), }), 'request-id': z.string(), requester: z.string(), - 'source-ip-address': z.string().ip(), + 'source-ip-address': z.string().ip().optional(), reason: z.string().optional(), 'deletion-type': z.string().optional(), 'restore-expiry-time': z.string().optional(), @@ -72,6 +72,10 @@ const S3EventNotificationEventBridgeSchema = z.object({ 'destination-access-tier': z.string().optional(), }); +const S3EventNotificationEventBridgeSchema = z.object({ + detail: S3EventNotificationEventBridgeDetailSchema, +}); + const S3Schema = z.object({ Records: z.array(S3Record), }); diff --git a/packages/parser/tests/tsconfig.json b/packages/parser/tests/tsconfig.json index 67322d5174..de1bac4ef4 100644 --- a/packages/parser/tests/tsconfig.json +++ b/packages/parser/tests/tsconfig.json @@ -8,5 +8,6 @@ "include": [ "../src/**/*", "./**/*", + "../tests/events/*.json" ] } \ No newline at end of file diff --git a/packages/parser/tests/unit/schema/schema.test.ts b/packages/parser/tests/unit/schema/schema.test.ts index 95b077f49e..7e68a9d3da 100644 --- a/packages/parser/tests/unit/schema/schema.test.ts +++ b/packages/parser/tests/unit/schema/schema.test.ts @@ -5,13 +5,20 @@ */ import dynamodbStreamEvent from '../../events/dynamoStreamEvent.json'; import albEvent from '../../events/albEvent.json'; +import albEventPathTrailingSlash from '../../events/albEventPathTrailingSlash.json'; +import albMultiValueHeadersEvent from '../../events/albMultiValueHeadersEvent.json'; import apiGatewayProxyEvent from '../../events/apiGatewayProxyEvent.json'; +import apiGatewayAuthorizerRequestEvent from '../../events/apiGatewayAuthorizerRequestEvent.json'; import apiGatewayProxyV2Event from '../../events/apiGatewayProxyV2Event.json'; import cloudFormationCustomResourceCreateEvent from '../../events/cloudformationCustomResourceCreate.json'; import cloudFormationCustomResourceUpdateEvent from '../../events/cloudformationCustomResourceUpdate.json'; import cloudFormationCustomResourceDeleteEvent from '../../events/cloudformationCustomResourceDelete.json'; import eventBridgeEvent from '../../events/eventBridgeEvent.json'; import s3Event from '../../events/s3Event.json'; +import s3EventBridgeNotificationObjectCreatedEvent from '../../events/s3EventBridgeNotificationObjectCreatedEvent.json'; +import s3EventBridgeNotificationObjectDeletedEvent from '../../events/s3EventBridgeNotificationObjectDeletedEvent.json'; +import s3EventBridgeNotificationObjectExpiredEvent from '../../events/s3EventBridgeNotificationObjectExpiredEvent.json'; +import s3SqsEvent from '../../events/s3SqsEvent.json'; import sesEvent from '../../events/sesEvent.json'; import snsEvent from '../../events/snsEvent.json'; import sqsEvent from '../../events/sqsEvent.json'; @@ -28,6 +35,9 @@ import { SesSchema, SnsSchema, SqsSchema, + S3EventNotificationEventBridgeSchema, + S3SqsEventNotificationSchema, + AlbMultiValueHeadersSchema, } from '../../../src'; /** @@ -35,14 +45,24 @@ import { * once we have more examples, we can break them out into their own describe blocks */ describe('Schema:', () => { - it('DynamoDB should parse a stream of records', () => { - DynamoDBStreamSchema.parse(dynamodbStreamEvent); - }); - it('ALB should parse alb event', () => { - AlbSchema.parse(albEvent); + describe('ALB ', () => { + it('should parse alb event', () => { + AlbSchema.parse(albEvent); + }); + it('should parse alb event path trailing slash', () => { + AlbSchema.parse(albEventPathTrailingSlash); + }); + it('should parse alb event with multi value headers event', () => { + AlbMultiValueHeadersSchema.parse(albMultiValueHeadersEvent); + }); }); - it('APIGateway should parse api gateway event', () => { - APIGatewayProxyEventSchema.parse(apiGatewayProxyEvent); + describe('APIGateway ', () => { + it('should parse api gateway event', () => { + APIGatewayProxyEventSchema.parse(apiGatewayProxyEvent); + }); + it('should parse api gateway authorizer request event', () => { + APIGatewayProxyEventSchema.parse(apiGatewayAuthorizerRequestEvent); + }); }); it('APIGatewayV2 should parse api gateway v2 event', () => { APIGatewayProxyEventV2Schema.parse(apiGatewayProxyV2Event); @@ -64,11 +84,37 @@ describe('Schema:', () => { ); }); }); + it('DynamoDB should parse a stream of records', () => { + DynamoDBStreamSchema.parse(dynamodbStreamEvent); + }); it('EventBridge should parse eventbridge event', () => { EventBridgeSchema.parse(eventBridgeEvent); }); - it('S3 should parse s3 event', () => { - S3Schema.parse(s3Event); + describe('S3 ', () => { + it('should parse s3 event', () => { + S3Schema.parse(s3Event); + }); + + it('should parse s3 event bridge notification event created', () => { + S3EventNotificationEventBridgeSchema.parse( + s3EventBridgeNotificationObjectCreatedEvent + ); + }); + + it('should parse s3 event bridge notification event detelted', () => { + S3EventNotificationEventBridgeSchema.parse( + s3EventBridgeNotificationObjectDeletedEvent + ); + }); + it('should parse s3 event bridge notification event expired', () => { + S3EventNotificationEventBridgeSchema.parse( + s3EventBridgeNotificationObjectExpiredEvent + ); + }); + + it('should parse s3 sqs notification event', () => { + S3SqsEventNotificationSchema.parse(s3SqsEvent); + }); }); it('SNS should parse sns event', () => { SnsSchema.parse(snsEvent); From 0e9db619d960dcfa68bcb5167d1cc07800c47093 Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Fri, 10 Nov 2023 16:07:05 +0100 Subject: [PATCH 08/48] remove index export --- packages/parser/src/schemas/index.ts | 10 --------- .../parser/tests/unit/schema/schema.test.ts | 22 +++++++++++-------- 2 files changed, 13 insertions(+), 19 deletions(-) delete mode 100644 packages/parser/src/schemas/index.ts diff --git a/packages/parser/src/schemas/index.ts b/packages/parser/src/schemas/index.ts deleted file mode 100644 index a128fa1b9d..0000000000 --- a/packages/parser/src/schemas/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -export * from './dynamodb.js'; -export * from './alb.js'; -export * from './apigw.js'; -export * from './apigwv2.js'; -export * from './cloudformation-custom-resource.js'; -export * from './eventbridge.js'; -export * from './s3.js'; -export * from './sns.js'; -export * from './sqs.js'; -export * from './ses.js'; diff --git a/packages/parser/tests/unit/schema/schema.test.ts b/packages/parser/tests/unit/schema/schema.test.ts index 7e68a9d3da..5c34fd8738 100644 --- a/packages/parser/tests/unit/schema/schema.test.ts +++ b/packages/parser/tests/unit/schema/schema.test.ts @@ -24,21 +24,25 @@ import snsEvent from '../../events/snsEvent.json'; import sqsEvent from '../../events/sqsEvent.json'; import { AlbSchema, - APIGatewayProxyEventSchema, - APIGatewayProxyEventV2Schema, + AlbMultiValueHeadersSchema, +} from '../../../src/schemas/alb'; +import { APIGatewayProxyEventSchema } from '../../../src/schemas/apigw'; +import { APIGatewayProxyEventV2Schema } from '../../../src/schemas/apigwv2'; +import { CloudFormationCustomResourceCreateSchema, CloudFormationCustomResourceUpdateSchema, CloudFormationCustomResourceDeleteSchema, - DynamoDBStreamSchema, - EventBridgeSchema, +} from '../../../src/schemas/cloudformation-custom-resource'; +import { DynamoDBStreamSchema } from '../../../src/schemas/dynamodb'; +import { EventBridgeSchema } from '../../../src/schemas/eventbridge'; +import { S3Schema, - SesSchema, - SnsSchema, - SqsSchema, S3EventNotificationEventBridgeSchema, S3SqsEventNotificationSchema, - AlbMultiValueHeadersSchema, -} from '../../../src'; +} from '../../../src/schemas/s3'; +import { SnsSchema } from '../../../src/schemas/sns'; +import { SqsSchema } from '../../../src/schemas/sqs'; +import { SesSchema } from '../../../src/schemas/ses'; /** * keep everything in one describe block for now. From c06989b0fc82d8d7f67fa2d3e83fb999b06558e9 Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Mon, 13 Nov 2023 12:03:39 +0100 Subject: [PATCH 09/48] add cloudwatch with base64 zlip transform --- packages/parser/src/schemas/cloudwatch.ts | 36 +++++++++++++++++++ .../parser/tests/unit/schema/schema.test.ts | 11 ++++++ 2 files changed, 47 insertions(+) create mode 100644 packages/parser/src/schemas/cloudwatch.ts diff --git a/packages/parser/src/schemas/cloudwatch.ts b/packages/parser/src/schemas/cloudwatch.ts new file mode 100644 index 0000000000..dcdb666226 --- /dev/null +++ b/packages/parser/src/schemas/cloudwatch.ts @@ -0,0 +1,36 @@ +import { z } from 'zod'; +import { gunzipSync } from 'zlib'; + +const CloudWatchLogEventSchema = z.object({ + id: z.string(), + timestamp: z.number(), + message: z.string(), +}); + +const CloudWatchLogsDecodeSchema = z.object({ + messageType: z.string(), + owner: z.string(), + logGroup: z.string(), + logStream: z.string(), + subscriptionFilters: z.array(z.string()), + logEvents: z.array(CloudWatchLogEventSchema), +}); + +const CloudWatchLogsSchema = z.object({ + awslogs: z.object({ + data: z.string().transform((data) => { + try { + console.debug('Decoding data', data); + const uncompressed = gunzipSync(Buffer.from(data, 'base64')).toString( + 'utf8' + ); + + return CloudWatchLogsDecodeSchema.parse(JSON.parse(uncompressed)); + } catch (e) { + console.debug('Failed to gunzip data', e); + } + }), + }), +}); + +export { CloudWatchLogsSchema }; diff --git a/packages/parser/tests/unit/schema/schema.test.ts b/packages/parser/tests/unit/schema/schema.test.ts index 5c34fd8738..f2a31e9271 100644 --- a/packages/parser/tests/unit/schema/schema.test.ts +++ b/packages/parser/tests/unit/schema/schema.test.ts @@ -13,6 +13,7 @@ import apiGatewayProxyV2Event from '../../events/apiGatewayProxyV2Event.json'; import cloudFormationCustomResourceCreateEvent from '../../events/cloudformationCustomResourceCreate.json'; import cloudFormationCustomResourceUpdateEvent from '../../events/cloudformationCustomResourceUpdate.json'; import cloudFormationCustomResourceDeleteEvent from '../../events/cloudformationCustomResourceDelete.json'; +import cloudWatchLogEvent from '../../events/cloudWatchLogEvent.json'; import eventBridgeEvent from '../../events/eventBridgeEvent.json'; import s3Event from '../../events/s3Event.json'; import s3EventBridgeNotificationObjectCreatedEvent from '../../events/s3EventBridgeNotificationObjectCreatedEvent.json'; @@ -43,6 +44,7 @@ import { import { SnsSchema } from '../../../src/schemas/sns'; import { SqsSchema } from '../../../src/schemas/sqs'; import { SesSchema } from '../../../src/schemas/ses'; +import { CloudWatchLogsSchema } from '../../../src/schemas/cloudwatch'; /** * keep everything in one describe block for now. @@ -88,6 +90,15 @@ describe('Schema:', () => { ); }); }); + it('CloudWatchLogs should parse cloudwatch logs event', () => { + const parsed = CloudWatchLogsSchema.parse(cloudWatchLogEvent); + expect(parsed.awslogs.data).toBeDefined(); + expect(parsed.awslogs.data?.logEvents[0]).toEqual({ + id: 'eventId1', + timestamp: 1440442987000, + message: '[ERROR] First test message', + }); + }); it('DynamoDB should parse a stream of records', () => { DynamoDBStreamSchema.parse(dynamodbStreamEvent); }); From a4d385288d07caf043642959c8bfb3b259268ae9 Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Mon, 13 Nov 2023 12:05:51 +0100 Subject: [PATCH 10/48] add throw test case --- packages/parser/src/schemas/cloudwatch.ts | 1 + .../parser/tests/unit/schema/schema.test.ts | 25 +++++++++++++------ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/packages/parser/src/schemas/cloudwatch.ts b/packages/parser/src/schemas/cloudwatch.ts index dcdb666226..460970d15d 100644 --- a/packages/parser/src/schemas/cloudwatch.ts +++ b/packages/parser/src/schemas/cloudwatch.ts @@ -28,6 +28,7 @@ const CloudWatchLogsSchema = z.object({ return CloudWatchLogsDecodeSchema.parse(JSON.parse(uncompressed)); } catch (e) { console.debug('Failed to gunzip data', e); + throw e; } }), }), diff --git a/packages/parser/tests/unit/schema/schema.test.ts b/packages/parser/tests/unit/schema/schema.test.ts index f2a31e9271..d5356c8dcc 100644 --- a/packages/parser/tests/unit/schema/schema.test.ts +++ b/packages/parser/tests/unit/schema/schema.test.ts @@ -90,13 +90,24 @@ describe('Schema:', () => { ); }); }); - it('CloudWatchLogs should parse cloudwatch logs event', () => { - const parsed = CloudWatchLogsSchema.parse(cloudWatchLogEvent); - expect(parsed.awslogs.data).toBeDefined(); - expect(parsed.awslogs.data?.logEvents[0]).toEqual({ - id: 'eventId1', - timestamp: 1440442987000, - message: '[ERROR] First test message', + describe('CloudWatchLogs ', () => { + it('should parse cloudwatch logs event', () => { + const parsed = CloudWatchLogsSchema.parse(cloudWatchLogEvent); + expect(parsed.awslogs.data).toBeDefined(); + expect(parsed.awslogs.data?.logEvents[0]).toEqual({ + id: 'eventId1', + timestamp: 1440442987000, + message: '[ERROR] First test message', + }); + }); + it('should throw error if cloudwatch logs event is invalid', () => { + expect(() => + CloudWatchLogsSchema.parse({ + awslogs: { + data: 'invalid', + }, + }) + ).toThrowError(); }); }); it('DynamoDB should parse a stream of records', () => { From 7a2a2031ae05f8cdbf46092df2fd9139273aefc0 Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Mon, 13 Nov 2023 12:06:06 +0100 Subject: [PATCH 11/48] formatting --- docs/snippets/idempotency/samples/makeIdempotentJmes.json | 2 +- .../samples/workingWIthIdempotencyRequiredKeyError.json | 2 +- .../samples/workingWIthIdempotencyRequiredKeySuccess.json | 2 +- docs/snippets/idempotency/samples/workingWithBatch.json | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/snippets/idempotency/samples/makeIdempotentJmes.json b/docs/snippets/idempotency/samples/makeIdempotentJmes.json index 9f608983da..158b3a874f 100644 --- a/docs/snippets/idempotency/samples/makeIdempotentJmes.json +++ b/docs/snippets/idempotency/samples/makeIdempotentJmes.json @@ -27,4 +27,4 @@ }, "body": "{\"user\":\"xyz\",\"productId\":\"123456789\"}", "isBase64Encoded": false -} \ No newline at end of file +} diff --git a/docs/snippets/idempotency/samples/workingWIthIdempotencyRequiredKeyError.json b/docs/snippets/idempotency/samples/workingWIthIdempotencyRequiredKeyError.json index a905b83e7a..14ca8067ae 100644 --- a/docs/snippets/idempotency/samples/workingWIthIdempotencyRequiredKeyError.json +++ b/docs/snippets/idempotency/samples/workingWIthIdempotencyRequiredKeyError.json @@ -4,4 +4,4 @@ "name": "foo", "productId": 10000 } -} \ No newline at end of file +} diff --git a/docs/snippets/idempotency/samples/workingWIthIdempotencyRequiredKeySuccess.json b/docs/snippets/idempotency/samples/workingWIthIdempotencyRequiredKeySuccess.json index e721b2c24c..ef9c932907 100644 --- a/docs/snippets/idempotency/samples/workingWIthIdempotencyRequiredKeySuccess.json +++ b/docs/snippets/idempotency/samples/workingWIthIdempotencyRequiredKeySuccess.json @@ -4,4 +4,4 @@ "name": "Foo" }, "productId": 10000 -} \ No newline at end of file +} diff --git a/docs/snippets/idempotency/samples/workingWithBatch.json b/docs/snippets/idempotency/samples/workingWithBatch.json index 44bd07a141..73a5029d61 100644 --- a/docs/snippets/idempotency/samples/workingWithBatch.json +++ b/docs/snippets/idempotency/samples/workingWithBatch.json @@ -23,4 +23,4 @@ "awsRegion": "us-east-2" } ] -} \ No newline at end of file +} From 689ef453431ccaf3e0f5ce007d1456582267dfbd Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Mon, 13 Nov 2023 13:34:18 +0100 Subject: [PATCH 12/48] add kafka schema --- packages/parser/src/schemas/kafka.ts | 44 +++++++++++++++++++ .../parser/tests/unit/schema/schema.test.ts | 31 +++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 packages/parser/src/schemas/kafka.ts diff --git a/packages/parser/src/schemas/kafka.ts b/packages/parser/src/schemas/kafka.ts new file mode 100644 index 0000000000..8c71a21097 --- /dev/null +++ b/packages/parser/src/schemas/kafka.ts @@ -0,0 +1,44 @@ +import { z } from 'zod'; + +const KafkaRecordSchema = z.object({ + topic: z.string(), + partition: z.number(), + offset: z.number(), + timestamp: z.number(), + timestampType: z.string(), + key: z.string().transform((key) => { + return key ? Buffer.from(key, 'base64').toString() : undefined; + }), + value: z.string().transform((value) => { + return value ? Buffer.from(value, 'base64').toString() : undefined; + }), + headers: z.array( + z.record( + z.string(), + z.array(z.number()).transform((value) => { + return String.fromCharCode(...value); + }) + ) + ), +}); + +const KafkaBaseEventSchema = z.object({ + bootstrapServers: z + .string() + .transform((bootstrapServers) => { + return bootstrapServers ? bootstrapServers.split(',') : undefined; + }) + .nullish(), + records: z.record(z.string(), z.array(KafkaRecordSchema)), +}); + +const KafkaSelfManagedEventSchema = KafkaBaseEventSchema.extend({ + eventSource: z.literal('aws:SelfManagedKafka'), +}); + +const KafkaMskEventSchema = KafkaBaseEventSchema.extend({ + eventSource: z.literal('aws:kafka'), + eventSourceArn: z.string(), +}); + +export { KafkaSelfManagedEventSchema, KafkaMskEventSchema }; diff --git a/packages/parser/tests/unit/schema/schema.test.ts b/packages/parser/tests/unit/schema/schema.test.ts index d5356c8dcc..adf386d05e 100644 --- a/packages/parser/tests/unit/schema/schema.test.ts +++ b/packages/parser/tests/unit/schema/schema.test.ts @@ -15,6 +15,8 @@ import cloudFormationCustomResourceUpdateEvent from '../../events/cloudformation import cloudFormationCustomResourceDeleteEvent from '../../events/cloudformationCustomResourceDelete.json'; import cloudWatchLogEvent from '../../events/cloudWatchLogEvent.json'; import eventBridgeEvent from '../../events/eventBridgeEvent.json'; +import kafkaEventMsk from '../../events/kafkaEventMsk.json'; +import kafkaEventSelfManaged from '../../events/kafkaEventSelfManaged.json'; import s3Event from '../../events/s3Event.json'; import s3EventBridgeNotificationObjectCreatedEvent from '../../events/s3EventBridgeNotificationObjectCreatedEvent.json'; import s3EventBridgeNotificationObjectDeletedEvent from '../../events/s3EventBridgeNotificationObjectDeletedEvent.json'; @@ -45,6 +47,10 @@ import { SnsSchema } from '../../../src/schemas/sns'; import { SqsSchema } from '../../../src/schemas/sqs'; import { SesSchema } from '../../../src/schemas/ses'; import { CloudWatchLogsSchema } from '../../../src/schemas/cloudwatch'; +import { + KafkaMskEventSchema, + KafkaSelfManagedEventSchema, +} from '../../../src/schemas/kafka'; /** * keep everything in one describe block for now. @@ -116,6 +122,31 @@ describe('Schema:', () => { it('EventBridge should parse eventbridge event', () => { EventBridgeSchema.parse(eventBridgeEvent); }); + describe('Kafka ', () => { + const expectedTestEvent = { + key: 'recordKey', + value: JSON.stringify({ key: 'value' }), + partition: 0, + topic: 'mytopic', + offset: 15, + timestamp: 1545084650987, + timestampType: 'CREATE_TIME', + headers: [ + { + headerKey: 'headerValue', + }, + ], + }; + it('should parse kafka MSK event', () => { + const parsed = KafkaMskEventSchema.parse(kafkaEventMsk); + + expect(parsed.records['mytopic-0'][0]).toEqual(expectedTestEvent); + }); + it('should parse kafka self managed event', () => { + const parsed = KafkaSelfManagedEventSchema.parse(kafkaEventSelfManaged); + expect(parsed.records['mytopic-0'][0]).toEqual(expectedTestEvent); + }); + }); describe('S3 ', () => { it('should parse s3 event', () => { S3Schema.parse(s3Event); From 7e0dd7186fa3b05afc88fa11b2c90c36302a808c Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Mon, 13 Nov 2023 16:44:02 +0100 Subject: [PATCH 13/48] restructured tests --- packages/parser/src/schemas/cloudwatch.ts | 36 ++-- .../parser/src/schemas/kinesis-firehose.ts | 55 ++++++ packages/parser/src/schemas/kinesis.ts | 35 ++++ packages/parser/src/schemas/sqs.ts | 2 +- packages/parser/tests/tsconfig.json | 3 +- packages/parser/tests/unit/schema/alb.test.ts | 24 +++ .../parser/tests/unit/schema/apigw.test.ts | 17 ++ .../parser/tests/unit/schema/apigwv2.test.ts | 13 ++ .../cloudformation-custom-resource.test.ts | 31 +++ .../tests/unit/schema/cloudwatch.test.ts | 28 +++ .../parser/tests/unit/schema/dynamodb.test.ts | 13 ++ .../tests/unit/schema/eventbridge.test.ts | 14 ++ .../parser/tests/unit/schema/kafka.test.ts | 37 ++++ .../parser/tests/unit/schema/kinesis.test.ts | 71 +++++++ packages/parser/tests/unit/schema/s3.test.ts | 42 ++++ .../parser/tests/unit/schema/schema.test.ts | 185 ------------------ packages/parser/tests/unit/schema/ses.test.ts | 13 ++ packages/parser/tests/unit/schema/sns.test.ts | 13 ++ packages/parser/tests/unit/schema/sqs.test.ts | 13 ++ 19 files changed, 444 insertions(+), 201 deletions(-) create mode 100644 packages/parser/src/schemas/kinesis-firehose.ts create mode 100644 packages/parser/src/schemas/kinesis.ts create mode 100644 packages/parser/tests/unit/schema/alb.test.ts create mode 100644 packages/parser/tests/unit/schema/apigw.test.ts create mode 100644 packages/parser/tests/unit/schema/apigwv2.test.ts create mode 100644 packages/parser/tests/unit/schema/cloudformation-custom-resource.test.ts create mode 100644 packages/parser/tests/unit/schema/cloudwatch.test.ts create mode 100644 packages/parser/tests/unit/schema/dynamodb.test.ts create mode 100644 packages/parser/tests/unit/schema/eventbridge.test.ts create mode 100644 packages/parser/tests/unit/schema/kafka.test.ts create mode 100644 packages/parser/tests/unit/schema/kinesis.test.ts create mode 100644 packages/parser/tests/unit/schema/s3.test.ts delete mode 100644 packages/parser/tests/unit/schema/schema.test.ts create mode 100644 packages/parser/tests/unit/schema/ses.test.ts create mode 100644 packages/parser/tests/unit/schema/sns.test.ts create mode 100644 packages/parser/tests/unit/schema/sqs.test.ts diff --git a/packages/parser/src/schemas/cloudwatch.ts b/packages/parser/src/schemas/cloudwatch.ts index 460970d15d..024be971c5 100644 --- a/packages/parser/src/schemas/cloudwatch.ts +++ b/packages/parser/src/schemas/cloudwatch.ts @@ -16,22 +16,30 @@ const CloudWatchLogsDecodeSchema = z.object({ logEvents: z.array(CloudWatchLogEventSchema), }); +function decompressRecordToJSON( + data: string +): z.infer { + try { + console.debug('Decoding data', data); + const uncompressed = gunzipSync(Buffer.from(data, 'base64')).toString( + 'utf8' + ); + + return CloudWatchLogsDecodeSchema.parse(JSON.parse(uncompressed)); + } catch (e) { + console.debug('Failed to gunzip data', e); + throw e; + } +} + const CloudWatchLogsSchema = z.object({ awslogs: z.object({ - data: z.string().transform((data) => { - try { - console.debug('Decoding data', data); - const uncompressed = gunzipSync(Buffer.from(data, 'base64')).toString( - 'utf8' - ); - - return CloudWatchLogsDecodeSchema.parse(JSON.parse(uncompressed)); - } catch (e) { - console.debug('Failed to gunzip data', e); - throw e; - } - }), + data: z.string().transform((data) => decompressRecordToJSON(data)), }), }); -export { CloudWatchLogsSchema }; +export { + CloudWatchLogsSchema, + CloudWatchLogsDecodeSchema, + decompressRecordToJSON, +}; diff --git a/packages/parser/src/schemas/kinesis-firehose.ts b/packages/parser/src/schemas/kinesis-firehose.ts new file mode 100644 index 0000000000..b5f3f72fd0 --- /dev/null +++ b/packages/parser/src/schemas/kinesis-firehose.ts @@ -0,0 +1,55 @@ +import { z } from 'zod'; +import { SqsRecordSchema } from './sqs.js'; + +const KinesisRecordMetaData = z.object({ + shardId: z.string(), + partitionKey: z.string(), + approximateArrivalTimestamp: z.number().positive(), + sequenceNumber: z.string(), + subsequenceNumber: z.number(), +}); + +const KinesisFireHoseRecordBase = z.object({ + recordId: z.string(), + approximateArrivalTimestamp: z.number().positive(), + kinesisRecordMetaData: KinesisRecordMetaData.optional(), +}); + +const KinesisFireHoseBaseSchema = z.object({ + invocationId: z.string(), + deliveryStreamArn: z.string(), + region: z.string(), + sourceKinesisStreamArn: z.string().optional(), +}); + +const KinesisFirehoseRecord = KinesisFireHoseRecordBase.extend({ + data: z + .string() + .transform((data) => Buffer.from(data, 'base64').toString('utf8')), +}); + +const KinesisFirehoseSqsRecord = KinesisFireHoseRecordBase.extend({ + data: z.string().transform((data) => { + try { + console.debug('Parsing sqs record', data); + + return SqsRecordSchema.parse( + JSON.parse(Buffer.from(data, 'base64').toString('utf8')) + ); + } catch (e) { + console.warn('Failed to parse sqs record', e); + + return data; + } + }), +}); + +const KinesisFirehoseSchema = KinesisFireHoseBaseSchema.extend({ + records: z.array(KinesisFirehoseRecord), +}); + +const KinesisFirehoseSqsSchema = KinesisFireHoseBaseSchema.extend({ + records: z.array(KinesisFirehoseSqsRecord), +}); + +export { KinesisFirehoseSchema, KinesisFirehoseSqsSchema }; diff --git a/packages/parser/src/schemas/kinesis.ts b/packages/parser/src/schemas/kinesis.ts new file mode 100644 index 0000000000..9369ea1f48 --- /dev/null +++ b/packages/parser/src/schemas/kinesis.ts @@ -0,0 +1,35 @@ +import { z } from 'zod'; +import { + CloudWatchLogsDecodeSchema, + decompressRecordToJSON, +} from './cloudwatch.js'; + +const KinesisDataStreamRecordPayload = z.object({ + kinesisSchemaVersion: z.string(), + partitionKey: z.string(), + sequenceNumber: z.string(), + approximateArrivalTimestamp: z.number(), + data: z.string(), +}); + +const KinesisDataStreamRecord = z.object({ + eventSource: z.literal('aws:kinesis'), + eventVersion: z.string(), + eventID: z.string(), + eventName: z.literal('aws:kinesis:record'), + invokeIdentityArn: z.string(), + eventSourceARN: z.string(), + kinesis: KinesisDataStreamRecordPayload, +}); + +const KinesisDataStreamSchema = z.object({ + Records: z.array(KinesisDataStreamRecord), +}); + +const extractCloudWatchLogFromEvent = ( + event: z.infer +): z.infer => { + return decompressRecordToJSON(event.kinesis.data); +}; + +export { KinesisDataStreamSchema, extractCloudWatchLogFromEvent }; diff --git a/packages/parser/src/schemas/sqs.ts b/packages/parser/src/schemas/sqs.ts index a10f2bfb46..844c8940ac 100644 --- a/packages/parser/src/schemas/sqs.ts +++ b/packages/parser/src/schemas/sqs.ts @@ -26,7 +26,7 @@ const SqsRecordSchema = z.object({ attributes: SqsAttributeSchema, messageAttributes: z.record(z.string(), SqsMsgAttributeSchema), md5OfBody: z.string(), - md5OfMessageAttributes: z.string().optional(), + md5OfMessageAttributes: z.string().optional().nullable(), eventSource: z.literal('aws:sqs'), eventSourceARN: z.string(), awsRegion: z.string(), diff --git a/packages/parser/tests/tsconfig.json b/packages/parser/tests/tsconfig.json index de1bac4ef4..706537574a 100644 --- a/packages/parser/tests/tsconfig.json +++ b/packages/parser/tests/tsconfig.json @@ -8,6 +8,7 @@ "include": [ "../src/**/*", "./**/*", - "../tests/events/*.json" + "../tests/events/*.json", + "../tests/events/*.*" ] } \ No newline at end of file diff --git a/packages/parser/tests/unit/schema/alb.test.ts b/packages/parser/tests/unit/schema/alb.test.ts new file mode 100644 index 0000000000..af583952e2 --- /dev/null +++ b/packages/parser/tests/unit/schema/alb.test.ts @@ -0,0 +1,24 @@ +/** + * Test built in schema + * + * @group unit/parser/schema/ + */ +import { + AlbSchema, + AlbMultiValueHeadersSchema, +} from '../../../src/schemas/alb'; +import albEvent from '../../events/albEvent.json'; +import albEventPathTrailingSlash from '../../events/albEventPathTrailingSlash.json'; +import albMultiValueHeadersEvent from '../../events/albMultiValueHeadersEvent.json'; + +describe('ALB ', () => { + it('should parse alb event', () => { + AlbSchema.parse(albEvent); + }); + it('should parse alb event path trailing slash', () => { + AlbSchema.parse(albEventPathTrailingSlash); + }); + it('should parse alb event with multi value headers event', () => { + AlbMultiValueHeadersSchema.parse(albMultiValueHeadersEvent); + }); +}); diff --git a/packages/parser/tests/unit/schema/apigw.test.ts b/packages/parser/tests/unit/schema/apigw.test.ts new file mode 100644 index 0000000000..ecb0a8d2cb --- /dev/null +++ b/packages/parser/tests/unit/schema/apigw.test.ts @@ -0,0 +1,17 @@ +/** + * Test built in schema + * + * @group unit/parser/schema/ + */ +import { APIGatewayProxyEventSchema } from '../../../src/schemas/apigw'; +import apiGatewayProxyEvent from '../../events/apiGatewayProxyEvent.json'; +import apiGatewayAuthorizerRequestEvent from '../../events/apiGatewayAuthorizerRequestEvent.json'; + +describe('APIGateway ', () => { + it('should parse api gateway event', () => { + APIGatewayProxyEventSchema.parse(apiGatewayProxyEvent); + }); + it('should parse api gateway authorizer request event', () => { + APIGatewayProxyEventSchema.parse(apiGatewayAuthorizerRequestEvent); + }); +}); diff --git a/packages/parser/tests/unit/schema/apigwv2.test.ts b/packages/parser/tests/unit/schema/apigwv2.test.ts new file mode 100644 index 0000000000..ed5ebba624 --- /dev/null +++ b/packages/parser/tests/unit/schema/apigwv2.test.ts @@ -0,0 +1,13 @@ +/** + * Test built in schema + * + * @group unit/parser/schema/ + */ +import { APIGatewayProxyEventV2Schema } from '../../../src/schemas/apigwv2'; +import apiGatewayProxyV2Event from '../../events/apiGatewayProxyV2Event.json'; + +describe('API GW v2 ', () => { + it('APIGatewayV2 should parse api gateway v2 event', () => { + APIGatewayProxyEventV2Schema.parse(apiGatewayProxyV2Event); + }); +}); diff --git a/packages/parser/tests/unit/schema/cloudformation-custom-resource.test.ts b/packages/parser/tests/unit/schema/cloudformation-custom-resource.test.ts new file mode 100644 index 0000000000..109dd60c49 --- /dev/null +++ b/packages/parser/tests/unit/schema/cloudformation-custom-resource.test.ts @@ -0,0 +1,31 @@ +/** + * Test built in schema + * + * @group unit/parser/schema/ + */ +import { + CloudFormationCustomResourceCreateSchema, + CloudFormationCustomResourceUpdateSchema, + CloudFormationCustomResourceDeleteSchema, +} from '../../../src/schemas/cloudformation-custom-resource'; +import cloudFormationCustomResourceCreateEvent from '../../events/cloudformationCustomResourceCreate.json'; +import cloudFormationCustomResourceUpdateEvent from '../../events/cloudformationCustomResourceUpdate.json'; +import cloudFormationCustomResourceDeleteEvent from '../../events/cloudformationCustomResourceDelete.json'; + +describe('CloudFormationCustomResource ', () => { + it('should parse create event', () => { + CloudFormationCustomResourceCreateSchema.parse( + cloudFormationCustomResourceCreateEvent + ); + }); + it('should parse update event', () => { + CloudFormationCustomResourceUpdateSchema.parse( + cloudFormationCustomResourceUpdateEvent + ); + }); + it('should parse delete event', () => { + CloudFormationCustomResourceDeleteSchema.parse( + cloudFormationCustomResourceDeleteEvent + ); + }); +}); diff --git a/packages/parser/tests/unit/schema/cloudwatch.test.ts b/packages/parser/tests/unit/schema/cloudwatch.test.ts new file mode 100644 index 0000000000..6a56fbe760 --- /dev/null +++ b/packages/parser/tests/unit/schema/cloudwatch.test.ts @@ -0,0 +1,28 @@ +/** + * Test built in schema + * + * @group unit/parser/schema/ + */ +import { CloudWatchLogsSchema } from '../../../src/schemas/cloudwatch'; +import cloudWatchLogEvent from '../../events/cloudWatchLogEvent.json'; + +describe('CloudWatchLogs ', () => { + it('should parse cloudwatch logs event', () => { + const parsed = CloudWatchLogsSchema.parse(cloudWatchLogEvent); + expect(parsed.awslogs.data).toBeDefined(); + expect(parsed.awslogs.data?.logEvents[0]).toEqual({ + id: 'eventId1', + timestamp: 1440442987000, + message: '[ERROR] First test message', + }); + }); + it('should throw error if cloudwatch logs event is invalid', () => { + expect(() => + CloudWatchLogsSchema.parse({ + awslogs: { + data: 'invalid', + }, + }) + ).toThrowError(); + }); +}); diff --git a/packages/parser/tests/unit/schema/dynamodb.test.ts b/packages/parser/tests/unit/schema/dynamodb.test.ts new file mode 100644 index 0000000000..f074b7f2c0 --- /dev/null +++ b/packages/parser/tests/unit/schema/dynamodb.test.ts @@ -0,0 +1,13 @@ +/** + * Test built in schema + * + * @group unit/parser/schema/ + */ +import { DynamoDBStreamSchema } from '../../../src/schemas/dynamodb'; +import dynamodbStreamEvent from '../../events/dynamoStreamEvent.json'; + +describe('DynamoDB ', () => { + it('should parse a stream of records', () => { + DynamoDBStreamSchema.parse(dynamodbStreamEvent); + }); +}); diff --git a/packages/parser/tests/unit/schema/eventbridge.test.ts b/packages/parser/tests/unit/schema/eventbridge.test.ts new file mode 100644 index 0000000000..fc068da859 --- /dev/null +++ b/packages/parser/tests/unit/schema/eventbridge.test.ts @@ -0,0 +1,14 @@ +/** + * Test built in schema + * + * @group unit/parser/schema/ + */ + +import { EventBridgeSchema } from '../../../src/schemas/eventbridge'; +import eventBridgeEvent from '../../events/eventBridgeEvent.json'; + +describe('EventBridge ', () => { + it('should parse eventbridge event', () => { + EventBridgeSchema.parse(eventBridgeEvent); + }); +}); diff --git a/packages/parser/tests/unit/schema/kafka.test.ts b/packages/parser/tests/unit/schema/kafka.test.ts new file mode 100644 index 0000000000..ad5e21e49d --- /dev/null +++ b/packages/parser/tests/unit/schema/kafka.test.ts @@ -0,0 +1,37 @@ +/** + * Test built in schema + * + * @group unit/parser/schema/ + */ +import { + KafkaMskEventSchema, + KafkaSelfManagedEventSchema, +} from '../../../src/schemas/kafka'; +import kafkaEventMsk from '../../events/kafkaEventMsk.json'; +import kafkaEventSelfManaged from '../../events/kafkaEventSelfManaged.json'; + +describe('Kafka ', () => { + const expectedTestEvent = { + key: 'recordKey', + value: JSON.stringify({ key: 'value' }), + partition: 0, + topic: 'mytopic', + offset: 15, + timestamp: 1545084650987, + timestampType: 'CREATE_TIME', + headers: [ + { + headerKey: 'headerValue', + }, + ], + }; + it('should parse kafka MSK event', () => { + const parsed = KafkaMskEventSchema.parse(kafkaEventMsk); + + expect(parsed.records['mytopic-0'][0]).toEqual(expectedTestEvent); + }); + it('should parse kafka self managed event', () => { + const parsed = KafkaSelfManagedEventSchema.parse(kafkaEventSelfManaged); + expect(parsed.records['mytopic-0'][0]).toEqual(expectedTestEvent); + }); +}); diff --git a/packages/parser/tests/unit/schema/kinesis.test.ts b/packages/parser/tests/unit/schema/kinesis.test.ts new file mode 100644 index 0000000000..829e3ef14b --- /dev/null +++ b/packages/parser/tests/unit/schema/kinesis.test.ts @@ -0,0 +1,71 @@ +/** + * Test built in schema + * + * @group unit/parser/schema/ + */ +import { + KinesisDataStreamSchema, + extractCloudWatchLogFromEvent, +} from '../../../src/schemas/kinesis'; +import kinesisStreamEvent from '../../events/kinesisStreamEvent.json'; +import kinesisStreamEventOneRecord from '../../events/kinesisStreamEventOneRecord.json'; +import { + KinesisFirehoseSchema, + KinesisFirehoseSqsSchema, +} from '../../../src/schemas/kinesis-firehose'; +import kinesisFirehoseKinesisEvent from '../../events/kinesisFirehoseKinesisEvent.json'; +import kinesisFirehosePutEvent from '../../events/kinesisFirehosePutEvent.json'; +import kinesisFirehoseSQSEvent from '../../events/kinesisFirehoseSQSEvent.json'; +import kinesisStreamCloudWatchLogsEvent from '../../events/kinesisStreamCloudWatchLogsEvent.json'; + +describe('Kinesis ', () => { + it('should parse kinesis event', () => { + const parsed = KinesisDataStreamSchema.parse(kinesisStreamEvent); + const decodedData = Buffer.from( + parsed.Records[0].kinesis.data, + 'base64' + ).toString('utf8'); + expect(decodedData).toEqual('Hello, this is a test.'); + }); + it('should prase single kinesis record', () => { + const parsed = KinesisDataStreamSchema.parse(kinesisStreamEventOneRecord); + const decodedJson = JSON.parse( + Buffer.from(parsed.Records[0].kinesis.data, 'base64').toString('utf8') + ); + expect(decodedJson).toEqual({ + message: 'test message', + username: 'test', + }); + }); + it('should parse Firehose event', () => { + const parsed = KinesisFirehoseSchema.parse(kinesisFirehoseKinesisEvent); + expect(parsed.records[0].data).toEqual('Hello World'); + }); + it('should parse Kinesis Firehose PutEvents event', () => { + const parsed = KinesisFirehoseSchema.parse(kinesisFirehosePutEvent); + expect(JSON.parse(parsed.records[1].data)).toEqual({ + Hello: 'World', + }); + }); + it('should parse Firehose event with SQS event', () => { + const parsed = KinesisFirehoseSqsSchema.parse(kinesisFirehoseSQSEvent); + console.log(parsed.records[0].data); + expect(parsed.records[0].data).toMatchObject({ + messageId: '5ab807d4-5644-4c55-97a3-47396635ac74', + body: 'Test message.', + }); + }); + it('should parse Firehose event with CloudWatch event', () => { + const parsed = KinesisDataStreamSchema.parse( + kinesisStreamCloudWatchLogsEvent + ); + + const jsonParsed = extractCloudWatchLogFromEvent(parsed.Records[0]); + expect(jsonParsed).toMatchObject({ + messageType: 'DATA_MESSAGE', + owner: '231436140809', + logGroup: '/aws/lambda/pt-1488-DummyLogDataFunction-gnWXPvL6jJyG', + logStream: '2022/11/10/[$LATEST]26b6a45d574f442ea28438923cbf7bf7', + }); + }); +}); diff --git a/packages/parser/tests/unit/schema/s3.test.ts b/packages/parser/tests/unit/schema/s3.test.ts new file mode 100644 index 0000000000..ea01401677 --- /dev/null +++ b/packages/parser/tests/unit/schema/s3.test.ts @@ -0,0 +1,42 @@ +/** + * Test built in schema + * + * @group unit/parser/schema/ + */ +import { + S3Schema, + S3EventNotificationEventBridgeSchema, + S3SqsEventNotificationSchema, +} from '../../../src/schemas/s3'; +import s3Event from '../../events/s3Event.json'; +import s3EventBridgeNotificationObjectCreatedEvent from '../../events/s3EventBridgeNotificationObjectCreatedEvent.json'; +import s3EventBridgeNotificationObjectDeletedEvent from '../../events/s3EventBridgeNotificationObjectDeletedEvent.json'; +import s3EventBridgeNotificationObjectExpiredEvent from '../../events/s3EventBridgeNotificationObjectExpiredEvent.json'; +import s3SqsEvent from '../../events/s3SqsEvent.json'; + +describe('S3 ', () => { + it('should parse s3 event', () => { + S3Schema.parse(s3Event); + }); + + it('should parse s3 event bridge notification event created', () => { + S3EventNotificationEventBridgeSchema.parse( + s3EventBridgeNotificationObjectCreatedEvent + ); + }); + + it('should parse s3 event bridge notification event detelted', () => { + S3EventNotificationEventBridgeSchema.parse( + s3EventBridgeNotificationObjectDeletedEvent + ); + }); + it('should parse s3 event bridge notification event expired', () => { + S3EventNotificationEventBridgeSchema.parse( + s3EventBridgeNotificationObjectExpiredEvent + ); + }); + + it('should parse s3 sqs notification event', () => { + S3SqsEventNotificationSchema.parse(s3SqsEvent); + }); +}); diff --git a/packages/parser/tests/unit/schema/schema.test.ts b/packages/parser/tests/unit/schema/schema.test.ts deleted file mode 100644 index adf386d05e..0000000000 --- a/packages/parser/tests/unit/schema/schema.test.ts +++ /dev/null @@ -1,185 +0,0 @@ -/** - * Test built in schema - * - * @group unit/parser/schema/ - */ -import dynamodbStreamEvent from '../../events/dynamoStreamEvent.json'; -import albEvent from '../../events/albEvent.json'; -import albEventPathTrailingSlash from '../../events/albEventPathTrailingSlash.json'; -import albMultiValueHeadersEvent from '../../events/albMultiValueHeadersEvent.json'; -import apiGatewayProxyEvent from '../../events/apiGatewayProxyEvent.json'; -import apiGatewayAuthorizerRequestEvent from '../../events/apiGatewayAuthorizerRequestEvent.json'; -import apiGatewayProxyV2Event from '../../events/apiGatewayProxyV2Event.json'; -import cloudFormationCustomResourceCreateEvent from '../../events/cloudformationCustomResourceCreate.json'; -import cloudFormationCustomResourceUpdateEvent from '../../events/cloudformationCustomResourceUpdate.json'; -import cloudFormationCustomResourceDeleteEvent from '../../events/cloudformationCustomResourceDelete.json'; -import cloudWatchLogEvent from '../../events/cloudWatchLogEvent.json'; -import eventBridgeEvent from '../../events/eventBridgeEvent.json'; -import kafkaEventMsk from '../../events/kafkaEventMsk.json'; -import kafkaEventSelfManaged from '../../events/kafkaEventSelfManaged.json'; -import s3Event from '../../events/s3Event.json'; -import s3EventBridgeNotificationObjectCreatedEvent from '../../events/s3EventBridgeNotificationObjectCreatedEvent.json'; -import s3EventBridgeNotificationObjectDeletedEvent from '../../events/s3EventBridgeNotificationObjectDeletedEvent.json'; -import s3EventBridgeNotificationObjectExpiredEvent from '../../events/s3EventBridgeNotificationObjectExpiredEvent.json'; -import s3SqsEvent from '../../events/s3SqsEvent.json'; -import sesEvent from '../../events/sesEvent.json'; -import snsEvent from '../../events/snsEvent.json'; -import sqsEvent from '../../events/sqsEvent.json'; -import { - AlbSchema, - AlbMultiValueHeadersSchema, -} from '../../../src/schemas/alb'; -import { APIGatewayProxyEventSchema } from '../../../src/schemas/apigw'; -import { APIGatewayProxyEventV2Schema } from '../../../src/schemas/apigwv2'; -import { - CloudFormationCustomResourceCreateSchema, - CloudFormationCustomResourceUpdateSchema, - CloudFormationCustomResourceDeleteSchema, -} from '../../../src/schemas/cloudformation-custom-resource'; -import { DynamoDBStreamSchema } from '../../../src/schemas/dynamodb'; -import { EventBridgeSchema } from '../../../src/schemas/eventbridge'; -import { - S3Schema, - S3EventNotificationEventBridgeSchema, - S3SqsEventNotificationSchema, -} from '../../../src/schemas/s3'; -import { SnsSchema } from '../../../src/schemas/sns'; -import { SqsSchema } from '../../../src/schemas/sqs'; -import { SesSchema } from '../../../src/schemas/ses'; -import { CloudWatchLogsSchema } from '../../../src/schemas/cloudwatch'; -import { - KafkaMskEventSchema, - KafkaSelfManagedEventSchema, -} from '../../../src/schemas/kafka'; - -/** - * keep everything in one describe block for now. - * once we have more examples, we can break them out into their own describe blocks - */ -describe('Schema:', () => { - describe('ALB ', () => { - it('should parse alb event', () => { - AlbSchema.parse(albEvent); - }); - it('should parse alb event path trailing slash', () => { - AlbSchema.parse(albEventPathTrailingSlash); - }); - it('should parse alb event with multi value headers event', () => { - AlbMultiValueHeadersSchema.parse(albMultiValueHeadersEvent); - }); - }); - describe('APIGateway ', () => { - it('should parse api gateway event', () => { - APIGatewayProxyEventSchema.parse(apiGatewayProxyEvent); - }); - it('should parse api gateway authorizer request event', () => { - APIGatewayProxyEventSchema.parse(apiGatewayAuthorizerRequestEvent); - }); - }); - it('APIGatewayV2 should parse api gateway v2 event', () => { - APIGatewayProxyEventV2Schema.parse(apiGatewayProxyV2Event); - }); - describe('CloudFormationCustomResource ', () => { - it('should parse create event', () => { - CloudFormationCustomResourceCreateSchema.parse( - cloudFormationCustomResourceCreateEvent - ); - }); - it('should parse update event', () => { - CloudFormationCustomResourceUpdateSchema.parse( - cloudFormationCustomResourceUpdateEvent - ); - }); - it('should parse delete event', () => { - CloudFormationCustomResourceDeleteSchema.parse( - cloudFormationCustomResourceDeleteEvent - ); - }); - }); - describe('CloudWatchLogs ', () => { - it('should parse cloudwatch logs event', () => { - const parsed = CloudWatchLogsSchema.parse(cloudWatchLogEvent); - expect(parsed.awslogs.data).toBeDefined(); - expect(parsed.awslogs.data?.logEvents[0]).toEqual({ - id: 'eventId1', - timestamp: 1440442987000, - message: '[ERROR] First test message', - }); - }); - it('should throw error if cloudwatch logs event is invalid', () => { - expect(() => - CloudWatchLogsSchema.parse({ - awslogs: { - data: 'invalid', - }, - }) - ).toThrowError(); - }); - }); - it('DynamoDB should parse a stream of records', () => { - DynamoDBStreamSchema.parse(dynamodbStreamEvent); - }); - it('EventBridge should parse eventbridge event', () => { - EventBridgeSchema.parse(eventBridgeEvent); - }); - describe('Kafka ', () => { - const expectedTestEvent = { - key: 'recordKey', - value: JSON.stringify({ key: 'value' }), - partition: 0, - topic: 'mytopic', - offset: 15, - timestamp: 1545084650987, - timestampType: 'CREATE_TIME', - headers: [ - { - headerKey: 'headerValue', - }, - ], - }; - it('should parse kafka MSK event', () => { - const parsed = KafkaMskEventSchema.parse(kafkaEventMsk); - - expect(parsed.records['mytopic-0'][0]).toEqual(expectedTestEvent); - }); - it('should parse kafka self managed event', () => { - const parsed = KafkaSelfManagedEventSchema.parse(kafkaEventSelfManaged); - expect(parsed.records['mytopic-0'][0]).toEqual(expectedTestEvent); - }); - }); - describe('S3 ', () => { - it('should parse s3 event', () => { - S3Schema.parse(s3Event); - }); - - it('should parse s3 event bridge notification event created', () => { - S3EventNotificationEventBridgeSchema.parse( - s3EventBridgeNotificationObjectCreatedEvent - ); - }); - - it('should parse s3 event bridge notification event detelted', () => { - S3EventNotificationEventBridgeSchema.parse( - s3EventBridgeNotificationObjectDeletedEvent - ); - }); - it('should parse s3 event bridge notification event expired', () => { - S3EventNotificationEventBridgeSchema.parse( - s3EventBridgeNotificationObjectExpiredEvent - ); - }); - - it('should parse s3 sqs notification event', () => { - S3SqsEventNotificationSchema.parse(s3SqsEvent); - }); - }); - it('SNS should parse sns event', () => { - SnsSchema.parse(snsEvent); - }); - it('SQS should parse sqs event', () => { - SqsSchema.parse(sqsEvent); - }); - it('SES should parse ses event', () => { - SesSchema.parse(sesEvent); - }); -}); diff --git a/packages/parser/tests/unit/schema/ses.test.ts b/packages/parser/tests/unit/schema/ses.test.ts new file mode 100644 index 0000000000..326f94760f --- /dev/null +++ b/packages/parser/tests/unit/schema/ses.test.ts @@ -0,0 +1,13 @@ +/** + * Test built in schema + * + * @group unit/parser/schema/ + */ +import { SesSchema } from '../../../src/schemas/ses'; +import sesEvent from '../../events/sesEvent.json'; + +describe('Schema:', () => { + it('SES should parse ses event', () => { + SesSchema.parse(sesEvent); + }); +}); diff --git a/packages/parser/tests/unit/schema/sns.test.ts b/packages/parser/tests/unit/schema/sns.test.ts new file mode 100644 index 0000000000..96e69912ff --- /dev/null +++ b/packages/parser/tests/unit/schema/sns.test.ts @@ -0,0 +1,13 @@ +/** + * Test built in schema + * + * @group unit/parser/schema/ + */ +import { SnsSchema } from '../../../src/schemas/sns'; +import snsEvent from '../../events/snsEvent.json'; + +describe('Schema:', () => { + it('SNS should parse sns event', () => { + SnsSchema.parse(snsEvent); + }); +}); diff --git a/packages/parser/tests/unit/schema/sqs.test.ts b/packages/parser/tests/unit/schema/sqs.test.ts new file mode 100644 index 0000000000..cbfbd981a0 --- /dev/null +++ b/packages/parser/tests/unit/schema/sqs.test.ts @@ -0,0 +1,13 @@ +/** + * Test built in schema + * + * @group unit/parser/schema/ + */ +import { SqsSchema } from '../../../src/schemas/sqs'; +import sqsEvent from '../../events/sqsEvent.json'; + +describe('SQS ', () => { + it('should parse sqs event', () => { + SqsSchema.parse(sqsEvent); + }); +}); From 067fd82399e57026322be70900de9447adc4ccdb Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Tue, 14 Nov 2023 06:16:19 +0100 Subject: [PATCH 14/48] add vpc lattice and lattice v2 --- packages/parser/src/index.ts | 1 - packages/parser/src/schemas/vpc-lattice.ts | 12 +++++++ packages/parser/src/schemas/vpc-latticev2.ts | 36 +++++++++++++++++++ .../vpcLatticeEventV2PathTrailingSlash.json | 2 +- packages/parser/tests/tsconfig.json | 3 +- .../tests/unit/schema/vpc-lattice.test.ts | 20 +++++++++++ .../tests/unit/schema/vpc-latticev2.test.ts | 21 +++++++++++ 7 files changed, 91 insertions(+), 4 deletions(-) create mode 100644 packages/parser/src/schemas/vpc-lattice.ts create mode 100644 packages/parser/src/schemas/vpc-latticev2.ts create mode 100644 packages/parser/tests/unit/schema/vpc-lattice.test.ts create mode 100644 packages/parser/tests/unit/schema/vpc-latticev2.test.ts diff --git a/packages/parser/src/index.ts b/packages/parser/src/index.ts index 5171121992..e69de29bb2 100644 --- a/packages/parser/src/index.ts +++ b/packages/parser/src/index.ts @@ -1 +0,0 @@ -export * from './schemas/index.js'; diff --git a/packages/parser/src/schemas/vpc-lattice.ts b/packages/parser/src/schemas/vpc-lattice.ts new file mode 100644 index 0000000000..d57c4b4b5a --- /dev/null +++ b/packages/parser/src/schemas/vpc-lattice.ts @@ -0,0 +1,12 @@ +import { z } from 'zod'; + +const VpcLatticeSchema = z.object({ + method: z.string(), + raw_path: z.string(), + body: z.string(), + is_base64_encoded: z.boolean(), + headers: z.record(z.string(), z.string()), + query_string_parameters: z.record(z.string(), z.string()), +}); + +export { VpcLatticeSchema }; diff --git a/packages/parser/src/schemas/vpc-latticev2.ts b/packages/parser/src/schemas/vpc-latticev2.ts new file mode 100644 index 0000000000..1581758d9b --- /dev/null +++ b/packages/parser/src/schemas/vpc-latticev2.ts @@ -0,0 +1,36 @@ +import { z } from 'zod'; + +const VpcLatticeV2RequestContextIdentity = z.object({ + sourceVpcArn: z.string().optional(), + type: z.string().optional(), + principal: z.string().optional(), + principalOrgId: z.string().optional(), + sessionName: z.string().optional(), + X509SubjectCn: z.string().optional(), + X509IssuerOu: z.string().optional(), + x509SanDns: z.string().optional(), + x509SanUri: z.string().optional(), + X509SanNameCn: z.string().optional(), +}); + +const VpcLatticeV2RequestContext = z.object({ + serviceNetworkArn: z.string(), + serviceArn: z.string(), + targetGroupArn: z.string(), + region: z.string(), + timeEpoch: z.string(), + identity: VpcLatticeV2RequestContextIdentity, +}); + +const VpcLatticeV2Schema = z.object({ + version: z.string(), + path: z.string(), + method: z.string(), + headers: z.record(z.string(), z.string()), + queryStringParameters: z.record(z.string(), z.string()).optional(), + body: z.string().optional(), + isBase64Encoded: z.boolean().optional(), + requestContext: VpcLatticeV2RequestContext, +}); + +export { VpcLatticeV2Schema }; diff --git a/packages/parser/tests/events/vpcLatticeEventV2PathTrailingSlash.json b/packages/parser/tests/events/vpcLatticeEventV2PathTrailingSlash.json index 5f5fa7edd7..a9f0188852 100644 --- a/packages/parser/tests/events/vpcLatticeEventV2PathTrailingSlash.json +++ b/packages/parser/tests/events/vpcLatticeEventV2PathTrailingSlash.json @@ -8,7 +8,7 @@ "host": "test-lambda-service-3908sdf9u3u.dkfjd93.vpc-lattice-svcs.us-east-2.on.aws", "accept": "*/*" }, - "query_string_parameters": { + "queryStringParameters": { "order-id": "1" }, "body": "{\"message\": \"Hello from Lambda!\"}", diff --git a/packages/parser/tests/tsconfig.json b/packages/parser/tests/tsconfig.json index 706537574a..6e77b6731f 100644 --- a/packages/parser/tests/tsconfig.json +++ b/packages/parser/tests/tsconfig.json @@ -7,8 +7,7 @@ }, "include": [ "../src/**/*", - "./**/*", "../tests/events/*.json", - "../tests/events/*.*" + "./**/*", ] } \ No newline at end of file diff --git a/packages/parser/tests/unit/schema/vpc-lattice.test.ts b/packages/parser/tests/unit/schema/vpc-lattice.test.ts new file mode 100644 index 0000000000..0ac3337e0d --- /dev/null +++ b/packages/parser/tests/unit/schema/vpc-lattice.test.ts @@ -0,0 +1,20 @@ +/** + * Test built in schema + * + * @group unit/parser/schema/ + */ + +import { VpcLatticeSchema } from '../../../src/schemas/vpc-lattice'; +import vpcLatticeEvent from '../../events/vpcLatticeEvent.json'; +import vpcLatticeEventPathTrailingSlash from '../../events/vpcLatticeEventPathTrailingSlash.json'; + +describe('VPC Lattice ', () => { + it('should parse vpc lattice event', () => { + const parsed = VpcLatticeSchema.parse(vpcLatticeEvent); + expect(parsed).toMatchObject(vpcLatticeEvent); + }); + it('should parse vpc lattice path trailing slash event', () => { + const parsed = VpcLatticeSchema.parse(vpcLatticeEventPathTrailingSlash); + expect(parsed).toMatchObject(vpcLatticeEventPathTrailingSlash); + }); +}); diff --git a/packages/parser/tests/unit/schema/vpc-latticev2.test.ts b/packages/parser/tests/unit/schema/vpc-latticev2.test.ts new file mode 100644 index 0000000000..f3f5affe77 --- /dev/null +++ b/packages/parser/tests/unit/schema/vpc-latticev2.test.ts @@ -0,0 +1,21 @@ +/** + * Test built in schema + * + * @group unit/parser/schema/ + */ + +import { VpcLatticeV2Schema } from '../../../src/schemas/vpc-latticev2'; +import vpcLatticeV2Event from '../../events/vpcLatticeV2Event.json'; +import vpcLatticeEventV2PathTrailingSlash from '../../events/vpcLatticeEventV2PathTrailingSlash.json'; + +describe('VpcLatticeV2 ', () => { + it('should parse VpcLatticeV2 event', () => { + const parsed = VpcLatticeV2Schema.parse(vpcLatticeV2Event); + expect(parsed).toEqual(vpcLatticeV2Event); + }); + + it('should parse VpcLatticeV2PathTrailingSlash event', () => { + const parsed = VpcLatticeV2Schema.parse(vpcLatticeEventV2PathTrailingSlash); + expect(parsed).toEqual(vpcLatticeEventV2PathTrailingSlash); + }); +}); From 04fd8926f9704a37f6f1a04fbd7507d2df9a3ea4 Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Tue, 14 Nov 2023 08:31:50 +0100 Subject: [PATCH 15/48] s3 event notification should extend eventbridge --- packages/parser/src/schemas/s3.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/parser/src/schemas/s3.ts b/packages/parser/src/schemas/s3.ts index 0a64a48395..35dab6627f 100644 --- a/packages/parser/src/schemas/s3.ts +++ b/packages/parser/src/schemas/s3.ts @@ -1,4 +1,5 @@ import { z } from 'zod'; +import { EventBridgeSchema } from './eventbridge.js'; const S3Identity = z.object({ principalId: z.string(), @@ -72,7 +73,7 @@ const S3EventNotificationEventBridgeDetailSchema = z.object({ 'destination-access-tier': z.string().optional(), }); -const S3EventNotificationEventBridgeSchema = z.object({ +const S3EventNotificationEventBridgeSchema = EventBridgeSchema.extend({ detail: S3EventNotificationEventBridgeDetailSchema, }); From 694f389ebcb4d55e54cd503028a1a2ebbe650c72 Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Tue, 14 Nov 2023 09:26:28 +0100 Subject: [PATCH 16/48] s3 sqs should extend from sqs --- packages/parser/src/schemas/s3.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/parser/src/schemas/s3.ts b/packages/parser/src/schemas/s3.ts index 35dab6627f..c39ee9ae28 100644 --- a/packages/parser/src/schemas/s3.ts +++ b/packages/parser/src/schemas/s3.ts @@ -1,5 +1,6 @@ import { z } from 'zod'; import { EventBridgeSchema } from './eventbridge.js'; +import { SqsRecordSchema } from './sqs.js'; const S3Identity = z.object({ principalId: z.string(), @@ -81,7 +82,7 @@ const S3Schema = z.object({ Records: z.array(S3Record), }); -const S3SqsEventNotificationRecordSchema = z.object({ +const S3SqsEventNotificationRecordSchema = SqsRecordSchema.extend({ body: z.string(), }); From 1408bb968b97161f0b4aa0cb2ac7de38527621f6 Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Tue, 14 Nov 2023 09:29:50 +0100 Subject: [PATCH 17/48] simplify cloudwatch extract from string --- packages/parser/src/schemas/kinesis.ts | 4 ++-- packages/parser/tests/unit/schema/kinesis.test.ts | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/parser/src/schemas/kinesis.ts b/packages/parser/src/schemas/kinesis.ts index 9369ea1f48..d3f88b9bbc 100644 --- a/packages/parser/src/schemas/kinesis.ts +++ b/packages/parser/src/schemas/kinesis.ts @@ -27,9 +27,9 @@ const KinesisDataStreamSchema = z.object({ }); const extractCloudWatchLogFromEvent = ( - event: z.infer + data: string ): z.infer => { - return decompressRecordToJSON(event.kinesis.data); + return decompressRecordToJSON(data); }; export { KinesisDataStreamSchema, extractCloudWatchLogFromEvent }; diff --git a/packages/parser/tests/unit/schema/kinesis.test.ts b/packages/parser/tests/unit/schema/kinesis.test.ts index 829e3ef14b..0008c0dec0 100644 --- a/packages/parser/tests/unit/schema/kinesis.test.ts +++ b/packages/parser/tests/unit/schema/kinesis.test.ts @@ -60,7 +60,9 @@ describe('Kinesis ', () => { kinesisStreamCloudWatchLogsEvent ); - const jsonParsed = extractCloudWatchLogFromEvent(parsed.Records[0]); + const jsonParsed = extractCloudWatchLogFromEvent( + parsed.Records[0].kinesis.data + ); expect(jsonParsed).toMatchObject({ messageType: 'DATA_MESSAGE', owner: '231436140809', From 60b139b58705f4ed5aea88c910d957ccef7d12a4 Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Tue, 14 Nov 2023 10:02:46 +0100 Subject: [PATCH 18/48] keep message as string, instead of empty object --- packages/parser/src/schemas/sns.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/parser/src/schemas/sns.ts b/packages/parser/src/schemas/sns.ts index 98d6752c99..8c84a7d537 100644 --- a/packages/parser/src/schemas/sns.ts +++ b/packages/parser/src/schemas/sns.ts @@ -11,7 +11,7 @@ const SnsNotificationSchema = z.object({ UnsubscribeUrl: z.string().url(), Type: z.literal('Notification'), MessageAttributes: z.record(z.string(), SnsMsgAttribute).optional(), - Message: z.union([z.string(), z.object({})]), + Message: z.string(), MessageId: z.string(), Signature: z.string().optional(), SignatureVersion: z.string().optional(), From 1fdac4601968d43e0b3167497e34f22db61d5a4c Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Tue, 14 Nov 2023 13:41:22 +0100 Subject: [PATCH 19/48] fix detail type of eb and field names --- packages/parser/src/schemas/eventbridge.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/parser/src/schemas/eventbridge.ts b/packages/parser/src/schemas/eventbridge.ts index 99f90b7217..6e20f78bb6 100644 --- a/packages/parser/src/schemas/eventbridge.ts +++ b/packages/parser/src/schemas/eventbridge.ts @@ -8,9 +8,9 @@ const EventBridgeSchema = z.object({ time: z.string().datetime(), region: z.string(), resources: z.array(z.string()), - detail_type: z.string().optional(), - detail: z.object({}).optional(), - replay_name: z.string().optional(), + 'detail-type': z.string().optional(), + detail: z.unknown(), + 'replay-name': z.string().optional(), }); export { EventBridgeSchema }; From f6d09d2297ae4c48b3eb177f25d8f063e9487f25 Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Tue, 14 Nov 2023 17:44:11 +0100 Subject: [PATCH 20/48] remove duplicated entries --- .npmignore | 2 -- 1 file changed, 2 deletions(-) diff --git a/.npmignore b/.npmignore index 69d897e7af..54ce5720a8 100644 --- a/.npmignore +++ b/.npmignore @@ -1,7 +1,6 @@ src tests jest.config.cjs -jest.config.cjs tsconfig.json .vscode .github @@ -14,7 +13,6 @@ coverage tslint.json tsconfig.json MakeFile -jest.config.cjs .npmignore .eslintignore .huskyrc.js From 3f8f4bbd3da7c37f6b87a8a099e4bbdffe747a58 Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Tue, 14 Nov 2023 17:45:08 +0100 Subject: [PATCH 21/48] fix homepage URL in readme --- packages/parser/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/parser/package.json b/packages/parser/package.json index ef8a820d7b..7b1e2e6f12 100644 --- a/packages/parser/package.json +++ b/packages/parser/package.json @@ -24,7 +24,7 @@ "lint-staged": { "*.{js,ts}": "npm run lint-fix" }, - "homepage": "https://github.com/aws-powertools/powertools-lambda-typescript/tree/main/packages/batch#readme", + "homepage": "https://github.com/aws-powertools/powertools-lambda-typescript/tree/main/packages/parser#readme", "license": "MIT-0", "type": "module", "exports": { From ccb51e11cc4e148f6004b1cc87d760d569d46d00 Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Tue, 14 Nov 2023 18:20:04 +0100 Subject: [PATCH 22/48] improved test coverage --- packages/parser/tests/unit/schema/kafka.test.ts | 12 ++++++++++++ packages/parser/tests/unit/schema/kinesis.test.ts | 5 +++++ 2 files changed, 17 insertions(+) diff --git a/packages/parser/tests/unit/schema/kafka.test.ts b/packages/parser/tests/unit/schema/kafka.test.ts index ad5e21e49d..b5d0018e29 100644 --- a/packages/parser/tests/unit/schema/kafka.test.ts +++ b/packages/parser/tests/unit/schema/kafka.test.ts @@ -34,4 +34,16 @@ describe('Kafka ', () => { const parsed = KafkaSelfManagedEventSchema.parse(kafkaEventSelfManaged); expect(parsed.records['mytopic-0'][0]).toEqual(expectedTestEvent); }); + it('should transform bootstrapServers to array', () => { + const parsed = KafkaSelfManagedEventSchema.parse(kafkaEventSelfManaged); + expect(parsed.bootstrapServers).toEqual([ + 'b-2.demo-cluster-1.a1bcde.c1.kafka.us-east-1.amazonaws.com:9092', + 'b-1.demo-cluster-1.a1bcde.c1.kafka.us-east-1.amazonaws.com:9092', + ]); + }); + it('should return undefined if bootstrapServers is not present', () => { + kafkaEventSelfManaged.bootstrapServers = ''; + const parsed = KafkaSelfManagedEventSchema.parse(kafkaEventSelfManaged); + expect(parsed.bootstrapServers).toBeUndefined(); + }); }); diff --git a/packages/parser/tests/unit/schema/kinesis.test.ts b/packages/parser/tests/unit/schema/kinesis.test.ts index 0008c0dec0..71d9fb1faf 100644 --- a/packages/parser/tests/unit/schema/kinesis.test.ts +++ b/packages/parser/tests/unit/schema/kinesis.test.ts @@ -70,4 +70,9 @@ describe('Kinesis ', () => { logStream: '2022/11/10/[$LATEST]26b6a45d574f442ea28438923cbf7bf7', }); }); + it('should return original value if cannot parse KinesisFirehoseSqsRecord', () => { + kinesisFirehoseSQSEvent.records[0].data = 'not a valid json'; + const parsed = KinesisFirehoseSqsSchema.parse(kinesisFirehoseSQSEvent); + expect(parsed.records[0].data).toEqual('not a valid json'); + }); }); From 208a66fa4c39a244e16a68460b02da9322b0be6c Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Tue, 14 Nov 2023 18:20:22 +0100 Subject: [PATCH 23/48] key and value are always present --- packages/parser/src/schemas/kafka.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/parser/src/schemas/kafka.ts b/packages/parser/src/schemas/kafka.ts index 8c71a21097..880fb404d8 100644 --- a/packages/parser/src/schemas/kafka.ts +++ b/packages/parser/src/schemas/kafka.ts @@ -7,10 +7,10 @@ const KafkaRecordSchema = z.object({ timestamp: z.number(), timestampType: z.string(), key: z.string().transform((key) => { - return key ? Buffer.from(key, 'base64').toString() : undefined; + return Buffer.from(key, 'base64').toString(); }), value: z.string().transform((value) => { - return value ? Buffer.from(value, 'base64').toString() : undefined; + return Buffer.from(value, 'base64').toString(); }), headers: z.array( z.record( From d8919d366c03d80d97577d6b3efec35ac349f213 Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Tue, 14 Nov 2023 18:20:58 +0100 Subject: [PATCH 24/48] cleanup unnecessary definitions, widen peerDep version req --- packages/parser/package.json | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/packages/parser/package.json b/packages/parser/package.json index 7b1e2e6f12..6dd191ca17 100644 --- a/packages/parser/package.json +++ b/packages/parser/package.json @@ -39,14 +39,6 @@ } } }, - "typesVersions": { - "*": { - "types": [ - "./lib/esm/index.d.ts", - "./lib/cjs/index.d.ts" - ] - } - }, "main": "./lib/cjs/index.js", "types": "./lib/cjs/index.d.ts", "files": [ @@ -70,6 +62,6 @@ ], "peerDependencies": { - "zod": "^3.22.4" + "zod": ">=3.x" } } \ No newline at end of file From 8eefbe8047a3fed015ac9a9f2f15ac3329b98320 Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Wed, 15 Nov 2023 05:32:28 +0100 Subject: [PATCH 25/48] Update packages/parser/src/schemas/cloudwatch.ts Co-authored-by: Andrea Amorosi --- packages/parser/src/schemas/cloudwatch.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/parser/src/schemas/cloudwatch.ts b/packages/parser/src/schemas/cloudwatch.ts index 024be971c5..ed1982b627 100644 --- a/packages/parser/src/schemas/cloudwatch.ts +++ b/packages/parser/src/schemas/cloudwatch.ts @@ -1,5 +1,5 @@ import { z } from 'zod'; -import { gunzipSync } from 'zlib'; +import { gunzipSync } from 'node:zlib'; const CloudWatchLogEventSchema = z.object({ id: z.string(), From eceea763f6f8ada871a2bd0c9fd03d4e82716118 Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Wed, 15 Nov 2023 06:52:10 +0100 Subject: [PATCH 26/48] clean up events, some fields are imaginary --- .../parser/tests/events/apiGatewayAuthorizerRequestEvent.json | 3 +-- packages/parser/tests/events/apiGatewayProxyEvent.json | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/parser/tests/events/apiGatewayAuthorizerRequestEvent.json b/packages/parser/tests/events/apiGatewayAuthorizerRequestEvent.json index d8dfe3fecf..6a80fff823 100644 --- a/packages/parser/tests/events/apiGatewayAuthorizerRequestEvent.json +++ b/packages/parser/tests/events/apiGatewayAuthorizerRequestEvent.json @@ -35,14 +35,13 @@ "accessKey": null, "accountId": null, "caller": null, - "cognitoAmr": null, "cognitoAuthenticationProvider": null, "cognitoAuthenticationType": null, "cognitoIdentityId": null, "cognitoIdentityPoolId": null, "principalOrgId": null, "apiKey": "...", - "sourceIp": "...", + "sourceIp": "192.168.0.1", "user": null, "userAgent": "PostmanRuntime/7.28.3", "userArn": null, diff --git a/packages/parser/tests/events/apiGatewayProxyEvent.json b/packages/parser/tests/events/apiGatewayProxyEvent.json index 3f095e28e4..4d2fb62399 100644 --- a/packages/parser/tests/events/apiGatewayProxyEvent.json +++ b/packages/parser/tests/events/apiGatewayProxyEvent.json @@ -50,7 +50,7 @@ "cognitoIdentityId": null, "cognitoIdentityPoolId": null, "principalOrgId": null, - "sourceIp": "192.168.0.1/32", + "sourceIp": "192.168.0.1", "user": null, "userAgent": "user-agent", "userArn": null, From f67a8e1d4c159c7e9d1445599a6d9ac1424d3deb Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Wed, 15 Nov 2023 06:52:25 +0100 Subject: [PATCH 27/48] fix api gw --- packages/parser/src/schemas/apigw.ts | 83 +++++++++++++++---- .../parser/tests/unit/schema/apigw.test.ts | 8 +- 2 files changed, 74 insertions(+), 17 deletions(-) diff --git a/packages/parser/src/schemas/apigw.ts b/packages/parser/src/schemas/apigw.ts index db5c9981ec..aadc657344 100644 --- a/packages/parser/src/schemas/apigw.ts +++ b/packages/parser/src/schemas/apigw.ts @@ -11,26 +11,78 @@ const APIGatewayCert = z.object({ }), }); -const APIGatewayEventRequestContext = z.object({ - accessKey: z.string().optional(), - accountId: z.string().optional(), - apiKey: z.string().optional(), - apiKeyId: z.string().optional(), - caller: z.string().optional(), - cognitoAuthenticationProvider: z.string().optional(), - cognitoAuthenticationType: z.string().optional(), - cognitoIdentityId: z.string().optional(), - cognitoIdentityPoolId: z.string().optional(), - principalOrgId: z.string().optional(), +const APIGatewayEventIdentity = z.object({ + accessKey: z.string().nullish(), + accountId: z.string().nullish(), + apiKey: z.string().nullish(), + apiKeyId: z.string().nullish(), + caller: z.string().nullish(), + cognitoAuthenticationProvider: z.string().nullish(), + cognitoAuthenticationType: z.string().nullish(), + cognitoIdentityId: z.string().nullish(), + cognitoIdentityPoolId: z.string().nullish(), + principalOrgId: z.string().nullish(), sourceIp: z.string().ip().optional(), - user: z.string().optional(), - userAgent: z.string().optional(), - userArn: z.string().optional(), - clientCert: APIGatewayCert.optional(), + user: z.string().nullish(), + userAgent: z.string().nullish(), + userArn: z.string().nullish(), + clientCert: APIGatewayCert.nullish(), }); +const APIGatewayEventRequestContext = z + .object({ + accountId: z.string(), + apiId: z.string(), + authorizer: z + .object({ + claims: z.record(z.string(), z.any()).nullish(), + scopes: z.array(z.string()).nullish(), + }) + .nullish(), + stage: z.string(), + protocol: z.string(), + identity: APIGatewayEventIdentity, + requestId: z.string(), + requestTime: z.string(), + requestTimeEpoch: z.number(), + resourceId: z.string().nullish(), + resourcePath: z.string(), + domainName: z.string().nullish(), + domainPrefix: z.string().nullish(), + extendedRequestId: z.string().nullish(), + httpMethod: z.enum([ + 'GET', + 'POST', + 'PUT', + 'PATCH', + 'DELETE', + 'HEAD', + 'OPTIONS', + ]), + path: z.string(), + connectedAt: z.number().nullish(), + connectionId: z.string().nullish(), + eventType: z.enum(['CONNECT', 'MESSAGE', 'DISCONNECT']).nullish(), + messageDirection: z.string().nullish(), + messageId: z.string().nullish(), + routeKey: z.string().nullish(), + operationName: z.string().nullish(), + }) + .refine( + (input) => { + return !(input.messageId && input.eventType === 'MESSAGE'); + }, + { + message: 'messageId is available only when `eventType` is MESSAGE', + } + ); + const APIGatewayProxyEventSchema = z.object({ version: z.string().optional(), + authorizationToken: z.string().optional(), + identitySource: z.string().optional(), + methodArn: z.string().optional(), + type: z.enum(['TOKEN', 'REQUEST']).optional(), resource: z.string(), path: z.string(), httpMethod: z.enum([ @@ -49,6 +101,7 @@ const APIGatewayProxyEventSchema = z.object({ requestContext: APIGatewayEventRequestContext, pathParameters: z.record(z.string()).optional().nullish(), stageVariables: z.record(z.string()).optional().nullish(), + isBase64Encoded: z.boolean().optional(), body: z.string().optional(), }); diff --git a/packages/parser/tests/unit/schema/apigw.test.ts b/packages/parser/tests/unit/schema/apigw.test.ts index ecb0a8d2cb..23ab976e6f 100644 --- a/packages/parser/tests/unit/schema/apigw.test.ts +++ b/packages/parser/tests/unit/schema/apigw.test.ts @@ -9,9 +9,13 @@ import apiGatewayAuthorizerRequestEvent from '../../events/apiGatewayAuthorizerR describe('APIGateway ', () => { it('should parse api gateway event', () => { - APIGatewayProxyEventSchema.parse(apiGatewayProxyEvent); + const parsed = APIGatewayProxyEventSchema.parse(apiGatewayProxyEvent); + expect(parsed).toEqual(apiGatewayProxyEvent); }); it('should parse api gateway authorizer request event', () => { - APIGatewayProxyEventSchema.parse(apiGatewayAuthorizerRequestEvent); + const parsed = APIGatewayProxyEventSchema.parse( + apiGatewayAuthorizerRequestEvent + ); + expect(parsed).toEqual(apiGatewayAuthorizerRequestEvent); }); }); From 955d2779147844d3ff23d4dc6ad8d9702e90c15a Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Wed, 15 Nov 2023 07:01:05 +0100 Subject: [PATCH 28/48] fix broken IP addresses in examples --- .../parser/tests/events/apiGatewayProxyEventAnotherPath.json | 2 +- .../tests/events/apiGatewayProxyEventPathTrailingSlash.json | 2 +- .../parser/tests/events/apiGatewayProxyEvent_noVersionAuth.json | 2 +- packages/parser/tests/events/apiGatewayProxyOtherEvent.json | 2 +- .../tests/events/apiGatewayProxyV2EventPathTrailingSlash.json | 2 +- packages/parser/tests/events/apiGatewayProxyV2Event_GET.json | 2 +- packages/parser/tests/events/apiGatewayProxyV2IamEvent.json | 2 +- .../tests/events/apiGatewayProxyV2LambdaAuthorizerEvent.json | 2 +- .../parser/tests/events/apiGatewayProxyV2OtherGetEvent.json | 2 +- .../events/apiGatewayProxyV2SchemaMiddlwareInvalidEvent.json | 2 +- .../events/apiGatewayProxyV2SchemaMiddlwareValidEvent.json | 2 +- ...idEvent.json => apiGatewaySchemaMiddlewareInvalidEvent.json} | 2 +- ...alidEvent.json => apiGatewaySchemaMiddlewareValidEvent.json} | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) rename packages/parser/tests/events/{apigatewayeSchemaMiddlwareInvalidEvent.json => apiGatewaySchemaMiddlewareInvalidEvent.json} (98%) rename packages/parser/tests/events/{apigatewayeSchemaMiddlwareValidEvent.json => apiGatewaySchemaMiddlewareValidEvent.json} (98%) diff --git a/packages/parser/tests/events/apiGatewayProxyEventAnotherPath.json b/packages/parser/tests/events/apiGatewayProxyEventAnotherPath.json index d8f43e4626..660118a2f9 100644 --- a/packages/parser/tests/events/apiGatewayProxyEventAnotherPath.json +++ b/packages/parser/tests/events/apiGatewayProxyEventAnotherPath.json @@ -49,7 +49,7 @@ "cognitoIdentityId": null, "cognitoIdentityPoolId": null, "principalOrgId": null, - "sourceIp": "192.168.0.1/32", + "sourceIp": "192.168.0.1", "user": null, "userAgent": "user-agent", "userArn": null, diff --git a/packages/parser/tests/events/apiGatewayProxyEventPathTrailingSlash.json b/packages/parser/tests/events/apiGatewayProxyEventPathTrailingSlash.json index 8a321d96c8..ced73da8c9 100644 --- a/packages/parser/tests/events/apiGatewayProxyEventPathTrailingSlash.json +++ b/packages/parser/tests/events/apiGatewayProxyEventPathTrailingSlash.json @@ -49,7 +49,7 @@ "cognitoIdentityId": null, "cognitoIdentityPoolId": null, "principalOrgId": null, - "sourceIp": "192.168.0.1/32", + "sourceIp": "192.168.0.1", "user": null, "userAgent": "user-agent", "userArn": null, diff --git a/packages/parser/tests/events/apiGatewayProxyEvent_noVersionAuth.json b/packages/parser/tests/events/apiGatewayProxyEvent_noVersionAuth.json index 055301f8f1..3a4af1ae9a 100644 --- a/packages/parser/tests/events/apiGatewayProxyEvent_noVersionAuth.json +++ b/packages/parser/tests/events/apiGatewayProxyEvent_noVersionAuth.json @@ -44,7 +44,7 @@ "cognitoIdentityId": null, "cognitoIdentityPoolId": null, "principalOrgId": null, - "sourceIp": "192.168.0.1/32", + "sourceIp": "192.168.0.1", "user": null, "userAgent": "user-agent", "userArn": null, diff --git a/packages/parser/tests/events/apiGatewayProxyOtherEvent.json b/packages/parser/tests/events/apiGatewayProxyOtherEvent.json index 5b9d09844a..7d5f0ef753 100644 --- a/packages/parser/tests/events/apiGatewayProxyOtherEvent.json +++ b/packages/parser/tests/events/apiGatewayProxyOtherEvent.json @@ -50,7 +50,7 @@ "cognitoIdentityId": null, "cognitoIdentityPoolId": null, "principalOrgId": null, - "sourceIp": "192.168.0.1/32", + "sourceIp": "192.168.0.1", "user": null, "userAgent": "user-agent", "userArn": null, diff --git a/packages/parser/tests/events/apiGatewayProxyV2EventPathTrailingSlash.json b/packages/parser/tests/events/apiGatewayProxyV2EventPathTrailingSlash.json index dfb0d98f2e..6a745937ca 100644 --- a/packages/parser/tests/events/apiGatewayProxyV2EventPathTrailingSlash.json +++ b/packages/parser/tests/events/apiGatewayProxyV2EventPathTrailingSlash.json @@ -48,7 +48,7 @@ "method": "POST", "path": "/my/path", "protocol": "HTTP/1.1", - "sourceIp": "192.168.0.1/32", + "sourceIp": "192.168.0.1", "userAgent": "agent" }, "requestId": "id", diff --git a/packages/parser/tests/events/apiGatewayProxyV2Event_GET.json b/packages/parser/tests/events/apiGatewayProxyV2Event_GET.json index f411ea655d..34b9b04628 100644 --- a/packages/parser/tests/events/apiGatewayProxyV2Event_GET.json +++ b/packages/parser/tests/events/apiGatewayProxyV2Event_GET.json @@ -48,7 +48,7 @@ "method": "GET", "path": "/my/path", "protocol": "HTTP/1.1", - "sourceIp": "192.168.0.1/32", + "sourceIp": "192.168.0.1", "userAgent": "agent" }, "requestId": "id", diff --git a/packages/parser/tests/events/apiGatewayProxyV2IamEvent.json b/packages/parser/tests/events/apiGatewayProxyV2IamEvent.json index 43f33e1678..99f10ef989 100644 --- a/packages/parser/tests/events/apiGatewayProxyV2IamEvent.json +++ b/packages/parser/tests/events/apiGatewayProxyV2IamEvent.json @@ -49,7 +49,7 @@ "method": "GET", "path": "/my/path", "protocol": "HTTP/1.1", - "sourceIp": "192.168.0.1/32", + "sourceIp": "192.168.0.1", "userAgent": "agent" } }, diff --git a/packages/parser/tests/events/apiGatewayProxyV2LambdaAuthorizerEvent.json b/packages/parser/tests/events/apiGatewayProxyV2LambdaAuthorizerEvent.json index cae3130de8..e7e6aeb2ca 100644 --- a/packages/parser/tests/events/apiGatewayProxyV2LambdaAuthorizerEvent.json +++ b/packages/parser/tests/events/apiGatewayProxyV2LambdaAuthorizerEvent.json @@ -37,7 +37,7 @@ "method": "GET", "path": "/my/path", "protocol": "HTTP/1.1", - "sourceIp": "192.168.0.1/32", + "sourceIp": "192.168.0.1", "userAgent": "agent" } }, diff --git a/packages/parser/tests/events/apiGatewayProxyV2OtherGetEvent.json b/packages/parser/tests/events/apiGatewayProxyV2OtherGetEvent.json index b9bd88f1c2..c5499c46b4 100644 --- a/packages/parser/tests/events/apiGatewayProxyV2OtherGetEvent.json +++ b/packages/parser/tests/events/apiGatewayProxyV2OtherGetEvent.json @@ -48,7 +48,7 @@ "method": "GET", "path": "/other/path", "protocol": "HTTP/1.1", - "sourceIp": "192.168.0.1/32", + "sourceIp": "192.168.0.1", "userAgent": "agent" }, "requestId": "id", diff --git a/packages/parser/tests/events/apiGatewayProxyV2SchemaMiddlwareInvalidEvent.json b/packages/parser/tests/events/apiGatewayProxyV2SchemaMiddlwareInvalidEvent.json index d2f4c404c7..5b663ec40a 100644 --- a/packages/parser/tests/events/apiGatewayProxyV2SchemaMiddlwareInvalidEvent.json +++ b/packages/parser/tests/events/apiGatewayProxyV2SchemaMiddlwareInvalidEvent.json @@ -48,7 +48,7 @@ "method": "POST", "path": "/my/path", "protocol": "HTTP/1.1", - "sourceIp": "192.168.0.1/32", + "sourceIp": "192.168.0.1", "userAgent": "agent" }, "requestId": "id", diff --git a/packages/parser/tests/events/apiGatewayProxyV2SchemaMiddlwareValidEvent.json b/packages/parser/tests/events/apiGatewayProxyV2SchemaMiddlwareValidEvent.json index 7be3d1194d..f59a6ef318 100644 --- a/packages/parser/tests/events/apiGatewayProxyV2SchemaMiddlwareValidEvent.json +++ b/packages/parser/tests/events/apiGatewayProxyV2SchemaMiddlwareValidEvent.json @@ -48,7 +48,7 @@ "method": "POST", "path": "/my/path", "protocol": "HTTP/1.1", - "sourceIp": "192.168.0.1/32", + "sourceIp": "192.168.0.1", "userAgent": "agent" }, "requestId": "id", diff --git a/packages/parser/tests/events/apigatewayeSchemaMiddlwareInvalidEvent.json b/packages/parser/tests/events/apiGatewaySchemaMiddlewareInvalidEvent.json similarity index 98% rename from packages/parser/tests/events/apigatewayeSchemaMiddlwareInvalidEvent.json rename to packages/parser/tests/events/apiGatewaySchemaMiddlewareInvalidEvent.json index 13d810870e..f601583a76 100644 --- a/packages/parser/tests/events/apigatewayeSchemaMiddlwareInvalidEvent.json +++ b/packages/parser/tests/events/apiGatewaySchemaMiddlewareInvalidEvent.json @@ -50,7 +50,7 @@ "cognitoIdentityId": null, "cognitoIdentityPoolId": null, "principalOrgId": null, - "sourceIp": "192.168.0.1/32", + "sourceIp": "192.168.0.1", "user": null, "userAgent": "user-agent", "userArn": null, diff --git a/packages/parser/tests/events/apigatewayeSchemaMiddlwareValidEvent.json b/packages/parser/tests/events/apiGatewaySchemaMiddlewareValidEvent.json similarity index 98% rename from packages/parser/tests/events/apigatewayeSchemaMiddlwareValidEvent.json rename to packages/parser/tests/events/apiGatewaySchemaMiddlewareValidEvent.json index 454465b9a4..7437eba9e0 100644 --- a/packages/parser/tests/events/apigatewayeSchemaMiddlwareValidEvent.json +++ b/packages/parser/tests/events/apiGatewaySchemaMiddlewareValidEvent.json @@ -50,7 +50,7 @@ "cognitoIdentityId": null, "cognitoIdentityPoolId": null, "principalOrgId": null, - "sourceIp": "192.168.0.1/32", + "sourceIp": "192.168.0.1", "user": null, "userAgent": "user-agent", "userArn": null, From f165302f03b375194e989f4d5b288b63f34b1d42 Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Wed, 15 Nov 2023 07:05:04 +0100 Subject: [PATCH 29/48] add more tests to api gw --- .../parser/tests/unit/schema/apigw.test.ts | 46 +++++++++++++++++-- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/packages/parser/tests/unit/schema/apigw.test.ts b/packages/parser/tests/unit/schema/apigw.test.ts index 23ab976e6f..feeb2ba71c 100644 --- a/packages/parser/tests/unit/schema/apigw.test.ts +++ b/packages/parser/tests/unit/schema/apigw.test.ts @@ -6,16 +6,52 @@ import { APIGatewayProxyEventSchema } from '../../../src/schemas/apigw'; import apiGatewayProxyEvent from '../../events/apiGatewayProxyEvent.json'; import apiGatewayAuthorizerRequestEvent from '../../events/apiGatewayAuthorizerRequestEvent.json'; +import apiGatewaySchemaMiddlewareInvalidEvent from '../../events/apiGatewaySchemaMiddlewareInvalidEvent.json'; +import apiGatewaySchemaMiddlewareValidEvent from '../../events/apiGatewaySchemaMiddlewareValidEvent.json'; +import apiGatewayProxyEvent_noVersionAuth from '../../events/apiGatewayProxyEvent_noVersionAuth.json'; +import apiGatewayProxyEventAnotherPath from '../../events/apiGatewayProxyEventAnotherPath.json'; +import apiGatewayProxyEventPathTrailingSlash from '../../events/apiGatewayProxyEventPathTrailingSlash.json'; +import apiGatewayProxyOtherEvent from '../../events/apiGatewayProxyOtherEvent.json'; describe('APIGateway ', () => { it('should parse api gateway event', () => { - const parsed = APIGatewayProxyEventSchema.parse(apiGatewayProxyEvent); - expect(parsed).toEqual(apiGatewayProxyEvent); + expect(APIGatewayProxyEventSchema.parse(apiGatewayProxyEvent)).toEqual( + apiGatewayProxyEvent + ); }); it('should parse api gateway authorizer request event', () => { - const parsed = APIGatewayProxyEventSchema.parse( - apiGatewayAuthorizerRequestEvent + expect( + APIGatewayProxyEventSchema.parse(apiGatewayAuthorizerRequestEvent) + ).toEqual(apiGatewayAuthorizerRequestEvent); + }); + it('should parse schema middleware invalid event', () => { + expect( + APIGatewayProxyEventSchema.parse(apiGatewaySchemaMiddlewareInvalidEvent) + ).toEqual(apiGatewaySchemaMiddlewareInvalidEvent); + }); + it('should parse schema middleware valid event', () => { + expect( + APIGatewayProxyEventSchema.parse(apiGatewaySchemaMiddlewareValidEvent) + ).toEqual(apiGatewaySchemaMiddlewareValidEvent); + }); + it('should parse proxy event with no version auth', () => { + expect( + APIGatewayProxyEventSchema.parse(apiGatewayProxyEvent_noVersionAuth) + ).toEqual(apiGatewayProxyEvent_noVersionAuth); + }); + it('should parse proxy event with another path', () => { + expect( + APIGatewayProxyEventSchema.parse(apiGatewayProxyEventAnotherPath) + ).toEqual(apiGatewayProxyEventAnotherPath); + }); + it('should parse proxy event with path trailing slash', () => { + expect( + APIGatewayProxyEventSchema.parse(apiGatewayProxyEventPathTrailingSlash) + ).toEqual(apiGatewayProxyEventPathTrailingSlash); + }); + it('should parse other proxy event', () => { + expect(APIGatewayProxyEventSchema.parse(apiGatewayProxyOtherEvent)).toEqual( + apiGatewayProxyOtherEvent ); - expect(parsed).toEqual(apiGatewayAuthorizerRequestEvent); }); }); From 06d5467163f546c94fc6f7bd9b7fadcdaa3df414 Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Wed, 15 Nov 2023 07:29:15 +0100 Subject: [PATCH 30/48] fix apigw2 add more tests --- packages/parser/src/schemas/apigw.ts | 4 +- packages/parser/src/schemas/apigwv2.ts | 19 ++++++-- ...yProxyV2SchemaMiddlewareInvalidEvent.json} | 0 ...wayProxyV2SchemaMiddlewareValidEvent.json} | 0 .../parser/tests/unit/schema/apigwv2.test.ts | 46 ++++++++++++++++++- 5 files changed, 60 insertions(+), 9 deletions(-) rename packages/parser/tests/events/{apiGatewayProxyV2SchemaMiddlwareInvalidEvent.json => apiGatewayProxyV2SchemaMiddlewareInvalidEvent.json} (100%) rename packages/parser/tests/events/{apiGatewayProxyV2SchemaMiddlwareValidEvent.json => apiGatewayProxyV2SchemaMiddlewareValidEvent.json} (100%) diff --git a/packages/parser/src/schemas/apigw.ts b/packages/parser/src/schemas/apigw.ts index aadc657344..13a7fb7483 100644 --- a/packages/parser/src/schemas/apigw.ts +++ b/packages/parser/src/schemas/apigw.ts @@ -101,8 +101,8 @@ const APIGatewayProxyEventSchema = z.object({ requestContext: APIGatewayEventRequestContext, pathParameters: z.record(z.string()).optional().nullish(), stageVariables: z.record(z.string()).optional().nullish(), - isBase64Encoded: z.boolean().optional(), + isBase64Encoded: z.boolean(), body: z.string().optional(), }); -export { APIGatewayProxyEventSchema }; +export { APIGatewayProxyEventSchema, APIGatewayCert }; diff --git a/packages/parser/src/schemas/apigwv2.ts b/packages/parser/src/schemas/apigwv2.ts index 5132c5d051..9295dfca2e 100644 --- a/packages/parser/src/schemas/apigwv2.ts +++ b/packages/parser/src/schemas/apigwv2.ts @@ -1,10 +1,13 @@ import { z } from 'zod'; +import { APIGatewayCert } from './apigw.js'; const RequestContextV2Authorizer = z.object({ - jwt: z.object({ - claims: z.record(z.string()), - scopes: z.array(z.string()), - }), + jwt: z + .object({ + claims: z.record(z.string(), z.any()), + scopes: z.array(z.string()), + }) + .optional(), iam: z .object({ accessKey: z.string().optional(), @@ -12,7 +15,7 @@ const RequestContextV2Authorizer = z.object({ callerId: z.string().optional(), principalOrgId: z.string().optional(), userArn: z.string().optional(), - user: z.string().optional(), + userId: z.string().optional(), cognitoIdentity: z.object({ amr: z.array(z.string()), identityId: z.string(), @@ -20,6 +23,7 @@ const RequestContextV2Authorizer = z.object({ }), }) .optional(), + lambda: z.record(z.string(), z.any()).optional(), }); const RequestContextV2Http = z.object({ @@ -34,6 +38,11 @@ const RequestContextV2 = z.object({ accountId: z.string(), apiId: z.string(), authorizer: RequestContextV2Authorizer.optional(), + authentication: z + .object({ + clientCert: APIGatewayCert.optional(), + }) + .optional(), domainName: z.string(), domainPrefix: z.string(), http: RequestContextV2Http, diff --git a/packages/parser/tests/events/apiGatewayProxyV2SchemaMiddlwareInvalidEvent.json b/packages/parser/tests/events/apiGatewayProxyV2SchemaMiddlewareInvalidEvent.json similarity index 100% rename from packages/parser/tests/events/apiGatewayProxyV2SchemaMiddlwareInvalidEvent.json rename to packages/parser/tests/events/apiGatewayProxyV2SchemaMiddlewareInvalidEvent.json diff --git a/packages/parser/tests/events/apiGatewayProxyV2SchemaMiddlwareValidEvent.json b/packages/parser/tests/events/apiGatewayProxyV2SchemaMiddlewareValidEvent.json similarity index 100% rename from packages/parser/tests/events/apiGatewayProxyV2SchemaMiddlwareValidEvent.json rename to packages/parser/tests/events/apiGatewayProxyV2SchemaMiddlewareValidEvent.json diff --git a/packages/parser/tests/unit/schema/apigwv2.test.ts b/packages/parser/tests/unit/schema/apigwv2.test.ts index ed5ebba624..e4b6dcc8e7 100644 --- a/packages/parser/tests/unit/schema/apigwv2.test.ts +++ b/packages/parser/tests/unit/schema/apigwv2.test.ts @@ -5,9 +5,51 @@ */ import { APIGatewayProxyEventV2Schema } from '../../../src/schemas/apigwv2'; import apiGatewayProxyV2Event from '../../events/apiGatewayProxyV2Event.json'; +import apiGatewayProxyV2Event_GET from '../../events/apiGatewayProxyV2Event_GET.json'; +import apiGatewayProxyV2EventPathTrailingSlash from '../../events/apiGatewayProxyV2EventPathTrailingSlash.json'; +import apiGatewayProxyV2IamEvent from '../../events/apiGatewayProxyV2IamEvent.json'; +import apiGatewayProxyV2LambdaAuthorizerEvent from '../../events/apiGatewayProxyV2LambdaAuthorizerEvent.json'; +import apiGatewayProxyV2OtherGetEvent from '../../events/apiGatewayProxyV2OtherGetEvent.json'; +import apiGatewayProxyV2SchemaMiddlewareValidEvent from '../../events/apiGatewayProxyV2SchemaMiddlewareValidEvent.json'; describe('API GW v2 ', () => { - it('APIGatewayV2 should parse api gateway v2 event', () => { - APIGatewayProxyEventV2Schema.parse(apiGatewayProxyV2Event); + it('should parse api gateway v2 event', () => { + expect(APIGatewayProxyEventV2Schema.parse(apiGatewayProxyV2Event)).toEqual( + apiGatewayProxyV2Event + ); + }); + it('should parse api gateway v2 event with GET method', () => { + expect( + APIGatewayProxyEventV2Schema.parse(apiGatewayProxyV2Event_GET) + ).toEqual(apiGatewayProxyV2Event_GET); + }); + it('should parse api gateway v2 event with path trailing slash', () => { + expect( + APIGatewayProxyEventV2Schema.parse( + apiGatewayProxyV2EventPathTrailingSlash + ) + ).toEqual(apiGatewayProxyV2EventPathTrailingSlash); + }); + it('should parse api gateway v2 event with iam', () => { + expect( + APIGatewayProxyEventV2Schema.parse(apiGatewayProxyV2IamEvent) + ).toEqual(apiGatewayProxyV2IamEvent); + }); + it('should parse api gateway v2 event with lambda authorizer', () => { + expect( + APIGatewayProxyEventV2Schema.parse(apiGatewayProxyV2LambdaAuthorizerEvent) + ).toEqual(apiGatewayProxyV2LambdaAuthorizerEvent); + }); + it('should parse api gateway v2 event with other get event', () => { + expect( + APIGatewayProxyEventV2Schema.parse(apiGatewayProxyV2OtherGetEvent) + ).toEqual(apiGatewayProxyV2OtherGetEvent); + }); + it('should parse api gateway v2 event with schema middleware', () => { + expect( + APIGatewayProxyEventV2Schema.parse( + apiGatewayProxyV2SchemaMiddlewareValidEvent + ) + ).toEqual(apiGatewayProxyV2SchemaMiddlewareValidEvent); }); }); From 1af893a1b35098953413f4ed70838ed9ed57ba3d Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Wed, 15 Nov 2023 07:31:26 +0100 Subject: [PATCH 31/48] add optional scopes to apigwv2 --- packages/parser/src/schemas/apigwv2.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/parser/src/schemas/apigwv2.ts b/packages/parser/src/schemas/apigwv2.ts index 9295dfca2e..ec5cfb6156 100644 --- a/packages/parser/src/schemas/apigwv2.ts +++ b/packages/parser/src/schemas/apigwv2.ts @@ -5,7 +5,7 @@ const RequestContextV2Authorizer = z.object({ jwt: z .object({ claims: z.record(z.string(), z.any()), - scopes: z.array(z.string()), + scopes: z.array(z.string()).optional(), }) .optional(), iam: z From a9cfa6af279493ec9e52fdb3ab50e4389bd751e0 Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Wed, 15 Nov 2023 07:39:27 +0100 Subject: [PATCH 32/48] add optional field back to api gw, stricter methods for vpc lattice --- packages/parser/src/schemas/apigw.ts | 2 +- packages/parser/src/schemas/vpc-lattice.ts | 2 +- packages/parser/src/schemas/vpc-latticev2.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/parser/src/schemas/apigw.ts b/packages/parser/src/schemas/apigw.ts index 13a7fb7483..7df6d8d8a8 100644 --- a/packages/parser/src/schemas/apigw.ts +++ b/packages/parser/src/schemas/apigw.ts @@ -101,7 +101,7 @@ const APIGatewayProxyEventSchema = z.object({ requestContext: APIGatewayEventRequestContext, pathParameters: z.record(z.string()).optional().nullish(), stageVariables: z.record(z.string()).optional().nullish(), - isBase64Encoded: z.boolean(), + isBase64Encoded: z.boolean().optional(), body: z.string().optional(), }); diff --git a/packages/parser/src/schemas/vpc-lattice.ts b/packages/parser/src/schemas/vpc-lattice.ts index d57c4b4b5a..f8f266fa20 100644 --- a/packages/parser/src/schemas/vpc-lattice.ts +++ b/packages/parser/src/schemas/vpc-lattice.ts @@ -1,7 +1,7 @@ import { z } from 'zod'; const VpcLatticeSchema = z.object({ - method: z.string(), + method: z.enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS']), raw_path: z.string(), body: z.string(), is_base64_encoded: z.boolean(), diff --git a/packages/parser/src/schemas/vpc-latticev2.ts b/packages/parser/src/schemas/vpc-latticev2.ts index 1581758d9b..1ef3fd671f 100644 --- a/packages/parser/src/schemas/vpc-latticev2.ts +++ b/packages/parser/src/schemas/vpc-latticev2.ts @@ -25,7 +25,7 @@ const VpcLatticeV2RequestContext = z.object({ const VpcLatticeV2Schema = z.object({ version: z.string(), path: z.string(), - method: z.string(), + method: z.enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS']), headers: z.record(z.string(), z.string()), queryStringParameters: z.record(z.string(), z.string()).optional(), body: z.string().optional(), From 2d671d0eb8dc518d2511b5e2d99ce6a256b53840 Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Wed, 15 Nov 2023 07:51:42 +0100 Subject: [PATCH 33/48] add test for messageId refinement --- packages/parser/src/schemas/apigw.ts | 4 ++- .../parser/tests/unit/schema/apigw.test.ts | 29 +++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/packages/parser/src/schemas/apigw.ts b/packages/parser/src/schemas/apigw.ts index 7df6d8d8a8..72878de03a 100644 --- a/packages/parser/src/schemas/apigw.ts +++ b/packages/parser/src/schemas/apigw.ts @@ -70,7 +70,9 @@ const APIGatewayEventRequestContext = z }) .refine( (input) => { - return !(input.messageId && input.eventType === 'MESSAGE'); + return ( + !input.messageId || (input.messageId && input.eventType === 'MESSAGE') + ); }, { message: 'messageId is available only when `eventType` is MESSAGE', diff --git a/packages/parser/tests/unit/schema/apigw.test.ts b/packages/parser/tests/unit/schema/apigw.test.ts index feeb2ba71c..e44fa406ca 100644 --- a/packages/parser/tests/unit/schema/apigw.test.ts +++ b/packages/parser/tests/unit/schema/apigw.test.ts @@ -54,4 +54,33 @@ describe('APIGateway ', () => { apiGatewayProxyOtherEvent ); }); + it('should throw error when event is not a valid proxy event', () => { + const event = { + resource: '/', + path: '/', + httpMethod: 'GET', + headers: {}, + multiValueHeaders: {}, + isBase64Encoded: false, + body: 'Foo!', + requestContext: { + accountId: '1234', + apiId: 'myApi', + httpMethod: 'GET', + identity: { + sourceIp: '127.0.0.1', + }, + path: '/', + protocol: 'Https', + requestId: '1234', + requestTime: '2018-09-07T16:20:46Z', + requestTimeEpoch: 1536992496000, + resourcePath: '/', + stage: 'test', + eventType: 'DISCONNECT', + messageId: 'messageId', + }, + }; + expect(() => APIGatewayProxyEventSchema.parse(event)).toThrow(); + }); }); From 7cdcc0b27861207185c139d8efc688e5ecdd38f8 Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Wed, 15 Nov 2023 08:15:26 +0100 Subject: [PATCH 34/48] remove redundant entry --- packages/parser/tests/tsconfig.json | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/parser/tests/tsconfig.json b/packages/parser/tests/tsconfig.json index 6e77b6731f..67322d5174 100644 --- a/packages/parser/tests/tsconfig.json +++ b/packages/parser/tests/tsconfig.json @@ -7,7 +7,6 @@ }, "include": [ "../src/**/*", - "../tests/events/*.json", "./**/*", ] } \ No newline at end of file From dd39001d50f66f6ce2315f2af9265b5d7de4f725 Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Wed, 15 Nov 2023 08:15:40 +0100 Subject: [PATCH 35/48] fix sqs --- packages/parser/src/schemas/sqs.ts | 6 +++--- packages/parser/tests/unit/schema/sqs.test.ts | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/parser/src/schemas/sqs.ts b/packages/parser/src/schemas/sqs.ts index 844c8940ac..09aed635ea 100644 --- a/packages/parser/src/schemas/sqs.ts +++ b/packages/parser/src/schemas/sqs.ts @@ -8,7 +8,7 @@ const SqsMsgAttributeSchema = z.object({ dataType: z.string(), }); -const SqsAttributeSchema = z.object({ +const SqsAttributesSchema = z.object({ ApproximateReceiveCount: z.string(), ApproximateFirstReceiveTimestamp: z.string(), MessageDeduplicationId: z.string().optional(), @@ -23,7 +23,7 @@ const SqsRecordSchema = z.object({ messageId: z.string(), receiptHandle: z.string(), body: z.string(), - attributes: SqsAttributeSchema, + attributes: SqsAttributesSchema, messageAttributes: z.record(z.string(), SqsMsgAttributeSchema), md5OfBody: z.string(), md5OfMessageAttributes: z.string().optional().nullable(), @@ -39,6 +39,6 @@ const SqsSchema = z.object({ export { SqsSchema, SqsRecordSchema, - SqsAttributeSchema, + SqsAttributesSchema, SqsMsgAttributeSchema, }; diff --git a/packages/parser/tests/unit/schema/sqs.test.ts b/packages/parser/tests/unit/schema/sqs.test.ts index cbfbd981a0..098d53a6d8 100644 --- a/packages/parser/tests/unit/schema/sqs.test.ts +++ b/packages/parser/tests/unit/schema/sqs.test.ts @@ -8,6 +8,6 @@ import sqsEvent from '../../events/sqsEvent.json'; describe('SQS ', () => { it('should parse sqs event', () => { - SqsSchema.parse(sqsEvent); + expect(SqsSchema.parse(sqsEvent)).toEqual(sqsEvent); }); }); From bd0cefe85fba4b07016a1425c0154a07d7bef227 Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Wed, 15 Nov 2023 08:26:22 +0100 Subject: [PATCH 36/48] add dmarcPolicy for ses --- packages/parser/src/schemas/ses.ts | 10 ++++++---- packages/parser/tests/unit/schema/ses.test.ts | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/parser/src/schemas/ses.ts b/packages/parser/src/schemas/ses.ts index 96ca79388a..254d3de255 100644 --- a/packages/parser/src/schemas/ses.ts +++ b/packages/parser/src/schemas/ses.ts @@ -8,10 +8,12 @@ const SesReceipt = z.object({ timestamp: z.string().datetime(), processingTimeMillis: z.number().int().positive(), recipients: z.array(z.string()), - spamVerdict: SesReceiptVerdict.optional(), - virusVerdict: SesReceiptVerdict.optional(), - spfVerdict: SesReceiptVerdict.optional(), - dmarcVerdict: SesReceiptVerdict.optional(), + spamVerdict: SesReceiptVerdict, + virusVerdict: SesReceiptVerdict, + spfVerdict: SesReceiptVerdict, + dmarcVerdict: SesReceiptVerdict, + dkimVerdict: SesReceiptVerdict, + dmarcPolicy: z.enum(['none', 'quarantine', 'reject']), action: z.object({ type: z.enum(['Lambda']), invocationType: z.literal('Event'), diff --git a/packages/parser/tests/unit/schema/ses.test.ts b/packages/parser/tests/unit/schema/ses.test.ts index 326f94760f..87f86a25c0 100644 --- a/packages/parser/tests/unit/schema/ses.test.ts +++ b/packages/parser/tests/unit/schema/ses.test.ts @@ -8,6 +8,6 @@ import sesEvent from '../../events/sesEvent.json'; describe('Schema:', () => { it('SES should parse ses event', () => { - SesSchema.parse(sesEvent); + expect(SesSchema.parse(sesEvent)).toEqual(sesEvent); }); }); From 7b332505a7cd5a24ba8da1341ab26e13b2b16875 Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Wed, 15 Nov 2023 10:22:08 +0100 Subject: [PATCH 37/48] added tests --- .../schemas/cloudformation-custom-resource.ts | 26 ++++++++++------- packages/parser/src/schemas/eventbridge.ts | 2 +- packages/parser/src/schemas/s3.ts | 1 + packages/parser/tests/tsconfig.json | 3 +- packages/parser/tests/unit/schema/alb.test.ts | 10 +++++-- .../cloudformation-custom-resource.test.ts | 25 +++++++++++------ .../parser/tests/unit/schema/dynamodb.test.ts | 4 ++- .../tests/unit/schema/eventbridge.test.ts | 2 +- .../parser/tests/unit/schema/kafka.test.ts | 18 +++++++----- packages/parser/tests/unit/schema/s3.test.ts | 28 +++++++++++-------- packages/parser/tests/unit/schema/sns.test.ts | 2 +- .../tests/unit/schema/vpc-lattice.test.ts | 8 +++--- 12 files changed, 80 insertions(+), 49 deletions(-) diff --git a/packages/parser/src/schemas/cloudformation-custom-resource.ts b/packages/parser/src/schemas/cloudformation-custom-resource.ts index a03e9d13b7..13f9e9760d 100644 --- a/packages/parser/src/schemas/cloudformation-custom-resource.ts +++ b/packages/parser/src/schemas/cloudformation-custom-resource.ts @@ -11,20 +11,26 @@ const CloudFormationCustomResourceBaseSchema = z.object({ }); const CloudFormationCustomResourceCreateSchema = - CloudFormationCustomResourceBaseSchema.extend({ - RequestType: z.literal('Create'), - }); + CloudFormationCustomResourceBaseSchema.merge( + z.object({ + RequestType: z.literal('Create'), + }) + ); const CloudFormationCustomResourceDeleteSchema = - CloudFormationCustomResourceBaseSchema.extend({ - RequestType: z.literal('Delete'), - }); + CloudFormationCustomResourceBaseSchema.merge( + z.object({ + RequestType: z.literal('Delete'), + }) + ); const CloudFormationCustomResourceUpdateSchema = - CloudFormationCustomResourceBaseSchema.extend({ - RequestType: z.literal('Update'), - OldResourceProperties: z.record(z.any()), - }); + CloudFormationCustomResourceBaseSchema.merge( + z.object({ + RequestType: z.literal('Update'), + OldResourceProperties: z.record(z.any()), + }) + ); export { CloudFormationCustomResourceCreateSchema, diff --git a/packages/parser/src/schemas/eventbridge.ts b/packages/parser/src/schemas/eventbridge.ts index 6e20f78bb6..9c509e5c03 100644 --- a/packages/parser/src/schemas/eventbridge.ts +++ b/packages/parser/src/schemas/eventbridge.ts @@ -8,7 +8,7 @@ const EventBridgeSchema = z.object({ time: z.string().datetime(), region: z.string(), resources: z.array(z.string()), - 'detail-type': z.string().optional(), + 'detail-type': z.string(), detail: z.unknown(), 'replay-name': z.string().optional(), }); diff --git a/packages/parser/src/schemas/s3.ts b/packages/parser/src/schemas/s3.ts index c39ee9ae28..e4aa886acc 100644 --- a/packages/parser/src/schemas/s3.ts +++ b/packages/parser/src/schemas/s3.ts @@ -16,6 +16,7 @@ const S3ResponseElements = z.object({ }); const S3Message = z.object({ + s3SchemaVersion: z.string(), configurationId: z.string(), object: z.object({ key: z.string(), diff --git a/packages/parser/tests/tsconfig.json b/packages/parser/tests/tsconfig.json index 67322d5174..070483a63f 100644 --- a/packages/parser/tests/tsconfig.json +++ b/packages/parser/tests/tsconfig.json @@ -7,6 +7,7 @@ }, "include": [ "../src/**/*", - "./**/*", + "./**/*.*", + "./**/*.json", ] } \ No newline at end of file diff --git a/packages/parser/tests/unit/schema/alb.test.ts b/packages/parser/tests/unit/schema/alb.test.ts index af583952e2..9318d26da7 100644 --- a/packages/parser/tests/unit/schema/alb.test.ts +++ b/packages/parser/tests/unit/schema/alb.test.ts @@ -13,12 +13,16 @@ import albMultiValueHeadersEvent from '../../events/albMultiValueHeadersEvent.js describe('ALB ', () => { it('should parse alb event', () => { - AlbSchema.parse(albEvent); + expect(AlbSchema.parse(albEvent)).toEqual(albEvent); }); it('should parse alb event path trailing slash', () => { - AlbSchema.parse(albEventPathTrailingSlash); + expect(AlbSchema.parse(albEventPathTrailingSlash)).toEqual( + albEventPathTrailingSlash + ); }); it('should parse alb event with multi value headers event', () => { - AlbMultiValueHeadersSchema.parse(albMultiValueHeadersEvent); + expect(AlbMultiValueHeadersSchema.parse(albMultiValueHeadersEvent)).toEqual( + albMultiValueHeadersEvent + ); }); }); diff --git a/packages/parser/tests/unit/schema/cloudformation-custom-resource.test.ts b/packages/parser/tests/unit/schema/cloudformation-custom-resource.test.ts index 109dd60c49..3ef01fffa5 100644 --- a/packages/parser/tests/unit/schema/cloudformation-custom-resource.test.ts +++ b/packages/parser/tests/unit/schema/cloudformation-custom-resource.test.ts @@ -14,18 +14,25 @@ import cloudFormationCustomResourceDeleteEvent from '../../events/cloudformation describe('CloudFormationCustomResource ', () => { it('should parse create event', () => { - CloudFormationCustomResourceCreateSchema.parse( - cloudFormationCustomResourceCreateEvent - ); + console.log(CloudFormationCustomResourceCreateSchema.shape); + expect( + CloudFormationCustomResourceCreateSchema.parse( + cloudFormationCustomResourceCreateEvent + ) + ).toEqual(cloudFormationCustomResourceCreateEvent); }); it('should parse update event', () => { - CloudFormationCustomResourceUpdateSchema.parse( - cloudFormationCustomResourceUpdateEvent - ); + expect( + CloudFormationCustomResourceUpdateSchema.parse( + cloudFormationCustomResourceUpdateEvent + ) + ).toEqual(cloudFormationCustomResourceUpdateEvent); }); it('should parse delete event', () => { - CloudFormationCustomResourceDeleteSchema.parse( - cloudFormationCustomResourceDeleteEvent - ); + expect( + CloudFormationCustomResourceDeleteSchema.parse( + cloudFormationCustomResourceDeleteEvent + ) + ).toEqual(cloudFormationCustomResourceDeleteEvent); }); }); diff --git a/packages/parser/tests/unit/schema/dynamodb.test.ts b/packages/parser/tests/unit/schema/dynamodb.test.ts index f074b7f2c0..7a7f58d50c 100644 --- a/packages/parser/tests/unit/schema/dynamodb.test.ts +++ b/packages/parser/tests/unit/schema/dynamodb.test.ts @@ -8,6 +8,8 @@ import dynamodbStreamEvent from '../../events/dynamoStreamEvent.json'; describe('DynamoDB ', () => { it('should parse a stream of records', () => { - DynamoDBStreamSchema.parse(dynamodbStreamEvent); + expect(DynamoDBStreamSchema.parse(dynamodbStreamEvent)).toEqual( + dynamodbStreamEvent + ); }); }); diff --git a/packages/parser/tests/unit/schema/eventbridge.test.ts b/packages/parser/tests/unit/schema/eventbridge.test.ts index fc068da859..4cc2148686 100644 --- a/packages/parser/tests/unit/schema/eventbridge.test.ts +++ b/packages/parser/tests/unit/schema/eventbridge.test.ts @@ -9,6 +9,6 @@ import eventBridgeEvent from '../../events/eventBridgeEvent.json'; describe('EventBridge ', () => { it('should parse eventbridge event', () => { - EventBridgeSchema.parse(eventBridgeEvent); + expect(EventBridgeSchema.parse(eventBridgeEvent)).toEqual(eventBridgeEvent); }); }); diff --git a/packages/parser/tests/unit/schema/kafka.test.ts b/packages/parser/tests/unit/schema/kafka.test.ts index b5d0018e29..f204ce49b9 100644 --- a/packages/parser/tests/unit/schema/kafka.test.ts +++ b/packages/parser/tests/unit/schema/kafka.test.ts @@ -26,17 +26,21 @@ describe('Kafka ', () => { ], }; it('should parse kafka MSK event', () => { - const parsed = KafkaMskEventSchema.parse(kafkaEventMsk); - - expect(parsed.records['mytopic-0'][0]).toEqual(expectedTestEvent); + expect( + KafkaMskEventSchema.parse(kafkaEventMsk).records['mytopic-0'][0] + ).toEqual(expectedTestEvent); }); it('should parse kafka self managed event', () => { - const parsed = KafkaSelfManagedEventSchema.parse(kafkaEventSelfManaged); - expect(parsed.records['mytopic-0'][0]).toEqual(expectedTestEvent); + expect( + KafkaSelfManagedEventSchema.parse(kafkaEventSelfManaged).records[ + 'mytopic-0' + ][0] + ).toEqual(expectedTestEvent); }); it('should transform bootstrapServers to array', () => { - const parsed = KafkaSelfManagedEventSchema.parse(kafkaEventSelfManaged); - expect(parsed.bootstrapServers).toEqual([ + expect( + KafkaSelfManagedEventSchema.parse(kafkaEventSelfManaged).bootstrapServers + ).toEqual([ 'b-2.demo-cluster-1.a1bcde.c1.kafka.us-east-1.amazonaws.com:9092', 'b-1.demo-cluster-1.a1bcde.c1.kafka.us-east-1.amazonaws.com:9092', ]); diff --git a/packages/parser/tests/unit/schema/s3.test.ts b/packages/parser/tests/unit/schema/s3.test.ts index ea01401677..c4211dfc3d 100644 --- a/packages/parser/tests/unit/schema/s3.test.ts +++ b/packages/parser/tests/unit/schema/s3.test.ts @@ -16,27 +16,33 @@ import s3SqsEvent from '../../events/s3SqsEvent.json'; describe('S3 ', () => { it('should parse s3 event', () => { - S3Schema.parse(s3Event); + expect(S3Schema.parse(s3Event)).toEqual(s3Event); }); it('should parse s3 event bridge notification event created', () => { - S3EventNotificationEventBridgeSchema.parse( - s3EventBridgeNotificationObjectCreatedEvent - ); + expect( + S3EventNotificationEventBridgeSchema.parse( + s3EventBridgeNotificationObjectCreatedEvent + ) + ).toEqual(s3EventBridgeNotificationObjectCreatedEvent); }); it('should parse s3 event bridge notification event detelted', () => { - S3EventNotificationEventBridgeSchema.parse( - s3EventBridgeNotificationObjectDeletedEvent - ); + expect( + S3EventNotificationEventBridgeSchema.parse( + s3EventBridgeNotificationObjectDeletedEvent + ) + ).toEqual(s3EventBridgeNotificationObjectDeletedEvent); }); it('should parse s3 event bridge notification event expired', () => { - S3EventNotificationEventBridgeSchema.parse( - s3EventBridgeNotificationObjectExpiredEvent - ); + expect( + S3EventNotificationEventBridgeSchema.parse( + s3EventBridgeNotificationObjectExpiredEvent + ) + ).toEqual(s3EventBridgeNotificationObjectExpiredEvent); }); it('should parse s3 sqs notification event', () => { - S3SqsEventNotificationSchema.parse(s3SqsEvent); + expect(S3SqsEventNotificationSchema.parse(s3SqsEvent)).toEqual(s3SqsEvent); }); }); diff --git a/packages/parser/tests/unit/schema/sns.test.ts b/packages/parser/tests/unit/schema/sns.test.ts index 96e69912ff..29df44e00b 100644 --- a/packages/parser/tests/unit/schema/sns.test.ts +++ b/packages/parser/tests/unit/schema/sns.test.ts @@ -8,6 +8,6 @@ import snsEvent from '../../events/snsEvent.json'; describe('Schema:', () => { it('SNS should parse sns event', () => { - SnsSchema.parse(snsEvent); + expect(SnsSchema.parse(snsEvent)).toEqual(snsEvent); }); }); diff --git a/packages/parser/tests/unit/schema/vpc-lattice.test.ts b/packages/parser/tests/unit/schema/vpc-lattice.test.ts index 0ac3337e0d..e6fbbe06df 100644 --- a/packages/parser/tests/unit/schema/vpc-lattice.test.ts +++ b/packages/parser/tests/unit/schema/vpc-lattice.test.ts @@ -10,11 +10,11 @@ import vpcLatticeEventPathTrailingSlash from '../../events/vpcLatticeEventPathTr describe('VPC Lattice ', () => { it('should parse vpc lattice event', () => { - const parsed = VpcLatticeSchema.parse(vpcLatticeEvent); - expect(parsed).toMatchObject(vpcLatticeEvent); + expect(VpcLatticeSchema.parse(vpcLatticeEvent)).toEqual(vpcLatticeEvent); }); it('should parse vpc lattice path trailing slash event', () => { - const parsed = VpcLatticeSchema.parse(vpcLatticeEventPathTrailingSlash); - expect(parsed).toMatchObject(vpcLatticeEventPathTrailingSlash); + expect(VpcLatticeSchema.parse(vpcLatticeEventPathTrailingSlash)).toEqual( + vpcLatticeEventPathTrailingSlash + ); }); }); From 51219a8e31478e8d4f1067293c6bc2f05cbc8494 Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Fri, 17 Nov 2023 16:22:23 +0100 Subject: [PATCH 38/48] moved cw function from kinesis, fix imports --- packages/parser/src/schemas/cloudwatch.ts | 13 +++- packages/parser/src/schemas/kinesis.ts | 12 +--- packages/parser/src/schemas/s3.ts | 13 ++-- ...udformationCustomResourceCreateEvent.json} | 0 ...udformationCustomResourceDeleteEvent.json} | 0 ...udformationCustomResourceUpdateEvent.json} | 0 packages/parser/tests/tsconfig.json | 4 +- packages/parser/tests/unit/schema/alb.test.ts | 11 +++- .../parser/tests/unit/schema/apigw.test.ts | 31 ++++++--- .../parser/tests/unit/schema/apigwv2.test.ts | 29 +++++++-- .../cloudformation-custom-resource.test.ts | 13 +++- .../tests/unit/schema/cloudwatch.test.ts | 3 +- .../parser/tests/unit/schema/dynamodb.test.ts | 7 +- .../tests/unit/schema/eventbridge.test.ts | 3 +- .../parser/tests/unit/schema/kafka.test.ts | 13 +++- .../parser/tests/unit/schema/kinesis.test.ts | 32 +++++++--- packages/parser/tests/unit/schema/s3.test.ts | 64 +++++++++++++++++-- packages/parser/tests/unit/schema/ses.test.ts | 3 +- packages/parser/tests/unit/schema/sns.test.ts | 3 +- packages/parser/tests/unit/schema/sqs.test.ts | 3 +- packages/parser/tests/unit/schema/utils.ts | 11 ++++ .../tests/unit/schema/vpc-lattice.test.ts | 7 +- .../tests/unit/schema/vpc-latticev2.test.ts | 7 +- 23 files changed, 210 insertions(+), 72 deletions(-) rename packages/parser/tests/events/{cloudformationCustomResourceCreate.json => cloudformationCustomResourceCreateEvent.json} (100%) rename packages/parser/tests/events/{cloudformationCustomResourceDelete.json => cloudformationCustomResourceDeleteEvent.json} (100%) rename packages/parser/tests/events/{cloudformationCustomResourceUpdate.json => cloudformationCustomResourceUpdateEvent.json} (100%) create mode 100644 packages/parser/tests/unit/schema/utils.ts diff --git a/packages/parser/src/schemas/cloudwatch.ts b/packages/parser/src/schemas/cloudwatch.ts index ed1982b627..4383b9531c 100644 --- a/packages/parser/src/schemas/cloudwatch.ts +++ b/packages/parser/src/schemas/cloudwatch.ts @@ -16,9 +16,9 @@ const CloudWatchLogsDecodeSchema = z.object({ logEvents: z.array(CloudWatchLogEventSchema), }); -function decompressRecordToJSON( +const decompressRecordToJSON = ( data: string -): z.infer { +): z.infer => { try { console.debug('Decoding data', data); const uncompressed = gunzipSync(Buffer.from(data, 'base64')).toString( @@ -30,7 +30,7 @@ function decompressRecordToJSON( console.debug('Failed to gunzip data', e); throw e; } -} +}; const CloudWatchLogsSchema = z.object({ awslogs: z.object({ @@ -38,8 +38,15 @@ const CloudWatchLogsSchema = z.object({ }), }); +const extractCloudWatchLogFromEvent = ( + data: string +): z.infer => { + return decompressRecordToJSON(data); +}; + export { CloudWatchLogsSchema, CloudWatchLogsDecodeSchema, decompressRecordToJSON, + extractCloudWatchLogFromEvent, }; diff --git a/packages/parser/src/schemas/kinesis.ts b/packages/parser/src/schemas/kinesis.ts index d3f88b9bbc..d598715420 100644 --- a/packages/parser/src/schemas/kinesis.ts +++ b/packages/parser/src/schemas/kinesis.ts @@ -1,8 +1,4 @@ import { z } from 'zod'; -import { - CloudWatchLogsDecodeSchema, - decompressRecordToJSON, -} from './cloudwatch.js'; const KinesisDataStreamRecordPayload = z.object({ kinesisSchemaVersion: z.string(), @@ -26,10 +22,4 @@ const KinesisDataStreamSchema = z.object({ Records: z.array(KinesisDataStreamRecord), }); -const extractCloudWatchLogFromEvent = ( - data: string -): z.infer => { - return decompressRecordToJSON(data); -}; - -export { KinesisDataStreamSchema, extractCloudWatchLogFromEvent }; +export { KinesisDataStreamSchema }; diff --git a/packages/parser/src/schemas/s3.ts b/packages/parser/src/schemas/s3.ts index e4aa886acc..ab78a0184e 100644 --- a/packages/parser/src/schemas/s3.ts +++ b/packages/parser/src/schemas/s3.ts @@ -20,8 +20,9 @@ const S3Message = z.object({ configurationId: z.string(), object: z.object({ key: z.string(), - size: z.number(), - eTag: z.string(), + size: z.number().optional(), + urlDecodedKey: z.string().optional(), + eTag: z.string().optional(), sequencer: z.string(), versionId: z.optional(z.string()), }), @@ -118,7 +119,9 @@ const S3ObjectSessionContext = z.object({ }), attributes: z.object({ creationDate: z.string(), - mfaAuthenticated: z.string(), + mfaAuthenticated: z + .union([z.boolean(), z.literal('true'), z.literal('false')]) + .transform((value) => value === true || value === 'true'), }), }); @@ -129,13 +132,13 @@ const S3ObjectUserIdentity = z.object({ userName: z.string().optional(), principalId: z.string(), arn: z.string(), - sessionContext: S3ObjectSessionContext, + sessionContext: S3ObjectSessionContext.optional(), }); const S3ObjectLambdaEventSchema = z.object({ xAmzRequestId: z.string(), getObjectContext: S3ObjectContext, - configurationId: S3ObjectConfiguration, + configuration: S3ObjectConfiguration, userRequest: S3ObjectUserRequest, userIdentity: S3ObjectUserIdentity, protocolVersion: z.string(), diff --git a/packages/parser/tests/events/cloudformationCustomResourceCreate.json b/packages/parser/tests/events/cloudformationCustomResourceCreateEvent.json similarity index 100% rename from packages/parser/tests/events/cloudformationCustomResourceCreate.json rename to packages/parser/tests/events/cloudformationCustomResourceCreateEvent.json diff --git a/packages/parser/tests/events/cloudformationCustomResourceDelete.json b/packages/parser/tests/events/cloudformationCustomResourceDeleteEvent.json similarity index 100% rename from packages/parser/tests/events/cloudformationCustomResourceDelete.json rename to packages/parser/tests/events/cloudformationCustomResourceDeleteEvent.json diff --git a/packages/parser/tests/events/cloudformationCustomResourceUpdate.json b/packages/parser/tests/events/cloudformationCustomResourceUpdateEvent.json similarity index 100% rename from packages/parser/tests/events/cloudformationCustomResourceUpdate.json rename to packages/parser/tests/events/cloudformationCustomResourceUpdateEvent.json diff --git a/packages/parser/tests/tsconfig.json b/packages/parser/tests/tsconfig.json index 070483a63f..dc4ebdfc5f 100644 --- a/packages/parser/tests/tsconfig.json +++ b/packages/parser/tests/tsconfig.json @@ -1,13 +1,11 @@ { "extends": "../tsconfig.json", "compilerOptions": { - "resolveJsonModule": true, "rootDir": "../", "noEmit": true }, "include": [ "../src/**/*", - "./**/*.*", - "./**/*.json", + "./**/*.*" ] } \ No newline at end of file diff --git a/packages/parser/tests/unit/schema/alb.test.ts b/packages/parser/tests/unit/schema/alb.test.ts index 9318d26da7..c9ff8e654d 100644 --- a/packages/parser/tests/unit/schema/alb.test.ts +++ b/packages/parser/tests/unit/schema/alb.test.ts @@ -7,20 +7,25 @@ import { AlbSchema, AlbMultiValueHeadersSchema, } from '../../../src/schemas/alb'; -import albEvent from '../../events/albEvent.json'; -import albEventPathTrailingSlash from '../../events/albEventPathTrailingSlash.json'; -import albMultiValueHeadersEvent from '../../events/albMultiValueHeadersEvent.json'; +import { loadExampleEvent } from './utils'; describe('ALB ', () => { it('should parse alb event', () => { + const albEvent = loadExampleEvent('albEvent.json'); expect(AlbSchema.parse(albEvent)).toEqual(albEvent); }); it('should parse alb event path trailing slash', () => { + const albEventPathTrailingSlash = loadExampleEvent( + 'albEventPathTrailingSlash.json' + ); expect(AlbSchema.parse(albEventPathTrailingSlash)).toEqual( albEventPathTrailingSlash ); }); it('should parse alb event with multi value headers event', () => { + const albMultiValueHeadersEvent = loadExampleEvent( + 'albMultiValueHeadersEvent.json' + ); expect(AlbMultiValueHeadersSchema.parse(albMultiValueHeadersEvent)).toEqual( albMultiValueHeadersEvent ); diff --git a/packages/parser/tests/unit/schema/apigw.test.ts b/packages/parser/tests/unit/schema/apigw.test.ts index e44fa406ca..d97fc343c5 100644 --- a/packages/parser/tests/unit/schema/apigw.test.ts +++ b/packages/parser/tests/unit/schema/apigw.test.ts @@ -4,52 +4,67 @@ * @group unit/parser/schema/ */ import { APIGatewayProxyEventSchema } from '../../../src/schemas/apigw'; -import apiGatewayProxyEvent from '../../events/apiGatewayProxyEvent.json'; -import apiGatewayAuthorizerRequestEvent from '../../events/apiGatewayAuthorizerRequestEvent.json'; -import apiGatewaySchemaMiddlewareInvalidEvent from '../../events/apiGatewaySchemaMiddlewareInvalidEvent.json'; -import apiGatewaySchemaMiddlewareValidEvent from '../../events/apiGatewaySchemaMiddlewareValidEvent.json'; -import apiGatewayProxyEvent_noVersionAuth from '../../events/apiGatewayProxyEvent_noVersionAuth.json'; -import apiGatewayProxyEventAnotherPath from '../../events/apiGatewayProxyEventAnotherPath.json'; -import apiGatewayProxyEventPathTrailingSlash from '../../events/apiGatewayProxyEventPathTrailingSlash.json'; -import apiGatewayProxyOtherEvent from '../../events/apiGatewayProxyOtherEvent.json'; +import { loadExampleEvent } from './utils'; describe('APIGateway ', () => { it('should parse api gateway event', () => { + const apiGatewayProxyEvent = loadExampleEvent('apiGatewayProxyEvent.json'); expect(APIGatewayProxyEventSchema.parse(apiGatewayProxyEvent)).toEqual( apiGatewayProxyEvent ); }); it('should parse api gateway authorizer request event', () => { + const apiGatewayAuthorizerRequestEvent = loadExampleEvent( + 'apiGatewayAuthorizerRequestEvent.json' + ); expect( APIGatewayProxyEventSchema.parse(apiGatewayAuthorizerRequestEvent) ).toEqual(apiGatewayAuthorizerRequestEvent); }); it('should parse schema middleware invalid event', () => { + const apiGatewaySchemaMiddlewareInvalidEvent = loadExampleEvent( + 'apiGatewaySchemaMiddlewareInvalidEvent.json' + ); expect( APIGatewayProxyEventSchema.parse(apiGatewaySchemaMiddlewareInvalidEvent) ).toEqual(apiGatewaySchemaMiddlewareInvalidEvent); }); it('should parse schema middleware valid event', () => { + const apiGatewaySchemaMiddlewareValidEvent = loadExampleEvent( + 'apiGatewaySchemaMiddlewareValidEvent.json' + ); expect( APIGatewayProxyEventSchema.parse(apiGatewaySchemaMiddlewareValidEvent) ).toEqual(apiGatewaySchemaMiddlewareValidEvent); }); it('should parse proxy event with no version auth', () => { + const apiGatewayProxyEvent_noVersionAuth = loadExampleEvent( + 'apiGatewayProxyEvent_noVersionAuth.json' + ); expect( APIGatewayProxyEventSchema.parse(apiGatewayProxyEvent_noVersionAuth) ).toEqual(apiGatewayProxyEvent_noVersionAuth); }); it('should parse proxy event with another path', () => { + const apiGatewayProxyEventAnotherPath = loadExampleEvent( + 'apiGatewayProxyEventAnotherPath.json' + ); expect( APIGatewayProxyEventSchema.parse(apiGatewayProxyEventAnotherPath) ).toEqual(apiGatewayProxyEventAnotherPath); }); it('should parse proxy event with path trailing slash', () => { + const apiGatewayProxyEventPathTrailingSlash = loadExampleEvent( + 'apiGatewayProxyEventPathTrailingSlash.json' + ); expect( APIGatewayProxyEventSchema.parse(apiGatewayProxyEventPathTrailingSlash) ).toEqual(apiGatewayProxyEventPathTrailingSlash); }); it('should parse other proxy event', () => { + const apiGatewayProxyOtherEvent = loadExampleEvent( + 'apiGatewayProxyOtherEvent.json' + ); expect(APIGatewayProxyEventSchema.parse(apiGatewayProxyOtherEvent)).toEqual( apiGatewayProxyOtherEvent ); diff --git a/packages/parser/tests/unit/schema/apigwv2.test.ts b/packages/parser/tests/unit/schema/apigwv2.test.ts index e4b6dcc8e7..ea63982983 100644 --- a/packages/parser/tests/unit/schema/apigwv2.test.ts +++ b/packages/parser/tests/unit/schema/apigwv2.test.ts @@ -4,26 +4,29 @@ * @group unit/parser/schema/ */ import { APIGatewayProxyEventV2Schema } from '../../../src/schemas/apigwv2'; -import apiGatewayProxyV2Event from '../../events/apiGatewayProxyV2Event.json'; -import apiGatewayProxyV2Event_GET from '../../events/apiGatewayProxyV2Event_GET.json'; -import apiGatewayProxyV2EventPathTrailingSlash from '../../events/apiGatewayProxyV2EventPathTrailingSlash.json'; -import apiGatewayProxyV2IamEvent from '../../events/apiGatewayProxyV2IamEvent.json'; -import apiGatewayProxyV2LambdaAuthorizerEvent from '../../events/apiGatewayProxyV2LambdaAuthorizerEvent.json'; -import apiGatewayProxyV2OtherGetEvent from '../../events/apiGatewayProxyV2OtherGetEvent.json'; -import apiGatewayProxyV2SchemaMiddlewareValidEvent from '../../events/apiGatewayProxyV2SchemaMiddlewareValidEvent.json'; +import { loadExampleEvent } from './utils'; describe('API GW v2 ', () => { it('should parse api gateway v2 event', () => { + const apiGatewayProxyV2Event = loadExampleEvent( + 'apiGatewayProxyV2Event.json' + ); expect(APIGatewayProxyEventV2Schema.parse(apiGatewayProxyV2Event)).toEqual( apiGatewayProxyV2Event ); }); it('should parse api gateway v2 event with GET method', () => { + const apiGatewayProxyV2Event_GET = loadExampleEvent( + 'apiGatewayProxyV2Event_GET.json' + ); expect( APIGatewayProxyEventV2Schema.parse(apiGatewayProxyV2Event_GET) ).toEqual(apiGatewayProxyV2Event_GET); }); it('should parse api gateway v2 event with path trailing slash', () => { + const apiGatewayProxyV2EventPathTrailingSlash = loadExampleEvent( + 'apiGatewayProxyV2EventPathTrailingSlash.json' + ); expect( APIGatewayProxyEventV2Schema.parse( apiGatewayProxyV2EventPathTrailingSlash @@ -31,21 +34,33 @@ describe('API GW v2 ', () => { ).toEqual(apiGatewayProxyV2EventPathTrailingSlash); }); it('should parse api gateway v2 event with iam', () => { + const apiGatewayProxyV2IamEvent = loadExampleEvent( + 'apiGatewayProxyV2IamEvent.json' + ); expect( APIGatewayProxyEventV2Schema.parse(apiGatewayProxyV2IamEvent) ).toEqual(apiGatewayProxyV2IamEvent); }); it('should parse api gateway v2 event with lambda authorizer', () => { + const apiGatewayProxyV2LambdaAuthorizerEvent = loadExampleEvent( + 'apiGatewayProxyV2LambdaAuthorizerEvent.json' + ); expect( APIGatewayProxyEventV2Schema.parse(apiGatewayProxyV2LambdaAuthorizerEvent) ).toEqual(apiGatewayProxyV2LambdaAuthorizerEvent); }); it('should parse api gateway v2 event with other get event', () => { + const apiGatewayProxyV2OtherGetEvent = loadExampleEvent( + 'apiGatewayProxyV2OtherGetEvent.json' + ); expect( APIGatewayProxyEventV2Schema.parse(apiGatewayProxyV2OtherGetEvent) ).toEqual(apiGatewayProxyV2OtherGetEvent); }); it('should parse api gateway v2 event with schema middleware', () => { + const apiGatewayProxyV2SchemaMiddlewareValidEvent = loadExampleEvent( + 'apiGatewayProxyV2SchemaMiddlewareValidEvent.json' + ); expect( APIGatewayProxyEventV2Schema.parse( apiGatewayProxyV2SchemaMiddlewareValidEvent diff --git a/packages/parser/tests/unit/schema/cloudformation-custom-resource.test.ts b/packages/parser/tests/unit/schema/cloudformation-custom-resource.test.ts index 3ef01fffa5..0426414880 100644 --- a/packages/parser/tests/unit/schema/cloudformation-custom-resource.test.ts +++ b/packages/parser/tests/unit/schema/cloudformation-custom-resource.test.ts @@ -8,12 +8,13 @@ import { CloudFormationCustomResourceUpdateSchema, CloudFormationCustomResourceDeleteSchema, } from '../../../src/schemas/cloudformation-custom-resource'; -import cloudFormationCustomResourceCreateEvent from '../../events/cloudformationCustomResourceCreate.json'; -import cloudFormationCustomResourceUpdateEvent from '../../events/cloudformationCustomResourceUpdate.json'; -import cloudFormationCustomResourceDeleteEvent from '../../events/cloudformationCustomResourceDelete.json'; +import { loadExampleEvent } from './utils'; describe('CloudFormationCustomResource ', () => { it('should parse create event', () => { + const cloudFormationCustomResourceCreateEvent = loadExampleEvent( + 'cloudFormationCustomResourceCreateEvent.json' + ); console.log(CloudFormationCustomResourceCreateSchema.shape); expect( CloudFormationCustomResourceCreateSchema.parse( @@ -22,6 +23,9 @@ describe('CloudFormationCustomResource ', () => { ).toEqual(cloudFormationCustomResourceCreateEvent); }); it('should parse update event', () => { + const cloudFormationCustomResourceUpdateEvent = loadExampleEvent( + 'cloudFormationCustomResourceUpdateEvent.json' + ); expect( CloudFormationCustomResourceUpdateSchema.parse( cloudFormationCustomResourceUpdateEvent @@ -29,6 +33,9 @@ describe('CloudFormationCustomResource ', () => { ).toEqual(cloudFormationCustomResourceUpdateEvent); }); it('should parse delete event', () => { + const cloudFormationCustomResourceDeleteEvent = loadExampleEvent( + 'cloudFormationCustomResourceDeleteEvent.json' + ); expect( CloudFormationCustomResourceDeleteSchema.parse( cloudFormationCustomResourceDeleteEvent diff --git a/packages/parser/tests/unit/schema/cloudwatch.test.ts b/packages/parser/tests/unit/schema/cloudwatch.test.ts index 6a56fbe760..2bd98a4e1b 100644 --- a/packages/parser/tests/unit/schema/cloudwatch.test.ts +++ b/packages/parser/tests/unit/schema/cloudwatch.test.ts @@ -4,10 +4,11 @@ * @group unit/parser/schema/ */ import { CloudWatchLogsSchema } from '../../../src/schemas/cloudwatch'; -import cloudWatchLogEvent from '../../events/cloudWatchLogEvent.json'; +import { loadExampleEvent } from './utils'; describe('CloudWatchLogs ', () => { it('should parse cloudwatch logs event', () => { + const cloudWatchLogEvent = loadExampleEvent('cloudWatchLogEvent.json'); const parsed = CloudWatchLogsSchema.parse(cloudWatchLogEvent); expect(parsed.awslogs.data).toBeDefined(); expect(parsed.awslogs.data?.logEvents[0]).toEqual({ diff --git a/packages/parser/tests/unit/schema/dynamodb.test.ts b/packages/parser/tests/unit/schema/dynamodb.test.ts index 7a7f58d50c..52ae853274 100644 --- a/packages/parser/tests/unit/schema/dynamodb.test.ts +++ b/packages/parser/tests/unit/schema/dynamodb.test.ts @@ -4,12 +4,13 @@ * @group unit/parser/schema/ */ import { DynamoDBStreamSchema } from '../../../src/schemas/dynamodb'; -import dynamodbStreamEvent from '../../events/dynamoStreamEvent.json'; +import { loadExampleEvent } from './utils'; describe('DynamoDB ', () => { + const dynamoStreamEvent = loadExampleEvent('dynamoStreamEvent.json'); it('should parse a stream of records', () => { - expect(DynamoDBStreamSchema.parse(dynamodbStreamEvent)).toEqual( - dynamodbStreamEvent + expect(DynamoDBStreamSchema.parse(dynamoStreamEvent)).toEqual( + dynamoStreamEvent ); }); }); diff --git a/packages/parser/tests/unit/schema/eventbridge.test.ts b/packages/parser/tests/unit/schema/eventbridge.test.ts index 4cc2148686..181a1ef6ea 100644 --- a/packages/parser/tests/unit/schema/eventbridge.test.ts +++ b/packages/parser/tests/unit/schema/eventbridge.test.ts @@ -5,10 +5,11 @@ */ import { EventBridgeSchema } from '../../../src/schemas/eventbridge'; -import eventBridgeEvent from '../../events/eventBridgeEvent.json'; +import { loadExampleEvent } from './utils'; describe('EventBridge ', () => { it('should parse eventbridge event', () => { + const eventBridgeEvent = loadExampleEvent('eventBridgeEvent.json'); expect(EventBridgeSchema.parse(eventBridgeEvent)).toEqual(eventBridgeEvent); }); }); diff --git a/packages/parser/tests/unit/schema/kafka.test.ts b/packages/parser/tests/unit/schema/kafka.test.ts index f204ce49b9..62723471c2 100644 --- a/packages/parser/tests/unit/schema/kafka.test.ts +++ b/packages/parser/tests/unit/schema/kafka.test.ts @@ -7,8 +7,7 @@ import { KafkaMskEventSchema, KafkaSelfManagedEventSchema, } from '../../../src/schemas/kafka'; -import kafkaEventMsk from '../../events/kafkaEventMsk.json'; -import kafkaEventSelfManaged from '../../events/kafkaEventSelfManaged.json'; +import { loadExampleEvent } from './utils'; describe('Kafka ', () => { const expectedTestEvent = { @@ -26,11 +25,15 @@ describe('Kafka ', () => { ], }; it('should parse kafka MSK event', () => { + const kafkaEventMsk = loadExampleEvent('kafkaEventMsk.json'); expect( KafkaMskEventSchema.parse(kafkaEventMsk).records['mytopic-0'][0] ).toEqual(expectedTestEvent); }); it('should parse kafka self managed event', () => { + const kafkaEventSelfManaged = loadExampleEvent( + 'kafkaEventSelfManaged.json' + ); expect( KafkaSelfManagedEventSchema.parse(kafkaEventSelfManaged).records[ 'mytopic-0' @@ -38,6 +41,9 @@ describe('Kafka ', () => { ).toEqual(expectedTestEvent); }); it('should transform bootstrapServers to array', () => { + const kafkaEventSelfManaged = loadExampleEvent( + 'kafkaEventSelfManaged.json' + ); expect( KafkaSelfManagedEventSchema.parse(kafkaEventSelfManaged).bootstrapServers ).toEqual([ @@ -46,6 +52,9 @@ describe('Kafka ', () => { ]); }); it('should return undefined if bootstrapServers is not present', () => { + const kafkaEventSelfManaged = loadExampleEvent( + 'kafkaEventSelfManaged.json' + ); kafkaEventSelfManaged.bootstrapServers = ''; const parsed = KafkaSelfManagedEventSchema.parse(kafkaEventSelfManaged); expect(parsed.bootstrapServers).toBeUndefined(); diff --git a/packages/parser/tests/unit/schema/kinesis.test.ts b/packages/parser/tests/unit/schema/kinesis.test.ts index 71d9fb1faf..61893eac32 100644 --- a/packages/parser/tests/unit/schema/kinesis.test.ts +++ b/packages/parser/tests/unit/schema/kinesis.test.ts @@ -3,23 +3,17 @@ * * @group unit/parser/schema/ */ -import { - KinesisDataStreamSchema, - extractCloudWatchLogFromEvent, -} from '../../../src/schemas/kinesis'; -import kinesisStreamEvent from '../../events/kinesisStreamEvent.json'; -import kinesisStreamEventOneRecord from '../../events/kinesisStreamEventOneRecord.json'; +import { KinesisDataStreamSchema } from '../../../src/schemas/kinesis'; import { KinesisFirehoseSchema, KinesisFirehoseSqsSchema, } from '../../../src/schemas/kinesis-firehose'; -import kinesisFirehoseKinesisEvent from '../../events/kinesisFirehoseKinesisEvent.json'; -import kinesisFirehosePutEvent from '../../events/kinesisFirehosePutEvent.json'; -import kinesisFirehoseSQSEvent from '../../events/kinesisFirehoseSQSEvent.json'; -import kinesisStreamCloudWatchLogsEvent from '../../events/kinesisStreamCloudWatchLogsEvent.json'; +import { loadExampleEvent } from './utils'; +import { extractCloudWatchLogFromEvent } from '../../../src/schemas/cloudwatch'; describe('Kinesis ', () => { it('should parse kinesis event', () => { + const kinesisStreamEvent = loadExampleEvent('kinesisStreamEvent.json'); const parsed = KinesisDataStreamSchema.parse(kinesisStreamEvent); const decodedData = Buffer.from( parsed.Records[0].kinesis.data, @@ -28,6 +22,9 @@ describe('Kinesis ', () => { expect(decodedData).toEqual('Hello, this is a test.'); }); it('should prase single kinesis record', () => { + const kinesisStreamEventOneRecord = loadExampleEvent( + 'kinesisStreamEventOneRecord.json' + ); const parsed = KinesisDataStreamSchema.parse(kinesisStreamEventOneRecord); const decodedJson = JSON.parse( Buffer.from(parsed.Records[0].kinesis.data, 'base64').toString('utf8') @@ -38,16 +35,25 @@ describe('Kinesis ', () => { }); }); it('should parse Firehose event', () => { + const kinesisFirehoseKinesisEvent = loadExampleEvent( + 'kinesisFirehoseKinesisEvent.json' + ); const parsed = KinesisFirehoseSchema.parse(kinesisFirehoseKinesisEvent); expect(parsed.records[0].data).toEqual('Hello World'); }); it('should parse Kinesis Firehose PutEvents event', () => { + const kinesisFirehosePutEvent = loadExampleEvent( + 'kinesisFirehosePutEvent.json' + ); const parsed = KinesisFirehoseSchema.parse(kinesisFirehosePutEvent); expect(JSON.parse(parsed.records[1].data)).toEqual({ Hello: 'World', }); }); it('should parse Firehose event with SQS event', () => { + const kinesisFirehoseSQSEvent = loadExampleEvent( + 'kinesisFirehoseSQSEvent.json' + ); const parsed = KinesisFirehoseSqsSchema.parse(kinesisFirehoseSQSEvent); console.log(parsed.records[0].data); expect(parsed.records[0].data).toMatchObject({ @@ -56,6 +62,9 @@ describe('Kinesis ', () => { }); }); it('should parse Firehose event with CloudWatch event', () => { + const kinesisStreamCloudWatchLogsEvent = loadExampleEvent( + 'kinesisStreamCloudWatchLogsEvent.json' + ); const parsed = KinesisDataStreamSchema.parse( kinesisStreamCloudWatchLogsEvent ); @@ -71,6 +80,9 @@ describe('Kinesis ', () => { }); }); it('should return original value if cannot parse KinesisFirehoseSqsRecord', () => { + const kinesisFirehoseSQSEvent = loadExampleEvent( + 'kinesisFirehoseSQSEvent.json' + ); kinesisFirehoseSQSEvent.records[0].data = 'not a valid json'; const parsed = KinesisFirehoseSqsSchema.parse(kinesisFirehoseSQSEvent); expect(parsed.records[0].data).toEqual('not a valid json'); diff --git a/packages/parser/tests/unit/schema/s3.test.ts b/packages/parser/tests/unit/schema/s3.test.ts index c4211dfc3d..eb7aacad5a 100644 --- a/packages/parser/tests/unit/schema/s3.test.ts +++ b/packages/parser/tests/unit/schema/s3.test.ts @@ -7,19 +7,20 @@ import { S3Schema, S3EventNotificationEventBridgeSchema, S3SqsEventNotificationSchema, + S3ObjectLambdaEventSchema, } from '../../../src/schemas/s3'; -import s3Event from '../../events/s3Event.json'; -import s3EventBridgeNotificationObjectCreatedEvent from '../../events/s3EventBridgeNotificationObjectCreatedEvent.json'; -import s3EventBridgeNotificationObjectDeletedEvent from '../../events/s3EventBridgeNotificationObjectDeletedEvent.json'; -import s3EventBridgeNotificationObjectExpiredEvent from '../../events/s3EventBridgeNotificationObjectExpiredEvent.json'; -import s3SqsEvent from '../../events/s3SqsEvent.json'; +import { loadExampleEvent } from './utils'; describe('S3 ', () => { it('should parse s3 event', () => { + const s3Event = loadExampleEvent('s3Event.json'); expect(S3Schema.parse(s3Event)).toEqual(s3Event); }); it('should parse s3 event bridge notification event created', () => { + const s3EventBridgeNotificationObjectCreatedEvent = loadExampleEvent( + 's3EventBridgeNotificationObjectCreatedEvent.json' + ); expect( S3EventNotificationEventBridgeSchema.parse( s3EventBridgeNotificationObjectCreatedEvent @@ -28,6 +29,9 @@ describe('S3 ', () => { }); it('should parse s3 event bridge notification event detelted', () => { + const s3EventBridgeNotificationObjectDeletedEvent = loadExampleEvent( + 's3EventBridgeNotificationObjectDeletedEvent.json' + ); expect( S3EventNotificationEventBridgeSchema.parse( s3EventBridgeNotificationObjectDeletedEvent @@ -35,6 +39,9 @@ describe('S3 ', () => { ).toEqual(s3EventBridgeNotificationObjectDeletedEvent); }); it('should parse s3 event bridge notification event expired', () => { + const s3EventBridgeNotificationObjectExpiredEvent = loadExampleEvent( + 's3EventBridgeNotificationObjectExpiredEvent.json' + ); expect( S3EventNotificationEventBridgeSchema.parse( s3EventBridgeNotificationObjectExpiredEvent @@ -43,6 +50,53 @@ describe('S3 ', () => { }); it('should parse s3 sqs notification event', () => { + const s3SqsEvent = loadExampleEvent('s3SqsEvent.json'); expect(S3SqsEventNotificationSchema.parse(s3SqsEvent)).toEqual(s3SqsEvent); }); + + it('should parse s3 event with decoded key', () => { + const s3EventDecodedKey = loadExampleEvent('s3EventDecodedKey.json'); + expect(S3Schema.parse(s3EventDecodedKey)).toEqual(s3EventDecodedKey); + }); + + it('should parse s3 event delete object', () => { + const s3EventDeleteObject = loadExampleEvent('s3EventDeleteObject.json'); + expect(S3Schema.parse(s3EventDeleteObject)).toEqual(s3EventDeleteObject); + }); + + it('should parse s3 event glacier', () => { + const s3EventGlacier = loadExampleEvent('s3EventGlacier.json'); + expect(S3Schema.parse(s3EventGlacier)).toEqual(s3EventGlacier); + }); + + it('should parse s3 object event iam user', () => { + const s3ObjectEventIAMUser = loadExampleEvent('s3ObjectEventIAMUser.json'); + expect(S3ObjectLambdaEventSchema.parse(s3ObjectEventIAMUser)).toEqual( + s3ObjectEventIAMUser + ); + }); + + it('should parse s3 object event temp credentials', () => { + const s3ObjectEventTempCredentials = loadExampleEvent( + 's3ObjectEventTempCredentials.json' + ); + const parsed = S3ObjectLambdaEventSchema.parse( + s3ObjectEventTempCredentials + ); + expect(parsed.userRequest).toEqual( + s3ObjectEventTempCredentials.userRequest + ); + expect(parsed.getObjectContext).toEqual( + s3ObjectEventTempCredentials.getObjectContext + ); + expect(parsed.configuration).toEqual( + s3ObjectEventTempCredentials.configuration + ); + expect(parsed.userRequest).toEqual( + s3ObjectEventTempCredentials.userRequest + ); + expect( + parsed.userIdentity?.sessionContext?.attributes.mfaAuthenticated + ).toEqual(false); + }); }); diff --git a/packages/parser/tests/unit/schema/ses.test.ts b/packages/parser/tests/unit/schema/ses.test.ts index 87f86a25c0..a284554750 100644 --- a/packages/parser/tests/unit/schema/ses.test.ts +++ b/packages/parser/tests/unit/schema/ses.test.ts @@ -4,9 +4,10 @@ * @group unit/parser/schema/ */ import { SesSchema } from '../../../src/schemas/ses'; -import sesEvent from '../../events/sesEvent.json'; +import { loadExampleEvent } from './utils'; describe('Schema:', () => { + const sesEvent = loadExampleEvent('sesEvent.json'); it('SES should parse ses event', () => { expect(SesSchema.parse(sesEvent)).toEqual(sesEvent); }); diff --git a/packages/parser/tests/unit/schema/sns.test.ts b/packages/parser/tests/unit/schema/sns.test.ts index 29df44e00b..d8b7acd9d0 100644 --- a/packages/parser/tests/unit/schema/sns.test.ts +++ b/packages/parser/tests/unit/schema/sns.test.ts @@ -4,9 +4,10 @@ * @group unit/parser/schema/ */ import { SnsSchema } from '../../../src/schemas/sns'; -import snsEvent from '../../events/snsEvent.json'; +import { loadExampleEvent } from './utils'; describe('Schema:', () => { + const snsEvent = loadExampleEvent('snsEvent.json'); it('SNS should parse sns event', () => { expect(SnsSchema.parse(snsEvent)).toEqual(snsEvent); }); diff --git a/packages/parser/tests/unit/schema/sqs.test.ts b/packages/parser/tests/unit/schema/sqs.test.ts index 098d53a6d8..f1d87fee4a 100644 --- a/packages/parser/tests/unit/schema/sqs.test.ts +++ b/packages/parser/tests/unit/schema/sqs.test.ts @@ -4,9 +4,10 @@ * @group unit/parser/schema/ */ import { SqsSchema } from '../../../src/schemas/sqs'; -import sqsEvent from '../../events/sqsEvent.json'; +import { loadExampleEvent } from './utils'; describe('SQS ', () => { + const sqsEvent = loadExampleEvent('sqsEvent.json'); it('should parse sqs event', () => { expect(SqsSchema.parse(sqsEvent)).toEqual(sqsEvent); }); diff --git a/packages/parser/tests/unit/schema/utils.ts b/packages/parser/tests/unit/schema/utils.ts new file mode 100644 index 0000000000..4b70a493bc --- /dev/null +++ b/packages/parser/tests/unit/schema/utils.ts @@ -0,0 +1,11 @@ +import * as fs from 'fs'; + +export const loadExampleEvent = (fileName: string): unknown => { + try { + const event = fs.readFileSync(`tests/events/${fileName}`, 'utf8'); + + return JSON.parse(event); + } catch (err) { + console.error(err); + } +}; diff --git a/packages/parser/tests/unit/schema/vpc-lattice.test.ts b/packages/parser/tests/unit/schema/vpc-lattice.test.ts index e6fbbe06df..fe1f325254 100644 --- a/packages/parser/tests/unit/schema/vpc-lattice.test.ts +++ b/packages/parser/tests/unit/schema/vpc-lattice.test.ts @@ -5,14 +5,17 @@ */ import { VpcLatticeSchema } from '../../../src/schemas/vpc-lattice'; -import vpcLatticeEvent from '../../events/vpcLatticeEvent.json'; -import vpcLatticeEventPathTrailingSlash from '../../events/vpcLatticeEventPathTrailingSlash.json'; +import { loadExampleEvent } from './utils'; describe('VPC Lattice ', () => { it('should parse vpc lattice event', () => { + const vpcLatticeEvent = loadExampleEvent('vpcLatticeEvent.json'); expect(VpcLatticeSchema.parse(vpcLatticeEvent)).toEqual(vpcLatticeEvent); }); it('should parse vpc lattice path trailing slash event', () => { + const vpcLatticeEventPathTrailingSlash = loadExampleEvent( + 'vpcLatticeEventPathTrailingSlash.json' + ); expect(VpcLatticeSchema.parse(vpcLatticeEventPathTrailingSlash)).toEqual( vpcLatticeEventPathTrailingSlash ); diff --git a/packages/parser/tests/unit/schema/vpc-latticev2.test.ts b/packages/parser/tests/unit/schema/vpc-latticev2.test.ts index f3f5affe77..bde304c91b 100644 --- a/packages/parser/tests/unit/schema/vpc-latticev2.test.ts +++ b/packages/parser/tests/unit/schema/vpc-latticev2.test.ts @@ -5,16 +5,19 @@ */ import { VpcLatticeV2Schema } from '../../../src/schemas/vpc-latticev2'; -import vpcLatticeV2Event from '../../events/vpcLatticeV2Event.json'; -import vpcLatticeEventV2PathTrailingSlash from '../../events/vpcLatticeEventV2PathTrailingSlash.json'; +import { loadExampleEvent } from './utils'; describe('VpcLatticeV2 ', () => { it('should parse VpcLatticeV2 event', () => { + const vpcLatticeV2Event = loadExampleEvent('vpcLatticeV2Event.json'); const parsed = VpcLatticeV2Schema.parse(vpcLatticeV2Event); expect(parsed).toEqual(vpcLatticeV2Event); }); it('should parse VpcLatticeV2PathTrailingSlash event', () => { + const vpcLatticeEventV2PathTrailingSlash = loadExampleEvent( + 'vpcLatticeEventV2PathTrailingSlash.json' + ); const parsed = VpcLatticeV2Schema.parse(vpcLatticeEventV2PathTrailingSlash); expect(parsed).toEqual(vpcLatticeEventV2PathTrailingSlash); }); From bbf5ac36bc50e5d43775951488968ae73a4a3ce6 Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Fri, 17 Nov 2023 16:35:46 +0100 Subject: [PATCH 39/48] add parser to build step in ci --- .github/actions/cached-node-modules/action.yml | 1 + .../workflows/reusable-run-linting-check-and-unit-tests.yml | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/actions/cached-node-modules/action.yml b/.github/actions/cached-node-modules/action.yml index 008c852792..6d27b04694 100644 --- a/.github/actions/cached-node-modules/action.yml +++ b/.github/actions/cached-node-modules/action.yml @@ -44,5 +44,6 @@ runs: npm run build -w packages/parameters & \ npm run build -w packages/idempotency & \ npm run build -w packages/batch & \ + npm run build -w packages/parser & \ npm run build -w packages/testing shell: bash \ No newline at end of file diff --git a/.github/workflows/reusable-run-linting-check-and-unit-tests.yml b/.github/workflows/reusable-run-linting-check-and-unit-tests.yml index 6b845abe20..a8321ad566 100644 --- a/.github/workflows/reusable-run-linting-check-and-unit-tests.yml +++ b/.github/workflows/reusable-run-linting-check-and-unit-tests.yml @@ -25,9 +25,9 @@ jobs: with: nodeVersion: ${{ matrix.version }} - name: Run linting - run: npm run lint -w packages/commons -w packages/logger -w packages/tracer -w packages/metrics -w packages/parameters -w packages/idempotency -w packages/batch + run: npm run lint -w packages/commons -w packages/logger -w packages/tracer -w packages/metrics -w packages/parameters -w packages/idempotency -w packages/batch -w packages/parser - name: Run unit tests - run: npm t -w packages/commons -w packages/logger -w packages/tracer -w packages/metrics -w packages/parameters -w packages/idempotency -w packages/batch + run: npm t -w packages/commons -w packages/logger -w packages/tracer -w packages/metrics -w packages/parameters -w packages/idempotency -w packages/batch -w packages/parser check-examples: runs-on: ubuntu-latest env: From d8a040f92d21961ab5f7076baea912c9b3b3c11a Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Fri, 17 Nov 2023 17:07:07 +0100 Subject: [PATCH 40/48] use any safely here --- packages/parser/src/schemas/lambda.ts | 13 +++++++++++++ .../parser/tests/unit/schema/kafka.test.ts | 2 +- .../parser/tests/unit/schema/kinesis.test.ts | 2 +- .../parser/tests/unit/schema/lambda.test.ts | 18 ++++++++++++++++++ packages/parser/tests/unit/schema/s3.test.ts | 4 +++- 5 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 packages/parser/src/schemas/lambda.ts create mode 100644 packages/parser/tests/unit/schema/lambda.test.ts diff --git a/packages/parser/src/schemas/lambda.ts b/packages/parser/src/schemas/lambda.ts new file mode 100644 index 0000000000..65b746b4f2 --- /dev/null +++ b/packages/parser/src/schemas/lambda.ts @@ -0,0 +1,13 @@ +import { APIGatewayProxyEventV2Schema } from './apigwv2.js'; + +const LambdaFunctionUrlSchema = APIGatewayProxyEventV2Schema.extend({ + // Lambda Function URL follows the API Gateway HTTP APIs Payload Format Version 2.0. + // + // Keys related to API Gateway features not available in Function URL use a sentinel value (e.g.`routeKey`, `stage`). + // + // Documentation: + // - https://docs.aws.amazon.com/lambda/latest/dg/urls-configuration.html + // - https://docs.aws.amazon.com/lambda/latest/dg/urls-invocation.html#urls-payloads +}); + +export { LambdaFunctionUrlSchema }; diff --git a/packages/parser/tests/unit/schema/kafka.test.ts b/packages/parser/tests/unit/schema/kafka.test.ts index 62723471c2..55826e6884 100644 --- a/packages/parser/tests/unit/schema/kafka.test.ts +++ b/packages/parser/tests/unit/schema/kafka.test.ts @@ -54,7 +54,7 @@ describe('Kafka ', () => { it('should return undefined if bootstrapServers is not present', () => { const kafkaEventSelfManaged = loadExampleEvent( 'kafkaEventSelfManaged.json' - ); + ) as { bootstrapServers: string }; kafkaEventSelfManaged.bootstrapServers = ''; const parsed = KafkaSelfManagedEventSchema.parse(kafkaEventSelfManaged); expect(parsed.bootstrapServers).toBeUndefined(); diff --git a/packages/parser/tests/unit/schema/kinesis.test.ts b/packages/parser/tests/unit/schema/kinesis.test.ts index 61893eac32..7bf1fd0575 100644 --- a/packages/parser/tests/unit/schema/kinesis.test.ts +++ b/packages/parser/tests/unit/schema/kinesis.test.ts @@ -82,7 +82,7 @@ describe('Kinesis ', () => { it('should return original value if cannot parse KinesisFirehoseSqsRecord', () => { const kinesisFirehoseSQSEvent = loadExampleEvent( 'kinesisFirehoseSQSEvent.json' - ); + ) as { records: { data: string }[] }; kinesisFirehoseSQSEvent.records[0].data = 'not a valid json'; const parsed = KinesisFirehoseSqsSchema.parse(kinesisFirehoseSQSEvent); expect(parsed.records[0].data).toEqual('not a valid json'); diff --git a/packages/parser/tests/unit/schema/lambda.test.ts b/packages/parser/tests/unit/schema/lambda.test.ts new file mode 100644 index 0000000000..bbbf374e62 --- /dev/null +++ b/packages/parser/tests/unit/schema/lambda.test.ts @@ -0,0 +1,18 @@ +/** + * Test built in schema + * + * @group unit/parser/schema/ + */ +import { loadExampleEvent } from './utils'; +import { LambdaFunctionUrlSchema } from '../../../src/schemas/lambda'; + +describe('Lambda ', () => { + it('should parse lambda event', () => { + const lambdaFunctionUrlEvent = loadExampleEvent( + 'apiGatewayProxyV2Event.json' + ); + expect(LambdaFunctionUrlSchema.parse(lambdaFunctionUrlEvent)).toEqual( + lambdaFunctionUrlEvent + ); + }); +}); diff --git a/packages/parser/tests/unit/schema/s3.test.ts b/packages/parser/tests/unit/schema/s3.test.ts index eb7aacad5a..33703cddab 100644 --- a/packages/parser/tests/unit/schema/s3.test.ts +++ b/packages/parser/tests/unit/schema/s3.test.ts @@ -77,12 +77,14 @@ describe('S3 ', () => { }); it('should parse s3 object event temp credentials', () => { + // ignore any because we don't want typed json const s3ObjectEventTempCredentials = loadExampleEvent( 's3ObjectEventTempCredentials.json' - ); + ) as any; // eslint-disable-line @typescript-eslint/no-explicit-any const parsed = S3ObjectLambdaEventSchema.parse( s3ObjectEventTempCredentials ); + expect(parsed.userRequest).toEqual( s3ObjectEventTempCredentials.userRequest ); From 254ebd7055d988c374016199e9bfca2d7b1429e4 Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Fri, 17 Nov 2023 17:09:24 +0100 Subject: [PATCH 41/48] removed console logs --- packages/parser/src/schemas/cloudwatch.ts | 12 ++---------- packages/parser/src/schemas/kinesis-firehose.ts | 4 ---- .../schema/cloudformation-custom-resource.test.ts | 1 - packages/parser/tests/unit/schema/kinesis.test.ts | 1 - 4 files changed, 2 insertions(+), 16 deletions(-) diff --git a/packages/parser/src/schemas/cloudwatch.ts b/packages/parser/src/schemas/cloudwatch.ts index 4383b9531c..8c9e71f9a0 100644 --- a/packages/parser/src/schemas/cloudwatch.ts +++ b/packages/parser/src/schemas/cloudwatch.ts @@ -19,17 +19,9 @@ const CloudWatchLogsDecodeSchema = z.object({ const decompressRecordToJSON = ( data: string ): z.infer => { - try { - console.debug('Decoding data', data); - const uncompressed = gunzipSync(Buffer.from(data, 'base64')).toString( - 'utf8' - ); + const uncompressed = gunzipSync(Buffer.from(data, 'base64')).toString('utf8'); - return CloudWatchLogsDecodeSchema.parse(JSON.parse(uncompressed)); - } catch (e) { - console.debug('Failed to gunzip data', e); - throw e; - } + return CloudWatchLogsDecodeSchema.parse(JSON.parse(uncompressed)); }; const CloudWatchLogsSchema = z.object({ diff --git a/packages/parser/src/schemas/kinesis-firehose.ts b/packages/parser/src/schemas/kinesis-firehose.ts index b5f3f72fd0..e541cc3f65 100644 --- a/packages/parser/src/schemas/kinesis-firehose.ts +++ b/packages/parser/src/schemas/kinesis-firehose.ts @@ -31,14 +31,10 @@ const KinesisFirehoseRecord = KinesisFireHoseRecordBase.extend({ const KinesisFirehoseSqsRecord = KinesisFireHoseRecordBase.extend({ data: z.string().transform((data) => { try { - console.debug('Parsing sqs record', data); - return SqsRecordSchema.parse( JSON.parse(Buffer.from(data, 'base64').toString('utf8')) ); } catch (e) { - console.warn('Failed to parse sqs record', e); - return data; } }), diff --git a/packages/parser/tests/unit/schema/cloudformation-custom-resource.test.ts b/packages/parser/tests/unit/schema/cloudformation-custom-resource.test.ts index 0426414880..a7face9e8a 100644 --- a/packages/parser/tests/unit/schema/cloudformation-custom-resource.test.ts +++ b/packages/parser/tests/unit/schema/cloudformation-custom-resource.test.ts @@ -15,7 +15,6 @@ describe('CloudFormationCustomResource ', () => { const cloudFormationCustomResourceCreateEvent = loadExampleEvent( 'cloudFormationCustomResourceCreateEvent.json' ); - console.log(CloudFormationCustomResourceCreateSchema.shape); expect( CloudFormationCustomResourceCreateSchema.parse( cloudFormationCustomResourceCreateEvent diff --git a/packages/parser/tests/unit/schema/kinesis.test.ts b/packages/parser/tests/unit/schema/kinesis.test.ts index 7bf1fd0575..14d2a86979 100644 --- a/packages/parser/tests/unit/schema/kinesis.test.ts +++ b/packages/parser/tests/unit/schema/kinesis.test.ts @@ -55,7 +55,6 @@ describe('Kinesis ', () => { 'kinesisFirehoseSQSEvent.json' ); const parsed = KinesisFirehoseSqsSchema.parse(kinesisFirehoseSQSEvent); - console.log(parsed.records[0].data); expect(parsed.records[0].data).toMatchObject({ messageId: '5ab807d4-5644-4c55-97a3-47396635ac74', body: 'Test message.', From e0dcf23efa5f7d61d7afa3ef4d3820830fe9a5b0 Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Fri, 17 Nov 2023 17:25:21 +0100 Subject: [PATCH 42/48] name, add datetime to strings --- packages/parser/src/schemas/s3.ts | 4 ++-- packages/parser/src/schemas/sns.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/parser/src/schemas/s3.ts b/packages/parser/src/schemas/s3.ts index ab78a0184e..1d5269642b 100644 --- a/packages/parser/src/schemas/s3.ts +++ b/packages/parser/src/schemas/s3.ts @@ -40,7 +40,7 @@ const S3EventRecordGlacierEventData = z.object({ }), }); -const S3Record = z.object({ +const S3RecordSchema = z.object({ eventVersion: z.string(), eventSource: z.literal('aws:s3'), awsRegion: z.string(), @@ -81,7 +81,7 @@ const S3EventNotificationEventBridgeSchema = EventBridgeSchema.extend({ }); const S3Schema = z.object({ - Records: z.array(S3Record), + Records: z.array(S3RecordSchema), }); const S3SqsEventNotificationRecordSchema = SqsRecordSchema.extend({ diff --git a/packages/parser/src/schemas/sns.ts b/packages/parser/src/schemas/sns.ts index 8c84a7d537..f8d8d8bbc4 100644 --- a/packages/parser/src/schemas/sns.ts +++ b/packages/parser/src/schemas/sns.ts @@ -16,7 +16,7 @@ const SnsNotificationSchema = z.object({ Signature: z.string().optional(), SignatureVersion: z.string().optional(), SigningCertUrl: z.string().url().optional(), - Timestamp: z.string(), + Timestamp: z.string().datetime(), }); const SnsRecordSchema = z.object({ From 0b6d57096201134cba07dae38d6b81db3193ed46 Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Fri, 17 Nov 2023 17:26:24 +0100 Subject: [PATCH 43/48] narrow string to datetime --- packages/parser/src/schemas/s3.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/parser/src/schemas/s3.ts b/packages/parser/src/schemas/s3.ts index 1d5269642b..af0291373a 100644 --- a/packages/parser/src/schemas/s3.ts +++ b/packages/parser/src/schemas/s3.ts @@ -44,7 +44,7 @@ const S3RecordSchema = z.object({ eventVersion: z.string(), eventSource: z.literal('aws:s3'), awsRegion: z.string(), - eventTime: z.string(), + eventTime: z.string().datetime(), eventName: z.string(), userIdentity: S3Identity, requestParameters: S3RequestParameters, From f453246e7c4726c2546928c7c7ca1ab97522dcff Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Fri, 17 Nov 2023 17:44:16 +0100 Subject: [PATCH 44/48] refine to url --- packages/parser/src/schemas/s3.ts | 38 ++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/packages/parser/src/schemas/s3.ts b/packages/parser/src/schemas/s3.ts index af0291373a..558776ffa5 100644 --- a/packages/parser/src/schemas/s3.ts +++ b/packages/parser/src/schemas/s3.ts @@ -40,18 +40,30 @@ const S3EventRecordGlacierEventData = z.object({ }), }); -const S3RecordSchema = z.object({ - eventVersion: z.string(), - eventSource: z.literal('aws:s3'), - awsRegion: z.string(), - eventTime: z.string().datetime(), - eventName: z.string(), - userIdentity: S3Identity, - requestParameters: S3RequestParameters, - responseElements: S3ResponseElements, - s3: S3Message, - glacierEventData: z.optional(S3EventRecordGlacierEventData), -}); +const S3RecordSchema = z + .object({ + eventVersion: z.string(), + eventSource: z.literal('aws:s3'), + awsRegion: z.string(), + eventTime: z.string().datetime(), + eventName: z.string(), + userIdentity: S3Identity, + requestParameters: S3RequestParameters, + responseElements: S3ResponseElements, + s3: S3Message, + glacierEventData: z.optional(S3EventRecordGlacierEventData), + }) + .refine((value) => { + return ( + (!value.eventName.includes('ObjectRemoved') && + value.s3.object.size === undefined) || + value.s3.object.eTag === undefined, + { + message: + 'S3 event notification with ObjectRemoved event name must have size or eTag defined', + } + ); + }); const S3EventNotificationEventBridgeDetailSchema = z.object({ version: z.string(), @@ -93,7 +105,7 @@ const S3SqsEventNotificationSchema = z.object({ }); const S3ObjectContext = z.object({ - inputS3Url: z.string(), + inputS3Url: z.string().url(), outputRoute: z.string(), outputToken: z.string(), }); From 455b329d8e0ae20fa53fcbedfaa0e99febc7e70b Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Fri, 17 Nov 2023 17:45:42 +0100 Subject: [PATCH 45/48] imports, remove try/catch --- packages/parser/tests/unit/schema/utils.ts | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/packages/parser/tests/unit/schema/utils.ts b/packages/parser/tests/unit/schema/utils.ts index 4b70a493bc..0d33dfba38 100644 --- a/packages/parser/tests/unit/schema/utils.ts +++ b/packages/parser/tests/unit/schema/utils.ts @@ -1,11 +1,7 @@ -import * as fs from 'fs'; +import { readFileSync } from 'node:fs'; export const loadExampleEvent = (fileName: string): unknown => { - try { - const event = fs.readFileSync(`tests/events/${fileName}`, 'utf8'); + const event = readFileSync(`tests/events/${fileName}`, 'utf8'); - return JSON.parse(event); - } catch (err) { - console.error(err); - } + return JSON.parse(event); }; From 228217e557e398fe88ebdf0a8c48575ff4f5ce30 Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Fri, 17 Nov 2023 17:56:42 +0100 Subject: [PATCH 46/48] add .js extension to imports --- packages/parser/tests/unit/schema/alb.test.ts | 4 ++-- packages/parser/tests/unit/schema/apigw.test.ts | 5 +++-- packages/parser/tests/unit/schema/apigwv2.test.ts | 5 +++-- .../schema/cloudformation-custom-resource.test.ts | 5 +++-- packages/parser/tests/unit/schema/cloudwatch.test.ts | 5 +++-- packages/parser/tests/unit/schema/dynamodb.test.ts | 5 +++-- packages/parser/tests/unit/schema/eventbridge.test.ts | 4 ++-- packages/parser/tests/unit/schema/kafka.test.ts | 5 +++-- packages/parser/tests/unit/schema/kinesis.test.ts | 11 ++++++----- packages/parser/tests/unit/schema/lambda.test.ts | 5 +++-- packages/parser/tests/unit/schema/s3.test.ts | 7 ++++--- packages/parser/tests/unit/schema/ses.test.ts | 5 +++-- packages/parser/tests/unit/schema/sns.test.ts | 5 +++-- packages/parser/tests/unit/schema/sqs.test.ts | 5 +++-- packages/parser/tests/unit/schema/vpc-lattice.test.ts | 4 ++-- .../parser/tests/unit/schema/vpc-latticev2.test.ts | 4 ++-- 16 files changed, 48 insertions(+), 36 deletions(-) diff --git a/packages/parser/tests/unit/schema/alb.test.ts b/packages/parser/tests/unit/schema/alb.test.ts index c9ff8e654d..5e9144582e 100644 --- a/packages/parser/tests/unit/schema/alb.test.ts +++ b/packages/parser/tests/unit/schema/alb.test.ts @@ -6,8 +6,8 @@ import { AlbSchema, AlbMultiValueHeadersSchema, -} from '../../../src/schemas/alb'; -import { loadExampleEvent } from './utils'; +} from '../../../src/schemas/alb.js'; +import { loadExampleEvent } from './utils.js'; describe('ALB ', () => { it('should parse alb event', () => { diff --git a/packages/parser/tests/unit/schema/apigw.test.ts b/packages/parser/tests/unit/schema/apigw.test.ts index d97fc343c5..9aa23c6694 100644 --- a/packages/parser/tests/unit/schema/apigw.test.ts +++ b/packages/parser/tests/unit/schema/apigw.test.ts @@ -3,8 +3,9 @@ * * @group unit/parser/schema/ */ -import { APIGatewayProxyEventSchema } from '../../../src/schemas/apigw'; -import { loadExampleEvent } from './utils'; + +import { loadExampleEvent } from './utils.js'; +import { APIGatewayProxyEventSchema } from '../../../src/schemas/apigw.js'; describe('APIGateway ', () => { it('should parse api gateway event', () => { diff --git a/packages/parser/tests/unit/schema/apigwv2.test.ts b/packages/parser/tests/unit/schema/apigwv2.test.ts index ea63982983..85ac2da1a2 100644 --- a/packages/parser/tests/unit/schema/apigwv2.test.ts +++ b/packages/parser/tests/unit/schema/apigwv2.test.ts @@ -3,8 +3,9 @@ * * @group unit/parser/schema/ */ -import { APIGatewayProxyEventV2Schema } from '../../../src/schemas/apigwv2'; -import { loadExampleEvent } from './utils'; + +import { loadExampleEvent } from './utils.js'; +import { APIGatewayProxyEventV2Schema } from '../../../src/schemas/apigwv2.js'; describe('API GW v2 ', () => { it('should parse api gateway v2 event', () => { diff --git a/packages/parser/tests/unit/schema/cloudformation-custom-resource.test.ts b/packages/parser/tests/unit/schema/cloudformation-custom-resource.test.ts index a7face9e8a..66ec61680d 100644 --- a/packages/parser/tests/unit/schema/cloudformation-custom-resource.test.ts +++ b/packages/parser/tests/unit/schema/cloudformation-custom-resource.test.ts @@ -3,12 +3,13 @@ * * @group unit/parser/schema/ */ + +import { loadExampleEvent } from './utils.js'; import { CloudFormationCustomResourceCreateSchema, CloudFormationCustomResourceUpdateSchema, CloudFormationCustomResourceDeleteSchema, -} from '../../../src/schemas/cloudformation-custom-resource'; -import { loadExampleEvent } from './utils'; +} from '../../../src/schemas/cloudformation-custom-resource.js'; describe('CloudFormationCustomResource ', () => { it('should parse create event', () => { diff --git a/packages/parser/tests/unit/schema/cloudwatch.test.ts b/packages/parser/tests/unit/schema/cloudwatch.test.ts index 2bd98a4e1b..a978030de2 100644 --- a/packages/parser/tests/unit/schema/cloudwatch.test.ts +++ b/packages/parser/tests/unit/schema/cloudwatch.test.ts @@ -3,8 +3,9 @@ * * @group unit/parser/schema/ */ -import { CloudWatchLogsSchema } from '../../../src/schemas/cloudwatch'; -import { loadExampleEvent } from './utils'; + +import { loadExampleEvent } from './utils.js'; +import { CloudWatchLogsSchema } from '../../../src/schemas/cloudwatch.js'; describe('CloudWatchLogs ', () => { it('should parse cloudwatch logs event', () => { diff --git a/packages/parser/tests/unit/schema/dynamodb.test.ts b/packages/parser/tests/unit/schema/dynamodb.test.ts index 52ae853274..b152c07b72 100644 --- a/packages/parser/tests/unit/schema/dynamodb.test.ts +++ b/packages/parser/tests/unit/schema/dynamodb.test.ts @@ -3,8 +3,9 @@ * * @group unit/parser/schema/ */ -import { DynamoDBStreamSchema } from '../../../src/schemas/dynamodb'; -import { loadExampleEvent } from './utils'; + +import { DynamoDBStreamSchema } from '../../../src/schemas/dynamodb.js'; +import { loadExampleEvent } from './utils.js'; describe('DynamoDB ', () => { const dynamoStreamEvent = loadExampleEvent('dynamoStreamEvent.json'); diff --git a/packages/parser/tests/unit/schema/eventbridge.test.ts b/packages/parser/tests/unit/schema/eventbridge.test.ts index 181a1ef6ea..e92bd2248f 100644 --- a/packages/parser/tests/unit/schema/eventbridge.test.ts +++ b/packages/parser/tests/unit/schema/eventbridge.test.ts @@ -4,8 +4,8 @@ * @group unit/parser/schema/ */ -import { EventBridgeSchema } from '../../../src/schemas/eventbridge'; -import { loadExampleEvent } from './utils'; +import { loadExampleEvent } from './utils.js'; +import { EventBridgeSchema } from '../../../src/schemas/eventbridge.js'; describe('EventBridge ', () => { it('should parse eventbridge event', () => { diff --git a/packages/parser/tests/unit/schema/kafka.test.ts b/packages/parser/tests/unit/schema/kafka.test.ts index 55826e6884..3b2bc50b83 100644 --- a/packages/parser/tests/unit/schema/kafka.test.ts +++ b/packages/parser/tests/unit/schema/kafka.test.ts @@ -3,11 +3,12 @@ * * @group unit/parser/schema/ */ + +import { loadExampleEvent } from './utils.js'; import { KafkaMskEventSchema, KafkaSelfManagedEventSchema, -} from '../../../src/schemas/kafka'; -import { loadExampleEvent } from './utils'; +} from '../../../src/schemas/kafka.js'; describe('Kafka ', () => { const expectedTestEvent = { diff --git a/packages/parser/tests/unit/schema/kinesis.test.ts b/packages/parser/tests/unit/schema/kinesis.test.ts index 14d2a86979..99fc5eebc4 100644 --- a/packages/parser/tests/unit/schema/kinesis.test.ts +++ b/packages/parser/tests/unit/schema/kinesis.test.ts @@ -3,13 +3,14 @@ * * @group unit/parser/schema/ */ -import { KinesisDataStreamSchema } from '../../../src/schemas/kinesis'; + +import { loadExampleEvent } from './utils.js'; +import { KinesisDataStreamSchema } from '../../../src/schemas/kinesis.js'; import { KinesisFirehoseSchema, KinesisFirehoseSqsSchema, -} from '../../../src/schemas/kinesis-firehose'; -import { loadExampleEvent } from './utils'; -import { extractCloudWatchLogFromEvent } from '../../../src/schemas/cloudwatch'; +} from '../../../src/schemas/kinesis-firehose.js'; +import { extractCloudWatchLogFromEvent } from '../../../src/schemas/cloudwatch.js'; describe('Kinesis ', () => { it('should parse kinesis event', () => { @@ -21,7 +22,7 @@ describe('Kinesis ', () => { ).toString('utf8'); expect(decodedData).toEqual('Hello, this is a test.'); }); - it('should prase single kinesis record', () => { + it('should parse single kinesis record', () => { const kinesisStreamEventOneRecord = loadExampleEvent( 'kinesisStreamEventOneRecord.json' ); diff --git a/packages/parser/tests/unit/schema/lambda.test.ts b/packages/parser/tests/unit/schema/lambda.test.ts index bbbf374e62..459cd8a32e 100644 --- a/packages/parser/tests/unit/schema/lambda.test.ts +++ b/packages/parser/tests/unit/schema/lambda.test.ts @@ -3,8 +3,9 @@ * * @group unit/parser/schema/ */ -import { loadExampleEvent } from './utils'; -import { LambdaFunctionUrlSchema } from '../../../src/schemas/lambda'; + +import { loadExampleEvent } from './utils.js'; +import { LambdaFunctionUrlSchema } from '../../../src/schemas/lambda.js'; describe('Lambda ', () => { it('should parse lambda event', () => { diff --git a/packages/parser/tests/unit/schema/s3.test.ts b/packages/parser/tests/unit/schema/s3.test.ts index 33703cddab..2c5378fdf7 100644 --- a/packages/parser/tests/unit/schema/s3.test.ts +++ b/packages/parser/tests/unit/schema/s3.test.ts @@ -3,13 +3,14 @@ * * @group unit/parser/schema/ */ + import { - S3Schema, S3EventNotificationEventBridgeSchema, S3SqsEventNotificationSchema, + S3Schema, S3ObjectLambdaEventSchema, -} from '../../../src/schemas/s3'; -import { loadExampleEvent } from './utils'; +} from '../../../src/schemas/s3.js'; +import { loadExampleEvent } from './utils.js'; describe('S3 ', () => { it('should parse s3 event', () => { diff --git a/packages/parser/tests/unit/schema/ses.test.ts b/packages/parser/tests/unit/schema/ses.test.ts index a284554750..eeb29f6a1b 100644 --- a/packages/parser/tests/unit/schema/ses.test.ts +++ b/packages/parser/tests/unit/schema/ses.test.ts @@ -3,8 +3,9 @@ * * @group unit/parser/schema/ */ -import { SesSchema } from '../../../src/schemas/ses'; -import { loadExampleEvent } from './utils'; + +import { loadExampleEvent } from './utils.js'; +import { SesSchema } from '../../../src/schemas/ses.js'; describe('Schema:', () => { const sesEvent = loadExampleEvent('sesEvent.json'); diff --git a/packages/parser/tests/unit/schema/sns.test.ts b/packages/parser/tests/unit/schema/sns.test.ts index d8b7acd9d0..66ec7aa297 100644 --- a/packages/parser/tests/unit/schema/sns.test.ts +++ b/packages/parser/tests/unit/schema/sns.test.ts @@ -3,8 +3,9 @@ * * @group unit/parser/schema/ */ -import { SnsSchema } from '../../../src/schemas/sns'; -import { loadExampleEvent } from './utils'; + +import { loadExampleEvent } from './utils.js'; +import { SnsSchema } from '../../../src/schemas/sns.js'; describe('Schema:', () => { const snsEvent = loadExampleEvent('snsEvent.json'); diff --git a/packages/parser/tests/unit/schema/sqs.test.ts b/packages/parser/tests/unit/schema/sqs.test.ts index f1d87fee4a..191b843298 100644 --- a/packages/parser/tests/unit/schema/sqs.test.ts +++ b/packages/parser/tests/unit/schema/sqs.test.ts @@ -3,8 +3,9 @@ * * @group unit/parser/schema/ */ -import { SqsSchema } from '../../../src/schemas/sqs'; -import { loadExampleEvent } from './utils'; + +import { loadExampleEvent } from './utils.js'; +import { SqsSchema } from '../../../src/schemas/sqs.js'; describe('SQS ', () => { const sqsEvent = loadExampleEvent('sqsEvent.json'); diff --git a/packages/parser/tests/unit/schema/vpc-lattice.test.ts b/packages/parser/tests/unit/schema/vpc-lattice.test.ts index fe1f325254..ea0a0dd4a4 100644 --- a/packages/parser/tests/unit/schema/vpc-lattice.test.ts +++ b/packages/parser/tests/unit/schema/vpc-lattice.test.ts @@ -4,8 +4,8 @@ * @group unit/parser/schema/ */ -import { VpcLatticeSchema } from '../../../src/schemas/vpc-lattice'; -import { loadExampleEvent } from './utils'; +import { loadExampleEvent } from './utils.js'; +import { VpcLatticeSchema } from '../../../src/schemas/vpc-lattice.js'; describe('VPC Lattice ', () => { it('should parse vpc lattice event', () => { diff --git a/packages/parser/tests/unit/schema/vpc-latticev2.test.ts b/packages/parser/tests/unit/schema/vpc-latticev2.test.ts index bde304c91b..da6d7d885e 100644 --- a/packages/parser/tests/unit/schema/vpc-latticev2.test.ts +++ b/packages/parser/tests/unit/schema/vpc-latticev2.test.ts @@ -4,8 +4,8 @@ * @group unit/parser/schema/ */ -import { VpcLatticeV2Schema } from '../../../src/schemas/vpc-latticev2'; -import { loadExampleEvent } from './utils'; +import { loadExampleEvent } from './utils.js'; +import { VpcLatticeV2Schema } from '../../../src/schemas/vpc-latticev2.js'; describe('VpcLatticeV2 ', () => { it('should parse VpcLatticeV2 event', () => { From e330e51c07ef1e9652b49165984ae2769bb7d7e9 Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Fri, 17 Nov 2023 21:00:50 +0100 Subject: [PATCH 47/48] moved comment, fixed path --- packages/parser/src/schemas/lambda.ts | 19 ++++++++++--------- packages/parser/tests/unit/schema/utils.ts | 2 +- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/packages/parser/src/schemas/lambda.ts b/packages/parser/src/schemas/lambda.ts index 65b746b4f2..e8e72be255 100644 --- a/packages/parser/src/schemas/lambda.ts +++ b/packages/parser/src/schemas/lambda.ts @@ -1,13 +1,14 @@ import { APIGatewayProxyEventV2Schema } from './apigwv2.js'; -const LambdaFunctionUrlSchema = APIGatewayProxyEventV2Schema.extend({ - // Lambda Function URL follows the API Gateway HTTP APIs Payload Format Version 2.0. - // - // Keys related to API Gateway features not available in Function URL use a sentinel value (e.g.`routeKey`, `stage`). - // - // Documentation: - // - https://docs.aws.amazon.com/lambda/latest/dg/urls-configuration.html - // - https://docs.aws.amazon.com/lambda/latest/dg/urls-invocation.html#urls-payloads -}); +/** + * Lambda Function URL follows the API Gateway HTTP APIs Payload Format Version 2.0. + * + * Keys related to API Gateway features not available in Function URL use a sentinel value (e.g.`routeKey`, `stage`). + * Documentation: + * - https://docs.aws.amazon.com/lambda/latest/dg/urls-configuration.html + * - https://docs.aws.amazon.com/lambda/latest/dg/urls-invocation.html#urls-payloads + * + */ +const LambdaFunctionUrlSchema = APIGatewayProxyEventV2Schema.extend({}); export { LambdaFunctionUrlSchema }; diff --git a/packages/parser/tests/unit/schema/utils.ts b/packages/parser/tests/unit/schema/utils.ts index 0d33dfba38..8101dfefdb 100644 --- a/packages/parser/tests/unit/schema/utils.ts +++ b/packages/parser/tests/unit/schema/utils.ts @@ -1,7 +1,7 @@ import { readFileSync } from 'node:fs'; export const loadExampleEvent = (fileName: string): unknown => { - const event = readFileSync(`tests/events/${fileName}`, 'utf8'); + const event = readFileSync(`./tests/events/${fileName}`, 'utf8'); return JSON.parse(event); }; From 8ce4af60af96e2e841f6ef9e70a0f83d981873f5 Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Mon, 20 Nov 2023 11:12:03 +0100 Subject: [PATCH 48/48] rename event filename to fix events --- ...ateEvent.json => cloudFormationCustomResourceCreateEvent.json} | 0 ...eteEvent.json => cloudFormationCustomResourceDeleteEvent.json} | 0 ...ateEvent.json => cloudFormationCustomResourceUpdateEvent.json} | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename packages/parser/tests/events/{cloudformationCustomResourceCreateEvent.json => cloudFormationCustomResourceCreateEvent.json} (100%) rename packages/parser/tests/events/{cloudformationCustomResourceDeleteEvent.json => cloudFormationCustomResourceDeleteEvent.json} (100%) rename packages/parser/tests/events/{cloudformationCustomResourceUpdateEvent.json => cloudFormationCustomResourceUpdateEvent.json} (100%) diff --git a/packages/parser/tests/events/cloudformationCustomResourceCreateEvent.json b/packages/parser/tests/events/cloudFormationCustomResourceCreateEvent.json similarity index 100% rename from packages/parser/tests/events/cloudformationCustomResourceCreateEvent.json rename to packages/parser/tests/events/cloudFormationCustomResourceCreateEvent.json diff --git a/packages/parser/tests/events/cloudformationCustomResourceDeleteEvent.json b/packages/parser/tests/events/cloudFormationCustomResourceDeleteEvent.json similarity index 100% rename from packages/parser/tests/events/cloudformationCustomResourceDeleteEvent.json rename to packages/parser/tests/events/cloudFormationCustomResourceDeleteEvent.json diff --git a/packages/parser/tests/events/cloudformationCustomResourceUpdateEvent.json b/packages/parser/tests/events/cloudFormationCustomResourceUpdateEvent.json similarity index 100% rename from packages/parser/tests/events/cloudformationCustomResourceUpdateEvent.json rename to packages/parser/tests/events/cloudFormationCustomResourceUpdateEvent.json