Skip to content

Commit

Permalink
feat(parser): add built-in schemas (#1788)
Browse files Browse the repository at this point in the history
* add dynamodb schema

* add alb

* add parser to v2 build

* fix test

* add alb

* add built-in schema

* add more tests for schemas

* remove index export

* add cloudwatch with base64 zlip transform

* add throw test case

* formatting

* add kafka schema

* restructured tests

* add vpc lattice and lattice v2

* s3 event notification should extend eventbridge

* s3 sqs should extend from sqs

* simplify cloudwatch extract from string

* keep message as string, instead of empty object

* fix detail type of eb and field names

* remove duplicated entries

* fix homepage URL in readme

* improved test coverage

* key and value are always present

* cleanup unnecessary definitions, widen peerDep version req

* Update packages/parser/src/schemas/cloudwatch.ts

Co-authored-by: Andrea Amorosi <dreamorosi@gmail.com>

* clean up events, some fields are imaginary

* fix api gw

* fix broken IP addresses in examples

* add more tests to api gw

* fix apigw2 add more tests

* add optional scopes to apigwv2

* add optional field back to api gw, stricter methods for vpc lattice

* add test for messageId refinement

* remove redundant entry

* fix sqs

* add dmarcPolicy for ses

* added tests

* moved cw function from kinesis, fix imports

* add parser to build step in ci

* use any safely here

* removed console logs

* name, add datetime to strings

* narrow string to datetime

* refine to url

* imports, remove try/catch

* add .js extension to imports

* moved comment, fixed path

* rename event filename to fix events

---------

Co-authored-by: Andrea Amorosi <dreamorosi@gmail.com>
  • Loading branch information
am29d and dreamorosi authored Nov 20, 2023
1 parent f54e1b5 commit 20cde95
Show file tree
Hide file tree
Showing 137 changed files with 4,951 additions and 27 deletions.
1 change: 1 addition & 0 deletions .github/actions/cached-node-modules/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
3 changes: 1 addition & 2 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
src
tests
jest.config.js
jest.config.cjs
tsconfig.json
.vscode
.github
Expand All @@ -13,7 +13,6 @@ coverage
tslint.json
tsconfig.json
MakeFile
jest.config.js
.npmignore
.eslintignore
.huskyrc.js
Expand Down
2 changes: 1 addition & 1 deletion docs/snippets/idempotency/samples/makeIdempotentJmes.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,4 @@
},
"body": "{\"user\":\"xyz\",\"productId\":\"123456789\"}",
"isBase64Encoded": false
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@
"name": "foo",
"productId": 10000
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@
"name": "Foo"
},
"productId": 10000
}
}
2 changes: 1 addition & 1 deletion docs/snippets/idempotency/samples/workingWithBatch.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@
"awsRegion": "us-east-2"
}
]
}
}
22 changes: 22 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,20 @@ module.exports = {
},
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/**'],
testMatch: ['**/?(*.)+(spec|test).ts'],
roots: ['<rootDir>/src', '<rootDir>/tests'],
testPathIgnorePatterns: ['/node_modules/'],
testEnvironment: 'node',
coveragePathIgnorePatterns: ['/node_modules/', '/types/'],
coveragePathIgnorePatterns: ['/node_modules/', '/types'],
coverageThreshold: {
global: {
statements: 100,
Expand All @@ -24,5 +28,4 @@ module.exports = {
},
},
coverageReporters: ['json-summary', 'text', 'lcov'],
setupFiles: ['<rootDir>/tests/helpers/populateEnvironmentVariables.ts'],
};
46 changes: 31 additions & 15 deletions packages/parser/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,45 @@
"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",
"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": {
"name": "Amazon Web Services",
"url": "https://aws.amazon.com"
},
"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",
"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"
}
}
},
"main": "./lib/cjs/index.js",
"types": "./lib/cjs/index.d.ts",
"files": [
"lib"
],
Expand All @@ -42,10 +60,8 @@
"serverless",
"nodejs"
],
"publishConfig": {
"access": "restricted"
},
"devDependencies": {
"zod": "^3.22.2"

"peerDependencies": {
"zod": ">=3.x"
}
}
}
File renamed without changes.
22 changes: 22 additions & 0 deletions packages/parser/src/schemas/alb.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
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()).optional(),
queryStringParameters: z.record(z.string(), z.string()).optional(),
requestContext: z.object({
elb: z.object({
targetGroupArn: z.string(),
}),
}),
});

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 };
110 changes: 110 additions & 0 deletions packages/parser/src/schemas/apigw.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
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 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().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.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([
'GET',
'POST',
'PUT',
'PATCH',
'DELETE',
'HEAD',
'OPTIONS',
]),
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(),
stageVariables: z.record(z.string()).optional().nullish(),
isBase64Encoded: z.boolean().optional(),
body: z.string().optional(),
});

export { APIGatewayProxyEventSchema, APIGatewayCert };
Loading

0 comments on commit 20cde95

Please sign in to comment.