From e0ca92c667bfbcc3978343227330337828ab8370 Mon Sep 17 00:00:00 2001 From: Michael Kaiser Date: Mon, 24 Mar 2025 16:14:24 -0500 Subject: [PATCH 1/7] Update package version --- .../amazon-mq-rabbitmq-lambda/package.json | 10 +++--- typescript/amplify-console-app/package.json | 8 ++--- .../lambdas/package.json | 2 +- .../package.json | 8 ++--- .../package.json | 8 ++--- .../package.json | 16 ++++----- .../package.json | 12 +++---- .../package.json | 8 ++--- .../application-load-balancer/package.json | 8 ++--- .../appsync-graphql-dynamodb/package.json | 14 ++++---- .../appsync-graphql-eventbridge/package.json | 10 +++--- typescript/appsync-graphql-http/package.json | 10 +++--- .../package.json | 12 +++---- .../resolvers/package.json | 10 +++--- typescript/aspects/package.json | 14 ++++---- .../aws-codepipeline-ecs-lambda/package.json | 8 ++--- .../aws-transfer-sftp-server/package.json | 16 ++++----- typescript/backup-s3/package.json | 16 ++++----- typescript/bedrock-kb-agent/package.json | 33 ++++++++----------- typescript/cdkpipeline-ecs/package.json | 12 +++---- typescript/classic-load-balancer/package.json | 8 ++--- typescript/cloudfront-functions/package.json | 14 ++++---- .../local-image/package.json | 4 +-- .../package.json | 8 ++--- .../package.json | 10 +++--- .../codepipeline-build-deploy/package.json | 16 ++++----- .../codepipeline-glue-deploy/package.json | 10 +++--- .../codewhisperer-cloudwatch/package.json | 14 ++++---- typescript/cognito-api-lambda/package.json | 8 ++--- typescript/connect-cdk/package.json | 12 +++---- typescript/custom-logical-names/package.json | 8 ++--- .../custom-resource-provider/package.json | 16 ++++----- typescript/custom-resource/package.json | 8 ++--- typescript/ddb-stream-lambda-sns/package.json | 10 +++--- .../ddb/global-table-with-cmk/package.json | 16 ++++----- .../package.json | 14 ++++---- typescript/ec2-instance/package.json | 18 +++++----- typescript/ec2-ssm-local-zone/package.json | 16 ++++----- typescript/ecs/cluster/package.json | 8 ++--- .../cross-stack-load-balancer/package.json | 8 ++--- .../package.json | 8 ++--- .../package.json | 8 ++--- .../ecs/ecs-service-with-logging/package.json | 8 ++--- .../package.json | 8 ++--- .../package.json | 8 ++--- .../package.json | 8 ++--- .../package.json | 8 ++--- .../ecs/fargate-service-with-efs/package.json | 8 ++--- .../package.json | 8 ++--- .../fargate-service-with-logging/package.json | 8 ++--- typescript/eks/cluster/package.json | 10 +++--- .../elasticbeanstalk-bg-pipeline/package.json | 8 ++--- .../elasticbeanstalk-environment/package.json | 8 ++--- typescript/eventbridge-lambda/package.json | 12 +++---- typescript/fsx-ad/package.json | 8 ++--- typescript/http-proxy-apigateway/package.json | 8 ++--- typescript/imagebuilder/package.json | 14 ++++---- typescript/inspector2/package.json | 16 ++++----- typescript/lambda-api-ci/package.json | 10 +++--- typescript/lambda-api-ci/src/package.json | 6 ++-- .../lambda-cloudwatch-dashboard/package.json | 16 ++++----- typescript/lambda-cron/package.json | 12 +++---- typescript/lambda-layer/package.json | 10 +++--- .../package.json | 10 +++--- .../package.json | 15 ++++----- typescript/lexbot/package.json | 14 ++++---- typescript/my-widget-service/package.json | 8 ++--- typescript/neptune-with-vpc/package.json | 2 +- .../opensearch/cwlogs_ingestion/package.json | 16 ++++----- .../opensearch/os_vpc_provision/package.json | 16 ++++----- typescript/quicksight/package.json | 12 +++---- typescript/r53-resolver/package.json | 12 +++---- typescript/rds/aurora/package.json | 12 +++---- typescript/rds/mysql/package.json | 16 ++++----- typescript/rds/oracle/package.json | 12 +++---- .../package.json | 12 +++---- typescript/resource-overrides/package.json | 8 ++--- .../package.json | 8 ++--- .../package.json | 16 ++++----- typescript/s3-object-lambda/package.json | 12 +++---- typescript/s3-sns-lambda-chain/package.json | 18 +++++----- .../secrets-manager-rotation/package.json | 18 +++++----- .../portfolio-with-ec2-product/package.json | 16 ++++----- typescript/static-site-basic/package.json | 8 ++--- typescript/static-site/package.json | 8 ++--- .../package.json | 8 ++--- .../stepfunctions-job-poller/package.json | 8 ++--- typescript/waf/package.json | 10 +++--- 88 files changed, 483 insertions(+), 491 deletions(-) diff --git a/typescript/amazon-mq-rabbitmq-lambda/package.json b/typescript/amazon-mq-rabbitmq-lambda/package.json index 75379da8ec..d9b7741a6b 100644 --- a/typescript/amazon-mq-rabbitmq-lambda/package.json +++ b/typescript/amazon-mq-rabbitmq-lambda/package.json @@ -11,17 +11,17 @@ "cdk": "cdk" }, "devDependencies": { - "@types/jest": "^29.5.12", - "@types/node": "22.5.4", - "aws-cdk": "2.160.0", + "@types/jest": "^29.5.14", + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", "jest": "^29.7.0", "ts-jest": "^29.2.5", "ts-node": "^10.9.2", - "typescript": "~5.6.2" + "typescript": "~5.6.3" }, "dependencies": { "@cdklabs/cdk-amazonmq": "^0.0.1", - "aws-cdk-lib": "2.160.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0" } } diff --git a/typescript/amplify-console-app/package.json b/typescript/amplify-console-app/package.json index 079e25b40d..54d653c109 100644 --- a/typescript/amplify-console-app/package.json +++ b/typescript/amplify-console-app/package.json @@ -14,12 +14,12 @@ }, "license": "Apache-2.0", "devDependencies": { - "@types/node": "^8.10.38", - "aws-cdk": "*", - "typescript": "~5.1.6" + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "^2.0.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0" } } diff --git a/typescript/api-cors-lambda-crud-dynamodb/lambdas/package.json b/typescript/api-cors-lambda-crud-dynamodb/lambdas/package.json index be979d03ee..48ba4b28e6 100644 --- a/typescript/api-cors-lambda-crud-dynamodb/lambdas/package.json +++ b/typescript/api-cors-lambda-crud-dynamodb/lambdas/package.json @@ -5,7 +5,7 @@ "private": true, "license": "Apache-2.0", "devDependencies": { - "@types/node": "*", + "@types/node": "22.7.9", "@types/uuid": "*" }, "dependencies": { diff --git a/typescript/api-cors-lambda-crud-dynamodb/package.json b/typescript/api-cors-lambda-crud-dynamodb/package.json index 5eb01180c4..9a21e6edda 100644 --- a/typescript/api-cors-lambda-crud-dynamodb/package.json +++ b/typescript/api-cors-lambda-crud-dynamodb/package.json @@ -15,13 +15,13 @@ }, "license": "Apache-2.0", "devDependencies": { - "@types/node": "*", - "aws-cdk": "*", + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", "esbuild": "*", - "typescript": "~5.1.6" + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "^2.0.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0" } } diff --git a/typescript/api-gateway-async-lambda-invocation/package.json b/typescript/api-gateway-async-lambda-invocation/package.json index ea1fcf4f12..93fe31608d 100644 --- a/typescript/api-gateway-async-lambda-invocation/package.json +++ b/typescript/api-gateway-async-lambda-invocation/package.json @@ -10,13 +10,13 @@ "cdk": "cdk" }, "devDependencies": { - "@types/node": "22.5.4", - "aws-cdk": "2.163.0", + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", "ts-node": "^10.9.2", - "typescript": "~5.6.2" + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "2.163.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0", "source-map-support": "^0.5.21" } diff --git a/typescript/api-gateway-lambda-token-authorizer/package.json b/typescript/api-gateway-lambda-token-authorizer/package.json index 25a23241d2..1674e6e5ef 100644 --- a/typescript/api-gateway-lambda-token-authorizer/package.json +++ b/typescript/api-gateway-lambda-token-authorizer/package.json @@ -13,18 +13,18 @@ "cdk": "cdk" }, "devDependencies": { - "@types/jest": "^29.5.4", - "@types/node": "20.5.9", - "aws-cdk": "2.96.2", - "jest": "^29.6.4", - "ts-jest": "^29.1.1", - "ts-node": "^10.9.1", - "typescript": "~5.2.2", + "@types/jest": "^29.5.14", + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", + "jest": "^29.7.0", + "ts-jest": "^29.2.5", + "ts-node": "^10.9.2", + "typescript": "~5.6.3", "esbuild": "^0.19.4" }, "dependencies": { "@types/aws-lambda": "^8.10.121", - "aws-cdk-lib": "2.177.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0", "source-map-support": "^0.5.21" }, diff --git a/typescript/api-gateway-parallel-step-functions/package.json b/typescript/api-gateway-parallel-step-functions/package.json index 34d1403737..660fe08d47 100644 --- a/typescript/api-gateway-parallel-step-functions/package.json +++ b/typescript/api-gateway-parallel-step-functions/package.json @@ -18,14 +18,14 @@ "cdk": "cdk" }, "devDependencies": { - "@types/node": "20.5.7", - "aws-cdk": "2.93.0", - "ts-node": "^10.9.1", - "typescript": "^5.2.2" + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", + "ts-node": "^10.9.2", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "2.177.0", - "constructs": "^10.2.70", + "aws-cdk-lib": "2.185.0", + "constructs": "^10.0.0", "source-map-support": "^0.5.21" } } diff --git a/typescript/api-websocket-lambda-dynamodb/package.json b/typescript/api-websocket-lambda-dynamodb/package.json index 73a1e8f180..54033a7c27 100644 --- a/typescript/api-websocket-lambda-dynamodb/package.json +++ b/typescript/api-websocket-lambda-dynamodb/package.json @@ -15,12 +15,12 @@ }, "license": "Apache-2.0", "devDependencies": { - "@types/node": "^10.17.0", - "aws-cdk": "*", - "typescript": "~5.1.6" + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "^2.0.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0" } } diff --git a/typescript/application-load-balancer/package.json b/typescript/application-load-balancer/package.json index f43fa0e87b..a2e717adbb 100644 --- a/typescript/application-load-balancer/package.json +++ b/typescript/application-load-balancer/package.json @@ -15,12 +15,12 @@ }, "license": "Apache-2.0", "devDependencies": { - "@types/node": "^10.17.0", - "aws-cdk": "*", - "typescript": "~5.1.6" + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "^2.0.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0" } } diff --git a/typescript/appsync-graphql-dynamodb/package.json b/typescript/appsync-graphql-dynamodb/package.json index 18ecbfeaf9..34494a7e88 100644 --- a/typescript/appsync-graphql-dynamodb/package.json +++ b/typescript/appsync-graphql-dynamodb/package.json @@ -11,17 +11,17 @@ "push-data": "node utils/index.js" }, "devDependencies": { - "@types/jest": "^29.5.5", - "@types/node": "20.6.3", - "aws-cdk": "2.99.1", + "@types/jest": "^29.5.14", + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", "jest": "^29.7.0", - "ts-jest": "^29.1.1", - "ts-node": "^10.9.1", - "typescript": "~5.2.2" + "ts-jest": "^29.2.5", + "ts-node": "^10.9.2", + "typescript": "~5.6.3" }, "dependencies": { "@aws-sdk/client-dynamodb": "^3.535.0", - "aws-cdk-lib": "2.99.1", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0", "source-map-support": "^0.5.21" } diff --git a/typescript/appsync-graphql-eventbridge/package.json b/typescript/appsync-graphql-eventbridge/package.json index fa9ee586f8..766dc439ab 100644 --- a/typescript/appsync-graphql-eventbridge/package.json +++ b/typescript/appsync-graphql-eventbridge/package.json @@ -13,13 +13,13 @@ }, "license": "Apache-2.0", "devDependencies": { - "@types/node": "10.17.0", - "aws-cdk": "*", - "typescript": "~5.1.6", - "ts-node": "^8.1.0" + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", + "typescript": "~5.6.3", + "ts-node": "^10.9.2" }, "dependencies": { - "aws-cdk-lib": "^2.0.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0", "source-map-support": "^0.5.9" } diff --git a/typescript/appsync-graphql-http/package.json b/typescript/appsync-graphql-http/package.json index 887f193cac..fd574aae4c 100644 --- a/typescript/appsync-graphql-http/package.json +++ b/typescript/appsync-graphql-http/package.json @@ -16,12 +16,12 @@ "license": "Apache-2.0", "devDependencies": { "@aws-appsync/utils": "^1.5.0", - "@types/node": "^10.17.0", - "aws-cdk": "*", - "typescript": "~5.2.2" + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "^2.103.1", - "constructs": "^10.3.0" + "aws-cdk-lib": "2.185.0", + "constructs": "^10.0.0" } } diff --git a/typescript/appsync-graphql-typescript-resolver/package.json b/typescript/appsync-graphql-typescript-resolver/package.json index 6ddd32f059..b200fad910 100644 --- a/typescript/appsync-graphql-typescript-resolver/package.json +++ b/typescript/appsync-graphql-typescript-resolver/package.json @@ -14,16 +14,16 @@ }, "devDependencies": { "@aws-appsync/utils": "^1.2.5", - "@types/jest": "^29.5.12", - "@types/node": "20.11.19", + "@types/jest": "^29.5.14", + "@types/node": "22.7.9", "jest": "^29.7.0", - "ts-jest": "^29.1.2", - "aws-cdk": "2.133.0", + "ts-jest": "^29.2.5", + "aws-cdk": "2.1004.0", "ts-node": "^10.9.2", - "typescript": "~5.3.3" + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "2.133.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0", "source-map-support": "^0.5.21" } diff --git a/typescript/appsync-graphql-typescript-resolver/resolvers/package.json b/typescript/appsync-graphql-typescript-resolver/resolvers/package.json index 8c0801d552..e1a5e8fa08 100644 --- a/typescript/appsync-graphql-typescript-resolver/resolvers/package.json +++ b/typescript/appsync-graphql-typescript-resolver/resolvers/package.json @@ -15,14 +15,14 @@ "devDependencies": { "@aws-appsync/eslint-plugin": "^1.2.1", "@aws-appsync/utils": "^1.2.5", - "@types/jest": "^29.5.2", + "@types/jest": "^29.5.14", "@typescript-eslint/eslint-plugin": "^5.60.0", "@typescript-eslint/parser": "^5.60.0", "esbuild": "^0.18.6", "eslint": "^8.43.0", - "jest": "^29.5.0", - "ts-jest": "^29.1.0", - "ts-node": "^10.9.1", - "typescript": "^4.9.5" + "jest": "^29.7.0", + "ts-jest": "^29.2.5", + "ts-node": "^10.9.2", + "typescript": "~5.6.3" } } diff --git a/typescript/aspects/package.json b/typescript/aspects/package.json index 855fce811a..e08bf72808 100644 --- a/typescript/aspects/package.json +++ b/typescript/aspects/package.json @@ -12,22 +12,22 @@ "cdk": "cdk" }, "devDependencies": { - "@types/jest": "^29.5.8", - "@types/node": "20.9.0", + "@types/jest": "^29.5.14", + "@types/node": "22.7.9", "@typescript-eslint/eslint-plugin": "^6.11.0", - "aws-cdk": "2.106.1", + "aws-cdk": "2.1004.0", "eslint": "^8.54.0", "eslint-config-standard-with-typescript": "^40.0.0", "eslint-plugin-import": "^2.29.0", "eslint-plugin-n": "^16.3.1", "eslint-plugin-promise": "^6.1.1", "jest": "^29.7.0", - "ts-jest": "^29.1.1", - "ts-node": "^10.9.1", - "typescript": "~5.2.2" + "ts-jest": "^29.2.5", + "ts-node": "^10.9.2", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "2.106.1", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0", "source-map-support": "^0.5.21" } diff --git a/typescript/aws-codepipeline-ecs-lambda/package.json b/typescript/aws-codepipeline-ecs-lambda/package.json index f5353766df..02255cd3a7 100644 --- a/typescript/aws-codepipeline-ecs-lambda/package.json +++ b/typescript/aws-codepipeline-ecs-lambda/package.json @@ -11,13 +11,13 @@ }, "devDependencies": { "@types/aws-lambda": "^8.10.140", - "@types/node": "20.14.2", - "aws-cdk": "2.162.1", + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", "ts-node": "^10.9.2", - "typescript": "~5.4.5" + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "2.162.1", + "aws-cdk-lib": "2.185.0", "@types/aws-lambda": "^8.10.140", "constructs": "^10.0.0", "source-map-support": "^0.5.21" diff --git a/typescript/aws-transfer-sftp-server/package.json b/typescript/aws-transfer-sftp-server/package.json index 29c0033459..94c4a3ee79 100644 --- a/typescript/aws-transfer-sftp-server/package.json +++ b/typescript/aws-transfer-sftp-server/package.json @@ -19,16 +19,16 @@ "cdk": "cdk" }, "devDependencies": { - "@types/jest": "^29.5.2", - "@types/node": "18.15.11", - "aws-cdk": "*", - "jest": "^29.5.0", - "ts-jest": "^29.1.0", - "ts-node": "^10.9.1", - "typescript": "~5.1.6" + "@types/jest": "^29.5.14", + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", + "jest": "^29.7.0", + "ts-jest": "^29.2.5", + "ts-node": "^10.9.2", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "^2.0.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0" } } diff --git a/typescript/backup-s3/package.json b/typescript/backup-s3/package.json index f51898e68e..74caa81be5 100644 --- a/typescript/backup-s3/package.json +++ b/typescript/backup-s3/package.json @@ -10,16 +10,16 @@ "cdk": "cdk" }, "devDependencies": { - "@types/jest": "^26.0.10", - "@types/node": "10.17.27", - "jest": "^26.4.2", - "ts-jest": "^26.2.0", - "aws-cdk": "2.80.0", - "ts-node": "^9.0.0", - "typescript": "~4.6.0" + "@types/jest": "^29.5.14", + "@types/node": "22.7.9", + "jest": "^29.7.0", + "ts-jest": "^29.2.5", + "aws-cdk": "2.1004.0", + "ts-node": "^10.9.2", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "2.80.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0", "source-map-support": "^0.5.16" } diff --git a/typescript/bedrock-kb-agent/package.json b/typescript/bedrock-kb-agent/package.json index bddbf1c961..288ca52f89 100644 --- a/typescript/bedrock-kb-agent/package.json +++ b/typescript/bedrock-kb-agent/package.json @@ -13,22 +13,9 @@ "devDependencies": { "@types/jest": "^29.5.14", "@types/node": "22.7.9", - "jest": "^29.7.0", - "ts-jest": "^29.2.5", - "aws-cdk": "2.173.2", - "ts-node": "^10.9.2", - "typescript": "~5.6.3" - }, - "dependencies": { - "aws-cdk-lib": "2.173.2", - "constructs": "^10.0.0" - }, - "devDependencies": { - "@types/jest": "^29.5.11", - "@types/node": "20.10.4", "@typescript-eslint/eslint-plugin": "^7.0.0", "@typescript-eslint/parser": "^7.0.0", - "aws-cdk": "^2.173.2", + "aws-cdk": "2.1004.0", "aws-cdk-lib": "^2.173.2", "aws-sdk": "^2.1518.0", "cdk-nag": "^2.27.216", @@ -41,17 +28,23 @@ "jest": "^29.7.0", "source-map-support": "^0.5.16", "ts-node": "^10.9.2", - "typescript": "~4.9.4", + "typescript": "~5.6.3", "@aws-cdk/aws-lambda-python-alpha": "^2.114.1-alpha.0", "@cdklabs/generative-ai-cdk-constructs": "^0.1.278", - "jest": "^29.0.0", - "@types/jest": "^29.0.0", - "ts-jest": "^29.0.0" + "ts-jest": "^29.2.5" + }, + "dependencies": { + "aws-cdk-lib": "2.185.0", + "constructs": "^10.0.0" }, "jest": { "testEnvironment": "node", - "roots": ["/test"], - "testMatch": ["**/*.test.ts"], + "roots": [ + "/test" + ], + "testMatch": [ + "**/*.test.ts" + ], "transform": { "^.+\\.tsx?$": "ts-jest" } diff --git a/typescript/cdkpipeline-ecs/package.json b/typescript/cdkpipeline-ecs/package.json index 76adf362fc..5ac127f793 100644 --- a/typescript/cdkpipeline-ecs/package.json +++ b/typescript/cdkpipeline-ecs/package.json @@ -10,16 +10,16 @@ "cdk": "cdk" }, "devDependencies": { - "@types/jest": "^29.5.12", - "@types/node": "20.12.7", + "@types/jest": "^29.5.14", + "@types/node": "22.7.9", "jest": "^29.7.0", - "ts-jest": "^29.1.2", - "aws-cdk": "2.148.1", + "ts-jest": "^29.2.5", + "aws-cdk": "2.1004.0", "ts-node": "^10.9.2", - "typescript": "~5.4.5" + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "2.143.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0", "source-map-support": "^0.5.21" } diff --git a/typescript/classic-load-balancer/package.json b/typescript/classic-load-balancer/package.json index 6ad58ec599..a31a32f065 100644 --- a/typescript/classic-load-balancer/package.json +++ b/typescript/classic-load-balancer/package.json @@ -15,12 +15,12 @@ }, "license": "Apache-2.0", "devDependencies": { - "@types/node": "^10.17.0", - "aws-cdk": "*", - "typescript": "~5.1.6" + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "^2.0.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0" } } diff --git a/typescript/cloudfront-functions/package.json b/typescript/cloudfront-functions/package.json index 180eee5ab6..306f0023d3 100644 --- a/typescript/cloudfront-functions/package.json +++ b/typescript/cloudfront-functions/package.json @@ -11,17 +11,17 @@ "cdk": "cdk" }, "devDependencies": { - "@types/jest": "^29.5.11", - "@types/node": "20.11.6", + "@types/jest": "^29.5.14", + "@types/node": "22.7.9", "jest": "^29.7.0", - "ts-jest": "^29.1.2", - "aws-cdk": "2.123.0", + "ts-jest": "^29.2.5", + "aws-cdk": "2.1004.0", "ts-node": "^10.9.2", - "typescript": "~5.3.3" + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "2.123.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0", "source-map-support": "^0.5.21" } -} \ No newline at end of file +} diff --git a/typescript/cloudwatch/evidently-client-side-evaluation-ecs/local-image/package.json b/typescript/cloudwatch/evidently-client-side-evaluation-ecs/local-image/package.json index 5da92025e1..1373037e17 100644 --- a/typescript/cloudwatch/evidently-client-side-evaluation-ecs/local-image/package.json +++ b/typescript/cloudwatch/evidently-client-side-evaluation-ecs/local-image/package.json @@ -14,7 +14,7 @@ }, "devDependencies": { "@types/express": "^4.17.15", - "@types/node": "^10.17.0", - "typescript": "~5.1.6" + "@types/node": "22.7.9", + "typescript": "~5.6.3" } } diff --git a/typescript/cloudwatch/evidently-client-side-evaluation-ecs/package.json b/typescript/cloudwatch/evidently-client-side-evaluation-ecs/package.json index 8a55b935e1..a7e98f5585 100644 --- a/typescript/cloudwatch/evidently-client-side-evaluation-ecs/package.json +++ b/typescript/cloudwatch/evidently-client-side-evaluation-ecs/package.json @@ -12,13 +12,13 @@ "license": "Apache-2.0", "devDependencies": { "@types/express": "^4.17.15", - "@types/node": "^8.10.38", - "aws-cdk": "*", - "typescript": "~5.1.6" + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", + "typescript": "~5.6.3" }, "dependencies": { "@aws-sdk/client-evidently": "^3.245.0", - "aws-cdk-lib": "^2.0.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0", "express": "^4.17.1" } diff --git a/typescript/cloudwatch/evidently-client-side-evaluation-lambda/package.json b/typescript/cloudwatch/evidently-client-side-evaluation-lambda/package.json index b7b6349e75..b4eba4a708 100644 --- a/typescript/cloudwatch/evidently-client-side-evaluation-lambda/package.json +++ b/typescript/cloudwatch/evidently-client-side-evaluation-lambda/package.json @@ -15,12 +15,12 @@ }, "license": "Apache-2.0", "devDependencies": { - "@types/node": "^20.5.7", - "aws-cdk": "^2.93.0", - "typescript": "~5.2.2" + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "^2.93.0", - "constructs": "^10.2.70" + "aws-cdk-lib": "2.185.0", + "constructs": "^10.0.0" } } diff --git a/typescript/codepipeline-build-deploy/package.json b/typescript/codepipeline-build-deploy/package.json index 7553b34fc2..9793f5c335 100644 --- a/typescript/codepipeline-build-deploy/package.json +++ b/typescript/codepipeline-build-deploy/package.json @@ -11,16 +11,16 @@ "cdk": "cdk" }, "devDependencies": { - "@types/jest": "^29.4.0", - "@types/node": "18.14.6", - "aws-cdk": "2.72.1", - "jest": "^29.5.0", - "ts-jest": "^29.0.5", - "ts-node": "^10.9.1", - "typescript": "~5.1.6" + "@types/jest": "^29.5.14", + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", + "jest": "^29.7.0", + "ts-jest": "^29.2.5", + "ts-node": "^10.9.2", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "2.177.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0", "jest-junit": "^16.0.0", "source-map-support": "^0.5.21" diff --git a/typescript/codepipeline-glue-deploy/package.json b/typescript/codepipeline-glue-deploy/package.json index 37c6b6e60e..25b1182516 100644 --- a/typescript/codepipeline-glue-deploy/package.json +++ b/typescript/codepipeline-glue-deploy/package.json @@ -10,13 +10,13 @@ "cdk": "cdk" }, "devDependencies": { - "@types/node": "20.4.5", - "aws-cdk": "^2.130.0", - "ts-node": "^10.9.1", - "typescript": "~5.1.6" + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", + "ts-node": "^10.9.2", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "^2.130.0", + "aws-cdk-lib": "2.185.0", "cdk": "^2.130.0", "constructs": "^10.0.0", "source-map-support": "^0.5.21" diff --git a/typescript/codewhisperer-cloudwatch/package.json b/typescript/codewhisperer-cloudwatch/package.json index 10babf680c..ad1604a320 100644 --- a/typescript/codewhisperer-cloudwatch/package.json +++ b/typescript/codewhisperer-cloudwatch/package.json @@ -11,16 +11,16 @@ "cdk": "cdk" }, "devDependencies": { - "@types/jest": "^29.5.5", - "@types/node": "20.7.1", + "@types/jest": "^29.5.14", + "@types/node": "22.7.9", "jest": "^29.7.0", - "ts-jest": "^29.1.1", - "aws-cdk": "2.102.0", - "ts-node": "^10.9.1", - "typescript": "~5.2.2" + "ts-jest": "^29.2.5", + "aws-cdk": "2.1004.0", + "ts-node": "^10.9.2", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "2.102.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0", "source-map-support": "^0.5.21" } diff --git a/typescript/cognito-api-lambda/package.json b/typescript/cognito-api-lambda/package.json index 1396309b38..07628b8692 100644 --- a/typescript/cognito-api-lambda/package.json +++ b/typescript/cognito-api-lambda/package.json @@ -13,12 +13,12 @@ }, "license": "Apache-2.0", "devDependencies": { - "@types/node": "^10.17.0", - "aws-cdk": "*", - "typescript": "~5.1.6" + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "^2.0.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0" } } diff --git a/typescript/connect-cdk/package.json b/typescript/connect-cdk/package.json index 27da02d6c1..fa495b0705 100644 --- a/typescript/connect-cdk/package.json +++ b/typescript/connect-cdk/package.json @@ -11,16 +11,16 @@ "cdk": "cdk" }, "devDependencies": { - "@types/jest": "^29.5.12", - "@types/node": "20.14.9", - "aws-cdk": "2.157.0", + "@types/jest": "^29.5.14", + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", "jest": "^29.7.0", - "ts-jest": "^29.1.5", + "ts-jest": "^29.2.5", "ts-node": "^10.9.2", - "typescript": "~5.5.3" + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "2.157.0", + "aws-cdk-lib": "2.185.0", "cdk-nag": "^2.30.0", "constructs": "^10.0.0", "source-map-support": "^0.5.21" diff --git a/typescript/custom-logical-names/package.json b/typescript/custom-logical-names/package.json index 892f46fcc0..188945ff57 100644 --- a/typescript/custom-logical-names/package.json +++ b/typescript/custom-logical-names/package.json @@ -10,12 +10,12 @@ "cdk": "cdk" }, "devDependencies": { - "aws-cdk": "*", - "ts-node": "^8.1.0", - "typescript": "~5.1.6" + "aws-cdk": "2.1004.0", + "ts-node": "^10.9.2", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "^2.0.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0", "source-map-support": "^0.5.9" } diff --git a/typescript/custom-resource-provider/package.json b/typescript/custom-resource-provider/package.json index e19d4c744e..39adb022a8 100644 --- a/typescript/custom-resource-provider/package.json +++ b/typescript/custom-resource-provider/package.json @@ -11,16 +11,16 @@ }, "devDependencies": { "@aws-cdk/assert": "*", - "@types/jest": "^26.0.10", - "@types/node": "10.17.27", - "jest": "^26.4.2", - "ts-jest": "^29.1.1", - "aws-cdk": "*", - "ts-node": "^10.9.1", - "typescript": "~5.1.6" + "@types/jest": "^29.5.14", + "@types/node": "22.7.9", + "jest": "^29.7.0", + "ts-jest": "^29.2.5", + "aws-cdk": "2.1004.0", + "ts-node": "^10.9.2", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "^2.0.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0", "source-map-support": "^0.5.16" } diff --git a/typescript/custom-resource/package.json b/typescript/custom-resource/package.json index f90961b5c7..2d2804f725 100644 --- a/typescript/custom-resource/package.json +++ b/typescript/custom-resource/package.json @@ -15,12 +15,12 @@ }, "license": "Apache-2.0", "devDependencies": { - "@types/node": "^10.17.0", - "aws-cdk": "*", - "typescript": "~5.1.6" + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "^2.0.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0" } } diff --git a/typescript/ddb-stream-lambda-sns/package.json b/typescript/ddb-stream-lambda-sns/package.json index 8ef8796e63..5594f7dc0f 100644 --- a/typescript/ddb-stream-lambda-sns/package.json +++ b/typescript/ddb-stream-lambda-sns/package.json @@ -12,8 +12,8 @@ }, "devDependencies": { "@types/jest": "^29.5.14", - "@types/node": "22.9.0", - "aws-cdk": "2.166.0", + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", "jest": "^29.7.0", "ts-jest": "^29.2.5", "ts-node": "^10.9.2", @@ -21,7 +21,7 @@ }, "dependencies": { "@aws-solutions-constructs/aws-dynamodbstreams-lambda": "^2.74.0", - "aws-cdk-lib": "2.167.0", - "constructs": "^10.4.2" + "aws-cdk-lib": "2.185.0", + "constructs": "^10.0.0" } -} \ No newline at end of file +} diff --git a/typescript/ddb/global-table-with-cmk/package.json b/typescript/ddb/global-table-with-cmk/package.json index 501bb0126c..e71e23611d 100644 --- a/typescript/ddb/global-table-with-cmk/package.json +++ b/typescript/ddb/global-table-with-cmk/package.json @@ -10,16 +10,16 @@ "cdk": "cdk" }, "devDependencies": { - "@types/jest": "^26.0.10", - "@types/node": "10.17.27", - "aws-cdk": "2.80.0", - "jest": "^26.4.2", - "ts-jest": "^26.2.0", - "ts-node": "^9.0.0", - "typescript": "~5.1.6" + "@types/jest": "^29.5.14", + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", + "jest": "^29.7.0", + "ts-jest": "^29.2.5", + "ts-node": "^10.9.2", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "2.80.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0", "source-map-support": "^0.5.16" } diff --git a/typescript/ec2-instance-connect-endpoint/package.json b/typescript/ec2-instance-connect-endpoint/package.json index 4d8b73b0bb..a7548fe071 100644 --- a/typescript/ec2-instance-connect-endpoint/package.json +++ b/typescript/ec2-instance-connect-endpoint/package.json @@ -34,18 +34,18 @@ "organization": false }, "devDependencies": { - "@types/jest": "^29.5.2", - "@types/node": "^16", + "@types/jest": "^29.5.14", + "@types/node": "22.7.9", "@typescript-eslint/eslint-plugin": "^5", "@typescript-eslint/parser": "^5", - "aws-cdk": "2.85.0", + "aws-cdk": "2.1004.0", "aws-cdk-lib": "2.85.0", "constructs": "10.0.5", "eslint": "^8", "eslint-import-resolver-node": "^0.3.7", "eslint-import-resolver-typescript": "^3.5.5", "eslint-plugin-import": "^2.27.5", - "jest": "^29.5.0", + "jest": "^29.7.0", "jest-junit": "^15", "jsii": "~5.0.0", "jsii-diff": "^1.84.0", @@ -55,9 +55,9 @@ "npm-check-updates": "^16", "projen": "^0.71.118", "standard-version": "^9", - "ts-jest": "^29.1.1", - "ts-node": "^10.9.1", - "typescript": "^5.1.6" + "ts-jest": "^29.2.5", + "ts-node": "^10.9.2", + "typescript": "~5.6.3" }, "peerDependencies": { "aws-cdk-lib": "^2.85.0", diff --git a/typescript/ec2-instance/package.json b/typescript/ec2-instance/package.json index 59803b8804..7f9051a6f9 100644 --- a/typescript/ec2-instance/package.json +++ b/typescript/ec2-instance/package.json @@ -25,27 +25,27 @@ "projen": "npx projen" }, "devDependencies": { - "@types/jest": "^29.5.3", - "@types/node": "^16", + "@types/jest": "^29.5.14", + "@types/node": "22.7.9", "@typescript-eslint/eslint-plugin": "^5", "@typescript-eslint/parser": "^5", - "aws-cdk": "^2.83.0", + "aws-cdk": "2.1004.0", "esbuild": "^0.18.17", "eslint": "^8", "eslint-import-resolver-node": "^0.3.7", "eslint-import-resolver-typescript": "^3.5.5", "eslint-plugin-import": "^2.28.0", - "jest": "^29.6.2", + "jest": "^29.7.0", "jest-junit": "^15", "npm-check-updates": "^16", "projen": "^0.71.158", - "ts-jest": "^29.1.1", - "ts-node": "^10.9.1", - "typescript": "^5.1.6" + "ts-jest": "^29.2.5", + "ts-node": "^10.9.2", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "^2.83.0", - "constructs": "^10.0.5", + "aws-cdk-lib": "2.185.0", + "constructs": "^10.0.0", "dotenv": "^16.3.1" }, "license": "MIT-0", diff --git a/typescript/ec2-ssm-local-zone/package.json b/typescript/ec2-ssm-local-zone/package.json index c355c1c660..9e121714ce 100644 --- a/typescript/ec2-ssm-local-zone/package.json +++ b/typescript/ec2-ssm-local-zone/package.json @@ -11,16 +11,16 @@ "cdk": "cdk" }, "devDependencies": { - "@types/jest": "^29.2.4", - "@types/node": "18.11.15", - "aws-cdk": "*", - "jest": "^29.3.1", - "ts-jest": "^29.0.3", - "ts-node": "^10.9.1", - "typescript": "~5.1.6" + "@types/jest": "^29.5.14", + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", + "jest": "^29.7.0", + "ts-jest": "^29.2.5", + "ts-node": "^10.9.2", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "^2.0.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0" } } diff --git a/typescript/ecs/cluster/package.json b/typescript/ecs/cluster/package.json index 13a5ae0eed..2c3ab0c0e4 100644 --- a/typescript/ecs/cluster/package.json +++ b/typescript/ecs/cluster/package.json @@ -15,12 +15,12 @@ }, "license": "Apache-2.0", "devDependencies": { - "@types/node": "^8.10.38", - "aws-cdk": "*", - "typescript": "~5.1.6" + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "^2.0.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0" } } diff --git a/typescript/ecs/cross-stack-load-balancer/package.json b/typescript/ecs/cross-stack-load-balancer/package.json index 3083fc570c..6df0150d81 100644 --- a/typescript/ecs/cross-stack-load-balancer/package.json +++ b/typescript/ecs/cross-stack-load-balancer/package.json @@ -15,12 +15,12 @@ }, "license": "Apache-2.0", "devDependencies": { - "@types/node": "^8.10.38", - "aws-cdk": "*", - "typescript": "~5.1.6" + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "^2.0.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0" } } diff --git a/typescript/ecs/ecs-network-load-balanced-service/package.json b/typescript/ecs/ecs-network-load-balanced-service/package.json index 5c78e70bc5..cb20b543ae 100644 --- a/typescript/ecs/ecs-network-load-balanced-service/package.json +++ b/typescript/ecs/ecs-network-load-balanced-service/package.json @@ -15,12 +15,12 @@ }, "license": "Apache-2.0", "devDependencies": { - "@types/node": "^8.10.38", - "aws-cdk": "*", - "typescript": "~5.1.6" + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "^2.0.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0" } } diff --git a/typescript/ecs/ecs-service-with-advanced-alb-config/package.json b/typescript/ecs/ecs-service-with-advanced-alb-config/package.json index 22df8a4eca..c3ca3dcd14 100644 --- a/typescript/ecs/ecs-service-with-advanced-alb-config/package.json +++ b/typescript/ecs/ecs-service-with-advanced-alb-config/package.json @@ -15,12 +15,12 @@ }, "license": "Apache-2.0", "devDependencies": { - "@types/node": "^8.10.38", - "aws-cdk": "*", - "typescript": "~5.1.6" + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "^2.0.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0" } } diff --git a/typescript/ecs/ecs-service-with-logging/package.json b/typescript/ecs/ecs-service-with-logging/package.json index 6e8749b579..b14d076d6b 100644 --- a/typescript/ecs/ecs-service-with-logging/package.json +++ b/typescript/ecs/ecs-service-with-logging/package.json @@ -15,12 +15,12 @@ }, "license": "Apache-2.0", "devDependencies": { - "@types/node": "^8.10.38", - "aws-cdk": "*", - "typescript": "~5.1.6" + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "^2.0.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0" } } diff --git a/typescript/ecs/ecs-service-with-task-networking/package.json b/typescript/ecs/ecs-service-with-task-networking/package.json index 6acc7f05ec..20896e5402 100644 --- a/typescript/ecs/ecs-service-with-task-networking/package.json +++ b/typescript/ecs/ecs-service-with-task-networking/package.json @@ -15,12 +15,12 @@ }, "license": "Apache-2.0", "devDependencies": { - "@types/node": "^8.10.38", - "aws-cdk": "*", - "typescript": "~5.1.6" + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "^2.0.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0" } } diff --git a/typescript/ecs/ecs-service-with-task-placement/package.json b/typescript/ecs/ecs-service-with-task-placement/package.json index 22df8a4eca..c3ca3dcd14 100644 --- a/typescript/ecs/ecs-service-with-task-placement/package.json +++ b/typescript/ecs/ecs-service-with-task-placement/package.json @@ -15,12 +15,12 @@ }, "license": "Apache-2.0", "devDependencies": { - "@types/node": "^8.10.38", - "aws-cdk": "*", - "typescript": "~5.1.6" + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "^2.0.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0" } } diff --git a/typescript/ecs/fargate-application-load-balanced-service/package.json b/typescript/ecs/fargate-application-load-balanced-service/package.json index 44d69d2615..da722fd43f 100644 --- a/typescript/ecs/fargate-application-load-balanced-service/package.json +++ b/typescript/ecs/fargate-application-load-balanced-service/package.json @@ -15,12 +15,12 @@ }, "license": "Apache-2.0", "devDependencies": { - "@types/node": "^8.10.38", - "aws-cdk": "*", - "typescript": "~5.1.6" + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "^2.0.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0" } } diff --git a/typescript/ecs/fargate-service-with-auto-scaling/package.json b/typescript/ecs/fargate-service-with-auto-scaling/package.json index 6b2791aedc..4cbb2aa423 100644 --- a/typescript/ecs/fargate-service-with-auto-scaling/package.json +++ b/typescript/ecs/fargate-service-with-auto-scaling/package.json @@ -15,12 +15,12 @@ }, "license": "Apache-2.0", "devDependencies": { - "@types/node": "^8.10.38", - "aws-cdk": "*", - "typescript": "~5.1.6" + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "^2.0.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0" } } diff --git a/typescript/ecs/fargate-service-with-efs/package.json b/typescript/ecs/fargate-service-with-efs/package.json index 5ba58fd8cf..15f625e3e2 100644 --- a/typescript/ecs/fargate-service-with-efs/package.json +++ b/typescript/ecs/fargate-service-with-efs/package.json @@ -15,12 +15,12 @@ }, "license": "Apache-2.0", "devDependencies": { - "@types/node": "^8.10.38", - "aws-cdk": "*", - "typescript": "~5.1.6" + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "^2.0.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0" } } diff --git a/typescript/ecs/fargate-service-with-local-image/package.json b/typescript/ecs/fargate-service-with-local-image/package.json index 6c6ce6d6f1..73cc130109 100644 --- a/typescript/ecs/fargate-service-with-local-image/package.json +++ b/typescript/ecs/fargate-service-with-local-image/package.json @@ -15,12 +15,12 @@ }, "license": "Apache-2.0", "devDependencies": { - "@types/node": "^8.10.38", - "aws-cdk": "*", - "typescript": "~5.1.6" + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "^2.0.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0" } } diff --git a/typescript/ecs/fargate-service-with-logging/package.json b/typescript/ecs/fargate-service-with-logging/package.json index 42b6b1cdaa..32f2bc842f 100644 --- a/typescript/ecs/fargate-service-with-logging/package.json +++ b/typescript/ecs/fargate-service-with-logging/package.json @@ -15,12 +15,12 @@ }, "license": "Apache-2.0", "devDependencies": { - "@types/node": "^8.10.38", - "aws-cdk": "*", - "typescript": "~5.1.6" + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "^2.0.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0" } } diff --git a/typescript/eks/cluster/package.json b/typescript/eks/cluster/package.json index 88c441f7d6..3766439c9d 100644 --- a/typescript/eks/cluster/package.json +++ b/typescript/eks/cluster/package.json @@ -16,17 +16,17 @@ "license": "Apache-2.0", "devDependencies": { "@types/jest": "^29.5.14", - "@types/node": "22.10.5", - "aws-cdk": "^2.175.1", + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", "jest": "^29.7.0", "ts-jest": "^29.2.5", "ts-node": "^10.9.2", - "typescript": "~5.7.3" + "typescript": "~5.6.3" }, "dependencies": { "@aws-cdk/lambda-layer-kubectl-v31": "^2.0.0", - "aws-cdk-lib": "^2.175.1", - "constructs": "^10.4.2", + "aws-cdk-lib": "2.185.0", + "constructs": "^10.0.0", "source-map-support": "^0.5.21" } } diff --git a/typescript/elasticbeanstalk/elasticbeanstalk-bg-pipeline/package.json b/typescript/elasticbeanstalk/elasticbeanstalk-bg-pipeline/package.json index d83daef591..0ac767f4c0 100644 --- a/typescript/elasticbeanstalk/elasticbeanstalk-bg-pipeline/package.json +++ b/typescript/elasticbeanstalk/elasticbeanstalk-bg-pipeline/package.json @@ -15,12 +15,12 @@ }, "license": "Apache-2.0", "devDependencies": { - "@types/node": "^8.10.40", - "typescript": "~5.1.6", - "aws-cdk": "*" + "@types/node": "22.7.9", + "typescript": "~5.6.3", + "aws-cdk": "2.1004.0" }, "dependencies": { - "aws-cdk-lib": "^2.0.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0", "source-map-support": "^0.5.9" } diff --git a/typescript/elasticbeanstalk/elasticbeanstalk-environment/package.json b/typescript/elasticbeanstalk/elasticbeanstalk-environment/package.json index c0356f4eb2..08106a0aff 100644 --- a/typescript/elasticbeanstalk/elasticbeanstalk-environment/package.json +++ b/typescript/elasticbeanstalk/elasticbeanstalk-environment/package.json @@ -15,12 +15,12 @@ }, "license": "Apache-2.0", "devDependencies": { - "@types/node": "^8.10.40", - "typescript": "~5.1.6", - "aws-cdk": "*" + "@types/node": "22.7.9", + "typescript": "~5.6.3", + "aws-cdk": "2.1004.0" }, "dependencies": { - "aws-cdk-lib": "^2.0.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0", "source-map-support": "^0.5.9" } diff --git a/typescript/eventbridge-lambda/package.json b/typescript/eventbridge-lambda/package.json index beab5c6940..6734506dd8 100644 --- a/typescript/eventbridge-lambda/package.json +++ b/typescript/eventbridge-lambda/package.json @@ -15,14 +15,14 @@ }, "license": "Apache-2.0", "devDependencies": { - "@types/node": "^10.17.0", - "@types/jest": "^26.0.24", - "aws-cdk": "*", - "jest": "^26.6.3", - "typescript": "~5.1.6" + "@types/node": "22.7.9", + "@types/jest": "^29.5.14", + "aws-cdk": "2.1004.0", + "jest": "^29.7.0", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "^2.0.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0" } } diff --git a/typescript/fsx-ad/package.json b/typescript/fsx-ad/package.json index 087224638c..e5bb693a07 100644 --- a/typescript/fsx-ad/package.json +++ b/typescript/fsx-ad/package.json @@ -15,12 +15,12 @@ }, "license": "Apache-2.0", "devDependencies": { - "@types/node": "^10.17.0", - "aws-cdk": "*", - "typescript": "~5.1.6" + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "^2.0.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0" } } diff --git a/typescript/http-proxy-apigateway/package.json b/typescript/http-proxy-apigateway/package.json index 4088a90f09..c0ba73dcc5 100644 --- a/typescript/http-proxy-apigateway/package.json +++ b/typescript/http-proxy-apigateway/package.json @@ -15,12 +15,12 @@ }, "license": "Apache-2.0", "devDependencies": { - "@types/node": "^14.0.6", - "aws-cdk": "*", - "typescript": "~5.1.6" + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "^2.0.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0" } } diff --git a/typescript/imagebuilder/package.json b/typescript/imagebuilder/package.json index 2415d112d8..0d47b02139 100644 --- a/typescript/imagebuilder/package.json +++ b/typescript/imagebuilder/package.json @@ -10,16 +10,16 @@ "cdk": "cdk" }, "devDependencies": { - "@types/jest": "29.5.11", - "@types/node": "20.11.5", - "aws-cdk": "2.122.0", - "ts-node": "10.9.2", - "typescript": "5.3.3" + "@types/jest": "^29.5.14", + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", + "ts-node": "^10.9.2", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "2.122.0", + "aws-cdk-lib": "2.185.0", "cdk-nag": "2.28.27", - "constructs": "10.3.0", + "constructs": "^10.0.0", "source-map-support": "0.5.21" } } diff --git a/typescript/inspector2/package.json b/typescript/inspector2/package.json index 5114e87180..4368906448 100644 --- a/typescript/inspector2/package.json +++ b/typescript/inspector2/package.json @@ -13,16 +13,16 @@ "devDependencies": { "@aws-sdk/client-inspector2": "^3.258.0", "@types/aws-lambda": "^8.10.109", - "@types/jest": "^29.2.4", - "@types/node": "18.11.15", + "@types/jest": "^29.5.14", + "@types/node": "22.7.9", "esbuild": "^0.17.4", - "jest": "^29.3.1", - "ts-jest": "^29.0.5", - "ts-node": "^10.9.1", - "typescript": "~5.1.6" + "jest": "^29.7.0", + "ts-jest": "^29.2.5", + "ts-node": "^10.9.2", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "2.80.0", - "constructs": "^10.1.190" + "aws-cdk-lib": "2.185.0", + "constructs": "^10.0.0" } } diff --git a/typescript/lambda-api-ci/package.json b/typescript/lambda-api-ci/package.json index 1a64f17b17..c686434fc4 100644 --- a/typescript/lambda-api-ci/package.json +++ b/typescript/lambda-api-ci/package.json @@ -12,15 +12,15 @@ "prettier": "prettier --write '**/{bin,lib,src,tst}/*.ts'" }, "devDependencies": { - "aws-cdk": "*", - "@types/node": "^20.11.24", + "aws-cdk": "2.1004.0", + "@types/node": "22.7.9", "ts-node": "^10.9.2", - "typescript": "~5.3.3", + "typescript": "~5.6.3", "prettier": "^3.2.5" }, "dependencies": { - "aws-cdk-lib": "^2.131.0", - "constructs": "^10.3.0", + "aws-cdk-lib": "2.185.0", + "constructs": "^10.0.0", "@aws-sdk/client-s3": "^3.525.0", "source-map-support": "^0.5.21" }, diff --git a/typescript/lambda-api-ci/src/package.json b/typescript/lambda-api-ci/src/package.json index 78e204fc70..30a7b0f5ec 100644 --- a/typescript/lambda-api-ci/src/package.json +++ b/typescript/lambda-api-ci/src/package.json @@ -9,11 +9,11 @@ "test": "jest" }, "devDependencies": { - "@types/node": "^20.11.25", + "@types/node": "22.7.9", "jest": "^29.7.0", - "ts-jest": "^29.1.2", + "ts-jest": "^29.2.5", "ts-node": "^10.9.2", - "typescript": "~5.4.2" + "typescript": "~5.6.3" }, "dependencies": { "@aws-sdk/client-s3": "^3.525.0" diff --git a/typescript/lambda-cloudwatch-dashboard/package.json b/typescript/lambda-cloudwatch-dashboard/package.json index d2aea88fc7..3688c2987d 100644 --- a/typescript/lambda-cloudwatch-dashboard/package.json +++ b/typescript/lambda-cloudwatch-dashboard/package.json @@ -11,16 +11,16 @@ }, "devDependencies": { "@aws-cdk/assert": "*", - "@types/jest": "^26.0.10", - "@types/node": "10.17.27", - "jest": "^26.4.2", - "ts-jest": "^26.2.0", - "aws-cdk": "*", - "ts-node": "^10.9.1", - "typescript": "~5.1.6" + "@types/jest": "^29.5.14", + "@types/node": "22.7.9", + "jest": "^29.7.0", + "ts-jest": "^29.2.5", + "aws-cdk": "2.1004.0", + "ts-node": "^10.9.2", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "^2.0.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0", "source-map-support": "^0.5.16" } diff --git a/typescript/lambda-cron/package.json b/typescript/lambda-cron/package.json index 7c6039429a..f4407313b2 100644 --- a/typescript/lambda-cron/package.json +++ b/typescript/lambda-cron/package.json @@ -16,14 +16,14 @@ }, "license": "Apache-2.0", "devDependencies": { - "@types/node": "^10.17.0", - "@types/jest": "^26.0.24", - "aws-cdk": "*", - "jest": "^26.6.3", - "typescript": "~5.1.6" + "@types/node": "22.7.9", + "@types/jest": "^29.5.14", + "aws-cdk": "2.1004.0", + "jest": "^29.7.0", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "^2.0.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0" } } diff --git a/typescript/lambda-layer/package.json b/typescript/lambda-layer/package.json index 3196b8be6e..b755432d40 100644 --- a/typescript/lambda-layer/package.json +++ b/typescript/lambda-layer/package.json @@ -11,13 +11,13 @@ }, "devDependencies": { "@aws-cdk/assert": "*", - "@types/node": "10.17.27", - "aws-cdk": "*", - "ts-node": "^10.9.1", - "typescript": "~5.1.6" + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", + "ts-node": "^10.9.2", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "^2.0.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0", "source-map-support": "^0.5.16" } diff --git a/typescript/lambda-manage-s3-event-notification/package.json b/typescript/lambda-manage-s3-event-notification/package.json index ff797469ff..54b22abfde 100644 --- a/typescript/lambda-manage-s3-event-notification/package.json +++ b/typescript/lambda-manage-s3-event-notification/package.json @@ -11,14 +11,14 @@ }, "devDependencies": { "@aws-cdk/assert": "*", - "@types/node": "^10.17.27", - "aws-cdk": "*", - "ts-node": "^10.9.1", - "typescript": "~5.1.6" + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", + "ts-node": "^10.9.2", + "typescript": "~5.6.3" }, "dependencies": { "@aws-sdk/client-s3": "^3.427.0", - "aws-cdk-lib": "^2.0.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0", "source-map-support": "^0.5.16" } diff --git a/typescript/lambda-provisioned-concurrency-autoscaling/package.json b/typescript/lambda-provisioned-concurrency-autoscaling/package.json index 0d17261ca1..02984c58a9 100644 --- a/typescript/lambda-provisioned-concurrency-autoscaling/package.json +++ b/typescript/lambda-provisioned-concurrency-autoscaling/package.json @@ -17,16 +17,15 @@ }, "devDependencies": { "@aws-cdk/assert": "*", - "@types/node": "10.17.27", - "aws-cdk": "*", - "ts-node": "^10.9.1", - "@types/jest": "^26.0.24", - "jest": "^26.6.3", - "typescript": "~5.1.6" + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", + "ts-node": "^10.9.2", + "@types/jest": "^29.5.14", + "jest": "^29.7.0", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "^2.0.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0" - } } diff --git a/typescript/lexbot/package.json b/typescript/lexbot/package.json index 091c136fe4..52864a787e 100644 --- a/typescript/lexbot/package.json +++ b/typescript/lexbot/package.json @@ -11,17 +11,17 @@ "cdk": "cdk" }, "devDependencies": { - "@types/jest": "^29.5.11", - "@types/node": "20.11.14", + "@types/jest": "^29.5.14", + "@types/node": "22.7.9", "jest": "^29.7.0", - "ts-jest": "^29.1.2", - "aws-cdk": "2.126.0", + "ts-jest": "^29.2.5", + "aws-cdk": "2.1004.0", "ts-node": "^10.9.2", - "typescript": "~5.3.3" + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "2.126.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0", "source-map-support": "^0.5.21" } -} \ No newline at end of file +} diff --git a/typescript/my-widget-service/package.json b/typescript/my-widget-service/package.json index 01124db75d..d7976c6e0b 100644 --- a/typescript/my-widget-service/package.json +++ b/typescript/my-widget-service/package.json @@ -15,12 +15,12 @@ }, "license": "Apache-2.0", "devDependencies": { - "@types/node": "^10.17.0", - "aws-cdk": "*", - "typescript": "~5.1.6" + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "^2.0.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0", "source-map-support": "*" } diff --git a/typescript/neptune-with-vpc/package.json b/typescript/neptune-with-vpc/package.json index c08fbdcd3a..ae59b67146 100644 --- a/typescript/neptune-with-vpc/package.json +++ b/typescript/neptune-with-vpc/package.json @@ -10,7 +10,7 @@ "cdk": "cdk" }, "dependencies": { - "aws-cdk-lib": "^2.0.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0", "@aws-cdk/aws-neptune-alpha": "^2.0.0-alpha.10", "@types/jest": "^26.0.10", diff --git a/typescript/opensearch/cwlogs_ingestion/package.json b/typescript/opensearch/cwlogs_ingestion/package.json index cba042315d..856a4fd5f9 100644 --- a/typescript/opensearch/cwlogs_ingestion/package.json +++ b/typescript/opensearch/cwlogs_ingestion/package.json @@ -11,21 +11,21 @@ "cdk": "cdk" }, "devDependencies": { - "@types/jest": "^29.5.4", - "@types/node": "20.5.9", - "aws-cdk": "^2.165.0", + "@types/jest": "^29.5.14", + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", "aws-cdk-lib": "^2.165.0", "constructs": "^10.2.43", "globals": "^15.6.0", - "jest": "^29.6.4", - "ts-jest": "^29.1.1", - "ts-node": "^10.9.1", - "typescript": "~5.2.2" + "jest": "^29.7.0", + "ts-jest": "^29.2.5", + "ts-node": "^10.9.2", + "typescript": "~5.6.3" }, "dependencies": { "@aws-cdk/aws-lambda-python-alpha": "2.165.0-alpha.0", "aws-cdk": "^2.165.0", - "aws-cdk-lib": "^2.165.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0", "source-map-support": "^0.5.21" } diff --git a/typescript/opensearch/os_vpc_provision/package.json b/typescript/opensearch/os_vpc_provision/package.json index ade93c4746..66c218d4c8 100644 --- a/typescript/opensearch/os_vpc_provision/package.json +++ b/typescript/opensearch/os_vpc_provision/package.json @@ -10,18 +10,18 @@ "cdk": "cdk" }, "devDependencies": { - "@types/jest": "^29.5.4", - "@types/node": "20.5.9", - "jest": "^29.6.4", - "ts-jest": "^29.1.1", - "aws-cdk": "2.95.1", - "ts-node": "^10.9.1", - "typescript": "~5.2.2", + "@types/jest": "^29.5.14", + "@types/node": "22.7.9", + "jest": "^29.7.0", + "ts-jest": "^29.2.5", + "aws-cdk": "2.1004.0", + "ts-node": "^10.9.2", + "typescript": "~5.6.3", "constructs": "^10.2.43" }, "dependencies": { "aws-cdk": "^2.102.0", - "aws-cdk-lib": "2.90.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0", "source-map-support": "^0.5.21" } diff --git a/typescript/quicksight/package.json b/typescript/quicksight/package.json index c0302e659f..9060d31678 100644 --- a/typescript/quicksight/package.json +++ b/typescript/quicksight/package.json @@ -10,16 +10,16 @@ "cdk": "cdk" }, "devDependencies": { - "@types/jest": "^29.5.12", - "@types/node": "20.14.9", - "aws-cdk": "2.156.0", + "@types/jest": "^29.5.14", + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", "jest": "^29.7.0", - "ts-jest": "^29.1.5", + "ts-jest": "^29.2.5", "ts-node": "^10.9.2", - "typescript": "~5.5.3" + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "2.156.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0", "source-map-support": "^0.5.21" } diff --git a/typescript/r53-resolver/package.json b/typescript/r53-resolver/package.json index a9a3343bf7..dc7a76c8e4 100644 --- a/typescript/r53-resolver/package.json +++ b/typescript/r53-resolver/package.json @@ -11,17 +11,17 @@ "cdk": "cdk" }, "devDependencies": { - "@types/jest": "^29.5.12", - "@types/node": "20.11.19", - "aws-cdk": "2.133.0", + "@types/jest": "^29.5.14", + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", "jest": "^29.7.0", - "ts-jest": "^29.1.2", + "ts-jest": "^29.2.5", "ts-node": "^10.9.2", - "typescript": "~5.3.3" + "typescript": "~5.6.3" }, "dependencies": { "@aws-cdk/aws-route53resolver-alpha": "^2.133.0-alpha.0", - "aws-cdk-lib": "2.133.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0", "source-map-support": "^0.5.21" } diff --git a/typescript/rds/aurora/package.json b/typescript/rds/aurora/package.json index a857a1ff31..629998b523 100644 --- a/typescript/rds/aurora/package.json +++ b/typescript/rds/aurora/package.json @@ -10,17 +10,17 @@ "cdk": "cdk" }, "devDependencies": { - "@types/jest": "^29.5.13", - "@types/node": "*", + "@types/jest": "^29.5.14", + "@types/node": "22.7.9", "jest": "^29.7.0", - "aws-cdk": "*", + "aws-cdk": "2.1004.0", "ts-jest": "^29.2.5", "ts-node": "^10.9.2", - "typescript": "~5.6.2" + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "^2.158.0", - "constructs": "^10.3.0", + "aws-cdk-lib": "2.185.0", + "constructs": "^10.0.0", "source-map-support": "^0.5.21" } } diff --git a/typescript/rds/mysql/package.json b/typescript/rds/mysql/package.json index c4c9e6d770..03c4a245ce 100644 --- a/typescript/rds/mysql/package.json +++ b/typescript/rds/mysql/package.json @@ -10,18 +10,18 @@ "cdk": "cdk" }, "devDependencies": { - "@types/jest": "^29.5.13", - "@types/node": "*", - "jest": "29.7.0", - "ts-jest": "29.2.5", + "@types/jest": "^29.5.14", + "@types/node": "22.7.9", + "jest": "^29.7.0", + "ts-jest": "^29.2.5", "ts-node": "^10.9.2", - "aws-cdk": "*", - "typescript": "~5.6.2" + "aws-cdk": "2.1004.0", + "typescript": "~5.6.3" }, "esModuleInterop": true, "dependencies": { - "aws-cdk-lib": "^2.158.0", - "constructs": "^10.3.0", + "aws-cdk-lib": "2.185.0", + "constructs": "^10.0.0", "source-map-support": "^0.5.21" } } diff --git a/typescript/rds/oracle/package.json b/typescript/rds/oracle/package.json index 332e905643..a5cef61ba8 100644 --- a/typescript/rds/oracle/package.json +++ b/typescript/rds/oracle/package.json @@ -10,17 +10,17 @@ "cdk": "cdk" }, "devDependencies": { - "@types/jest": "^29.5.13", - "@types/node": "*", + "@types/jest": "^29.5.14", + "@types/node": "22.7.9", "jest": "^29.7.0", - "aws-cdk": "*", + "aws-cdk": "2.1004.0", "ts-jest": "^29.2.5", "ts-node": "^10.9.2", - "typescript": "~5.6.2" + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "^2.158.0", - "constructs": "^10.3.0", + "aws-cdk-lib": "2.185.0", + "constructs": "^10.0.0", "source-map-support": "^0.5.21" } } diff --git a/typescript/rekognition-lambda-s3-trigger/package.json b/typescript/rekognition-lambda-s3-trigger/package.json index 237a081ea9..8acceb2e56 100644 --- a/typescript/rekognition-lambda-s3-trigger/package.json +++ b/typescript/rekognition-lambda-s3-trigger/package.json @@ -10,16 +10,16 @@ "cdk": "cdk" }, "devDependencies": { - "@types/node": "10.17.27", - "aws-cdk": "*", - "ts-node": "^9.0.0", - "typescript": "~5.1.6" + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", + "ts-node": "^10.9.2", + "typescript": "~5.6.3" }, "dependencies": { "@aws-sdk/client-dynamodb": "^3.538.0", "@aws-sdk/client-rekognition": "^3.535.0", - "aws-cdk-lib": "*", - "constructs": "*", + "aws-cdk-lib": "2.185.0", + "constructs": "^10.0.0", "source-map-support": "^0.5.16" } } diff --git a/typescript/resource-overrides/package.json b/typescript/resource-overrides/package.json index beb2ba8810..ec5f6d8a6f 100644 --- a/typescript/resource-overrides/package.json +++ b/typescript/resource-overrides/package.json @@ -15,12 +15,12 @@ }, "license": "Apache-2.0", "devDependencies": { - "aws-cdk": "*", - "@types/node": "^10.17.0", - "typescript": "~5.1.6" + "aws-cdk": "2.1004.0", + "@types/node": "22.7.9", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "^2.0.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0" } } diff --git a/typescript/route53-resolver-dns-firewall/package.json b/typescript/route53-resolver-dns-firewall/package.json index e6e71d5f95..a3ea5e85c6 100644 --- a/typescript/route53-resolver-dns-firewall/package.json +++ b/typescript/route53-resolver-dns-firewall/package.json @@ -15,12 +15,12 @@ }, "license": "Apache-2.0", "devDependencies": { - "@types/node": "10.17.27", - "aws-cdk": "2.80.0", - "typescript": "^4.9.3" + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "2.80.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0", "source-map-support": "^0.5.21" } diff --git a/typescript/s3-kms-cross-account-replication/package.json b/typescript/s3-kms-cross-account-replication/package.json index c4cbcccf15..b0680e9e65 100644 --- a/typescript/s3-kms-cross-account-replication/package.json +++ b/typescript/s3-kms-cross-account-replication/package.json @@ -11,18 +11,18 @@ "cdk": "cdk" }, "devDependencies": { - "@types/jest": "^26.0.10", - "@types/node": "10.17.27", - "aws-cdk": "^2.79.1", + "@types/jest": "^29.5.14", + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", "cdk-nag": "^2.0.0", - "jest": "^29.6.2", + "jest": "^29.7.0", "prettier": "2.6.2", - "ts-jest": "^29.1.1", - "ts-node": "^10.9.1", - "typescript": "~5.1.6" + "ts-jest": "^29.2.5", + "ts-node": "^10.9.2", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "^2.79.1", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0", "source-map-support": "^0.5.16" } diff --git a/typescript/s3-object-lambda/package.json b/typescript/s3-object-lambda/package.json index 8345ca0f74..d4dd3496be 100644 --- a/typescript/s3-object-lambda/package.json +++ b/typescript/s3-object-lambda/package.json @@ -10,15 +10,15 @@ "cdk": "cdk" }, "devDependencies": { - "@types/node": "18.11.17", - "aws-cdk": "*", - "ts-node": "^10.9.1", - "typescript": "~5.1.6" + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", + "ts-node": "^10.9.2", + "typescript": "~5.6.3" }, "dependencies": { "@aws-sdk/client-s3": "^3.537.0", - "aws-cdk-lib": "^2.0.0", - "constructs": "^10.1.190", + "aws-cdk-lib": "2.185.0", + "constructs": "^10.0.0", "source-map-support": "^0.5.21" } } diff --git a/typescript/s3-sns-lambda-chain/package.json b/typescript/s3-sns-lambda-chain/package.json index 47dffb202f..026089cc3f 100644 --- a/typescript/s3-sns-lambda-chain/package.json +++ b/typescript/s3-sns-lambda-chain/package.json @@ -12,17 +12,17 @@ "cdk": "cdk" }, "devDependencies": { - "@types/jest": "^29.2.5", - "@types/node": "18.11.18", - "aws-cdk": "*", - "jest": "^29.3.1", - "ts-jest": "^29.0.5", - "ts-node": "^10.9.1", - "typescript": "~4.9.4" + "@types/jest": "^29.5.14", + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", + "jest": "^29.7.0", + "ts-jest": "^29.2.5", + "ts-node": "^10.9.2", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "*", - "constructs": "*" + "aws-cdk-lib": "2.185.0", + "constructs": "^10.0.0" }, "jest": { "preset": "ts-jest", diff --git a/typescript/secrets-manager-rotation/package.json b/typescript/secrets-manager-rotation/package.json index 82af4a6208..2dce21919f 100644 --- a/typescript/secrets-manager-rotation/package.json +++ b/typescript/secrets-manager-rotation/package.json @@ -15,17 +15,17 @@ }, "license": "Apache-2.0", "devDependencies": { - "@types/jest": "^26.0.10", - "@types/node": "10.17.27", - "aws-cdk": "*", - "jest": "^26.4.2", - "ts-jest": "^26.2.0", - "ts-node": "^9.0.0", - "typescript": "~3.9.7" + "@types/jest": "^29.5.14", + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", + "jest": "^29.7.0", + "ts-jest": "^29.2.5", + "ts-node": "^10.9.2", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "*", + "aws-cdk-lib": "2.185.0", "@aws-cdk/aws-lambda-python-alpha": "*", - "constructs": "*" + "constructs": "^10.0.0" } } diff --git a/typescript/servicecatalog/portfolio-with-ec2-product/package.json b/typescript/servicecatalog/portfolio-with-ec2-product/package.json index 54f65fe39c..51e3fc2438 100644 --- a/typescript/servicecatalog/portfolio-with-ec2-product/package.json +++ b/typescript/servicecatalog/portfolio-with-ec2-product/package.json @@ -10,16 +10,16 @@ "cdk": "cdk" }, "devDependencies": { - "@types/jest": "^26.0.10", - "@types/node": "10.17.27", - "jest": "^29.6.2", - "ts-jest": "^29.1.1", - "aws-cdk": "*", - "ts-node": "^10.9.1", - "typescript": "~5.1.6" + "@types/jest": "^29.5.14", + "@types/node": "22.7.9", + "jest": "^29.7.0", + "ts-jest": "^29.2.5", + "aws-cdk": "2.1004.0", + "ts-node": "^10.9.2", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "^2.0.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0" } } diff --git a/typescript/static-site-basic/package.json b/typescript/static-site-basic/package.json index 6aef547485..8c8cf37368 100644 --- a/typescript/static-site-basic/package.json +++ b/typescript/static-site-basic/package.json @@ -14,12 +14,12 @@ }, "license": "Apache-2.0", "devDependencies": { - "@types/node": "^10.17.0", - "aws-cdk": "*", - "typescript": "~5.1.6" + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "^2.0.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0", "ts-node": "^10.9.2" } diff --git a/typescript/static-site/package.json b/typescript/static-site/package.json index 3315dde4f8..8ceb6c6ed7 100644 --- a/typescript/static-site/package.json +++ b/typescript/static-site/package.json @@ -14,12 +14,12 @@ }, "license": "Apache-2.0", "devDependencies": { - "@types/node": "^10.17.0", - "aws-cdk": "*", - "typescript": "~5.1.6" + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "^2.0.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0" } } diff --git a/typescript/stepfunction-external-definition/package.json b/typescript/stepfunction-external-definition/package.json index 8bffbf265a..e4a021602e 100644 --- a/typescript/stepfunction-external-definition/package.json +++ b/typescript/stepfunction-external-definition/package.json @@ -10,13 +10,13 @@ "cdk": "cdk" }, "devDependencies": { - "@types/node": "22.5.4", - "aws-cdk": "2.162.1", + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", "ts-node": "^10.9.2", - "typescript": "~5.6.2" + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "2.162.1", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0", "source-map-support": "^0.5.21" } diff --git a/typescript/stepfunctions-job-poller/package.json b/typescript/stepfunctions-job-poller/package.json index b8b1269969..4899fff8a8 100644 --- a/typescript/stepfunctions-job-poller/package.json +++ b/typescript/stepfunctions-job-poller/package.json @@ -15,12 +15,12 @@ }, "license": "Apache-2.0", "devDependencies": { - "@types/node": "*", - "aws-cdk": "*", - "typescript": "~5.1.6" + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "^2.0.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0" } } diff --git a/typescript/waf/package.json b/typescript/waf/package.json index 1ffdf9b48b..41f456408b 100644 --- a/typescript/waf/package.json +++ b/typescript/waf/package.json @@ -10,13 +10,13 @@ "cdk": "cdk" }, "devDependencies": { - "@types/jest": "^26.0.10", - "@types/node": "*", - "aws-cdk": "*", - "typescript": "~5.1.6" + "@types/jest": "^29.5.14", + "@types/node": "22.7.9", + "aws-cdk": "2.1004.0", + "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "^2.0.0", + "aws-cdk-lib": "2.185.0", "constructs": "^10.0.0", "jest": "^26.4.2", "ts-jest": "^26.2.0", From 81dfc941718a45bbb3bfbe70b4d131c66ee8da8f Mon Sep 17 00:00:00 2001 From: Michael Kaiser Date: Mon, 24 Mar 2025 18:38:11 -0500 Subject: [PATCH 2/7] Commit these fixes --- .../gateway-lambda-auth-stack.test.ts.snap | 12 +- .../package.json | 12 +- .../.gitattributes | 24 -- .../.github/pull_request_template.md | 1 - .../.github/workflows/build.yml | 110 ------- .../.github/workflows/pull-request-lint.yml | 28 -- .../.github/workflows/release.yml | 109 ------ .../.github/workflows/upgrade-main.yml | 90 ----- .../ec2-instance-connect-endpoint/.gitignore | 57 ---- .../.mergify.yml | 26 -- .../.projen/deps.json | 133 -------- .../.projen/files.json | 21 -- .../.projen/tasks.json | 310 ------------------ .../.projenrc.ts | 39 --- .../ec2-instance-connect-endpoint/LICENSE | 202 ------------ .../ec2-instance-connect-endpoint/cdk.json | 3 +- .../package.json | 99 +----- .../test-reports/junit.xml | 3 + .../tsconfig.dev.json | 38 --- .../tsconfig.json} | 25 +- typescript/ec2-instance/.gitattributes | 23 -- .../.github/pull_request_template.md | 1 - .../ec2-instance/.github/workflows/build.yml | 73 ----- .../.github/workflows/pull-request-lint.yml | 29 -- .../.github/workflows/upgrade.yml | 83 ----- typescript/ec2-instance/.gitignore | 58 ---- typescript/ec2-instance/.mergify.yml | 24 -- typescript/ec2-instance/.projen/deps.json | 94 ------ typescript/ec2-instance/.projen/files.json | 22 -- typescript/ec2-instance/.projen/tasks.json | 269 --------------- typescript/ec2-instance/.projenrc.js | 27 -- typescript/ec2-instance/cdk.json | 45 ++- typescript/ec2-instance/package.json | 82 +---- .../ec2-instance/test-reports/junit.xml | 23 ++ typescript/ec2-instance/tsconfig.json | 47 +-- .../example-localzone-stack.test.ts.snap | 18 + typescript/inspector2/jest.config.js | 12 + ...egated-admin-account-resource.test.ts.snap | 94 ++++-- .../inspector2-enable-resources.test.ts.snap | 99 +++--- ...nspector2-monitoring-resource.test.ts.snap | 104 +++--- ...r2-update-org-config-resource.test.ts.snap | 94 ++++-- 41 files changed, 392 insertions(+), 2271 deletions(-) delete mode 100644 typescript/ec2-instance-connect-endpoint/.gitattributes delete mode 100644 typescript/ec2-instance-connect-endpoint/.github/pull_request_template.md delete mode 100644 typescript/ec2-instance-connect-endpoint/.github/workflows/build.yml delete mode 100644 typescript/ec2-instance-connect-endpoint/.github/workflows/pull-request-lint.yml delete mode 100644 typescript/ec2-instance-connect-endpoint/.github/workflows/release.yml delete mode 100644 typescript/ec2-instance-connect-endpoint/.github/workflows/upgrade-main.yml delete mode 100644 typescript/ec2-instance-connect-endpoint/.gitignore delete mode 100644 typescript/ec2-instance-connect-endpoint/.mergify.yml delete mode 100644 typescript/ec2-instance-connect-endpoint/.projen/deps.json delete mode 100644 typescript/ec2-instance-connect-endpoint/.projen/files.json delete mode 100644 typescript/ec2-instance-connect-endpoint/.projen/tasks.json delete mode 100644 typescript/ec2-instance-connect-endpoint/.projenrc.ts delete mode 100644 typescript/ec2-instance-connect-endpoint/LICENSE create mode 100644 typescript/ec2-instance-connect-endpoint/test-reports/junit.xml delete mode 100644 typescript/ec2-instance-connect-endpoint/tsconfig.dev.json rename typescript/{ec2-instance/tsconfig.dev.json => ec2-instance-connect-endpoint/tsconfig.json} (65%) delete mode 100644 typescript/ec2-instance/.gitattributes delete mode 100644 typescript/ec2-instance/.github/pull_request_template.md delete mode 100644 typescript/ec2-instance/.github/workflows/build.yml delete mode 100644 typescript/ec2-instance/.github/workflows/pull-request-lint.yml delete mode 100644 typescript/ec2-instance/.github/workflows/upgrade.yml delete mode 100644 typescript/ec2-instance/.gitignore delete mode 100644 typescript/ec2-instance/.mergify.yml delete mode 100644 typescript/ec2-instance/.projen/deps.json delete mode 100644 typescript/ec2-instance/.projen/files.json delete mode 100644 typescript/ec2-instance/.projen/tasks.json delete mode 100644 typescript/ec2-instance/.projenrc.js create mode 100644 typescript/ec2-instance/test-reports/junit.xml create mode 100644 typescript/inspector2/jest.config.js diff --git a/typescript/api-gateway-lambda-token-authorizer/test/stack/__snapshots__/gateway-lambda-auth-stack.test.ts.snap b/typescript/api-gateway-lambda-token-authorizer/test/stack/__snapshots__/gateway-lambda-auth-stack.test.ts.snap index e54989d21d..1ca9c87994 100644 --- a/typescript/api-gateway-lambda-token-authorizer/test/stack/__snapshots__/gateway-lambda-auth-stack.test.ts.snap +++ b/typescript/api-gateway-lambda-token-authorizer/test/stack/__snapshots__/gateway-lambda-auth-stack.test.ts.snap @@ -50,10 +50,10 @@ exports[`Snapshot Stack 1`] = ` "value": "nodejs20.x", }, "cn-north-1": { - "value": "nodejs18.x", + "value": "nodejs20.x", }, "cn-northwest-1": { - "value": "nodejs18.x", + "value": "nodejs20.x", }, "eu-central-1": { "value": "nodejs20.x", @@ -104,10 +104,10 @@ exports[`Snapshot Stack 1`] = ` "value": "nodejs20.x", }, "us-gov-east-1": { - "value": "nodejs18.x", + "value": "nodejs20.x", }, "us-gov-west-1": { - "value": "nodejs18.x", + "value": "nodejs20.x", }, "us-iso-east-1": { "value": "nodejs18.x", @@ -322,7 +322,7 @@ exports[`Snapshot Stack 1`] = ` "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}", }, - "S3Key": "a1deff17a695906f93c544b1deae2bf444210622f05330da961687eb8f4a51a7.zip", + "S3Key": "2ad282c80ed8bef2dc8a20da8b07e92dd5259826cca0b685f8cc11f808eca9bb.zip", }, "Description": "Lambda Authorizer", "Environment": { @@ -507,7 +507,7 @@ exports[`Snapshot Stack 1`] = ` "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}", }, - "S3Key": "5ce4b859d5e57c3d238da3ac017e0ea37bf34ad1b71de268430b08e38bb9450d.zip", + "S3Key": "dc8dcb7f07403837f3ff1672cbf17e30ee3eaa1a3a058c5397b9db8b9e964b6b.zip", }, "Description": "Operational Lambda", "Environment": { diff --git a/typescript/appsync-graphql-typescript-resolver/package.json b/typescript/appsync-graphql-typescript-resolver/package.json index b200fad910..6ddd32f059 100644 --- a/typescript/appsync-graphql-typescript-resolver/package.json +++ b/typescript/appsync-graphql-typescript-resolver/package.json @@ -14,16 +14,16 @@ }, "devDependencies": { "@aws-appsync/utils": "^1.2.5", - "@types/jest": "^29.5.14", - "@types/node": "22.7.9", + "@types/jest": "^29.5.12", + "@types/node": "20.11.19", "jest": "^29.7.0", - "ts-jest": "^29.2.5", - "aws-cdk": "2.1004.0", + "ts-jest": "^29.1.2", + "aws-cdk": "2.133.0", "ts-node": "^10.9.2", - "typescript": "~5.6.3" + "typescript": "~5.3.3" }, "dependencies": { - "aws-cdk-lib": "2.185.0", + "aws-cdk-lib": "2.133.0", "constructs": "^10.0.0", "source-map-support": "^0.5.21" } diff --git a/typescript/ec2-instance-connect-endpoint/.gitattributes b/typescript/ec2-instance-connect-endpoint/.gitattributes deleted file mode 100644 index 556d869bf3..0000000000 --- a/typescript/ec2-instance-connect-endpoint/.gitattributes +++ /dev/null @@ -1,24 +0,0 @@ -# ~~ Generated by projen. To modify, edit .projenrc.ts and run "npx projen". - -*.snap linguist-generated -/.eslintrc.json linguist-generated -/.gitattributes linguist-generated -/.github/pull_request_template.md linguist-generated -/.github/workflows/build.yml linguist-generated -/.github/workflows/pull-request-lint.yml linguist-generated -/.github/workflows/release.yml linguist-generated -/.github/workflows/upgrade-main.yml linguist-generated -/.gitignore linguist-generated -/.mergify.yml linguist-generated -/.npmignore linguist-generated -/.npmrc linguist-generated -/.projen/** linguist-generated -/.projen/deps.json linguist-generated -/.projen/files.json linguist-generated -/.projen/tasks.json linguist-generated -/API.md linguist-generated -/cdk.json linguist-generated -/LICENSE linguist-generated -/package.json linguist-generated -/tsconfig.dev.json linguist-generated -/yarn.lock linguist-generated \ No newline at end of file diff --git a/typescript/ec2-instance-connect-endpoint/.github/pull_request_template.md b/typescript/ec2-instance-connect-endpoint/.github/pull_request_template.md deleted file mode 100644 index 11d479bcae..0000000000 --- a/typescript/ec2-instance-connect-endpoint/.github/pull_request_template.md +++ /dev/null @@ -1 +0,0 @@ -Fixes # \ No newline at end of file diff --git a/typescript/ec2-instance-connect-endpoint/.github/workflows/build.yml b/typescript/ec2-instance-connect-endpoint/.github/workflows/build.yml deleted file mode 100644 index 9d766c7ad6..0000000000 --- a/typescript/ec2-instance-connect-endpoint/.github/workflows/build.yml +++ /dev/null @@ -1,110 +0,0 @@ -# ~~ Generated by projen. To modify, edit .projenrc.ts and run "npx projen". - -name: build -on: - pull_request: {} - workflow_dispatch: {} -jobs: - build: - runs-on: ubuntu-latest - permissions: - contents: write - outputs: - self_mutation_happened: ${{ steps.self_mutation.outputs.self_mutation_happened }} - env: - CI: "true" - steps: - - name: Checkout - uses: actions/checkout@v3 - with: - ref: ${{ github.event.pull_request.head.ref }} - repository: ${{ github.event.pull_request.head.repo.full_name }} - - name: Setup Node.js - uses: actions/setup-node@v3 - with: - node-version: 16.x - - name: Install dependencies - run: yarn install --check-files - - name: build - run: npx projen build - - name: Find mutations - id: self_mutation - run: |- - git add . - git diff --staged --patch --exit-code > .repo.patch || echo "self_mutation_happened=true" >> $GITHUB_OUTPUT - - name: Upload patch - if: steps.self_mutation.outputs.self_mutation_happened - uses: actions/upload-artifact@v3 - with: - name: .repo.patch - path: .repo.patch - - name: Fail build on mutation - if: steps.self_mutation.outputs.self_mutation_happened - run: |- - echo "::error::Files were changed during build (see build log). If this was triggered from a fork, you will need to update your branch." - cat .repo.patch - exit 1 - - name: Backup artifact permissions - run: cd dist && getfacl -R . > permissions-backup.acl - continue-on-error: true - - name: Upload artifact - uses: actions/upload-artifact@v3 - with: - name: build-artifact - path: dist - self-mutation: - needs: build - runs-on: ubuntu-latest - permissions: - contents: write - if: always() && needs.build.outputs.self_mutation_happened && !(github.event.pull_request.head.repo.full_name != github.repository) - steps: - - name: Checkout - uses: actions/checkout@v3 - with: - token: ${{ secrets.PROJEN_GITHUB_TOKEN }} - ref: ${{ github.event.pull_request.head.ref }} - repository: ${{ github.event.pull_request.head.repo.full_name }} - - name: Download patch - uses: actions/download-artifact@v3 - with: - name: .repo.patch - path: ${{ runner.temp }} - - name: Apply patch - run: '[ -s ${{ runner.temp }}/.repo.patch ] && git apply ${{ runner.temp }}/.repo.patch || echo "Empty patch. Skipping."' - - name: Set git identity - run: |- - git config user.name "github-actions" - git config user.email "github-actions@github.com" - - name: Push changes - env: - PULL_REQUEST_REF: ${{ github.event.pull_request.head.ref }} - run: |- - git add . - git commit -s -m "chore: self mutation" - git push origin HEAD:$PULL_REQUEST_REF - package-js: - needs: build - runs-on: ubuntu-latest - permissions: {} - if: "! needs.build.outputs.self_mutation_happened" - steps: - - uses: actions/setup-node@v3 - with: - node-version: 16.x - - name: Download build artifacts - uses: actions/download-artifact@v3 - with: - name: build-artifact - path: dist - - name: Restore build artifact permissions - run: cd dist && setfacl --restore=permissions-backup.acl - continue-on-error: true - - name: Prepare Repository - run: mv dist .repo - - name: Install Dependencies - run: cd .repo && yarn install --check-files --frozen-lockfile - - name: Create js artifact - run: cd .repo && npx projen package:js - - name: Collect js Artifact - run: mv .repo/dist dist diff --git a/typescript/ec2-instance-connect-endpoint/.github/workflows/pull-request-lint.yml b/typescript/ec2-instance-connect-endpoint/.github/workflows/pull-request-lint.yml deleted file mode 100644 index 062108a6d7..0000000000 --- a/typescript/ec2-instance-connect-endpoint/.github/workflows/pull-request-lint.yml +++ /dev/null @@ -1,28 +0,0 @@ -# ~~ Generated by projen. To modify, edit .projenrc.ts and run "npx projen". - -name: pull-request-lint -on: - pull_request_target: - types: - - labeled - - opened - - synchronize - - reopened - - ready_for_review - - edited -jobs: - validate: - name: Validate PR title - runs-on: ubuntu-latest - permissions: - pull-requests: write - steps: - - uses: amannn/action-semantic-pull-request@v5.0.2 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - types: |- - feat - fix - chore - requireScope: false diff --git a/typescript/ec2-instance-connect-endpoint/.github/workflows/release.yml b/typescript/ec2-instance-connect-endpoint/.github/workflows/release.yml deleted file mode 100644 index 0ac463f555..0000000000 --- a/typescript/ec2-instance-connect-endpoint/.github/workflows/release.yml +++ /dev/null @@ -1,109 +0,0 @@ -# ~~ Generated by projen. To modify, edit .projenrc.ts and run "npx projen". - -name: release -on: - push: - branches: - - main - workflow_dispatch: {} -jobs: - release: - runs-on: ubuntu-latest - permissions: - contents: write - outputs: - latest_commit: ${{ steps.git_remote.outputs.latest_commit }} - env: - CI: "true" - steps: - - name: Checkout - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - name: Set git identity - run: |- - git config user.name "github-actions" - git config user.email "github-actions@github.com" - - name: Setup Node.js - uses: actions/setup-node@v3 - with: - node-version: 16.x - - name: Install dependencies - run: yarn install --check-files --frozen-lockfile - - name: release - run: npx projen release - - name: Check for new commits - id: git_remote - run: echo "latest_commit=$(git ls-remote origin -h ${{ github.ref }} | cut -f1)" >> $GITHUB_OUTPUT - - name: Backup artifact permissions - if: ${{ steps.git_remote.outputs.latest_commit == github.sha }} - run: cd dist && getfacl -R . > permissions-backup.acl - continue-on-error: true - - name: Upload artifact - if: ${{ steps.git_remote.outputs.latest_commit == github.sha }} - uses: actions/upload-artifact@v3 - with: - name: build-artifact - path: dist - release_github: - name: Publish to GitHub Releases - needs: release - runs-on: ubuntu-latest - permissions: - contents: write - if: needs.release.outputs.latest_commit == github.sha - steps: - - uses: actions/setup-node@v3 - with: - node-version: 16.x - - name: Download build artifacts - uses: actions/download-artifact@v3 - with: - name: build-artifact - path: dist - - name: Restore build artifact permissions - run: cd dist && setfacl --restore=permissions-backup.acl - continue-on-error: true - - name: Prepare Repository - run: mv dist .repo - - name: Collect GitHub Metadata - run: mv .repo/dist dist - - name: Release - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - GITHUB_REPOSITORY: ${{ github.repository }} - GITHUB_REF: ${{ github.ref }} - run: errout=$(mktemp); gh release create $(cat dist/releasetag.txt) -R $GITHUB_REPOSITORY -F dist/changelog.md -t $(cat dist/releasetag.txt) --target $GITHUB_REF 2> $errout && true; exitcode=$?; if [ $exitcode -ne 0 ] && ! grep -q "Release.tag_name already exists" $errout; then cat $errout; exit $exitcode; fi - release_npm: - name: Publish to npm - needs: release - runs-on: ubuntu-latest - permissions: - contents: read - if: needs.release.outputs.latest_commit == github.sha - steps: - - uses: actions/setup-node@v3 - with: - node-version: 16.x - - name: Download build artifacts - uses: actions/download-artifact@v3 - with: - name: build-artifact - path: dist - - name: Restore build artifact permissions - run: cd dist && setfacl --restore=permissions-backup.acl - continue-on-error: true - - name: Prepare Repository - run: mv dist .repo - - name: Install Dependencies - run: cd .repo && yarn install --check-files --frozen-lockfile - - name: Create js artifact - run: cd .repo && npx projen package:js - - name: Collect js Artifact - run: mv .repo/dist dist - - name: Release - env: - NPM_DIST_TAG: latest - NPM_REGISTRY: registry.npmjs.org - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - run: npx -p publib@latest publib-npm diff --git a/typescript/ec2-instance-connect-endpoint/.github/workflows/upgrade-main.yml b/typescript/ec2-instance-connect-endpoint/.github/workflows/upgrade-main.yml deleted file mode 100644 index 6b7068b5ca..0000000000 --- a/typescript/ec2-instance-connect-endpoint/.github/workflows/upgrade-main.yml +++ /dev/null @@ -1,90 +0,0 @@ -# ~~ Generated by projen. To modify, edit .projenrc.ts and run "npx projen". - -name: upgrade-main -on: - workflow_dispatch: {} - schedule: - - cron: 0 0 * * * -jobs: - upgrade: - name: Upgrade - runs-on: ubuntu-latest - permissions: - contents: read - outputs: - patch_created: ${{ steps.create_patch.outputs.patch_created }} - steps: - - name: Checkout - uses: actions/checkout@v3 - with: - ref: main - - name: Setup Node.js - uses: actions/setup-node@v3 - with: - node-version: 16.x - - name: Install dependencies - run: yarn install --check-files --frozen-lockfile - - name: Upgrade dependencies - run: npx projen upgrade - - name: Find mutations - id: create_patch - run: |- - git add . - git diff --staged --patch --exit-code > .repo.patch || echo "patch_created=true" >> $GITHUB_OUTPUT - - name: Upload patch - if: steps.create_patch.outputs.patch_created - uses: actions/upload-artifact@v3 - with: - name: .repo.patch - path: .repo.patch - pr: - name: Create Pull Request - needs: upgrade - runs-on: ubuntu-latest - permissions: - contents: read - if: ${{ needs.upgrade.outputs.patch_created }} - steps: - - name: Checkout - uses: actions/checkout@v3 - with: - ref: main - - name: Download patch - uses: actions/download-artifact@v3 - with: - name: .repo.patch - path: ${{ runner.temp }} - - name: Apply patch - run: '[ -s ${{ runner.temp }}/.repo.patch ] && git apply ${{ runner.temp }}/.repo.patch || echo "Empty patch. Skipping."' - - name: Set git identity - run: |- - git config user.name "github-actions" - git config user.email "github-actions@github.com" - - name: Create Pull Request - id: create-pr - uses: peter-evans/create-pull-request@v4 - with: - token: ${{ secrets.PROJEN_GITHUB_TOKEN }} - commit-message: |- - chore(deps): upgrade dependencies - - Upgrades project dependencies. See details in [workflow run]. - - [Workflow Run]: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} - - ------ - - *Automatically created by projen via the "upgrade-main" workflow* - branch: github-actions/upgrade-main - title: "chore(deps): upgrade dependencies" - body: |- - Upgrades project dependencies. See details in [workflow run]. - - [Workflow Run]: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} - - ------ - - *Automatically created by projen via the "upgrade-main" workflow* - author: github-actions - committer: github-actions - signoff: true diff --git a/typescript/ec2-instance-connect-endpoint/.gitignore b/typescript/ec2-instance-connect-endpoint/.gitignore deleted file mode 100644 index 323b836a97..0000000000 --- a/typescript/ec2-instance-connect-endpoint/.gitignore +++ /dev/null @@ -1,57 +0,0 @@ -# ~~ Generated by projen. To modify, edit .projenrc.ts and run "npx projen". -!/.gitattributes -!/.projen/tasks.json -!/.projen/deps.json -!/.projen/files.json -!/.github/workflows/pull-request-lint.yml -!/package.json -!/LICENSE -!/.npmignore -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -lerna-debug.log* -report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json -pids -*.pid -*.seed -*.pid.lock -lib-cov -coverage -*.lcov -.nyc_output -build/Release -node_modules/ -jspm_packages/ -*.tsbuildinfo -.eslintcache -*.tgz -.yarn-integrity -.cache -!/.projenrc.js -/test-reports/ -junit.xml -/coverage/ -!/.github/workflows/build.yml -/dist/changelog.md -/dist/version.txt -!/.github/workflows/release.yml -!/.mergify.yml -!/.github/workflows/upgrade-main.yml -!/.github/pull_request_template.md -!/.npmrc -!/test/ -!/tsconfig.dev.json -!/src/ -/lib -/dist/ -!/.eslintrc.json -.jsii -tsconfig.json -!/API.md -!/cdk.json -cdk.out -cdk.context.json -yarn-error.log diff --git a/typescript/ec2-instance-connect-endpoint/.mergify.yml b/typescript/ec2-instance-connect-endpoint/.mergify.yml deleted file mode 100644 index 154b39fa50..0000000000 --- a/typescript/ec2-instance-connect-endpoint/.mergify.yml +++ /dev/null @@ -1,26 +0,0 @@ -# ~~ Generated by projen. To modify, edit .projenrc.ts and run "npx projen". - -queue_rules: - - name: default - update_method: merge - conditions: - - "#approved-reviews-by>=1" - - -label~=(do-not-merge) - - status-success=build - - status-success=package-js -pull_request_rules: - - name: Automatic merge on approval and successful build - actions: - delete_head_branch: {} - queue: - method: squash - name: default - commit_message_template: |- - {{ title }} (#{{ number }}) - - {{ body }} - conditions: - - "#approved-reviews-by>=1" - - -label~=(do-not-merge) - - status-success=build - - status-success=package-js diff --git a/typescript/ec2-instance-connect-endpoint/.projen/deps.json b/typescript/ec2-instance-connect-endpoint/.projen/deps.json deleted file mode 100644 index 000bc96bf3..0000000000 --- a/typescript/ec2-instance-connect-endpoint/.projen/deps.json +++ /dev/null @@ -1,133 +0,0 @@ -{ - "dependencies": [ - { - "name": "@types/jest", - "type": "build" - }, - { - "name": "@types/node", - "version": "^16", - "type": "build" - }, - { - "name": "@typescript-eslint/eslint-plugin", - "version": "^5", - "type": "build" - }, - { - "name": "@typescript-eslint/parser", - "version": "^5", - "type": "build" - }, - { - "name": "aws-cdk-lib", - "version": "2.85.0", - "type": "build" - }, - { - "name": "aws-cdk", - "version": "2.85.0", - "type": "build" - }, - { - "name": "constructs", - "version": "10.0.5", - "type": "build" - }, - { - "name": "eslint-import-resolver-node", - "type": "build" - }, - { - "name": "eslint-import-resolver-typescript", - "type": "build" - }, - { - "name": "eslint-plugin-import", - "type": "build" - }, - { - "name": "eslint", - "version": "^8", - "type": "build" - }, - { - "name": "jest", - "type": "build" - }, - { - "name": "jest-junit", - "version": "^15", - "type": "build" - }, - { - "name": "jsii-diff", - "type": "build" - }, - { - "name": "jsii-docgen", - "type": "build" - }, - { - "name": "jsii-pacmak", - "type": "build" - }, - { - "name": "jsii-rosetta", - "version": "~5.0.0", - "type": "build" - }, - { - "name": "jsii", - "version": "~5.0.0", - "type": "build" - }, - { - "name": "npm-check-updates", - "version": "^16", - "type": "build" - }, - { - "name": "projen", - "type": "build" - }, - { - "name": "standard-version", - "version": "^9", - "type": "build" - }, - { - "name": "ts-jest", - "type": "build" - }, - { - "name": "ts-node", - "type": "build" - }, - { - "name": "typescript", - "type": "build" - }, - { - "name": "aws-cdk-lib", - "version": "^2.85.0", - "type": "peer" - }, - { - "name": "constructs", - "version": "^10.0.5", - "type": "peer" - }, - { - "name": "@aws-cdk/aws-lambda-python-alpha", - "version": "^2.85.0-alpha.0", - "type": "runtime" - }, - { - "name": "@aws-cdk/integ-tests-alpha", - "version": "^2.85.0-alpha.0", - "type": "runtime" - } - ], - "//": "~~ Generated by projen. To modify, edit .projenrc.ts and run \"npx projen\"." -} diff --git a/typescript/ec2-instance-connect-endpoint/.projen/files.json b/typescript/ec2-instance-connect-endpoint/.projen/files.json deleted file mode 100644 index 4be0fa682e..0000000000 --- a/typescript/ec2-instance-connect-endpoint/.projen/files.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "files": [ - ".eslintrc.json", - ".gitattributes", - ".github/pull_request_template.md", - ".github/workflows/build.yml", - ".github/workflows/pull-request-lint.yml", - ".github/workflows/release.yml", - ".github/workflows/upgrade-main.yml", - ".gitignore", - ".mergify.yml", - ".npmrc", - ".projen/deps.json", - ".projen/files.json", - ".projen/tasks.json", - "cdk.json", - "LICENSE", - "tsconfig.dev.json" - ], - "//": "~~ Generated by projen. To modify, edit .projenrc.ts and run \"npx projen\"." -} diff --git a/typescript/ec2-instance-connect-endpoint/.projen/tasks.json b/typescript/ec2-instance-connect-endpoint/.projen/tasks.json deleted file mode 100644 index 14d7f9be68..0000000000 --- a/typescript/ec2-instance-connect-endpoint/.projen/tasks.json +++ /dev/null @@ -1,310 +0,0 @@ -{ - "tasks": { - "build": { - "name": "build", - "description": "Full release build", - "steps": [ - { - "spawn": "default" - }, - { - "spawn": "pre-compile" - }, - { - "spawn": "compile" - }, - { - "spawn": "post-compile" - }, - { - "spawn": "test" - }, - { - "spawn": "package" - } - ] - }, - "bump": { - "name": "bump", - "description": "Bumps version based on latest git tag and generates a changelog entry", - "env": { - "OUTFILE": "package.json", - "CHANGELOG": "dist/changelog.md", - "BUMPFILE": "dist/version.txt", - "RELEASETAG": "dist/releasetag.txt", - "RELEASE_TAG_PREFIX": "" - }, - "steps": [ - { - "builtin": "release/bump-version" - } - ], - "condition": "! git log --oneline -1 | grep -q \"chore(release):\"" - }, - "clobber": { - "name": "clobber", - "description": "hard resets to HEAD of origin and cleans the local repo", - "env": { - "BRANCH": "$(git branch --show-current)" - }, - "steps": [ - { - "exec": "git checkout -b scratch", - "name": "save current HEAD in \"scratch\" branch" - }, - { - "exec": "git checkout $BRANCH" - }, - { - "exec": "git fetch origin", - "name": "fetch latest changes from origin" - }, - { - "exec": "git reset --hard origin/$BRANCH", - "name": "hard reset to origin commit" - }, - { - "exec": "git clean -fdx", - "name": "clean all untracked files" - }, - { - "say": "ready to rock! (unpushed commits are under the \"scratch\" branch)" - } - ], - "condition": "git diff --exit-code > /dev/null" - }, - "compat": { - "name": "compat", - "description": "Perform API compatibility check against latest version", - "steps": [ - { - "exec": "jsii-diff npm:$(node -p \"require('./package.json').name\") -k --ignore-file .compatignore || (echo \"\nUNEXPECTED BREAKING CHANGES: add keys such as 'removed:constructs.Node.of' to .compatignore to skip.\n\" && exit 1)" - } - ] - }, - "compile": { - "name": "compile", - "description": "Only compile", - "steps": [ - { - "exec": "jsii --silence-warnings=reserved-word" - } - ] - }, - "default": { - "name": "default", - "description": "Synthesize project files", - "steps": [ - { - "exec": "ts-node --project tsconfig.dev.json .projenrc.ts" - } - ] - }, - "docgen": { - "name": "docgen", - "description": "Generate API.md from .jsii manifest", - "steps": [ - { - "exec": "jsii-docgen -o API.md" - } - ] - }, - "eject": { - "name": "eject", - "description": "Remove projen from the project", - "env": { - "PROJEN_EJECTING": "true" - }, - "steps": [ - { - "spawn": "default" - } - ] - }, - "eslint": { - "name": "eslint", - "description": "Runs eslint against the codebase", - "steps": [ - { - "exec": "eslint --ext .ts,.tsx --fix --no-error-on-unmatched-pattern src test build-tools projenrc .projenrc.ts --parser-options={tsconfigRootDir:null}" - } - ] - }, - "install": { - "name": "install", - "description": "Install project dependencies and update lockfile (non-frozen)", - "steps": [ - { - "exec": "yarn install --check-files" - } - ] - }, - "install:ci": { - "name": "install:ci", - "description": "Install project dependencies using frozen lockfile", - "steps": [ - { - "exec": "yarn install --check-files --frozen-lockfile" - } - ] - }, - "package": { - "name": "package", - "description": "Creates the distribution package", - "steps": [ - { - "exec": "if [ ! -z ${CI} ]; then rsync -a . .repo --exclude .git --exclude node_modules && rm -rf dist && mv .repo dist; else npx projen package-all; fi" - } - ] - }, - "package-all": { - "name": "package-all", - "description": "Packages artifacts for all target languages", - "steps": [ - { - "spawn": "package:js" - } - ] - }, - "package:js": { - "name": "package:js", - "description": "Create js language bindings", - "steps": [ - { - "exec": "jsii-pacmak -v --target js" - } - ] - }, - "post-compile": { - "name": "post-compile", - "description": "Runs after successful compilation", - "steps": [ - { - "spawn": "docgen" - } - ] - }, - "post-upgrade": { - "name": "post-upgrade", - "description": "Runs after upgrading dependencies" - }, - "pre-compile": { - "name": "pre-compile", - "description": "Prepare the project for compilation" - }, - "release": { - "name": "release", - "description": "Prepare a release from \"main\" branch", - "env": { - "RELEASE": "true" - }, - "steps": [ - { - "exec": "rm -fr dist" - }, - { - "spawn": "bump" - }, - { - "spawn": "build" - }, - { - "spawn": "unbump" - }, - { - "exec": "git diff --ignore-space-at-eol --exit-code" - } - ] - }, - "test": { - "name": "test", - "description": "Run tests", - "steps": [ - { - "exec": "jest --passWithNoTests --updateSnapshot", - "receiveArgs": true - }, - { - "spawn": "eslint" - } - ] - }, - "test:watch": { - "name": "test:watch", - "description": "Run jest in watch mode", - "steps": [ - { - "exec": "jest --watch" - } - ] - }, - "unbump": { - "name": "unbump", - "description": "Restores version to 0.0.0", - "env": { - "OUTFILE": "package.json", - "CHANGELOG": "dist/changelog.md", - "BUMPFILE": "dist/version.txt", - "RELEASETAG": "dist/releasetag.txt", - "RELEASE_TAG_PREFIX": "" - }, - "steps": [ - { - "builtin": "release/reset-version" - } - ] - }, - "upgrade": { - "name": "upgrade", - "description": "upgrade dependencies", - "env": { - "CI": "0" - }, - "steps": [ - { - "exec": "yarn upgrade npm-check-updates" - }, - { - "exec": "npm-check-updates --dep dev --upgrade --target=minor --reject='aws-cdk-lib,aws-cdk,constructs,jsii-rosetta,jsii'" - }, - { - "exec": "npm-check-updates --dep optional --upgrade --target=minor --reject='aws-cdk-lib,aws-cdk,constructs,jsii-rosetta,jsii'" - }, - { - "exec": "npm-check-updates --dep peer --upgrade --target=minor --reject='aws-cdk-lib,aws-cdk,constructs,jsii-rosetta,jsii'" - }, - { - "exec": "npm-check-updates --dep prod --upgrade --target=minor --reject='aws-cdk-lib,aws-cdk,constructs,jsii-rosetta,jsii'" - }, - { - "exec": "npm-check-updates --dep bundle --upgrade --target=minor --reject='aws-cdk-lib,aws-cdk,constructs,jsii-rosetta,jsii'" - }, - { - "exec": "yarn install --check-files" - }, - { - "exec": "yarn upgrade" - }, - { - "exec": "npx projen" - }, - { - "spawn": "post-upgrade" - } - ] - }, - "watch": { - "name": "watch", - "description": "Watch & compile in the background", - "steps": [ - { - "exec": "jsii -w --silence-warnings=reserved-word" - } - ] - } - }, - "env": { - "PATH": "$(npx -c \"node --print process.env.PATH\")" - }, - "//": "~~ Generated by projen. To modify, edit .projenrc.ts and run \"npx projen\"." -} diff --git a/typescript/ec2-instance-connect-endpoint/.projenrc.ts b/typescript/ec2-instance-connect-endpoint/.projenrc.ts deleted file mode 100644 index be005479cc..0000000000 --- a/typescript/ec2-instance-connect-endpoint/.projenrc.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { awscdk, JsonFile } from 'projen'; -const project = new awscdk.AwsCdkConstructLibrary({ - author: 'Pahud Hsieh', - authorAddress: 'pahudnet@gmail.com', - cdkVersion: '2.85.0', - defaultReleaseBranch: 'main', - jsiiVersion: '~5.0.0', - name: 'ec2-instance-connect-endpoint', - projenrcTs: true, - repositoryUrl: 'https://github.com/aws-samples/aws-cdk-examples.git', - deps: [ - '@aws-cdk/integ-tests-alpha@^2.85.0-alpha.0', - '@aws-cdk/aws-lambda-python-alpha@^2.85.0-alpha.0', - ], - devDeps: [ - 'aws-cdk@2.85.0', - ], -}); - -// required for vscode eslint extension to locate the tsconfig correctly -project.eslint!.config.parserOptions.tsconfigRootDir = 'typescript/ec2-instance-connect-endpoint'; -/** - * reset tsconfigRootDir to null as a workaround for eslint CLI - * see https://github.com/typescript-eslint/typescript-eslint/issues/251#issuecomment-493187240 - */ -const tasksJson = project.tryFindObjectFile('.projen/tasks.json')!; -tasksJson.addOverride('tasks.eslint.steps.0.exec', 'eslint --ext .ts,.tsx --fix --no-error-on-unmatched-pattern src test build-tools projenrc .projenrc.ts --parser-options={tsconfigRootDir:null}'); - -new JsonFile(project, 'cdk.json', { - obj: { - app: 'npx ts-node --prefer-ts-exts src/integ.default.ts', - }, -}); - -const common_exclude = ['cdk.out', 'cdk.context.json', 'yarn-error.log']; -project.npmignore?.exclude(...common_exclude); -project.gitignore.exclude(...common_exclude); - -project.synth(); \ No newline at end of file diff --git a/typescript/ec2-instance-connect-endpoint/LICENSE b/typescript/ec2-instance-connect-endpoint/LICENSE deleted file mode 100644 index d645695673..0000000000 --- a/typescript/ec2-instance-connect-endpoint/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/typescript/ec2-instance-connect-endpoint/cdk.json b/typescript/ec2-instance-connect-endpoint/cdk.json index de39f2e1ed..f818b2a3da 100644 --- a/typescript/ec2-instance-connect-endpoint/cdk.json +++ b/typescript/ec2-instance-connect-endpoint/cdk.json @@ -1,4 +1,3 @@ { - "app": "npx ts-node --prefer-ts-exts src/integ.default.ts", - "//": "~~ Generated by projen. To modify, edit .projenrc.ts and run \"npx projen\"." + "app": "npx ts-node --prefer-ts-exts src/integ.default.ts" } diff --git a/typescript/ec2-instance-connect-endpoint/package.json b/typescript/ec2-instance-connect-endpoint/package.json index a7548fe071..cdcb68154f 100644 --- a/typescript/ec2-instance-connect-endpoint/package.json +++ b/typescript/ec2-instance-connect-endpoint/package.json @@ -1,60 +1,30 @@ { "name": "ec2-instance-connect-endpoint", + "version": "0.0.0", "repository": { "type": "git", "url": "https://github.com/aws-samples/aws-cdk-examples.git" }, "scripts": { - "build": "npx projen build", - "bump": "npx projen bump", - "clobber": "npx projen clobber", - "compat": "npx projen compat", - "compile": "npx projen compile", - "default": "npx projen default", - "docgen": "npx projen docgen", - "eject": "npx projen eject", - "eslint": "npx projen eslint", - "package": "npx projen package", - "package-all": "npx projen package-all", - "package:js": "npx projen package:js", - "post-compile": "npx projen post-compile", - "post-upgrade": "npx projen post-upgrade", - "pre-compile": "npx projen pre-compile", - "release": "npx projen release", - "test": "npx projen test", - "test:watch": "npx projen test:watch", - "unbump": "npx projen unbump", - "upgrade": "npx projen upgrade", - "watch": "npx projen watch", - "projen": "npx projen" + "build": "tsc", + "watch": "tsc -w", + "test": "jest", + "cdk": "cdk" }, "author": { "name": "Pahud Hsieh", - "email": "pahudnet@gmail.com", - "organization": false + "email": "pahudnet@gmail.com" }, "devDependencies": { "@types/jest": "^29.5.14", - "@types/node": "22.7.9", + "@types/node": "^16", "@typescript-eslint/eslint-plugin": "^5", "@typescript-eslint/parser": "^5", - "aws-cdk": "2.1004.0", + "aws-cdk": "2.85.0", "aws-cdk-lib": "2.85.0", "constructs": "10.0.5", "eslint": "^8", - "eslint-import-resolver-node": "^0.3.7", - "eslint-import-resolver-typescript": "^3.5.5", - "eslint-plugin-import": "^2.27.5", "jest": "^29.7.0", - "jest-junit": "^15", - "jsii": "~5.0.0", - "jsii-diff": "^1.84.0", - "jsii-docgen": "^9.0.14", - "jsii-pacmak": "^1.84.0", - "jsii-rosetta": "~5.0.0", - "npm-check-updates": "^16", - "projen": "^0.71.118", - "standard-version": "^9", "ts-jest": "^29.2.5", "ts-node": "^10.9.2", "typescript": "~5.6.3" @@ -71,57 +41,6 @@ "cdk" ], "main": "lib/index.js", - "license": "Apache-2.0", - "version": "0.0.0", - "jest": { - "testMatch": [ - "/src/**/__tests__/**/*.ts?(x)", - "/(test|src)/**/*(*.)@(spec|test).ts?(x)" - ], - "clearMocks": true, - "collectCoverage": true, - "coverageReporters": [ - "json", - "lcov", - "clover", - "cobertura", - "text" - ], - "coverageDirectory": "coverage", - "coveragePathIgnorePatterns": [ - "/node_modules/" - ], - "testPathIgnorePatterns": [ - "/node_modules/" - ], - "watchPathIgnorePatterns": [ - "/node_modules/" - ], - "reporters": [ - "default", - [ - "jest-junit", - { - "outputDirectory": "test-reports" - } - ] - ], - "preset": "ts-jest", - "globals": { - "ts-jest": { - "tsconfig": "tsconfig.dev.json" - } - } - }, "types": "lib/index.d.ts", - "stability": "stable", - "jsii": { - "outdir": "dist", - "targets": {}, - "tsc": { - "outDir": "lib", - "rootDir": "src" - } - }, - "//": "~~ Generated by projen. To modify, edit .projenrc.ts and run \"npx projen\"." + "license": "Apache-2.0" } diff --git a/typescript/ec2-instance-connect-endpoint/test-reports/junit.xml b/typescript/ec2-instance-connect-endpoint/test-reports/junit.xml new file mode 100644 index 0000000000..d82c4289dc --- /dev/null +++ b/typescript/ec2-instance-connect-endpoint/test-reports/junit.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/typescript/ec2-instance-connect-endpoint/tsconfig.dev.json b/typescript/ec2-instance-connect-endpoint/tsconfig.dev.json deleted file mode 100644 index 88cc2f2f33..0000000000 --- a/typescript/ec2-instance-connect-endpoint/tsconfig.dev.json +++ /dev/null @@ -1,38 +0,0 @@ -// ~~ Generated by projen. To modify, edit .projenrc.ts and run "npx projen". -{ - "compilerOptions": { - "alwaysStrict": true, - "declaration": true, - "esModuleInterop": true, - "experimentalDecorators": true, - "inlineSourceMap": true, - "inlineSources": true, - "lib": [ - "es2019" - ], - "module": "CommonJS", - "noEmitOnError": false, - "noFallthroughCasesInSwitch": true, - "noImplicitAny": true, - "noImplicitReturns": true, - "noImplicitThis": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "resolveJsonModule": true, - "strict": true, - "strictNullChecks": true, - "strictPropertyInitialization": true, - "stripInternal": true, - "target": "ES2019" - }, - "include": [ - ".projenrc.js", - "src/**/*.ts", - "test/**/*.ts", - ".projenrc.ts", - "projenrc/**/*.ts" - ], - "exclude": [ - "node_modules" - ] -} diff --git a/typescript/ec2-instance/tsconfig.dev.json b/typescript/ec2-instance-connect-endpoint/tsconfig.json similarity index 65% rename from typescript/ec2-instance/tsconfig.dev.json rename to typescript/ec2-instance-connect-endpoint/tsconfig.json index 3bd3671661..93d89c09f9 100644 --- a/typescript/ec2-instance/tsconfig.dev.json +++ b/typescript/ec2-instance-connect-endpoint/tsconfig.json @@ -1,17 +1,19 @@ -// ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". { "compilerOptions": { + "outDir": "lib", + "rootDir": "src", + "declarationMap": false, + "inlineSourceMap": true, + "inlineSources": true, "alwaysStrict": true, "declaration": true, - "esModuleInterop": true, "experimentalDecorators": true, - "inlineSourceMap": true, - "inlineSources": true, + "incremental": true, "lib": [ - "es2019" + "es2020" ], "module": "CommonJS", - "noEmitOnError": false, + "noEmitOnError": true, "noFallthroughCasesInSwitch": true, "noImplicitAny": true, "noImplicitReturns": true, @@ -19,16 +21,17 @@ "noUnusedLocals": true, "noUnusedParameters": true, "resolveJsonModule": true, + "skipLibCheck": true, "strict": true, "strictNullChecks": true, "strictPropertyInitialization": true, - "stripInternal": true, - "target": "ES2019" + "stripInternal": false, + "target": "ES2020", + "composite": false, + "tsBuildInfoFile": "lib/tsconfig.tsbuildinfo" }, "include": [ - ".projenrc.js", - "src/**/*.ts", - "test/**/*.ts" + "src/**/*.ts" ], "exclude": [ "node_modules" diff --git a/typescript/ec2-instance/.gitattributes b/typescript/ec2-instance/.gitattributes deleted file mode 100644 index 37f8188eea..0000000000 --- a/typescript/ec2-instance/.gitattributes +++ /dev/null @@ -1,23 +0,0 @@ -# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". - -*.snap linguist-generated -/.eslintrc.json linguist-generated -/.gitattributes linguist-generated -/.github/pull_request_template.md linguist-generated -/.github/workflows/build.yml linguist-generated -/.github/workflows/pull-request-lint.yml linguist-generated -/.github/workflows/upgrade.yml linguist-generated -/.gitignore linguist-generated -/.mergify.yml linguist-generated -/.npmignore linguist-generated -/.npmrc linguist-generated -/.projen/** linguist-generated -/.projen/deps.json linguist-generated -/.projen/files.json linguist-generated -/.projen/tasks.json linguist-generated -/cdk.json linguist-generated -/LICENSE linguist-generated -/package.json linguist-generated -/tsconfig.dev.json linguist-generated -/tsconfig.json linguist-generated -/yarn.lock linguist-generated \ No newline at end of file diff --git a/typescript/ec2-instance/.github/pull_request_template.md b/typescript/ec2-instance/.github/pull_request_template.md deleted file mode 100644 index 11d479bcae..0000000000 --- a/typescript/ec2-instance/.github/pull_request_template.md +++ /dev/null @@ -1 +0,0 @@ -Fixes # \ No newline at end of file diff --git a/typescript/ec2-instance/.github/workflows/build.yml b/typescript/ec2-instance/.github/workflows/build.yml deleted file mode 100644 index 574ad74475..0000000000 --- a/typescript/ec2-instance/.github/workflows/build.yml +++ /dev/null @@ -1,73 +0,0 @@ -# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". - -name: build -on: - pull_request: {} - workflow_dispatch: {} -jobs: - build: - runs-on: ubuntu-latest - permissions: - contents: write - outputs: - self_mutation_happened: ${{ steps.self_mutation.outputs.self_mutation_happened }} - env: - CI: "true" - steps: - - name: Checkout - uses: actions/checkout@v3 - with: - ref: ${{ github.event.pull_request.head.ref }} - repository: ${{ github.event.pull_request.head.repo.full_name }} - - name: Install dependencies - run: yarn install --check-files - - name: build - run: npx projen build - - name: Find mutations - id: self_mutation - run: |- - git add . - git diff --staged --patch --exit-code > .repo.patch || echo "self_mutation_happened=true" >> $GITHUB_OUTPUT - - name: Upload patch - if: steps.self_mutation.outputs.self_mutation_happened - uses: actions/upload-artifact@v3 - with: - name: .repo.patch - path: .repo.patch - - name: Fail build on mutation - if: steps.self_mutation.outputs.self_mutation_happened - run: |- - echo "::error::Files were changed during build (see build log). If this was triggered from a fork, you will need to update your branch." - cat .repo.patch - exit 1 - self-mutation: - needs: build - runs-on: ubuntu-latest - permissions: - contents: write - if: always() && needs.build.outputs.self_mutation_happened && !(github.event.pull_request.head.repo.full_name != github.repository) - steps: - - name: Checkout - uses: actions/checkout@v3 - with: - token: ${{ secrets.PROJEN_GITHUB_TOKEN }} - ref: ${{ github.event.pull_request.head.ref }} - repository: ${{ github.event.pull_request.head.repo.full_name }} - - name: Download patch - uses: actions/download-artifact@v3 - with: - name: .repo.patch - path: ${{ runner.temp }} - - name: Apply patch - run: '[ -s ${{ runner.temp }}/.repo.patch ] && git apply ${{ runner.temp }}/.repo.patch || echo "Empty patch. Skipping."' - - name: Set git identity - run: |- - git config user.name "github-actions" - git config user.email "github-actions@github.com" - - name: Push changes - env: - PULL_REQUEST_REF: ${{ github.event.pull_request.head.ref }} - run: |- - git add . - git commit -s -m "chore: self mutation" - git push origin HEAD:$PULL_REQUEST_REF diff --git a/typescript/ec2-instance/.github/workflows/pull-request-lint.yml b/typescript/ec2-instance/.github/workflows/pull-request-lint.yml deleted file mode 100644 index 6758951b5f..0000000000 --- a/typescript/ec2-instance/.github/workflows/pull-request-lint.yml +++ /dev/null @@ -1,29 +0,0 @@ -# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". - -name: pull-request-lint -on: - pull_request_target: - types: - - labeled - - opened - - synchronize - - reopened - - ready_for_review - - edited -jobs: - validate: - name: Validate PR title - runs-on: ubuntu-latest - permissions: - pull-requests: write - steps: - - uses: amannn/action-semantic-pull-request@v5.0.2 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - types: |- - feat - fix - chore - requireScope: false - githubBaseUrl: ${{ github.api_url }} diff --git a/typescript/ec2-instance/.github/workflows/upgrade.yml b/typescript/ec2-instance/.github/workflows/upgrade.yml deleted file mode 100644 index cb5ff07110..0000000000 --- a/typescript/ec2-instance/.github/workflows/upgrade.yml +++ /dev/null @@ -1,83 +0,0 @@ -# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". - -name: upgrade -on: - workflow_dispatch: {} - schedule: - - cron: 0 0 * * * -jobs: - upgrade: - name: Upgrade - runs-on: ubuntu-latest - permissions: - contents: read - outputs: - patch_created: ${{ steps.create_patch.outputs.patch_created }} - steps: - - name: Checkout - uses: actions/checkout@v3 - - name: Install dependencies - run: yarn install --check-files --frozen-lockfile - - name: Upgrade dependencies - run: npx projen upgrade - - name: Find mutations - id: create_patch - run: |- - git add . - git diff --staged --patch --exit-code > .repo.patch || echo "patch_created=true" >> $GITHUB_OUTPUT - - name: Upload patch - if: steps.create_patch.outputs.patch_created - uses: actions/upload-artifact@v3 - with: - name: .repo.patch - path: .repo.patch - pr: - name: Create Pull Request - needs: upgrade - runs-on: ubuntu-latest - permissions: - contents: read - if: ${{ needs.upgrade.outputs.patch_created }} - steps: - - name: Checkout - uses: actions/checkout@v3 - with: {} - - name: Download patch - uses: actions/download-artifact@v3 - with: - name: .repo.patch - path: ${{ runner.temp }} - - name: Apply patch - run: '[ -s ${{ runner.temp }}/.repo.patch ] && git apply ${{ runner.temp }}/.repo.patch || echo "Empty patch. Skipping."' - - name: Set git identity - run: |- - git config user.name "github-actions" - git config user.email "github-actions@github.com" - - name: Create Pull Request - id: create-pr - uses: peter-evans/create-pull-request@v4 - with: - token: ${{ secrets.PROJEN_GITHUB_TOKEN }} - commit-message: |- - chore(deps): upgrade dependencies - - Upgrades project dependencies. See details in [workflow run]. - - [Workflow Run]: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} - - ------ - - *Automatically created by projen via the "upgrade" workflow* - branch: github-actions/upgrade - title: "chore(deps): upgrade dependencies" - body: |- - Upgrades project dependencies. See details in [workflow run]. - - [Workflow Run]: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} - - ------ - - *Automatically created by projen via the "upgrade" workflow* - author: github-actions - committer: github-actions - signoff: true diff --git a/typescript/ec2-instance/.gitignore b/typescript/ec2-instance/.gitignore deleted file mode 100644 index aa5c82deaf..0000000000 --- a/typescript/ec2-instance/.gitignore +++ /dev/null @@ -1,58 +0,0 @@ -# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". -!/.gitattributes -!/.projen/tasks.json -!/.projen/deps.json -!/.projen/files.json -!/.github/workflows/pull-request-lint.yml -!/package.json -!/LICENSE -!/.npmignore -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -lerna-debug.log* -report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json -pids -*.pid -*.seed -*.pid.lock -lib-cov -coverage -*.lcov -.nyc_output -build/Release -node_modules/ -jspm_packages/ -*.tsbuildinfo -.eslintcache -*.tgz -.yarn-integrity -.cache -!/.projenrc.js -/test-reports/ -junit.xml -/coverage/ -!/.github/workflows/build.yml -!/.mergify.yml -!/.github/workflows/upgrade.yml -!/.github/pull_request_template.md -!/.npmrc -!/test/ -!/tsconfig.json -!/tsconfig.dev.json -!/src/ -/lib -/dist/ -!/.eslintrc.json -/assets/ -!/cdk.json -/cdk.out/ -.cdk.staging/ -.parcel-cache/ -cdk.out -cdk.context.json -yarn-error.log -dependabot.yml -.DS_Store diff --git a/typescript/ec2-instance/.mergify.yml b/typescript/ec2-instance/.mergify.yml deleted file mode 100644 index d0f90113d9..0000000000 --- a/typescript/ec2-instance/.mergify.yml +++ /dev/null @@ -1,24 +0,0 @@ -# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". - -queue_rules: - - name: default - update_method: merge - conditions: - - "#approved-reviews-by>=1" - - -label~=(do-not-merge) - - status-success=build -pull_request_rules: - - name: Automatic merge on approval and successful build - actions: - delete_head_branch: {} - queue: - method: squash - name: default - commit_message_template: |- - {{ title }} (#{{ number }}) - - {{ body }} - conditions: - - "#approved-reviews-by>=1" - - -label~=(do-not-merge) - - status-success=build diff --git a/typescript/ec2-instance/.projen/deps.json b/typescript/ec2-instance/.projen/deps.json deleted file mode 100644 index 5fe1e1397f..0000000000 --- a/typescript/ec2-instance/.projen/deps.json +++ /dev/null @@ -1,94 +0,0 @@ -{ - "dependencies": [ - { - "name": "@types/jest", - "type": "build" - }, - { - "name": "@types/node", - "version": "^16", - "type": "build" - }, - { - "name": "@typescript-eslint/eslint-plugin", - "version": "^5", - "type": "build" - }, - { - "name": "@typescript-eslint/parser", - "version": "^5", - "type": "build" - }, - { - "name": "aws-cdk", - "version": "^2.83.0", - "type": "build" - }, - { - "name": "esbuild", - "type": "build" - }, - { - "name": "eslint-import-resolver-node", - "type": "build" - }, - { - "name": "eslint-import-resolver-typescript", - "type": "build" - }, - { - "name": "eslint-plugin-import", - "type": "build" - }, - { - "name": "eslint", - "version": "^8", - "type": "build" - }, - { - "name": "jest", - "type": "build" - }, - { - "name": "jest-junit", - "version": "^15", - "type": "build" - }, - { - "name": "npm-check-updates", - "version": "^16", - "type": "build" - }, - { - "name": "projen", - "type": "build" - }, - { - "name": "ts-jest", - "type": "build" - }, - { - "name": "ts-node", - "type": "build" - }, - { - "name": "typescript", - "type": "build" - }, - { - "name": "aws-cdk-lib", - "version": "^2.83.0", - "type": "runtime" - }, - { - "name": "constructs", - "version": "^10.0.5", - "type": "runtime" - }, - { - "name": "dotenv", - "type": "runtime" - } - ], - "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." -} diff --git a/typescript/ec2-instance/.projen/files.json b/typescript/ec2-instance/.projen/files.json deleted file mode 100644 index ce0b501142..0000000000 --- a/typescript/ec2-instance/.projen/files.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "files": [ - ".eslintrc.json", - ".gitattributes", - ".github/pull_request_template.md", - ".github/workflows/build.yml", - ".github/workflows/pull-request-lint.yml", - ".github/workflows/upgrade.yml", - ".gitignore", - ".mergify.yml", - ".npmignore", - ".npmrc", - ".projen/deps.json", - ".projen/files.json", - ".projen/tasks.json", - "cdk.json", - "LICENSE", - "tsconfig.dev.json", - "tsconfig.json" - ], - "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." -} diff --git a/typescript/ec2-instance/.projen/tasks.json b/typescript/ec2-instance/.projen/tasks.json deleted file mode 100644 index eb86dc14f1..0000000000 --- a/typescript/ec2-instance/.projen/tasks.json +++ /dev/null @@ -1,269 +0,0 @@ -{ - "tasks": { - "build": { - "name": "build", - "description": "Full release build", - "steps": [ - { - "spawn": "default" - }, - { - "spawn": "pre-compile" - }, - { - "spawn": "compile" - }, - { - "spawn": "post-compile" - }, - { - "spawn": "test" - }, - { - "spawn": "package" - } - ] - }, - "bundle": { - "name": "bundle", - "description": "Prepare assets" - }, - "clobber": { - "name": "clobber", - "description": "hard resets to HEAD of origin and cleans the local repo", - "env": { - "BRANCH": "$(git branch --show-current)" - }, - "steps": [ - { - "exec": "git checkout -b scratch", - "name": "save current HEAD in \"scratch\" branch" - }, - { - "exec": "git checkout $BRANCH" - }, - { - "exec": "git fetch origin", - "name": "fetch latest changes from origin" - }, - { - "exec": "git reset --hard origin/$BRANCH", - "name": "hard reset to origin commit" - }, - { - "exec": "git clean -fdx", - "name": "clean all untracked files" - }, - { - "say": "ready to rock! (unpushed commits are under the \"scratch\" branch)" - } - ], - "condition": "git diff --exit-code > /dev/null" - }, - "compile": { - "name": "compile", - "description": "Only compile" - }, - "default": { - "name": "default", - "description": "Synthesize project files", - "steps": [ - { - "exec": "node .projenrc.js" - } - ] - }, - "deploy": { - "name": "deploy", - "description": "Deploys your CDK app to the AWS cloud", - "steps": [ - { - "exec": "cdk deploy", - "receiveArgs": true - } - ] - }, - "destroy": { - "name": "destroy", - "description": "Destroys your cdk app in the AWS cloud", - "steps": [ - { - "exec": "cdk destroy", - "receiveArgs": true - } - ] - }, - "diff": { - "name": "diff", - "description": "Diffs the currently deployed app against your code", - "steps": [ - { - "exec": "cdk diff" - } - ] - }, - "eject": { - "name": "eject", - "description": "Remove projen from the project", - "env": { - "PROJEN_EJECTING": "true" - }, - "steps": [ - { - "spawn": "default" - } - ] - }, - "eslint": { - "name": "eslint", - "description": "Runs eslint against the codebase", - "steps": [ - { - "exec": "eslint --ext .ts,.tsx --fix --no-error-on-unmatched-pattern src test build-tools .projenrc.js" - } - ] - }, - "install": { - "name": "install", - "description": "Install project dependencies and update lockfile (non-frozen)", - "steps": [ - { - "exec": "yarn install --check-files" - } - ] - }, - "install:ci": { - "name": "install:ci", - "description": "Install project dependencies using frozen lockfile", - "steps": [ - { - "exec": "yarn install --check-files --frozen-lockfile" - } - ] - }, - "launch": { - "name": "launch", - "steps": [ - { - "exec": "yarn && yarn projen && yarn build && yarn cdk bootstrap && yarn cdk deploy --require-approval never" - } - ] - }, - "package": { - "name": "package", - "description": "Creates the distribution package" - }, - "post-compile": { - "name": "post-compile", - "description": "Runs after successful compilation", - "steps": [ - { - "spawn": "synth:silent" - } - ] - }, - "post-upgrade": { - "name": "post-upgrade", - "description": "Runs after upgrading dependencies" - }, - "pre-compile": { - "name": "pre-compile", - "description": "Prepare the project for compilation" - }, - "synth": { - "name": "synth", - "description": "Synthesizes your cdk app into cdk.out", - "steps": [ - { - "exec": "cdk synth" - } - ] - }, - "synth:silent": { - "name": "synth:silent", - "description": "Synthesizes your cdk app into cdk.out and suppresses the template in stdout (part of \"yarn build\")", - "steps": [ - { - "exec": "cdk synth -q" - } - ] - }, - "test": { - "name": "test", - "description": "Run tests", - "steps": [ - { - "exec": "jest --passWithNoTests --updateSnapshot", - "receiveArgs": true - }, - { - "spawn": "eslint" - } - ] - }, - "test:watch": { - "name": "test:watch", - "description": "Run jest in watch mode", - "steps": [ - { - "exec": "jest --watch" - } - ] - }, - "upgrade": { - "name": "upgrade", - "description": "upgrade dependencies", - "env": { - "CI": "0" - }, - "steps": [ - { - "exec": "yarn upgrade npm-check-updates" - }, - { - "exec": "npm-check-updates --dep dev --upgrade --target=minor" - }, - { - "exec": "npm-check-updates --dep bundle --upgrade --target=minor" - }, - { - "exec": "npm-check-updates --dep peer --upgrade --target=minor" - }, - { - "exec": "npm-check-updates --dep prod --upgrade --target=minor" - }, - { - "exec": "npm-check-updates --dep optional --upgrade --target=minor" - }, - { - "exec": "yarn install --check-files" - }, - { - "exec": "yarn upgrade @types/jest @types/node @typescript-eslint/eslint-plugin @typescript-eslint/parser aws-cdk esbuild eslint-import-resolver-node eslint-import-resolver-typescript eslint-plugin-import eslint jest jest-junit npm-check-updates projen ts-jest ts-node typescript aws-cdk-lib constructs dotenv" - }, - { - "exec": "npx projen" - }, - { - "spawn": "post-upgrade" - } - ] - }, - "watch": { - "name": "watch", - "description": "Watches changes in your source code and rebuilds and deploys to the current account", - "steps": [ - { - "exec": "cdk deploy --hotswap" - }, - { - "exec": "cdk watch" - } - ] - } - }, - "env": { - "PATH": "$(npx -c \"node --print process.env.PATH\")" - }, - "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." -} diff --git a/typescript/ec2-instance/.projenrc.js b/typescript/ec2-instance/.projenrc.js deleted file mode 100644 index b9dae9e1ef..0000000000 --- a/typescript/ec2-instance/.projenrc.js +++ /dev/null @@ -1,27 +0,0 @@ -const { awscdk } = require('projen'); -const project = new awscdk.AwsCdkTypeScriptApp({ - cdkVersion: '2.83.0', - license: 'MIT-0', - author: 'Court Schuett', - copyrightOwner: 'Amazon.com, Inc.', - authorAddress: 'https://aws.amazon.com', - appEntrypoint: 'ec2-instance.ts', - name: 'ec2-instance', - eslintOptions: { ignorePatterns: ['resources/**'] }, - devDeps: ['esbuild'], - defaultReleaseBranch: 'master', - deps: ['dotenv'], -}); - -const common_exclude = [ - 'cdk.out', - 'cdk.context.json', - 'yarn-error.log', - 'dependabot.yml', - '.DS_Store', -]; -project.addTask('launch', { - exec: 'yarn && yarn projen && yarn build && yarn cdk bootstrap && yarn cdk deploy --require-approval never', -}); -project.gitignore.exclude(...common_exclude); -project.synth(); diff --git a/typescript/ec2-instance/cdk.json b/typescript/ec2-instance/cdk.json index e1f07214b7..c35feae3c7 100644 --- a/typescript/ec2-instance/cdk.json +++ b/typescript/ec2-instance/cdk.json @@ -1,11 +1,8 @@ { - "app": "npx ts-node -P tsconfig.json --prefer-ts-exts src/ec2-instance.ts", - "output": "cdk.out", - "build": "npx projen bundle", + "app": "npx ts-node --prefer-ts-exts src/ec2-instance.ts", "watch": { "include": [ - "src/**/*.ts", - "test/**/*.ts" + "**" ], "exclude": [ "README.md", @@ -15,8 +12,40 @@ "tsconfig.json", "package*.json", "yarn.lock", - "node_modules" + "node_modules", + "test" ] }, - "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." -} + "context": { + "@aws-cdk/aws-lambda:recognizeLayerVersion": true, + "@aws-cdk/core:checkSecretUsage": true, + "@aws-cdk/core:target-partitions": [ + "aws", + "aws-cn" + ], + "@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true, + "@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true, + "@aws-cdk/aws-ecs:arnFormatIncludesClusterName": true, + "@aws-cdk/aws-iam:minimizePolicies": true, + "@aws-cdk/core:validateSnapshotRemovalPolicy": true, + "@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": true, + "@aws-cdk/aws-s3:createDefaultLoggingPolicy": true, + "@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": true, + "@aws-cdk/aws-apigateway:disableCloudWatchRole": true, + "@aws-cdk/core:enablePartitionLiterals": true, + "@aws-cdk/aws-events:eventsTargetQueueSameAccount": true, + "@aws-cdk/aws-iam:standardizedServicePrincipals": true, + "@aws-cdk/aws-ecs:disableExplicitDeploymentControllerForCircuitBreaker": true, + "@aws-cdk/aws-iam:importedRoleStackSafeDefaultPolicyName": true, + "@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy": true, + "@aws-cdk/aws-route53-patters:useCertificate": true, + "@aws-cdk/customresources:installLatestAwsSdkDefault": false, + "@aws-cdk/aws-rds:databaseProxyUniqueResourceName": true, + "@aws-cdk/aws-codedeploy:removeAlarmsFromDeploymentGroup": true, + "@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId": true, + "@aws-cdk/aws-ec2:launchTemplateDefaultUserData": true, + "@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments": true, + "@aws-cdk/aws-redshift:columnId": true, + "@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2": true + } +} \ No newline at end of file diff --git a/typescript/ec2-instance/package.json b/typescript/ec2-instance/package.json index 7f9051a6f9..3b11025568 100644 --- a/typescript/ec2-instance/package.json +++ b/typescript/ec2-instance/package.json @@ -1,94 +1,32 @@ { "name": "ec2-instance", + "version": "0.0.0", "scripts": { - "build": "npx projen build", - "bundle": "npx projen bundle", - "clobber": "npx projen clobber", - "compile": "npx projen compile", - "default": "npx projen default", - "deploy": "npx projen deploy", - "destroy": "npx projen destroy", - "diff": "npx projen diff", - "eject": "npx projen eject", - "eslint": "npx projen eslint", - "launch": "npx projen launch", - "package": "npx projen package", - "post-compile": "npx projen post-compile", - "post-upgrade": "npx projen post-upgrade", - "pre-compile": "npx projen pre-compile", - "synth": "npx projen synth", - "synth:silent": "npx projen synth:silent", - "test": "npx projen test", - "test:watch": "npx projen test:watch", - "upgrade": "npx projen upgrade", - "watch": "npx projen watch", - "projen": "npx projen" + "build": "tsc", + "watch": "tsc -w", + "test": "jest", + "cdk": "cdk" }, "devDependencies": { "@types/jest": "^29.5.14", - "@types/node": "22.7.9", + "@types/node": "^16", "@typescript-eslint/eslint-plugin": "^5", "@typescript-eslint/parser": "^5", - "aws-cdk": "2.1004.0", - "esbuild": "^0.18.17", + "aws-cdk": "^2.83.0", "eslint": "^8", "eslint-import-resolver-node": "^0.3.7", "eslint-import-resolver-typescript": "^3.5.5", "eslint-plugin-import": "^2.28.0", "jest": "^29.7.0", "jest-junit": "^15", - "npm-check-updates": "^16", - "projen": "^0.71.158", "ts-jest": "^29.2.5", "ts-node": "^10.9.2", "typescript": "~5.6.3" }, "dependencies": { - "aws-cdk-lib": "2.185.0", - "constructs": "^10.0.0", + "aws-cdk-lib": "^2.83.0", + "constructs": "^10.0.5", "dotenv": "^16.3.1" }, - "license": "MIT-0", - "version": "0.0.0", - "jest": { - "testMatch": [ - "/src/**/__tests__/**/*.ts?(x)", - "/(test|src)/**/*(*.)@(spec|test).ts?(x)" - ], - "clearMocks": true, - "collectCoverage": true, - "coverageReporters": [ - "json", - "lcov", - "clover", - "cobertura", - "text" - ], - "coverageDirectory": "coverage", - "coveragePathIgnorePatterns": [ - "/node_modules/" - ], - "testPathIgnorePatterns": [ - "/node_modules/" - ], - "watchPathIgnorePatterns": [ - "/node_modules/" - ], - "reporters": [ - "default", - [ - "jest-junit", - { - "outputDirectory": "test-reports" - } - ] - ], - "preset": "ts-jest", - "globals": { - "ts-jest": { - "tsconfig": "tsconfig.dev.json" - } - } - }, - "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." + "license": "MIT-0" } diff --git a/typescript/ec2-instance/test-reports/junit.xml b/typescript/ec2-instance/test-reports/junit.xml new file mode 100644 index 0000000000..52c0568337 --- /dev/null +++ b/typescript/ec2-instance/test-reports/junit.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/typescript/ec2-instance/tsconfig.json b/typescript/ec2-instance/tsconfig.json index c96331d0d5..130298dff5 100644 --- a/typescript/ec2-instance/tsconfig.json +++ b/typescript/ec2-instance/tsconfig.json @@ -1,36 +1,25 @@ -// ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". { "compilerOptions": { - "rootDir": "src", - "outDir": "lib", - "alwaysStrict": true, + "target": "ES2018", + "module": "commonjs", + "lib": ["es2018"], "declaration": true, - "esModuleInterop": true, - "experimentalDecorators": true, - "inlineSourceMap": true, - "inlineSources": true, - "lib": [ - "es2019" - ], - "module": "CommonJS", - "noEmitOnError": false, - "noFallthroughCasesInSwitch": true, - "noImplicitAny": true, - "noImplicitReturns": true, - "noImplicitThis": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "resolveJsonModule": true, "strict": true, + "noImplicitAny": true, "strictNullChecks": true, - "strictPropertyInitialization": true, - "stripInternal": true, - "target": "ES2019" + "noImplicitThis": true, + "alwaysStrict": true, + "noUnusedLocals": false, + "noUnusedParameters": false, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": false, + "inlineSourceMap": true, + "inlineSources": true, + "experimentalDecorators": true, + "strictPropertyInitialization": false, + "typeRoots": ["./node_modules/@types"], + "outDir": "dist", + "rootDir": "src" }, - "include": [ - "src/**/*.ts" - ], - "exclude": [ - "cdk.out" - ] + "exclude": ["node_modules", "cdk.out", "dist"] } diff --git a/typescript/ec2-ssm-local-zone/test/__snapshots__/example-localzone-stack.test.ts.snap b/typescript/ec2-ssm-local-zone/test/__snapshots__/example-localzone-stack.test.ts.snap index 10462f64b4..3d32063fad 100644 --- a/typescript/ec2-ssm-local-zone/test/__snapshots__/example-localzone-stack.test.ts.snap +++ b/typescript/ec2-ssm-local-zone/test/__snapshots__/example-localzone-stack.test.ts.snap @@ -376,6 +376,12 @@ sudo iptables-save", "Ref": "VpcprivateSubnet1SubnetCEAD3716", }, ], + "Tags": [ + { + "Key": "Name", + "Value": "ExampleLocalZoneStack/Vpc", + }, + ], "VpcEndpointType": "Interface", "VpcId": { "Ref": "Vpc8378EB38", @@ -703,6 +709,12 @@ sudo iptables-save", "Ref": "VpcprivateSubnet1SubnetCEAD3716", }, ], + "Tags": [ + { + "Key": "Name", + "Value": "ExampleLocalZoneStack/Vpc", + }, + ], "VpcEndpointType": "Interface", "VpcId": { "Ref": "Vpc8378EB38", @@ -788,6 +800,12 @@ sudo iptables-save", "Ref": "VpcprivateSubnet1SubnetCEAD3716", }, ], + "Tags": [ + { + "Key": "Name", + "Value": "ExampleLocalZoneStack/Vpc", + }, + ], "VpcEndpointType": "Interface", "VpcId": { "Ref": "Vpc8378EB38", diff --git a/typescript/inspector2/jest.config.js b/typescript/inspector2/jest.config.js new file mode 100644 index 0000000000..c4f95b0aea --- /dev/null +++ b/typescript/inspector2/jest.config.js @@ -0,0 +1,12 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const config = { + testEnvironment: 'node', + roots: ['/test'], + testMatch: ['**/*.test.ts'], + transform: { + '^.+\\.tsx?$': 'ts-jest' + } +}; +exports.default = config; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiamVzdC5jb25maWcuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJqZXN0LmNvbmZpZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUVBLE1BQU0sTUFBTSxHQUFXO0lBQ3JCLGVBQWUsRUFBRSxNQUFNO0lBQ3ZCLEtBQUssRUFBRSxDQUFDLGdCQUFnQixDQUFDO0lBQ3pCLFNBQVMsRUFBRSxDQUFDLGNBQWMsQ0FBQztJQUMzQixTQUFTLEVBQUU7UUFDVCxhQUFhLEVBQUUsU0FBUztLQUN6QjtDQUNGLENBQUM7QUFDRixrQkFBZSxNQUFNLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSB7IENvbmZpZyB9IGZyb20gJ2plc3QnO1xuXG5jb25zdCBjb25maWc6IENvbmZpZyA9IHtcbiAgdGVzdEVudmlyb25tZW50OiAnbm9kZScsXG4gIHJvb3RzOiBbJzxyb290RGlyPi90ZXN0J10sXG4gIHRlc3RNYXRjaDogWycqKi8qLnRlc3QudHMnXSxcbiAgdHJhbnNmb3JtOiB7XG4gICAgJ14uK1xcXFwudHN4PyQnOiAndHMtamVzdCdcbiAgfVxufTtcbmV4cG9ydCBkZWZhdWx0IGNvbmZpZztcbiJdfQ== \ No newline at end of file diff --git a/typescript/inspector2/test/__snapshots__/inspector2-enable-delegated-admin-account-resource.test.ts.snap b/typescript/inspector2/test/__snapshots__/inspector2-enable-delegated-admin-account-resource.test.ts.snap index 771eefa2e5..adb5bb4b0c 100644 --- a/typescript/inspector2/test/__snapshots__/inspector2-enable-delegated-admin-account-resource.test.ts.snap +++ b/typescript/inspector2/test/__snapshots__/inspector2-enable-delegated-admin-account-resource.test.ts.snap @@ -3,105 +3,126 @@ exports[`Inspector2EnableDelegatedAdminAccountResource creates required resources 1`] = ` { "Mappings": { - "DefaultCrNodeVersionMap": { + "LatestNodeRuntimeMap": { "af-south-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "ap-east-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "ap-northeast-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "ap-northeast-2": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "ap-northeast-3": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "ap-south-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "ap-south-2": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "ap-southeast-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "ap-southeast-2": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "ap-southeast-3": { - "value": "nodejs16.x", + "value": "nodejs20.x", + }, + "ap-southeast-4": { + "value": "nodejs20.x", + }, + "ap-southeast-5": { + "value": "nodejs20.x", + }, + "ap-southeast-7": { + "value": "nodejs20.x", }, "ca-central-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", + }, + "ca-west-1": { + "value": "nodejs20.x", }, "cn-north-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "cn-northwest-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "eu-central-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "eu-central-2": { - "value": "nodejs16.x", + "value": "nodejs20.x", + }, + "eu-isoe-west-1": { + "value": "nodejs18.x", }, "eu-north-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "eu-south-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "eu-south-2": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "eu-west-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "eu-west-2": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "eu-west-3": { - "value": "nodejs16.x", + "value": "nodejs20.x", + }, + "il-central-1": { + "value": "nodejs20.x", }, "me-central-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "me-south-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", + }, + "mx-central-1": { + "value": "nodejs20.x", }, "sa-east-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "us-east-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "us-east-2": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "us-gov-east-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "us-gov-west-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "us-iso-east-1": { - "value": "nodejs14.x", + "value": "nodejs18.x", }, "us-iso-west-1": { - "value": "nodejs14.x", + "value": "nodejs18.x", }, "us-isob-east-1": { - "value": "nodejs14.x", + "value": "nodejs18.x", }, "us-west-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "us-west-2": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, }, }, @@ -122,9 +143,10 @@ exports[`Inspector2EnableDelegatedAdminAccountResource creates required resource "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}", }, - "S3Key": "bb459fac5f6b4b052aac9803443226d161a5cfe96f4648b21f9e4912c698bf30.zip", + "S3Key": "4cd2f2411231aa073e609dc99a49b5c5e974252bf9abf0f9350d237d17cce8be.zip", }, "Handler": "index.handler", + "MemorySize": 512, "Role": { "Fn::GetAtt": [ "Inspector2EnableDelegatedAdminAccountResourceInspector2EnableResourceInspectorRole00253606", @@ -133,7 +155,7 @@ exports[`Inspector2EnableDelegatedAdminAccountResource creates required resource }, "Runtime": { "Fn::FindInMap": [ - "DefaultCrNodeVersionMap", + "LatestNodeRuntimeMap", { "Ref": "AWS::Region", }, diff --git a/typescript/inspector2/test/__snapshots__/inspector2-enable-resources.test.ts.snap b/typescript/inspector2/test/__snapshots__/inspector2-enable-resources.test.ts.snap index 841830cd08..0ae21d5c31 100644 --- a/typescript/inspector2/test/__snapshots__/inspector2-enable-resources.test.ts.snap +++ b/typescript/inspector2/test/__snapshots__/inspector2-enable-resources.test.ts.snap @@ -3,105 +3,126 @@ exports[`Inspector2EnableResource creates required resources 1`] = ` { "Mappings": { - "DefaultCrNodeVersionMap": { + "LatestNodeRuntimeMap": { "af-south-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "ap-east-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "ap-northeast-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "ap-northeast-2": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "ap-northeast-3": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "ap-south-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "ap-south-2": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "ap-southeast-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "ap-southeast-2": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "ap-southeast-3": { - "value": "nodejs16.x", + "value": "nodejs20.x", + }, + "ap-southeast-4": { + "value": "nodejs20.x", + }, + "ap-southeast-5": { + "value": "nodejs20.x", + }, + "ap-southeast-7": { + "value": "nodejs20.x", }, "ca-central-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", + }, + "ca-west-1": { + "value": "nodejs20.x", }, "cn-north-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "cn-northwest-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "eu-central-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "eu-central-2": { - "value": "nodejs16.x", + "value": "nodejs20.x", + }, + "eu-isoe-west-1": { + "value": "nodejs18.x", }, "eu-north-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "eu-south-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "eu-south-2": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "eu-west-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "eu-west-2": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "eu-west-3": { - "value": "nodejs16.x", + "value": "nodejs20.x", + }, + "il-central-1": { + "value": "nodejs20.x", }, "me-central-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "me-south-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", + }, + "mx-central-1": { + "value": "nodejs20.x", }, "sa-east-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "us-east-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "us-east-2": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "us-gov-east-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "us-gov-west-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "us-iso-east-1": { - "value": "nodejs14.x", + "value": "nodejs18.x", }, "us-iso-west-1": { - "value": "nodejs14.x", + "value": "nodejs18.x", }, "us-isob-east-1": { - "value": "nodejs14.x", + "value": "nodejs18.x", }, "us-west-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "us-west-2": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, }, }, @@ -122,9 +143,10 @@ exports[`Inspector2EnableResource creates required resources 1`] = ` "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}", }, - "S3Key": "bb459fac5f6b4b052aac9803443226d161a5cfe96f4648b21f9e4912c698bf30.zip", + "S3Key": "4cd2f2411231aa073e609dc99a49b5c5e974252bf9abf0f9350d237d17cce8be.zip", }, "Handler": "index.handler", + "MemorySize": 512, "Role": { "Fn::GetAtt": [ "EnableInspector2ResourceInspectorRole75753456", @@ -133,7 +155,7 @@ exports[`Inspector2EnableResource creates required resources 1`] = ` }, "Runtime": { "Fn::FindInMap": [ - "DefaultCrNodeVersionMap", + "LatestNodeRuntimeMap", { "Ref": "AWS::Region", }, @@ -236,7 +258,7 @@ exports[`Inspector2EnableResource creates required resources 1`] = ` "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}", }, - "S3Key": "5fa1330271b8967d9254ba2d4a07144f8acefe8b77e6d6bba38261373a50d5f8.zip", + "S3Key": "2819175352ad1ce0dae768e83fc328fb70fb5f10b4a8ff0ccbcb791f02b0716d.zip", }, "Handler": "index.handler", "Role": { @@ -247,13 +269,14 @@ exports[`Inspector2EnableResource creates required resources 1`] = ` }, "Runtime": { "Fn::FindInMap": [ - "DefaultCrNodeVersionMap", + "LatestNodeRuntimeMap", { "Ref": "AWS::Region", }, "value", ], }, + "Timeout": 900, }, "Type": "AWS::Lambda::Function", }, diff --git a/typescript/inspector2/test/__snapshots__/inspector2-monitoring-resource.test.ts.snap b/typescript/inspector2/test/__snapshots__/inspector2-monitoring-resource.test.ts.snap index 0c8df3d09d..84c1e9f9f5 100644 --- a/typescript/inspector2/test/__snapshots__/inspector2-monitoring-resource.test.ts.snap +++ b/typescript/inspector2/test/__snapshots__/inspector2-monitoring-resource.test.ts.snap @@ -3,105 +3,126 @@ exports[`Inspector2MonitoringResource creates required resources 1`] = ` { "Mappings": { - "DefaultCrNodeVersionMap": { + "LatestNodeRuntimeMap": { "af-south-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "ap-east-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "ap-northeast-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "ap-northeast-2": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "ap-northeast-3": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "ap-south-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "ap-south-2": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "ap-southeast-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "ap-southeast-2": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "ap-southeast-3": { - "value": "nodejs16.x", + "value": "nodejs20.x", + }, + "ap-southeast-4": { + "value": "nodejs20.x", + }, + "ap-southeast-5": { + "value": "nodejs20.x", + }, + "ap-southeast-7": { + "value": "nodejs20.x", }, "ca-central-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", + }, + "ca-west-1": { + "value": "nodejs20.x", }, "cn-north-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "cn-northwest-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "eu-central-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "eu-central-2": { - "value": "nodejs16.x", + "value": "nodejs20.x", + }, + "eu-isoe-west-1": { + "value": "nodejs18.x", }, "eu-north-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "eu-south-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "eu-south-2": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "eu-west-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "eu-west-2": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "eu-west-3": { - "value": "nodejs16.x", + "value": "nodejs20.x", + }, + "il-central-1": { + "value": "nodejs20.x", }, "me-central-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "me-south-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", + }, + "mx-central-1": { + "value": "nodejs20.x", }, "sa-east-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "us-east-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "us-east-2": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "us-gov-east-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "us-gov-west-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "us-iso-east-1": { - "value": "nodejs14.x", + "value": "nodejs18.x", }, "us-iso-west-1": { - "value": "nodejs14.x", + "value": "nodejs18.x", }, "us-isob-east-1": { - "value": "nodejs14.x", + "value": "nodejs18.x", }, "us-west-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "us-west-2": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, }, }, @@ -124,11 +145,6 @@ exports[`Inspector2MonitoringResource creates required resources 1`] = ` }, "S3Key": "387c7c1f429cca9662171575d60cec88ab73d6da0e9d197558cbc4bbd665bb6e.zip", }, - "Environment": { - "Variables": { - "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", - }, - }, "Handler": "index.handler", "Role": { "Fn::GetAtt": [ @@ -206,11 +222,6 @@ exports[`Inspector2MonitoringResource creates required resources 1`] = ` }, "S3Key": "08c8f1505ccfb98c41cb39e43e5ec867fcb42aee41bba9ea3bb3ca27a3025c0c.zip", }, - "Environment": { - "Variables": { - "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", - }, - }, "Handler": "index.handler", "Role": { "Fn::GetAtt": [ @@ -385,7 +396,7 @@ exports[`Inspector2MonitoringResource creates required resources 1`] = ` "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}", }, - "S3Key": "5fa1330271b8967d9254ba2d4a07144f8acefe8b77e6d6bba38261373a50d5f8.zip", + "S3Key": "2819175352ad1ce0dae768e83fc328fb70fb5f10b4a8ff0ccbcb791f02b0716d.zip", }, "Handler": "index.handler", "Role": { @@ -396,13 +407,14 @@ exports[`Inspector2MonitoringResource creates required resources 1`] = ` }, "Runtime": { "Fn::FindInMap": [ - "DefaultCrNodeVersionMap", + "LatestNodeRuntimeMap", { "Ref": "AWS::Region", }, "value", ], }, + "Timeout": 900, }, "Type": "AWS::Lambda::Function", }, diff --git a/typescript/inspector2/test/__snapshots__/inspector2-update-org-config-resource.test.ts.snap b/typescript/inspector2/test/__snapshots__/inspector2-update-org-config-resource.test.ts.snap index 837e5d18d6..bb330bfdaa 100644 --- a/typescript/inspector2/test/__snapshots__/inspector2-update-org-config-resource.test.ts.snap +++ b/typescript/inspector2/test/__snapshots__/inspector2-update-org-config-resource.test.ts.snap @@ -3,105 +3,126 @@ exports[`Inspector2UpdateOrganizationConfigurationResource creates required resources 1`] = ` { "Mappings": { - "DefaultCrNodeVersionMap": { + "LatestNodeRuntimeMap": { "af-south-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "ap-east-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "ap-northeast-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "ap-northeast-2": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "ap-northeast-3": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "ap-south-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "ap-south-2": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "ap-southeast-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "ap-southeast-2": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "ap-southeast-3": { - "value": "nodejs16.x", + "value": "nodejs20.x", + }, + "ap-southeast-4": { + "value": "nodejs20.x", + }, + "ap-southeast-5": { + "value": "nodejs20.x", + }, + "ap-southeast-7": { + "value": "nodejs20.x", }, "ca-central-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", + }, + "ca-west-1": { + "value": "nodejs20.x", }, "cn-north-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "cn-northwest-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "eu-central-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "eu-central-2": { - "value": "nodejs16.x", + "value": "nodejs20.x", + }, + "eu-isoe-west-1": { + "value": "nodejs18.x", }, "eu-north-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "eu-south-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "eu-south-2": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "eu-west-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "eu-west-2": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "eu-west-3": { - "value": "nodejs16.x", + "value": "nodejs20.x", + }, + "il-central-1": { + "value": "nodejs20.x", }, "me-central-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "me-south-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", + }, + "mx-central-1": { + "value": "nodejs20.x", }, "sa-east-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "us-east-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "us-east-2": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "us-gov-east-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "us-gov-west-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "us-iso-east-1": { - "value": "nodejs14.x", + "value": "nodejs18.x", }, "us-iso-west-1": { - "value": "nodejs14.x", + "value": "nodejs18.x", }, "us-isob-east-1": { - "value": "nodejs14.x", + "value": "nodejs18.x", }, "us-west-1": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, "us-west-2": { - "value": "nodejs16.x", + "value": "nodejs20.x", }, }, }, @@ -122,9 +143,10 @@ exports[`Inspector2UpdateOrganizationConfigurationResource creates required reso "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}", }, - "S3Key": "bb459fac5f6b4b052aac9803443226d161a5cfe96f4648b21f9e4912c698bf30.zip", + "S3Key": "4cd2f2411231aa073e609dc99a49b5c5e974252bf9abf0f9350d237d17cce8be.zip", }, "Handler": "index.handler", + "MemorySize": 512, "Role": { "Fn::GetAtt": [ "AWS679f53fac002430cb0da5b7982bd2287ServiceRoleC1EA0FF2", @@ -133,7 +155,7 @@ exports[`Inspector2UpdateOrganizationConfigurationResource creates required reso }, "Runtime": { "Fn::FindInMap": [ - "DefaultCrNodeVersionMap", + "LatestNodeRuntimeMap", { "Ref": "AWS::Region", }, From d68eee0fb8d1c17631f52c4c6b180b4003a9d230 Mon Sep 17 00:00:00 2001 From: Michael Kaiser Date: Mon, 24 Mar 2025 18:55:34 -0500 Subject: [PATCH 3/7] Fix api-gateway-lambda-token-authorizer --- .../gateway-lambda-auth-stack.test.ts.snap | 6 ++-- .../stack/gateway-lambda-auth-stack.test.ts | 35 +++++++++++++++++-- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/typescript/api-gateway-lambda-token-authorizer/test/stack/__snapshots__/gateway-lambda-auth-stack.test.ts.snap b/typescript/api-gateway-lambda-token-authorizer/test/stack/__snapshots__/gateway-lambda-auth-stack.test.ts.snap index 1ca9c87994..eca14a1665 100644 --- a/typescript/api-gateway-lambda-token-authorizer/test/stack/__snapshots__/gateway-lambda-auth-stack.test.ts.snap +++ b/typescript/api-gateway-lambda-token-authorizer/test/stack/__snapshots__/gateway-lambda-auth-stack.test.ts.snap @@ -198,7 +198,7 @@ exports[`Snapshot Stack 1`] = ` "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}", }, - "S3Key": "2819175352ad1ce0dae768e83fc328fb70fb5f10b4a8ff0ccbcb791f02b0716d.zip", + "S3Key": "NORMALIZED_ASSET_HASH.zip", }, "Handler": "index.handler", "Role": { @@ -322,7 +322,7 @@ exports[`Snapshot Stack 1`] = ` "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}", }, - "S3Key": "2ad282c80ed8bef2dc8a20da8b07e92dd5259826cca0b685f8cc11f808eca9bb.zip", + "S3Key": "NORMALIZED_ASSET_HASH.zip", }, "Description": "Lambda Authorizer", "Environment": { @@ -507,7 +507,7 @@ exports[`Snapshot Stack 1`] = ` "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}", }, - "S3Key": "dc8dcb7f07403837f3ff1672cbf17e30ee3eaa1a3a058c5397b9db8b9e964b6b.zip", + "S3Key": "NORMALIZED_ASSET_HASH.zip", }, "Description": "Operational Lambda", "Environment": { diff --git a/typescript/api-gateway-lambda-token-authorizer/test/stack/gateway-lambda-auth-stack.test.ts b/typescript/api-gateway-lambda-token-authorizer/test/stack/gateway-lambda-auth-stack.test.ts index 9f8882602e..bff535ba1e 100644 --- a/typescript/api-gateway-lambda-token-authorizer/test/stack/gateway-lambda-auth-stack.test.ts +++ b/typescript/api-gateway-lambda-token-authorizer/test/stack/gateway-lambda-auth-stack.test.ts @@ -2,14 +2,43 @@ import { App } from "aws-cdk-lib"; import { GatewayLambdaAuth } from "../../lib/stack/gateway-lambda-auth-stack"; import { Template } from "aws-cdk-lib/assertions"; -describe('Snapshot', () => { +/** + * Normalizes asset hashes in CloudFormation templates to ensure consistent snapshots + * across different environments (local vs CI/CD). + */ +function normalizeAssetHashes(template: any): any { + // Create a deep copy of the template to avoid modifying the original + const templateCopy = JSON.parse(JSON.stringify(template)); + + // Function to recursively traverse the template and replace asset hashes + function replaceAssetHashes(obj: any) { + if (!obj || typeof obj !== 'object') return; + + // Process object properties + for (const key in obj) { + if (key === 'S3Key' && typeof obj[key] === 'string' && /^[a-f0-9]{64}\.zip$/.test(obj[key])) { + // Replace asset hash with a constant placeholder + obj[key] = 'NORMALIZED_ASSET_HASH.zip'; + } else if (typeof obj[key] === 'object') { + // Recursively process nested objects and arrays + replaceAssetHashes(obj[key]); + } + } + } + + replaceAssetHashes(templateCopy); + return templateCopy; +} +describe('Snapshot', () => { it('Stack', () => { const app = new App(); const stack = new GatewayLambdaAuth(app, 'test-api-gateway-lambda-auth'); const template = Template.fromStack(stack); - expect(template.toJSON()).toMatchSnapshot(); + + // Normalize asset hashes before snapshot comparison + const normalizedTemplate = normalizeAssetHashes(template.toJSON()); + expect(normalizedTemplate).toMatchSnapshot(); }); - }) From 96d353cf5c9a0ba4cca73afc86fb20c3d16dc320 Mon Sep 17 00:00:00 2001 From: Michael Kaiser Date: Mon, 24 Mar 2025 19:05:54 -0500 Subject: [PATCH 4/7] Fix snapshot tests by normalizing asset hashes --- .../stack/gateway-lambda-auth-stack.test.ts | 35 ++----------- .../aws-transfer-sftp-server/jest.config.js | 12 +++++ .../test/aws-transfer-sftp-server.test.ts | 6 ++- .../jest.config.js | 8 +++ .../test/integ.default.test.ts | 5 +- .../tsconfig.json | 49 +++++++------------ typescript/ec2-instance/jest.config.js | 8 +++ typescript/ec2-instance/test/main.test.ts | 4 +- typescript/ec2-ssm-local-zone/jest.config.js | 12 +++++ .../test/example-localzone-stack.test.ts | 5 +- ...egated-admin-account-resource.test.ts.snap | 2 +- .../inspector2-enable-resources.test.ts.snap | 4 +- ...nspector2-monitoring-resource.test.ts.snap | 6 +-- ...r2-update-org-config-resource.test.ts.snap | 2 +- ...e-delegated-admin-account-resource.test.ts | 5 +- .../test/inspector2-enable-resources.test.ts | 5 +- .../inspector2-monitoring-resource.test.ts | 5 +- ...pector2-update-org-config-resource.test.ts | 5 +- .../jest.config.js | 12 +++++ typescript/test-utils/normalize-template.ts | 40 +++++++++++++++ 20 files changed, 153 insertions(+), 77 deletions(-) create mode 100644 typescript/aws-transfer-sftp-server/jest.config.js create mode 100644 typescript/ec2-instance-connect-endpoint/jest.config.js create mode 100644 typescript/ec2-instance/jest.config.js create mode 100644 typescript/ec2-ssm-local-zone/jest.config.js create mode 100644 typescript/s3-kms-cross-account-replication/jest.config.js create mode 100644 typescript/test-utils/normalize-template.ts diff --git a/typescript/api-gateway-lambda-token-authorizer/test/stack/gateway-lambda-auth-stack.test.ts b/typescript/api-gateway-lambda-token-authorizer/test/stack/gateway-lambda-auth-stack.test.ts index bff535ba1e..75e4f0bb21 100644 --- a/typescript/api-gateway-lambda-token-authorizer/test/stack/gateway-lambda-auth-stack.test.ts +++ b/typescript/api-gateway-lambda-token-authorizer/test/stack/gateway-lambda-auth-stack.test.ts @@ -1,44 +1,19 @@ import { App } from "aws-cdk-lib"; import { GatewayLambdaAuth } from "../../lib/stack/gateway-lambda-auth-stack"; import { Template } from "aws-cdk-lib/assertions"; - -/** - * Normalizes asset hashes in CloudFormation templates to ensure consistent snapshots - * across different environments (local vs CI/CD). - */ -function normalizeAssetHashes(template: any): any { - // Create a deep copy of the template to avoid modifying the original - const templateCopy = JSON.parse(JSON.stringify(template)); - - // Function to recursively traverse the template and replace asset hashes - function replaceAssetHashes(obj: any) { - if (!obj || typeof obj !== 'object') return; - - // Process object properties - for (const key in obj) { - if (key === 'S3Key' && typeof obj[key] === 'string' && /^[a-f0-9]{64}\.zip$/.test(obj[key])) { - // Replace asset hash with a constant placeholder - obj[key] = 'NORMALIZED_ASSET_HASH.zip'; - } else if (typeof obj[key] === 'object') { - // Recursively process nested objects and arrays - replaceAssetHashes(obj[key]); - } - } - } - - replaceAssetHashes(templateCopy); - return templateCopy; -} +import { normalizeTemplate } from "../../../test-utils/normalize-template"; describe('Snapshot', () => { + it('Stack', () => { const app = new App(); const stack = new GatewayLambdaAuth(app, 'test-api-gateway-lambda-auth'); const template = Template.fromStack(stack); - // Normalize asset hashes before snapshot comparison - const normalizedTemplate = normalizeAssetHashes(template.toJSON()); + // Normalize the template before snapshot comparison + const normalizedTemplate = normalizeTemplate(template.toJSON()); expect(normalizedTemplate).toMatchSnapshot(); }); + }) diff --git a/typescript/aws-transfer-sftp-server/jest.config.js b/typescript/aws-transfer-sftp-server/jest.config.js new file mode 100644 index 0000000000..c4f95b0aea --- /dev/null +++ b/typescript/aws-transfer-sftp-server/jest.config.js @@ -0,0 +1,12 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const config = { + testEnvironment: 'node', + roots: ['/test'], + testMatch: ['**/*.test.ts'], + transform: { + '^.+\\.tsx?$': 'ts-jest' + } +}; +exports.default = config; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiamVzdC5jb25maWcuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJqZXN0LmNvbmZpZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUVBLE1BQU0sTUFBTSxHQUFXO0lBQ3JCLGVBQWUsRUFBRSxNQUFNO0lBQ3ZCLEtBQUssRUFBRSxDQUFDLGdCQUFnQixDQUFDO0lBQ3pCLFNBQVMsRUFBRSxDQUFDLGNBQWMsQ0FBQztJQUMzQixTQUFTLEVBQUU7UUFDVCxhQUFhLEVBQUUsU0FBUztLQUN6QjtDQUNGLENBQUM7QUFDRixrQkFBZSxNQUFNLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSB7IENvbmZpZyB9IGZyb20gJ2plc3QnO1xuXG5jb25zdCBjb25maWc6IENvbmZpZyA9IHtcbiAgdGVzdEVudmlyb25tZW50OiAnbm9kZScsXG4gIHJvb3RzOiBbJzxyb290RGlyPi90ZXN0J10sXG4gIHRlc3RNYXRjaDogWycqKi8qLnRlc3QudHMnXSxcbiAgdHJhbnNmb3JtOiB7XG4gICAgJ14uK1xcXFwudHN4PyQnOiAndHMtamVzdCdcbiAgfVxufTtcbmV4cG9ydCBkZWZhdWx0IGNvbmZpZztcbiJdfQ== \ No newline at end of file diff --git a/typescript/aws-transfer-sftp-server/test/aws-transfer-sftp-server.test.ts b/typescript/aws-transfer-sftp-server/test/aws-transfer-sftp-server.test.ts index 3ed27f187a..dedeb1f3d2 100644 --- a/typescript/aws-transfer-sftp-server/test/aws-transfer-sftp-server.test.ts +++ b/typescript/aws-transfer-sftp-server/test/aws-transfer-sftp-server.test.ts @@ -4,6 +4,7 @@ import { } from 'aws-cdk-lib'; import { Template } from 'aws-cdk-lib/assertions'; import { SftpServerStack } from '../aws-transfer-sftp-server'; +import { normalizeTemplate } from '../../test-utils/normalize-template'; test('SftpServerStack has required resources', () => { const app = new cdk.App(); @@ -23,5 +24,8 @@ test('SftpServerStack has required resources', () => { dataBucket: bucket, }); - expect(Template.fromStack(stack)).toMatchSnapshot(); + // Normalize the template before snapshot comparison + const template = Template.fromStack(stack); + const normalizedTemplate = normalizeTemplate(template.toJSON()); + expect(normalizedTemplate).toMatchSnapshot(); }); diff --git a/typescript/ec2-instance-connect-endpoint/jest.config.js b/typescript/ec2-instance-connect-endpoint/jest.config.js new file mode 100644 index 0000000000..08263b8954 --- /dev/null +++ b/typescript/ec2-instance-connect-endpoint/jest.config.js @@ -0,0 +1,8 @@ +module.exports = { + testEnvironment: 'node', + roots: ['/test'], + testMatch: ['**/*.test.ts'], + transform: { + '^.+\\.tsx?$': 'ts-jest' + } +}; diff --git a/typescript/ec2-instance-connect-endpoint/test/integ.default.test.ts b/typescript/ec2-instance-connect-endpoint/test/integ.default.test.ts index 4cf3af447a..5350884124 100644 --- a/typescript/ec2-instance-connect-endpoint/test/integ.default.test.ts +++ b/typescript/ec2-instance-connect-endpoint/test/integ.default.test.ts @@ -1,11 +1,14 @@ import { Template } from 'aws-cdk-lib/assertions'; import { IntegTesting } from '../src/integ.default'; +import { normalizeTemplate } from '../../test-utils/normalize-template'; test('default validation', () => { const integ = new IntegTesting(); integ.stack.forEach(stack => { const t = Template.fromStack(stack); + // Normalize the template before snapshot comparison + const normalizedTemplate = normalizeTemplate(t.toJSON()); // should match snapshot - expect(t).toMatchSnapshot(); + expect(normalizedTemplate).toMatchSnapshot(); }); }); \ No newline at end of file diff --git a/typescript/ec2-instance-connect-endpoint/tsconfig.json b/typescript/ec2-instance-connect-endpoint/tsconfig.json index 93d89c09f9..dc6a7b03f6 100644 --- a/typescript/ec2-instance-connect-endpoint/tsconfig.json +++ b/typescript/ec2-instance-connect-endpoint/tsconfig.json @@ -1,39 +1,24 @@ { "compilerOptions": { - "outDir": "lib", - "rootDir": "src", - "declarationMap": false, - "inlineSourceMap": true, - "inlineSources": true, - "alwaysStrict": true, + "target": "ES2018", + "module": "commonjs", + "lib": ["es2018"], "declaration": true, - "experimentalDecorators": true, - "incremental": true, - "lib": [ - "es2020" - ], - "module": "CommonJS", - "noEmitOnError": true, - "noFallthroughCasesInSwitch": true, - "noImplicitAny": true, - "noImplicitReturns": true, - "noImplicitThis": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "resolveJsonModule": true, - "skipLibCheck": true, "strict": true, + "noImplicitAny": true, "strictNullChecks": true, - "strictPropertyInitialization": true, - "stripInternal": false, - "target": "ES2020", - "composite": false, - "tsBuildInfoFile": "lib/tsconfig.tsbuildinfo" + "noImplicitThis": true, + "alwaysStrict": true, + "noUnusedLocals": false, + "noUnusedParameters": false, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": false, + "inlineSourceMap": true, + "inlineSources": true, + "experimentalDecorators": true, + "strictPropertyInitialization": false, + "typeRoots": ["./node_modules/@types"], + "outDir": "dist" }, - "include": [ - "src/**/*.ts" - ], - "exclude": [ - "node_modules" - ] + "exclude": ["node_modules", "cdk.out"] } diff --git a/typescript/ec2-instance/jest.config.js b/typescript/ec2-instance/jest.config.js new file mode 100644 index 0000000000..08263b8954 --- /dev/null +++ b/typescript/ec2-instance/jest.config.js @@ -0,0 +1,8 @@ +module.exports = { + testEnvironment: 'node', + roots: ['/test'], + testMatch: ['**/*.test.ts'], + transform: { + '^.+\\.tsx?$': 'ts-jest' + } +}; diff --git a/typescript/ec2-instance/test/main.test.ts b/typescript/ec2-instance/test/main.test.ts index f07b6e448b..88021b5aea 100644 --- a/typescript/ec2-instance/test/main.test.ts +++ b/typescript/ec2-instance/test/main.test.ts @@ -2,6 +2,7 @@ import { App, Stack } from 'aws-cdk-lib'; import { Template } from 'aws-cdk-lib/assertions'; import { EC2Example } from '../src/ec2-instance'; import { InstanceSize, CPUTypes } from '../src/envValidator'; +import { normalizeTemplate } from '../../test-utils/normalize-template'; const devEnv = { account: process.env.CDK_DEFAULT_ACCOUNT, @@ -28,7 +29,8 @@ test('Snapshot', () => { }); const template = Template.fromStack(stack); - expect(template.toJSON()).toMatchSnapshot(); + const normalizedTemplate = normalizeTemplate(template.toJSON()); + expect(normalizedTemplate).toMatchSnapshot(); }); test('LARGE', () => { diff --git a/typescript/ec2-ssm-local-zone/jest.config.js b/typescript/ec2-ssm-local-zone/jest.config.js new file mode 100644 index 0000000000..c4f95b0aea --- /dev/null +++ b/typescript/ec2-ssm-local-zone/jest.config.js @@ -0,0 +1,12 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const config = { + testEnvironment: 'node', + roots: ['/test'], + testMatch: ['**/*.test.ts'], + transform: { + '^.+\\.tsx?$': 'ts-jest' + } +}; +exports.default = config; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiamVzdC5jb25maWcuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJqZXN0LmNvbmZpZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUVBLE1BQU0sTUFBTSxHQUFXO0lBQ3JCLGVBQWUsRUFBRSxNQUFNO0lBQ3ZCLEtBQUssRUFBRSxDQUFDLGdCQUFnQixDQUFDO0lBQ3pCLFNBQVMsRUFBRSxDQUFDLGNBQWMsQ0FBQztJQUMzQixTQUFTLEVBQUU7UUFDVCxhQUFhLEVBQUUsU0FBUztLQUN6QjtDQUNGLENBQUM7QUFDRixrQkFBZSxNQUFNLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSB7IENvbmZpZyB9IGZyb20gJ2plc3QnO1xuXG5jb25zdCBjb25maWc6IENvbmZpZyA9IHtcbiAgdGVzdEVudmlyb25tZW50OiAnbm9kZScsXG4gIHJvb3RzOiBbJzxyb290RGlyPi90ZXN0J10sXG4gIHRlc3RNYXRjaDogWycqKi8qLnRlc3QudHMnXSxcbiAgdHJhbnNmb3JtOiB7XG4gICAgJ14uK1xcXFwudHN4PyQnOiAndHMtamVzdCdcbiAgfVxufTtcbmV4cG9ydCBkZWZhdWx0IGNvbmZpZztcbiJdfQ== \ No newline at end of file diff --git a/typescript/ec2-ssm-local-zone/test/example-localzone-stack.test.ts b/typescript/ec2-ssm-local-zone/test/example-localzone-stack.test.ts index 34b897a6f1..b1588dd90c 100644 --- a/typescript/ec2-ssm-local-zone/test/example-localzone-stack.test.ts +++ b/typescript/ec2-ssm-local-zone/test/example-localzone-stack.test.ts @@ -1,11 +1,14 @@ import * as cdk from 'aws-cdk-lib'; import { Template } from 'aws-cdk-lib/assertions'; import { ExampleLocalZoneStack } from '../example-localzone-stack'; +import { normalizeTemplate } from '../../test-utils/normalize-template'; test('ExampleLocalZoneStack has required resources', () => { const app = new cdk.App(); // WHEN const stack = new ExampleLocalZoneStack(app, 'ExampleLocalZoneStack', { }); - expect(Template.fromStack(stack)).toMatchSnapshot(); + const template = Template.fromStack(stack); + const normalizedTemplate = normalizeTemplate(template.toJSON()); + expect(normalizedTemplate).toMatchSnapshot(); }); diff --git a/typescript/inspector2/test/__snapshots__/inspector2-enable-delegated-admin-account-resource.test.ts.snap b/typescript/inspector2/test/__snapshots__/inspector2-enable-delegated-admin-account-resource.test.ts.snap index adb5bb4b0c..2ab2c3128c 100644 --- a/typescript/inspector2/test/__snapshots__/inspector2-enable-delegated-admin-account-resource.test.ts.snap +++ b/typescript/inspector2/test/__snapshots__/inspector2-enable-delegated-admin-account-resource.test.ts.snap @@ -143,7 +143,7 @@ exports[`Inspector2EnableDelegatedAdminAccountResource creates required resource "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}", }, - "S3Key": "4cd2f2411231aa073e609dc99a49b5c5e974252bf9abf0f9350d237d17cce8be.zip", + "S3Key": "NORMALIZED_ASSET_HASH.zip", }, "Handler": "index.handler", "MemorySize": 512, diff --git a/typescript/inspector2/test/__snapshots__/inspector2-enable-resources.test.ts.snap b/typescript/inspector2/test/__snapshots__/inspector2-enable-resources.test.ts.snap index 0ae21d5c31..344719a8c7 100644 --- a/typescript/inspector2/test/__snapshots__/inspector2-enable-resources.test.ts.snap +++ b/typescript/inspector2/test/__snapshots__/inspector2-enable-resources.test.ts.snap @@ -143,7 +143,7 @@ exports[`Inspector2EnableResource creates required resources 1`] = ` "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}", }, - "S3Key": "4cd2f2411231aa073e609dc99a49b5c5e974252bf9abf0f9350d237d17cce8be.zip", + "S3Key": "NORMALIZED_ASSET_HASH.zip", }, "Handler": "index.handler", "MemorySize": 512, @@ -258,7 +258,7 @@ exports[`Inspector2EnableResource creates required resources 1`] = ` "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}", }, - "S3Key": "2819175352ad1ce0dae768e83fc328fb70fb5f10b4a8ff0ccbcb791f02b0716d.zip", + "S3Key": "NORMALIZED_ASSET_HASH.zip", }, "Handler": "index.handler", "Role": { diff --git a/typescript/inspector2/test/__snapshots__/inspector2-monitoring-resource.test.ts.snap b/typescript/inspector2/test/__snapshots__/inspector2-monitoring-resource.test.ts.snap index 84c1e9f9f5..1595b53c2c 100644 --- a/typescript/inspector2/test/__snapshots__/inspector2-monitoring-resource.test.ts.snap +++ b/typescript/inspector2/test/__snapshots__/inspector2-monitoring-resource.test.ts.snap @@ -143,7 +143,7 @@ exports[`Inspector2MonitoringResource creates required resources 1`] = ` "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}", }, - "S3Key": "387c7c1f429cca9662171575d60cec88ab73d6da0e9d197558cbc4bbd665bb6e.zip", + "S3Key": "NORMALIZED_ASSET_HASH.zip", }, "Handler": "index.handler", "Role": { @@ -220,7 +220,7 @@ exports[`Inspector2MonitoringResource creates required resources 1`] = ` "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}", }, - "S3Key": "08c8f1505ccfb98c41cb39e43e5ec867fcb42aee41bba9ea3bb3ca27a3025c0c.zip", + "S3Key": "NORMALIZED_ASSET_HASH.zip", }, "Handler": "index.handler", "Role": { @@ -396,7 +396,7 @@ exports[`Inspector2MonitoringResource creates required resources 1`] = ` "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}", }, - "S3Key": "2819175352ad1ce0dae768e83fc328fb70fb5f10b4a8ff0ccbcb791f02b0716d.zip", + "S3Key": "NORMALIZED_ASSET_HASH.zip", }, "Handler": "index.handler", "Role": { diff --git a/typescript/inspector2/test/__snapshots__/inspector2-update-org-config-resource.test.ts.snap b/typescript/inspector2/test/__snapshots__/inspector2-update-org-config-resource.test.ts.snap index bb330bfdaa..4c1fc162ee 100644 --- a/typescript/inspector2/test/__snapshots__/inspector2-update-org-config-resource.test.ts.snap +++ b/typescript/inspector2/test/__snapshots__/inspector2-update-org-config-resource.test.ts.snap @@ -143,7 +143,7 @@ exports[`Inspector2UpdateOrganizationConfigurationResource creates required reso "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}", }, - "S3Key": "4cd2f2411231aa073e609dc99a49b5c5e974252bf9abf0f9350d237d17cce8be.zip", + "S3Key": "NORMALIZED_ASSET_HASH.zip", }, "Handler": "index.handler", "MemorySize": 512, diff --git a/typescript/inspector2/test/inspector2-enable-delegated-admin-account-resource.test.ts b/typescript/inspector2/test/inspector2-enable-delegated-admin-account-resource.test.ts index 686505aaf7..dd67f31891 100644 --- a/typescript/inspector2/test/inspector2-enable-delegated-admin-account-resource.test.ts +++ b/typescript/inspector2/test/inspector2-enable-delegated-admin-account-resource.test.ts @@ -1,6 +1,7 @@ import * as cdk from 'aws-cdk-lib'; import { Template } from 'aws-cdk-lib/assertions'; import { Inspector2EnableDelegatedAdminAccountResource } from '../lib/inspector2-enable-delegated-admin-account-resource'; +import { normalizeTemplate } from '../../test-utils/normalize-template'; test('Inspector2EnableDelegatedAdminAccountResource creates required resources', () => { const app = new cdk.App(); @@ -18,5 +19,7 @@ test('Inspector2EnableDelegatedAdminAccountResource creates required resources', }, }); - expect(Template.fromStack(stack)).toMatchSnapshot(); + const template = Template.fromStack(stack); + const normalizedTemplate = normalizeTemplate(template.toJSON()); + expect(normalizedTemplate).toMatchSnapshot(); }); diff --git a/typescript/inspector2/test/inspector2-enable-resources.test.ts b/typescript/inspector2/test/inspector2-enable-resources.test.ts index 24c6d29c4b..1cda44d775 100644 --- a/typescript/inspector2/test/inspector2-enable-resources.test.ts +++ b/typescript/inspector2/test/inspector2-enable-resources.test.ts @@ -1,6 +1,7 @@ import * as cdk from 'aws-cdk-lib'; import { Template } from 'aws-cdk-lib/assertions'; import { Inspector2EnableResource } from '../lib/inspector2-enable-resource'; +import { normalizeTemplate } from '../../test-utils/normalize-template'; test('Inspector2EnableResource creates required resources', () => { const app = new cdk.App(); @@ -11,5 +12,7 @@ test('Inspector2EnableResource creates required resources', () => { logRetention: cdk.aws_logs.RetentionDays.ONE_DAY, }); - expect(Template.fromStack(stack)).toMatchSnapshot(); + const template = Template.fromStack(stack); + const normalizedTemplate = normalizeTemplate(template.toJSON()); + expect(normalizedTemplate).toMatchSnapshot(); }); diff --git a/typescript/inspector2/test/inspector2-monitoring-resource.test.ts b/typescript/inspector2/test/inspector2-monitoring-resource.test.ts index 6b8fbd1657..6385c39446 100644 --- a/typescript/inspector2/test/inspector2-monitoring-resource.test.ts +++ b/typescript/inspector2/test/inspector2-monitoring-resource.test.ts @@ -1,6 +1,7 @@ import * as cdk from 'aws-cdk-lib'; import { Template } from 'aws-cdk-lib/assertions'; import { Inspector2MonitoringResource } from '../lib/inspector2-monitoring-resource'; +import { normalizeTemplate } from '../../test-utils/normalize-template'; test('Inspector2MonitoringResource creates required resources', () => { const app = new cdk.App(); @@ -8,5 +9,7 @@ test('Inspector2MonitoringResource creates required resources', () => { const stack = new cdk.Stack(app, 'Inspector2MonitoringStack', { }); new Inspector2MonitoringResource(stack, 'Inspector2Monitoring', { }); - expect(Template.fromStack(stack)).toMatchSnapshot(); + const template = Template.fromStack(stack); + const normalizedTemplate = normalizeTemplate(template.toJSON()); + expect(normalizedTemplate).toMatchSnapshot(); }); diff --git a/typescript/inspector2/test/inspector2-update-org-config-resource.test.ts b/typescript/inspector2/test/inspector2-update-org-config-resource.test.ts index 7662c58608..b6f6fd8828 100644 --- a/typescript/inspector2/test/inspector2-update-org-config-resource.test.ts +++ b/typescript/inspector2/test/inspector2-update-org-config-resource.test.ts @@ -1,6 +1,7 @@ import * as cdk from 'aws-cdk-lib'; import { Template } from 'aws-cdk-lib/assertions'; import { Inspector2UpdateOrganizationConfigurationResource } from '../lib/inspector2-update-org-config-resource'; +import { normalizeTemplate } from '../../test-utils/normalize-template'; test('Inspector2UpdateOrganizationConfigurationResource creates required resources', () => { const app = new cdk.App(); @@ -15,5 +16,7 @@ test('Inspector2UpdateOrganizationConfigurationResource creates required resourc }, }); - expect(Template.fromStack(stack)).toMatchSnapshot(); + const template = Template.fromStack(stack); + const normalizedTemplate = normalizeTemplate(template.toJSON()); + expect(normalizedTemplate).toMatchSnapshot(); }); diff --git a/typescript/s3-kms-cross-account-replication/jest.config.js b/typescript/s3-kms-cross-account-replication/jest.config.js new file mode 100644 index 0000000000..c4f95b0aea --- /dev/null +++ b/typescript/s3-kms-cross-account-replication/jest.config.js @@ -0,0 +1,12 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const config = { + testEnvironment: 'node', + roots: ['/test'], + testMatch: ['**/*.test.ts'], + transform: { + '^.+\\.tsx?$': 'ts-jest' + } +}; +exports.default = config; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiamVzdC5jb25maWcuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJqZXN0LmNvbmZpZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUVBLE1BQU0sTUFBTSxHQUFXO0lBQ3JCLGVBQWUsRUFBRSxNQUFNO0lBQ3ZCLEtBQUssRUFBRSxDQUFDLGdCQUFnQixDQUFDO0lBQ3pCLFNBQVMsRUFBRSxDQUFDLGNBQWMsQ0FBQztJQUMzQixTQUFTLEVBQUU7UUFDVCxhQUFhLEVBQUUsU0FBUztLQUN6QjtDQUNGLENBQUM7QUFDRixrQkFBZSxNQUFNLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSB7IENvbmZpZyB9IGZyb20gJ2plc3QnO1xuXG5jb25zdCBjb25maWc6IENvbmZpZyA9IHtcbiAgdGVzdEVudmlyb25tZW50OiAnbm9kZScsXG4gIHJvb3RzOiBbJzxyb290RGlyPi90ZXN0J10sXG4gIHRlc3RNYXRjaDogWycqKi8qLnRlc3QudHMnXSxcbiAgdHJhbnNmb3JtOiB7XG4gICAgJ14uK1xcXFwudHN4PyQnOiAndHMtamVzdCdcbiAgfVxufTtcbmV4cG9ydCBkZWZhdWx0IGNvbmZpZztcbiJdfQ== \ No newline at end of file diff --git a/typescript/test-utils/normalize-template.ts b/typescript/test-utils/normalize-template.ts new file mode 100644 index 0000000000..ee048ef978 --- /dev/null +++ b/typescript/test-utils/normalize-template.ts @@ -0,0 +1,40 @@ +/** + * Utility function to normalize CloudFormation templates for consistent snapshot testing + * across different environments (local vs CI/CD). + * + * This function normalizes: + * - Asset hashes in S3Key properties + * - Any other environment-specific values that might change between runs + */ +export function normalizeTemplate(template: any): any { + // Create a deep copy of the template to avoid modifying the original + const templateCopy = JSON.parse(JSON.stringify(template)); + + // Function to recursively traverse the template and normalize values + function normalizeValues(obj: any) { + if (!obj || typeof obj !== 'object') return; + + // Process object properties + for (const key in obj) { + // Normalize S3Key asset hashes + if (key === 'S3Key' && typeof obj[key] === 'string' && /^[a-f0-9]{64}\.zip$/.test(obj[key])) { + obj[key] = 'NORMALIZED_ASSET_HASH.zip'; + } + // Normalize S3Key asset hashes with different patterns + else if (key === 'S3Key' && typeof obj[key] === 'string' && /^[a-f0-9]{64}$/.test(obj[key])) { + obj[key] = 'NORMALIZED_ASSET_HASH'; + } + // Normalize Docker image digests + else if (key === 'ImageDigest' && typeof obj[key] === 'string' && obj[key].startsWith('sha256:')) { + obj[key] = 'NORMALIZED_IMAGE_DIGEST'; + } + // Recursively process nested objects and arrays + else if (typeof obj[key] === 'object') { + normalizeValues(obj[key]); + } + } + } + + normalizeValues(templateCopy); + return templateCopy; +} From c8dd8ed2eee7147f80ed75689f798437a8c0f633 Mon Sep 17 00:00:00 2001 From: Michael Kaiser Date: Mon, 24 Mar 2025 19:09:41 -0500 Subject: [PATCH 5/7] Add documentation for snapshot testing with asset hash normalization --- SNAPSHOT_TESTING.md | 106 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 SNAPSHOT_TESTING.md diff --git a/SNAPSHOT_TESTING.md b/SNAPSHOT_TESTING.md new file mode 100644 index 0000000000..26c80caca7 --- /dev/null +++ b/SNAPSHOT_TESTING.md @@ -0,0 +1,106 @@ +# CDK Snapshot Testing Guide + +This guide explains how to use the asset hash normalization utility for consistent CDK snapshot testing across different environments. + +## Problem + +CDK snapshot tests often fail in CI/CD environments because asset hashes change between different environments. This happens because: + +- Asset hashes are generated based on content and environment variables +- Different machines or CI/CD environments produce different hashes +- This causes snapshot tests to fail even when there are no actual changes to the infrastructure + +## Solution + +We've created a utility function that normalizes asset hashes and other environment-specific values in CloudFormation templates before comparing them with snapshots. + +## How to Use the Normalization Utility + +### 1. Import the Utility + +```typescript +import { normalizeTemplate } from '../../test-utils/normalize-template'; +``` + +### 2. Apply Normalization Before Snapshot Comparison + +```typescript +import { App } from 'aws-cdk-lib'; +import { Template } from 'aws-cdk-lib/assertions'; +import { YourStack } from '../lib/your-stack'; +import { normalizeTemplate } from '../../test-utils/normalize-template'; + +test('YourStack creates the expected resources', () => { + const app = new App(); + const stack = new YourStack(app, 'TestStack'); + + // Get the CloudFormation template + const template = Template.fromStack(stack); + + // Normalize the template before snapshot comparison + const normalizedTemplate = normalizeTemplate(template.toJSON()); + + // Compare with snapshot + expect(normalizedTemplate).toMatchSnapshot(); +}); +``` + +### 3. Update Existing Snapshots + +After adding the normalization to your tests, update your snapshots: + +```bash +npm test -- -u +``` + +## What Gets Normalized + +The utility currently normalizes: + +1. **S3 Asset Keys**: Replaces asset hashes in S3Key properties + - Pattern with extension: `[64 hex chars].zip` → `NORMALIZED_ASSET_HASH.zip` + - Pattern without extension: `[64 hex chars]` → `NORMALIZED_ASSET_HASH` + +2. **Docker Image Digests**: Replaces image digests + - Pattern: `sha256:[digest]` → `NORMALIZED_IMAGE_DIGEST` + +## Adding New Test Files + +When creating new test files that use snapshot testing: + +1. Import the normalization utility +2. Apply it to your template before comparing with snapshots +3. Update your snapshots with the `-u` flag + +## Extending the Utility + +If you encounter other environment-specific values that need normalization, you can extend the utility at `typescript/test-utils/normalize-template.ts`. + +Example of adding a new normalization rule: + +```typescript +// Inside the normalizeValues function +if (key === 'NewPropertyToNormalize' && typeof obj[key] === 'string' && /pattern-to-match/.test(obj[key])) { + obj[key] = 'NORMALIZED_VALUE'; +} +``` + +## Troubleshooting + +If you're still seeing snapshot test failures: + +1. **Check for new patterns**: There might be new types of asset hashes or environment-specific values that need normalization +2. **Verify imports**: Make sure you're importing and using the utility correctly +3. **Check snapshot updates**: Ensure you've updated your snapshots after adding normalization + +## Best Practices + +1. **Always normalize before snapshot comparison**: This ensures consistent results +2. **Update snapshots deliberately**: Only use the `-u` flag when you expect changes +3. **Review snapshot diffs**: When updating snapshots, review the changes to ensure they're expected +4. **Keep the utility updated**: As new patterns emerge, add them to the normalization utility + +## Additional Resources + +- [Jest Snapshot Testing Documentation](https://jestjs.io/docs/snapshot-testing) +- [AWS CDK Testing Documentation](https://docs.aws.amazon.com/cdk/v2/guide/testing.html) From 5e95c569d225aaf998902f7da3af260d1535c407 Mon Sep 17 00:00:00 2001 From: Michael Kaiser Date: Mon, 24 Mar 2025 19:11:10 -0500 Subject: [PATCH 6/7] Add script for building all typescript projects --- scripts/build-all-typescript.sh | 166 ++++++++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100755 scripts/build-all-typescript.sh diff --git a/scripts/build-all-typescript.sh b/scripts/build-all-typescript.sh new file mode 100755 index 0000000000..eb6287b539 --- /dev/null +++ b/scripts/build-all-typescript.sh @@ -0,0 +1,166 @@ +#!/bin/bash +# +# Script to build all TypeScript CDK projects in parallel +# +set -euo pipefail + +# Get the directory of this script +SCRIPT_DIR=$(cd $(dirname $0) && pwd) +REPO_ROOT=$(dirname "$SCRIPT_DIR") +TYPESCRIPT_DIR="${REPO_ROOT}/typescript" +BUILD_SCRIPT="$SCRIPT_DIR/build-typescript.sh" + +# Check if parallel is installed +if ! command -v parallel &> /dev/null; then + echo "GNU parallel is not installed. Please install it first." + exit 1 +fi + +# Check if the build script exists +if [ ! -f "$BUILD_SCRIPT" ]; then + echo "Error: Build script not found at $BUILD_SCRIPT" + exit 1 +fi + +# Create a temporary directory for build logs +TEMP_DIR=$(mktemp -d) +trap 'rm -rf "$TEMP_DIR"' EXIT + +# Find all TypeScript CDK projects (directories with cdk.json) +# Exclude any matches from node_modules directories, cdk.out directories, and specific problematic projects +echo "Finding all TypeScript CDK projects..." +PROJECTS=$(find "$TYPESCRIPT_DIR" -name "cdk.json" -type f \ + -not -path "*/node_modules/*" \ + -not -path "*/cdk.out/*" \ + | sort) + +# Count total projects +TOTAL_PROJECTS=$(echo "$PROJECTS" | wc -l) +echo "Found $TOTAL_PROJECTS TypeScript CDK projects to build" +echo "==============================" + +# Function to build a single project +build_project() { + CDK_JSON_PATH="$1" + PROJECT_DIR=$(dirname "$CDK_JSON_PATH") + REL_PATH=$(realpath --relative-to="$REPO_ROOT" "$PROJECT_DIR") + LOG_FILE="$TEMP_DIR/$(echo "$REL_PATH" | tr '/' '_').log" + + # Show start message + echo "▶️ Starting build: $REL_PATH" + + # Check for DO_NOT_AUTOTEST file + if [ -f "$PROJECT_DIR/DO_NOT_AUTOTEST" ]; then + echo "⏭️ Skipping $REL_PATH (DO_NOT_AUTOTEST flag found)" + echo "SKIPPED:$REL_PATH" > "$LOG_FILE.status" + return 0 + fi + + # Find the package.json in the project directory + PACKAGE_JSON="$PROJECT_DIR/package.json" + if [ ! -f "$PACKAGE_JSON" ]; then + echo "⏭️ Skipping $REL_PATH (no package.json found)" + echo "SKIPPED:$REL_PATH" > "$LOG_FILE.status" + return 0 + fi + + # Get the relative path to package.json for the build script + PACKAGE_JSON_REL_PATH=$(realpath --relative-to="$REPO_ROOT" "$PACKAGE_JSON") + + # Create a modified version of the build script that suppresses cdk synth output + TEMP_BUILD_SCRIPT="$TEMP_DIR/build-$(basename "$REL_PATH").sh" + cat > "$TEMP_BUILD_SCRIPT" << 'EOF' +#!/bin/bash +set -euo pipefail + +# Get the original script and arguments +ORIGINAL_SCRIPT="$1" +shift +ARGS="$@" + +# Run the original script but capture and filter the output +"$ORIGINAL_SCRIPT" "$ARGS" 2>&1 | grep -v "cdk synth" | grep -v "Synthesizing" +EOF + chmod +x "$TEMP_BUILD_SCRIPT" + + # Run the build script with filtered output + if "$TEMP_BUILD_SCRIPT" "$BUILD_SCRIPT" "$PACKAGE_JSON_REL_PATH" > "$LOG_FILE" 2>&1; then + echo "✅ Build successful: $REL_PATH" + echo "SUCCESS:$REL_PATH" > "$LOG_FILE.status" + else + echo "❌ Build failed: $REL_PATH" + echo "FAILED:$REL_PATH" > "$LOG_FILE.status" + fi +} +export -f build_project +export SCRIPT_DIR +export REPO_ROOT +export BUILD_SCRIPT +export TEMP_DIR + +# Run builds in parallel +echo "$PROJECTS" | parallel --will-cite --jobs 50% build_project + +# Collect results +SUCCESSFUL=0 +FAILED=0 +SKIPPED=0 +ALL_PROJECTS=() + +for STATUS_FILE in "$TEMP_DIR"/*.status; do + [ -f "$STATUS_FILE" ] || continue + + STATUS_CONTENT=$(cat "$STATUS_FILE") + STATUS_TYPE=${STATUS_CONTENT%%:*} + PROJECT_PATH=${STATUS_CONTENT#*:} + + case "$STATUS_TYPE" in + "SUCCESS") + ((SUCCESSFUL++)) + ALL_PROJECTS+=("✅ $PROJECT_PATH") + ;; + "FAILED") + ((FAILED++)) + ALL_PROJECTS+=("❌ $PROJECT_PATH") + ;; + "SKIPPED") + ((SKIPPED++)) + ALL_PROJECTS+=("⏭️ $PROJECT_PATH") + ;; + esac +done + +# Sort the projects list +IFS=$'\n' SORTED_PROJECTS=($(sort <<<"${ALL_PROJECTS[*]}")) +unset IFS + +# Print summary +echo "" +echo "==============================" +echo "BUILD SUMMARY" +echo "==============================" +echo "Total: $((SUCCESSFUL + FAILED + SKIPPED)) (✅ $SUCCESSFUL succeeded, ❌ $FAILED failed, ⏭️ $SKIPPED skipped)" +echo "" +echo "Project Status:" +echo "-----------------------------" +for PROJ in "${SORTED_PROJECTS[@]}"; do + echo "$PROJ" +done + +# If any builds failed, print their logs and exit with error +if [ $FAILED -gt 0 ]; then + echo "" + echo "Build logs for failed projects:" + echo "==============================" + for PROJ in "${SORTED_PROJECTS[@]}"; do + if [[ $PROJ == ❌* ]]; then + PROJECT_PATH=${PROJ#❌ } + echo "" + echo "Log for $PROJECT_PATH:" + echo "-------------------------------------------" + cat "$TEMP_DIR/$(echo "$PROJECT_PATH" | tr '/' '_').log" + echo "-------------------------------------------" + fi + done + exit 1 +fi From c10d1e48df69c93cda5583268b979f6f3ac9bcee Mon Sep 17 00:00:00 2001 From: Michael Kaiser Date: Mon, 24 Mar 2025 19:28:49 -0500 Subject: [PATCH 7/7] Remove bedrock agent examples as the project is completely broken with update from latest cdklabs --- typescript/bedrock-kb-agent/.gitignore | 81 ------ typescript/bedrock-kb-agent/.npmignore | 6 - typescript/bedrock-kb-agent/README.md | 230 ---------------- .../api/example-agent/example.py | 59 ---- .../api/example-agent/openapi.json | 1 - .../api/example-agent/requirements.dev.txt | 1 - .../api/example-agent/requirements.txt | 4 - .../api/example-powertools/example.py | 258 ------------------ .../example-powertools/requirements.dev.txt | 1 - .../api/example-powertools/requirements.txt | 4 - .../bedrock-kb-agent/architecture.drawio.png | Bin 190542 -> 0 bytes .../bedrock-kb-agent/bin/bedrock-kb-agent.ts | 20 -- typescript/bedrock-kb-agent/cdk.json | 81 ------ .../lib/bedrock-kb-agent-stack.ts | 213 --------------- .../apigatewayv2-cloudfront-construct.ts | 161 ----------- .../apigatewayv2-lambda-construct.ts | 66 ----- .../cloudfront-s3-website-construct.ts | 225 --------------- .../cognito-web-native-construct.ts | 208 -------------- .../lib/constructs/s3-construct.ts | 84 ------ typescript/bedrock-kb-agent/media/kb-s3.png | Bin 115952 -> 0 bytes typescript/bedrock-kb-agent/package.json | 52 ---- .../test/bedrock-kb-agent-stack.test.ts | 104 ------- typescript/bedrock-kb-agent/tsconfig.json | 31 --- typescript/bedrock-kb-agent/web-app/.gitkeep | 0 .../bedrock-kb-agent/web-app/dist/.gitkeep | 0 25 files changed, 1890 deletions(-) delete mode 100644 typescript/bedrock-kb-agent/.gitignore delete mode 100644 typescript/bedrock-kb-agent/.npmignore delete mode 100644 typescript/bedrock-kb-agent/README.md delete mode 100644 typescript/bedrock-kb-agent/api/example-agent/example.py delete mode 100644 typescript/bedrock-kb-agent/api/example-agent/openapi.json delete mode 100644 typescript/bedrock-kb-agent/api/example-agent/requirements.dev.txt delete mode 100644 typescript/bedrock-kb-agent/api/example-agent/requirements.txt delete mode 100644 typescript/bedrock-kb-agent/api/example-powertools/example.py delete mode 100644 typescript/bedrock-kb-agent/api/example-powertools/requirements.dev.txt delete mode 100644 typescript/bedrock-kb-agent/api/example-powertools/requirements.txt delete mode 100644 typescript/bedrock-kb-agent/architecture.drawio.png delete mode 100644 typescript/bedrock-kb-agent/bin/bedrock-kb-agent.ts delete mode 100644 typescript/bedrock-kb-agent/cdk.json delete mode 100644 typescript/bedrock-kb-agent/lib/bedrock-kb-agent-stack.ts delete mode 100644 typescript/bedrock-kb-agent/lib/constructs/apigatewayv2-cloudfront-construct.ts delete mode 100644 typescript/bedrock-kb-agent/lib/constructs/apigatewayv2-lambda-construct.ts delete mode 100644 typescript/bedrock-kb-agent/lib/constructs/cloudfront-s3-website-construct.ts delete mode 100644 typescript/bedrock-kb-agent/lib/constructs/cognito-web-native-construct.ts delete mode 100755 typescript/bedrock-kb-agent/lib/constructs/s3-construct.ts delete mode 100644 typescript/bedrock-kb-agent/media/kb-s3.png delete mode 100644 typescript/bedrock-kb-agent/package.json delete mode 100644 typescript/bedrock-kb-agent/test/bedrock-kb-agent-stack.test.ts delete mode 100644 typescript/bedrock-kb-agent/tsconfig.json delete mode 100644 typescript/bedrock-kb-agent/web-app/.gitkeep delete mode 100644 typescript/bedrock-kb-agent/web-app/dist/.gitkeep diff --git a/typescript/bedrock-kb-agent/.gitignore b/typescript/bedrock-kb-agent/.gitignore deleted file mode 100644 index 8952faab5f..0000000000 --- a/typescript/bedrock-kb-agent/.gitignore +++ /dev/null @@ -1,81 +0,0 @@ -# Build, dist and temp folders -build/ -dist/ -tmp/ -temp/ - -# Compiled source -*.com -*.class -*.dll -*.exe -*.o -*.so -*.py[cod] -*$py.class - -# npm & bower -bower_components -node_modules -npm-debug.log -.npmignore - -# Caches # -*.sass-cache - -# Logs and databases -*.log -*.sql -*.sqlite - -# OS generated files -.DS_Store -Desktop.ini - -# Thumbnails -._* -ehthumbs.db -*[Tt]humbs.db - -# Files that might appear on external disks -.Spotlight-V100 -.Trashes - -# Packages # -# It's better to unpack these files and commit the raw source because -# git has its own built in compression methods. -*.7z -*.jar -*.rar -*.zip -*.gz -*.bzip -*.xz -*.lzma - -#packing-only formats -*.iso -*.tar - -# IDEs stuff -.idea - -#package management formats -*.dmg -*.xpi -*.gem -*.egg -*.deb -*.rpm - -# python -__pycache__/ - -# python environments -.env -.venv -env/ -venv/ - -# cdk -cdk.out diff --git a/typescript/bedrock-kb-agent/.npmignore b/typescript/bedrock-kb-agent/.npmignore deleted file mode 100644 index c1d6d45dcf..0000000000 --- a/typescript/bedrock-kb-agent/.npmignore +++ /dev/null @@ -1,6 +0,0 @@ -*.ts -!*.d.ts - -# CDK asset staging directory -.cdk.staging -cdk.out diff --git a/typescript/bedrock-kb-agent/README.md b/typescript/bedrock-kb-agent/README.md deleted file mode 100644 index 83b4af2648..0000000000 --- a/typescript/bedrock-kb-agent/README.md +++ /dev/null @@ -1,230 +0,0 @@ -## Intro - -### Knowledge bases and agents - -Knowledge bases and agents are essential tools in enhancing organizational efficiency and decision-making. Knowledge bases serve as centralized repositories of information, enabling quick access to accurate data, which reduces search times, improves productivity, and supports consistent communication across teams. Knowledge-based agents, on the other hand, utilize this information to make informed decisions and take appropriate actions based on their understanding of the environment, thereby facilitating learning and adaptation through continuous knowledge updates. Together, they streamline operations, reduce training time for new employees, and enhance customer support by providing instant access to resources, ultimately leading to improved organizational performance. - -### Amazon Bedrock Knowledge bases and agents - -Amazon Bedrock Knowledge Bases and Agents offer powerful tools for ingesting documentation and answering questions intelligently. This example demonstrates how to leverage these capabilities effectively. -Amazon Bedrock Knowledge Bases are used for implementing Retrieval Augmented Generation (RAG), a technique that enhances AI responses by incorporating contextual information from your company's data sources. The knowledge base ingests and processes your documentation, converting it into vector embeddings that can be efficiently searched. -Amazon Bedrock Agents, built on top of the knowledge base, provide a natural language interface to interact with the stored information3. These agents can be configured to not only retrieve relevant data but also to execute various actions, including leveraging third-party APIs, in response to user queries. - -By combining these technologies, you can create a system that: - -1. Ingests and processes your documentation semi-automatically -2. Retrieves relevant information based on user queries -3. Generates accurate and contextually appropriate responses -4. Performs additional actions or API calls as needed to supplement the information - -This approach enables the creation of highly customized, intelligent applications that can efficiently answer questions about your specific documentation while also integrating external data sources when necessary - -#### AWS Powertools - -For this examples we leverage [AWS Powertools](https://docs.powertools.aws.dev/lambda/python/latest/) for lambda. -The reason is, AWS Powertools is essential for optimizing AWS Lambda functions, providing a suite of utilities that enhance performance, monitoring, and security while reducing the complexity of serverless application development. -By implementing best practices such as structured logging, custom metrics, and distributed tracing, AWS Powertools enables developers to focus on business logic rather than boilerplate code, streamlining the development process. -Additionally, it supports multiple programming languages and integrates seamlessly with AWS services, making it a versatile tool for teams looking to improve their serverless architecture and operational efficiency. - -### Architecture - -![Architecture](architecture.drawio.png "Architecture") - -To understand the architecture of this solution, let’s break it down step by step, moving from left to right in the system's workflow: - -#### **User Interaction and REST API** - -- **User Interaction**: The system begins with user interaction through REST API calls. These calls can be initiated from a **Web UI**, enabling users to interact with the solution seamlessly. -- **Security with Amazon Cognito**: All REST API interactions are secured using **Amazon Cognito**. This ensures that only authenticated and authorized users can access the APIs. Users must register and authenticate via Cognito to obtain valid tokens, which are included in the API requests for validation. - -#### **API Gateway** - -- The **Amazon API Gateway** acts as the entry point for all REST API requests. It exposes the system's functionality by routing requests to the appropriate backend services. -- API Gateway integrates with Amazon Cognito to validate user credentials before forwarding requests, ensuring robust security and fine-grained access control. - -#### **AWS Lambda** - -- Once the request passes through the API Gateway, it is processed by **AWS Lambda** functions. These serverless functions handle business logic and interact with other components of the architecture. -- Lambda functions are responsible for querying and interacting with: - - **Knowledge Bases**: These could include databases or other structured repositories of information. - - **Agents**: External or internal systems that perform specific tasks or provide additional data. - -#### **Data Storage in Amazon S3** - -- The data to be processed or searched by the knowledge base and agents is stored in an **Amazon S3 bucket**. -- For this specific use case, it is assumed that users manually upload documents to the S3 bucket. This allows the system to process these documents as part of its operations. - -#### **Key Features of the Architecture** - -1. **Security**: By leveraging Amazon Cognito and JWT-based authentication, the architecture ensures secure access to APIs without requiring session management overhead[6]. -2. **Scalability**: With serverless components like AWS Lambda and S3, the system is highly scalable, capable of handling varying workloads efficiently. -3. **Modularity**: Each component (API Gateway, Lambda, Cognito, S3) is independent yet seamlessly integrated, allowing for easy updates or replacements without disrupting the entire system. - -This architecture demonstrates a robust design for handling secure user interactions, efficient data processing, and scalable storage using AWS services. It aligns with best practices in solution architecture by ensuring security, scalability, and maintainability. - -## Deploying the CDK Stack: A Step-by-Step Guide - -Follow the these steps to install the example: - -### 1. Install Dependencies - -Begin by installing the necessary npm dependencies. Navigate to the top-level directory of your project in your terminal and run: - -``` -npm install -``` - -This command will fetch and install all required packages specified in your `package.json` file. - -### 2. Bootstrap CDK - -Before deploying your stack, you need to bootstrap CDK in your AWS account and region. This process sets up the necessary resources for CDK to manage deployments. Execute the following command, replacing `` and `` with your AWS account ID and desired region: - -``` -npx cdk bootstrap aws:/// -``` - -For example, if your account ID is 123456789012 and you're deploying to us-east-1, the command would be: - -``` -npx cdk bootstrap aws://123456789012/us-east-1 -``` - -### 3. Deploy the Stack - -With the dependencies installed and CDK bootstrapped, you're ready to deploy your stack. Simply run: - -``` -npx cdk deploy -``` - -This command synthesizes a CloudFormation template from your CDK code and deploys it to your AWS account, creating or updating the specified resources. - -By following these steps, you'll have your CDK stack up and running in your AWS environment, ready to manage your infrastructure efficiently. - -### 4. Knowledge Base Configuration and Document Processing - -After completing the installation process, you'll be able to access your newly created Knowledge Base within Amazon Bedrock. To view and manage your Knowledge Base: - -1. Navigate to the AWS Management Console -2. Locate and select the Amazon Bedrock service -3. Choose "Knowledge and datasource" from the sidebar menu - -This will display your Knowledge Base and its associated S3 bucket, which serves as the repository for documents used in your Knowledge Base. - -![Knowledge Base and its associated S3 bucket](./media/kb-s3.png "Knowledge Base and its associated S3 bucket") - -### Document Upload and Synchronization - -To populate your Knowledge Base with relevant information: - -1. Select an appropriate document for ingestion. For this exercise, we recommend using the [Amazon S3 user manual](https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-userguide.pdf), which provides a comprehensive overview of S3 functionality. -2. Upload the chosen document to the S3 bucket directory specified in your Knowledge Base configuration. -3. After successful upload, locate and press the "Synchronize" button within the Bedrock console. - -The synchronization process is a crucial step that accomplishes the following: - -- It triggers the creation of embeddings for the uploaded documents. -- These embeddings are vector representations of the text content, enabling efficient semantic search and retrieval. -- The system uses a specified embeddings model to convert the textual data into these high-dimensional vectors. - -### Behind the Scenes - -During synchronization, Amazon Bedrock performs several important tasks: - -1. **Document Chunking**: The uploaded content is divided into manageable chunks, optimizing it for processing and retrieval. - -2. **Embedding Generation**: Each chunk is processed through the selected embeddings model, transforming the text into numerical vectors. - -3. **Vector Storage**: The generated embeddings are stored in the configured vector database, which could be Amazon OpenSearch Serverless or another compatible service. - -4. **Metadata Association**: Any relevant metadata from the original documents is preserved and associated with the corresponding embeddings. - -This process enables your Knowledge Base to efficiently search and retrieve relevant information when queried, forming the foundation for powerful retrieval-augmented generation (RAG) applications. - -By following these steps, you'll have successfully initialized and populated your Amazon Bedrock Knowledge Base, preparing it for use in various AI-driven tasks and applications. - -### Test the Knowledge Base with the AWS console - -To interact with Amazon Bedrock Knowledge Bases using the AWS console, you first need to navigate to the Amazon Bedrock service and select "Knowledge bases" from the left navigation pane. -You will notice the new created knowledge base named: `KBBedrockKb.....` select it and then use the knowledge base chat to query information or generate AI responses based on the ingested data. For this step you need to choose a model, for this exercise we sued Anthropic/Claude 3 Haiku. - -If you choose to use the `Amazon S3 user manual` you can test the Knowledge Base you can ask for questions about S3. - -#### Amazon Bedrock Model access - -In order to be able to use foundation models you need to request access for. In order to do this navigate to the Amazon Bedrock service and select "Model access" from the left navigation pane. -On the Model access page, users can review the End User License Agreement (EULA) for each model and then click "Modify model access" to select the desired models. After selecting the models, users should review the terms, submit any required use case details (such as for Anthropic models), and click "Submit" to request access, which may take several minutes to be reflected in the console. - -For this exercise we recommend you to request access for all Anthropic/Claude 3 models. - -## Test it with AWS Console - -The interaction/functionality from section `Test the Knowledge Base with the AWS console` is can be done programmatic as well as code. -For this exercise we prepared two distinct functionalities, the Knowledge Base RAG query and Agent query. -The codebase provide two Amazon Powertools lambdas let's try to explore them. - -### Knowledge Base RAG query and agent query - -The code is available in the `api/example-powertools/example.py` file. - -The AWS Lambda function in this code is designed to be triggered by API Gateway when a REST request is received. -API Gateway routes incoming HTTP requests to the appropriate Lambda function based on the configured API endpoints. -When a request matches a defined route, API Gateway invokes the Lambda function, passing the request details as an event object. - -You can test the lambda function from the AWS console using the event the predefined events with the Lambda AWS console as follow steps. - -First navigate to the Lambda function `BedrockKbAgentStack-ExampleLambdaFn....` in the AWS console and click on the "Test" tab. -Create a new test event by selecting "Configure test event" from the dropdown menu, then enter `..test/lambda-events/ask-kb.json` JSON payload in the event body. Finally, click "Test" to execute the Lambda function with your specified event, and view the results in the console's execution output. - -Same logic for agent query, with the difference that for the agent query you need to use `..test/lambda-events/ask-agent.json` - -This is how the `ask-kb` event response looks like - -```json -{ - "statusCode": 200, - "body": "{\"conv_id\":\"0b772d3a-3b56-4bb4-ac8f-ee5d4272dc89\",\"question\":\"what is s3?\",\"answer\":\"Amazon S3 (Simple Storage Service) is an object storage service offered by Amazon Web Services (AWS). It allows users to store and retrieve data of any amount or type, from anywhere on the web. Some key features of Amazon S3 include:\\n\\n- Storage classes: S3 offers a range of storage classes designed for different use cases, such as frequently accessed data, infrequently accessed data, and archived data.\\n- Data protection: S3 is designed to provide 99.999999999% durability and 99.99% availability of objects over a given year.\\n- Lifecycle management: Users can configure lifecycle rules to automatically transition objects between storage classes or expire objects that reach the end of their lifetimes.\\n- Access management: S3 provides various access management tools to control who can access the stored data and what actions they can perform.\"}", - "isBase64Encoded": false, - "headers": { - "Content-Type": "application/json" - }, - "cookies": [] -} -``` - -Let's try to understand it - -1. for the exercise we ingest the `S3 user manual` and this means we can ask S# specific questions, for this case we send the question: `what is s3?` -2. the Knowledge Base RAG answer is: `Amazon S3 (Simple Storage Service) is an object storage ....` -3. the method returns also conversation id, useful if you want to create a longer conversation. - -This is how the `ask-kb` event response looks like - -```json -{ - "statusCode": 200, - "body": "{\"conv_id\":\"adc56b78a40b4a99bf82c5236596bc01\",\"question\":\"how is the weather in London?\",\"answer\":\"The weather in London is rainy\"}", - "isBase64Encoded": false, - "headers": { - "Content-Type": "application/json" - }, - "cookies": [] -} -``` - -Let's try to understand it. - -This event is routed to the Knowledge Base Agent, the source code for this is in the `./api/example-agent/example.py`. -This file s is simple implementation of a Knowledge Base Agent. - -The Knowledge Base Agent, implemented in example.py, is designed to recognize and respond to weather-related questions for specific locations. This agent utilizes a llm mechanisms to determine the location mentioned in a query and provides a mock weather forecast for that location. -The implementation includes a /weather endpoint that generates a random weather condition (either "rainy" or "sunny") for the given location, demonstrating a basic example of how a knowledge-based system can process and respond to user queries. - -## Destroy - -In order to remove this example run: - -``` -npx cdk destroy -``` diff --git a/typescript/bedrock-kb-agent/api/example-agent/example.py b/typescript/bedrock-kb-agent/api/example-agent/example.py deleted file mode 100644 index 534c891f1a..0000000000 --- a/typescript/bedrock-kb-agent/api/example-agent/example.py +++ /dev/null @@ -1,59 +0,0 @@ -""" -Copyright 2023 Amazon.com, Inc. and its affiliates. All Rights Reserved. - -Licensed under the Amazon Software License (the "License"). -You may not use this file except in compliance with the License. -A copy of the License is located at - - http://aws.amazon.com/asl/ - -or in the "license" file accompanying this file. This file is distributed -on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -express or implied. See the License for the specific language governing -permissions and limitations under the License. -""" - -from aws_lambda_powertools import Logger, Tracer -from aws_lambda_powertools.event_handler import BedrockAgentResolver -from aws_lambda_powertools.utilities.data_masking import DataMasking -from aws_lambda_powertools.utilities.typing import LambdaContext -from aws_lambda_powertools.event_handler.openapi.params import Body, Query -import json -import sys -from typing import Annotated -import random - -tracer = Tracer() -logger = Logger() -data_masker = DataMasking() -app = BedrockAgentResolver() - - -@app.get( - "/weather", - description="Provides the weather forecast for a given location", -) -@tracer.capture_method -def describe_scrap( - location: Annotated[ - str, - Query(description="The location form where the weather will be forecasted."), - ] -) -> Annotated[str, Body(description="The weather forecast for a given location")]: - weather = "rainy" if bool(random.getrandbits(1)) else "sunny" - return f"The weather in {location} is {weather}" - - -@logger.inject_lambda_context -@tracer.capture_lambda_handler -@tracer.capture_method -def lambda_handler(event: dict, context: LambdaContext): - logger.info(event) - return app.resolve(event, context) - - -if __name__ == "__main__": - openapi_file = "openapi.json" - with open(openapi_file, "w") as f: - f.write(app.get_openapi_json_schema()) - print(f"\n\n{openapi_file} was generated.\n\n") diff --git a/typescript/bedrock-kb-agent/api/example-agent/openapi.json b/typescript/bedrock-kb-agent/api/example-agent/openapi.json deleted file mode 100644 index 79555da5d1..0000000000 --- a/typescript/bedrock-kb-agent/api/example-agent/openapi.json +++ /dev/null @@ -1 +0,0 @@ -{"openapi": "3.0.3", "info": {"title": "Powertools API", "version": "1.0.0"}, "servers": [{"url": "/"}], "paths": {"/weather": {"get": {"summary": "GET /weather", "description": "Provides the weather forecast for a given location", "operationId": "describe_scrap_weather_get", "parameters": [{"description": "The location form where the weather will be forecasted.", "required": true, "schema": {"type": "string", "title": "Location", "description": "The location form where the weather will be forecasted."}, "name": "location", "in": "query"}], "responses": {"422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}, "200": {"description": "Successful Response", "content": {"application/json": {"schema": {"type": "string", "title": "Return", "description": "The weather forecast for a given location"}}}}}}}}, "components": {"schemas": {"HTTPValidationError": {"properties": {"detail": {"items": {"$ref": "#/components/schemas/ValidationError"}, "type": "array", "title": "Detail"}}, "type": "object", "title": "HTTPValidationError"}, "ValidationError": {"properties": {"loc": {"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, "type": "array", "title": "Location"}, "type": {"type": "string", "title": "Error Type"}}, "type": "object", "required": ["loc", "msg", "type"], "title": "ValidationError"}}}} \ No newline at end of file diff --git a/typescript/bedrock-kb-agent/api/example-agent/requirements.dev.txt b/typescript/bedrock-kb-agent/api/example-agent/requirements.dev.txt deleted file mode 100644 index 1db657b6b3..0000000000 --- a/typescript/bedrock-kb-agent/api/example-agent/requirements.dev.txt +++ /dev/null @@ -1 +0,0 @@ -boto3 \ No newline at end of file diff --git a/typescript/bedrock-kb-agent/api/example-agent/requirements.txt b/typescript/bedrock-kb-agent/api/example-agent/requirements.txt deleted file mode 100644 index 905ca38ded..0000000000 --- a/typescript/bedrock-kb-agent/api/example-agent/requirements.txt +++ /dev/null @@ -1,4 +0,0 @@ -aws-lambda-powertools -pydantic -aws_xray_sdk -jsonpath_ng diff --git a/typescript/bedrock-kb-agent/api/example-powertools/example.py b/typescript/bedrock-kb-agent/api/example-powertools/example.py deleted file mode 100644 index 7981de52d7..0000000000 --- a/typescript/bedrock-kb-agent/api/example-powertools/example.py +++ /dev/null @@ -1,258 +0,0 @@ -""" -Copyright 2024 Amazon.com, Inc. and its affiliates. All Rights Reserved. - -Licensed under the Amazon Software License (the "License"). -You may not use this file except in compliance with the License. -A copy of the License is located at - - http://aws.amazon.com/asl/ - -or in the "license" file accompanying this file. This file is distributed -on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -express or implied. See the License for the specific language governing -permissions and limitations under the License. -""" -import os -from typing import Optional -import boto3 -import json -import traceback -from aws_lambda_powertools.utilities.parser import ( - BaseModel, - Field, - parse -) - -from aws_lambda_powertools.event_handler import APIGatewayHttpResolver -from aws_lambda_powertools import Logger, Tracer -from aws_lambda_powertools.utilities.data_masking import DataMasking -from aws_lambda_powertools.utilities.typing import LambdaContext -from aws_lambda_powertools.logging import correlation_paths -import uuid - -# Docs: https://docs.powertools.aws.dev/lambda/python/latest/ - -tracer = Tracer() -logger = Logger() -data_masker = DataMasking() -app = APIGatewayHttpResolver() -bedrock_agent_runtime = boto3.client('bedrock-agent-runtime') - -class Question(BaseModel): - """Example response model""" - conv_id: Optional[str] = Field(description="The unique id for the conversation", - default=None) - question: str = Field(description="The text of the question") - - -class Answer(BaseModel): - """Example response model""" - conv_id: str = Field(description="The unique id for the conversation ") - question: str = Field(description="The text of the question") - answer: str = Field(description="The text of the response") - - -def _ask_rag(question: str, - conversation_id: str, - knowledge_base_id: str): - - model_arn = "arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-3-haiku-20240307-v1:0" - - response = ( - bedrock_agent_runtime.retrieve_and_generate( - sessionId=conversation_id, - input={"text": "What is S3?"}, - retrieveAndGenerateConfiguration={ - "type": "KNOWLEDGE_BASE", - "knowledgeBaseConfiguration": { - "knowledgeBaseId": knowledge_base_id, - "modelArn": model_arn, - "retrievalConfiguration": { - "vectorSearchConfiguration": {"numberOfResults": 10} - }, - }, - }, - ) - if conversation_id - else bedrock_agent_runtime.retrieve_and_generate( - input={"text": question}, - retrieveAndGenerateConfiguration={ - "type": "KNOWLEDGE_BASE", - "knowledgeBaseConfiguration": { - "knowledgeBaseId": knowledge_base_id, - "modelArn": model_arn, - "retrievalConfiguration": { - "vectorSearchConfiguration": {"numberOfResults": 10} - }, - }, - }, - ) - ) - - # Make the API call - # print(f"response=\n {json.dumps(response)}") - - answer = response.get("output", {}).get("text", "Not Found") - - citations = response.get("citations", []) - - citations = [ {"generatedResponse": citation.get("generatedResponsePart", {}).get("textResponsePart", {}).get("text", ""), - "retrievedReferences": [{"text": reference.get("content", {}).get("text"), - "location": reference.get("location",) - } for reference in citation.get("retrievedReferences", [])]} - for citation in citations] - - print(f"citations=\n {json.dumps(citations)}") - conversation_id = response.get("sessionId") - - return answer, citations, conversation_id - - -@app.post("/api/v1/example") -@tracer.capture_method -def answer_to_message() : - """ - Function to handle the POST request - """ - logger.info("Answer question form kb") - question_request = parse(event=app.current_event.json_body, model=Question) - - knowledge_base_id = os.environ.get("KNOWLEDGE_BASE_ID", None) - if knowledge_base_id is None: - return "Server Error", 500 - - try: - rag_answer = _ask_rag(question=question_request.question, - conversation_id=question_request.conv_id, - knowledge_base_id="AWXM2RSO70") - - return (Answer(conv_id=rag_answer[2], - question=question_request.question, - answer=rag_answer[0]), - 200) - except Exception as ex: - logger.error(traceback.format_exc()) - return "Server Error", 500 - - -@app.post("/api/v1/weather") -@tracer.capture_method -def get_weather() : - """ - Function to handle the POST request - """ - logger.info("Get weather form the agent") - - aget_id = os.environ.get("AGENT_ID") - if not aget_id: - raise ValueError("AGENT_ID environment variable is not set") - - aget_alias_id = os.environ.get("AGENT_ALIAS_ID") - if not aget_alias_id: - raise ValueError("AGENT_ALIAS_ID environment variable is not set") - - question_request = parse(event=app.current_event.json_body, model=Question) - - conv_id = question_request.conv_id - if not conv_id: - conv_id = uuid.uuid4().hex - - - agent_response = bedrock_agent_runtime.invoke_agent( - agentId=aget_id, - agentAliasId=aget_alias_id, - sessionId=conv_id, - inputText=question_request.question, - enableTrace=True) - - traces = [] - chunks = [] - for event in agent_response.get("completion"): - if "trace" in event: - traces.append(event["trace"]) - if "chunk" in event: - chunks.append(event["chunk"]["bytes"].decode()) - - answer = "".join(chunks) - return Answer(conv_id=conv_id, - question=question_request.question, - answer=answer) ,200 - - -@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_HTTP) -@tracer.capture_lambda_handler -def lambda_handler(event: dict, context: LambdaContext): - """ - Lambda handler entry point - """ - # remove sensitive information from the event before writing to CloudWatch - # logger.info( - # data_masker.erase( - # event, - # fields=[ - # "headers.authorization", - # ], - # ) - # ) - logger.info(event) - return app.resolve(event, context) - - -if __name__ == "__main__": - # event = { - # "version": "2.0", - # "routeKey": "POST /api/v1/example", - # "rawPath": "/api/v1/example", - # "rawQueryString": "", - # "headers": { - # "accept-encoding": "gzip", - # "authorization": "AAA", - # }, - # "requestContext": { - # "authorizer": {}, - # "http": { - # "method": "POST", - # "path": "/api/v1/example", - # "protocol": "HTTP/1.1", - # }, - # "routeKey": "POST /api/v1/example", - # "stage": "$default", - # }, - # "body": "{\"question\":\"what is S3?\"}", - # } - - event = { - "version": "2.0", - "routeKey": "POST /api/v1/weather", - "rawPath": "/api/v1/weather", - "rawQueryString": "", - "headers": { - "accept-encoding": "gzip", - "authorization": "AAA", - }, - "requestContext": { - "authorizer": {}, - "http": { - "method": "POST", - "path": "/api/v1/weather", - "protocol": "HTTP/1.1", - }, - "routeKey": "POST /api/v1/weather", - "stage": "$default", - }, - "body": "{\"question\":\"How is the weather in London?\"}", - } - - class MockContext: - def __init__(self): - self.function_name = "test_function" - self.memory_limit_in_mb = 128 - self.invoked_function_arn = ( - "arn:aws:lambda:us-east-1:123456789012:function:test_function" - ) - self.aws_request_id = "test_request_id" - - context = MockContext() - - response = lambda_handler(event, context) - print(json.dumps(response)) diff --git a/typescript/bedrock-kb-agent/api/example-powertools/requirements.dev.txt b/typescript/bedrock-kb-agent/api/example-powertools/requirements.dev.txt deleted file mode 100644 index 1db657b6b3..0000000000 --- a/typescript/bedrock-kb-agent/api/example-powertools/requirements.dev.txt +++ /dev/null @@ -1 +0,0 @@ -boto3 \ No newline at end of file diff --git a/typescript/bedrock-kb-agent/api/example-powertools/requirements.txt b/typescript/bedrock-kb-agent/api/example-powertools/requirements.txt deleted file mode 100644 index 905ca38ded..0000000000 --- a/typescript/bedrock-kb-agent/api/example-powertools/requirements.txt +++ /dev/null @@ -1,4 +0,0 @@ -aws-lambda-powertools -pydantic -aws_xray_sdk -jsonpath_ng diff --git a/typescript/bedrock-kb-agent/architecture.drawio.png b/typescript/bedrock-kb-agent/architecture.drawio.png deleted file mode 100644 index b108ff3e7200c254d0fe168f3e60fafff9e8bcd2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 190542 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

*T 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

{~x?_tn#biSeId)UgTv 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

@4JyW7AkS`X{{?-ACog!K}?}{8E^IVrI%&t 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 Z7k}iz?wS|hvi?1I`Rt~6iFbZ>>Yu3yFuMQ% diff --git a/typescript/bedrock-kb-agent/bin/bedrock-kb-agent.ts b/typescript/bedrock-kb-agent/bin/bedrock-kb-agent.ts deleted file mode 100644 index 05852440ba..0000000000 --- a/typescript/bedrock-kb-agent/bin/bedrock-kb-agent.ts +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env node -import * as cdk from 'aws-cdk-lib'; -import { BedrockKbAgentStack } from '../lib/bedrock-kb-agent-stack'; - -const app = new cdk.App(); -new BedrockKbAgentStack(app, 'BedrockKbAgentStack', { - /* If you don't specify 'env', this stack will be environment-agnostic. - * Account/Region-dependent features and context lookups will not work, - * but a single synthesized template can be deployed anywhere. */ - - /* Uncomment the next line to specialize this stack for the AWS Account - * and Region that are implied by the current CLI configuration. */ - // env: { account: process.env.CDK_DEFAULT_ACCOUNT, region: process.env.CDK_DEFAULT_REGION }, - - /* Uncomment the next line if you know exactly what Account and Region you - * want to deploy the stack to. */ - // env: { account: '123456789012', region: 'us-east-1' }, - - /* For more information, see https://docs.aws.amazon.com/cdk/latest/guide/environments.html */ -}); \ No newline at end of file diff --git a/typescript/bedrock-kb-agent/cdk.json b/typescript/bedrock-kb-agent/cdk.json deleted file mode 100644 index 76e9a1c819..0000000000 --- a/typescript/bedrock-kb-agent/cdk.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "app": "npx ts-node --prefer-ts-exts bin/bedrock-kb-agent.ts", - "watch": { - "include": [ - "**" - ], - "exclude": [ - "README.md", - "cdk*.json", - "**/*.d.ts", - "**/*.js", - "tsconfig.json", - "package*.json", - "yarn.lock", - "node_modules", - "test" - ] - }, - "context": { - "@aws-cdk/aws-lambda:recognizeLayerVersion": true, - "@aws-cdk/core:checkSecretUsage": true, - "@aws-cdk/core:target-partitions": [ - "aws", - "aws-cn" - ], - "@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true, - "@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true, - "@aws-cdk/aws-ecs:arnFormatIncludesClusterName": true, - "@aws-cdk/aws-iam:minimizePolicies": true, - "@aws-cdk/core:validateSnapshotRemovalPolicy": true, - "@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": true, - "@aws-cdk/aws-s3:createDefaultLoggingPolicy": true, - "@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": true, - "@aws-cdk/aws-apigateway:disableCloudWatchRole": true, - "@aws-cdk/core:enablePartitionLiterals": true, - "@aws-cdk/aws-events:eventsTargetQueueSameAccount": true, - "@aws-cdk/aws-ecs:disableExplicitDeploymentControllerForCircuitBreaker": true, - "@aws-cdk/aws-iam:importedRoleStackSafeDefaultPolicyName": true, - "@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy": true, - "@aws-cdk/aws-route53-patters:useCertificate": true, - "@aws-cdk/customresources:installLatestAwsSdkDefault": false, - "@aws-cdk/aws-rds:databaseProxyUniqueResourceName": true, - "@aws-cdk/aws-codedeploy:removeAlarmsFromDeploymentGroup": true, - "@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId": true, - "@aws-cdk/aws-ec2:launchTemplateDefaultUserData": true, - "@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments": true, - "@aws-cdk/aws-redshift:columnId": true, - "@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2": true, - "@aws-cdk/aws-ec2:restrictDefaultSecurityGroup": true, - "@aws-cdk/aws-apigateway:requestValidatorUniqueId": true, - "@aws-cdk/aws-kms:aliasNameRef": true, - "@aws-cdk/aws-autoscaling:generateLaunchTemplateInsteadOfLaunchConfig": true, - "@aws-cdk/core:includePrefixInUniqueNameGeneration": true, - "@aws-cdk/aws-efs:denyAnonymousAccess": true, - "@aws-cdk/aws-opensearchservice:enableOpensearchMultiAzWithStandby": true, - "@aws-cdk/aws-lambda-nodejs:useLatestRuntimeVersion": true, - "@aws-cdk/aws-efs:mountTargetOrderInsensitiveLogicalId": true, - "@aws-cdk/aws-rds:auroraClusterChangeScopeOfInstanceParameterGroupWithEachParameters": true, - "@aws-cdk/aws-appsync:useArnForSourceApiAssociationIdentifier": true, - "@aws-cdk/aws-rds:preventRenderingDeprecatedCredentials": true, - "@aws-cdk/aws-codepipeline-actions:useNewDefaultBranchForCodeCommitSource": true, - "@aws-cdk/aws-cloudwatch-actions:changeLambdaPermissionLogicalIdForLambdaAction": true, - "@aws-cdk/aws-codepipeline:crossAccountKeysDefaultValueToFalse": true, - "@aws-cdk/aws-codepipeline:defaultPipelineTypeToV2": true, - "@aws-cdk/aws-kms:reduceCrossAccountRegionPolicyScope": true, - "@aws-cdk/aws-eks:nodegroupNameAttribute": true, - "@aws-cdk/aws-ec2:ebsDefaultGp3Volume": true, - "@aws-cdk/aws-ecs:removeDefaultDeploymentAlarm": true, - "@aws-cdk/custom-resources:logApiResponseDataPropertyTrueDefault": false, - "@aws-cdk/aws-s3:keepNotificationInImportedBucket": false, - "@aws-cdk/aws-ecs:reduceEc2FargateCloudWatchPermissions": true, - "@aws-cdk/aws-dynamodb:resourcePolicyPerReplica": true, - "@aws-cdk/aws-ec2:ec2SumTImeoutEnabled": true, - "@aws-cdk/aws-appsync:appSyncGraphQLAPIScopeLambdaPermission": true, - "@aws-cdk/aws-rds:setCorrectValueForDatabaseInstanceReadReplicaInstanceResourceId": true, - "@aws-cdk/core:cfnIncludeRejectComplexResourceUpdateCreatePolicyIntrinsics": true, - "@aws-cdk/aws-lambda-nodejs:sdkV3ExcludeSmithyPackages": true, - "@aws-cdk/aws-stepfunctions-tasks:fixRunEcsTaskPolicy": true, - "@aws-cdk/aws-ec2:bastionHostUseAmazonLinux2023ByDefault": true - } -} diff --git a/typescript/bedrock-kb-agent/lib/bedrock-kb-agent-stack.ts b/typescript/bedrock-kb-agent/lib/bedrock-kb-agent-stack.ts deleted file mode 100644 index fdf05cd5ec..0000000000 --- a/typescript/bedrock-kb-agent/lib/bedrock-kb-agent-stack.ts +++ /dev/null @@ -1,213 +0,0 @@ -/** - * Copyright 2023 Amazon.com, Inc. and its affiliates. All Rights Reserved. - * - * Licensed under the Amazon Software License (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/asl/ - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -import * as cdk from "aws-cdk-lib"; -import * as lambdaPython from "@aws-cdk/aws-lambda-python-alpha"; -import * as genai from "@cdklabs/generative-ai-cdk-constructs"; -import { ApiGatewayV2CloudFrontConstruct } from "./constructs/apigatewayv2-cloudfront-construct"; -import { ApiGatewayV2LambdaConstruct } from "./constructs/apigatewayv2-lambda-construct"; -import { CloudFrontS3WebSiteConstruct } from "./constructs/cloudfront-s3-website-construct"; -import { Construct } from "constructs"; -import { CognitoWebNativeConstruct } from "./constructs/cognito-web-native-construct"; -import { S3Construct } from "./constructs/s3-construct"; -import { NagSuppressions } from "cdk-nag"; - -export class BedrockKbAgentStack extends cdk.Stack { - constructor(scope: Construct, id: string, props: cdk.StackProps) { - super(scope, id, props); - - const cognito = new CognitoWebNativeConstruct(this, "Cognito", props); - - const webAppBuildPath = "./web-app/dist"; - - const website = new CloudFrontS3WebSiteConstruct(this, "WebApp", { - userPoolId: cognito.userPool.userPoolId, - appClientId: cognito.webClientId, - identityPoolId: cognito.identityPoolId, - webSiteBuildPath: webAppBuildPath, - withApi: true, - // If you have created a bucket to be used as Storage for amplify - // use the following prop - // storageBucketName: myBucket.bucketName - }); - - const api = new ApiGatewayV2CloudFrontConstruct(this, "Api", { - cloudFrontDistribution: website.cloudFrontDistribution, - userPool: cognito.userPool, - userPoolClient: cognito.webClientUserPool, - }); - - const exampleFn = new lambdaPython.PythonFunction(this, "ExampleLambdaFn", { - runtime: cdk.aws_lambda.Runtime.PYTHON_3_10, - handler: "lambda_handler", - index: "example.py", - entry: "./api/example-powertools", - timeout: cdk.Duration.seconds(60), - environment: {}, - initialPolicy: [ - new cdk.aws_iam.PolicyStatement({ - effect: cdk.aws_iam.Effect.ALLOW, - actions: ["bedrock:RetrieveAndGenerate", "bedrock:Retrieve", "bedrock:InvokeModel", "bedrock:InvokeAgent"], - resources: ["*"], - }), - ], - - }); - - new ApiGatewayV2LambdaConstruct(this, "ExampleKBGateway", { - lambdaFn: exampleFn, - routePath: "/api/v1/example", - methods: [ - cdk.aws_apigatewayv2.HttpMethod.POST, - ], - api: api.apiGatewayV2, - }); - - new ApiGatewayV2LambdaConstruct(this, "ExampleAgentGateway", { - lambdaFn: exampleFn, - routePath: "/api/v1/weather", - methods: [ - cdk.aws_apigatewayv2.HttpMethod.POST, - ], - api: api.apiGatewayV2, - }); - const knowledgeBaseBucket = new S3Construct( - this, - `KnowledgeBase-${this.stackName}`, - {}, - ); - const knowledgeBase = this.buildKnowledgeBase({ - bucket: knowledgeBaseBucket.dataBucket, - knowledgeBaseFolder: "knowledge-base/", - }); - - exampleFn.addEnvironment("KNOWLEDGE_BASE_ID", knowledgeBase.knowledgeBaseId); - - const agent = this.buildAgent([knowledgeBase]); - - if (!agent.aliasName) { - throw Error("The agent must have a valid alias"); - } - if (!agent.aliasId) { - throw Error("The agent must have a valid alias"); - } - - exampleFn.addEnvironment("AGENT_ID", agent.agentId); - exampleFn.addEnvironment("AGENT_ALIAS_ID", agent.aliasId); - } - - private buildKnowledgeBase({ - bucket, - knowledgeBaseFolder, - }: { - bucket: cdk.aws_s3.Bucket; - knowledgeBaseFolder: string; - }): genai.bedrock.KnowledgeBase { - const knowledgeBase = new genai.bedrock.KnowledgeBase( - this, - "BedrockKnowledgeBase", - { - embeddingsModel: - genai.bedrock.BedrockFoundationModel.TITAN_EMBED_TEXT_V1, - instruction: - "Use this knowledge base to answer questions about Amazon Web Services products.", - }, - ); - - new genai.bedrock.S3DataSource(this, "DataSource", { - bucket: bucket, - knowledgeBase: knowledgeBase, - dataSourceName: `DataSource-${this.stackName}`, - inclusionPrefixes: [knowledgeBaseFolder], - chunkingStrategy: genai.bedrock.ChunkingStrategy.FIXED_SIZE, - }); - - NagSuppressions.addResourceSuppressionsByPath( - this, - `/${this.node.id}/LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a/ServiceRole/DefaultPolicy/Resource`, - [ - { - id: "AwsSolutions-IAM5", - reason: - "Resource automatically created by the Bedrock constructs and cannot be modified", - appliesTo: ["Resource::*"], - }, - ], - true, - ); - - return knowledgeBase; - } - - private buildAgent(knowledgeBases: genai.bedrock.KnowledgeBase[]): genai.bedrock.Agent { - const fn = new lambdaPython.PythonFunction(this, "agent", { - runtime: cdk.aws_lambda.Runtime.PYTHON_3_10, - handler: "lambda_handler", - index: "example.py", - entry: "./api/example-agent", - description: `Agent lambda for [${this.stackName}]`, - timeout: cdk.Duration.minutes(4), - memorySize: 10240, - - initialPolicy: [ - new cdk.aws_iam.PolicyStatement({ - effect: cdk.aws_iam.Effect.ALLOW, - actions: ["bedrock:InvokeModel"], - resources: ["*"], - }), - ], - reservedConcurrentExecutions: 1, - }); - - const timestamp = new Date().toISOString().replace(/[-:T]/g, "").split(".")[0]; - const aliasName = `agent-${timestamp}`; - - const agent = new genai.bedrock.Agent(this, "Agent", { - name: `Agent-${this.stackName}`, - aliasName: aliasName, - foundationModel: - genai.bedrock.BedrockFoundationModel.ANTHROPIC_CLAUDE_V2_1, - instruction: - "You are a helpful and friendly agent that answers weather related questions.", - knowledgeBases: knowledgeBases, - }); - - const actionGroup = new genai.bedrock.AgentActionGroup( - this, - "ActionGroup", - { - actionGroupName: "weatherAG", - description: - "Use these functions to get information about weather in a given location.", - actionGroupExecutor: { - lambda: fn, - }, - actionGroupState: "ENABLED", - apiSchema: genai.bedrock.ApiSchema.fromAsset("./api/example-agent/openapi.json",), - }, - ); - - agent.addActionGroup(actionGroup); - new cdk.CfnOutput(this, "AgentId", { value: agent.agentId }); - if (agent.aliasId) { - new cdk.CfnOutput(this, "AgentAliasId", { value: agent.aliasId }); - } - if (agent.aliasName) { - new cdk.CfnOutput(this, "AgentAliasName", { value: agent.aliasName }); - } - - return agent; - } -} diff --git a/typescript/bedrock-kb-agent/lib/constructs/apigatewayv2-cloudfront-construct.ts b/typescript/bedrock-kb-agent/lib/constructs/apigatewayv2-cloudfront-construct.ts deleted file mode 100644 index 654fb6f4a2..0000000000 --- a/typescript/bedrock-kb-agent/lib/constructs/apigatewayv2-cloudfront-construct.ts +++ /dev/null @@ -1,161 +0,0 @@ -/** - * Copyright 2023 Amazon.com, Inc. and its affiliates. All Rights Reserved. - * - * Licensed under the Amazon Software License (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/asl/ - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -import * as cdk from "aws-cdk-lib"; -import { Construct } from "constructs"; - -export interface ApiGatewayV2CloudFrontProps extends cdk.StackProps { - /** - * The Cognito UserPool to use for the default authorizer - */ - readonly userPool: cdk.aws_cognito.UserPool; - /** - * The Cognito UserPoolClient to use for the default authorizer - */ - readonly userPoolClient: cdk.aws_cognito.UserPoolClient; - /** - * The CloudFront Distribution to attach the `/api/*` behavior - */ - readonly cloudFrontDistribution: cdk.aws_cloudfront.Distribution; -} - -const defaultProps: Partial = {}; - -/** - * Deploys Api gateway proxied through a CloudFront distribution at route `/api` - * - * Any Api's attached to the gateway should be located at `/api/*` so that requests are correctly proxied. - * Make sure Api's return the header `"Cache-Control" = "no-cache, no-store"` or CloudFront will cache responses - * - * CORS: allowed origins for local development: - * - https://example.com:3000, http://example.com:3000 - * - * For a more relaxed CORS posture, you can set `allowCredentials: false`, then set `allowOrigins: ["*"]` - * - * Creates: - * - ApiGatewayV2 HttpApi - */ -export class ApiGatewayV2CloudFrontConstruct extends Construct { - /** - * Returns the ApiGatewayV2 instance to attach lambdas or other routes - */ - public apiGatewayV2: cdk.aws_apigatewayv2.HttpApi; - - constructor(parent: Construct, name: string, props: ApiGatewayV2CloudFrontProps) { - super(parent, name); - - props = { ...defaultProps, ...props }; - - // get the parent stack reference for the stackName and the aws region - const stack = cdk.Stack.of(this); - - // init cognito authorizer - const cognitoAuth = new cdk.aws_apigatewayv2_authorizers.HttpUserPoolAuthorizer( - "apiAuth", - props.userPool, - { - userPoolClients: [props.userPoolClient], - }, - ); - - // init api gateway - const api = new cdk.aws_apigatewayv2.HttpApi(this, "Api", { - apiName: `${stack.stackName}Api`, - // corsPreflight: { - // allowHeaders: [ - // "Authorization", - // "Content-Type", - // "Origin", - // "X-Amz-Date", - // "X-Api-Key", - // "X-Amz-Security-Token", - // "X-Amz-User-Agent", - // ], - // allowMethods: [ - // // remove methods you don't use for tighter security - // cdk.aws_apigatewayv2.CorsHttpMethod.DELETE, - // cdk.aws_apigatewayv2.CorsHttpMethod.GET, - // cdk.aws_apigatewayv2.CorsHttpMethod.HEAD, - // cdk.aws_apigatewayv2.CorsHttpMethod.OPTIONS, - // cdk.aws_apigatewayv2.CorsHttpMethod.PATCH, - // cdk.aws_apigatewayv2.CorsHttpMethod.POST, - // cdk.aws_apigatewayv2.CorsHttpMethod.PUT, - // ], - // // allow origins for development. no origin is needed for cloudfront - // allowOrigins: ["*"], - // exposeHeaders: ["Access-Control-Allow-Origin"], - // maxAge: cdk.Duration.hours(1), - // allowCredentials: false, - // }, - defaultAuthorizer: cognitoAuth, - }); - - const apiUrl = `${api.httpApiId}.execute-api.${stack.region}.amazonaws.com`; - this.addBehaviorToCloudFrontDistribution(props.cloudFrontDistribution, apiUrl); - - // export any cf outputs - new cdk.CfnOutput(this, "GatewayUrl", { - value: `https://${apiUrl}`, - }); - - // assign public properties - this.apiGatewayV2 = api; - } - - /** - * Adds a proxy route from CloudFront /api to the api gateway url - * @param cloudFrontDistribution - * @param apiUrl - */ - private addBehaviorToCloudFrontDistribution( - cloudFrontDistribution: cdk.aws_cloudfront.Distribution, - apiUrl: string, - ) { - cloudFrontDistribution.addBehavior( - "/api/*", - new cdk.aws_cloudfront_origins.HttpOrigin(apiUrl, { - originSslProtocols: [cdk.aws_cloudfront.OriginSslPolicy.TLS_V1_2], - protocolPolicy: cdk.aws_cloudfront.OriginProtocolPolicy.HTTPS_ONLY, - }), - { - cachePolicy: new cdk.aws_cloudfront.CachePolicy(this, "CachePolicy", { - // required or CloudFront will strip the Authorization token from the request. - // must be in the cache policy - headerBehavior: - cdk.aws_cloudfront.CacheHeaderBehavior.allowList("Authorization"), - queryStringBehavior: cdk.aws_cloudfront.CacheQueryStringBehavior.all(), - enableAcceptEncodingGzip: true, - minTtl: cdk.Duration.seconds(0), - defaultTtl: cdk.Duration.seconds(0), - }), - originRequestPolicy: new cdk.aws_cloudfront.OriginRequestPolicy( - this, - "OriginRequestPolicy", - { - headerBehavior: cdk.aws_cloudfront.OriginRequestHeaderBehavior.allowList( - "User-Agent", - "Referer", - ), - // required or CloudFront will strip all query strings off the request - queryStringBehavior: - cdk.aws_cloudfront.OriginRequestQueryStringBehavior.all(), - }, - ), - allowedMethods: cdk.aws_cloudfront.AllowedMethods.ALLOW_ALL, - viewerProtocolPolicy: cdk.aws_cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS, - }, - ); - } -} diff --git a/typescript/bedrock-kb-agent/lib/constructs/apigatewayv2-lambda-construct.ts b/typescript/bedrock-kb-agent/lib/constructs/apigatewayv2-lambda-construct.ts deleted file mode 100644 index 6d04381d26..0000000000 --- a/typescript/bedrock-kb-agent/lib/constructs/apigatewayv2-lambda-construct.ts +++ /dev/null @@ -1,66 +0,0 @@ -/** - * Copyright 2023 Amazon.com, Inc. and its affiliates. All Rights Reserved. - * - * Licensed under the Amazon Software License (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/asl/ - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -import * as cdk from "aws-cdk-lib"; -import { Construct } from "constructs"; - -export interface ApiGatewayV2LambdaConstructProps extends cdk.StackProps { - /** - * The lambda function - */ - readonly lambdaFn: cdk.aws_lambda.Function; - /** - * The apigatewayv2 route path - */ - readonly routePath: string; - /** - * Api methods supported by this API - */ - readonly methods: Array; - /** - * The ApiGatewayV2 HttpApi to attach the lambda - */ - readonly api: cdk.aws_apigatewayv2.HttpApi; -} - -const defaultProps: Partial = {}; - -/** - * Deploys a lambda and attaches it to a route on the apigatewayv2 - */ -export class ApiGatewayV2LambdaConstruct extends Construct { - constructor(parent: Construct, name: string, props: ApiGatewayV2LambdaConstructProps) { - super(parent, name); - - props = { ...defaultProps, ...props }; - - // add lambda policies - props.lambdaFn.grantInvoke(new cdk.aws_iam.ServicePrincipal("apigateway.amazonaws.com")); - - // add lambda integration - const lambdaFnIntegration = new cdk.aws_apigatewayv2_integrations.HttpLambdaIntegration( - "apiInt", - props.lambdaFn, - {}, - ); - - // add route to the api gateway - props.api.addRoutes({ - path: props.routePath, - methods: props.methods, - integration: lambdaFnIntegration, - }); - } -} diff --git a/typescript/bedrock-kb-agent/lib/constructs/cloudfront-s3-website-construct.ts b/typescript/bedrock-kb-agent/lib/constructs/cloudfront-s3-website-construct.ts deleted file mode 100644 index 476ebefeb5..0000000000 --- a/typescript/bedrock-kb-agent/lib/constructs/cloudfront-s3-website-construct.ts +++ /dev/null @@ -1,225 +0,0 @@ -/** - * Copyright 2024 Amazon.com, Inc. and its affiliates. All Rights Reserved. - * - * Licensed under the Amazon Software License (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/asl/ - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -import * as cdk from "aws-cdk-lib"; -import { Construct } from "constructs"; -import * as cloudfront_origins from "aws-cdk-lib/aws-cloudfront-origins"; - -export interface CloudFrontS3WebSiteConstructProps extends cdk.StackProps { - /** - * The path to the build directory of the web site, relative to the project root - * ex: "./app/dist" - */ - readonly webSiteBuildPath: string; - - /** - * The Arn of the WafV2 WebAcl. - */ - readonly webAclArn?: string; - /** - * The Cognito UserPoolId to authenticate users in the front-end - */ - readonly userPoolId: string; - - /** - * The Cognito AppClientId to authenticate users in the front-end - */ - readonly appClientId: string; - - /** - * The Cognito IdentityPoolId to authenticate users in the front-end - */ - readonly identityPoolId: string; - - /** - * The name of the bucket to use as storage using Amplify SDK if required - */ - readonly storageBucketName?: string; - - /** - * If you use Amplify SDK to access an API serving under /api path set this boolean to true - */ - readonly withApi?: boolean; -} - -const defaultProps: Partial = {}; - -/** - * Deploys a CloudFront Distribution pointing to an S3 bucket containing the deployed web application {webSiteBuildPath}. - * Creates: - * - S3 bucket - * - CloudFrontDistribution - * - OriginAccessIdentity - * - * On redeployment, will automatically invalidate the CloudFront distribution cache - */ -export class CloudFrontS3WebSiteConstruct extends Construct { - /** - * The origin access identity used to access the S3 website - */ - public originAccessIdentity: cdk.aws_cloudfront.OriginAccessIdentity; - - /** - * The cloud front distribution to attach additional behaviors like `/api` - */ - public cloudFrontDistribution: cdk.aws_cloudfront.Distribution; - - /** - * The name of the bucket where the frontend assets are stored - */ - public siteBucket: cdk.aws_s3.Bucket; - - constructor( - parent: Construct, - name: string, - props: CloudFrontS3WebSiteConstructProps, - ) { - super(parent, name); - - props = { ...defaultProps, ...props }; - const stack = cdk.Stack.of(this); - const region = stack.region; - - // When using Distribution, do not set the s3 bucket website documents - // if these are set then the distribution origin is configured for HTTP communication with the - // s3 bucket and won't configure the cloudformation correctly. - this.siteBucket = new cdk.aws_s3.Bucket(this, "WebApp", { - encryption: cdk.aws_s3.BucketEncryption.S3_MANAGED, - autoDeleteObjects: true, - blockPublicAccess: cdk.aws_s3.BlockPublicAccess.BLOCK_ALL, - removalPolicy: cdk.RemovalPolicy.DESTROY, - enforceSSL: true, - }); - - this.siteBucket.addToResourcePolicy( - new cdk.aws_iam.PolicyStatement({ - sid: "EnforceTLS", - effect: cdk.aws_iam.Effect.DENY, - principals: [new cdk.aws_iam.AnyPrincipal()], - actions: ["s3:*"], - resources: [ - this.siteBucket.bucketArn, - this.siteBucket.bucketArn + "/*", - ], - conditions: { Bool: { "aws:SecureTransport": "false" } }, - }), - ); - - const originAccessIdentity = new cdk.aws_cloudfront.OriginAccessIdentity( - this, - "OriginAccessIdentity", - ); - this.siteBucket.grantRead(originAccessIdentity); - - // const s3origin = new cdk.aws_cloudfront_origins.S3Origin(this.siteBucket, { - // originAccessIdentity: originAccessIdentity, - // }); - - const cloudFrontDistribution = new cdk.aws_cloudfront.Distribution( - this, - "WebAppDistribution", - { - defaultBehavior: { - // origin: s3origin, - origin: cloudfront_origins.S3BucketOrigin.withOriginAccessControl( - this.siteBucket, - ), - - cachePolicy: new cdk.aws_cloudfront.CachePolicy(this, "CachePolicy", { - defaultTtl: cdk.Duration.hours(1), - }), - allowedMethods: cdk.aws_cloudfront.AllowedMethods.ALLOW_ALL, - viewerProtocolPolicy: - cdk.aws_cloudfront.ViewerProtocolPolicy.HTTPS_ONLY, - }, - errorResponses: [ - { - httpStatus: 404, - ttl: cdk.Duration.hours(0), - responseHttpStatus: 200, - responsePagePath: "/index.html", - }, - ], - defaultRootObject: "index.html", - webAclId: props.webAclArn, - minimumProtocolVersion: - cdk.aws_cloudfront.SecurityPolicyProtocol.TLS_V1_2_2021, // Required by security - }, - ); - - const amplifyConfig: any = { - Auth: { - Cognito: { - allowGuestAccess: false, - region: region, - userPoolId: props.userPoolId, - userPoolClientId: props.appClientId, - identityPoolId: props.identityPoolId, - }, - }, - }; - if (props.withApi) { - // Add or remove extra config properties you may need here like API or storage - - amplifyConfig.API = { - REST: { - api: { - endpoint: `./api`, - region: region, - }, - }, - }; - } - if (props.storageBucketName) { - amplifyConfig.Storage = { - S3: { - region: region, - bucket: props.storageBucketName, - }, - }; - } - - new cdk.aws_s3_deployment.BucketDeployment(this, "DeployWithInvalidation", { - sources: [ - cdk.aws_s3_deployment.Source.asset(props.webSiteBuildPath), // Main webapp from root directory - cdk.aws_s3_deployment.Source.jsonData("config.json", amplifyConfig), // Amplify config file - ], - destinationBucket: this.siteBucket, - distribution: cloudFrontDistribution, // this assignment, on redeploy, will automatically invalidate the cloudfront cache - distributionPaths: ["/*"], - // default of 128 isn't large enough for larger website deployments. More memory doesn't improve the performance. - // You want just enough memory to guarantee deployment - memoryLimit: 512, - }); - - // export any cf outputs - new cdk.CfnOutput(this, "SiteBucket", { - value: this.siteBucket.bucketName, - }); - new cdk.CfnOutput(this, "CloudFrontDistributionId", { - value: cloudFrontDistribution.distributionId, - }); - new cdk.CfnOutput(this, "CloudFrontDistributionDomainName", { - value: cloudFrontDistribution.distributionDomainName, - }); - new cdk.CfnOutput(this, "CloudFrontDistributionUrl", { - value: `https://${cloudFrontDistribution.distributionDomainName}`, - }); - - // assign public properties - this.originAccessIdentity = originAccessIdentity; - this.cloudFrontDistribution = cloudFrontDistribution; - } -} diff --git a/typescript/bedrock-kb-agent/lib/constructs/cognito-web-native-construct.ts b/typescript/bedrock-kb-agent/lib/constructs/cognito-web-native-construct.ts deleted file mode 100644 index 7e7c2ee9b3..0000000000 --- a/typescript/bedrock-kb-agent/lib/constructs/cognito-web-native-construct.ts +++ /dev/null @@ -1,208 +0,0 @@ -/** - * Copyright 2023 Amazon.com, Inc. and its affiliates. All Rights Reserved. - * - * Licensed under the Amazon Software License (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/asl/ - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -import * as cdk from "aws-cdk-lib"; -import { Construct } from "constructs"; - -/* eslint-disable @typescript-eslint/no-empty-interface */ -export interface CognitoWebNativeConstructProps extends cdk.StackProps {} - -const defaultProps: Partial = {}; - -/** - * Deploys Cognito with an Authenticated & UnAuthenticated Role with a Web and Native client - */ -export class CognitoWebNativeConstruct extends Construct { - public userPool: cdk.aws_cognito.UserPool; - public webClientUserPool: cdk.aws_cognito.UserPoolClient; - public nativeClientUserPool: cdk.aws_cognito.UserPoolClient; - public userPoolId: string; - public identityPoolId: string; - public webClientId: string; - public nativeClientId: string; - public authenticatedRole: cdk.aws_iam.Role; - public unauthenticatedRole: cdk.aws_iam.Role; - - constructor( - parent: Construct, - name: string, - props: CognitoWebNativeConstructProps, - ) { - super(parent, name); - - /* eslint-disable @typescript-eslint/no-unused-vars */ - props = { ...defaultProps, ...props }; - - const stack = cdk.Stack.of(this); - const stackName = stack.stackName; - - const userPool = new cdk.aws_cognito.UserPool(this, "UserPool", { - userPoolName: `UserPool${stackName}`, - selfSignUpEnabled: false, // Prototype front-ends that are public to the internet should keep this value as false - autoVerify: { email: true }, - userVerification: { - emailSubject: "Verify your email the app!", - emailBody: - "Hello {username}, Thanks for signing up to the app! Your verification code is {####}", - emailStyle: cdk.aws_cognito.VerificationEmailStyle.CODE, - smsMessage: - "Hello {username}, Thanks for signing up to app! Your verification code is {####}", - }, - passwordPolicy: { - minLength: 8, - requireDigits: true, - requireUppercase: true, - requireSymbols: true, - requireLowercase: true, - }, - removalPolicy: cdk.RemovalPolicy.DESTROY, - }); - - const userPoolWebClient = new cdk.aws_cognito.UserPoolClient( - this, - "UserPoolWebClient", - { - generateSecret: false, - userPool: userPool, - userPoolClientName: "WebClient", - authFlows: { - userPassword: true, - userSrp: true, - custom: true, - }, - }, - ); - - const userPoolNativeClient = new cdk.aws_cognito.UserPoolClient( - this, - "UserPoolNativeClient", - { - generateSecret: true, - userPool: userPool, - userPoolClientName: "NativeClient", - }, - ); - - const identityPool = new cdk.aws_cognito.CfnIdentityPool( - this, - "IdentityPool", - { - allowUnauthenticatedIdentities: false, - cognitoIdentityProviders: [ - { - clientId: userPoolWebClient.userPoolClientId, - providerName: userPool.userPoolProviderName, - }, - { - clientId: userPoolNativeClient.userPoolClientId, - providerName: userPool.userPoolProviderName, - }, - ], - }, - ); - - const unauthenticatedRole = new cdk.aws_iam.Role( - this, - "DefaultUnauthenticatedRole", - { - assumedBy: new cdk.aws_iam.FederatedPrincipal( - "cognito-identity.amazonaws.com", - { - StringEquals: { - "cognito-identity.amazonaws.com:aud": identityPool.ref, - }, - "ForAnyValue:StringLike": { - "cognito-identity.amazonaws.com:amr": "unauthenticated", - }, - }, - "sts:AssumeRoleWithWebIdentity", - ), - }, - ); - - const authenticatedRole = new cdk.aws_iam.Role( - this, - "DefaultAuthenticatedRole", - { - assumedBy: new cdk.aws_iam.FederatedPrincipal( - "cognito-identity.amazonaws.com", - { - StringEquals: { - "cognito-identity.amazonaws.com:aud": identityPool.ref, - }, - "ForAnyValue:StringLike": { - "cognito-identity.amazonaws.com:amr": "authenticated", - }, - }, - "sts:AssumeRoleWithWebIdentity", - ), - }, - ); - - new cdk.aws_cognito.CfnIdentityPoolRoleAttachment( - this, - "IdentityPoolRoleAttachment", - { - identityPoolId: identityPool.ref, - roles: { - unauthenticated: unauthenticatedRole.roleArn, - authenticated: authenticatedRole.roleArn, - }, - }, - ); - - // Assign Cfn Outputs - new cdk.CfnOutput(this, "UserPoolId", { - value: userPool.userPoolId, - }); - new cdk.CfnOutput(this, "IdentityPoolId", { - value: identityPool.ref, - }); - new cdk.CfnOutput(this, "WebClientId", { - value: userPoolWebClient.userPoolClientId, - }); - new cdk.CfnOutput(this, "NativeClientId", { - value: userPoolNativeClient.userPoolClientId, - }); - - // Add SSM Parameters - new cdk.aws_ssm.StringParameter(this, "COGNITO_USER_POOL_ID", { - stringValue: userPool.userPoolId, - }); - - new cdk.aws_ssm.StringParameter(this, "COGNITO_IDENTITY_POOL_ID", { - stringValue: identityPool.ref, - }); - - new cdk.aws_ssm.StringParameter(this, "COGNITO_WEB_CLIENT_ID", { - stringValue: userPoolWebClient.userPoolClientId, - }); - - new cdk.aws_ssm.StringParameter(this, "COGNITO_NATIVE_CLIENT_ID", { - stringValue: userPoolNativeClient.userPoolClientId, - }); - - // assign public properties - this.userPool = userPool; - this.webClientUserPool = userPoolWebClient; - this.nativeClientUserPool = userPoolNativeClient; - this.authenticatedRole = authenticatedRole; - this.unauthenticatedRole = unauthenticatedRole; - this.userPoolId = userPool.userPoolId; - this.identityPoolId = identityPool.ref; - this.webClientId = userPoolWebClient.userPoolClientId; - this.nativeClientId = userPoolNativeClient.userPoolClientId; - } -} diff --git a/typescript/bedrock-kb-agent/lib/constructs/s3-construct.ts b/typescript/bedrock-kb-agent/lib/constructs/s3-construct.ts deleted file mode 100755 index d67358d395..0000000000 --- a/typescript/bedrock-kb-agent/lib/constructs/s3-construct.ts +++ /dev/null @@ -1,84 +0,0 @@ -/** - * Copyright (c) 2024 Amazon.com, Inc. and its affiliates. - * All Rights Reserved. - * - * Licensed under the Amazon Software License (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/asl/ - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ -import * as cdk from "aws-cdk-lib"; -import { Construct } from "constructs"; - -export interface S3ConstructProps extends cdk.StackProps { - /** - * Is versioning enabled on this bucket ? - * - * @default true - */ - readonly versioned?: boolean; - - /** - * What is the role of this bucket, general use or for VPC, S3 logging etc. - * Selecting 'logging' will add LOG_DELIVERY_WRITE access control and will also - * enable tiered storage fro 30/90 archive/deep archive of logs. - * - * @default general - */ - readonly config?: "general" | "logging"; -} - -const defaultProps: Partial = { - versioned: true, - config: "general", -}; - -/** - * Deploys the s3 bucket - */ -export class S3Construct extends Construct { - public dataBucket: cdk.aws_s3.Bucket; - - constructor(parent: Construct, name: string, props: S3ConstructProps) { - super(parent, name); - - props = { ...defaultProps, ...props }; - - this.dataBucket = new cdk.aws_s3.Bucket(this, "Bucket", { - encryption: cdk.aws_s3.BucketEncryption.S3_MANAGED, - blockPublicAccess: cdk.aws_s3.BlockPublicAccess.BLOCK_ALL, - enforceSSL: true, - versioned: props.versioned, - autoDeleteObjects: true, // NOT recommended for production code - removalPolicy: cdk.RemovalPolicy.DESTROY, // NOT recommended for production code - accessControl: - props.config === "logging" - ? cdk.aws_s3.BucketAccessControl.LOG_DELIVERY_WRITE - : undefined, - intelligentTieringConfigurations: - props.config === "logging" - ? [ - { - name: "archive", - archiveAccessTierTime: cdk.Duration.days(90), //Days specified in ARCHIVE_ACCESS tier should not be less than 90 - deepArchiveAccessTierTime: cdk.Duration.days(180), //Days specified in DEEP_ARCHIVE_ACCESS should not be less than 180, and be greater than days specified in ARCHIVE_ACCESS - }, - ] - : undefined, - }); - - new cdk.CfnOutput(this, `BucketName`, { - value: `${this.dataBucket.bucketName}`, - }); - - new cdk.CfnOutput(this, `BucketArn`, { - value: `${this.dataBucket.bucketArn}`, - }); - } -} diff --git a/typescript/bedrock-kb-agent/media/kb-s3.png b/typescript/bedrock-kb-agent/media/kb-s3.png deleted file mode 100644 index 9ebe819972480f5a4f4957888348986b7980b28c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 115952 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 diff --git a/typescript/bedrock-kb-agent/package.json b/typescript/bedrock-kb-agent/package.json deleted file mode 100644 index 288ca52f89..0000000000 --- a/typescript/bedrock-kb-agent/package.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "name": "bedrock-kb-agent", - "version": "0.1.0", - "bin": { - "bedrock-kb-agent": "bin/bedrock-kb-agent.js" - }, - "scripts": { - "build": "tsc", - "watch": "tsc -w", - "test": "jest", - "cdk": "cdk" - }, - "devDependencies": { - "@types/jest": "^29.5.14", - "@types/node": "22.7.9", - "@typescript-eslint/eslint-plugin": "^7.0.0", - "@typescript-eslint/parser": "^7.0.0", - "aws-cdk": "2.1004.0", - "aws-cdk-lib": "^2.173.2", - "aws-sdk": "^2.1518.0", - "cdk-nag": "^2.27.216", - "constructs": "^10.3.0", - "eslint": "^8.9.0", - "eslint-config-prettier": "^9.1.0", - "eslint-plugin-prettier": "^5.1.3", - "git-branch": "^1.0.0", - "git-repo-name": "^1.0.1", - "jest": "^29.7.0", - "source-map-support": "^0.5.16", - "ts-node": "^10.9.2", - "typescript": "~5.6.3", - "@aws-cdk/aws-lambda-python-alpha": "^2.114.1-alpha.0", - "@cdklabs/generative-ai-cdk-constructs": "^0.1.278", - "ts-jest": "^29.2.5" - }, - "dependencies": { - "aws-cdk-lib": "2.185.0", - "constructs": "^10.0.0" - }, - "jest": { - "testEnvironment": "node", - "roots": [ - "/test" - ], - "testMatch": [ - "**/*.test.ts" - ], - "transform": { - "^.+\\.tsx?$": "ts-jest" - } - } -} diff --git a/typescript/bedrock-kb-agent/test/bedrock-kb-agent-stack.test.ts b/typescript/bedrock-kb-agent/test/bedrock-kb-agent-stack.test.ts deleted file mode 100644 index fc155df33a..0000000000 --- a/typescript/bedrock-kb-agent/test/bedrock-kb-agent-stack.test.ts +++ /dev/null @@ -1,104 +0,0 @@ -import * as cdk from "aws-cdk-lib"; -import { Template } from "aws-cdk-lib/assertions"; -import { BedrockKbAgentStack } from "../lib/bedrock-kb-agent-stack"; - -describe("BedrockKbAgentStack", () => { - let app: cdk.App; - let stack: BedrockKbAgentStack; - let template: Template; - - beforeEach(() => { - app = new cdk.App(); - stack = new BedrockKbAgentStack(app, "TestStack", { - env: { account: "123456789012", region: "us-east-1" }, - }); - template = Template.fromStack(stack); - }); - - test("Cognito User Pool is created with correct name", () => { - template.hasResourceProperties("AWS::Cognito::UserPool", { - UserPoolName: "UserPoolTestStack", - }); - }); - - test("API Gateway HTTP API is created", () => { - template.hasResourceProperties("AWS::ApiGatewayV2::Api", { - ProtocolType: "HTTP", - }); - }); - - test("Lambda function is created with correct configuration", () => { - template.hasResourceProperties("AWS::Lambda::Function", { - Handler: "example.lambda_handler", - Runtime: "python3.10", - Timeout: 60, - }); - }); - test("At least one IAM policy includes required Bedrock permissions", () => { - const requiredActions = [ - "bedrock:RetrieveAndGenerate", - "bedrock:Retrieve", - "bedrock:InvokeModel", - "bedrock:InvokeAgent", - ]; - - const allPolicies = template.findResources("AWS::IAM::Policy"); - - const hasBedrockPermissions = Object.values(allPolicies).some((policy) => { - const statements = policy.Properties.PolicyDocument.Statement; - return statements.some( - (statement: any) => - statement.Effect === "Allow" && - Array.isArray(statement.Action) && - requiredActions.every((action) => statement.Action.includes(action)), - ); - }); - - expect(hasBedrockPermissions).toBe(true); - }); - - test("S3 bucket for knowledge base is created", () => { - template.hasResourceProperties("AWS::S3::Bucket", { - BucketEncryption: { - ServerSideEncryptionConfiguration: [ - { - ServerSideEncryptionByDefault: { - SSEAlgorithm: "AES256", - }, - }, - ], - }, - }); - }); - - test("Bedrock Knowledge Base is created", () => { - template.hasResourceProperties("AWS::Bedrock::KnowledgeBase", { - KnowledgeBaseConfiguration: { - Type: "VECTOR", - }, - }); - }); - - /// - - test("Bedrock Agent is created", () => { - template.hasResourceProperties("AWS::Bedrock::Agent", { - AgentName: "Agent-TestStack", - }); - }); - - test("API Gateway routes are created", () => { - template.hasResourceProperties("AWS::ApiGatewayV2::Route", { - RouteKey: "POST /api/v1/example", - }); - - template.hasResourceProperties("AWS::ApiGatewayV2::Route", { - RouteKey: "POST /api/v1/weather", - }); - }); - - test("Stack has the expected number of resources", () => { - const resources = template.toJSON().Resources; - expect(Object.keys(resources).length).toBeGreaterThan(0); - }); -}); diff --git a/typescript/bedrock-kb-agent/tsconfig.json b/typescript/bedrock-kb-agent/tsconfig.json deleted file mode 100644 index aaa7dc510f..0000000000 --- a/typescript/bedrock-kb-agent/tsconfig.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2020", - "module": "commonjs", - "lib": [ - "es2020", - "dom" - ], - "declaration": true, - "strict": true, - "noImplicitAny": true, - "strictNullChecks": true, - "noImplicitThis": true, - "alwaysStrict": true, - "noUnusedLocals": false, - "noUnusedParameters": false, - "noImplicitReturns": true, - "noFallthroughCasesInSwitch": false, - "inlineSourceMap": true, - "inlineSources": true, - "experimentalDecorators": true, - "strictPropertyInitialization": false, - "typeRoots": [ - "./node_modules/@types" - ] - }, - "exclude": [ - "node_modules", - "cdk.out" - ] -} diff --git a/typescript/bedrock-kb-agent/web-app/.gitkeep b/typescript/bedrock-kb-agent/web-app/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/typescript/bedrock-kb-agent/web-app/dist/.gitkeep b/typescript/bedrock-kb-agent/web-app/dist/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000