>": {
+ "Fn::Join": [
+ "",
+ [
+ ""https://",
+ {
+ "Ref": "DataAccessLayerDITApi51636B57",
+ },
+ ".execute-api.",
+ {
+ "Ref": "AWS::Region",
+ },
+ ".",
+ {
+ "Ref": "AWS::URLSuffix",
+ },
+ "/",
+ {
+ "Ref": "DataAccessLayerDITApiDeploymentStageprod1B577AB5",
+ },
+ "/"",
+ ],
+ ],
+ },
+ },
+ ],
+ "SourceMarkersConfig": [
+ {},
+ {},
+ ],
+ "SourceObjectKeys": "Omitted to remove snapshot dependency on hash",
+ "WaitForDistributionInvalidation": true,
+ },
+ "Type": "Custom::CDKBucketDeployment",
+ "UpdateReplacePolicy": "Delete",
+ },
+ "AuthInitialFullAccessUser3C7C83CA": {
+ "Properties": {
+ "UserAttributes": [
+ {
+ "Name": "email_verified",
+ "Value": "true",
+ },
+ {
+ "Name": "email",
+ "Value": {
+ "Ref": "AdminEmail",
+ },
+ },
+ ],
+ "UserPoolId": {
+ "Ref": "AuthUserPool8115E87F",
+ },
+ "Username": {
+ "Ref": "AdminEmail",
+ },
+ },
+ "Type": "AWS::Cognito::UserPoolUser",
+ },
+ "AuthManagedLoginBranding4DD8E3C1": {
+ "Properties": {
+ "ClientId": {
+ "Ref": "AuthUserPoolWebUIClient86DE5DEB",
+ },
+ "UseCognitoProvidedValues": true,
+ "UserPoolId": {
+ "Ref": "AuthUserPool8115E87F",
+ },
+ },
+ "Type": "AWS::Cognito::ManagedLoginBranding",
+ },
+ "AuthUserPool8115E87F": {
+ "DeletionPolicy": "Retain",
+ "Properties": {
+ "AccountRecoverySetting": {
+ "RecoveryMechanisms": [
+ {
+ "Name": "verified_email",
+ "Priority": 1,
+ },
+ ],
+ },
+ "AdminCreateUserConfig": {
+ "AllowAdminCreateUserOnly": true,
+ "InviteMessageTemplate": {
+ "EmailMessage": {
+ "Fn::Join": [
+ "",
+ [
+ "Dynamic Image Transformation on Amazon CloudFront - Web UI
Here are your temporary login credentials for the WebUI: https://",
+ {
+ "Fn::GetAtt": [
+ "WebDistributionAdminUIDistributionToS3CloudFrontDistribution6FD651BA",
+ "DomainName",
+ ],
+ },
+ "
+
+Region: ",
+ {
+ "Ref": "AWS::Region",
+ },
+ "
+Username: {username}
+Temporary Password: {####}
+
",
+ ],
+ ],
+ },
+ "EmailSubject": "Welcome to DIT",
+ },
+ },
+ "AutoVerifiedAttributes": [
+ "email",
+ ],
+ "EmailVerificationMessage": "Your Dynamic Image Transformation console verification code is {####}",
+ "EmailVerificationSubject": "Your Dynamic Image Transformation console verification code",
+ "EnabledMfas": [
+ "SOFTWARE_TOKEN_MFA",
+ ],
+ "MfaConfiguration": "ON",
+ "Policies": {
+ "PasswordPolicy": {
+ "MinimumLength": 8,
+ "RequireLowercase": true,
+ "RequireNumbers": true,
+ "RequireSymbols": true,
+ "RequireUppercase": true,
+ "TemporaryPasswordValidityDays": 7,
+ },
+ },
+ "Schema": [
+ {
+ "Mutable": false,
+ "Name": "email",
+ "Required": true,
+ },
+ ],
+ "SmsVerificationMessage": "The verification code to your new account is {####}",
+ "UserPoolAddOns": {
+ "AdvancedSecurityMode": "ENFORCED",
+ },
+ "UsernameAttributes": [
+ "email",
+ ],
+ "VerificationMessageTemplate": {
+ "DefaultEmailOption": "CONFIRM_WITH_CODE",
+ "EmailMessage": "Your Dynamic Image Transformation console verification code is {####}",
+ "EmailSubject": "Your Dynamic Image Transformation console verification code",
+ "SmsMessage": "The verification code to your new account is {####}",
+ },
+ },
+ "Type": "AWS::Cognito::UserPool",
+ "UpdateReplacePolicy": "Retain",
+ },
+ "AuthUserPoolResourceServerADA84D6F": {
+ "Properties": {
+ "Identifier": "dit-api",
+ "Name": "Resource server representing the API Gateway of the solution",
+ "Scopes": [
+ {
+ "ScopeDescription": "Access to solution API",
+ "ScopeName": "api",
+ },
+ ],
+ "UserPoolId": {
+ "Ref": "AuthUserPool8115E87F",
+ },
+ },
+ "Type": "AWS::Cognito::UserPoolResourceServer",
+ },
+ "AuthUserPoolUserPoolDomain4EEAE7CF": {
+ "Properties": {
+ "Domain": {
+ "Fn::Join": [
+ "",
+ [
+ "dit-",
+ {
+ "Ref": "AWS::AccountId",
+ },
+ "-",
+ {
+ "Ref": "AWS::Region",
+ },
+ ],
+ ],
+ },
+ "ManagedLoginVersion": 2,
+ "UserPoolId": {
+ "Ref": "AuthUserPool8115E87F",
+ },
+ },
+ "Type": "AWS::Cognito::UserPoolDomain",
+ },
+ "AuthUserPoolWebUIClient86DE5DEB": {
+ "DependsOn": [
+ "AuthUserPoolResourceServerADA84D6F",
+ ],
+ "Properties": {
+ "AccessTokenValidity": 60,
+ "AllowedOAuthFlows": [
+ "code",
+ ],
+ "AllowedOAuthFlowsUserPoolClient": true,
+ "AllowedOAuthScopes": [
+ "openid",
+ "profile",
+ "email",
+ "aws.cognito.signin.user.admin",
+ "dit-api/api",
+ ],
+ "CallbackURLs": [
+ {
+ "Fn::Join": [
+ "",
+ [
+ "https://",
+ {
+ "Fn::GetAtt": [
+ "WebDistributionAdminUIDistributionToS3CloudFrontDistribution6FD651BA",
+ "DomainName",
+ ],
+ },
+ "/",
+ ],
+ ],
+ },
+ ],
+ "ExplicitAuthFlows": [
+ "ALLOW_USER_SRP_AUTH",
+ "ALLOW_REFRESH_TOKEN_AUTH",
+ ],
+ "IdTokenValidity": 60,
+ "LogoutURLs": [
+ {
+ "Fn::Join": [
+ "",
+ [
+ "https://",
+ {
+ "Fn::GetAtt": [
+ "WebDistributionAdminUIDistributionToS3CloudFrontDistribution6FD651BA",
+ "DomainName",
+ ],
+ },
+ "/",
+ ],
+ ],
+ },
+ {
+ "Fn::Join": [
+ "",
+ [
+ "https://",
+ {
+ "Fn::GetAtt": [
+ "WebDistributionAdminUIDistributionToS3CloudFrontDistribution6FD651BA",
+ "DomainName",
+ ],
+ },
+ "/auth/logout-complete",
+ ],
+ ],
+ },
+ ],
+ "RefreshTokenValidity": 60,
+ "SupportedIdentityProviders": [
+ "COGNITO",
+ ],
+ "TokenValidityUnits": {
+ "AccessToken": "minutes",
+ "IdToken": "minutes",
+ "RefreshToken": "minutes",
+ },
+ "UserPoolId": {
+ "Ref": "AuthUserPool8115E87F",
+ },
+ },
+ "Type": "AWS::Cognito::UserPoolClient",
+ },
+ "CSPUpdaterCSPUpdaterCustomResource91C60D66": {
+ "DeletionPolicy": "Delete",
+ "Properties": {
+ "DistributionId": {
+ "Ref": "WebDistributionAdminUIDistributionToS3CloudFrontDistribution6FD651BA",
+ },
+ "ResponseHeadersPolicyId": {
+ "Ref": "CSPUpdaterEnhancedCSPPolicy29E9C1BA",
+ },
+ "ServiceToken": {
+ "Fn::GetAtt": [
+ "CSPUpdaterCSPUpdaterProviderframeworkonEventE7D5E323",
+ "Arn",
+ ],
+ },
+ },
+ "Type": "AWS::CloudFormation::CustomResource",
+ "UpdateReplacePolicy": "Delete",
+ },
+ "CSPUpdaterCSPUpdaterFunction1ED2BD33": {
+ "DependsOn": [
+ "CSPUpdaterCSPUpdaterFunctionServiceRoleDefaultPolicyE164CCBB",
+ "CSPUpdaterCSPUpdaterFunctionServiceRoleDCA79242",
+ ],
+ "Metadata": {
+ "guard": {
+ "SuppressedRules": [
+ "LAMBDA_INSIDE_VPC",
+ "LAMBDA_CONCURRENCY_CHECK",
+ ],
+ },
+ },
+ "Properties": {
+ "Code": {
+ "S3Bucket": "Omitted to remove snapshot dependency on bucket",
+ "S3Key": "Omitted to remove snapshot dependency on hash",
+ },
+ "Environment": {
+ "Variables": {
+ "SOLUTION_ID": "SO0023",
+ "SOLUTION_VERSION": "v8.0.4",
+ },
+ },
+ "Handler": "index.handler",
+ "LoggingConfig": {
+ "LogGroup": {
+ "Ref": "CSPUpdaterCSPUpdaterFunctionLogGroup3255BE06",
+ },
+ },
+ "MemorySize": 512,
+ "Role": {
+ "Fn::GetAtt": [
+ "CSPUpdaterCSPUpdaterFunctionServiceRoleDCA79242",
+ "Arn",
+ ],
+ },
+ "Runtime": "nodejs22.x",
+ "Timeout": 30,
+ },
+ "Type": "AWS::Lambda::Function",
+ },
+ "CSPUpdaterCSPUpdaterFunctionLogGroup3255BE06": {
+ "DeletionPolicy": "Retain",
+ "Metadata": {
+ "guard": {
+ "SuppressedRules": [
+ "CLOUDWATCH_LOG_GROUP_ENCRYPTED",
+ ],
+ },
+ },
+ "Properties": {
+ "RetentionInDays": 3653,
+ },
+ "Type": "AWS::Logs::LogGroup",
+ "UpdateReplacePolicy": "Retain",
+ },
+ "CSPUpdaterCSPUpdaterFunctionServiceRoleDCA79242": {
+ "Properties": {
+ "AssumeRolePolicyDocument": {
+ "Statement": [
+ {
+ "Action": "sts:AssumeRole",
+ "Effect": "Allow",
+ "Principal": {
+ "Service": "lambda.amazonaws.com",
+ },
+ },
+ ],
+ "Version": "2012-10-17",
+ },
+ "ManagedPolicyArns": [
+ {
+ "Fn::Join": [
+ "",
+ [
+ "arn:",
+ {
+ "Ref": "AWS::Partition",
+ },
+ ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole",
+ ],
+ ],
+ },
+ ],
+ },
+ "Type": "AWS::IAM::Role",
+ },
+ "CSPUpdaterCSPUpdaterFunctionServiceRoleDefaultPolicyE164CCBB": {
+ "Properties": {
+ "PolicyDocument": {
+ "Statement": [
+ {
+ "Action": [
+ "cloudfront:GetDistributionConfig",
+ "cloudfront:UpdateDistribution",
+ ],
+ "Effect": "Allow",
+ "Resource": {
+ "Fn::Join": [
+ "",
+ [
+ "arn:aws:cloudfront::",
+ {
+ "Ref": "AWS::AccountId",
+ },
+ ":distribution/",
+ {
+ "Ref": "WebDistributionAdminUIDistributionToS3CloudFrontDistribution6FD651BA",
+ },
+ ],
+ ],
+ },
+ },
+ ],
+ "Version": "2012-10-17",
+ },
+ "PolicyName": "CSPUpdaterCSPUpdaterFunctionServiceRoleDefaultPolicyE164CCBB",
+ "Roles": [
+ {
+ "Ref": "CSPUpdaterCSPUpdaterFunctionServiceRoleDCA79242",
+ },
+ ],
+ },
+ "Type": "AWS::IAM::Policy",
+ },
+ "CSPUpdaterCSPUpdaterProviderframeworkonEventE7D5E323": {
+ "DependsOn": [
+ "CSPUpdaterCSPUpdaterProviderframeworkonEventServiceRoleDefaultPolicy0AFAE5F5",
+ "CSPUpdaterCSPUpdaterProviderframeworkonEventServiceRole9DF2EE66",
+ ],
+ "Metadata": {
+ "guard": {
+ "SuppressedRules": [
+ "LAMBDA_INSIDE_VPC",
+ "LAMBDA_CONCURRENCY_CHECK",
+ ],
+ },
+ },
+ "Properties": {
+ "Code": {
+ "S3Bucket": "Omitted to remove snapshot dependency on bucket",
+ "S3Key": "Omitted to remove snapshot dependency on hash",
+ },
+ "Description": "AWS CDK resource provider framework - onEvent (TestManagementStack/CSPUpdater/CSPUpdaterProvider)",
+ "Environment": {
+ "Variables": {
+ "USER_ON_EVENT_FUNCTION_ARN": {
+ "Fn::GetAtt": [
+ "CSPUpdaterCSPUpdaterFunction1ED2BD33",
+ "Arn",
+ ],
+ },
+ },
+ },
+ "Handler": "framework.onEvent",
+ "LoggingConfig": {
+ "ApplicationLogLevel": "FATAL",
+ "LogFormat": "JSON",
+ "LogGroup": {
+ "Ref": "CSPUpdaterCSPUpdaterFunctionLogGroup3255BE06",
+ },
+ },
+ "Role": {
+ "Fn::GetAtt": [
+ "CSPUpdaterCSPUpdaterProviderframeworkonEventServiceRole9DF2EE66",
+ "Arn",
+ ],
+ },
+ "Runtime": "nodejs22.x",
+ "Timeout": 900,
+ },
+ "Type": "AWS::Lambda::Function",
+ },
+ "CSPUpdaterCSPUpdaterProviderframeworkonEventServiceRole9DF2EE66": {
+ "Properties": {
+ "AssumeRolePolicyDocument": {
+ "Statement": [
+ {
+ "Action": "sts:AssumeRole",
+ "Effect": "Allow",
+ "Principal": {
+ "Service": "lambda.amazonaws.com",
+ },
+ },
+ ],
+ "Version": "2012-10-17",
+ },
+ "ManagedPolicyArns": [
+ {
+ "Fn::Join": [
+ "",
+ [
+ "arn:",
+ {
+ "Ref": "AWS::Partition",
+ },
+ ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole",
+ ],
+ ],
+ },
+ ],
+ },
+ "Type": "AWS::IAM::Role",
+ },
+ "CSPUpdaterCSPUpdaterProviderframeworkonEventServiceRoleDefaultPolicy0AFAE5F5": {
+ "Properties": {
+ "PolicyDocument": {
+ "Statement": [
+ {
+ "Action": "lambda:InvokeFunction",
+ "Effect": "Allow",
+ "Resource": [
+ {
+ "Fn::GetAtt": [
+ "CSPUpdaterCSPUpdaterFunction1ED2BD33",
+ "Arn",
+ ],
+ },
+ {
+ "Fn::Join": [
+ "",
+ [
+ {
+ "Fn::GetAtt": [
+ "CSPUpdaterCSPUpdaterFunction1ED2BD33",
+ "Arn",
+ ],
+ },
+ ":*",
+ ],
+ ],
+ },
+ ],
+ },
+ {
+ "Action": "lambda:GetFunction",
+ "Effect": "Allow",
+ "Resource": {
+ "Fn::GetAtt": [
+ "CSPUpdaterCSPUpdaterFunction1ED2BD33",
+ "Arn",
+ ],
+ },
+ },
+ ],
+ "Version": "2012-10-17",
+ },
+ "PolicyName": "CSPUpdaterCSPUpdaterProviderframeworkonEventServiceRoleDefaultPolicy0AFAE5F5",
+ "Roles": [
+ {
+ "Ref": "CSPUpdaterCSPUpdaterProviderframeworkonEventServiceRole9DF2EE66",
+ },
+ ],
+ },
+ "Type": "AWS::IAM::Policy",
+ },
+ "CSPUpdaterEnhancedCSPPolicy29E9C1BA": {
+ "Properties": {
+ "ResponseHeadersPolicyConfig": {
+ "Comment": "Enhanced security headers for CSP with external services",
+ "CustomHeadersConfig": {
+ "Items": [
+ {
+ "Header": "Cache-Control",
+ "Override": true,
+ "Value": "no-store, no-cache",
+ },
+ ],
+ },
+ "Name": {
+ "Fn::Join": [
+ "",
+ [
+ "CSP-for-DIT-Admin-UI-Enhanced-",
+ {
+ "Ref": "AWS::Region",
+ },
+ ],
+ ],
+ },
+ "SecurityHeadersConfig": {
+ "ContentSecurityPolicy": {
+ "ContentSecurityPolicy": {
+ "Fn::Join": [
+ "",
+ [
+ "upgrade-insecure-requests; object-src 'none'; frame-ancestors 'none'; base-uri 'none'; script-src 'self'; style-src 'self'; font-src 'self' data:; img-src 'self' data: https:; connect-src 'self' https://cognito-identity.",
+ {
+ "Ref": "AWS::Region",
+ },
+ ".amazonaws.com https://cognito-idp.",
+ {
+ "Ref": "AWS::Region",
+ },
+ ".amazonaws.com dit-",
+ {
+ "Ref": "AWS::AccountId",
+ },
+ "-",
+ {
+ "Ref": "AWS::Region",
+ },
+ ".auth.",
+ {
+ "Ref": "AWS::Region",
+ },
+ ".amazoncognito.com https://",
+ {
+ "Ref": "DataAccessLayerDITApi51636B57",
+ },
+ ".execute-api.",
+ {
+ "Ref": "AWS::Region",
+ },
+ ".",
+ {
+ "Ref": "AWS::URLSuffix",
+ },
+ "/",
+ {
+ "Ref": "DataAccessLayerDITApiDeploymentStageprod1B577AB5",
+ },
+ "/; default-src 'self';",
+ ],
+ ],
+ },
+ "Override": false,
+ },
+ "ContentTypeOptions": {
+ "Override": true,
+ },
+ "FrameOptions": {
+ "FrameOption": "DENY",
+ "Override": true,
+ },
+ "ReferrerPolicy": {
+ "Override": true,
+ "ReferrerPolicy": "strict-origin-when-cross-origin",
+ },
+ "StrictTransportSecurity": {
+ "AccessControlMaxAgeSec": 47304000,
+ "IncludeSubdomains": true,
+ "Override": true,
+ },
+ },
+ },
+ },
+ "Type": "AWS::CloudFront::ResponseHeadersPolicy",
+ },
+ "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C81C01536": {
+ "DependsOn": [
+ "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRoleDefaultPolicy88902FDF",
+ "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRole89A01265",
+ ],
+ "Metadata": {
+ "guard": {
+ "SuppressedRules": [
+ "LAMBDA_INSIDE_VPC",
+ "LAMBDA_CONCURRENCY_CHECK",
+ ],
+ },
+ },
+ "Properties": {
+ "Code": {
+ "S3Bucket": "Omitted to remove snapshot dependency on bucket",
+ "S3Key": "Omitted to remove snapshot dependency on hash",
+ },
+ "Environment": {
+ "Variables": {
+ "AWS_CA_BUNDLE": "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem",
+ },
+ },
+ "Handler": "index.handler",
+ "Layers": [
+ {
+ "Ref": "AdminUIDeploymentAwsCliLayer7F18FF6D",
+ },
+ ],
+ "Role": {
+ "Fn::GetAtt": [
+ "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRole89A01265",
+ "Arn",
+ ],
+ },
+ "Runtime": "python3.13",
+ "Timeout": 900,
+ },
+ "Type": "AWS::Lambda::Function",
+ },
+ "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CLogRetention1948627D": {
+ "Properties": {
+ "LogGroupName": {
+ "Fn::Join": [
+ "",
+ [
+ "/aws/lambda/",
+ {
+ "Ref": "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C81C01536",
+ },
+ ],
+ ],
+ },
+ "RetentionInDays": 3653,
+ "ServiceToken": {
+ "Fn::GetAtt": [
+ "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aFD4BFC8A",
+ "Arn",
+ ],
+ },
+ },
+ "Type": "Custom::LogRetention",
+ },
+ "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRole89A01265": {
+ "Properties": {
+ "AssumeRolePolicyDocument": {
+ "Statement": [
+ {
+ "Action": "sts:AssumeRole",
+ "Effect": "Allow",
+ "Principal": {
+ "Service": "lambda.amazonaws.com",
+ },
+ },
+ ],
+ "Version": "2012-10-17",
+ },
+ "ManagedPolicyArns": [
+ {
+ "Fn::Join": [
+ "",
+ [
+ "arn:",
+ {
+ "Ref": "AWS::Partition",
+ },
+ ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole",
+ ],
+ ],
+ },
+ ],
+ },
+ "Type": "AWS::IAM::Role",
+ },
+ "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRoleDefaultPolicy88902FDF": {
+ "Properties": {
+ "PolicyDocument": {
+ "Statement": [
+ {
+ "Action": [
+ "s3:GetObject*",
+ "s3:GetBucket*",
+ "s3:List*",
+ ],
+ "Effect": "Allow",
+ "Resource": [
+ {
+ "Fn::Join": [
+ "",
+ [
+ "arn:",
+ {
+ "Ref": "AWS::Partition",
+ },
+ ":s3:::",
+ {
+ "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}",
+ },
+ ],
+ ],
+ },
+ {
+ "Fn::Join": [
+ "",
+ [
+ "arn:",
+ {
+ "Ref": "AWS::Partition",
+ },
+ ":s3:::",
+ {
+ "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}",
+ },
+ "/*",
+ ],
+ ],
+ },
+ ],
+ },
+ {
+ "Action": [
+ "s3:GetObject*",
+ "s3:GetBucket*",
+ "s3:List*",
+ "s3:DeleteObject*",
+ "s3:PutObject",
+ "s3:PutObjectLegalHold",
+ "s3:PutObjectRetention",
+ "s3:PutObjectTagging",
+ "s3:PutObjectVersionTagging",
+ "s3:Abort*",
+ ],
+ "Effect": "Allow",
+ "Resource": [
+ {
+ "Fn::GetAtt": [
+ "WebDistributionAdminUIDistributionToS3S3BucketBEF73512",
+ "Arn",
+ ],
+ },
+ {
+ "Fn::Join": [
+ "",
+ [
+ {
+ "Fn::GetAtt": [
+ "WebDistributionAdminUIDistributionToS3S3BucketBEF73512",
+ "Arn",
+ ],
+ },
+ "/*",
+ ],
+ ],
+ },
+ ],
+ },
+ ],
+ "Version": "2012-10-17",
+ },
+ "PolicyName": "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRoleDefaultPolicy88902FDF",
+ "Roles": [
+ {
+ "Ref": "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRole89A01265",
+ },
+ ],
+ },
+ "Type": "AWS::IAM::Policy",
+ },
+ "DataAccessLayerApiLambda53F93106": {
+ "DependsOn": [
+ "DataAccessLayerApiLambdaServiceRoleDefaultPolicyEDE8072B",
+ "DataAccessLayerApiLambdaServiceRole24F83C52",
+ ],
+ "Metadata": {
+ "guard": {
+ "SuppressedRules": [
+ "LAMBDA_INSIDE_VPC",
+ "LAMBDA_CONCURRENCY_CHECK",
+ ],
+ },
+ },
+ "Properties": {
+ "Code": {
+ "S3Bucket": "Omitted to remove snapshot dependency on bucket",
+ "S3Key": "Omitted to remove snapshot dependency on hash",
+ },
+ "Environment": {
+ "Variables": {
+ "CONFIG_TABLE_NAME": {
+ "Ref": "DataAccessLayerConfigTableFC483DD7",
+ },
+ "CORS_ORIGIN": {
+ "Fn::Join": [
+ "",
+ [
+ "https://",
+ {
+ "Fn::GetAtt": [
+ "WebDistributionAdminUIDistributionToS3CloudFrontDistribution6FD651BA",
+ "DomainName",
+ ],
+ },
+ ],
+ ],
+ },
+ "POWERTOOLS_LOGGER_LOG_EVENT": "false",
+ "POWERTOOLS_LOGGER_LOG_LEVEL": "INFO",
+ "SOLUTION_ID": "SO0023",
+ "SOLUTION_VERSION": "v8.0.4",
+ },
+ },
+ "Handler": "index.handler",
+ "LoggingConfig": {
+ "LogGroup": {
+ "Ref": "DataAccessLayerApiLambdaLogGroup8B3CE8F8",
+ },
+ },
+ "MemorySize": 512,
+ "Role": {
+ "Fn::GetAtt": [
+ "DataAccessLayerApiLambdaServiceRole24F83C52",
+ "Arn",
+ ],
+ },
+ "Runtime": "nodejs22.x",
+ "Timeout": 30,
+ },
+ "Type": "AWS::Lambda::Function",
+ },
+ "DataAccessLayerApiLambdaLogGroup8B3CE8F8": {
+ "DeletionPolicy": "Retain",
+ "Metadata": {
+ "guard": {
+ "SuppressedRules": [
+ "CLOUDWATCH_LOG_GROUP_ENCRYPTED",
+ ],
+ },
+ },
+ "Properties": {
+ "RetentionInDays": 3653,
+ },
+ "Type": "AWS::Logs::LogGroup",
+ "UpdateReplacePolicy": "Retain",
+ },
+ "DataAccessLayerApiLambdaServiceRole24F83C52": {
+ "Properties": {
+ "AssumeRolePolicyDocument": {
+ "Statement": [
+ {
+ "Action": "sts:AssumeRole",
+ "Effect": "Allow",
+ "Principal": {
+ "Service": "lambda.amazonaws.com",
+ },
+ },
+ ],
+ "Version": "2012-10-17",
+ },
+ "ManagedPolicyArns": [
+ {
+ "Fn::Join": [
+ "",
+ [
+ "arn:",
+ {
+ "Ref": "AWS::Partition",
+ },
+ ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole",
+ ],
+ ],
+ },
+ ],
+ },
+ "Type": "AWS::IAM::Role",
+ },
+ "DataAccessLayerApiLambdaServiceRoleDefaultPolicyEDE8072B": {
+ "Properties": {
+ "PolicyDocument": {
+ "Statement": [
+ {
+ "Action": [
+ "dynamodb:BatchGetItem",
+ "dynamodb:Query",
+ "dynamodb:GetItem",
+ "dynamodb:Scan",
+ "dynamodb:ConditionCheckItem",
+ "dynamodb:BatchWriteItem",
+ "dynamodb:PutItem",
+ "dynamodb:UpdateItem",
+ "dynamodb:DeleteItem",
+ "dynamodb:DescribeTable",
+ ],
+ "Effect": "Allow",
+ "Resource": [
+ {
+ "Fn::GetAtt": [
+ "DataAccessLayerConfigTableFC483DD7",
+ "Arn",
+ ],
+ },
+ {
+ "Fn::Join": [
+ "",
+ [
+ {
+ "Fn::GetAtt": [
+ "DataAccessLayerConfigTableFC483DD7",
+ "Arn",
+ ],
+ },
+ "/index/*",
+ ],
+ ],
+ },
+ ],
+ },
+ {
+ "Action": [
+ "dynamodb:GetRecords",
+ "dynamodb:GetShardIterator",
+ ],
+ "Effect": "Allow",
+ "Resource": [
+ {
+ "Fn::GetAtt": [
+ "DataAccessLayerConfigTableFC483DD7",
+ "Arn",
+ ],
+ },
+ {
+ "Fn::Join": [
+ "",
+ [
+ {
+ "Fn::GetAtt": [
+ "DataAccessLayerConfigTableFC483DD7",
+ "Arn",
+ ],
+ },
+ "/index/*",
+ ],
+ ],
+ },
+ ],
+ },
+ ],
+ "Version": "2012-10-17",
+ },
+ "PolicyName": "DataAccessLayerApiLambdaServiceRoleDefaultPolicyEDE8072B",
+ "Roles": [
+ {
+ "Ref": "DataAccessLayerApiLambdaServiceRole24F83C52",
+ },
+ ],
+ },
+ "Type": "AWS::IAM::Policy",
+ },
+ "DataAccessLayerCORSResponse4xx88C1D1E3": {
+ "Properties": {
+ "ResponseParameters": {
+ "gatewayresponse.header.gatewayresponse.header.Access-Control-Allow-Headers": "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent'",
+ "gatewayresponse.header.gatewayresponse.header.Access-Control-Allow-Methods": "'GET,OPTIONS,POST,PUT,DELETE'",
+ "gatewayresponse.header.gatewayresponse.header.Access-Control-Allow-Origin": {
+ "Fn::Join": [
+ "",
+ [
+ "'https://",
+ {
+ "Fn::GetAtt": [
+ "WebDistributionAdminUIDistributionToS3CloudFrontDistribution6FD651BA",
+ "DomainName",
+ ],
+ },
+ "'",
+ ],
+ ],
+ },
+ },
+ "ResponseType": "DEFAULT_4XX",
+ "RestApiId": {
+ "Ref": "DataAccessLayerDITApi51636B57",
+ },
+ },
+ "Type": "AWS::ApiGateway::GatewayResponse",
+ },
+ "DataAccessLayerCORSResponse5xx07AEF476": {
+ "Properties": {
+ "ResponseParameters": {
+ "gatewayresponse.header.gatewayresponse.header.Access-Control-Allow-Headers": "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent'",
+ "gatewayresponse.header.gatewayresponse.header.Access-Control-Allow-Methods": "'GET,OPTIONS,POST,PUT,DELETE'",
+ "gatewayresponse.header.gatewayresponse.header.Access-Control-Allow-Origin": {
+ "Fn::Join": [
+ "",
+ [
+ "'https://",
+ {
+ "Fn::GetAtt": [
+ "WebDistributionAdminUIDistributionToS3CloudFrontDistribution6FD651BA",
+ "DomainName",
+ ],
+ },
+ "'",
+ ],
+ ],
+ },
+ },
+ "ResponseType": "DEFAULT_5XX",
+ "RestApiId": {
+ "Ref": "DataAccessLayerDITApi51636B57",
+ },
+ },
+ "Type": "AWS::ApiGateway::GatewayResponse",
+ },
+ "DataAccessLayerConfigTableFC483DD7": {
+ "DeletionPolicy": "Retain",
+ "Metadata": {
+ "guard": {
+ "SuppressedRules": [
+ "DYNAMODB_TABLE_ENCRYPTED_KMS",
+ ],
+ },
+ },
+ "Properties": {
+ "AttributeDefinitions": [
+ {
+ "AttributeName": "PK",
+ "AttributeType": "S",
+ },
+ {
+ "AttributeName": "GSI1PK",
+ "AttributeType": "S",
+ },
+ {
+ "AttributeName": "GSI1SK",
+ "AttributeType": "S",
+ },
+ {
+ "AttributeName": "GSI2PK",
+ "AttributeType": "S",
+ },
+ {
+ "AttributeName": "GSI3PK",
+ "AttributeType": "S",
+ },
+ ],
+ "BillingMode": "PAY_PER_REQUEST",
+ "GlobalSecondaryIndexes": [
+ {
+ "IndexName": "GSI1",
+ "KeySchema": [
+ {
+ "AttributeName": "GSI1PK",
+ "KeyType": "HASH",
+ },
+ {
+ "AttributeName": "GSI1SK",
+ "KeyType": "RANGE",
+ },
+ ],
+ "Projection": {
+ "ProjectionType": "ALL",
+ },
+ },
+ {
+ "IndexName": "GSI2",
+ "KeySchema": [
+ {
+ "AttributeName": "GSI2PK",
+ "KeyType": "HASH",
+ },
+ ],
+ "Projection": {
+ "ProjectionType": "ALL",
+ },
+ },
+ {
+ "IndexName": "GSI3",
+ "KeySchema": [
+ {
+ "AttributeName": "GSI3PK",
+ "KeyType": "HASH",
+ },
+ ],
+ "Projection": {
+ "ProjectionType": "ALL",
+ },
+ },
+ ],
+ "KeySchema": [
+ {
+ "AttributeName": "PK",
+ "KeyType": "HASH",
+ },
+ ],
+ "Replicas": [
+ {
+ "GlobalSecondaryIndexes": [
+ {
+ "IndexName": "GSI1",
+ },
+ {
+ "IndexName": "GSI2",
+ },
+ {
+ "IndexName": "GSI3",
+ },
+ ],
+ "PointInTimeRecoverySpecification": {
+ "PointInTimeRecoveryEnabled": true,
+ },
+ "Region": {
+ "Ref": "AWS::Region",
+ },
+ },
+ ],
+ "SSESpecification": {
+ "SSEEnabled": true,
+ "SSEType": "KMS",
+ },
+ "StreamSpecification": {
+ "StreamViewType": "NEW_AND_OLD_IMAGES",
+ },
+ },
+ "Type": "AWS::DynamoDB::GlobalTable",
+ "UpdateReplacePolicy": "Retain",
+ },
+ "DataAccessLayerDITApi51636B57": {
+ "Properties": {
+ "Name": "DITApi",
+ },
+ "Type": "AWS::ApiGateway::RestApi",
+ },
+ "DataAccessLayerDITApiANY6E92AB3D": {
+ "Properties": {
+ "AuthorizationScopes": [
+ "dit-api/api",
+ ],
+ "AuthorizationType": "COGNITO_USER_POOLS",
+ "AuthorizerId": {
+ "Ref": "DataAccessLayerFullAccessAuthorizer9954F0E5",
+ },
+ "HttpMethod": "ANY",
+ "Integration": {
+ "IntegrationHttpMethod": "POST",
+ "Type": "AWS_PROXY",
+ "Uri": {
+ "Fn::Join": [
+ "",
+ [
+ "arn:",
+ {
+ "Ref": "AWS::Partition",
+ },
+ ":apigateway:",
+ {
+ "Ref": "AWS::Region",
+ },
+ ":lambda:path/2015-03-31/functions/",
+ {
+ "Fn::GetAtt": [
+ "DataAccessLayerApiLambda53F93106",
+ "Arn",
+ ],
+ },
+ "/invocations",
+ ],
+ ],
+ },
+ },
+ "ResourceId": {
+ "Fn::GetAtt": [
+ "DataAccessLayerDITApi51636B57",
+ "RootResourceId",
+ ],
+ },
+ "RestApiId": {
+ "Ref": "DataAccessLayerDITApi51636B57",
+ },
+ },
+ "Type": "AWS::ApiGateway::Method",
+ },
+ "DataAccessLayerDITApiANYApiPermissionTestManagementStackDataAccessLayerDITApi8A6BE97DANY1DCBC28E": {
+ "Properties": {
+ "Action": "lambda:InvokeFunction",
+ "FunctionName": {
+ "Fn::GetAtt": [
+ "DataAccessLayerApiLambda53F93106",
+ "Arn",
+ ],
+ },
+ "Principal": "apigateway.amazonaws.com",
+ "SourceArn": {
+ "Fn::Join": [
+ "",
+ [
+ "arn:",
+ {
+ "Ref": "AWS::Partition",
+ },
+ ":execute-api:",
+ {
+ "Ref": "AWS::Region",
+ },
+ ":",
+ {
+ "Ref": "AWS::AccountId",
+ },
+ ":",
+ {
+ "Ref": "DataAccessLayerDITApi51636B57",
+ },
+ "/",
+ {
+ "Ref": "DataAccessLayerDITApiDeploymentStageprod1B577AB5",
+ },
+ "/*/",
+ ],
+ ],
+ },
+ },
+ "Type": "AWS::Lambda::Permission",
+ },
+ "DataAccessLayerDITApiANYApiPermissionTestTestManagementStackDataAccessLayerDITApi8A6BE97DANYAE8F61DC": {
+ "Properties": {
+ "Action": "lambda:InvokeFunction",
+ "FunctionName": {
+ "Fn::GetAtt": [
+ "DataAccessLayerApiLambda53F93106",
+ "Arn",
+ ],
+ },
+ "Principal": "apigateway.amazonaws.com",
+ "SourceArn": {
+ "Fn::Join": [
+ "",
+ [
+ "arn:",
+ {
+ "Ref": "AWS::Partition",
+ },
+ ":execute-api:",
+ {
+ "Ref": "AWS::Region",
+ },
+ ":",
+ {
+ "Ref": "AWS::AccountId",
+ },
+ ":",
+ {
+ "Ref": "DataAccessLayerDITApi51636B57",
+ },
+ "/test-invoke-stage/*/",
+ ],
+ ],
+ },
+ },
+ "Type": "AWS::Lambda::Permission",
+ },
+ "DataAccessLayerDITApiAccount13F50FA2": {
+ "DeletionPolicy": "Retain",
+ "DependsOn": [
+ "DataAccessLayerDITApi51636B57",
+ ],
+ "Properties": {
+ "CloudWatchRoleArn": {
+ "Fn::GetAtt": [
+ "DataAccessLayerDITApiCloudWatchRole5597E17C",
+ "Arn",
+ ],
+ },
+ },
+ "Type": "AWS::ApiGateway::Account",
+ "UpdateReplacePolicy": "Retain",
+ },
+ "DataAccessLayerDITApiCloudWatchRole5597E17C": {
+ "DeletionPolicy": "Retain",
+ "Properties": {
+ "AssumeRolePolicyDocument": {
+ "Statement": [
+ {
+ "Action": "sts:AssumeRole",
+ "Effect": "Allow",
+ "Principal": {
+ "Service": "apigateway.amazonaws.com",
+ },
+ },
+ ],
+ "Version": "2012-10-17",
+ },
+ "ManagedPolicyArns": [
+ {
+ "Fn::Join": [
+ "",
+ [
+ "arn:",
+ {
+ "Ref": "AWS::Partition",
+ },
+ ":iam::aws:policy/service-role/AmazonAPIGatewayPushToCloudWatchLogs",
+ ],
+ ],
+ },
+ ],
+ },
+ "Type": "AWS::IAM::Role",
+ "UpdateReplacePolicy": "Retain",
+ },
+ "DataAccessLayerDITApiDeploymentF2E2DE9Fbc4c2a73824095272c467282d96cc74d": {
+ "DependsOn": [
+ "DataAccessLayerCORSResponse4xx88C1D1E3",
+ "DataAccessLayerCORSResponse5xx07AEF476",
+ "DataAccessLayerDITApiproxyANY751BCCB6",
+ "DataAccessLayerDITApiproxyOPTIONSCB41EFA8",
+ "DataAccessLayerDITApiproxyF57F8464",
+ "DataAccessLayerDITApiANY6E92AB3D",
+ "DataAccessLayerDITApiOPTIONSAEFE0783",
+ ],
+ "Metadata": {
+ "aws:cdk:do-not-refactor": true,
+ },
+ "Properties": {
+ "Description": "Automatically created by the RestApi construct",
+ "RestApiId": {
+ "Ref": "DataAccessLayerDITApi51636B57",
+ },
+ },
+ "Type": "AWS::ApiGateway::Deployment",
+ },
+ "DataAccessLayerDITApiDeploymentStageprod1B577AB5": {
+ "DependsOn": [
+ "DataAccessLayerDITApiAccount13F50FA2",
+ ],
+ "Metadata": {
+ "guard": {
+ "SuppressedRules": [
+ "API_GW_CACHE_ENABLED_AND_ENCRYPTED",
+ ],
+ },
+ },
+ "Properties": {
+ "AccessLogSetting": {
+ "DestinationArn": {
+ "Fn::GetAtt": [
+ "DataAccessLayerProdLogs1C739F5D",
+ "Arn",
+ ],
+ },
+ "Format": "{"requestId":"$context.requestId","extendedRequestId":"$context.extendedRequestId","sourceIp":"$context.identity.sourceIp","caller":"$context.identity.caller","user":"$context.identity.user","method":"$context.httpMethod","resourcePath":"$context.resourcePath","protocol":"$context.protocol","status":"$context.status","requestTime":"$context.requestTime","responseLength":"$context.responseLength"}",
+ },
+ "DeploymentId": {
+ "Ref": "DataAccessLayerDITApiDeploymentF2E2DE9Fbc4c2a73824095272c467282d96cc74d",
+ },
+ "MethodSettings": [
+ {
+ "DataTraceEnabled": false,
+ "HttpMethod": "*",
+ "ResourcePath": "/*",
+ "ThrottlingBurstLimit": 200,
+ "ThrottlingRateLimit": 100,
+ },
+ ],
+ "RestApiId": {
+ "Ref": "DataAccessLayerDITApi51636B57",
+ },
+ "StageName": "prod",
+ "TracingEnabled": true,
+ },
+ "Type": "AWS::ApiGateway::Stage",
+ },
+ "DataAccessLayerDITApiOPTIONSAEFE0783": {
+ "Properties": {
+ "ApiKeyRequired": false,
+ "AuthorizationType": "NONE",
+ "HttpMethod": "OPTIONS",
+ "Integration": {
+ "IntegrationResponses": [
+ {
+ "ResponseParameters": {
+ "method.response.header.Access-Control-Allow-Credentials": "'true'",
+ "method.response.header.Access-Control-Allow-Headers": "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent'",
+ "method.response.header.Access-Control-Allow-Methods": "'*'",
+ "method.response.header.Access-Control-Allow-Origin": {
+ "Fn::Join": [
+ "",
+ [
+ "'https://",
+ {
+ "Fn::GetAtt": [
+ "WebDistributionAdminUIDistributionToS3CloudFrontDistribution6FD651BA",
+ "DomainName",
+ ],
+ },
+ "'",
+ ],
+ ],
+ },
+ "method.response.header.Vary": "'Origin'",
+ },
+ "StatusCode": "204",
+ },
+ ],
+ "RequestTemplates": {
+ "application/json": "{ statusCode: 200 }",
+ },
+ "Type": "MOCK",
+ },
+ "MethodResponses": [
+ {
+ "ResponseParameters": {
+ "method.response.header.Access-Control-Allow-Credentials": true,
+ "method.response.header.Access-Control-Allow-Headers": true,
+ "method.response.header.Access-Control-Allow-Methods": true,
+ "method.response.header.Access-Control-Allow-Origin": true,
+ "method.response.header.Vary": true,
+ },
+ "StatusCode": "204",
+ },
+ ],
+ "ResourceId": {
+ "Fn::GetAtt": [
+ "DataAccessLayerDITApi51636B57",
+ "RootResourceId",
+ ],
+ },
+ "RestApiId": {
+ "Ref": "DataAccessLayerDITApi51636B57",
+ },
+ },
+ "Type": "AWS::ApiGateway::Method",
+ },
+ "DataAccessLayerDITApiproxyANY751BCCB6": {
+ "Properties": {
+ "AuthorizationScopes": [
+ "dit-api/api",
+ ],
+ "AuthorizationType": "COGNITO_USER_POOLS",
+ "AuthorizerId": {
+ "Ref": "DataAccessLayerFullAccessAuthorizer9954F0E5",
+ },
+ "HttpMethod": "ANY",
+ "Integration": {
+ "IntegrationHttpMethod": "POST",
+ "Type": "AWS_PROXY",
+ "Uri": {
+ "Fn::Join": [
+ "",
+ [
+ "arn:",
+ {
+ "Ref": "AWS::Partition",
+ },
+ ":apigateway:",
+ {
+ "Ref": "AWS::Region",
+ },
+ ":lambda:path/2015-03-31/functions/",
+ {
+ "Fn::GetAtt": [
+ "DataAccessLayerApiLambda53F93106",
+ "Arn",
+ ],
+ },
+ "/invocations",
+ ],
+ ],
+ },
+ },
+ "ResourceId": {
+ "Ref": "DataAccessLayerDITApiproxyF57F8464",
+ },
+ "RestApiId": {
+ "Ref": "DataAccessLayerDITApi51636B57",
+ },
+ },
+ "Type": "AWS::ApiGateway::Method",
+ },
+ "DataAccessLayerDITApiproxyANYApiPermissionTestManagementStackDataAccessLayerDITApi8A6BE97DANYproxyE6DEB256": {
+ "Properties": {
+ "Action": "lambda:InvokeFunction",
+ "FunctionName": {
+ "Fn::GetAtt": [
+ "DataAccessLayerApiLambda53F93106",
+ "Arn",
+ ],
+ },
+ "Principal": "apigateway.amazonaws.com",
+ "SourceArn": {
+ "Fn::Join": [
+ "",
+ [
+ "arn:",
+ {
+ "Ref": "AWS::Partition",
+ },
+ ":execute-api:",
+ {
+ "Ref": "AWS::Region",
+ },
+ ":",
+ {
+ "Ref": "AWS::AccountId",
+ },
+ ":",
+ {
+ "Ref": "DataAccessLayerDITApi51636B57",
+ },
+ "/",
+ {
+ "Ref": "DataAccessLayerDITApiDeploymentStageprod1B577AB5",
+ },
+ "/*/*",
+ ],
+ ],
+ },
+ },
+ "Type": "AWS::Lambda::Permission",
+ },
+ "DataAccessLayerDITApiproxyANYApiPermissionTestTestManagementStackDataAccessLayerDITApi8A6BE97DANYproxy61758DEA": {
+ "Properties": {
+ "Action": "lambda:InvokeFunction",
+ "FunctionName": {
+ "Fn::GetAtt": [
+ "DataAccessLayerApiLambda53F93106",
+ "Arn",
+ ],
+ },
+ "Principal": "apigateway.amazonaws.com",
+ "SourceArn": {
+ "Fn::Join": [
+ "",
+ [
+ "arn:",
+ {
+ "Ref": "AWS::Partition",
+ },
+ ":execute-api:",
+ {
+ "Ref": "AWS::Region",
+ },
+ ":",
+ {
+ "Ref": "AWS::AccountId",
+ },
+ ":",
+ {
+ "Ref": "DataAccessLayerDITApi51636B57",
+ },
+ "/test-invoke-stage/*/*",
+ ],
+ ],
+ },
+ },
+ "Type": "AWS::Lambda::Permission",
+ },
+ "DataAccessLayerDITApiproxyF57F8464": {
+ "Properties": {
+ "ParentId": {
+ "Fn::GetAtt": [
+ "DataAccessLayerDITApi51636B57",
+ "RootResourceId",
+ ],
+ },
+ "PathPart": "{proxy+}",
+ "RestApiId": {
+ "Ref": "DataAccessLayerDITApi51636B57",
+ },
+ },
+ "Type": "AWS::ApiGateway::Resource",
+ },
+ "DataAccessLayerDITApiproxyOPTIONSCB41EFA8": {
+ "Properties": {
+ "ApiKeyRequired": false,
+ "AuthorizationType": "NONE",
+ "HttpMethod": "OPTIONS",
+ "Integration": {
+ "IntegrationResponses": [
+ {
+ "ResponseParameters": {
+ "method.response.header.Access-Control-Allow-Credentials": "'true'",
+ "method.response.header.Access-Control-Allow-Headers": "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent'",
+ "method.response.header.Access-Control-Allow-Methods": "'*'",
+ "method.response.header.Access-Control-Allow-Origin": {
+ "Fn::Join": [
+ "",
+ [
+ "'https://",
+ {
+ "Fn::GetAtt": [
+ "WebDistributionAdminUIDistributionToS3CloudFrontDistribution6FD651BA",
+ "DomainName",
+ ],
+ },
+ "'",
+ ],
+ ],
+ },
+ "method.response.header.Vary": "'Origin'",
+ },
+ "StatusCode": "204",
+ },
+ ],
+ "RequestTemplates": {
+ "application/json": "{ statusCode: 200 }",
+ },
+ "Type": "MOCK",
+ },
+ "MethodResponses": [
+ {
+ "ResponseParameters": {
+ "method.response.header.Access-Control-Allow-Credentials": true,
+ "method.response.header.Access-Control-Allow-Headers": true,
+ "method.response.header.Access-Control-Allow-Methods": true,
+ "method.response.header.Access-Control-Allow-Origin": true,
+ "method.response.header.Vary": true,
+ },
+ "StatusCode": "204",
+ },
+ ],
+ "ResourceId": {
+ "Ref": "DataAccessLayerDITApiproxyF57F8464",
+ },
+ "RestApiId": {
+ "Ref": "DataAccessLayerDITApi51636B57",
+ },
+ },
+ "Type": "AWS::ApiGateway::Method",
+ },
+ "DataAccessLayerFullAccessAuthorizer9954F0E5": {
+ "Properties": {
+ "IdentitySource": "method.request.header.Authorization",
+ "Name": "FullAccessAuthorizer",
+ "ProviderARNs": [
+ {
+ "Fn::GetAtt": [
+ "AuthUserPool8115E87F",
+ "Arn",
+ ],
+ },
+ ],
+ "RestApiId": {
+ "Ref": "DataAccessLayerDITApi51636B57",
+ },
+ "Type": "COGNITO_USER_POOLS",
+ },
+ "Type": "AWS::ApiGateway::Authorizer",
+ },
+ "DataAccessLayerProdLogs1C739F5D": {
+ "DeletionPolicy": "Retain",
+ "Metadata": {
+ "guard": {
+ "SuppressedRules": [
+ "CLOUDWATCH_LOG_GROUP_ENCRYPTED",
+ ],
+ },
+ },
+ "Properties": {
+ "RetentionInDays": 3653,
+ },
+ "Type": "AWS::Logs::LogGroup",
+ "UpdateReplacePolicy": "Retain",
+ },
+ "ImageProcessingNestedStackImageProcessingNestedStackResource96AF94AE": {
+ "DeletionPolicy": "Delete",
+ "Properties": {
+ "Parameters": {
+ "referencetoTestManagementStackCorsOriginParameter7234A77ARef": {
+ "Ref": "CorsOriginParameter",
+ },
+ "referencetoTestManagementStackDataAccessLayerConfigTable9BD19AB9Arn": {
+ "Fn::GetAtt": [
+ "DataAccessLayerConfigTableFC483DD7",
+ "Arn",
+ ],
+ },
+ "referencetoTestManagementStackDataAccessLayerConfigTable9BD19AB9StreamArn": {
+ "Fn::GetAtt": [
+ "DataAccessLayerConfigTableFC483DD7",
+ "StreamArn",
+ ],
+ },
+ "referencetoTestManagementStackDeploymentSize0180D410Ref": {
+ "Ref": "DeploymentSize",
+ },
+ "referencetoTestManagementStackMetricsUUID9BBED294UUID": {
+ "Fn::GetAtt": [
+ "MetricsUUIDABD69ADD",
+ "UUID",
+ ],
+ },
+ "referencetoTestManagementStackOriginOverrideHeader4D0E20B0Ref": {
+ "Ref": "OriginOverrideHeader",
+ },
+ },
+ "TemplateURL": "Omitted to remove snapshot dependency on hash",
+ },
+ "Type": "AWS::CloudFormation::Stack",
+ "UpdateReplacePolicy": "Delete",
+ },
+ "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aFD4BFC8A": {
+ "DependsOn": [
+ "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRoleDefaultPolicyADDA7DEB",
+ "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRole9741ECFB",
+ ],
+ "Metadata": {
+ "guard": {
+ "SuppressedRules": [
+ "LAMBDA_INSIDE_VPC",
+ "LAMBDA_CONCURRENCY_CHECK",
+ ],
+ },
+ },
+ "Properties": {
+ "Code": {
+ "S3Bucket": "Omitted to remove snapshot dependency on bucket",
+ "S3Key": "Omitted to remove snapshot dependency on hash",
+ },
+ "Handler": "index.handler",
+ "Role": {
+ "Fn::GetAtt": [
+ "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRole9741ECFB",
+ "Arn",
+ ],
+ },
+ "Runtime": "nodejs22.x",
+ "Timeout": 900,
+ },
+ "Type": "AWS::Lambda::Function",
+ },
+ "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRole9741ECFB": {
+ "Properties": {
+ "AssumeRolePolicyDocument": {
+ "Statement": [
+ {
+ "Action": "sts:AssumeRole",
+ "Effect": "Allow",
+ "Principal": {
+ "Service": "lambda.amazonaws.com",
+ },
+ },
+ ],
+ "Version": "2012-10-17",
+ },
+ "ManagedPolicyArns": [
+ {
+ "Fn::Join": [
+ "",
+ [
+ "arn:",
+ {
+ "Ref": "AWS::Partition",
+ },
+ ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole",
+ ],
+ ],
+ },
+ ],
+ },
+ "Type": "AWS::IAM::Role",
+ },
+ "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRoleDefaultPolicyADDA7DEB": {
+ "Properties": {
+ "PolicyDocument": {
+ "Statement": [
+ {
+ "Action": [
+ "logs:PutRetentionPolicy",
+ "logs:DeleteRetentionPolicy",
+ ],
+ "Effect": "Allow",
+ "Resource": "*",
+ },
+ ],
+ "Version": "2012-10-17",
+ },
+ "PolicyName": "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRoleDefaultPolicyADDA7DEB",
+ "Roles": [
+ {
+ "Ref": "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRole9741ECFB",
+ },
+ ],
+ },
+ "Type": "AWS::IAM::Policy",
+ },
+ "MetricsA5C7F5DB": {
+ "DeletionPolicy": "Delete",
+ "Properties": {
+ "AnonymousData": "Yes",
+ "CustomAction": "sendMetric",
+ "DeploymentSize": {
+ "Ref": "DeploymentSize",
+ },
+ "Region": {
+ "Ref": "AWS::Region",
+ },
+ "ServiceToken": {
+ "Fn::GetAtt": [
+ "MetricsCustomResourceLambda8AAD16EB",
+ "Arn",
+ ],
+ },
+ "UUID": {
+ "Fn::GetAtt": [
+ "MetricsUUIDABD69ADD",
+ "UUID",
+ ],
+ },
+ "UseExistingCloudFrontDistribution": "n/a",
+ },
+ "Type": "AWS::CloudFormation::CustomResource",
+ "UpdateReplacePolicy": "Delete",
+ },
+ "MetricsCustomResourceLambda8AAD16EB": {
+ "DependsOn": [
+ "MetricsCustomResourceLambdaServiceRole493FC361",
+ ],
+ "Metadata": {
+ "guard": {
+ "SuppressedRules": [
+ "LAMBDA_INSIDE_VPC",
+ "LAMBDA_CONCURRENCY_CHECK",
+ ],
+ },
+ },
+ "Properties": {
+ "Code": {
+ "S3Bucket": "Omitted to remove snapshot dependency on bucket",
+ "S3Key": "Omitted to remove snapshot dependency on hash",
+ },
+ "Environment": {
+ "Variables": {
+ "SOLUTION_ID": "SO0023",
+ "SOLUTION_VERSION": "v8.0.4",
+ },
+ },
+ "Handler": "index.handler",
+ "LoggingConfig": {
+ "LogGroup": {
+ "Ref": "MetricsCustomResourceLambdaLogGroup041E9E89",
+ },
+ },
+ "MemorySize": 512,
+ "Role": {
+ "Fn::GetAtt": [
+ "MetricsCustomResourceLambdaServiceRole493FC361",
+ "Arn",
+ ],
+ },
+ "Runtime": "nodejs22.x",
+ "Timeout": 30,
+ },
+ "Type": "AWS::Lambda::Function",
+ },
+ "MetricsCustomResourceLambdaLogGroup041E9E89": {
+ "DeletionPolicy": "Retain",
+ "Metadata": {
+ "guard": {
+ "SuppressedRules": [
+ "CLOUDWATCH_LOG_GROUP_ENCRYPTED",
+ ],
+ },
+ },
+ "Properties": {
+ "RetentionInDays": 3653,
+ },
+ "Type": "AWS::Logs::LogGroup",
+ "UpdateReplacePolicy": "Retain",
+ },
+ "MetricsCustomResourceLambdaServiceRole493FC361": {
+ "Properties": {
+ "AssumeRolePolicyDocument": {
+ "Statement": [
+ {
+ "Action": "sts:AssumeRole",
+ "Effect": "Allow",
+ "Principal": {
+ "Service": "lambda.amazonaws.com",
+ },
+ },
+ ],
+ "Version": "2012-10-17",
+ },
+ "ManagedPolicyArns": [
+ {
+ "Fn::Join": [
+ "",
+ [
+ "arn:",
+ {
+ "Ref": "AWS::Partition",
+ },
+ ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole",
+ ],
+ ],
+ },
+ ],
+ },
+ "Type": "AWS::IAM::Role",
+ },
+ "MetricsUUIDABD69ADD": {
+ "DeletionPolicy": "Delete",
+ "Properties": {
+ "CustomAction": "createUuid",
+ "ServiceToken": {
+ "Fn::GetAtt": [
+ "MetricsCustomResourceLambda8AAD16EB",
+ "Arn",
+ ],
+ },
+ },
+ "Type": "AWS::CloudFormation::CustomResource",
+ "UpdateReplacePolicy": "Delete",
+ },
+ "WebDistributionAdminUIDistributionToS3CloudFrontDistribution6FD651BA": {
+ "Metadata": {
+ "cfn_nag": {
+ "rules_to_suppress": [
+ {
+ "id": "W70",
+ "reason": "Since the distribution uses the CloudFront domain name, CloudFront automatically sets the security policy to TLSv1 regardless of the value of MinimumProtocolVersion",
+ },
+ ],
+ },
+ },
+ "Properties": {
+ "DistributionConfig": {
+ "Comment": "Admin UI Distribution for Dynamic Image Transformation for Amazon CloudFront",
+ "CustomErrorResponses": [
+ {
+ "ErrorCode": 403,
+ "ResponseCode": 200,
+ "ResponsePagePath": "/index.html",
+ },
+ {
+ "ErrorCode": 404,
+ "ResponseCode": 200,
+ "ResponsePagePath": "/index.html",
+ },
+ ],
+ "DefaultCacheBehavior": {
+ "CachePolicyId": "658327ea-f89d-4fab-a63d-7e88639e58f6",
+ "Compress": true,
+ "TargetOriginId": "TestManagementStackWebDistributionAdminUIDistributionToS3CloudFrontDistributionOrigin19EDB06FA",
+ "ViewerProtocolPolicy": "redirect-to-https",
+ },
+ "DefaultRootObject": "index.html",
+ "Enabled": true,
+ "HttpVersion": "http2",
+ "IPV6Enabled": true,
+ "Logging": {
+ "Bucket": {
+ "Fn::GetAtt": [
+ "WebDistributionAdminUIDistributionToS3CloudfrontLoggingBucket1CBD1EBB",
+ "RegionalDomainName",
+ ],
+ },
+ "Prefix": "admin-ui-cloudfront/",
+ },
+ "Origins": [
+ {
+ "DomainName": {
+ "Fn::GetAtt": [
+ "WebDistributionAdminUIDistributionToS3S3BucketBEF73512",
+ "RegionalDomainName",
+ ],
+ },
+ "Id": "TestManagementStackWebDistributionAdminUIDistributionToS3CloudFrontDistributionOrigin19EDB06FA",
+ "OriginAccessControlId": {
+ "Fn::GetAtt": [
+ "WebDistributionAdminUIDistributionToS3CloudFrontOac6E25E5C5",
+ "Id",
+ ],
+ },
+ "S3OriginConfig": {
+ "OriginAccessIdentity": "",
+ },
+ },
+ ],
+ },
+ },
+ "Type": "AWS::CloudFront::Distribution",
+ },
+ "WebDistributionAdminUIDistributionToS3CloudFrontOac6E25E5C5": {
+ "Properties": {
+ "OriginAccessControlConfig": {
+ "Description": "Origin access control provisioned by aws-cloudfront-s3",
+ "Name": {
+ "Fn::Join": [
+ "",
+ [
+ "aws-cloudfront-s3-AdminToS3-",
+ {
+ "Fn::Select": [
+ 2,
+ {
+ "Fn::Split": [
+ "/",
+ {
+ "Ref": "AWS::StackId",
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ ],
+ },
+ "OriginAccessControlOriginType": "s3",
+ "SigningBehavior": "always",
+ "SigningProtocol": "sigv4",
+ },
+ },
+ "Type": "AWS::CloudFront::OriginAccessControl",
+ },
+ "WebDistributionAdminUIDistributionToS3CloudfrontLoggingBucket1CBD1EBB": {
+ "DeletionPolicy": "Retain",
+ "Properties": {
+ "AccessControl": "LogDeliveryWrite",
+ "BucketEncryption": {
+ "ServerSideEncryptionConfiguration": [
+ {
+ "ServerSideEncryptionByDefault": {
+ "SSEAlgorithm": "AES256",
+ },
+ },
+ ],
+ },
+ "LoggingConfiguration": {
+ "DestinationBucketName": {
+ "Ref": "WebDistributionAdminUIDistributionToS3CloudfrontLoggingBucketAccessLog1B2CB542",
+ },
+ },
+ "OwnershipControls": {
+ "Rules": [
+ {
+ "ObjectOwnership": "ObjectWriter",
+ },
+ ],
+ },
+ "PublicAccessBlockConfiguration": {
+ "BlockPublicAcls": true,
+ "BlockPublicPolicy": true,
+ "IgnorePublicAcls": true,
+ "RestrictPublicBuckets": true,
+ },
+ "VersioningConfiguration": {
+ "Status": "Enabled",
+ },
+ },
+ "Type": "AWS::S3::Bucket",
+ "UpdateReplacePolicy": "Retain",
+ },
+ "WebDistributionAdminUIDistributionToS3CloudfrontLoggingBucketAccessLog1B2CB542": {
+ "DeletionPolicy": "Retain",
+ "Metadata": {
+ "cfn_nag": {
+ "rules_to_suppress": [
+ {
+ "id": "W35",
+ "reason": "This S3 bucket is used as the access logging bucket for another bucket",
+ },
+ ],
+ },
+ },
+ "Properties": {
+ "BucketEncryption": {
+ "ServerSideEncryptionConfiguration": [
+ {
+ "ServerSideEncryptionByDefault": {
+ "SSEAlgorithm": "AES256",
+ },
+ },
+ ],
+ },
+ "OwnershipControls": {
+ "Rules": [
+ {
+ "ObjectOwnership": "ObjectWriter",
+ },
+ ],
+ },
+ "PublicAccessBlockConfiguration": {
+ "BlockPublicAcls": true,
+ "BlockPublicPolicy": true,
+ "IgnorePublicAcls": true,
+ "RestrictPublicBuckets": true,
+ },
+ "VersioningConfiguration": {
+ "Status": "Enabled",
+ },
+ },
+ "Type": "AWS::S3::Bucket",
+ "UpdateReplacePolicy": "Retain",
+ },
+ "WebDistributionAdminUIDistributionToS3CloudfrontLoggingBucketAccessLogPolicyF0EDCBBD": {
+ "Properties": {
+ "Bucket": {
+ "Ref": "WebDistributionAdminUIDistributionToS3CloudfrontLoggingBucketAccessLog1B2CB542",
+ },
+ "PolicyDocument": {
+ "Statement": [
+ {
+ "Action": "s3:*",
+ "Condition": {
+ "Bool": {
+ "aws:SecureTransport": "false",
+ },
+ },
+ "Effect": "Deny",
+ "Principal": {
+ "AWS": "*",
+ },
+ "Resource": [
+ {
+ "Fn::GetAtt": [
+ "WebDistributionAdminUIDistributionToS3CloudfrontLoggingBucketAccessLog1B2CB542",
+ "Arn",
+ ],
+ },
+ {
+ "Fn::Join": [
+ "",
+ [
+ {
+ "Fn::GetAtt": [
+ "WebDistributionAdminUIDistributionToS3CloudfrontLoggingBucketAccessLog1B2CB542",
+ "Arn",
+ ],
+ },
+ "/*",
+ ],
+ ],
+ },
+ ],
+ },
+ {
+ "Action": "s3:PutObject",
+ "Condition": {
+ "ArnLike": {
+ "aws:SourceArn": {
+ "Fn::GetAtt": [
+ "WebDistributionAdminUIDistributionToS3CloudfrontLoggingBucket1CBD1EBB",
+ "Arn",
+ ],
+ },
+ },
+ "StringEquals": {
+ "aws:SourceAccount": {
+ "Ref": "AWS::AccountId",
+ },
+ },
+ },
+ "Effect": "Allow",
+ "Principal": {
+ "Service": "logging.s3.amazonaws.com",
+ },
+ "Resource": {
+ "Fn::Join": [
+ "",
+ [
+ {
+ "Fn::GetAtt": [
+ "WebDistributionAdminUIDistributionToS3CloudfrontLoggingBucketAccessLog1B2CB542",
+ "Arn",
+ ],
+ },
+ "/*",
+ ],
+ ],
+ },
+ },
+ ],
+ "Version": "2012-10-17",
+ },
+ },
+ "Type": "AWS::S3::BucketPolicy",
+ },
+ "WebDistributionAdminUIDistributionToS3CloudfrontLoggingBucketPolicyDF3305F5": {
+ "Properties": {
+ "Bucket": {
+ "Ref": "WebDistributionAdminUIDistributionToS3CloudfrontLoggingBucket1CBD1EBB",
+ },
+ "PolicyDocument": {
+ "Statement": [
+ {
+ "Action": "s3:*",
+ "Condition": {
+ "Bool": {
+ "aws:SecureTransport": "false",
+ },
+ },
+ "Effect": "Deny",
+ "Principal": {
+ "AWS": "*",
+ },
+ "Resource": [
+ {
+ "Fn::GetAtt": [
+ "WebDistributionAdminUIDistributionToS3CloudfrontLoggingBucket1CBD1EBB",
+ "Arn",
+ ],
+ },
+ {
+ "Fn::Join": [
+ "",
+ [
+ {
+ "Fn::GetAtt": [
+ "WebDistributionAdminUIDistributionToS3CloudfrontLoggingBucket1CBD1EBB",
+ "Arn",
+ ],
+ },
+ "/*",
+ ],
+ ],
+ },
+ ],
+ },
+ ],
+ "Version": "2012-10-17",
+ },
+ },
+ "Type": "AWS::S3::BucketPolicy",
+ },
+ "WebDistributionAdminUIDistributionToS3S3BucketBEF73512": {
+ "DeletionPolicy": "Retain",
+ "Metadata": {
+ "guard": {
+ "SuppressedRules": [
+ "S3_BUCKET_LOGGING_ENABLED",
+ ],
+ },
+ },
+ "Properties": {
+ "BucketEncryption": {
+ "ServerSideEncryptionConfiguration": [
+ {
+ "ServerSideEncryptionByDefault": {
+ "SSEAlgorithm": "AES256",
+ },
+ },
+ ],
+ },
+ "LifecycleConfiguration": {
+ "Rules": [
+ {
+ "NoncurrentVersionTransitions": [
+ {
+ "StorageClass": "GLACIER",
+ "TransitionInDays": 90,
+ },
+ ],
+ "Status": "Enabled",
+ },
+ ],
+ },
+ "PublicAccessBlockConfiguration": {
+ "BlockPublicAcls": true,
+ "BlockPublicPolicy": true,
+ "IgnorePublicAcls": true,
+ "RestrictPublicBuckets": true,
+ },
+ "Tags": [
+ {
+ "Key": "aws-cdk:cr-owned:ec92ed08",
+ "Value": "true",
+ },
+ ],
+ "VersioningConfiguration": {
+ "Status": "Enabled",
+ },
+ },
+ "Type": "AWS::S3::Bucket",
+ "UpdateReplacePolicy": "Retain",
+ },
+ "WebDistributionAdminUIDistributionToS3S3BucketPolicy1B0745FE": {
+ "Metadata": {
+ "cfn_nag": {
+ "rules_to_suppress": [
+ {
+ "id": "F16",
+ "reason": "Public website bucket policy requires a wildcard principal",
+ },
+ ],
+ },
+ },
+ "Properties": {
+ "Bucket": {
+ "Ref": "WebDistributionAdminUIDistributionToS3S3BucketBEF73512",
+ },
+ "PolicyDocument": {
+ "Statement": [
+ {
+ "Action": "s3:*",
+ "Condition": {
+ "Bool": {
+ "aws:SecureTransport": "false",
+ },
+ },
+ "Effect": "Deny",
+ "Principal": {
+ "AWS": "*",
+ },
+ "Resource": [
+ {
+ "Fn::GetAtt": [
+ "WebDistributionAdminUIDistributionToS3S3BucketBEF73512",
+ "Arn",
+ ],
+ },
+ {
+ "Fn::Join": [
+ "",
+ [
+ {
+ "Fn::GetAtt": [
+ "WebDistributionAdminUIDistributionToS3S3BucketBEF73512",
+ "Arn",
+ ],
+ },
+ "/*",
+ ],
+ ],
+ },
+ ],
+ },
+ {
+ "Action": "s3:GetObject",
+ "Condition": {
+ "StringEquals": {
+ "AWS:SourceArn": {
+ "Fn::Join": [
+ "",
+ [
+ "arn:aws:cloudfront::",
+ {
+ "Ref": "AWS::AccountId",
+ },
+ ":distribution/",
+ {
+ "Ref": "WebDistributionAdminUIDistributionToS3CloudFrontDistribution6FD651BA",
+ },
+ ],
+ ],
+ },
+ },
+ },
+ "Effect": "Allow",
+ "Principal": {
+ "Service": "cloudfront.amazonaws.com",
+ },
+ "Resource": {
+ "Fn::Join": [
+ "",
+ [
+ {
+ "Fn::GetAtt": [
+ "WebDistributionAdminUIDistributionToS3S3BucketBEF73512",
+ "Arn",
+ ],
+ },
+ "/*",
+ ],
+ ],
+ },
+ },
+ ],
+ "Version": "2012-10-17",
+ },
+ },
+ "Type": "AWS::S3::BucketPolicy",
+ },
+ "WebDistributionAdminUIDistributionToS3S3LoggingBucket6996968F": {
+ "DeletionPolicy": "Retain",
+ "Metadata": {
+ "cfn_nag": {
+ "rules_to_suppress": [
+ {
+ "id": "W35",
+ "reason": "This S3 bucket is used as the access logging bucket for another bucket",
+ },
+ ],
+ },
+ },
+ "Properties": {
+ "BucketEncryption": {
+ "ServerSideEncryptionConfiguration": [
+ {
+ "ServerSideEncryptionByDefault": {
+ "SSEAlgorithm": "AES256",
+ },
+ },
+ ],
+ },
+ "PublicAccessBlockConfiguration": {
+ "BlockPublicAcls": true,
+ "BlockPublicPolicy": true,
+ "IgnorePublicAcls": true,
+ "RestrictPublicBuckets": true,
+ },
+ "VersioningConfiguration": {
+ "Status": "Enabled",
+ },
+ },
+ "Type": "AWS::S3::Bucket",
+ "UpdateReplacePolicy": "Retain",
+ },
+ "WebDistributionAdminUIDistributionToS3S3LoggingBucketPolicyF77AA8A6": {
+ "Properties": {
+ "Bucket": {
+ "Ref": "WebDistributionAdminUIDistributionToS3S3LoggingBucket6996968F",
+ },
+ "PolicyDocument": {
+ "Statement": [
+ {
+ "Action": "s3:*",
+ "Condition": {
+ "Bool": {
+ "aws:SecureTransport": "false",
+ },
+ },
+ "Effect": "Deny",
+ "Principal": {
+ "AWS": "*",
+ },
+ "Resource": [
+ {
+ "Fn::GetAtt": [
+ "WebDistributionAdminUIDistributionToS3S3LoggingBucket6996968F",
+ "Arn",
+ ],
+ },
+ {
+ "Fn::Join": [
+ "",
+ [
+ {
+ "Fn::GetAtt": [
+ "WebDistributionAdminUIDistributionToS3S3LoggingBucket6996968F",
+ "Arn",
+ ],
+ },
+ "/*",
+ ],
+ ],
+ },
+ ],
+ },
+ ],
+ "Version": "2012-10-17",
+ },
+ },
+ "Type": "AWS::S3::BucketPolicy",
+ },
+ },
+ "Rules": {
+ "CheckBootstrapVersion": {
+ "Assertions": [
+ {
+ "Assert": {
+ "Fn::Not": [
+ {
+ "Fn::Contains": [
+ [
+ "1",
+ "2",
+ "3",
+ "4",
+ "5",
+ ],
+ {
+ "Ref": "BootstrapVersion",
+ },
+ ],
+ },
+ ],
+ },
+ "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI.",
+ },
+ ],
+ },
+ },
+}
+`;
diff --git a/source/constructs/lib/v8/test/snapshot/image-processing-stack.test.ts b/source/constructs/lib/v8/test/snapshot/image-processing-stack.test.ts
new file mode 100644
index 000000000..4490be7dd
--- /dev/null
+++ b/source/constructs/lib/v8/test/snapshot/image-processing-stack.test.ts
@@ -0,0 +1,57 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+import { App, Stack } from "aws-cdk-lib";
+import { Template } from "aws-cdk-lib/assertions";
+import * as dynamodb from "aws-cdk-lib/aws-dynamodb";
+import { ImageProcessingStack } from "../../stacks";
+import { cleanTemplateForSnapshot } from "./test-utils";
+
+describe("ImageProcessingStack", () => {
+ let app: App;
+ let parentStack: Stack;
+ let configTable: dynamodb.TableV2;
+ let stack: ImageProcessingStack;
+ let template: Template;
+
+ beforeEach(() => {
+ process.env.SOLUTION_ID = "SO0023";
+ process.env.VERSION = "v8.0.4";
+
+ app = new App();
+
+ parentStack = new Stack(app, "TestParentStack");
+
+ // image processing stack has dependency on DDB Table from parent stack
+ configTable = new dynamodb.TableV2(parentStack, "TestConfigTable", {
+ partitionKey: { name: "PK", type: dynamodb.AttributeType.STRING },
+ });
+
+ stack = new ImageProcessingStack(parentStack, "TestImageProcessingStack", {
+ configTable,
+ deploymentSize: "small",
+ });
+
+ template = Template.fromStack(stack);
+ });
+
+ test("Snapshot Test", () => {
+ const templateJson = template.toJSON();
+ const cleanedTemplate = cleanTemplateForSnapshot(templateJson);
+
+ expect.assertions(1);
+ expect(cleanedTemplate).toMatchSnapshot();
+ });
+
+ test("All Lambda functions should use Node.js 22 runtime", () => {
+ const lambdaFunctions = template.findResources("AWS::Lambda::Function");
+ const functionNames = Object.keys(lambdaFunctions);
+
+ expect(functionNames.length).toBeGreaterThan(0);
+
+ functionNames.forEach((functionName) => {
+ const runtime = lambdaFunctions[functionName].Properties.Runtime;
+ expect(runtime).toBe("nodejs22.x");
+ });
+ });
+});
diff --git a/source/constructs/lib/v8/test/snapshot/management-stack.test.ts b/source/constructs/lib/v8/test/snapshot/management-stack.test.ts
new file mode 100644
index 000000000..05be48bdf
--- /dev/null
+++ b/source/constructs/lib/v8/test/snapshot/management-stack.test.ts
@@ -0,0 +1,50 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+import { App } from "aws-cdk-lib";
+import { Template } from "aws-cdk-lib/assertions";
+import { ManagementStack } from "../../stacks";
+import { cleanTemplateForSnapshot } from "./test-utils";
+
+const SUPPORTED_RUNTIMES = ["nodejs22.x", "python3.13"];
+
+describe("ManagementStack", () => {
+ let app: App;
+ let stack: ManagementStack;
+ let template: Template;
+
+ beforeEach(() => {
+ process.env.SOLUTION_ID = "SO0023";
+ process.env.VERSION = "v8.0.4";
+
+ app = new App();
+ stack = new ManagementStack(app, "TestManagementStack", {
+ description: "Test Management Stack for DIT v8",
+ solutionId: process.env.SOLUTION_ID,
+ solutionName: "dynamic-image-transformation-for-amazon-cloudfront",
+ solutionVersion: process.env.VERSION,
+ });
+
+ template = Template.fromStack(stack);
+ });
+
+ test("Snapshot Test", () => {
+ const templateJson = template.toJSON();
+ const cleanedTemplate = cleanTemplateForSnapshot(templateJson);
+
+ expect.assertions(1);
+ expect(cleanedTemplate).toMatchSnapshot();
+ });
+
+ test("All Lambda functions should use Node.js 22 runtime", () => {
+ const lambdaFunctions = template.findResources("AWS::Lambda::Function");
+ const functionNames = Object.keys(lambdaFunctions);
+
+ expect(functionNames.length).toBeGreaterThan(0);
+
+ functionNames.forEach((functionName) => {
+ const runtime = lambdaFunctions[functionName].Properties.Runtime;
+ expect(SUPPORTED_RUNTIMES).toContain(runtime);
+ });
+ });
+});
diff --git a/source/constructs/lib/v8/test/snapshot/test-utils.ts b/source/constructs/lib/v8/test/snapshot/test-utils.ts
new file mode 100644
index 000000000..0af79af05
--- /dev/null
+++ b/source/constructs/lib/v8/test/snapshot/test-utils.ts
@@ -0,0 +1,48 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+/**
+ * Cleans up cdk generated hash in CloudFormation template that would cause snapshot inconsistencies
+ * @param templateJson - The CloudFormation template JSON object
+ * @returns The cleaned template JSON object
+ */
+export function cleanTemplateForSnapshot(templateJson: any): any {
+ // Clean up dynamic values that would cause snapshot inconsistencies
+ Object.keys(templateJson.Resources || {}).forEach((key) => {
+ const resource = templateJson.Resources[key];
+
+ // Handle hash keys in template
+ if (resource.Properties?.Code?.S3Key) {
+ resource.Properties.Code.S3Key = "Omitted to remove snapshot dependency on hash";
+ }
+
+ if (resource.Properties?.Code?.S3Bucket) {
+ resource.Properties.Code.S3Bucket = "Omitted to remove snapshot dependency on bucket";
+ }
+
+ if (resource.Properties?.SourceObjectKeys) {
+ resource.Properties.SourceObjectKeys = "Omitted to remove snapshot dependency on hash";
+ }
+
+ if (resource.Properties?.TemplateURL) {
+ resource.Properties.TemplateURL = "Omitted to remove snapshot dependency on hash";
+ }
+
+ if (resource.Properties?.ContainerDefinitions) {
+ resource.Properties.ContainerDefinitions[0].Image = "Omitted to remove snapshot dependency on hash";
+ }
+
+ if (resource.Properties?.ImportSource?.SourceArn) {
+ resource.Properties.ImportSource.SourceArn = "Omitted to remove snapshot dependency on bucket";
+ }
+ });
+
+ Object.keys(templateJson.Outputs || {}).forEach((key) => {
+ const output = templateJson.Outputs[key];
+ if (key === "ImageUri" && output.Value) {
+ output.Value = "Omitted to remove snapshot dependency on hash";
+ }
+ });
+
+ return templateJson;
+}
diff --git a/source/constructs/lib/v8/test/unit/csp-updater-handler.test.ts b/source/constructs/lib/v8/test/unit/csp-updater-handler.test.ts
new file mode 100644
index 000000000..6ca2ef41a
--- /dev/null
+++ b/source/constructs/lib/v8/test/unit/csp-updater-handler.test.ts
@@ -0,0 +1,92 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+import { CloudFrontClient } from "@aws-sdk/client-cloudfront";
+
+const mockSend = jest.fn().mockResolvedValue({
+ DistributionConfig: { DefaultCacheBehavior: {} },
+ ETag: "test-etag",
+});
+
+jest.mock("@aws-sdk/client-cloudfront", () => ({
+ CloudFrontClient: jest.fn().mockImplementation(() => ({
+ send: mockSend,
+ })),
+ GetDistributionConfigCommand: jest.fn(),
+ UpdateDistributionCommand: jest.fn(),
+}));
+
+describe("csp-updater-handler CloudFrontClient configuration", () => {
+ beforeEach(() => {
+ jest.clearAllMocks();
+ });
+
+ it("should instantiate CloudFrontClient with custom user agent for Create event", async () => {
+ process.env.SOLUTION_ID = "SO0023";
+ process.env.SOLUTION_VERSION = "v0.0.0-test";
+
+ const { handler } = await import("../../constructs/frontend/csp-updater-handler");
+
+ const event = {
+ RequestType: "Create",
+ ResourceProperties: {
+ DistributionId: "test-dist-id",
+ ResponseHeadersPolicyId: "test-policy-id",
+ },
+ };
+
+ await handler(event as any, {} as any);
+
+ expect(CloudFrontClient).toHaveBeenCalledTimes(1);
+ expect(CloudFrontClient).toHaveBeenCalledWith(
+ expect.objectContaining({
+ customUserAgent: "AwsSolution/SO0023/v0.0.0-test",
+ })
+ );
+ });
+
+ it("should instantiate CloudFrontClient with custom user agent for Delete event", async () => {
+ const { handler } = await import("../../constructs/frontend/csp-updater-handler");
+
+ const event = {
+ RequestType: "Delete",
+ ResourceProperties: {
+ DistributionId: "test-dist-id",
+ ResponseHeadersPolicyId: "test-policy-id",
+ },
+ };
+
+ await handler(event as any, {} as any);
+
+ expect(CloudFrontClient).toHaveBeenCalledTimes(1);
+ expect(CloudFrontClient).toHaveBeenCalledWith(
+ expect.objectContaining({
+ customUserAgent: "AwsSolution/SO0023/v0.0.0-test",
+ })
+ );
+ });
+
+ it("should instantiate CloudFrontClient without custom user agent when SOLUTION_ID is not set", async () => {
+ delete process.env.SOLUTION_ID;
+ delete process.env.SOLUTION_VERSION;
+
+ const { handler } = await import("../../constructs/frontend/csp-updater-handler");
+
+ const event = {
+ RequestType: "Create",
+ ResourceProperties: {
+ DistributionId: "test-dist-id",
+ ResponseHeadersPolicyId: "test-policy-id",
+ },
+ };
+
+ await handler(event as any, {} as any);
+
+ expect(CloudFrontClient).toHaveBeenCalledTimes(1);
+ expect(CloudFrontClient).toHaveBeenCalledWith(
+ expect.not.objectContaining({
+ customUserAgent: expect.any(String),
+ })
+ );
+ });
+});
diff --git a/source/constructs/lib/v8/test/unit/dit-function.test.ts b/source/constructs/lib/v8/test/unit/dit-function.test.ts
new file mode 100644
index 000000000..12797445f
--- /dev/null
+++ b/source/constructs/lib/v8/test/unit/dit-function.test.ts
@@ -0,0 +1,255 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+import * as fs from "fs";
+import * as path from "path";
+
+// CloudFront Function types
+interface CloudFrontRequest {
+ headers: Record;
+}
+
+interface CloudFrontEvent {
+ request: CloudFrontRequest;
+}
+
+describe("DIT CloudFront Function", () => {
+ let handler: (event: CloudFrontEvent) => Promise;
+
+ beforeAll(() => {
+ // Load and evaluate the CloudFront function
+ const functionCode = fs.readFileSync(path.join(__dirname, "../../functions/dit-header-normalization.js"), "utf8");
+
+ // Extract handler function and make it available globally
+ const mockFunctionCode = functionCode.replace("async function handler", "global.handler = async function handler");
+
+ eval(mockFunctionCode);
+ handler = (global as any).handler;
+ });
+
+ test("should normalize desktop viewport width", async () => {
+ const event: CloudFrontEvent = {
+ request: {
+ headers: {
+ host: { value: "example.com" },
+ accept: { value: "image/webp,*/*" },
+ "sec-ch-viewport-width": { value: "1366" },
+ "sec-ch-dpr": { value: "2" },
+ },
+ },
+ };
+
+ const result = await handler(event);
+
+ expect(result.headers["dit-host"]?.value).toEqual(event.request.headers["host"].value);
+ expect(result.headers["dit-accept"]?.value).toEqual("image/webp");
+ expect(result.headers["dit-viewport-width"]?.value).toBe("1440");
+ expect(result.headers["dit-dpr"]?.value).toEqual(event.request.headers["sec-ch-dpr"].value);
+ });
+
+ test("should normalize mobile viewport width", async () => {
+ const event: CloudFrontEvent = {
+ request: {
+ headers: {
+ host: { value: "mobile.example.com" },
+ "sec-ch-viewport-width": { value: "375" },
+ },
+ },
+ };
+
+ const result = await handler(event);
+
+ expect(result.headers["dit-host"]?.value).toEqual(event.request.headers["host"].value);
+ expect(result.headers["dit-viewport-width"]?.value).toBe("480");
+ });
+
+ test("should handle missing viewport header", async () => {
+ const event: CloudFrontEvent = {
+ request: {
+ headers: {
+ host: { value: "example.com" },
+ accept: { value: "image/*" },
+ },
+ },
+ };
+
+ const result = await handler(event);
+
+ expect(result.headers["dit-host"]?.value).toEqual(event.request.headers["host"].value);
+ expect(result.headers["dit-accept"]).toBeUndefined(); // Wildcards are ignored
+ expect(result.headers["dit-viewport-width"]).toBeUndefined();
+ });
+
+ test("should preserve original headers while adding DIT headers", async () => {
+ const event: CloudFrontEvent = {
+ request: {
+ headers: {
+ host: { value: "example.com" },
+ accept: { value: "image/webp,*/*" },
+ "sec-ch-viewport-width": { value: "1366" },
+ "sec-ch-dpr": { value: "2" },
+ "user-agent": { value: "Mozilla/5.0" },
+ authorization: { value: "Bearer token123" },
+ },
+ },
+ };
+
+ const result = await handler(event);
+
+ // Original headers should be preserved
+ expect(result.headers["host"]?.value).toEqual(event.request.headers["host"].value);
+ expect(result.headers["accept"]?.value).toEqual(event.request.headers["accept"].value);
+ expect(result.headers["sec-ch-viewport-width"]?.value).toEqual(
+ event.request.headers["sec-ch-viewport-width"].value
+ );
+ expect(result.headers["sec-ch-dpr"]?.value).toEqual(event.request.headers["sec-ch-dpr"].value);
+ expect(result.headers["user-agent"]?.value).toEqual(event.request.headers["user-agent"].value);
+ expect(result.headers["authorization"]?.value).toEqual(event.request.headers["authorization"].value);
+
+ // DIT headers should be added
+ expect(result.headers["dit-host"]?.value).toEqual(event.request.headers["host"].value);
+ expect(result.headers["dit-accept"]?.value).toEqual("image/webp");
+ expect(result.headers["dit-viewport-width"]?.value).toBe("1440");
+ expect(result.headers["dit-dpr"]?.value).toEqual(event.request.headers["sec-ch-dpr"].value);
+ });
+
+ test("should handle edge case viewport widths", async () => {
+ const testCases = [
+ { input: "100", expected: "320" }, // Below smallest
+ { input: "320", expected: "320" }, // Exact match
+ { input: "400", expected: "480" }, // Between breakpoints
+ { input: "2000", expected: "1920" }, // Above largest
+ ];
+
+ for (const testCase of testCases) {
+ const event: CloudFrontEvent = {
+ request: {
+ headers: {
+ host: { value: "test.com" },
+ "sec-ch-viewport-width": { value: testCase.input },
+ },
+ },
+ };
+
+ const result = await handler(event);
+ expect(result.headers["dit-viewport-width"]?.value).toBe(testCase.expected);
+ }
+ });
+
+ test("should normalize DPR values to nearest tenth and cap at 5.0", async () => {
+ const testCases = [
+ { input: "1.23", expected: "1.2" },
+ { input: "2.87", expected: "2.9" },
+ { input: "0.14", expected: "0.1" },
+ { input: "6.5", expected: "5" },
+ { input: "1.0", expected: "1" },
+ { input: "5.0", expected: "5" },
+ ];
+
+ for (const testCase of testCases) {
+ const event: CloudFrontEvent = {
+ request: {
+ headers: {
+ host: { value: "test.com" },
+ "sec-ch-dpr": { value: testCase.input },
+ },
+ },
+ };
+
+ const result = await handler(event);
+ expect(result.headers["dit-dpr"]?.value).toBe(testCase.expected);
+ }
+ });
+
+ describe("Accept header normalization", () => {
+ test("should select highest priority format from Accept header", async () => {
+ const testCases = [
+ { input: "image/avif,image/webp,image/png", expected: "image/webp" },
+ { input: "image/png,image/jpeg", expected: "image/jpeg" },
+ { input: "image/avif,image/heif", expected: "image/avif" },
+ { input: "image/gif", expected: "image/gif" },
+ ];
+
+ for (const testCase of testCases) {
+ const event: CloudFrontEvent = {
+ request: {
+ headers: {
+ host: { value: "test.com" },
+ accept: { value: testCase.input },
+ },
+ },
+ };
+
+ const result = await handler(event);
+ expect(result.headers["dit-accept"]?.value).toBe(testCase.expected);
+ }
+ });
+
+ test("should ignore wildcards in Accept header", async () => {
+ const testCases = ["*/*", "image/*", "image/*,*/*;q=0.8"];
+
+ for (const input of testCases) {
+ const event: CloudFrontEvent = {
+ request: {
+ headers: {
+ host: { value: "test.com" },
+ accept: { value: input },
+ },
+ },
+ };
+
+ const result = await handler(event);
+ expect(result.headers["dit-accept"]).toBeUndefined();
+ }
+ });
+
+ test("should strip quality values from Accept header", async () => {
+ const event: CloudFrontEvent = {
+ request: {
+ headers: {
+ host: { value: "test.com" },
+ accept: { value: "image/webp;q=0.9,image/png;q=0.8" },
+ },
+ },
+ };
+
+ const result = await handler(event);
+ expect(result.headers["dit-accept"]?.value).toBe("image/webp");
+ });
+
+ test("should ignore quality values when selecting format", async () => {
+ const event: CloudFrontEvent = {
+ request: {
+ headers: {
+ host: { value: "test.com" },
+ accept: { value: "image/png;q=1.0,image/webp;q=0.1" },
+ },
+ },
+ };
+
+ const result = await handler(event);
+ expect(result.headers["dit-accept"]?.value).toBe("image/webp");
+ });
+
+ test("should handle MIME type aliases", async () => {
+ const testCases = [
+ { input: "image/jpg", expected: "image/jpeg" },
+ { input: "image/heic", expected: "image/heif" },
+ ];
+
+ for (const testCase of testCases) {
+ const event: CloudFrontEvent = {
+ request: {
+ headers: {
+ host: { value: "test.com" },
+ accept: { value: testCase.input },
+ },
+ },
+ };
+
+ const result = await handler(event);
+ expect(result.headers["dit-accept"]?.value).toBe(testCase.expected);
+ }
+ });
+ });
+});
diff --git a/source/constructs/package-lock.json b/source/constructs/package-lock.json
new file mode 100644
index 000000000..06b88605c
--- /dev/null
+++ b/source/constructs/package-lock.json
@@ -0,0 +1,8480 @@
+{
+ "name": "constructs",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "constructs",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-lambda-powertools/logger": "^2.27.0",
+ "@aws-sdk/client-cloudfront": "^3.993.0",
+ "@aws-sdk/client-cloudwatch": "^3.993.0",
+ "@aws-sdk/client-cloudwatch-logs": "^3.993.0",
+ "@aws-sdk/client-sqs": "^3.993.0",
+ "@middy/core": "^5.0.0",
+ "@middy/http-header-normalizer": "^5.0.0",
+ "@middy/http-router": "^5.0.0",
+ "@smithy/core": "^3.8.0",
+ "metrics-utils": "file:../metrics-utils",
+ "sharp": "^0.34.5"
+ },
+ "bin": {
+ "constructs": "bin/constructs.js"
+ },
+ "devDependencies": {
+ "@aws-sdk/client-cloudformation": "^3.993.0",
+ "@aws-solutions-constructs/aws-alb-fargate": "^2.86.0",
+ "@aws-solutions-constructs/aws-apigateway-lambda": "2.51.0",
+ "@aws-solutions-constructs/aws-cloudfront-apigateway-lambda": "2.51.0",
+ "@aws-solutions-constructs/aws-cloudfront-s3": "2.51.0",
+ "@aws-solutions-constructs/aws-lambda-dynamodb": "^2.86.0",
+ "@aws-solutions-constructs/aws-openapigateway-lambda": "^2.86.0",
+ "@aws-solutions-constructs/core": "2.51.0",
+ "@types/aws-lambda": "^8.10.156",
+ "@types/jest": "^29.5.6",
+ "@types/node": "^20.10.4",
+ "aws-cdk": "^2.1018.0",
+ "aws-cdk-lib": "2.248.0",
+ "constructs": "^10.3.0",
+ "esbuild": "^0.25.0",
+ "jest": "^29.7.0",
+ "ts-jest": "^29.1.1",
+ "ts-node": "^10.9.2",
+ "typescript": "^5.3.3"
+ }
+ },
+ "../metrics-utils": {
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/client-cloudwatch": "^3.993.0",
+ "@aws-sdk/client-cloudwatch-logs": "^3.993.0",
+ "@aws-sdk/client-dynamodb": "^3.993.0",
+ "@aws-sdk/client-sqs": "^3.993.0",
+ "@aws-solutions-constructs/aws-eventbridge-lambda": "^2.59.0",
+ "@aws-solutions-constructs/aws-lambda-sqs-lambda": "^2.59.0",
+ "@types/aws-lambda": "^8.10.143",
+ "esbuild": "^0.25.0"
+ },
+ "devDependencies": {
+ "@types/jest": "^30.0.0",
+ "@types/node": "20.4.5",
+ "aws-cdk-lib": "2.248.0",
+ "constructs": "^10.0.0",
+ "jest": "^30.0.5",
+ "ts-jest": "^29.4.0"
+ },
+ "peerDependencies": {
+ "aws-cdk-lib": "^2.182.0",
+ "constructs": "^10.0.0"
+ }
+ },
+ "node_modules/@aws-cdk/asset-awscli-v1": {
+ "version": "2.2.273",
+ "resolved": "https://registry.npmjs.org/@aws-cdk/asset-awscli-v1/-/asset-awscli-v1-2.2.273.tgz",
+ "integrity": "sha512-X57HYUtHt9BQrlrzUNcMyRsDUCoakYNnY6qh5lNwRCHPtQoTfXmuISkfLk0AjLkcbS5lw1LLTQFiQhTDXfiTvg==",
+ "dev": true,
+ "license": "Apache-2.0"
+ },
+ "node_modules/@aws-cdk/asset-node-proxy-agent-v6": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@aws-cdk/asset-node-proxy-agent-v6/-/asset-node-proxy-agent-v6-2.1.1.tgz",
+ "integrity": "sha512-We4bmHaowOPHr+IQR4/FyTGjRfjgBj4ICMjtqmJeBDWad3Q/6St12NT07leNtyuukv2qMhtSZJQorD8KpKTwRA==",
+ "dev": true,
+ "license": "Apache-2.0"
+ },
+ "node_modules/@aws-cdk/cloud-assembly-schema": {
+ "version": "53.14.0",
+ "resolved": "https://registry.npmjs.org/@aws-cdk/cloud-assembly-schema/-/cloud-assembly-schema-53.14.0.tgz",
+ "integrity": "sha512-prx2sbFfKrVf3NNXMOmWq6lsIBeWQDIqMTILLAddGiidn9j7OnLUubknWpJlLozMveTvQELdI++nUwq6jwCm9g==",
+ "bundleDependencies": [
+ "jsonschema",
+ "semver"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "jsonschema": "~1.4.1",
+ "semver": "^7.7.4"
+ },
+ "engines": {
+ "node": ">= 18.0.0"
+ }
+ },
+ "node_modules/@aws-cdk/cloud-assembly-schema/node_modules/jsonschema": {
+ "version": "1.4.1",
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/@aws-cdk/cloud-assembly-schema/node_modules/semver": {
+ "version": "7.7.4",
+ "inBundle": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@aws-crypto/crc32": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz",
+ "integrity": "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/util": "^5.2.0",
+ "@aws-sdk/types": "^3.222.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
+ "node_modules/@aws-crypto/sha256-browser": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz",
+ "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/sha256-js": "^5.2.0",
+ "@aws-crypto/supports-web-crypto": "^5.2.0",
+ "@aws-crypto/util": "^5.2.0",
+ "@aws-sdk/types": "^3.222.0",
+ "@aws-sdk/util-locate-window": "^3.0.0",
+ "@smithy/util-utf8": "^2.0.0",
+ "tslib": "^2.6.2"
+ }
+ },
+ "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/is-array-buffer": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz",
+ "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-buffer-from": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz",
+ "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/is-array-buffer": "^2.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-utf8": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz",
+ "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/util-buffer-from": "^2.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-crypto/sha256-js": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz",
+ "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/util": "^5.2.0",
+ "@aws-sdk/types": "^3.222.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
+ "node_modules/@aws-crypto/supports-web-crypto": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz",
+ "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ }
+ },
+ "node_modules/@aws-crypto/util": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz",
+ "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "^3.222.0",
+ "@smithy/util-utf8": "^2.0.0",
+ "tslib": "^2.6.2"
+ }
+ },
+ "node_modules/@aws-crypto/util/node_modules/@smithy/is-array-buffer": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz",
+ "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-crypto/util/node_modules/@smithy/util-buffer-from": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz",
+ "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/is-array-buffer": "^2.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-crypto/util/node_modules/@smithy/util-utf8": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz",
+ "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/util-buffer-from": "^2.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-lambda-powertools/commons": {
+ "version": "2.33.0",
+ "resolved": "https://registry.npmjs.org/@aws-lambda-powertools/commons/-/commons-2.33.0.tgz",
+ "integrity": "sha512-cXGfWT4FXtLO7Ny/shep6V/xYzgVN7hvukOA0bTa4nlg2GWiQsPoBoKvCEcfQ9I8GIS0tPyDfRkdx80SvA7LpA==",
+ "license": "MIT-0",
+ "dependencies": {
+ "@aws/lambda-invoke-store": "0.2.4"
+ }
+ },
+ "node_modules/@aws-lambda-powertools/logger": {
+ "version": "2.33.0",
+ "resolved": "https://registry.npmjs.org/@aws-lambda-powertools/logger/-/logger-2.33.0.tgz",
+ "integrity": "sha512-ejkgit7O8yrhu5Mbx8fBAd3lykBNtYsVzFSR653Sh3d8ojpp8zo2OoARt3lKEK4cjHsKB/kUGbpzZcSYkR6Hvg==",
+ "license": "MIT-0",
+ "dependencies": {
+ "@aws-lambda-powertools/commons": "2.33.0",
+ "@aws/lambda-invoke-store": "0.2.4"
+ },
+ "peerDependencies": {
+ "@aws-lambda-powertools/jmespath": "2.33.0",
+ "@middy/core": "4.x || 5.x || 6.x || 7.x"
+ },
+ "peerDependenciesMeta": {
+ "@aws-lambda-powertools/jmespath": {
+ "optional": true
+ },
+ "@middy/core": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@aws-sdk/client-cloudformation": {
+ "version": "3.1030.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-cloudformation/-/client-cloudformation-3.1030.0.tgz",
+ "integrity": "sha512-0irh7PYRGW8fLSHQE6fKM3f/MAHA9CE3WmQWbkcaZ9JWsKhbUxtmfSX3vAoUyaoRIZgPgKS1Qi0hlh6R0qNRag==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/sha256-browser": "5.2.0",
+ "@aws-crypto/sha256-js": "5.2.0",
+ "@aws-sdk/core": "^3.973.27",
+ "@aws-sdk/credential-provider-node": "^3.972.30",
+ "@aws-sdk/middleware-host-header": "^3.972.9",
+ "@aws-sdk/middleware-logger": "^3.972.9",
+ "@aws-sdk/middleware-recursion-detection": "^3.972.10",
+ "@aws-sdk/middleware-user-agent": "^3.972.29",
+ "@aws-sdk/region-config-resolver": "^3.972.11",
+ "@aws-sdk/types": "^3.973.7",
+ "@aws-sdk/util-endpoints": "^3.996.6",
+ "@aws-sdk/util-user-agent-browser": "^3.972.9",
+ "@aws-sdk/util-user-agent-node": "^3.973.15",
+ "@smithy/config-resolver": "^4.4.14",
+ "@smithy/core": "^3.23.14",
+ "@smithy/fetch-http-handler": "^5.3.16",
+ "@smithy/hash-node": "^4.2.13",
+ "@smithy/invalid-dependency": "^4.2.13",
+ "@smithy/middleware-content-length": "^4.2.13",
+ "@smithy/middleware-endpoint": "^4.4.29",
+ "@smithy/middleware-retry": "^4.5.0",
+ "@smithy/middleware-serde": "^4.2.17",
+ "@smithy/middleware-stack": "^4.2.13",
+ "@smithy/node-config-provider": "^4.3.13",
+ "@smithy/node-http-handler": "^4.5.2",
+ "@smithy/protocol-http": "^5.3.13",
+ "@smithy/smithy-client": "^4.12.9",
+ "@smithy/types": "^4.14.0",
+ "@smithy/url-parser": "^4.2.13",
+ "@smithy/util-base64": "^4.3.2",
+ "@smithy/util-body-length-browser": "^4.2.2",
+ "@smithy/util-body-length-node": "^4.2.3",
+ "@smithy/util-defaults-mode-browser": "^4.3.45",
+ "@smithy/util-defaults-mode-node": "^4.2.49",
+ "@smithy/util-endpoints": "^3.3.4",
+ "@smithy/util-middleware": "^4.2.13",
+ "@smithy/util-retry": "^4.3.0",
+ "@smithy/util-utf8": "^4.2.2",
+ "@smithy/util-waiter": "^4.2.15",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-cloudfront": {
+ "version": "3.1030.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-cloudfront/-/client-cloudfront-3.1030.0.tgz",
+ "integrity": "sha512-ilOcxiIvOf8sHIAFT9Z0Hg8AknUl4NY7VBc4BQMbxiyWGGJ3EnXFySlpQMLhOvJ9Me2TciSXxro++QGZlXa3Ew==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/sha256-browser": "5.2.0",
+ "@aws-crypto/sha256-js": "5.2.0",
+ "@aws-sdk/core": "^3.973.27",
+ "@aws-sdk/credential-provider-node": "^3.972.30",
+ "@aws-sdk/middleware-host-header": "^3.972.9",
+ "@aws-sdk/middleware-logger": "^3.972.9",
+ "@aws-sdk/middleware-recursion-detection": "^3.972.10",
+ "@aws-sdk/middleware-user-agent": "^3.972.29",
+ "@aws-sdk/region-config-resolver": "^3.972.11",
+ "@aws-sdk/types": "^3.973.7",
+ "@aws-sdk/util-endpoints": "^3.996.6",
+ "@aws-sdk/util-user-agent-browser": "^3.972.9",
+ "@aws-sdk/util-user-agent-node": "^3.973.15",
+ "@smithy/config-resolver": "^4.4.14",
+ "@smithy/core": "^3.23.14",
+ "@smithy/fetch-http-handler": "^5.3.16",
+ "@smithy/hash-node": "^4.2.13",
+ "@smithy/invalid-dependency": "^4.2.13",
+ "@smithy/middleware-content-length": "^4.2.13",
+ "@smithy/middleware-endpoint": "^4.4.29",
+ "@smithy/middleware-retry": "^4.5.0",
+ "@smithy/middleware-serde": "^4.2.17",
+ "@smithy/middleware-stack": "^4.2.13",
+ "@smithy/node-config-provider": "^4.3.13",
+ "@smithy/node-http-handler": "^4.5.2",
+ "@smithy/protocol-http": "^5.3.13",
+ "@smithy/smithy-client": "^4.12.9",
+ "@smithy/types": "^4.14.0",
+ "@smithy/url-parser": "^4.2.13",
+ "@smithy/util-base64": "^4.3.2",
+ "@smithy/util-body-length-browser": "^4.2.2",
+ "@smithy/util-body-length-node": "^4.2.3",
+ "@smithy/util-defaults-mode-browser": "^4.3.45",
+ "@smithy/util-defaults-mode-node": "^4.2.49",
+ "@smithy/util-endpoints": "^3.3.4",
+ "@smithy/util-middleware": "^4.2.13",
+ "@smithy/util-retry": "^4.3.0",
+ "@smithy/util-stream": "^4.5.22",
+ "@smithy/util-utf8": "^4.2.2",
+ "@smithy/util-waiter": "^4.2.15",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-cloudwatch": {
+ "version": "3.1030.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-cloudwatch/-/client-cloudwatch-3.1030.0.tgz",
+ "integrity": "sha512-LEPjGvcwAVsfZhVP0kMir9CBwRM0cFjIkSiyJ4tHPkpqIenrYTPEMwn54GfeF/k1IFMGvmCDwsOB3Ht58Oo8OA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/sha256-browser": "5.2.0",
+ "@aws-crypto/sha256-js": "5.2.0",
+ "@aws-sdk/core": "^3.973.27",
+ "@aws-sdk/credential-provider-node": "^3.972.30",
+ "@aws-sdk/middleware-host-header": "^3.972.9",
+ "@aws-sdk/middleware-logger": "^3.972.9",
+ "@aws-sdk/middleware-recursion-detection": "^3.972.10",
+ "@aws-sdk/middleware-user-agent": "^3.972.29",
+ "@aws-sdk/region-config-resolver": "^3.972.11",
+ "@aws-sdk/types": "^3.973.7",
+ "@aws-sdk/util-endpoints": "^3.996.6",
+ "@aws-sdk/util-user-agent-browser": "^3.972.9",
+ "@aws-sdk/util-user-agent-node": "^3.973.15",
+ "@smithy/config-resolver": "^4.4.14",
+ "@smithy/core": "^3.23.14",
+ "@smithy/fetch-http-handler": "^5.3.16",
+ "@smithy/hash-node": "^4.2.13",
+ "@smithy/invalid-dependency": "^4.2.13",
+ "@smithy/middleware-compression": "^4.3.43",
+ "@smithy/middleware-content-length": "^4.2.13",
+ "@smithy/middleware-endpoint": "^4.4.29",
+ "@smithy/middleware-retry": "^4.5.0",
+ "@smithy/middleware-serde": "^4.2.17",
+ "@smithy/middleware-stack": "^4.2.13",
+ "@smithy/node-config-provider": "^4.3.13",
+ "@smithy/node-http-handler": "^4.5.2",
+ "@smithy/protocol-http": "^5.3.13",
+ "@smithy/smithy-client": "^4.12.9",
+ "@smithy/types": "^4.14.0",
+ "@smithy/url-parser": "^4.2.13",
+ "@smithy/util-base64": "^4.3.2",
+ "@smithy/util-body-length-browser": "^4.2.2",
+ "@smithy/util-body-length-node": "^4.2.3",
+ "@smithy/util-defaults-mode-browser": "^4.3.45",
+ "@smithy/util-defaults-mode-node": "^4.2.49",
+ "@smithy/util-endpoints": "^3.3.4",
+ "@smithy/util-middleware": "^4.2.13",
+ "@smithy/util-retry": "^4.3.0",
+ "@smithy/util-utf8": "^4.2.2",
+ "@smithy/util-waiter": "^4.2.15",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-cloudwatch-logs": {
+ "version": "3.1030.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-cloudwatch-logs/-/client-cloudwatch-logs-3.1030.0.tgz",
+ "integrity": "sha512-8VVoVOy7bTERDwY1emGktBMB3f7eTDbjvb0RqRR1rtCdGGtelocdGJeazkZvWS3yQmErN5GK6Puvq+4Uq6BHqw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/sha256-browser": "5.2.0",
+ "@aws-crypto/sha256-js": "5.2.0",
+ "@aws-sdk/core": "^3.973.27",
+ "@aws-sdk/credential-provider-node": "^3.972.30",
+ "@aws-sdk/middleware-host-header": "^3.972.9",
+ "@aws-sdk/middleware-logger": "^3.972.9",
+ "@aws-sdk/middleware-recursion-detection": "^3.972.10",
+ "@aws-sdk/middleware-user-agent": "^3.972.29",
+ "@aws-sdk/region-config-resolver": "^3.972.11",
+ "@aws-sdk/types": "^3.973.7",
+ "@aws-sdk/util-endpoints": "^3.996.6",
+ "@aws-sdk/util-user-agent-browser": "^3.972.9",
+ "@aws-sdk/util-user-agent-node": "^3.973.15",
+ "@smithy/config-resolver": "^4.4.14",
+ "@smithy/core": "^3.23.14",
+ "@smithy/eventstream-serde-browser": "^4.2.13",
+ "@smithy/eventstream-serde-config-resolver": "^4.3.13",
+ "@smithy/eventstream-serde-node": "^4.2.13",
+ "@smithy/fetch-http-handler": "^5.3.16",
+ "@smithy/hash-node": "^4.2.13",
+ "@smithy/invalid-dependency": "^4.2.13",
+ "@smithy/middleware-content-length": "^4.2.13",
+ "@smithy/middleware-endpoint": "^4.4.29",
+ "@smithy/middleware-retry": "^4.5.0",
+ "@smithy/middleware-serde": "^4.2.17",
+ "@smithy/middleware-stack": "^4.2.13",
+ "@smithy/node-config-provider": "^4.3.13",
+ "@smithy/node-http-handler": "^4.5.2",
+ "@smithy/protocol-http": "^5.3.13",
+ "@smithy/smithy-client": "^4.12.9",
+ "@smithy/types": "^4.14.0",
+ "@smithy/url-parser": "^4.2.13",
+ "@smithy/util-base64": "^4.3.2",
+ "@smithy/util-body-length-browser": "^4.2.2",
+ "@smithy/util-body-length-node": "^4.2.3",
+ "@smithy/util-defaults-mode-browser": "^4.3.45",
+ "@smithy/util-defaults-mode-node": "^4.2.49",
+ "@smithy/util-endpoints": "^3.3.4",
+ "@smithy/util-middleware": "^4.2.13",
+ "@smithy/util-retry": "^4.3.0",
+ "@smithy/util-utf8": "^4.2.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-sqs": {
+ "version": "3.1030.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-sqs/-/client-sqs-3.1030.0.tgz",
+ "integrity": "sha512-v+m4uejMysJ+Ay9SKDqg8zzdw2WfOGwKIGeYEPR12Wn7j5vKRPXa5Yixnzi07qMGAgOiFj9iEjV2tcqkPqD4ww==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/sha256-browser": "5.2.0",
+ "@aws-crypto/sha256-js": "5.2.0",
+ "@aws-sdk/core": "^3.973.27",
+ "@aws-sdk/credential-provider-node": "^3.972.30",
+ "@aws-sdk/middleware-host-header": "^3.972.9",
+ "@aws-sdk/middleware-logger": "^3.972.9",
+ "@aws-sdk/middleware-recursion-detection": "^3.972.10",
+ "@aws-sdk/middleware-sdk-sqs": "^3.972.19",
+ "@aws-sdk/middleware-user-agent": "^3.972.29",
+ "@aws-sdk/region-config-resolver": "^3.972.11",
+ "@aws-sdk/types": "^3.973.7",
+ "@aws-sdk/util-endpoints": "^3.996.6",
+ "@aws-sdk/util-user-agent-browser": "^3.972.9",
+ "@aws-sdk/util-user-agent-node": "^3.973.15",
+ "@smithy/config-resolver": "^4.4.14",
+ "@smithy/core": "^3.23.14",
+ "@smithy/fetch-http-handler": "^5.3.16",
+ "@smithy/hash-node": "^4.2.13",
+ "@smithy/invalid-dependency": "^4.2.13",
+ "@smithy/md5-js": "^4.2.13",
+ "@smithy/middleware-content-length": "^4.2.13",
+ "@smithy/middleware-endpoint": "^4.4.29",
+ "@smithy/middleware-retry": "^4.5.0",
+ "@smithy/middleware-serde": "^4.2.17",
+ "@smithy/middleware-stack": "^4.2.13",
+ "@smithy/node-config-provider": "^4.3.13",
+ "@smithy/node-http-handler": "^4.5.2",
+ "@smithy/protocol-http": "^5.3.13",
+ "@smithy/smithy-client": "^4.12.9",
+ "@smithy/types": "^4.14.0",
+ "@smithy/url-parser": "^4.2.13",
+ "@smithy/util-base64": "^4.3.2",
+ "@smithy/util-body-length-browser": "^4.2.2",
+ "@smithy/util-body-length-node": "^4.2.3",
+ "@smithy/util-defaults-mode-browser": "^4.3.45",
+ "@smithy/util-defaults-mode-node": "^4.2.49",
+ "@smithy/util-endpoints": "^3.3.4",
+ "@smithy/util-middleware": "^4.2.13",
+ "@smithy/util-retry": "^4.3.0",
+ "@smithy/util-utf8": "^4.2.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/core": {
+ "version": "3.973.27",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.973.27.tgz",
+ "integrity": "sha512-CUZ5m8hwMCH6OYI4Li/WgMfIEx10Q2PLI9Y3XOUTPGZJ53aZ0007jCv+X/ywsaERyKPdw5MRZWk877roQksQ4A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "^3.973.7",
+ "@aws-sdk/xml-builder": "^3.972.17",
+ "@smithy/core": "^3.23.14",
+ "@smithy/node-config-provider": "^4.3.13",
+ "@smithy/property-provider": "^4.2.13",
+ "@smithy/protocol-http": "^5.3.13",
+ "@smithy/signature-v4": "^5.3.13",
+ "@smithy/smithy-client": "^4.12.9",
+ "@smithy/types": "^4.14.0",
+ "@smithy/util-base64": "^4.3.2",
+ "@smithy/util-middleware": "^4.2.13",
+ "@smithy/util-utf8": "^4.2.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-env": {
+ "version": "3.972.25",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.25.tgz",
+ "integrity": "sha512-6QfI0wv4jpG5CrdO/AO0JfZ2ux+tKwJPrUwmvxXF50vI5KIypKVGNF6b4vlkYEnKumDTI1NX2zUBi8JoU5QU3A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "^3.973.27",
+ "@aws-sdk/types": "^3.973.7",
+ "@smithy/property-provider": "^4.2.13",
+ "@smithy/types": "^4.14.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-http": {
+ "version": "3.972.27",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.27.tgz",
+ "integrity": "sha512-3V3Usj9Gs93h865DqN4M2NWJhC5kXU9BvZskfN3+69omuYlE3TZxOEcVQtBGLOloJB7BVfJKXVLqeNhOzHqSlQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "^3.973.27",
+ "@aws-sdk/types": "^3.973.7",
+ "@smithy/fetch-http-handler": "^5.3.16",
+ "@smithy/node-http-handler": "^4.5.2",
+ "@smithy/property-provider": "^4.2.13",
+ "@smithy/protocol-http": "^5.3.13",
+ "@smithy/smithy-client": "^4.12.9",
+ "@smithy/types": "^4.14.0",
+ "@smithy/util-stream": "^4.5.22",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-ini": {
+ "version": "3.972.29",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.972.29.tgz",
+ "integrity": "sha512-SiBuAnXecCbT/OpAf3vqyI/AVE3mTaYr9ShXLybxZiPLBiPCCOIWSGAtYYGQWMRvobBTiqOewaB+wcgMMZI2Aw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "^3.973.27",
+ "@aws-sdk/credential-provider-env": "^3.972.25",
+ "@aws-sdk/credential-provider-http": "^3.972.27",
+ "@aws-sdk/credential-provider-login": "^3.972.29",
+ "@aws-sdk/credential-provider-process": "^3.972.25",
+ "@aws-sdk/credential-provider-sso": "^3.972.29",
+ "@aws-sdk/credential-provider-web-identity": "^3.972.29",
+ "@aws-sdk/nested-clients": "^3.996.19",
+ "@aws-sdk/types": "^3.973.7",
+ "@smithy/credential-provider-imds": "^4.2.13",
+ "@smithy/property-provider": "^4.2.13",
+ "@smithy/shared-ini-file-loader": "^4.4.8",
+ "@smithy/types": "^4.14.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-login": {
+ "version": "3.972.29",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.29.tgz",
+ "integrity": "sha512-OGOslTbOlxXexKMqhxCEbBQbUIfuhGxU5UXw3Fm56ypXHvrXH4aTt/xb5Y884LOoteP1QST1lVZzHfcTnWhiPQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "^3.973.27",
+ "@aws-sdk/nested-clients": "^3.996.19",
+ "@aws-sdk/types": "^3.973.7",
+ "@smithy/property-provider": "^4.2.13",
+ "@smithy/protocol-http": "^5.3.13",
+ "@smithy/shared-ini-file-loader": "^4.4.8",
+ "@smithy/types": "^4.14.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-node": {
+ "version": "3.972.30",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.30.tgz",
+ "integrity": "sha512-FMnAnWxc8PG+ZrZ2OBKzY4luCUJhe9CG0B9YwYr4pzrYGLXBS2rl+UoUvjGbAwiptxRL6hyA3lFn03Bv1TLqTw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/credential-provider-env": "^3.972.25",
+ "@aws-sdk/credential-provider-http": "^3.972.27",
+ "@aws-sdk/credential-provider-ini": "^3.972.29",
+ "@aws-sdk/credential-provider-process": "^3.972.25",
+ "@aws-sdk/credential-provider-sso": "^3.972.29",
+ "@aws-sdk/credential-provider-web-identity": "^3.972.29",
+ "@aws-sdk/types": "^3.973.7",
+ "@smithy/credential-provider-imds": "^4.2.13",
+ "@smithy/property-provider": "^4.2.13",
+ "@smithy/shared-ini-file-loader": "^4.4.8",
+ "@smithy/types": "^4.14.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-process": {
+ "version": "3.972.25",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.25.tgz",
+ "integrity": "sha512-HR7ynNRdNhNsdVCOCegy1HsfsRzozCOPtD3RzzT1JouuaHobWyRfJzCBue/3jP7gECHt+kQyZUvwg/cYLWurNQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "^3.973.27",
+ "@aws-sdk/types": "^3.973.7",
+ "@smithy/property-provider": "^4.2.13",
+ "@smithy/shared-ini-file-loader": "^4.4.8",
+ "@smithy/types": "^4.14.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-sso": {
+ "version": "3.972.29",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.972.29.tgz",
+ "integrity": "sha512-HWv4SEq3jZDYPlwryZVef97+U8CxxRos5mK8sgGO1dQaFZpV5giZLzqGE5hkDmh2csYcBO2uf5XHjPTpZcJlig==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "^3.973.27",
+ "@aws-sdk/nested-clients": "^3.996.19",
+ "@aws-sdk/token-providers": "3.1026.0",
+ "@aws-sdk/types": "^3.973.7",
+ "@smithy/property-provider": "^4.2.13",
+ "@smithy/shared-ini-file-loader": "^4.4.8",
+ "@smithy/types": "^4.14.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-web-identity": {
+ "version": "3.972.29",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.29.tgz",
+ "integrity": "sha512-PdMBza1WEKEUPFEmMGCfnU2RYCz9MskU2e8JxjyUOsMKku7j9YaDKvbDi2dzC0ihFoM6ods2SbhfAAro+Gwlew==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "^3.973.27",
+ "@aws-sdk/nested-clients": "^3.996.19",
+ "@aws-sdk/types": "^3.973.7",
+ "@smithy/property-provider": "^4.2.13",
+ "@smithy/shared-ini-file-loader": "^4.4.8",
+ "@smithy/types": "^4.14.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-host-header": {
+ "version": "3.972.9",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.972.9.tgz",
+ "integrity": "sha512-je5vRdNw4SkuTnmRbFZLdye4sQ0faLt8kwka5wnnSU30q1mHO4X+idGEJOOE+Tn1ME7Oryn05xxkDvIb3UaLaQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "^3.973.7",
+ "@smithy/protocol-http": "^5.3.13",
+ "@smithy/types": "^4.14.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-logger": {
+ "version": "3.972.9",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.972.9.tgz",
+ "integrity": "sha512-HsVgDrruhqI28RkaXALm8grJ7Agc1wF6Et0xh6pom8NdO2VdO/SD9U/tPwUjewwK/pVoka+EShBxyCvgsPCtog==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "^3.973.7",
+ "@smithy/types": "^4.14.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-recursion-detection": {
+ "version": "3.972.10",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.972.10.tgz",
+ "integrity": "sha512-RVQQbq5orQ/GHUnXvqEOj2HHPBJm+mM+ySwZKS5UaLBwra5ugRtiH09PLUoOZRl7a1YzaOzXSuGbn9iD5j60WQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "^3.973.7",
+ "@aws/lambda-invoke-store": "^0.2.2",
+ "@smithy/protocol-http": "^5.3.13",
+ "@smithy/types": "^4.14.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-sdk-sqs": {
+ "version": "3.972.19",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sqs/-/middleware-sdk-sqs-3.972.19.tgz",
+ "integrity": "sha512-S7AWsrOTcs52AdS4uWPtP6n7tloOscfeNfJWK4wvNPJBI01lrfHb6g+tYRckwDzruhhdaPpn/CARZ+YPw6oMGw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "^3.973.7",
+ "@smithy/smithy-client": "^4.12.9",
+ "@smithy/types": "^4.14.0",
+ "@smithy/util-hex-encoding": "^4.2.2",
+ "@smithy/util-utf8": "^4.2.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-user-agent": {
+ "version": "3.972.29",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.972.29.tgz",
+ "integrity": "sha512-f/sIRzuTfEjg6NsbMYvye2VsmnQoNgntntleQyx5uGacUYzszbfIlO3GcI6G6daWUmTm0IDZc11qMHWwF0o0mQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "^3.973.27",
+ "@aws-sdk/types": "^3.973.7",
+ "@aws-sdk/util-endpoints": "^3.996.6",
+ "@smithy/core": "^3.23.14",
+ "@smithy/protocol-http": "^5.3.13",
+ "@smithy/types": "^4.14.0",
+ "@smithy/util-retry": "^4.3.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/nested-clients": {
+ "version": "3.996.19",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.996.19.tgz",
+ "integrity": "sha512-uFkmCDXvmQYLanlYdOFS0+MQWkrj9wPMt/ZCc/0J0fjPim6F5jBVBmEomvGY/j77ILW6GTPwN22Jc174Mhkw6Q==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/sha256-browser": "5.2.0",
+ "@aws-crypto/sha256-js": "5.2.0",
+ "@aws-sdk/core": "^3.973.27",
+ "@aws-sdk/middleware-host-header": "^3.972.9",
+ "@aws-sdk/middleware-logger": "^3.972.9",
+ "@aws-sdk/middleware-recursion-detection": "^3.972.10",
+ "@aws-sdk/middleware-user-agent": "^3.972.29",
+ "@aws-sdk/region-config-resolver": "^3.972.11",
+ "@aws-sdk/types": "^3.973.7",
+ "@aws-sdk/util-endpoints": "^3.996.6",
+ "@aws-sdk/util-user-agent-browser": "^3.972.9",
+ "@aws-sdk/util-user-agent-node": "^3.973.15",
+ "@smithy/config-resolver": "^4.4.14",
+ "@smithy/core": "^3.23.14",
+ "@smithy/fetch-http-handler": "^5.3.16",
+ "@smithy/hash-node": "^4.2.13",
+ "@smithy/invalid-dependency": "^4.2.13",
+ "@smithy/middleware-content-length": "^4.2.13",
+ "@smithy/middleware-endpoint": "^4.4.29",
+ "@smithy/middleware-retry": "^4.5.0",
+ "@smithy/middleware-serde": "^4.2.17",
+ "@smithy/middleware-stack": "^4.2.13",
+ "@smithy/node-config-provider": "^4.3.13",
+ "@smithy/node-http-handler": "^4.5.2",
+ "@smithy/protocol-http": "^5.3.13",
+ "@smithy/smithy-client": "^4.12.9",
+ "@smithy/types": "^4.14.0",
+ "@smithy/url-parser": "^4.2.13",
+ "@smithy/util-base64": "^4.3.2",
+ "@smithy/util-body-length-browser": "^4.2.2",
+ "@smithy/util-body-length-node": "^4.2.3",
+ "@smithy/util-defaults-mode-browser": "^4.3.45",
+ "@smithy/util-defaults-mode-node": "^4.2.49",
+ "@smithy/util-endpoints": "^3.3.4",
+ "@smithy/util-middleware": "^4.2.13",
+ "@smithy/util-retry": "^4.3.0",
+ "@smithy/util-utf8": "^4.2.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/region-config-resolver": {
+ "version": "3.972.11",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.972.11.tgz",
+ "integrity": "sha512-6Q8B1dcx6BBqUTY1Mc/eROKA0FImEEY5VPSd6AGPEUf0ErjExz4snVqa9kNJSoVDV1rKaNf3qrWojgcKW+SdDg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "^3.973.7",
+ "@smithy/config-resolver": "^4.4.14",
+ "@smithy/node-config-provider": "^4.3.13",
+ "@smithy/types": "^4.14.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/token-providers": {
+ "version": "3.1026.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.1026.0.tgz",
+ "integrity": "sha512-Ieq/HiRrbEtrYP387Nes0XlR7H1pJiJOZKv+QyQzMYpvTiDs0VKy2ZB3E2Zf+aFovWmeE7lRE4lXyF7dYM6GgA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "^3.973.27",
+ "@aws-sdk/nested-clients": "^3.996.19",
+ "@aws-sdk/types": "^3.973.7",
+ "@smithy/property-provider": "^4.2.13",
+ "@smithy/shared-ini-file-loader": "^4.4.8",
+ "@smithy/types": "^4.14.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/types": {
+ "version": "3.973.7",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.973.7.tgz",
+ "integrity": "sha512-reXRwoJ6CfChoqAsBszUYajAF8Z2LRE+CRcKocvFSMpIiLOtYU3aJ9trmn6VVPAzbbY5LXF+FfmUslbXk1SYFg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.14.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/util-endpoints": {
+ "version": "3.996.6",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.996.6.tgz",
+ "integrity": "sha512-2nUQ+2ih7CShuKHpGSIYvvAIOHy52dOZguYG36zptBukhw6iFwcvGfG0tes0oZFWQqEWvgZe9HLWaNlvXGdOrg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "^3.973.7",
+ "@smithy/types": "^4.14.0",
+ "@smithy/url-parser": "^4.2.13",
+ "@smithy/util-endpoints": "^3.3.4",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/util-locate-window": {
+ "version": "3.965.5",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.965.5.tgz",
+ "integrity": "sha512-WhlJNNINQB+9qtLtZJcpQdgZw3SCDCpXdUJP7cToGwHbCWCnRckGlc6Bx/OhWwIYFNAn+FIydY8SZ0QmVu3xTQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/util-user-agent-browser": {
+ "version": "3.972.9",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.972.9.tgz",
+ "integrity": "sha512-sn/LMzTbGjYqCCF24390WxPd6hkpoSptiUn5DzVp4cD71yqw+yGEGm1YCxyEoPXyc8qciM8UzLJcZBFslxo5Uw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "^3.973.7",
+ "@smithy/types": "^4.14.0",
+ "bowser": "^2.11.0",
+ "tslib": "^2.6.2"
+ }
+ },
+ "node_modules/@aws-sdk/util-user-agent-node": {
+ "version": "3.973.15",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.973.15.tgz",
+ "integrity": "sha512-fYn3s9PtKdgQkczGZCFMgkNEe8aq1JCVbnRqjqN9RSVW43xn2RV9xdcZ3z01a48Jpkuh/xCmBKJxdLOo4Ozg7w==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/middleware-user-agent": "^3.972.29",
+ "@aws-sdk/types": "^3.973.7",
+ "@smithy/node-config-provider": "^4.3.13",
+ "@smithy/types": "^4.14.0",
+ "@smithy/util-config-provider": "^4.2.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ },
+ "peerDependencies": {
+ "aws-crt": ">=1.0.0"
+ },
+ "peerDependenciesMeta": {
+ "aws-crt": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@aws-sdk/xml-builder": {
+ "version": "3.972.22",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.972.22.tgz",
+ "integrity": "sha512-PMYKKtJd70IsSG0yHrdAbxBr+ZWBKLvzFZfD3/urxgf6hXVMzuU5M+3MJ5G67RpOmLBu1fAUN65SbWuKUCOlAA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@nodable/entities": "2.1.0",
+ "@smithy/types": "^4.14.1",
+ "fast-xml-parser": "5.7.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/aws-alb-fargate": {
+ "version": "2.101.0",
+ "resolved": "https://registry.npmjs.org/@aws-solutions-constructs/aws-alb-fargate/-/aws-alb-fargate-2.101.0.tgz",
+ "integrity": "sha512-X0JQTVw2piBGjBafQEyyjbRGtPQxxpHBM3lHhykwSO7S+bNuhvmmxO15+UUCa1uFLjj9mQqkBKPMd6hpIAggHw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-solutions-constructs/core": "2.101.0",
+ "constructs": "^10.0.0"
+ },
+ "peerDependencies": {
+ "@aws-solutions-constructs/core": "2.101.0",
+ "aws-cdk-lib": "^2.248.0",
+ "constructs": "^10.0.0"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/aws-alb-fargate/node_modules/@aws-solutions-constructs/core": {
+ "version": "2.101.0",
+ "resolved": "https://registry.npmjs.org/@aws-solutions-constructs/core/-/core-2.101.0.tgz",
+ "integrity": "sha512-5pXH1WIGC/gAgq6cjoa5Xkjfi81QFfX9vS/vT1yJUa8mtoIuHmNtUsMgHGI4ReiBebQK5oIg428KhF+bjyI+og==",
+ "bundleDependencies": [
+ "deepmerge",
+ "npmlog",
+ "deep-diff"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-cdk/cloud-assembly-schema": "^53.13.0",
+ "constructs": "^10.0.0",
+ "deep-diff": "^1.0.2",
+ "deepmerge": "^4.0.0",
+ "npmlog": "^7.0.0"
+ },
+ "peerDependencies": {
+ "aws-cdk-lib": "^2.248.0",
+ "constructs": "^10.0.0"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/aws-alb-fargate/node_modules/@aws-solutions-constructs/core/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/aws-alb-fargate/node_modules/@aws-solutions-constructs/core/node_modules/aproba": {
+ "version": "2.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/@aws-solutions-constructs/aws-alb-fargate/node_modules/@aws-solutions-constructs/core/node_modules/are-we-there-yet": {
+ "version": "4.0.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/aws-alb-fargate/node_modules/@aws-solutions-constructs/core/node_modules/color-support": {
+ "version": "1.1.3",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/@aws-solutions-constructs/aws-alb-fargate/node_modules/@aws-solutions-constructs/core/node_modules/console-control-strings": {
+ "version": "1.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/@aws-solutions-constructs/aws-alb-fargate/node_modules/@aws-solutions-constructs/core/node_modules/deep-diff": {
+ "version": "1.0.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/@aws-solutions-constructs/aws-alb-fargate/node_modules/@aws-solutions-constructs/core/node_modules/deepmerge": {
+ "version": "4.3.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/aws-alb-fargate/node_modules/@aws-solutions-constructs/core/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/@aws-solutions-constructs/aws-alb-fargate/node_modules/@aws-solutions-constructs/core/node_modules/gauge": {
+ "version": "5.0.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "aproba": "^1.0.3 || ^2.0.0",
+ "color-support": "^1.1.3",
+ "console-control-strings": "^1.1.0",
+ "has-unicode": "^2.0.1",
+ "signal-exit": "^4.0.1",
+ "string-width": "^4.2.3",
+ "strip-ansi": "^6.0.1",
+ "wide-align": "^1.1.5"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/aws-alb-fargate/node_modules/@aws-solutions-constructs/core/node_modules/has-unicode": {
+ "version": "2.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/@aws-solutions-constructs/aws-alb-fargate/node_modules/@aws-solutions-constructs/core/node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/aws-alb-fargate/node_modules/@aws-solutions-constructs/core/node_modules/npmlog": {
+ "version": "7.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "are-we-there-yet": "^4.0.0",
+ "console-control-strings": "^1.1.0",
+ "gauge": "^5.0.0",
+ "set-blocking": "^2.0.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/aws-alb-fargate/node_modules/@aws-solutions-constructs/core/node_modules/set-blocking": {
+ "version": "2.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/@aws-solutions-constructs/aws-alb-fargate/node_modules/@aws-solutions-constructs/core/node_modules/signal-exit": {
+ "version": "4.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/aws-alb-fargate/node_modules/@aws-solutions-constructs/core/node_modules/string-width": {
+ "version": "4.2.3",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/aws-alb-fargate/node_modules/@aws-solutions-constructs/core/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/aws-alb-fargate/node_modules/@aws-solutions-constructs/core/node_modules/wide-align": {
+ "version": "1.1.5",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^1.0.2 || 2 || 3 || 4"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/aws-apigateway-lambda": {
+ "version": "2.51.0",
+ "resolved": "https://registry.npmjs.org/@aws-solutions-constructs/aws-apigateway-lambda/-/aws-apigateway-lambda-2.51.0.tgz",
+ "integrity": "sha512-7RWaXGa//9j3YVB8tZxfsy8S0c9EokdMv+JdSNwBzygPuaZBnR8eDnjiPTor8MHv9fhhtSaLolMDpqdYpzFo7g==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-solutions-constructs/core": "2.51.0",
+ "constructs": "^10.0.0"
+ },
+ "peerDependencies": {
+ "@aws-solutions-constructs/core": "2.51.0",
+ "aws-cdk-lib": "^2.118.0",
+ "constructs": "^10.0.0"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/aws-cloudfront-apigateway": {
+ "version": "2.51.0",
+ "resolved": "https://registry.npmjs.org/@aws-solutions-constructs/aws-cloudfront-apigateway/-/aws-cloudfront-apigateway-2.51.0.tgz",
+ "integrity": "sha512-3UTEc+76cNOe7qn3qAwhNHlq7JIfwe07nijS9cfkUThAsfi4faP49+rcAzluZPx7dPGFUp0zK4MYiiXaVuN8vQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-solutions-constructs/core": "2.51.0",
+ "constructs": "^10.0.0"
+ },
+ "peerDependencies": {
+ "@aws-solutions-constructs/core": "2.51.0",
+ "aws-cdk-lib": "^2.118.0",
+ "constructs": "^10.0.0"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/aws-cloudfront-apigateway-lambda": {
+ "version": "2.51.0",
+ "resolved": "https://registry.npmjs.org/@aws-solutions-constructs/aws-cloudfront-apigateway-lambda/-/aws-cloudfront-apigateway-lambda-2.51.0.tgz",
+ "integrity": "sha512-juVPg0h9hP1i2YKh+avyBCpud9pOPPzZHW9+hcf6LlqdcYp0VrrmNFta3W7GhFFmXLxU77Nwn80i56Wn2chzxg==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-solutions-constructs/aws-cloudfront-apigateway": "2.51.0",
+ "@aws-solutions-constructs/core": "2.51.0",
+ "constructs": "^10.0.0"
+ },
+ "peerDependencies": {
+ "@aws-solutions-constructs/aws-cloudfront-apigateway": "2.51.0",
+ "@aws-solutions-constructs/core": "2.51.0",
+ "aws-cdk-lib": "^2.118.0",
+ "constructs": "^10.0.0"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/aws-cloudfront-s3": {
+ "version": "2.51.0",
+ "resolved": "https://registry.npmjs.org/@aws-solutions-constructs/aws-cloudfront-s3/-/aws-cloudfront-s3-2.51.0.tgz",
+ "integrity": "sha512-11TV5xdrT48lQams3fR8b7GYcECqrQ6lbvCfyENqbmozWwVrnmNZxoFcIy4VF9oQPwx07kKsAsgsHnuDJhQjBQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-solutions-constructs/core": "2.51.0",
+ "@aws-solutions-constructs/resources": "2.51.0",
+ "constructs": "^10.0.0"
+ },
+ "peerDependencies": {
+ "@aws-solutions-constructs/core": "2.51.0",
+ "@aws-solutions-constructs/resources": "2.51.0",
+ "aws-cdk-lib": "^2.118.0",
+ "constructs": "^10.0.0"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/aws-lambda-dynamodb": {
+ "version": "2.101.0",
+ "resolved": "https://registry.npmjs.org/@aws-solutions-constructs/aws-lambda-dynamodb/-/aws-lambda-dynamodb-2.101.0.tgz",
+ "integrity": "sha512-m9MmRGQdn2YWdLBKhTuoA7MnfH3gLTWdEbmf60VZkn/j6GAmqwK5iscyN7rTtECNdBC3vq5bxooa8lJpSlQEwQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-solutions-constructs/core": "2.101.0",
+ "constructs": "^10.0.0"
+ },
+ "peerDependencies": {
+ "@aws-solutions-constructs/core": "2.101.0",
+ "aws-cdk-lib": "^2.248.0",
+ "constructs": "^10.0.0"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/aws-lambda-dynamodb/node_modules/@aws-solutions-constructs/core": {
+ "version": "2.101.0",
+ "resolved": "https://registry.npmjs.org/@aws-solutions-constructs/core/-/core-2.101.0.tgz",
+ "integrity": "sha512-5pXH1WIGC/gAgq6cjoa5Xkjfi81QFfX9vS/vT1yJUa8mtoIuHmNtUsMgHGI4ReiBebQK5oIg428KhF+bjyI+og==",
+ "bundleDependencies": [
+ "deepmerge",
+ "npmlog",
+ "deep-diff"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-cdk/cloud-assembly-schema": "^53.13.0",
+ "constructs": "^10.0.0",
+ "deep-diff": "^1.0.2",
+ "deepmerge": "^4.0.0",
+ "npmlog": "^7.0.0"
+ },
+ "peerDependencies": {
+ "aws-cdk-lib": "^2.248.0",
+ "constructs": "^10.0.0"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/aws-lambda-dynamodb/node_modules/@aws-solutions-constructs/core/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/aws-lambda-dynamodb/node_modules/@aws-solutions-constructs/core/node_modules/aproba": {
+ "version": "2.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/@aws-solutions-constructs/aws-lambda-dynamodb/node_modules/@aws-solutions-constructs/core/node_modules/are-we-there-yet": {
+ "version": "4.0.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/aws-lambda-dynamodb/node_modules/@aws-solutions-constructs/core/node_modules/color-support": {
+ "version": "1.1.3",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/@aws-solutions-constructs/aws-lambda-dynamodb/node_modules/@aws-solutions-constructs/core/node_modules/console-control-strings": {
+ "version": "1.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/@aws-solutions-constructs/aws-lambda-dynamodb/node_modules/@aws-solutions-constructs/core/node_modules/deep-diff": {
+ "version": "1.0.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/@aws-solutions-constructs/aws-lambda-dynamodb/node_modules/@aws-solutions-constructs/core/node_modules/deepmerge": {
+ "version": "4.3.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/aws-lambda-dynamodb/node_modules/@aws-solutions-constructs/core/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/@aws-solutions-constructs/aws-lambda-dynamodb/node_modules/@aws-solutions-constructs/core/node_modules/gauge": {
+ "version": "5.0.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "aproba": "^1.0.3 || ^2.0.0",
+ "color-support": "^1.1.3",
+ "console-control-strings": "^1.1.0",
+ "has-unicode": "^2.0.1",
+ "signal-exit": "^4.0.1",
+ "string-width": "^4.2.3",
+ "strip-ansi": "^6.0.1",
+ "wide-align": "^1.1.5"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/aws-lambda-dynamodb/node_modules/@aws-solutions-constructs/core/node_modules/has-unicode": {
+ "version": "2.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/@aws-solutions-constructs/aws-lambda-dynamodb/node_modules/@aws-solutions-constructs/core/node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/aws-lambda-dynamodb/node_modules/@aws-solutions-constructs/core/node_modules/npmlog": {
+ "version": "7.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "are-we-there-yet": "^4.0.0",
+ "console-control-strings": "^1.1.0",
+ "gauge": "^5.0.0",
+ "set-blocking": "^2.0.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/aws-lambda-dynamodb/node_modules/@aws-solutions-constructs/core/node_modules/set-blocking": {
+ "version": "2.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/@aws-solutions-constructs/aws-lambda-dynamodb/node_modules/@aws-solutions-constructs/core/node_modules/signal-exit": {
+ "version": "4.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/aws-lambda-dynamodb/node_modules/@aws-solutions-constructs/core/node_modules/string-width": {
+ "version": "4.2.3",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/aws-lambda-dynamodb/node_modules/@aws-solutions-constructs/core/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/aws-lambda-dynamodb/node_modules/@aws-solutions-constructs/core/node_modules/wide-align": {
+ "version": "1.1.5",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^1.0.2 || 2 || 3 || 4"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/aws-openapigateway-lambda": {
+ "version": "2.101.0",
+ "resolved": "https://registry.npmjs.org/@aws-solutions-constructs/aws-openapigateway-lambda/-/aws-openapigateway-lambda-2.101.0.tgz",
+ "integrity": "sha512-w4UH3WUikrqGalgyXq+lBPXPMpBxRk7uAgNEM3LPqELDRH4uKwx+TBYaqUB5LhuFrk5gpXYeLYb6oPPFMqE2AA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-solutions-constructs/core": "2.101.0",
+ "@aws-solutions-constructs/resources": "2.101.0",
+ "constructs": "^10.0.0"
+ },
+ "peerDependencies": {
+ "@aws-solutions-constructs/core": "2.101.0",
+ "@aws-solutions-constructs/resources": "2.101.0",
+ "aws-cdk-lib": "^2.248.0",
+ "constructs": "^10.0.0"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/aws-openapigateway-lambda/node_modules/@aws-solutions-constructs/core": {
+ "version": "2.101.0",
+ "resolved": "https://registry.npmjs.org/@aws-solutions-constructs/core/-/core-2.101.0.tgz",
+ "integrity": "sha512-5pXH1WIGC/gAgq6cjoa5Xkjfi81QFfX9vS/vT1yJUa8mtoIuHmNtUsMgHGI4ReiBebQK5oIg428KhF+bjyI+og==",
+ "bundleDependencies": [
+ "deepmerge",
+ "npmlog",
+ "deep-diff"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-cdk/cloud-assembly-schema": "^53.13.0",
+ "constructs": "^10.0.0",
+ "deep-diff": "^1.0.2",
+ "deepmerge": "^4.0.0",
+ "npmlog": "^7.0.0"
+ },
+ "peerDependencies": {
+ "aws-cdk-lib": "^2.248.0",
+ "constructs": "^10.0.0"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/aws-openapigateway-lambda/node_modules/@aws-solutions-constructs/core/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/aws-openapigateway-lambda/node_modules/@aws-solutions-constructs/core/node_modules/aproba": {
+ "version": "2.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/@aws-solutions-constructs/aws-openapigateway-lambda/node_modules/@aws-solutions-constructs/core/node_modules/are-we-there-yet": {
+ "version": "4.0.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/aws-openapigateway-lambda/node_modules/@aws-solutions-constructs/core/node_modules/color-support": {
+ "version": "1.1.3",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/@aws-solutions-constructs/aws-openapigateway-lambda/node_modules/@aws-solutions-constructs/core/node_modules/console-control-strings": {
+ "version": "1.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/@aws-solutions-constructs/aws-openapigateway-lambda/node_modules/@aws-solutions-constructs/core/node_modules/deep-diff": {
+ "version": "1.0.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/@aws-solutions-constructs/aws-openapigateway-lambda/node_modules/@aws-solutions-constructs/core/node_modules/deepmerge": {
+ "version": "4.3.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/aws-openapigateway-lambda/node_modules/@aws-solutions-constructs/core/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/@aws-solutions-constructs/aws-openapigateway-lambda/node_modules/@aws-solutions-constructs/core/node_modules/gauge": {
+ "version": "5.0.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "aproba": "^1.0.3 || ^2.0.0",
+ "color-support": "^1.1.3",
+ "console-control-strings": "^1.1.0",
+ "has-unicode": "^2.0.1",
+ "signal-exit": "^4.0.1",
+ "string-width": "^4.2.3",
+ "strip-ansi": "^6.0.1",
+ "wide-align": "^1.1.5"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/aws-openapigateway-lambda/node_modules/@aws-solutions-constructs/core/node_modules/has-unicode": {
+ "version": "2.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/@aws-solutions-constructs/aws-openapigateway-lambda/node_modules/@aws-solutions-constructs/core/node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/aws-openapigateway-lambda/node_modules/@aws-solutions-constructs/core/node_modules/npmlog": {
+ "version": "7.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "are-we-there-yet": "^4.0.0",
+ "console-control-strings": "^1.1.0",
+ "gauge": "^5.0.0",
+ "set-blocking": "^2.0.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/aws-openapigateway-lambda/node_modules/@aws-solutions-constructs/core/node_modules/set-blocking": {
+ "version": "2.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/@aws-solutions-constructs/aws-openapigateway-lambda/node_modules/@aws-solutions-constructs/core/node_modules/signal-exit": {
+ "version": "4.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/aws-openapigateway-lambda/node_modules/@aws-solutions-constructs/core/node_modules/string-width": {
+ "version": "4.2.3",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/aws-openapigateway-lambda/node_modules/@aws-solutions-constructs/core/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/aws-openapigateway-lambda/node_modules/@aws-solutions-constructs/core/node_modules/wide-align": {
+ "version": "1.1.5",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^1.0.2 || 2 || 3 || 4"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/aws-openapigateway-lambda/node_modules/@aws-solutions-constructs/resources": {
+ "version": "2.101.0",
+ "resolved": "https://registry.npmjs.org/@aws-solutions-constructs/resources/-/resources-2.101.0.tgz",
+ "integrity": "sha512-YjGOUx/KEqvEHCceoJ9H3xYBXwowzLyhYGML0UYDTkmhjONP06ayKc95GLpib4QltI9CWeOqpfPVKmdjYstq3w==",
+ "bundleDependencies": [
+ "@aws-sdk/client-kms",
+ "@aws-sdk/client-s3"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/client-kms": "^3.478.0",
+ "@aws-sdk/client-s3": "^3.478.0",
+ "@aws-solutions-constructs/core": "2.101.0",
+ "constructs": "^10.0.0"
+ },
+ "peerDependencies": {
+ "@aws-solutions-constructs/core": "2.101.0",
+ "aws-cdk-lib": "^2.248.0",
+ "constructs": "^10.0.0"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/core": {
+ "version": "2.51.0",
+ "resolved": "https://registry.npmjs.org/@aws-solutions-constructs/core/-/core-2.51.0.tgz",
+ "integrity": "sha512-55LQfMgxbXSpfLduOygTNUrAOxlj09lDufbL+mcncB/1hDkJiawYQYx/OUcFWFfGSheXRwNoxOP4FYVS/7cCDQ==",
+ "bundleDependencies": [
+ "deepmerge",
+ "npmlog",
+ "deep-diff"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "constructs": "^10.0.0",
+ "deep-diff": "^1.0.2",
+ "deepmerge": "^4.0.0",
+ "npmlog": "^4.1.2"
+ },
+ "peerDependencies": {
+ "aws-cdk-lib": "^2.118.0",
+ "constructs": "^10.0.0"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/ansi-regex": {
+ "version": "2.1.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/aproba": {
+ "version": "1.2.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/are-we-there-yet": {
+ "version": "1.1.7",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "delegates": "^1.0.0",
+ "readable-stream": "^2.0.6"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/code-point-at": {
+ "version": "1.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/console-control-strings": {
+ "version": "1.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/core-util-is": {
+ "version": "1.0.3",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/deep-diff": {
+ "version": "1.0.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/deepmerge": {
+ "version": "4.3.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/delegates": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/gauge": {
+ "version": "2.7.4",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "aproba": "^1.0.3",
+ "console-control-strings": "^1.0.0",
+ "has-unicode": "^2.0.0",
+ "object-assign": "^4.1.0",
+ "signal-exit": "^3.0.0",
+ "string-width": "^1.0.1",
+ "strip-ansi": "^3.0.1",
+ "wide-align": "^1.1.0"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/has-unicode": {
+ "version": "2.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/inherits": {
+ "version": "2.0.4",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "number-is-nan": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/isarray": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/npmlog": {
+ "version": "4.1.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "are-we-there-yet": "~1.1.2",
+ "console-control-strings": "~1.1.0",
+ "gauge": "~2.7.3",
+ "set-blocking": "~2.0.0"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/number-is-nan": {
+ "version": "1.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/object-assign": {
+ "version": "4.1.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/process-nextick-args": {
+ "version": "2.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/readable-stream": {
+ "version": "2.3.8",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/safe-buffer": {
+ "version": "5.1.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/set-blocking": {
+ "version": "2.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/signal-exit": {
+ "version": "3.0.7",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/string_decoder": {
+ "version": "1.1.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/string-width": {
+ "version": "1.0.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/strip-ansi": {
+ "version": "3.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/wide-align": {
+ "version": "1.1.5",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^1.0.2 || 2 || 3 || 4"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/wide-align/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/wide-align/node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/wide-align/node_modules/string-width": {
+ "version": "4.2.3",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/wide-align/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/resources": {
+ "version": "2.51.0",
+ "resolved": "https://registry.npmjs.org/@aws-solutions-constructs/resources/-/resources-2.51.0.tgz",
+ "integrity": "sha512-QYZjnyGnMsdKYxYPfQ6vVn2AfbnuwuzVBbWiC/mJhWBE6N5IPXd7YRj+dWT0D440fdFx/sBUpsWWPWeWbgwNWw==",
+ "bundleDependencies": [
+ "@aws-sdk/client-kms",
+ "@aws-sdk/client-s3",
+ "aws-sdk-client-mock"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/client-kms": "^3.478.0",
+ "@aws-sdk/client-s3": "^3.478.0",
+ "@aws-solutions-constructs/core": "2.51.0",
+ "aws-sdk-client-mock": "^3.0.0",
+ "constructs": "^10.0.0"
+ },
+ "peerDependencies": {
+ "@aws-solutions-constructs/core": "2.51.0",
+ "aws-cdk-lib": "^2.118.0",
+ "constructs": "^10.0.0"
+ }
+ },
+ "node_modules/@aws/lambda-invoke-store": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/@aws/lambda-invoke-store/-/lambda-invoke-store-0.2.4.tgz",
+ "integrity": "sha512-iY8yvjE0y651BixKNPgmv1WrQc+GZ142sb0z4gYnChDDY2YqI4P/jsSopBWrKfAt7LOJAkOXt7rC/hms+WclQQ==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz",
+ "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.28.5",
+ "js-tokens": "^4.0.0",
+ "picocolors": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/compat-data": {
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz",
+ "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/core": {
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz",
+ "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.29.0",
+ "@babel/generator": "^7.29.0",
+ "@babel/helper-compilation-targets": "^7.28.6",
+ "@babel/helper-module-transforms": "^7.28.6",
+ "@babel/helpers": "^7.28.6",
+ "@babel/parser": "^7.29.0",
+ "@babel/template": "^7.28.6",
+ "@babel/traverse": "^7.29.0",
+ "@babel/types": "^7.29.0",
+ "@jridgewell/remapping": "^2.3.5",
+ "convert-source-map": "^2.0.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.3",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
+ }
+ },
+ "node_modules/@babel/generator": {
+ "version": "7.29.1",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz",
+ "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.29.0",
+ "@babel/types": "^7.29.0",
+ "@jridgewell/gen-mapping": "^0.3.12",
+ "@jridgewell/trace-mapping": "^0.3.28",
+ "jsesc": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz",
+ "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/compat-data": "^7.28.6",
+ "@babel/helper-validator-option": "^7.27.1",
+ "browserslist": "^4.24.0",
+ "lru-cache": "^5.1.1",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-globals": {
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz",
+ "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-imports": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz",
+ "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/traverse": "^7.28.6",
+ "@babel/types": "^7.28.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-transforms": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz",
+ "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.28.6",
+ "@babel/helper-validator-identifier": "^7.28.5",
+ "@babel/traverse": "^7.28.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-plugin-utils": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz",
+ "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
+ "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
+ "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-option": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz",
+ "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helpers": {
+ "version": "7.29.2",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz",
+ "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/template": "^7.28.6",
+ "@babel/types": "^7.29.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.29.2",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz",
+ "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.29.0"
+ },
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-async-generators": {
+ "version": "7.8.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
+ "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-bigint": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz",
+ "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-class-properties": {
+ "version": "7.12.13",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz",
+ "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.12.13"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-class-static-block": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz",
+ "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-import-attributes": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.28.6.tgz",
+ "integrity": "sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.28.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-import-meta": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz",
+ "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-json-strings": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
+ "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-jsx": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.28.6.tgz",
+ "integrity": "sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.28.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-logical-assignment-operators": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
+ "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
+ "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-numeric-separator": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz",
+ "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-object-rest-spread": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz",
+ "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-optional-catch-binding": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz",
+ "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-optional-chaining": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
+ "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-private-property-in-object": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz",
+ "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-top-level-await": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz",
+ "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-typescript": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.28.6.tgz",
+ "integrity": "sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.28.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/template": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz",
+ "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.28.6",
+ "@babel/parser": "^7.28.6",
+ "@babel/types": "^7.28.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse": {
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz",
+ "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.29.0",
+ "@babel/generator": "^7.29.0",
+ "@babel/helper-globals": "^7.28.0",
+ "@babel/parser": "^7.29.0",
+ "@babel/template": "^7.28.6",
+ "@babel/types": "^7.29.0",
+ "debug": "^4.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz",
+ "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.27.1",
+ "@babel/helper-validator-identifier": "^7.28.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@bcoe/v8-coverage": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz",
+ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@cspotcode/source-map-support": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
+ "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/trace-mapping": "0.3.9"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.9",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
+ "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.0.3",
+ "@jridgewell/sourcemap-codec": "^1.4.10"
+ }
+ },
+ "node_modules/@datastream/core": {
+ "version": "0.0.38",
+ "resolved": "https://registry.npmjs.org/@datastream/core/-/core-0.0.38.tgz",
+ "integrity": "sha512-9rFyIg+dlEhrFqf2IxkMm+nSEptOdBB/soXxvU0ynnkIhBW4CZk5jkDubiaeygOxXzN9sm6pAWdWdmkQohQVxg==",
+ "license": "MIT",
+ "dependencies": {
+ "cloneable-readable": "3.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@emnapi/runtime": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz",
+ "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@esbuild/aix-ppc64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz",
+ "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz",
+ "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz",
+ "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz",
+ "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz",
+ "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz",
+ "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz",
+ "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz",
+ "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz",
+ "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz",
+ "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz",
+ "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz",
+ "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz",
+ "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz",
+ "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz",
+ "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz",
+ "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz",
+ "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz",
+ "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz",
+ "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz",
+ "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz",
+ "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openharmony-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz",
+ "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz",
+ "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz",
+ "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz",
+ "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz",
+ "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@img/colour": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz",
+ "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@img/sharp-darwin-arm64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz",
+ "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-darwin-arm64": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-darwin-x64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz",
+ "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-darwin-x64": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-libvips-darwin-arm64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz",
+ "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-darwin-x64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz",
+ "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-arm": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz",
+ "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-arm64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz",
+ "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-ppc64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz",
+ "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-riscv64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz",
+ "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==",
+ "cpu": [
+ "riscv64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-s390x": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz",
+ "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==",
+ "cpu": [
+ "s390x"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-x64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz",
+ "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linuxmusl-arm64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz",
+ "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linuxmusl-x64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz",
+ "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-linux-arm": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz",
+ "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-arm": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-linux-arm64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz",
+ "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-arm64": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-linux-ppc64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz",
+ "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-ppc64": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-linux-riscv64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz",
+ "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==",
+ "cpu": [
+ "riscv64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-riscv64": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-linux-s390x": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz",
+ "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==",
+ "cpu": [
+ "s390x"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-s390x": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-linux-x64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz",
+ "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-x64": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-linuxmusl-arm64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz",
+ "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linuxmusl-arm64": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-linuxmusl-x64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz",
+ "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linuxmusl-x64": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-wasm32": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz",
+ "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==",
+ "cpu": [
+ "wasm32"
+ ],
+ "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/runtime": "^1.7.0"
+ },
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-win32-arm64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz",
+ "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "Apache-2.0 AND LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-win32-ia32": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz",
+ "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==",
+ "cpu": [
+ "ia32"
+ ],
+ "license": "Apache-2.0 AND LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-win32-x64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz",
+ "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "Apache-2.0 AND LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
+ "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "camelcase": "^5.3.1",
+ "find-up": "^4.1.0",
+ "get-package-type": "^0.1.0",
+ "js-yaml": "^3.13.1",
+ "resolve-from": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@istanbuljs/schema": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.6.tgz",
+ "integrity": "sha512-+Sg6GCR/wy1oSmQDFq4LQDAhm3ETKnorxN+y5nbLULOR3P0c14f2Wurzj3/xqPXtasLFfHd5iRFQ7AJt4KH2cw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@jest/console": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz",
+ "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "jest-message-util": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/core": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz",
+ "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/console": "^29.7.0",
+ "@jest/reporters": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "ansi-escapes": "^4.2.1",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "exit": "^0.1.2",
+ "graceful-fs": "^4.2.9",
+ "jest-changed-files": "^29.7.0",
+ "jest-config": "^29.7.0",
+ "jest-haste-map": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-regex-util": "^29.6.3",
+ "jest-resolve": "^29.7.0",
+ "jest-resolve-dependencies": "^29.7.0",
+ "jest-runner": "^29.7.0",
+ "jest-runtime": "^29.7.0",
+ "jest-snapshot": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-validate": "^29.7.0",
+ "jest-watcher": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "pretty-format": "^29.7.0",
+ "slash": "^3.0.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@jest/environment": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz",
+ "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/fake-timers": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "jest-mock": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/expect": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz",
+ "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "expect": "^29.7.0",
+ "jest-snapshot": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/expect-utils": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz",
+ "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "jest-get-type": "^29.6.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/fake-timers": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz",
+ "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@sinonjs/fake-timers": "^10.0.2",
+ "@types/node": "*",
+ "jest-message-util": "^29.7.0",
+ "jest-mock": "^29.7.0",
+ "jest-util": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/globals": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz",
+ "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/environment": "^29.7.0",
+ "@jest/expect": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "jest-mock": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/reporters": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz",
+ "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@bcoe/v8-coverage": "^0.2.3",
+ "@jest/console": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@jridgewell/trace-mapping": "^0.3.18",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "collect-v8-coverage": "^1.0.0",
+ "exit": "^0.1.2",
+ "glob": "^7.1.3",
+ "graceful-fs": "^4.2.9",
+ "istanbul-lib-coverage": "^3.0.0",
+ "istanbul-lib-instrument": "^6.0.0",
+ "istanbul-lib-report": "^3.0.0",
+ "istanbul-lib-source-maps": "^4.0.0",
+ "istanbul-reports": "^3.1.3",
+ "jest-message-util": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-worker": "^29.7.0",
+ "slash": "^3.0.0",
+ "string-length": "^4.0.1",
+ "strip-ansi": "^6.0.0",
+ "v8-to-istanbul": "^9.0.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@jest/schemas": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
+ "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@sinclair/typebox": "^0.27.8"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/source-map": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz",
+ "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/trace-mapping": "^0.3.18",
+ "callsites": "^3.0.0",
+ "graceful-fs": "^4.2.9"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/test-result": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz",
+ "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/console": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "collect-v8-coverage": "^1.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/test-sequencer": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz",
+ "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/test-result": "^29.7.0",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.7.0",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/transform": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz",
+ "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.11.6",
+ "@jest/types": "^29.6.3",
+ "@jridgewell/trace-mapping": "^0.3.18",
+ "babel-plugin-istanbul": "^6.1.1",
+ "chalk": "^4.0.0",
+ "convert-source-map": "^2.0.0",
+ "fast-json-stable-stringify": "^2.1.0",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.7.0",
+ "jest-regex-util": "^29.6.3",
+ "jest-util": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "pirates": "^4.0.4",
+ "slash": "^3.0.0",
+ "write-file-atomic": "^4.0.2"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/types": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.13",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
+ "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.0",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ }
+ },
+ "node_modules/@jridgewell/remapping": {
+ "version": "2.3.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
+ "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.5.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
+ "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.31",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
+ "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
+ "node_modules/@middy/core": {
+ "version": "5.5.1",
+ "resolved": "https://registry.npmjs.org/@middy/core/-/core-5.5.1.tgz",
+ "integrity": "sha512-D7q0WXoH2HKyAqw+EN9DuKTp1j+Yr1Aup4m+ALdkyx60fZNGYOFXIx8rKO+ipPC9BBqjbig/zloyIHCZhdK0xg==",
+ "license": "MIT",
+ "dependencies": {
+ "@datastream/core": "0.0.38"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/willfarrell"
+ }
+ },
+ "node_modules/@middy/http-header-normalizer": {
+ "version": "5.5.1",
+ "resolved": "https://registry.npmjs.org/@middy/http-header-normalizer/-/http-header-normalizer-5.5.1.tgz",
+ "integrity": "sha512-5h3EO627MEZqmRksehzXZPhlyzafBbqD8AUF+0N5iySDiInfnEQPebfUzdDz1U5EpNB5Pbj6ryqJAlyxyHw3Kw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/willfarrell"
+ }
+ },
+ "node_modules/@middy/http-router": {
+ "version": "5.5.1",
+ "resolved": "https://registry.npmjs.org/@middy/http-router/-/http-router-5.5.1.tgz",
+ "integrity": "sha512-/S1Uur3BOh4MKV/74rojnFgS3Zm8/jy3zurV7tRzPiHL+0LTIl2x5SHLwi5SYRRMk3mId1LyIeyhSahQrEjYsw==",
+ "license": "MIT",
+ "dependencies": {
+ "@middy/util": "5.5.1"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/willfarrell"
+ }
+ },
+ "node_modules/@middy/util": {
+ "version": "5.5.1",
+ "resolved": "https://registry.npmjs.org/@middy/util/-/util-5.5.1.tgz",
+ "integrity": "sha512-yWvycirftFpXFYt4MXCPjPfM4tQOs4Ib2eyzZEIPOJoEz2cg8mogVNI1TehiCD5O2S1rOPbMduUaXNO6LXiOMA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/willfarrell"
+ }
+ },
+ "node_modules/@nodable/entities": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@nodable/entities/-/entities-2.1.0.tgz",
+ "integrity": "sha512-nyT7T3nbMyBI/lvr6L5TyWbFJAI9FTgVRakNoBqCD+PmID8DzFrrNdLLtHMwMszOtqZa8PAOV24ZqDnQrhQINA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/nodable"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/@sinclair/typebox": {
+ "version": "0.27.10",
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz",
+ "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@sinonjs/commons": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz",
+ "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "type-detect": "4.0.8"
+ }
+ },
+ "node_modules/@sinonjs/fake-timers": {
+ "version": "10.3.0",
+ "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz",
+ "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@sinonjs/commons": "^3.0.0"
+ }
+ },
+ "node_modules/@smithy/config-resolver": {
+ "version": "4.4.15",
+ "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.4.15.tgz",
+ "integrity": "sha512-BJdMBY5YO9iHh+lPLYdHv6LbX+J8IcPCYMl1IJdBt2KDWNHwONHrPVHk3ttYBqJd9wxv84wlbN0f7GlQzcQtNQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/node-config-provider": "^4.3.13",
+ "@smithy/types": "^4.14.0",
+ "@smithy/util-config-provider": "^4.2.2",
+ "@smithy/util-endpoints": "^3.4.0",
+ "@smithy/util-middleware": "^4.2.13",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/core": {
+ "version": "3.23.14",
+ "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.23.14.tgz",
+ "integrity": "sha512-vJ0IhpZxZAkFYOegMKSrxw7ujhhT2pass/1UEcZ4kfl5srTAqtPU5I7MdYQoreVas3204ykCiNhY1o7Xlz6Yyg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/protocol-http": "^5.3.13",
+ "@smithy/types": "^4.14.0",
+ "@smithy/url-parser": "^4.2.13",
+ "@smithy/util-base64": "^4.3.2",
+ "@smithy/util-body-length-browser": "^4.2.2",
+ "@smithy/util-middleware": "^4.2.13",
+ "@smithy/util-stream": "^4.5.22",
+ "@smithy/util-utf8": "^4.2.2",
+ "@smithy/uuid": "^1.1.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/credential-provider-imds": {
+ "version": "4.2.13",
+ "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.2.13.tgz",
+ "integrity": "sha512-wboCPijzf6RJKLOvnjDAiBxGSmSnGXj35o5ZAWKDaHa/cvQ5U3ZJ13D4tMCE8JG4dxVAZFy/P0x/V9CwwdfULQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/node-config-provider": "^4.3.13",
+ "@smithy/property-provider": "^4.2.13",
+ "@smithy/types": "^4.14.0",
+ "@smithy/url-parser": "^4.2.13",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/eventstream-codec": {
+ "version": "4.2.13",
+ "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-4.2.13.tgz",
+ "integrity": "sha512-vYahwBAtRaAcFbOmE9aLr12z7RiHYDSLcnogSdxfm7kKfsNa3wH+NU5r7vTeB5rKvLsWyPjVX8iH94brP7umiQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/crc32": "5.2.0",
+ "@smithy/types": "^4.14.0",
+ "@smithy/util-hex-encoding": "^4.2.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/eventstream-serde-browser": {
+ "version": "4.2.13",
+ "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-4.2.13.tgz",
+ "integrity": "sha512-wwybfcOX0tLqCcBP378TIU9IqrDuZq/tDV48LlZNydMpCnqnYr+hWBAYbRE+rFFf/p7IkDJySM3bgiMKP2ihPg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/eventstream-serde-universal": "^4.2.13",
+ "@smithy/types": "^4.14.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/eventstream-serde-config-resolver": {
+ "version": "4.3.13",
+ "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-4.3.13.tgz",
+ "integrity": "sha512-ied1lO559PtAsMJzg2TKRlctLnEi1PfkNeMMpdwXDImk1zV9uvS/Oxoy/vcy9uv1GKZAjDAB5xT6ziE9fzm5wA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.14.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/eventstream-serde-node": {
+ "version": "4.2.13",
+ "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-4.2.13.tgz",
+ "integrity": "sha512-hFyK+ORJrxAN3RYoaD6+gsGDQjeix8HOEkosoajvXYZ4VeqonM3G4jd9IIRm/sWGXUKmudkY9KdYjzosUqdM8A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/eventstream-serde-universal": "^4.2.13",
+ "@smithy/types": "^4.14.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/eventstream-serde-universal": {
+ "version": "4.2.13",
+ "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-4.2.13.tgz",
+ "integrity": "sha512-kRrq4EKLGeOxhC2CBEhRNcu1KSzNJzYY7RK3S7CxMPgB5dRrv55WqQOtRwQxQLC04xqORFLUgnDlc6xrNUULaA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/eventstream-codec": "^4.2.13",
+ "@smithy/types": "^4.14.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/fetch-http-handler": {
+ "version": "5.3.16",
+ "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.3.16.tgz",
+ "integrity": "sha512-nYDRUIvNd4mFmuXraRWt6w5UsZTNqtj4hXJA/iiOD4tuseIdLP9Lq38teH/SZTcIFCa2f+27o7hYpIsWktJKEQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/protocol-http": "^5.3.13",
+ "@smithy/querystring-builder": "^4.2.13",
+ "@smithy/types": "^4.14.0",
+ "@smithy/util-base64": "^4.3.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/hash-node": {
+ "version": "4.2.13",
+ "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.2.13.tgz",
+ "integrity": "sha512-4/oy9h0jjmY80a2gOIo75iLl8TOPhmtx4E2Hz+PfMjvx/vLtGY4TMU/35WRyH2JHPfT5CVB38u4JRow7gnmzJA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.14.0",
+ "@smithy/util-buffer-from": "^4.2.2",
+ "@smithy/util-utf8": "^4.2.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/invalid-dependency": {
+ "version": "4.2.13",
+ "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.2.13.tgz",
+ "integrity": "sha512-jvC0RB/8BLj2SMIkY0Npl425IdnxZJxInpZJbu563zIRnVjpDMXevU3VMCRSabaLB0kf/eFIOusdGstrLJ8IDg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.14.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/is-array-buffer": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-4.2.2.tgz",
+ "integrity": "sha512-n6rQ4N8Jj4YTQO3YFrlgZuwKodf4zUFs7EJIWH86pSCWBaAtAGBFfCM7Wx6D2bBJ2xqFNxGBSrUWswT3M0VJow==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/md5-js": {
+ "version": "4.2.13",
+ "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-4.2.13.tgz",
+ "integrity": "sha512-cNm7I9NXolFxtS20ojROddOEpSAeI1Obq6pd1Kj5HtHws3s9Fkk8DdHDfQSs5KuxCewZuVK6UqrJnfJmiMzDuQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.14.0",
+ "@smithy/util-utf8": "^4.2.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/middleware-compression": {
+ "version": "4.3.43",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-compression/-/middleware-compression-4.3.43.tgz",
+ "integrity": "sha512-MphcLSNTvBN9G2/ko7NBV2psEfsQRZviXmf612ZwvbSY7dJZNroc2+WPHBf+I9KO2SFl4VFz11rTTueihwWjlQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/core": "^3.23.14",
+ "@smithy/is-array-buffer": "^4.2.2",
+ "@smithy/node-config-provider": "^4.3.13",
+ "@smithy/protocol-http": "^5.3.13",
+ "@smithy/types": "^4.14.0",
+ "@smithy/util-config-provider": "^4.2.2",
+ "@smithy/util-middleware": "^4.2.13",
+ "@smithy/util-utf8": "^4.2.2",
+ "fflate": "0.8.1",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/middleware-content-length": {
+ "version": "4.2.13",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.2.13.tgz",
+ "integrity": "sha512-IPMLm/LE4AZwu6qiE8Rr8vJsWhs9AtOdySRXrOM7xnvclp77Tyh7hMs/FRrMf26kgIe67vFJXXOSmVxS7oKeig==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/protocol-http": "^5.3.13",
+ "@smithy/types": "^4.14.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/middleware-endpoint": {
+ "version": "4.4.29",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.4.29.tgz",
+ "integrity": "sha512-R9Q/58U+qBiSARGWbAbFLczECg/RmysRksX6Q8BaQEpt75I7LI6WGDZnjuC9GXSGKljEbA7N118LhGaMbfrTXw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/core": "^3.23.14",
+ "@smithy/middleware-serde": "^4.2.17",
+ "@smithy/node-config-provider": "^4.3.13",
+ "@smithy/shared-ini-file-loader": "^4.4.8",
+ "@smithy/types": "^4.14.0",
+ "@smithy/url-parser": "^4.2.13",
+ "@smithy/util-middleware": "^4.2.13",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/middleware-retry": {
+ "version": "4.5.1",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.5.1.tgz",
+ "integrity": "sha512-/zY+Gp7Qj2D2hVm3irkCyONER7E9MiX3cUUm/k2ZmhkzZkrPgwVS4aJ5NriZUEN/M0D1hhjrgjUmX04HhRwdWA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/core": "^3.23.14",
+ "@smithy/node-config-provider": "^4.3.13",
+ "@smithy/protocol-http": "^5.3.13",
+ "@smithy/service-error-classification": "^4.2.13",
+ "@smithy/smithy-client": "^4.12.9",
+ "@smithy/types": "^4.14.0",
+ "@smithy/util-middleware": "^4.2.13",
+ "@smithy/util-retry": "^4.3.1",
+ "@smithy/uuid": "^1.1.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/middleware-serde": {
+ "version": "4.2.17",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.2.17.tgz",
+ "integrity": "sha512-0T2mcaM6v9W1xku86Dk0bEW7aEseG6KenFkPK98XNw0ZhOqOiD1MrMsdnQw9QsL3/Oa85T53iSMlm0SZdSuIEQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/core": "^3.23.14",
+ "@smithy/protocol-http": "^5.3.13",
+ "@smithy/types": "^4.14.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/middleware-stack": {
+ "version": "4.2.13",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.2.13.tgz",
+ "integrity": "sha512-g72jN/sGDLyTanrCLH9fhg3oysO3f7tQa6eWWsMyn2BiYNCgjF24n4/I9wff/5XidFvjj9ilipAoQrurTUrLvw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.14.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/node-config-provider": {
+ "version": "4.3.13",
+ "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.3.13.tgz",
+ "integrity": "sha512-iGxQ04DsKXLckbgnX4ipElrOTk+IHgTyu0q0WssZfYhDm9CQWHmu6cOeI5wmWRxpXbBDhIIfXMWz5tPEtcVqbw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/property-provider": "^4.2.13",
+ "@smithy/shared-ini-file-loader": "^4.4.8",
+ "@smithy/types": "^4.14.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/node-http-handler": {
+ "version": "4.5.2",
+ "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.5.2.tgz",
+ "integrity": "sha512-/oD7u8M0oj2ZTFw7GkuuHWpIxtWdLlnyNkbrWcyVYhd5RJNDuczdkb0wfnQICyNFrVPlr8YHOhamjNy3zidhmA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/protocol-http": "^5.3.13",
+ "@smithy/querystring-builder": "^4.2.13",
+ "@smithy/types": "^4.14.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/property-provider": {
+ "version": "4.2.13",
+ "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.2.13.tgz",
+ "integrity": "sha512-bGzUCthxRmezuxkbu9wD33wWg9KX3hJpCXpQ93vVkPrHn9ZW6KNNdY5xAUWNuRCwQ+VyboFuWirG1lZhhkcyRQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.14.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/protocol-http": {
+ "version": "5.3.13",
+ "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.3.13.tgz",
+ "integrity": "sha512-+HsmuJUF4u8POo6s8/a2Yb/AQ5t/YgLovCuHF9oxbocqv+SZ6gd8lC2duBFiCA/vFHoHQhoq7QjqJqZC6xOxxg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.14.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/querystring-builder": {
+ "version": "4.2.13",
+ "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.2.13.tgz",
+ "integrity": "sha512-tG4aOYFCZdPMjbgfhnIQ322H//ojujldp1SrHPHpBSb3NqgUp3dwiUGRJzie87hS1DYwWGqDuPaowoDF+rYCbQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.14.0",
+ "@smithy/util-uri-escape": "^4.2.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/querystring-parser": {
+ "version": "4.2.13",
+ "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.2.13.tgz",
+ "integrity": "sha512-hqW3Q4P+CDzUyQ87GrboGMeD7XYNMOF+CuTwu936UQRB/zeYn3jys8C3w+wMkDfY7CyyyVwZQ5cNFoG0x1pYmA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.14.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/service-error-classification": {
+ "version": "4.2.13",
+ "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.2.13.tgz",
+ "integrity": "sha512-a0s8XZMfOC/qpqq7RCPvJlk93rWFrElH6O++8WJKz0FqnA4Y7fkNi/0mnGgSH1C4x6MFsuBA8VKu4zxFrMe5Vw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.14.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/shared-ini-file-loader": {
+ "version": "4.4.8",
+ "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.4.8.tgz",
+ "integrity": "sha512-VZCZx2bZasxdqxVgEAhREvDSlkatTPnkdWy1+Kiy8w7kYPBosW0V5IeDwzDUMvWBt56zpK658rx1cOBFOYaPaw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.14.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/signature-v4": {
+ "version": "5.3.13",
+ "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.3.13.tgz",
+ "integrity": "sha512-YpYSyM0vMDwKbHD/JA7bVOF6kToVRpa+FM5ateEVRpsTNu564g1muBlkTubXhSKKYXInhpADF46FPyrZcTLpXg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/is-array-buffer": "^4.2.2",
+ "@smithy/protocol-http": "^5.3.13",
+ "@smithy/types": "^4.14.0",
+ "@smithy/util-hex-encoding": "^4.2.2",
+ "@smithy/util-middleware": "^4.2.13",
+ "@smithy/util-uri-escape": "^4.2.2",
+ "@smithy/util-utf8": "^4.2.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/smithy-client": {
+ "version": "4.12.9",
+ "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.12.9.tgz",
+ "integrity": "sha512-ovaLEcTU5olSeHcRXcxV6viaKtpkHZumn6Ps0yn7dRf2rRSfy794vpjOtrWDO0d1auDSvAqxO+lyhERSXQ03EQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/core": "^3.23.14",
+ "@smithy/middleware-endpoint": "^4.4.29",
+ "@smithy/middleware-stack": "^4.2.13",
+ "@smithy/protocol-http": "^5.3.13",
+ "@smithy/types": "^4.14.0",
+ "@smithy/util-stream": "^4.5.22",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/types": {
+ "version": "4.14.1",
+ "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.14.1.tgz",
+ "integrity": "sha512-59b5HtSVrVR/eYNei3BUj3DCPKD/G7EtDDe7OEJE7i7FtQFugYo6MxbotS8mVJkLNVf8gYaAlEBwwtJ9HzhWSg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/url-parser": {
+ "version": "4.2.13",
+ "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.2.13.tgz",
+ "integrity": "sha512-2G03yoboIRZlZze2+PT4GZEjgwQsJjUgn6iTsvxA02bVceHR6vp4Cuk7TUnPFWKF+ffNUk3kj4COwkENS2K3vw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/querystring-parser": "^4.2.13",
+ "@smithy/types": "^4.14.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-base64": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-4.3.2.tgz",
+ "integrity": "sha512-XRH6b0H/5A3SgblmMa5ErXQ2XKhfbQB+Fm/oyLZ2O2kCUrwgg55bU0RekmzAhuwOjA9qdN5VU2BprOvGGUkOOQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/util-buffer-from": "^4.2.2",
+ "@smithy/util-utf8": "^4.2.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-body-length-browser": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-4.2.2.tgz",
+ "integrity": "sha512-JKCrLNOup3OOgmzeaKQwi4ZCTWlYR5H4Gm1r2uTMVBXoemo1UEghk5vtMi1xSu2ymgKVGW631e2fp9/R610ZjQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-body-length-node": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-4.2.3.tgz",
+ "integrity": "sha512-ZkJGvqBzMHVHE7r/hcuCxlTY8pQr1kMtdsVPs7ex4mMU+EAbcXppfo5NmyxMYi2XU49eqaz56j2gsk4dHHPG/g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-buffer-from": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-4.2.2.tgz",
+ "integrity": "sha512-FDXD7cvUoFWwN6vtQfEta540Y/YBe5JneK3SoZg9bThSoOAC/eGeYEua6RkBgKjGa/sz6Y+DuBZj3+YEY21y4Q==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/is-array-buffer": "^4.2.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-config-provider": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-4.2.2.tgz",
+ "integrity": "sha512-dWU03V3XUprJwaUIFVv4iOnS1FC9HnMHDfUrlNDSh4315v0cWyaIErP8KiqGVbf5z+JupoVpNM7ZB3jFiTejvQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-defaults-mode-browser": {
+ "version": "4.3.45",
+ "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.3.45.tgz",
+ "integrity": "sha512-ag9sWc6/nWZAuK3Wm9KlFJUnRkXLrXn33RFjIAmCTFThqLHY+7wCst10BGq56FxslsDrjhSie46c8OULS+BiIw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/property-provider": "^4.2.13",
+ "@smithy/smithy-client": "^4.12.9",
+ "@smithy/types": "^4.14.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-defaults-mode-node": {
+ "version": "4.2.50",
+ "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.2.50.tgz",
+ "integrity": "sha512-xpjncL5XozFA3No7WypTsPU1du0fFS8flIyO+Wh2nhCy7bpEapvU7BR55Bg+wrfw+1cRA+8G8UsTjaxgzrMzXg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/config-resolver": "^4.4.15",
+ "@smithy/credential-provider-imds": "^4.2.13",
+ "@smithy/node-config-provider": "^4.3.13",
+ "@smithy/property-provider": "^4.2.13",
+ "@smithy/smithy-client": "^4.12.9",
+ "@smithy/types": "^4.14.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-endpoints": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.4.0.tgz",
+ "integrity": "sha512-QQHGPKkw6NPcU6TJ1rNEEa201srPtZiX4k61xL163vvs9sTqW/XKz+UEuJ00uvPqoN+5Rs4Ka1UJ7+Mp03IXJw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/node-config-provider": "^4.3.13",
+ "@smithy/types": "^4.14.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-hex-encoding": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-4.2.2.tgz",
+ "integrity": "sha512-Qcz3W5vuHK4sLQdyT93k/rfrUwdJ8/HZ+nMUOyGdpeGA1Wxt65zYwi3oEl9kOM+RswvYq90fzkNDahPS8K0OIg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-middleware": {
+ "version": "4.2.13",
+ "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.2.13.tgz",
+ "integrity": "sha512-GTooyrlmRTqvUen4eK7/K1p6kryF7bnDfq6XsAbIsf2mo51B/utaH+XThY6dKgNCWzMAaH/+OLmqaBuLhLWRow==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.14.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-retry": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.3.1.tgz",
+ "integrity": "sha512-FwmicpgWOkP5kZUjN3y+3JIom8NLGqSAJBeoIgK0rIToI817TEBHCrd0A2qGeKQlgDeP+Jzn4i0H/NLAXGy9uQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/service-error-classification": "^4.2.13",
+ "@smithy/types": "^4.14.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-stream": {
+ "version": "4.5.22",
+ "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.5.22.tgz",
+ "integrity": "sha512-3H8iq/0BfQjUs2/4fbHZ9aG9yNzcuZs24LPkcX1Q7Z+qpqaGM8+qbGmE8zo9m2nCRgamyvS98cHdcWvR6YUsew==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/fetch-http-handler": "^5.3.16",
+ "@smithy/node-http-handler": "^4.5.2",
+ "@smithy/types": "^4.14.0",
+ "@smithy/util-base64": "^4.3.2",
+ "@smithy/util-buffer-from": "^4.2.2",
+ "@smithy/util-hex-encoding": "^4.2.2",
+ "@smithy/util-utf8": "^4.2.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-uri-escape": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-4.2.2.tgz",
+ "integrity": "sha512-2kAStBlvq+lTXHyAZYfJRb/DfS3rsinLiwb+69SstC9Vb0s9vNWkRwpnj918Pfi85mzi42sOqdV72OLxWAISnw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-utf8": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-4.2.2.tgz",
+ "integrity": "sha512-75MeYpjdWRe8M5E3AW0O4Cx3UadweS+cwdXjwYGBW5h/gxxnbeZ877sLPX/ZJA9GVTlL/qG0dXP29JWFCD1Ayw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/util-buffer-from": "^4.2.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-waiter": {
+ "version": "4.2.15",
+ "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-4.2.15.tgz",
+ "integrity": "sha512-oUt9o7n8hBv3BL56sLSneL0XeigZSuem0Hr78JaoK33D9oKieyCvVP8eTSe3j7g2mm/S1DvzxKieG7JEWNJUNg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.14.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/uuid": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@smithy/uuid/-/uuid-1.1.2.tgz",
+ "integrity": "sha512-O/IEdcCUKkubz60tFbGA7ceITTAJsty+lBjNoorP4Z6XRqaFb/OjQjZODophEcuq68nKm6/0r+6/lLQ+XVpk8g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@tsconfig/node10": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz",
+ "integrity": "sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@tsconfig/node12": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
+ "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@tsconfig/node14": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
+ "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@tsconfig/node16": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz",
+ "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/aws-lambda": {
+ "version": "8.10.161",
+ "resolved": "https://registry.npmjs.org/@types/aws-lambda/-/aws-lambda-8.10.161.tgz",
+ "integrity": "sha512-rUYdp+MQwSFocxIOcSsYSF3YYYC/uUpMbCY/mbO21vGqfrEYvNSoPyKYDj6RhXXpPfS0KstW9RwG3qXh9sL7FQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/babel__core": {
+ "version": "7.20.5",
+ "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
+ "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.20.7",
+ "@babel/types": "^7.20.7",
+ "@types/babel__generator": "*",
+ "@types/babel__template": "*",
+ "@types/babel__traverse": "*"
+ }
+ },
+ "node_modules/@types/babel__generator": {
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz",
+ "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__template": {
+ "version": "7.4.4",
+ "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
+ "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__traverse": {
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz",
+ "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.28.2"
+ }
+ },
+ "node_modules/@types/graceful-fs": {
+ "version": "4.1.9",
+ "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz",
+ "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/istanbul-lib-coverage": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
+ "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/istanbul-lib-report": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz",
+ "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/istanbul-lib-coverage": "*"
+ }
+ },
+ "node_modules/@types/istanbul-reports": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz",
+ "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/istanbul-lib-report": "*"
+ }
+ },
+ "node_modules/@types/jest": {
+ "version": "29.5.14",
+ "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.14.tgz",
+ "integrity": "sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "expect": "^29.0.0",
+ "pretty-format": "^29.0.0"
+ }
+ },
+ "node_modules/@types/node": {
+ "version": "20.19.39",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.39.tgz",
+ "integrity": "sha512-orrrD74MBUyK8jOAD/r0+lfa1I2MO6I+vAkmAWzMYbCcgrN4lCrmK52gRFQq/JRxfYPfonkr4b0jcY7Olqdqbw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~6.21.0"
+ }
+ },
+ "node_modules/@types/stack-utils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz",
+ "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/yargs": {
+ "version": "17.0.35",
+ "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz",
+ "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/yargs-parser": "*"
+ }
+ },
+ "node_modules/@types/yargs-parser": {
+ "version": "21.0.3",
+ "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz",
+ "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/abort-controller": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
+ "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
+ "license": "MIT",
+ "dependencies": {
+ "event-target-shim": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=6.5"
+ }
+ },
+ "node_modules/acorn": {
+ "version": "8.16.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz",
+ "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-walk": {
+ "version": "8.3.5",
+ "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.5.tgz",
+ "integrity": "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "acorn": "^8.11.0"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/ansi-escapes": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
+ "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "type-fest": "^0.21.3"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/arg": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
+ "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
+ "node_modules/aws-cdk": {
+ "version": "2.1118.0",
+ "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1118.0.tgz",
+ "integrity": "sha512-Tfd865GRewDTXIbTVtix/l+v8t3rZENvdHcQQZS2wXYVXfHzljULFXe9JKkgZUNDPB1zo9tSBUu8jjiHRm7nWg==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "cdk": "bin/cdk"
+ },
+ "engines": {
+ "node": ">= 18.0.0"
+ }
+ },
+ "node_modules/aws-cdk-lib": {
+ "version": "2.248.0",
+ "resolved": "https://registry.npmjs.org/aws-cdk-lib/-/aws-cdk-lib-2.248.0.tgz",
+ "integrity": "sha512-PGQycx/OdyX+t0o6QUFI1KJAOLoyIVj2WwrN0syrwCi8lYxW2KzldZsW0X+/UN/ALNQwcjSr927ImTpuDOh+bg==",
+ "bundleDependencies": [
+ "@balena/dockerignore",
+ "@aws-cdk/cloud-assembly-api",
+ "case",
+ "fs-extra",
+ "ignore",
+ "jsonschema",
+ "minimatch",
+ "punycode",
+ "semver",
+ "table",
+ "yaml",
+ "mime-types"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-cdk/asset-awscli-v1": "2.2.273",
+ "@aws-cdk/asset-node-proxy-agent-v6": "^2.1.1",
+ "@aws-cdk/cloud-assembly-api": "^2.2.0",
+ "@aws-cdk/cloud-assembly-schema": "^53.0.0",
+ "@balena/dockerignore": "^1.0.2",
+ "case": "1.6.3",
+ "fs-extra": "^11.3.3",
+ "ignore": "^5.3.2",
+ "jsonschema": "^1.5.0",
+ "mime-types": "^2.1.35",
+ "minimatch": "^10.2.3",
+ "punycode": "^2.3.1",
+ "semver": "^7.7.4",
+ "table": "^6.9.0",
+ "yaml": "1.10.3"
+ },
+ "engines": {
+ "node": ">= 20.0.0"
+ },
+ "peerDependencies": {
+ "constructs": "^10.5.0"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/@aws-cdk/cloud-assembly-api": {
+ "version": "2.2.0",
+ "bundleDependencies": [
+ "jsonschema",
+ "semver"
+ ],
+ "inBundle": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "jsonschema": "~1.4.1",
+ "semver": "^7.7.4"
+ },
+ "engines": {
+ "node": ">= 18.0.0"
+ },
+ "peerDependencies": {
+ "@aws-cdk/cloud-assembly-schema": ">=53.0.0"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/@aws-cdk/cloud-assembly-api/node_modules/jsonschema": {
+ "version": "1.4.1",
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/@aws-cdk/cloud-assembly-api/node_modules/semver": {
+ "version": "7.7.4",
+ "inBundle": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/@balena/dockerignore": {
+ "version": "1.0.2",
+ "inBundle": true,
+ "license": "Apache-2.0"
+ },
+ "node_modules/aws-cdk-lib/node_modules/ajv": {
+ "version": "8.18.0",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.3",
+ "fast-uri": "^3.0.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/astral-regex": {
+ "version": "2.0.0",
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/balanced-match": {
+ "version": "4.0.4",
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": "18 || 20 || >=22"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/brace-expansion": {
+ "version": "5.0.5",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^4.0.2"
+ },
+ "engines": {
+ "node": "18 || 20 || >=22"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/case": {
+ "version": "1.6.3",
+ "inBundle": true,
+ "license": "(MIT OR GPL-3.0-or-later)",
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/color-convert": {
+ "version": "2.0.1",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/color-name": {
+ "version": "1.1.4",
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/aws-cdk-lib/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/aws-cdk-lib/node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/aws-cdk-lib/node_modules/fast-uri": {
+ "version": "3.1.0",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fastify"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fastify"
+ }
+ ],
+ "inBundle": true,
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/aws-cdk-lib/node_modules/fs-extra": {
+ "version": "11.3.3",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=14.14"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/graceful-fs": {
+ "version": "4.2.11",
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/aws-cdk-lib/node_modules/ignore": {
+ "version": "5.3.2",
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/json-schema-traverse": {
+ "version": "1.0.0",
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/aws-cdk-lib/node_modules/jsonfile": {
+ "version": "6.2.0",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "universalify": "^2.0.0"
+ },
+ "optionalDependencies": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/jsonschema": {
+ "version": "1.5.0",
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/lodash.truncate": {
+ "version": "4.4.2",
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/aws-cdk-lib/node_modules/mime-db": {
+ "version": "1.52.0",
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/mime-types": {
+ "version": "2.1.35",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/minimatch": {
+ "version": "10.2.5",
+ "inBundle": true,
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "brace-expansion": "^5.0.5"
+ },
+ "engines": {
+ "node": "18 || 20 || >=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/punycode": {
+ "version": "2.3.1",
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/require-from-string": {
+ "version": "2.0.2",
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/semver": {
+ "version": "7.7.4",
+ "inBundle": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/slice-ansi": {
+ "version": "4.0.0",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "astral-regex": "^2.0.0",
+ "is-fullwidth-code-point": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/slice-ansi?sponsor=1"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/string-width": {
+ "version": "4.2.3",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/table": {
+ "version": "6.9.0",
+ "inBundle": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "ajv": "^8.0.1",
+ "lodash.truncate": "^4.4.2",
+ "slice-ansi": "^4.0.0",
+ "string-width": "^4.2.3",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/universalify": {
+ "version": "2.0.1",
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10.0.0"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/yaml": {
+ "version": "1.10.3",
+ "inBundle": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/babel-jest": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz",
+ "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/transform": "^29.7.0",
+ "@types/babel__core": "^7.1.14",
+ "babel-plugin-istanbul": "^6.1.1",
+ "babel-preset-jest": "^29.6.3",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.8.0"
+ }
+ },
+ "node_modules/babel-plugin-istanbul": {
+ "version": "6.1.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz",
+ "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@istanbuljs/load-nyc-config": "^1.0.0",
+ "@istanbuljs/schema": "^0.1.2",
+ "istanbul-lib-instrument": "^5.0.4",
+ "test-exclude": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz",
+ "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@babel/core": "^7.12.3",
+ "@babel/parser": "^7.14.7",
+ "@istanbuljs/schema": "^0.1.2",
+ "istanbul-lib-coverage": "^3.2.0",
+ "semver": "^6.3.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/babel-plugin-jest-hoist": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz",
+ "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/template": "^7.3.3",
+ "@babel/types": "^7.3.3",
+ "@types/babel__core": "^7.1.14",
+ "@types/babel__traverse": "^7.0.6"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/babel-preset-current-node-syntax": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz",
+ "integrity": "sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/plugin-syntax-async-generators": "^7.8.4",
+ "@babel/plugin-syntax-bigint": "^7.8.3",
+ "@babel/plugin-syntax-class-properties": "^7.12.13",
+ "@babel/plugin-syntax-class-static-block": "^7.14.5",
+ "@babel/plugin-syntax-import-attributes": "^7.24.7",
+ "@babel/plugin-syntax-import-meta": "^7.10.4",
+ "@babel/plugin-syntax-json-strings": "^7.8.3",
+ "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4",
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
+ "@babel/plugin-syntax-numeric-separator": "^7.10.4",
+ "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
+ "@babel/plugin-syntax-optional-catch-binding": "^7.8.3",
+ "@babel/plugin-syntax-optional-chaining": "^7.8.3",
+ "@babel/plugin-syntax-private-property-in-object": "^7.14.5",
+ "@babel/plugin-syntax-top-level-await": "^7.14.5"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0 || ^8.0.0-0"
+ }
+ },
+ "node_modules/babel-preset-jest": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz",
+ "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "babel-plugin-jest-hoist": "^29.6.3",
+ "babel-preset-current-node-syntax": "^1.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/base64-js": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/baseline-browser-mapping": {
+ "version": "2.10.19",
+ "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.19.tgz",
+ "integrity": "sha512-qCkNLi2sfBOn8XhZQ0FXsT1Ki/Yo5P90hrkRamVFRS7/KV9hpfA4HkoWNU152+8w0zPjnxo5psx5NL3PSGgv5g==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "baseline-browser-mapping": "dist/cli.cjs"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/bowser": {
+ "version": "2.14.1",
+ "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.14.1.tgz",
+ "integrity": "sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==",
+ "license": "MIT"
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.13",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz",
+ "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fill-range": "^7.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/browserslist": {
+ "version": "4.28.2",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz",
+ "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "baseline-browser-mapping": "^2.10.12",
+ "caniuse-lite": "^1.0.30001782",
+ "electron-to-chromium": "^1.5.328",
+ "node-releases": "^2.0.36",
+ "update-browserslist-db": "^1.2.3"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
+ "node_modules/bs-logger": {
+ "version": "0.2.6",
+ "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz",
+ "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-json-stable-stringify": "2.x"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/bser": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz",
+ "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "node-int64": "^0.4.0"
+ }
+ },
+ "node_modules/buffer": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
+ "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.2.1"
+ }
+ },
+ "node_modules/buffer-from": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
+ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/camelcase": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001788",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001788.tgz",
+ "integrity": "sha512-6q8HFp+lOQtcf7wBK+uEenxymVWkGKkjFpCvw5W25cmMwEDU45p1xQFBQv8JDlMMry7eNxyBaR+qxgmTUZkIRQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "CC-BY-4.0"
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/char-regex": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz",
+ "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/ci-info": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
+ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cjs-module-lexer": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz",
+ "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/cloneable-readable": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-3.0.0.tgz",
+ "integrity": "sha512-Lkfd9IRx1nfiBr7UHNxJSl/x7DOeUfYmxzCkxYJC2tyc/9vKgV75msgLGurGQsak/NvJDHMWcshzEXRlxfvhqg==",
+ "license": "MIT",
+ "dependencies": {
+ "readable-stream": "^4.0.0"
+ }
+ },
+ "node_modules/co": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
+ "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "iojs": ">= 1.0.0",
+ "node": ">= 0.12.0"
+ }
+ },
+ "node_modules/collect-v8-coverage": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.3.tgz",
+ "integrity": "sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/constructs": {
+ "version": "10.6.0",
+ "resolved": "https://registry.npmjs.org/constructs/-/constructs-10.6.0.tgz",
+ "integrity": "sha512-TxHOnBO5zMo/G76ykzGF/wMpEHu257TbWiIxP9K0Yv/+t70UzgBQiTqjkAsWOPC6jW91DzJI0+ehQV6xDRNBuQ==",
+ "dev": true,
+ "license": "Apache-2.0"
+ },
+ "node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/create-jest": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz",
+ "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "chalk": "^4.0.0",
+ "exit": "^0.1.2",
+ "graceful-fs": "^4.2.9",
+ "jest-config": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "prompts": "^2.0.1"
+ },
+ "bin": {
+ "create-jest": "bin/create-jest.js"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/create-require": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
+ "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/dedent": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.2.tgz",
+ "integrity": "sha512-WzMx3mW98SN+zn3hgemf4OzdmyNhhhKz5Ay0pUfQiMQ3e1g+xmTJWp/pKdwKVXhdSkAEGIIzqeuWrL3mV/AXbA==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "babel-plugin-macros": "^3.1.0"
+ },
+ "peerDependenciesMeta": {
+ "babel-plugin-macros": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/deepmerge": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
+ "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/detect-libc": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
+ "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/detect-newline": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz",
+ "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/diff": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz",
+ "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.3.1"
+ }
+ },
+ "node_modules/diff-sequences": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz",
+ "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/electron-to-chromium": {
+ "version": "1.5.339",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.339.tgz",
+ "integrity": "sha512-Is+0BBHJ4NrdpAYiperrmp53pLywG/yV/6lIMTAnhxvzj/Cmn5Q/ogSHC6AKe7X+8kPLxxFk0cs5oc/3j/fxIg==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/emittery": {
+ "version": "0.13.1",
+ "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz",
+ "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/emittery?sponsor=1"
+ }
+ },
+ "node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/error-ex": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz",
+ "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "node_modules/es-errors": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/esbuild": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz",
+ "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.25.12",
+ "@esbuild/android-arm": "0.25.12",
+ "@esbuild/android-arm64": "0.25.12",
+ "@esbuild/android-x64": "0.25.12",
+ "@esbuild/darwin-arm64": "0.25.12",
+ "@esbuild/darwin-x64": "0.25.12",
+ "@esbuild/freebsd-arm64": "0.25.12",
+ "@esbuild/freebsd-x64": "0.25.12",
+ "@esbuild/linux-arm": "0.25.12",
+ "@esbuild/linux-arm64": "0.25.12",
+ "@esbuild/linux-ia32": "0.25.12",
+ "@esbuild/linux-loong64": "0.25.12",
+ "@esbuild/linux-mips64el": "0.25.12",
+ "@esbuild/linux-ppc64": "0.25.12",
+ "@esbuild/linux-riscv64": "0.25.12",
+ "@esbuild/linux-s390x": "0.25.12",
+ "@esbuild/linux-x64": "0.25.12",
+ "@esbuild/netbsd-arm64": "0.25.12",
+ "@esbuild/netbsd-x64": "0.25.12",
+ "@esbuild/openbsd-arm64": "0.25.12",
+ "@esbuild/openbsd-x64": "0.25.12",
+ "@esbuild/openharmony-arm64": "0.25.12",
+ "@esbuild/sunos-x64": "0.25.12",
+ "@esbuild/win32-arm64": "0.25.12",
+ "@esbuild/win32-ia32": "0.25.12",
+ "@esbuild/win32-x64": "0.25.12"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
+ "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "bin": {
+ "esparse": "bin/esparse.js",
+ "esvalidate": "bin/esvalidate.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/event-target-shim": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
+ "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/events": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
+ "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.x"
+ }
+ },
+ "node_modules/execa": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
+ "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cross-spawn": "^7.0.3",
+ "get-stream": "^6.0.0",
+ "human-signals": "^2.1.0",
+ "is-stream": "^2.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^4.0.1",
+ "onetime": "^5.1.2",
+ "signal-exit": "^3.0.3",
+ "strip-final-newline": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/execa?sponsor=1"
+ }
+ },
+ "node_modules/exit": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
+ "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/expect": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz",
+ "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/expect-utils": "^29.7.0",
+ "jest-get-type": "^29.6.3",
+ "jest-matcher-utils": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-util": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-xml-builder": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.2.0.tgz",
+ "integrity": "sha512-00aAWieqff+ZJhsXA4g1g7M8k+7AYoMUUHF+/zFb5U6Uv/P0Vl4QZo84/IcufzYalLuEj9928bXN9PbbFzMF0Q==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/NaturalIntelligence"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "path-expression-matcher": "^1.5.0",
+ "xml-naming": "^0.1.0"
+ }
+ },
+ "node_modules/fast-xml-parser": {
+ "version": "5.7.2",
+ "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.7.2.tgz",
+ "integrity": "sha512-P7oW7tLbYnhOLQk/Gv7cZgzgMPP/XN03K02/Jy6Y/NHzyIAIpxuZIM/YqAkfiXFPxA2CTm7NtCijK9EDu09u2w==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/NaturalIntelligence"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "@nodable/entities": "^2.1.0",
+ "fast-xml-builder": "^1.1.5",
+ "path-expression-matcher": "^1.5.0",
+ "strnum": "^2.2.3"
+ },
+ "bin": {
+ "fxparser": "src/cli/cli.js"
+ }
+ },
+ "node_modules/fb-watchman": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz",
+ "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "bser": "2.1.1"
+ }
+ },
+ "node_modules/fflate": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.1.tgz",
+ "integrity": "sha512-/exOvEuc+/iaUm105QIiOt4LpBdMTWsXxqR0HDF35vx3fmaKzw7354gTilCh5rkzEt8WYyG//ku3h3nRmd7CHQ==",
+ "license": "MIT"
+ },
+ "node_modules/fill-range": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/gensync": {
+ "version": "1.0.0-beta.2",
+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
+ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
+ }
+ },
+ "node_modules/get-package-type": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz",
+ "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/get-stream": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
+ "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/handlebars": {
+ "version": "4.7.9",
+ "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.9.tgz",
+ "integrity": "sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "minimist": "^1.2.5",
+ "neo-async": "^2.6.2",
+ "source-map": "^0.6.1",
+ "wordwrap": "^1.0.0"
+ },
+ "bin": {
+ "handlebars": "bin/handlebars"
+ },
+ "engines": {
+ "node": ">=0.4.7"
+ },
+ "optionalDependencies": {
+ "uglify-js": "^3.1.4"
+ }
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/hasown": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/html-escaper": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
+ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/human-signals": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
+ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=10.17.0"
+ }
+ },
+ "node_modules/ieee754": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/import-local": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz",
+ "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "pkg-dir": "^4.2.0",
+ "resolve-cwd": "^3.0.0"
+ },
+ "bin": {
+ "import-local-fixture": "fixtures/cli.js"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/is-core-module": {
+ "version": "2.16.1",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
+ "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-generator-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz",
+ "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-stream": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
+ "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/istanbul-lib-coverage": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz",
+ "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/istanbul-lib-instrument": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz",
+ "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@babel/core": "^7.23.9",
+ "@babel/parser": "^7.23.9",
+ "@istanbuljs/schema": "^0.1.3",
+ "istanbul-lib-coverage": "^3.2.0",
+ "semver": "^7.5.4"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/istanbul-lib-instrument/node_modules/semver": {
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
+ "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/istanbul-lib-report": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz",
+ "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "istanbul-lib-coverage": "^3.0.0",
+ "make-dir": "^4.0.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/istanbul-lib-source-maps": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz",
+ "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "debug": "^4.1.1",
+ "istanbul-lib-coverage": "^3.0.0",
+ "source-map": "^0.6.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/istanbul-reports": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz",
+ "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "html-escaper": "^2.0.0",
+ "istanbul-lib-report": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/jest": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz",
+ "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/core": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "import-local": "^3.0.2",
+ "jest-cli": "^29.7.0"
+ },
+ "bin": {
+ "jest": "bin/jest.js"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jest-changed-files": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz",
+ "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "execa": "^5.0.0",
+ "jest-util": "^29.7.0",
+ "p-limit": "^3.1.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-circus": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz",
+ "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/environment": "^29.7.0",
+ "@jest/expect": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "co": "^4.6.0",
+ "dedent": "^1.0.0",
+ "is-generator-fn": "^2.0.0",
+ "jest-each": "^29.7.0",
+ "jest-matcher-utils": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-runtime": "^29.7.0",
+ "jest-snapshot": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "p-limit": "^3.1.0",
+ "pretty-format": "^29.7.0",
+ "pure-rand": "^6.0.0",
+ "slash": "^3.0.0",
+ "stack-utils": "^2.0.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-cli": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz",
+ "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/core": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "chalk": "^4.0.0",
+ "create-jest": "^29.7.0",
+ "exit": "^0.1.2",
+ "import-local": "^3.0.2",
+ "jest-config": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-validate": "^29.7.0",
+ "yargs": "^17.3.1"
+ },
+ "bin": {
+ "jest": "bin/jest.js"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jest-config": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz",
+ "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.11.6",
+ "@jest/test-sequencer": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "babel-jest": "^29.7.0",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "deepmerge": "^4.2.2",
+ "glob": "^7.1.3",
+ "graceful-fs": "^4.2.9",
+ "jest-circus": "^29.7.0",
+ "jest-environment-node": "^29.7.0",
+ "jest-get-type": "^29.6.3",
+ "jest-regex-util": "^29.6.3",
+ "jest-resolve": "^29.7.0",
+ "jest-runner": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-validate": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "parse-json": "^5.2.0",
+ "pretty-format": "^29.7.0",
+ "slash": "^3.0.0",
+ "strip-json-comments": "^3.1.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "@types/node": "*",
+ "ts-node": ">=9.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "ts-node": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jest-diff": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz",
+ "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^4.0.0",
+ "diff-sequences": "^29.6.3",
+ "jest-get-type": "^29.6.3",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-docblock": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz",
+ "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "detect-newline": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-each": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz",
+ "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "chalk": "^4.0.0",
+ "jest-get-type": "^29.6.3",
+ "jest-util": "^29.7.0",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-environment-node": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz",
+ "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/environment": "^29.7.0",
+ "@jest/fake-timers": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "jest-mock": "^29.7.0",
+ "jest-util": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-get-type": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz",
+ "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-haste-map": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz",
+ "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@types/graceful-fs": "^4.1.3",
+ "@types/node": "*",
+ "anymatch": "^3.0.3",
+ "fb-watchman": "^2.0.0",
+ "graceful-fs": "^4.2.9",
+ "jest-regex-util": "^29.6.3",
+ "jest-util": "^29.7.0",
+ "jest-worker": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "walker": "^1.0.8"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "^2.3.2"
+ }
+ },
+ "node_modules/jest-leak-detector": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz",
+ "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "jest-get-type": "^29.6.3",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-matcher-utils": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz",
+ "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^4.0.0",
+ "jest-diff": "^29.7.0",
+ "jest-get-type": "^29.6.3",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-message-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz",
+ "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.12.13",
+ "@jest/types": "^29.6.3",
+ "@types/stack-utils": "^2.0.0",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "micromatch": "^4.0.4",
+ "pretty-format": "^29.7.0",
+ "slash": "^3.0.0",
+ "stack-utils": "^2.0.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-mock": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz",
+ "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "jest-util": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-pnp-resolver": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz",
+ "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ },
+ "peerDependencies": {
+ "jest-resolve": "*"
+ },
+ "peerDependenciesMeta": {
+ "jest-resolve": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jest-regex-util": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz",
+ "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-resolve": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz",
+ "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.7.0",
+ "jest-pnp-resolver": "^1.2.2",
+ "jest-util": "^29.7.0",
+ "jest-validate": "^29.7.0",
+ "resolve": "^1.20.0",
+ "resolve.exports": "^2.0.0",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-resolve-dependencies": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz",
+ "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "jest-regex-util": "^29.6.3",
+ "jest-snapshot": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-runner": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz",
+ "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/console": "^29.7.0",
+ "@jest/environment": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "emittery": "^0.13.1",
+ "graceful-fs": "^4.2.9",
+ "jest-docblock": "^29.7.0",
+ "jest-environment-node": "^29.7.0",
+ "jest-haste-map": "^29.7.0",
+ "jest-leak-detector": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-resolve": "^29.7.0",
+ "jest-runtime": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-watcher": "^29.7.0",
+ "jest-worker": "^29.7.0",
+ "p-limit": "^3.1.0",
+ "source-map-support": "0.5.13"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-runtime": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz",
+ "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/environment": "^29.7.0",
+ "@jest/fake-timers": "^29.7.0",
+ "@jest/globals": "^29.7.0",
+ "@jest/source-map": "^29.6.3",
+ "@jest/test-result": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "cjs-module-lexer": "^1.0.0",
+ "collect-v8-coverage": "^1.0.0",
+ "glob": "^7.1.3",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-mock": "^29.7.0",
+ "jest-regex-util": "^29.6.3",
+ "jest-resolve": "^29.7.0",
+ "jest-snapshot": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "slash": "^3.0.0",
+ "strip-bom": "^4.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-snapshot": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz",
+ "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.11.6",
+ "@babel/generator": "^7.7.2",
+ "@babel/plugin-syntax-jsx": "^7.7.2",
+ "@babel/plugin-syntax-typescript": "^7.7.2",
+ "@babel/types": "^7.3.3",
+ "@jest/expect-utils": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "babel-preset-current-node-syntax": "^1.0.0",
+ "chalk": "^4.0.0",
+ "expect": "^29.7.0",
+ "graceful-fs": "^4.2.9",
+ "jest-diff": "^29.7.0",
+ "jest-get-type": "^29.6.3",
+ "jest-matcher-utils": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "natural-compare": "^1.4.0",
+ "pretty-format": "^29.7.0",
+ "semver": "^7.5.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-snapshot/node_modules/semver": {
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
+ "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/jest-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz",
+ "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "graceful-fs": "^4.2.9",
+ "picomatch": "^2.2.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-validate": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz",
+ "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "camelcase": "^6.2.0",
+ "chalk": "^4.0.0",
+ "jest-get-type": "^29.6.3",
+ "leven": "^3.1.0",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-validate/node_modules/camelcase": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/jest-watcher": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz",
+ "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/test-result": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "ansi-escapes": "^4.2.1",
+ "chalk": "^4.0.0",
+ "emittery": "^0.13.1",
+ "jest-util": "^29.7.0",
+ "string-length": "^4.0.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-worker": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz",
+ "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*",
+ "jest-util": "^29.7.0",
+ "merge-stream": "^2.0.0",
+ "supports-color": "^8.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-worker/node_modules/supports-color": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
+ }
+ },
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/js-yaml": {
+ "version": "3.14.2",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz",
+ "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/jsesc": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
+ "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/json-parse-even-better-errors": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
+ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json5": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "json5": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/kleur": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
+ "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/leven": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
+ "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/lines-and-columns": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
+ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/lodash.memoize": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
+ "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "node_modules/make-dir": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz",
+ "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "semver": "^7.5.3"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/make-dir/node_modules/semver": {
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
+ "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/make-error": {
+ "version": "1.3.6",
+ "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
+ "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/makeerror": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz",
+ "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "tmpl": "1.0.5"
+ }
+ },
+ "node_modules/merge-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/metrics-utils": {
+ "resolved": "../metrics-utils",
+ "link": true
+ },
+ "node_modules/micromatch": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
+ "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "braces": "^3.0.3",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/mimic-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
+ "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/minimist": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
+ "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/neo-async": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
+ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/node-int64": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
+ "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/node-releases": {
+ "version": "2.0.37",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.37.tgz",
+ "integrity": "sha512-1h5gKZCF+pO/o3Iqt5Jp7wc9rH3eJJ0+nh/CIoiRwjRxde/hAHyLPXYN4V3CqKAbiZPSeJFSWHmJsbkicta0Eg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npm-run-path": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
+ "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/onetime": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
+ "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mimic-fn": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/p-locate/node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/parse-json": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
+ "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.0.0",
+ "error-ex": "^1.3.1",
+ "json-parse-even-better-errors": "^2.3.0",
+ "lines-and-columns": "^1.1.6"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-expression-matcher": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.5.0.tgz",
+ "integrity": "sha512-cbrerZV+6rvdQrrD+iGMcZFEiiSrbv9Tfdkvnusy6y0x0GKBXREFg/Y65GhIfm0tnLntThhzCnfKwp1WRjeCyQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/NaturalIntelligence"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
+ "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/pirates": {
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz",
+ "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/pkg-dir": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
+ "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "find-up": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/pretty-format": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
+ "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^18.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/pretty-format/node_modules/ansi-styles": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/process": {
+ "version": "0.11.10",
+ "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
+ "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6.0"
+ }
+ },
+ "node_modules/prompts": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
+ "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "kleur": "^3.0.3",
+ "sisteransi": "^1.0.5"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/pure-rand": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz",
+ "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/dubzzz"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fast-check"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/react-is": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
+ "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/readable-stream": {
+ "version": "4.7.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz",
+ "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==",
+ "license": "MIT",
+ "dependencies": {
+ "abort-controller": "^3.0.0",
+ "buffer": "^6.0.3",
+ "events": "^3.3.0",
+ "process": "^0.11.10",
+ "string_decoder": "^1.3.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ }
+ },
+ "node_modules/require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/resolve": {
+ "version": "1.22.12",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz",
+ "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "is-core-module": "^2.16.1",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/resolve-cwd": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz",
+ "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "resolve-from": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/resolve.exports": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz",
+ "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/sharp": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz",
+ "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==",
+ "hasInstallScript": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@img/colour": "^1.0.0",
+ "detect-libc": "^2.1.2",
+ "semver": "^7.7.3"
+ },
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-darwin-arm64": "0.34.5",
+ "@img/sharp-darwin-x64": "0.34.5",
+ "@img/sharp-libvips-darwin-arm64": "1.2.4",
+ "@img/sharp-libvips-darwin-x64": "1.2.4",
+ "@img/sharp-libvips-linux-arm": "1.2.4",
+ "@img/sharp-libvips-linux-arm64": "1.2.4",
+ "@img/sharp-libvips-linux-ppc64": "1.2.4",
+ "@img/sharp-libvips-linux-riscv64": "1.2.4",
+ "@img/sharp-libvips-linux-s390x": "1.2.4",
+ "@img/sharp-libvips-linux-x64": "1.2.4",
+ "@img/sharp-libvips-linuxmusl-arm64": "1.2.4",
+ "@img/sharp-libvips-linuxmusl-x64": "1.2.4",
+ "@img/sharp-linux-arm": "0.34.5",
+ "@img/sharp-linux-arm64": "0.34.5",
+ "@img/sharp-linux-ppc64": "0.34.5",
+ "@img/sharp-linux-riscv64": "0.34.5",
+ "@img/sharp-linux-s390x": "0.34.5",
+ "@img/sharp-linux-x64": "0.34.5",
+ "@img/sharp-linuxmusl-arm64": "0.34.5",
+ "@img/sharp-linuxmusl-x64": "0.34.5",
+ "@img/sharp-wasm32": "0.34.5",
+ "@img/sharp-win32-arm64": "0.34.5",
+ "@img/sharp-win32-ia32": "0.34.5",
+ "@img/sharp-win32-x64": "0.34.5"
+ }
+ },
+ "node_modules/sharp/node_modules/semver": {
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
+ "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/sisteransi": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
+ "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/source-map-support": {
+ "version": "0.5.13",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz",
+ "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "node_modules/sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
+ "dev": true,
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/stack-utils": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz",
+ "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "escape-string-regexp": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/string_decoder": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "~5.2.0"
+ }
+ },
+ "node_modules/string-length": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz",
+ "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "char-regex": "^1.0.2",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-bom": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz",
+ "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-final-newline": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
+ "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/strnum": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.3.0.tgz",
+ "integrity": "sha512-ums3KNd42PGyx5xaoVTO1mjU1bH3NpY4vsrVlnv9PNGqQj8wd7rJ6nEypLrJ7z5vxK5RP0yMLo6J/Gsm62DI5Q==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/NaturalIntelligence"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/test-exclude": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz",
+ "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "@istanbuljs/schema": "^0.1.2",
+ "glob": "^7.1.4",
+ "minimatch": "^3.0.4"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/tmpl": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
+ "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==",
+ "dev": true,
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/ts-jest": {
+ "version": "29.4.9",
+ "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.9.tgz",
+ "integrity": "sha512-LTb9496gYPMCqjeDLdPrKuXtncudeV1yRZnF4Wo5l3SFi0RYEnYRNgMrFIdg+FHvfzjCyQk1cLncWVqiSX+EvQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "bs-logger": "^0.2.6",
+ "fast-json-stable-stringify": "^2.1.0",
+ "handlebars": "^4.7.9",
+ "json5": "^2.2.3",
+ "lodash.memoize": "^4.1.2",
+ "make-error": "^1.3.6",
+ "semver": "^7.7.4",
+ "type-fest": "^4.41.0",
+ "yargs-parser": "^21.1.1"
+ },
+ "bin": {
+ "ts-jest": "cli.js"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": ">=7.0.0-beta.0 <8",
+ "@jest/transform": "^29.0.0 || ^30.0.0",
+ "@jest/types": "^29.0.0 || ^30.0.0",
+ "babel-jest": "^29.0.0 || ^30.0.0",
+ "jest": "^29.0.0 || ^30.0.0",
+ "jest-util": "^29.0.0 || ^30.0.0",
+ "typescript": ">=4.3 <7"
+ },
+ "peerDependenciesMeta": {
+ "@babel/core": {
+ "optional": true
+ },
+ "@jest/transform": {
+ "optional": true
+ },
+ "@jest/types": {
+ "optional": true
+ },
+ "babel-jest": {
+ "optional": true
+ },
+ "esbuild": {
+ "optional": true
+ },
+ "jest-util": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/ts-jest/node_modules/semver": {
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
+ "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/ts-jest/node_modules/type-fest": {
+ "version": "4.41.0",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz",
+ "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==",
+ "dev": true,
+ "license": "(MIT OR CC0-1.0)",
+ "engines": {
+ "node": ">=16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ts-node": {
+ "version": "10.9.2",
+ "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
+ "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@cspotcode/source-map-support": "^0.8.0",
+ "@tsconfig/node10": "^1.0.7",
+ "@tsconfig/node12": "^1.0.7",
+ "@tsconfig/node14": "^1.0.0",
+ "@tsconfig/node16": "^1.0.2",
+ "acorn": "^8.4.1",
+ "acorn-walk": "^8.1.1",
+ "arg": "^4.1.0",
+ "create-require": "^1.1.0",
+ "diff": "^4.0.1",
+ "make-error": "^1.1.1",
+ "v8-compile-cache-lib": "^3.0.1",
+ "yn": "3.1.1"
+ },
+ "bin": {
+ "ts-node": "dist/bin.js",
+ "ts-node-cwd": "dist/bin-cwd.js",
+ "ts-node-esm": "dist/bin-esm.js",
+ "ts-node-script": "dist/bin-script.js",
+ "ts-node-transpile-only": "dist/bin-transpile.js",
+ "ts-script": "dist/bin-script-deprecated.js"
+ },
+ "peerDependencies": {
+ "@swc/core": ">=1.2.50",
+ "@swc/wasm": ">=1.2.50",
+ "@types/node": "*",
+ "typescript": ">=2.7"
+ },
+ "peerDependenciesMeta": {
+ "@swc/core": {
+ "optional": true
+ },
+ "@swc/wasm": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
+ "license": "0BSD"
+ },
+ "node_modules/type-detect": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
+ "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/type-fest": {
+ "version": "0.21.3",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
+ "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
+ "dev": true,
+ "license": "(MIT OR CC0-1.0)",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "5.9.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
+ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/uglify-js": {
+ "version": "3.19.3",
+ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz",
+ "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "optional": true,
+ "bin": {
+ "uglifyjs": "bin/uglifyjs"
+ },
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/undici-types": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
+ "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/update-browserslist-db": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz",
+ "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "escalade": "^3.2.0",
+ "picocolors": "^1.1.1"
+ },
+ "bin": {
+ "update-browserslist-db": "cli.js"
+ },
+ "peerDependencies": {
+ "browserslist": ">= 4.21.0"
+ }
+ },
+ "node_modules/v8-compile-cache-lib": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
+ "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/v8-to-istanbul": {
+ "version": "9.3.0",
+ "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz",
+ "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "@jridgewell/trace-mapping": "^0.3.12",
+ "@types/istanbul-lib-coverage": "^2.0.1",
+ "convert-source-map": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10.12.0"
+ }
+ },
+ "node_modules/walker": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz",
+ "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "makeerror": "1.0.12"
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/wordwrap": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
+ "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/write-file-atomic": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz",
+ "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "imurmurhash": "^0.1.4",
+ "signal-exit": "^3.0.7"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/xml-naming": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/xml-naming/-/xml-naming-0.1.0.tgz",
+ "integrity": "sha512-k8KO9hrMyNk6tUWqUfkTEZbezRRpONVOzUTnc97VnCvyj6Tf9lyUR9EDAIeiVLv56jsMcoXEwjW8Kv5yPY52lw==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/NaturalIntelligence"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
+ "node_modules/y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yallist": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/yargs": {
+ "version": "17.7.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yn": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
+ "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ }
+ }
+}
diff --git a/source/constructs/package.json b/source/constructs/package.json
index 546f8e93d..094e43773 100644
--- a/source/constructs/package.json
+++ b/source/constructs/package.json
@@ -1,37 +1,66 @@
{
"name": "constructs",
- "description": "Serverless Image Handler Constructs",
- "version": "5.2.0",
+ "description": "Dynamic Image Transformation for Amazon CloudFront Constructs",
"license": "Apache-2.0",
+ "author": {
+ "name": "Amazon Web Services",
+ "url": "https://aws.amazon.com/solutions"
+ },
"bin": {
"constructs": "bin/constructs.js"
},
"scripts": {
+ "cdk": "cdk",
+ "clean:install": "rm -rf node_modules/ cdk.out/ coverage/ && npm ci && cd ../ && npm run install:dependencies && cd metrics-utils && rm -rf node_modules/aws-cdk-lib && ln -s ../../constructs/node_modules/aws-cdk-lib node_modules/aws-cdk-lib",
+ "cdk:synth": "npm run clean:install && overrideWarningsEnabled=false npx cdk synth --asset-metadata false --path-metadata false --json false",
+ "pretest": "npm run clean:install",
"build": "tsc",
"watch": "tsc -w",
- "test": "export BUCKET_NAME=TEST && export SOLUTION_NAME=serverless-image-handler && export VERSION=TEST_VERSION && jest",
- "cdk": "cdk"
+ "test": "overrideWarningsEnabled=false jest --coverage",
+ "e2e-test": "TEST_TYPE=e2e jest --coverage"
},
"devDependencies": {
- "@aws-cdk/assert": "1.64.1",
- "@types/jest": "^26.0.14",
- "@types/node": "^14.11.2",
- "aws-cdk": "1.64.1",
- "jest": "^26.4.2",
- "ts-jest": "^26.4.0",
- "ts-node": "^9.0.0",
- "typescript": "~4.0.3"
+ "@aws-sdk/client-cloudformation": "^3.993.0",
+ "@aws-solutions-constructs/aws-alb-fargate": "^2.86.0",
+ "@aws-solutions-constructs/aws-apigateway-lambda": "2.51.0",
+ "@aws-solutions-constructs/aws-cloudfront-apigateway-lambda": "2.51.0",
+ "@aws-solutions-constructs/aws-cloudfront-s3": "2.51.0",
+ "@aws-solutions-constructs/aws-lambda-dynamodb": "^2.86.0",
+ "@aws-solutions-constructs/aws-openapigateway-lambda": "^2.86.0",
+ "@aws-solutions-constructs/core": "2.51.0",
+ "@types/aws-lambda": "^8.10.156",
+ "@types/jest": "^29.5.6",
+ "@types/node": "^20.10.4",
+ "aws-cdk": "^2.1018.0",
+ "aws-cdk-lib": "2.248.0",
+ "constructs": "^10.3.0",
+ "esbuild": "^0.25.0",
+ "jest": "^29.7.0",
+ "ts-jest": "^29.1.1",
+ "ts-node": "^10.9.2",
+ "typescript": "^5.3.3"
},
"dependencies": {
- "@aws-cdk/aws-apigateway": "1.64.1",
- "@aws-cdk/aws-cloudfront": "1.64.1",
- "@aws-cdk/aws-iam": "1.64.1",
- "@aws-cdk/aws-lambda": "1.64.1",
- "@aws-cdk/aws-s3": "1.64.1",
- "@aws-cdk/core": "1.64.1",
- "@aws-solutions-constructs/aws-apigateway-lambda": "1.64.1",
- "@aws-solutions-constructs/aws-cloudfront-apigateway-lambda": "1.64.1",
- "@aws-solutions-constructs/aws-cloudfront-s3": "1.64.1",
- "@aws-solutions-constructs/core": "1.64.1"
+ "@aws-lambda-powertools/logger": "^2.27.0",
+ "@aws-sdk/client-cloudfront": "^3.993.0",
+ "@aws-sdk/client-cloudwatch": "^3.993.0",
+ "@aws-sdk/client-cloudwatch-logs": "^3.993.0",
+ "@aws-sdk/client-sqs": "^3.993.0",
+ "@middy/core": "^5.0.0",
+ "@middy/http-header-normalizer": "^5.0.0",
+ "@middy/http-router": "^5.0.0",
+ "@smithy/core": "^3.8.0",
+ "metrics-utils": "file:../metrics-utils",
+ "sharp": "^0.34.5"
+ },
+ "overrides": {
+ "minimatch@3": "3.1.5",
+ "flatted": "3.4.2",
+ "handlebars": "4.7.9",
+ "picomatch@2": "2.3.2",
+ "picomatch@4": "4.0.4",
+ "brace-expansion@1": "1.1.13",
+ "brace-expansion@5": "5.0.5",
+ "yaml@1": "1.10.3"
}
}
diff --git a/source/constructs/test/__snapshots__/constructs.test.ts.snap b/source/constructs/test/__snapshots__/constructs.test.ts.snap
new file mode 100644
index 000000000..de813fdd9
--- /dev/null
+++ b/source/constructs/test/__snapshots__/constructs.test.ts.snap
@@ -0,0 +1,4551 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`ServerlessImageHandlerStack Dynamic Image Transformation for Amazon CloudFront Stack Snapshot 1`] = `
+{
+ "Conditions": {
+ "BackEndDeployAPIGDistributionF4E75280": {
+ "Fn::And": [
+ {
+ "Condition": "CommonResourcesDisableS3ObjectLambdaCondition017AC33C",
+ },
+ {
+ "Fn::Not": [
+ {
+ "Condition": "CommonResourcesUseExistingCloudFrontDistributionConditionEBC48184",
+ },
+ ],
+ },
+ ],
+ },
+ "BackEndDeployS3OLDistribution869FCC7C": {
+ "Fn::And": [
+ {
+ "Condition": "CommonResourcesEnableS3ObjectLambdaConditionF2C07DCD",
+ },
+ {
+ "Fn::Not": [
+ {
+ "Condition": "CommonResourcesUseExistingCloudFrontDistributionConditionEBC48184",
+ },
+ ],
+ },
+ ],
+ },
+ "BackEndShortLogRetentionCondition72EA1A33": {
+ "Fn::Or": [
+ {
+ "Fn::Equals": [
+ {
+ "Ref": "LogRetentionPeriodParameter",
+ },
+ "1",
+ ],
+ },
+ {
+ "Fn::Equals": [
+ {
+ "Ref": "LogRetentionPeriodParameter",
+ },
+ "3",
+ ],
+ },
+ {
+ "Fn::Equals": [
+ {
+ "Ref": "LogRetentionPeriodParameter",
+ },
+ "5",
+ ],
+ },
+ ],
+ },
+ "CommonResourcesAutoWebPCondition7119C768": {
+ "Fn::Equals": [
+ {
+ "Ref": "AutoWebPParameter",
+ },
+ "Yes",
+ ],
+ },
+ "CommonResourcesDeployDemoUICondition308D3B09": {
+ "Fn::Equals": [
+ {
+ "Ref": "DeployDemoUIParameter",
+ },
+ "Yes",
+ ],
+ },
+ "CommonResourcesDisableS3ObjectLambdaCondition017AC33C": {
+ "Fn::Not": [
+ {
+ "Fn::Equals": [
+ {
+ "Ref": "EnableS3ObjectLambdaParameter",
+ },
+ "Yes",
+ ],
+ },
+ ],
+ },
+ "CommonResourcesEnableCorsConditionA0615348": {
+ "Fn::Equals": [
+ {
+ "Ref": "CorsEnabledParameter",
+ },
+ "Yes",
+ ],
+ },
+ "CommonResourcesEnableDefaultFallbackImageConditionD1A10983": {
+ "Fn::Equals": [
+ {
+ "Ref": "EnableDefaultFallbackImageParameter",
+ },
+ "Yes",
+ ],
+ },
+ "CommonResourcesEnableOriginShieldConditionCEE94847": {
+ "Fn::Not": [
+ {
+ "Fn::Equals": [
+ {
+ "Ref": "OriginShieldRegionParameter",
+ },
+ "Disabled",
+ ],
+ },
+ ],
+ },
+ "CommonResourcesEnableS3ObjectLambdaConditionF2C07DCD": {
+ "Fn::Equals": [
+ {
+ "Ref": "EnableS3ObjectLambdaParameter",
+ },
+ "Yes",
+ ],
+ },
+ "CommonResourcesEnableSignatureCondition909DC7A1": {
+ "Fn::Equals": [
+ {
+ "Ref": "EnableSignatureParameter",
+ },
+ "Yes",
+ ],
+ },
+ "CommonResourcesIsLogRetentionPeriodInfinite129C8A82": {
+ "Fn::Equals": [
+ {
+ "Ref": "LogRetentionPeriodParameter",
+ },
+ "Infinite",
+ ],
+ },
+ "CommonResourcesUseExistingCloudFrontDistributionConditionEBC48184": {
+ "Fn::Equals": [
+ {
+ "Ref": "UseExistingCloudFrontDistributionParameter",
+ },
+ "Yes",
+ ],
+ },
+ "DeployCloudWatchDashboard": {
+ "Fn::Equals": [
+ {
+ "Fn::FindInMap": [
+ "Solution",
+ "Config",
+ "DeployCloudWatchDashboard",
+ ],
+ },
+ "Yes",
+ ],
+ },
+ "SendAnonymousStatistics": {
+ "Fn::Equals": [
+ {
+ "Fn::FindInMap": [
+ "Solution",
+ "Config",
+ "AnonymousUsage",
+ ],
+ },
+ "Yes",
+ ],
+ },
+ },
+ "Mappings": {
+ "Solution": {
+ "Config": {
+ "AnonymousUsage": "Yes",
+ "DeployCloudWatchDashboard": "Yes",
+ "SharpSizeLimit": "",
+ "SolutionId": "S0ABC",
+ "Version": "v7.0.1",
+ },
+ },
+ },
+ "Metadata": {
+ "AWS::CloudFormation::Interface": {
+ "ParameterGroups": [
+ {
+ "Label": {
+ "default": "S3 Object Lambda",
+ },
+ "Parameters": [
+ "EnableS3ObjectLambdaParameter",
+ ],
+ },
+ {
+ "Label": {
+ "default": "CORS Options",
+ },
+ "Parameters": [
+ "CorsEnabledParameter",
+ "CorsOriginParameter",
+ ],
+ },
+ {
+ "Label": {
+ "default": "Image Sources",
+ },
+ "Parameters": [
+ "SourceBucketsParameter",
+ ],
+ },
+ {
+ "Label": {
+ "default": "Demo UI",
+ },
+ "Parameters": [
+ "DeployDemoUIParameter",
+ ],
+ },
+ {
+ "Label": {
+ "default": "Event Logging",
+ },
+ "Parameters": [
+ "LogRetentionPeriodParameter",
+ ],
+ },
+ {
+ "Label": {
+ "default": "Image URL Signature (Note: Enabling signature is not compatible with previous image URLs, which could result in broken image links. Please refer to the implementation guide for details: https://docs.aws.amazon.com/solutions/latest/serverless-image-handler/architecture-details.html#image-url-signature)",
+ },
+ "Parameters": [
+ "EnableSignatureParameter",
+ "SecretsManagerSecretParameter",
+ "SecretsManagerKeyParameter",
+ ],
+ },
+ {
+ "Label": {
+ "default": "Default Fallback Image (Note: Enabling default fallback image returns the default fallback image instead of JSON object when error happens. Please refer to the implementation guide for details: https://docs.aws.amazon.com/solutions/latest/serverless-image-handler/architecture-details.html#default-fallback-image)",
+ },
+ "Parameters": [
+ "EnableDefaultFallbackImageParameter",
+ "FallbackImageS3BucketParameter",
+ "FallbackImageS3KeyParameter",
+ ],
+ },
+ {
+ "Label": {
+ "default": "Auto WebP",
+ },
+ "Parameters": [
+ "AutoWebPParameter",
+ ],
+ },
+ {
+ "Label": {
+ "default": "CloudFront",
+ },
+ "Parameters": [
+ "OriginShieldRegionParameter",
+ "CloudFrontPriceClassParameter",
+ "UseExistingCloudFrontDistributionParameter",
+ "ExistingCloudFrontDistributionIdParameter",
+ ],
+ },
+ ],
+ "ParameterLabels": {
+ "AutoWebPParameter": {
+ "default": "AutoWebP",
+ },
+ "CloudFrontPriceClassParameter": {
+ "default": "CloudFront PriceClass",
+ },
+ "CorsEnabledParameter": {
+ "default": "CORS Enabled",
+ },
+ "CorsOriginParameter": {
+ "default": "CORS Origin",
+ },
+ "DeployDemoUIParameter": {
+ "default": "Deploy Demo UI",
+ },
+ "EnableDefaultFallbackImageParameter": {
+ "default": "Enable Default Fallback Image",
+ },
+ "EnableS3ObjectLambdaParameter": {
+ "default": "Enable S3 Object Lambda (DEPRECATED)",
+ },
+ "EnableSignatureParameter": {
+ "default": "Enable Signature",
+ },
+ "ExistingCloudFrontDistributionIdParameter": {
+ "default": "Existing CloudFront Distribution Id",
+ },
+ "FallbackImageS3BucketParameter": {
+ "default": "Fallback Image S3 Bucket",
+ },
+ "FallbackImageS3KeyParameter": {
+ "default": "Fallback Image S3 Key",
+ },
+ "LogRetentionPeriodParameter": {
+ "default": "Log Retention Period",
+ },
+ "OriginShieldRegionParameter": {
+ "default": "Origin Shield Region",
+ },
+ "SecretsManagerKeyParameter": {
+ "default": "SecretsManager Key",
+ },
+ "SecretsManagerSecretParameter": {
+ "default": "SecretsManager Secret",
+ },
+ "SourceBucketsParameter": {
+ "default": "Source Buckets",
+ },
+ "UseExistingCloudFrontDistributionParameter": {
+ "default": "Use Existing CloudFront Distribution",
+ },
+ },
+ },
+ },
+ "Outputs": {
+ "ApiEndpoint": {
+ "Description": "Link to API endpoint for sending image requests to.",
+ "Value": {
+ "Fn::If": [
+ "CommonResourcesUseExistingCloudFrontDistributionConditionEBC48184",
+ {
+ "Fn::Join": [
+ "",
+ [
+ "https://",
+ {
+ "Fn::GetAtt": [
+ "CommonResourcesCustomResourcesCustomResourceValidateExistingDistribution34A6673C",
+ "DistributionDomainName",
+ ],
+ },
+ ],
+ ],
+ },
+ {
+ "Fn::If": [
+ "CommonResourcesDisableS3ObjectLambdaCondition017AC33C",
+ {
+ "Fn::Join": [
+ "",
+ [
+ "https://",
+ {
+ "Fn::If": [
+ "CommonResourcesUseExistingCloudFrontDistributionConditionEBC48184",
+ "",
+ {
+ "Fn::GetAtt": [
+ "BackEndImageHandlerCloudFrontApiGatewayLambdaCloudFrontToApiGatewayCloudFrontDistribution03AA31B2",
+ "DomainName",
+ ],
+ },
+ ],
+ },
+ ],
+ ],
+ },
+ {
+ "Fn::Join": [
+ "",
+ [
+ "https://",
+ {
+ "Fn::If": [
+ "CommonResourcesUseExistingCloudFrontDistributionConditionEBC48184",
+ "",
+ {
+ "Fn::GetAtt": [
+ "BackEndImageHandlerCloudFrontDistributionB5464C90",
+ "DomainName",
+ ],
+ },
+ ],
+ },
+ ],
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ },
+ "CloudFrontDashboard": {
+ "Condition": "DeployCloudWatchDashboard",
+ "Description": "CloudFront metrics dashboard for the distribution.",
+ "Value": {
+ "Fn::Join": [
+ "",
+ [
+ "https://console.aws.amazon.com/cloudwatch/home?#dashboards/dashboard/",
+ {
+ "Ref": "OperationalInsightsDashboard00409C46",
+ },
+ ],
+ ],
+ },
+ },
+ "CloudFrontLoggingBucket": {
+ "Description": "Amazon S3 bucket for storing CloudFront access logs.",
+ "Value": {
+ "Fn::GetAtt": [
+ "CommonResourcesCustomResourcesLogBucketCustomResource2445A3AB",
+ "BucketName",
+ ],
+ },
+ },
+ "CorsEnabled": {
+ "Description": "Indicates whether Cross-Origin Resource Sharing (CORS) has been enabled for the image handler API.",
+ "Value": {
+ "Ref": "CorsEnabledParameter",
+ },
+ },
+ "CorsOrigin": {
+ "Condition": "CommonResourcesEnableCorsConditionA0615348",
+ "Description": "Origin value returned in the Access-Control-Allow-Origin header of image handler API responses.",
+ "Value": {
+ "Ref": "CorsOriginParameter",
+ },
+ },
+ "DemoUrl": {
+ "Condition": "CommonResourcesDeployDemoUICondition308D3B09",
+ "Description": "Link to the demo user interface for the solution.",
+ "Value": {
+ "Fn::Join": [
+ "",
+ [
+ "https://",
+ {
+ "Fn::GetAtt": [
+ "FrontEndDistributionToS3CloudFrontDistribution15FE13D0",
+ "DomainName",
+ ],
+ },
+ "/index.html",
+ ],
+ ],
+ },
+ },
+ "LogRetentionPeriod": {
+ "Description": "Number of days for event logs from Lambda to be retained in CloudWatch.",
+ "Value": {
+ "Ref": "LogRetentionPeriodParameter",
+ },
+ },
+ "SourceBuckets": {
+ "Description": "Amazon S3 bucket location containing original image files.",
+ "Value": {
+ "Ref": "SourceBucketsParameter",
+ },
+ },
+ },
+ "Parameters": {
+ "AutoWebPParameter": {
+ "AllowedValues": [
+ "Yes",
+ "No",
+ ],
+ "Default": "No",
+ "Description": "Would you like to enable automatic formatting to WebP images when accept headers include "image/webp"? Select 'Yes' if so.",
+ "Type": "String",
+ },
+ "BootstrapVersion": {
+ "Default": "/cdk-bootstrap/hnb659fds/version",
+ "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]",
+ "Type": "AWS::SSM::Parameter::Value",
+ },
+ "CloudFrontPriceClassParameter": {
+ "AllowedValues": [
+ "PriceClass_All",
+ "PriceClass_200",
+ "PriceClass_100",
+ ],
+ "Default": "PriceClass_All",
+ "Description": "The AWS CloudFront price class to use. Lower price classes will avoid high cost edge locations, reducing cost at the expense of possibly increasing request latency. For more information see: https://docs.aws.amazon.com/cdk/api/v2/python/aws_cdk.aws_cloudfront/PriceClass.html",
+ "Type": "String",
+ },
+ "CorsEnabledParameter": {
+ "AllowedValues": [
+ "Yes",
+ "No",
+ ],
+ "Default": "No",
+ "Description": "Would you like to enable Cross-Origin Resource Sharing (CORS) for the image handler API? Select 'Yes' if so.",
+ "Type": "String",
+ },
+ "CorsOriginParameter": {
+ "Default": "*",
+ "Description": "If you selected 'Yes' above, please specify an origin value here. A wildcard (*) value will support any origin. We recommend specifying an origin (i.e. https://example.domain) to restrict cross-site access to your API.",
+ "Type": "String",
+ },
+ "DeployDemoUIParameter": {
+ "AllowedValues": [
+ "Yes",
+ "No",
+ ],
+ "Default": "Yes",
+ "Description": "Would you like to deploy a demo UI to explore the features and capabilities of this solution? This will create an additional Amazon S3 bucket and Amazon CloudFront distribution in your account.",
+ "Type": "String",
+ },
+ "EnableDefaultFallbackImageParameter": {
+ "AllowedValues": [
+ "Yes",
+ "No",
+ ],
+ "Default": "No",
+ "Description": "Would you like to enable the default fallback image? If so, select 'Yes' and provide FallbackImageS3Bucket and FallbackImageS3Key values.",
+ "Type": "String",
+ },
+ "EnableS3ObjectLambdaParameter": {
+ "AllowedValues": [
+ "Yes",
+ "No",
+ ],
+ "Default": "No",
+ "Description": "Deprecated: This option has been deprecated. Amazon S3 Object Lambda will no longer be open to new customers starting on November 7, 2025. If you were not an existing user of S3 Object Lambda before November 7, 2025, select 'No'. For more information, please visit https://docs.aws.amazon.com/AmazonS3/latest/userguide/amazons3-ol-change.html. **Important: Modifying this value after initial template deployment will delete the existing CloudFront Distribution and create a new one, providing a new domain name and clearing the cache**.",
+ "Type": "String",
+ },
+ "EnableSignatureParameter": {
+ "AllowedValues": [
+ "Yes",
+ "No",
+ ],
+ "Default": "No",
+ "Description": "Would you like to enable the signature? If so, select 'Yes' and provide SecretsManagerSecret and SecretsManagerKey values.",
+ "Type": "String",
+ },
+ "ExistingCloudFrontDistributionIdParameter": {
+ "AllowedPattern": "^$|^E[A-Z0-9]{8,}$",
+ "Default": "",
+ "Description": "The ID of the existing CloudFront distribution. This parameter is required if 'Use Existing CloudFront Distribution' is set to 'Yes'.",
+ "Type": "String",
+ },
+ "FallbackImageS3BucketParameter": {
+ "Default": "",
+ "Description": "The name of the Amazon S3 bucket which contains the default fallback image. e.g. my-fallback-image-bucket",
+ "Type": "String",
+ },
+ "FallbackImageS3KeyParameter": {
+ "Default": "",
+ "Description": "The name of the default fallback image object key including prefix. e.g. prefix/image.jpg",
+ "Type": "String",
+ },
+ "LogRetentionPeriodParameter": {
+ "AllowedValues": [
+ "1",
+ "3",
+ "5",
+ "7",
+ "14",
+ "30",
+ "60",
+ "90",
+ "120",
+ "150",
+ "180",
+ "365",
+ "400",
+ "545",
+ "731",
+ "1827",
+ "3653",
+ "Infinite",
+ ],
+ "Default": "180",
+ "Description": "This solution automatically logs events to Amazon CloudWatch. Select the amount of time for CloudWatch logs from this solution to be retained (in days).",
+ "Type": "String",
+ },
+ "OriginShieldRegionParameter": {
+ "AllowedValues": [
+ "Disabled",
+ "us-east-1",
+ "us-east-2",
+ "us-west-2",
+ "ap-south-1",
+ "ap-northeast-1",
+ "ap-southeast-1",
+ "ap-southeast-2",
+ "ap-northeast-1",
+ "eu-central-1",
+ "eu-west-1",
+ "eu-west-2",
+ "sa-east-1",
+ ],
+ "Default": "Disabled",
+ "Description": "Enabling Origin Shield may see reduced latency and increased cache hit ratios if your requests often come from many regions. If a region is selected, Origin Shield will be enabled and the Origin Shield caching layer will be set up in that region. For information on choosing a region, see https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/origin-shield.html#choose-origin-shield-region",
+ "Type": "String",
+ },
+ "SecretsManagerKeyParameter": {
+ "Default": "",
+ "Description": "The name of AWS Secrets Manager secret key. You need to create secret key with this key name. The secret value would be used to check signature.",
+ "Type": "String",
+ },
+ "SecretsManagerSecretParameter": {
+ "Default": "",
+ "Description": "The name of AWS Secrets Manager secret. You need to create your secret under this name.",
+ "Type": "String",
+ },
+ "SourceBucketsParameter": {
+ "AllowedPattern": "^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9](?:\\s*,\\s*[a-z0-9][a-z0-9.-]{1,61}[a-z0-9])*$",
+ "ConstraintDescription": "Source bucket is required. Please provide at least one valid S3 bucket name that is present in your account.",
+ "Description": "(Required) List the buckets (comma-separated) within your account that contain original image files. If you plan to use Thumbor or Custom image requests with this solution, the source bucket for those requests will default to the first bucket listed in this field. e.g. (defaultBucket,bucketNo2,bucketNo3,...)",
+ "Type": "String",
+ },
+ "UseExistingCloudFrontDistributionParameter": {
+ "AllowedValues": [
+ "Yes",
+ "No",
+ ],
+ "Default": "No",
+ "Description": "If you would like to use an existing CloudFront distribution, select 'Yes'. Otherwise, select 'No' to create a new CloudFront distribution. This option will require additional manual setup after deployment. Please refer to the implementation guide for details: https://docs.aws.amazon.com/solutions/latest/serverless-image-handler/attaching-existing-distribution.html",
+ "Type": "String",
+ },
+ },
+ "Resources": {
+ "BackEndAccessPoint6DA9B104": {
+ "Condition": "CommonResourcesEnableS3ObjectLambdaConditionF2C07DCD",
+ "Properties": {
+ "Bucket": {
+ "Fn::GetAtt": [
+ "CommonResourcesCustomResourcesCustomResourceCheckFirstBucketRegionE663CC31",
+ "BucketName",
+ ],
+ },
+ "Name": {
+ "Fn::Join": [
+ "",
+ [
+ "sih-ap-",
+ {
+ "Fn::GetAtt": [
+ "CommonResourcesCustomResourcesCustomResourceUuid64E7CCAD",
+ "UUID",
+ ],
+ },
+ "-",
+ {
+ "Fn::GetAtt": [
+ "CommonResourcesCustomResourcesCustomResourceCheckFirstBucketRegionE663CC31",
+ "BucketHash",
+ ],
+ },
+ ],
+ ],
+ },
+ "Policy": {
+ "Statement": {
+ "Action": "s3:*",
+ "Condition": {
+ "ForAnyValue:StringEquals": {
+ "aws:CalledVia": "s3-object-lambda.amazonaws.com",
+ },
+ },
+ "Effect": "Allow",
+ "Principal": {
+ "Service": "cloudfront.amazonaws.com",
+ },
+ "Resource": [
+ {
+ "Fn::Join": [
+ "",
+ [
+ "arn:aws:s3:",
+ {
+ "Ref": "AWS::Region",
+ },
+ ":",
+ {
+ "Ref": "AWS::AccountId",
+ },
+ ":accesspoint/sih-ap-",
+ {
+ "Fn::GetAtt": [
+ "CommonResourcesCustomResourcesCustomResourceUuid64E7CCAD",
+ "UUID",
+ ],
+ },
+ "-",
+ {
+ "Fn::GetAtt": [
+ "CommonResourcesCustomResourcesCustomResourceCheckFirstBucketRegionE663CC31",
+ "BucketHash",
+ ],
+ },
+ ],
+ ],
+ },
+ {
+ "Fn::Join": [
+ "",
+ [
+ "arn:aws:s3:",
+ {
+ "Ref": "AWS::Region",
+ },
+ ":",
+ {
+ "Ref": "AWS::AccountId",
+ },
+ ":accesspoint/sih-ap-",
+ {
+ "Fn::GetAtt": [
+ "CommonResourcesCustomResourcesCustomResourceUuid64E7CCAD",
+ "UUID",
+ ],
+ },
+ "-",
+ {
+ "Fn::GetAtt": [
+ "CommonResourcesCustomResourcesCustomResourceCheckFirstBucketRegionE663CC31",
+ "BucketHash",
+ ],
+ },
+ "/object/*",
+ ],
+ ],
+ },
+ ],
+ },
+ },
+ "Tags": [
+ {
+ "Key": "SolutionId",
+ "Value": "S0ABC",
+ },
+ ],
+ },
+ "Type": "AWS::S3::AccessPoint",
+ },
+ "BackEndApigRequestModifierFunction400C4F08": {
+ "Condition": "CommonResourcesDisableS3ObjectLambdaCondition017AC33C",
+ "Properties": {
+ "AutoPublish": true,
+ "FunctionCode": "// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+
+function handler(event) {
+ // Normalize accept header to only include values used on the backend
+ if(event.request.headers && event.request.headers.accept && event.request.headers.accept.value) {
+ event.request.headers.accept.value = event.request.headers.accept.value.indexOf("image/webp") > -1 ? "image/webp" : ""
+ }
+ event.request.querystring = processQueryParams(event.request.querystring).join('&')
+ return event.request;
+}
+
+function processQueryParams(querystring) {
+ if (querystring == null) {
+ return [];
+ }
+
+ const ALLOWED_PARAMS = ['signature', 'expires', 'format', 'fit', 'width', 'height', 'rotate', 'flip', 'flop', 'grayscale'];
+
+ let qs = [];
+ for (const key in querystring) {
+ if (!ALLOWED_PARAMS.includes(key)) {
+ continue;
+ }
+ const value = querystring[key];
+ qs.push(
+ value.multiValue
+ ? \`\${key}=\${value.multiValue[value.multiValue.length - 1].value}\`
+ : \`\${key}=\${value.value}\`
+ )
+ }
+
+ return qs.sort();
+}",
+ "FunctionConfig": {
+ "Comment": {
+ "Fn::Join": [
+ "",
+ [
+ "sih-apig-request-modifier-",
+ {
+ "Fn::GetAtt": [
+ "CommonResourcesCustomResourcesCustomResourceUuid64E7CCAD",
+ "UUID",
+ ],
+ },
+ ],
+ ],
+ },
+ "Runtime": "cloudfront-js-2.0",
+ },
+ "Name": {
+ "Fn::Join": [
+ "",
+ [
+ "sih-apig-request-modifier-",
+ {
+ "Fn::GetAtt": [
+ "CommonResourcesCustomResourcesCustomResourceUuid64E7CCAD",
+ "UUID",
+ ],
+ },
+ ],
+ ],
+ },
+ },
+ "Type": "AWS::CloudFront::Function",
+ },
+ "BackEndCachePolicy1DCE9B1B": {
+ "Properties": {
+ "CachePolicyConfig": {
+ "DefaultTTL": 86400,
+ "MaxTTL": 31536000,
+ "MinTTL": 1,
+ "Name": {
+ "Fn::Join": [
+ "",
+ [
+ "ServerlessImageHandler-",
+ {
+ "Fn::GetAtt": [
+ "CommonResourcesCustomResourcesCustomResourceUuid64E7CCAD",
+ "UUID",
+ ],
+ },
+ ],
+ ],
+ },
+ "ParametersInCacheKeyAndForwardedToOrigin": {
+ "CookiesConfig": {
+ "CookieBehavior": "none",
+ },
+ "EnableAcceptEncodingBrotli": false,
+ "EnableAcceptEncodingGzip": false,
+ "HeadersConfig": {
+ "HeaderBehavior": "whitelist",
+ "Headers": {
+ "Fn::If": [
+ "CommonResourcesAutoWebPCondition7119C768",
+ [
+ "origin",
+ "accept",
+ ],
+ [
+ "origin",
+ ],
+ ],
+ },
+ },
+ "QueryStringsConfig": {
+ "QueryStringBehavior": "all",
+ },
+ },
+ },
+ },
+ "Type": "AWS::CloudFront::CachePolicy",
+ },
+ "BackEndEventSourceMappingResolver0ACBB140": {
+ "Condition": "SendAnonymousStatistics",
+ "DeletionPolicy": "Delete",
+ "Properties": {
+ "EventSourceArn": {
+ "Fn::GetAtt": [
+ "BackEndSolutionMetricsLambdaToSqsToLambdalambdatosqsqueue60A92083",
+ "Arn",
+ ],
+ },
+ "FunctionName": {
+ "Ref": "BackEndSolutionMetricsMetricsLambdaF4FA4AF7",
+ },
+ "ServiceToken": {
+ "Fn::GetAtt": [
+ "BackEndEventSourceMappingResolverFunctionBA1EFDF2",
+ "Arn",
+ ],
+ },
+ },
+ "Type": "AWS::CloudFormation::CustomResource",
+ "UpdateReplacePolicy": "Delete",
+ },
+ "BackEndEventSourceMappingResolverFunctionBA1EFDF2": {
+ "Condition": "SendAnonymousStatistics",
+ "DependsOn": [
+ "BackEndEventSourceMappingResolverFunctionServiceRoleDefaultPolicyF223D80C",
+ "BackEndEventSourceMappingResolverFunctionServiceRole6D07127D",
+ ],
+ "Metadata": {
+ "cfn_nag": {
+ "rules_to_suppress": [
+ {
+ "id": "W89",
+ "reason": "Not in VPC — only calls Lambda control plane APIs",
+ },
+ {
+ "id": "W92",
+ "reason": "No reserved concurrency needed — runs once during deployment",
+ },
+ {
+ "id": "W58",
+ "reason": "The function does have permission to write CloudWatch Logs.",
+ },
+ {
+ "id": "W89",
+ "reason": "The Lambda function does not require any VPC connection at all.",
+ },
+ {
+ "id": "W92",
+ "reason": "The Lambda function does not require ReservedConcurrentExecutions.",
+ },
+ ],
+ },
+ },
+ "Properties": {
+ "Code": {
+ "S3Bucket": {
+ "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}",
+ },
+ "S3Key": "Omitted to remove snapshot dependency on hash",
+ },
+ "Description": "Resolves EventSourceMapping conflicts during stack upgrades",
+ "Handler": "index.handler",
+ "MemorySize": 128,
+ "Role": {
+ "Fn::GetAtt": [
+ "BackEndEventSourceMappingResolverFunctionServiceRole6D07127D",
+ "Arn",
+ ],
+ },
+ "Runtime": "nodejs22.x",
+ "Tags": [
+ {
+ "Key": "SolutionId",
+ "Value": "S0ABC",
+ },
+ ],
+ "Timeout": 30,
+ },
+ "Type": "AWS::Lambda::Function",
+ },
+ "BackEndEventSourceMappingResolverFunctionServiceRole6D07127D": {
+ "Condition": "SendAnonymousStatistics",
+ "Properties": {
+ "AssumeRolePolicyDocument": {
+ "Statement": [
+ {
+ "Action": "sts:AssumeRole",
+ "Effect": "Allow",
+ "Principal": {
+ "Service": "lambda.amazonaws.com",
+ },
+ },
+ ],
+ "Version": "2012-10-17",
+ },
+ "ManagedPolicyArns": [
+ {
+ "Fn::Join": [
+ "",
+ [
+ "arn:",
+ {
+ "Ref": "AWS::Partition",
+ },
+ ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole",
+ ],
+ ],
+ },
+ ],
+ "Tags": [
+ {
+ "Key": "SolutionId",
+ "Value": "S0ABC",
+ },
+ ],
+ },
+ "Type": "AWS::IAM::Role",
+ },
+ "BackEndEventSourceMappingResolverFunctionServiceRoleDefaultPolicyF223D80C": {
+ "Condition": "SendAnonymousStatistics",
+ "Properties": {
+ "PolicyDocument": {
+ "Statement": [
+ {
+ "Action": "lambda:ListEventSourceMappings",
+ "Effect": "Allow",
+ "Resource": "*",
+ },
+ {
+ "Action": "lambda:DeleteEventSourceMapping",
+ "Effect": "Allow",
+ "Resource": {
+ "Fn::Join": [
+ "",
+ [
+ "arn:",
+ {
+ "Ref": "AWS::Partition",
+ },
+ ":lambda:",
+ {
+ "Ref": "AWS::Region",
+ },
+ ":",
+ {
+ "Ref": "AWS::AccountId",
+ },
+ ":event-source-mapping:*",
+ ],
+ ],
+ },
+ },
+ {
+ "Action": "cloudformation:ListStackResources",
+ "Effect": "Allow",
+ "Resource": {
+ "Fn::Sub": "arn:\${AWS::Partition}:cloudformation:\${AWS::Region}:\${AWS::AccountId}:stack/\${AWS::StackName}/*",
+ },
+ },
+ ],
+ "Version": "2012-10-17",
+ },
+ "PolicyName": "BackEndEventSourceMappingResolverFunctionServiceRoleDefaultPolicyF223D80C",
+ "Roles": [
+ {
+ "Ref": "BackEndEventSourceMappingResolverFunctionServiceRole6D07127D",
+ },
+ ],
+ },
+ "Type": "AWS::IAM::Policy",
+ },
+ "BackEndImageHandlerCloudFrontApiGatewayLambdaApiAccessLogGroup9B786692": {
+ "Condition": "CommonResourcesDisableS3ObjectLambdaCondition017AC33C",
+ "DeletionPolicy": "Retain",
+ "Metadata": {
+ "cfn_nag": {
+ "rules_to_suppress": [
+ {
+ "id": "W86",
+ "reason": "Retention period for CloudWatchLogs LogGroups are set to 'Never Expire' to preserve customer data indefinitely",
+ },
+ {
+ "id": "W84",
+ "reason": "By default CloudWatchLogs LogGroups data is encrypted using the CloudWatch server-side encryption keys (AWS Managed Keys)",
+ },
+ ],
+ },
+ },
+ "Properties": {
+ "RetentionInDays": {
+ "Fn::If": [
+ "CommonResourcesIsLogRetentionPeriodInfinite129C8A82",
+ {
+ "Ref": "AWS::NoValue",
+ },
+ {
+ "Ref": "LogRetentionPeriodParameter",
+ },
+ ],
+ },
+ "Tags": [
+ {
+ "Key": "SolutionId",
+ "Value": "S0ABC",
+ },
+ ],
+ },
+ "Type": "AWS::Logs::LogGroup",
+ "UpdateReplacePolicy": "Retain",
+ },
+ "BackEndImageHandlerCloudFrontApiGatewayLambdaCloudFrontToApiGatewayCloudFrontDistribution03AA31B2": {
+ "Condition": "BackEndDeployAPIGDistributionF4E75280",
+ "Metadata": {
+ "cfn_nag": {
+ "rules_to_suppress": [
+ {
+ "id": "W70",
+ "reason": "Since the distribution uses the CloudFront domain name, CloudFront automatically sets the security policy to TLSv1 regardless of the value of MinimumProtocolVersion",
+ },
+ ],
+ },
+ },
+ "Properties": {
+ "DistributionConfig": {
+ "Comment": "Image Handler Distribution for Dynamic Image Transformation for Amazon CloudFront",
+ "CustomErrorResponses": [
+ {
+ "ErrorCachingMinTTL": 600,
+ "ErrorCode": 500,
+ },
+ {
+ "ErrorCachingMinTTL": 600,
+ "ErrorCode": 501,
+ },
+ {
+ "ErrorCachingMinTTL": 600,
+ "ErrorCode": 502,
+ },
+ {
+ "ErrorCachingMinTTL": 600,
+ "ErrorCode": 503,
+ },
+ {
+ "ErrorCachingMinTTL": 600,
+ "ErrorCode": 504,
+ },
+ ],
+ "DefaultCacheBehavior": {
+ "AllowedMethods": [
+ "GET",
+ "HEAD",
+ ],
+ "CachePolicyId": {
+ "Ref": "BackEndCachePolicy1DCE9B1B",
+ },
+ "Compress": true,
+ "FunctionAssociations": [
+ {
+ "EventType": "viewer-request",
+ "FunctionARN": {
+ "Fn::GetAtt": [
+ "BackEndApigRequestModifierFunction400C4F08",
+ "FunctionARN",
+ ],
+ },
+ },
+ ],
+ "OriginRequestPolicyId": {
+ "Ref": "BackEndOriginRequestPolicy771345D7",
+ },
+ "TargetOriginId": "TestStackBackEndImageHandlerCloudFrontApiGatewayLambdaCloudFrontToApiGatewayCloudFrontDistributionOrigin1A053AEB7",
+ "ViewerProtocolPolicy": "redirect-to-https",
+ },
+ "Enabled": true,
+ "HttpVersion": "http2",
+ "IPV6Enabled": true,
+ "Logging": {
+ "Bucket": {
+ "Fn::Join": [
+ "",
+ [
+ {
+ "Fn::GetAtt": [
+ "CommonResourcesCustomResourcesLogBucketCustomResource2445A3AB",
+ "BucketName",
+ ],
+ },
+ ".s3.",
+ {
+ "Fn::GetAtt": [
+ "CommonResourcesCustomResourcesLogBucketCustomResource2445A3AB",
+ "Region",
+ ],
+ },
+ ".",
+ {
+ "Ref": "AWS::URLSuffix",
+ },
+ ],
+ ],
+ },
+ "Prefix": "api-cloudfront/",
+ },
+ "Origins": [
+ {
+ "CustomOriginConfig": {
+ "OriginProtocolPolicy": "https-only",
+ "OriginSSLProtocols": [
+ "TLSv1.1",
+ "TLSv1.2",
+ ],
+ },
+ "DomainName": {
+ "Fn::Join": [
+ "",
+ [
+ {
+ "Ref": "BackEndImageHandlerCloudFrontApiGatewayLambdaLambdaRestApi5A77D109",
+ },
+ ".execute-api.",
+ {
+ "Ref": "AWS::Region",
+ },
+ ".amazonaws.com",
+ ],
+ ],
+ },
+ "Id": "TestStackBackEndImageHandlerCloudFrontApiGatewayLambdaCloudFrontToApiGatewayCloudFrontDistributionOrigin1A053AEB7",
+ "OriginPath": "/image",
+ "OriginShield": {
+ "Fn::If": [
+ "CommonResourcesEnableOriginShieldConditionCEE94847",
+ {
+ "Enabled": true,
+ "OriginShieldRegion": {
+ "Ref": "OriginShieldRegionParameter",
+ },
+ },
+ {
+ "Enabled": false,
+ },
+ ],
+ },
+ },
+ ],
+ "PriceClass": {
+ "Ref": "CloudFrontPriceClassParameter",
+ },
+ },
+ "Tags": [
+ {
+ "Key": "SolutionId",
+ "Value": "S0ABC",
+ },
+ ],
+ },
+ "Type": "AWS::CloudFront::Distribution",
+ },
+ "BackEndImageHandlerCloudFrontApiGatewayLambdaLambdaRestApi5A77D109": {
+ "Condition": "CommonResourcesDisableS3ObjectLambdaCondition017AC33C",
+ "Metadata": {
+ "cfn_nag": {
+ "rules_to_suppress": [
+ {
+ "id": "W59",
+ "reason": "AWS::ApiGateway::Method AuthorizationType is set to 'NONE' because API Gateway behind CloudFront does not support AWS_IAM authentication",
+ },
+ ],
+ },
+ },
+ "Properties": {
+ "BinaryMediaTypes": [
+ "*/*",
+ ],
+ "EndpointConfiguration": {
+ "Types": [
+ "REGIONAL",
+ ],
+ },
+ "Name": "LambdaRestApi",
+ "Tags": [
+ {
+ "Key": "SolutionId",
+ "Value": "S0ABC",
+ },
+ ],
+ },
+ "Type": "AWS::ApiGateway::RestApi",
+ },
+ "BackEndImageHandlerCloudFrontApiGatewayLambdaLambdaRestApiANYApiPermissionTestStackBackEndImageHandlerCloudFrontApiGatewayLambdaLambdaRestApi9D692DD2ANY979F1429": {
+ "Condition": "CommonResourcesDisableS3ObjectLambdaCondition017AC33C",
+ "Properties": {
+ "Action": "lambda:InvokeFunction",
+ "FunctionName": {
+ "Fn::GetAtt": [
+ "BackEndImageHandlerLambdaFunctionADEF7FF2",
+ "Arn",
+ ],
+ },
+ "Principal": "apigateway.amazonaws.com",
+ "SourceArn": {
+ "Fn::Join": [
+ "",
+ [
+ "arn:",
+ {
+ "Ref": "AWS::Partition",
+ },
+ ":execute-api:",
+ {
+ "Ref": "AWS::Region",
+ },
+ ":",
+ {
+ "Ref": "AWS::AccountId",
+ },
+ ":",
+ {
+ "Ref": "BackEndImageHandlerCloudFrontApiGatewayLambdaLambdaRestApi5A77D109",
+ },
+ "/",
+ {
+ "Ref": "BackEndImageHandlerCloudFrontApiGatewayLambdaLambdaRestApiDeploymentStageimageB55D20E3",
+ },
+ "/*/",
+ ],
+ ],
+ },
+ },
+ "Type": "AWS::Lambda::Permission",
+ },
+ "BackEndImageHandlerCloudFrontApiGatewayLambdaLambdaRestApiANYApiPermissionTestTestStackBackEndImageHandlerCloudFrontApiGatewayLambdaLambdaRestApi9D692DD2ANY932D3700": {
+ "Condition": "CommonResourcesDisableS3ObjectLambdaCondition017AC33C",
+ "Properties": {
+ "Action": "lambda:InvokeFunction",
+ "FunctionName": {
+ "Fn::GetAtt": [
+ "BackEndImageHandlerLambdaFunctionADEF7FF2",
+ "Arn",
+ ],
+ },
+ "Principal": "apigateway.amazonaws.com",
+ "SourceArn": {
+ "Fn::Join": [
+ "",
+ [
+ "arn:",
+ {
+ "Ref": "AWS::Partition",
+ },
+ ":execute-api:",
+ {
+ "Ref": "AWS::Region",
+ },
+ ":",
+ {
+ "Ref": "AWS::AccountId",
+ },
+ ":",
+ {
+ "Ref": "BackEndImageHandlerCloudFrontApiGatewayLambdaLambdaRestApi5A77D109",
+ },
+ "/test-invoke-stage/*/",
+ ],
+ ],
+ },
+ },
+ "Type": "AWS::Lambda::Permission",
+ },
+ "BackEndImageHandlerCloudFrontApiGatewayLambdaLambdaRestApiANYE4494B31": {
+ "Condition": "CommonResourcesDisableS3ObjectLambdaCondition017AC33C",
+ "Metadata": {
+ "cfn_nag": {
+ "rules_to_suppress": [
+ {
+ "id": "W59",
+ "reason": "No authorization currently on the API Gateway",
+ },
+ ],
+ },
+ },
+ "Properties": {
+ "AuthorizationType": "NONE",
+ "HttpMethod": "ANY",
+ "Integration": {
+ "IntegrationHttpMethod": "POST",
+ "Type": "AWS_PROXY",
+ "Uri": {
+ "Fn::Join": [
+ "",
+ [
+ "arn:",
+ {
+ "Ref": "AWS::Partition",
+ },
+ ":apigateway:",
+ {
+ "Ref": "AWS::Region",
+ },
+ ":lambda:path/2015-03-31/functions/",
+ {
+ "Fn::GetAtt": [
+ "BackEndImageHandlerLambdaFunctionADEF7FF2",
+ "Arn",
+ ],
+ },
+ "/invocations",
+ ],
+ ],
+ },
+ },
+ "ResourceId": {
+ "Fn::GetAtt": [
+ "BackEndImageHandlerCloudFrontApiGatewayLambdaLambdaRestApi5A77D109",
+ "RootResourceId",
+ ],
+ },
+ "RestApiId": {
+ "Ref": "BackEndImageHandlerCloudFrontApiGatewayLambdaLambdaRestApi5A77D109",
+ },
+ },
+ "Type": "AWS::ApiGateway::Method",
+ },
+ "BackEndImageHandlerCloudFrontApiGatewayLambdaLambdaRestApiAccountE5522E5D": {
+ "Condition": "CommonResourcesDisableS3ObjectLambdaCondition017AC33C",
+ "DependsOn": [
+ "BackEndImageHandlerCloudFrontApiGatewayLambdaLambdaRestApi5A77D109",
+ ],
+ "Properties": {
+ "CloudWatchRoleArn": {
+ "Fn::GetAtt": [
+ "BackEndImageHandlerCloudFrontApiGatewayLambdaLambdaRestApiCloudWatchRole12575C4D",
+ "Arn",
+ ],
+ },
+ },
+ "Type": "AWS::ApiGateway::Account",
+ },
+ "BackEndImageHandlerCloudFrontApiGatewayLambdaLambdaRestApiCloudWatchRole12575C4D": {
+ "Condition": "CommonResourcesDisableS3ObjectLambdaCondition017AC33C",
+ "Metadata": {
+ "cfn_nag": {
+ "rules_to_suppress": [
+ {
+ "id": "F10",
+ "reason": "Inline policy used in solutions construct",
+ },
+ ],
+ },
+ },
+ "Properties": {
+ "AssumeRolePolicyDocument": {
+ "Statement": [
+ {
+ "Action": "sts:AssumeRole",
+ "Effect": "Allow",
+ "Principal": {
+ "Service": "apigateway.amazonaws.com",
+ },
+ },
+ ],
+ "Version": "2012-10-17",
+ },
+ "Policies": [
+ {
+ "PolicyDocument": {
+ "Statement": [
+ {
+ "Action": [
+ "logs:CreateLogGroup",
+ "logs:CreateLogStream",
+ "logs:DescribeLogGroups",
+ "logs:DescribeLogStreams",
+ "logs:PutLogEvents",
+ "logs:GetLogEvents",
+ "logs:FilterLogEvents",
+ ],
+ "Effect": "Allow",
+ "Resource": {
+ "Fn::Join": [
+ "",
+ [
+ "arn:",
+ {
+ "Ref": "AWS::Partition",
+ },
+ ":logs:",
+ {
+ "Ref": "AWS::Region",
+ },
+ ":",
+ {
+ "Ref": "AWS::AccountId",
+ },
+ ":*",
+ ],
+ ],
+ },
+ },
+ ],
+ "Version": "2012-10-17",
+ },
+ "PolicyName": "LambdaRestApiCloudWatchRolePolicy",
+ },
+ ],
+ "Tags": [
+ {
+ "Key": "SolutionId",
+ "Value": "S0ABC",
+ },
+ ],
+ },
+ "Type": "AWS::IAM::Role",
+ },
+ "BackEndImageHandlerCloudFrontApiGatewayLambdaLambdaRestApiDeployment663240D68d2558b8e7783b0edad2e0b11793c95c": {
+ "Condition": "CommonResourcesDisableS3ObjectLambdaCondition017AC33C",
+ "DependsOn": [
+ "BackEndImageHandlerCloudFrontApiGatewayLambdaLambdaRestApiproxyANY8F9763E1",
+ "BackEndImageHandlerCloudFrontApiGatewayLambdaLambdaRestApiproxyBDF0A131",
+ "BackEndImageHandlerCloudFrontApiGatewayLambdaLambdaRestApiANYE4494B31",
+ ],
+ "Metadata": {
+ "aws:cdk:do-not-refactor": true,
+ "cfn_nag": {
+ "rules_to_suppress": [
+ {
+ "id": "W45",
+ "reason": "ApiGateway has AccessLogging enabled in AWS::ApiGateway::Stage resource, but cfn_nag checks for it in AWS::ApiGateway::Deployment resource",
+ },
+ ],
+ },
+ },
+ "Properties": {
+ "Description": "Automatically created by the RestApi construct",
+ "RestApiId": {
+ "Ref": "BackEndImageHandlerCloudFrontApiGatewayLambdaLambdaRestApi5A77D109",
+ },
+ },
+ "Type": "AWS::ApiGateway::Deployment",
+ },
+ "BackEndImageHandlerCloudFrontApiGatewayLambdaLambdaRestApiDeploymentStageimageB55D20E3": {
+ "Condition": "CommonResourcesDisableS3ObjectLambdaCondition017AC33C",
+ "Metadata": {
+ "cfn_nag": {
+ "rules_to_suppress": [
+ {
+ "id": "W87",
+ "reason": "Cache not enabled, using CloudFront for caching viewer response",
+ },
+ ],
+ },
+ },
+ "Properties": {
+ "AccessLogSetting": {
+ "DestinationArn": {
+ "Fn::GetAtt": [
+ "BackEndImageHandlerCloudFrontApiGatewayLambdaApiAccessLogGroup9B786692",
+ "Arn",
+ ],
+ },
+ "Format": "{"requestId":"$context.requestId","ip":"$context.identity.sourceIp","user":"$context.identity.user","caller":"$context.identity.caller","requestTime":"$context.requestTime","httpMethod":"$context.httpMethod","resourcePath":"$context.resourcePath","status":"$context.status","protocol":"$context.protocol","responseLength":"$context.responseLength"}",
+ },
+ "DeploymentId": {
+ "Ref": "BackEndImageHandlerCloudFrontApiGatewayLambdaLambdaRestApiDeployment663240D68d2558b8e7783b0edad2e0b11793c95c",
+ },
+ "MethodSettings": [
+ {
+ "DataTraceEnabled": false,
+ "HttpMethod": "*",
+ "LoggingLevel": "INFO",
+ "ResourcePath": "/*",
+ },
+ ],
+ "RestApiId": {
+ "Ref": "BackEndImageHandlerCloudFrontApiGatewayLambdaLambdaRestApi5A77D109",
+ },
+ "StageName": "image",
+ "Tags": [
+ {
+ "Key": "SolutionId",
+ "Value": "S0ABC",
+ },
+ ],
+ "TracingEnabled": true,
+ },
+ "Type": "AWS::ApiGateway::Stage",
+ },
+ "BackEndImageHandlerCloudFrontApiGatewayLambdaLambdaRestApiUsagePlan76CA1E70": {
+ "Condition": "CommonResourcesDisableS3ObjectLambdaCondition017AC33C",
+ "Properties": {
+ "ApiStages": [
+ {
+ "ApiId": {
+ "Ref": "BackEndImageHandlerCloudFrontApiGatewayLambdaLambdaRestApi5A77D109",
+ },
+ "Stage": {
+ "Ref": "BackEndImageHandlerCloudFrontApiGatewayLambdaLambdaRestApiDeploymentStageimageB55D20E3",
+ },
+ "Throttle": {},
+ },
+ ],
+ "Tags": [
+ {
+ "Key": "SolutionId",
+ "Value": "S0ABC",
+ },
+ ],
+ },
+ "Type": "AWS::ApiGateway::UsagePlan",
+ },
+ "BackEndImageHandlerCloudFrontApiGatewayLambdaLambdaRestApiproxyANY8F9763E1": {
+ "Condition": "CommonResourcesDisableS3ObjectLambdaCondition017AC33C",
+ "Metadata": {
+ "cfn_nag": {
+ "rules_to_suppress": [
+ {
+ "id": "W59",
+ "reason": "No authorization currently on the API Gateway",
+ },
+ ],
+ },
+ },
+ "Properties": {
+ "AuthorizationType": "NONE",
+ "HttpMethod": "ANY",
+ "Integration": {
+ "IntegrationHttpMethod": "POST",
+ "Type": "AWS_PROXY",
+ "Uri": {
+ "Fn::Join": [
+ "",
+ [
+ "arn:",
+ {
+ "Ref": "AWS::Partition",
+ },
+ ":apigateway:",
+ {
+ "Ref": "AWS::Region",
+ },
+ ":lambda:path/2015-03-31/functions/",
+ {
+ "Fn::GetAtt": [
+ "BackEndImageHandlerLambdaFunctionADEF7FF2",
+ "Arn",
+ ],
+ },
+ "/invocations",
+ ],
+ ],
+ },
+ },
+ "ResourceId": {
+ "Ref": "BackEndImageHandlerCloudFrontApiGatewayLambdaLambdaRestApiproxyBDF0A131",
+ },
+ "RestApiId": {
+ "Ref": "BackEndImageHandlerCloudFrontApiGatewayLambdaLambdaRestApi5A77D109",
+ },
+ },
+ "Type": "AWS::ApiGateway::Method",
+ },
+ "BackEndImageHandlerCloudFrontApiGatewayLambdaLambdaRestApiproxyANYApiPermissionTestStackBackEndImageHandlerCloudFrontApiGatewayLambdaLambdaRestApi9D692DD2ANYproxyB5CBD1F7": {
+ "Condition": "CommonResourcesDisableS3ObjectLambdaCondition017AC33C",
+ "Properties": {
+ "Action": "lambda:InvokeFunction",
+ "FunctionName": {
+ "Fn::GetAtt": [
+ "BackEndImageHandlerLambdaFunctionADEF7FF2",
+ "Arn",
+ ],
+ },
+ "Principal": "apigateway.amazonaws.com",
+ "SourceArn": {
+ "Fn::Join": [
+ "",
+ [
+ "arn:",
+ {
+ "Ref": "AWS::Partition",
+ },
+ ":execute-api:",
+ {
+ "Ref": "AWS::Region",
+ },
+ ":",
+ {
+ "Ref": "AWS::AccountId",
+ },
+ ":",
+ {
+ "Ref": "BackEndImageHandlerCloudFrontApiGatewayLambdaLambdaRestApi5A77D109",
+ },
+ "/",
+ {
+ "Ref": "BackEndImageHandlerCloudFrontApiGatewayLambdaLambdaRestApiDeploymentStageimageB55D20E3",
+ },
+ "/*/*",
+ ],
+ ],
+ },
+ },
+ "Type": "AWS::Lambda::Permission",
+ },
+ "BackEndImageHandlerCloudFrontApiGatewayLambdaLambdaRestApiproxyANYApiPermissionTestTestStackBackEndImageHandlerCloudFrontApiGatewayLambdaLambdaRestApi9D692DD2ANYproxyAEADD71A": {
+ "Condition": "CommonResourcesDisableS3ObjectLambdaCondition017AC33C",
+ "Properties": {
+ "Action": "lambda:InvokeFunction",
+ "FunctionName": {
+ "Fn::GetAtt": [
+ "BackEndImageHandlerLambdaFunctionADEF7FF2",
+ "Arn",
+ ],
+ },
+ "Principal": "apigateway.amazonaws.com",
+ "SourceArn": {
+ "Fn::Join": [
+ "",
+ [
+ "arn:",
+ {
+ "Ref": "AWS::Partition",
+ },
+ ":execute-api:",
+ {
+ "Ref": "AWS::Region",
+ },
+ ":",
+ {
+ "Ref": "AWS::AccountId",
+ },
+ ":",
+ {
+ "Ref": "BackEndImageHandlerCloudFrontApiGatewayLambdaLambdaRestApi5A77D109",
+ },
+ "/test-invoke-stage/*/*",
+ ],
+ ],
+ },
+ },
+ "Type": "AWS::Lambda::Permission",
+ },
+ "BackEndImageHandlerCloudFrontApiGatewayLambdaLambdaRestApiproxyBDF0A131": {
+ "Condition": "CommonResourcesDisableS3ObjectLambdaCondition017AC33C",
+ "Properties": {
+ "ParentId": {
+ "Fn::GetAtt": [
+ "BackEndImageHandlerCloudFrontApiGatewayLambdaLambdaRestApi5A77D109",
+ "RootResourceId",
+ ],
+ },
+ "PathPart": "{proxy+}",
+ "RestApiId": {
+ "Ref": "BackEndImageHandlerCloudFrontApiGatewayLambdaLambdaRestApi5A77D109",
+ },
+ },
+ "Type": "AWS::ApiGateway::Resource",
+ },
+ "BackEndImageHandlerCloudFrontDistributionB5464C90": {
+ "Condition": "BackEndDeployS3OLDistribution869FCC7C",
+ "Metadata": {
+ "cfn_nag": {
+ "rules_to_suppress": [
+ {
+ "id": "W70",
+ "reason": "Since the distribution uses the CloudFront domain name, CloudFront automatically sets the security policy to TLSv1 regardless of the value of MinimumProtocolVersion",
+ },
+ ],
+ },
+ },
+ "Properties": {
+ "DistributionConfig": {
+ "Comment": "Image Handler Distribution for Dynamic Image Transformation for Amazon CloudFront",
+ "CustomErrorResponses": [
+ {
+ "ErrorCachingMinTTL": 600,
+ "ErrorCode": 500,
+ },
+ {
+ "ErrorCachingMinTTL": 600,
+ "ErrorCode": 501,
+ },
+ {
+ "ErrorCachingMinTTL": 600,
+ "ErrorCode": 502,
+ },
+ {
+ "ErrorCachingMinTTL": 600,
+ "ErrorCode": 503,
+ },
+ {
+ "ErrorCachingMinTTL": 600,
+ "ErrorCode": 504,
+ },
+ ],
+ "DefaultCacheBehavior": {
+ "AllowedMethods": [
+ "GET",
+ "HEAD",
+ ],
+ "CachePolicyId": {
+ "Ref": "BackEndCachePolicy1DCE9B1B",
+ },
+ "Compress": true,
+ "FunctionAssociations": [
+ {
+ "EventType": "viewer-response",
+ "FunctionARN": {
+ "Fn::GetAtt": [
+ "BackEndOlResponseModifierFunctionB47B3834",
+ "FunctionARN",
+ ],
+ },
+ },
+ {
+ "EventType": "viewer-request",
+ "FunctionARN": {
+ "Fn::GetAtt": [
+ "BackEndOlRequestModifierFunction7E5192E3",
+ "FunctionARN",
+ ],
+ },
+ },
+ ],
+ "OriginRequestPolicyId": {
+ "Ref": "BackEndOriginRequestPolicy771345D7",
+ },
+ "TargetOriginId": "TestStackBackEndImageHandlerCloudFrontDistributionOrigin1781ABF9C",
+ "ViewerProtocolPolicy": "redirect-to-https",
+ },
+ "Enabled": true,
+ "HttpVersion": "http2",
+ "IPV6Enabled": true,
+ "Logging": {
+ "Bucket": {
+ "Fn::Join": [
+ "",
+ [
+ {
+ "Fn::GetAtt": [
+ "CommonResourcesCustomResourcesLogBucketCustomResource2445A3AB",
+ "BucketName",
+ ],
+ },
+ ".s3.",
+ {
+ "Fn::GetAtt": [
+ "CommonResourcesCustomResourcesLogBucketCustomResource2445A3AB",
+ "Region",
+ ],
+ },
+ ".",
+ {
+ "Ref": "AWS::URLSuffix",
+ },
+ ],
+ ],
+ },
+ "Prefix": "api-cloudfront/",
+ },
+ "Origins": [
+ {
+ "ConnectionAttempts": 1,
+ "DomainName": {
+ "Fn::Join": [
+ "",
+ [
+ {
+ "Fn::GetAtt": [
+ "BackEndObjectLambdaAccessPointBEE6B960",
+ "Alias.Value",
+ ],
+ },
+ ".s3.",
+ {
+ "Ref": "AWS::Region",
+ },
+ ".amazonaws.com",
+ ],
+ ],
+ },
+ "Id": "TestStackBackEndImageHandlerCloudFrontDistributionOrigin1781ABF9C",
+ "OriginAccessControlId": {
+ "Fn::GetAtt": [
+ "BackEndSIHoriginaccesscontrolAFC8496A",
+ "Id",
+ ],
+ },
+ "OriginPath": "/image",
+ "OriginShield": {
+ "Fn::If": [
+ "CommonResourcesEnableOriginShieldConditionCEE94847",
+ {
+ "Enabled": true,
+ "OriginShieldRegion": {
+ "Ref": "OriginShieldRegionParameter",
+ },
+ },
+ {
+ "Enabled": false,
+ },
+ ],
+ },
+ "S3OriginConfig": {},
+ },
+ ],
+ "PriceClass": {
+ "Ref": "CloudFrontPriceClassParameter",
+ },
+ },
+ "Tags": [
+ {
+ "Key": "SolutionId",
+ "Value": "S0ABC",
+ },
+ ],
+ },
+ "Type": "AWS::CloudFront::Distribution",
+ },
+ "BackEndImageHandlerFunctionPolicy437940B5": {
+ "Metadata": {
+ "cfn_nag": {
+ "rules_to_suppress": [
+ {
+ "id": "W12",
+ "reason": "rekognition:DetectFaces requires '*' resources.",
+ },
+ ],
+ },
+ },
+ "Properties": {
+ "PolicyDocument": {
+ "Statement": [
+ {
+ "Action": [
+ "logs:CreateLogGroup",
+ "logs:CreateLogStream",
+ "logs:PutLogEvents",
+ ],
+ "Effect": "Allow",
+ "Resource": {
+ "Fn::Join": [
+ "",
+ [
+ "arn:",
+ {
+ "Ref": "AWS::Partition",
+ },
+ ":logs:",
+ {
+ "Ref": "AWS::Region",
+ },
+ ":",
+ {
+ "Ref": "AWS::AccountId",
+ },
+ ":log-group:/aws/lambda/*",
+ ],
+ ],
+ },
+ },
+ {
+ "Action": "s3:GetObject",
+ "Effect": "Allow",
+ "Resource": {
+ "Fn::Split": [
+ ",",
+ {
+ "Fn::Sub": [
+ "arn:aws:s3:::\${rest}/*",
+ {
+ "rest": {
+ "Fn::Join": [
+ "/*,arn:aws:s3:::",
+ {
+ "Fn::Split": [
+ ",",
+ {
+ "Fn::Join": [
+ "",
+ {
+ "Fn::Split": [
+ " ",
+ {
+ "Ref": "SourceBucketsParameter",
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ },
+ ],
+ },
+ ],
+ },
+ },
+ {
+ "Action": "s3:ListBucket",
+ "Effect": "Allow",
+ "Resource": {
+ "Fn::Split": [
+ ",",
+ {
+ "Fn::Sub": [
+ "arn:aws:s3:::\${rest}",
+ {
+ "rest": {
+ "Fn::Join": [
+ ",arn:aws:s3:::",
+ {
+ "Fn::Split": [
+ ",",
+ {
+ "Fn::Join": [
+ "",
+ {
+ "Fn::Split": [
+ " ",
+ {
+ "Ref": "SourceBucketsParameter",
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ },
+ ],
+ },
+ ],
+ },
+ },
+ {
+ "Action": "s3:GetObject",
+ "Effect": "Allow",
+ "Resource": {
+ "Fn::Join": [
+ "",
+ [
+ "arn:aws:s3:::",
+ {
+ "Ref": "FallbackImageS3BucketParameter",
+ },
+ "/",
+ {
+ "Ref": "FallbackImageS3KeyParameter",
+ },
+ ],
+ ],
+ },
+ },
+ {
+ "Action": [
+ "rekognition:DetectFaces",
+ "rekognition:DetectModerationLabels",
+ ],
+ "Effect": "Allow",
+ "Resource": "*",
+ },
+ ],
+ "Version": "2012-10-17",
+ },
+ "PolicyName": "BackEndImageHandlerFunctionPolicy437940B5",
+ "Roles": [
+ {
+ "Ref": "BackEndImageHandlerFunctionRoleABF81E5C",
+ },
+ ],
+ },
+ "Type": "AWS::IAM::Policy",
+ },
+ "BackEndImageHandlerFunctionRoleABF81E5C": {
+ "Properties": {
+ "AssumeRolePolicyDocument": {
+ "Statement": [
+ {
+ "Action": "sts:AssumeRole",
+ "Effect": "Allow",
+ "Principal": {
+ "Service": "lambda.amazonaws.com",
+ },
+ },
+ ],
+ "Version": "2012-10-17",
+ },
+ "Path": "/",
+ "Tags": [
+ {
+ "Key": "SolutionId",
+ "Value": "S0ABC",
+ },
+ ],
+ },
+ "Type": "AWS::IAM::Role",
+ },
+ "BackEndImageHandlerLambdaFunctionADEF7FF2": {
+ "DependsOn": [
+ "BackEndImageHandlerFunctionRoleABF81E5C",
+ ],
+ "Metadata": {
+ "cfn_nag": {
+ "rules_to_suppress": [
+ {
+ "id": "W58",
+ "reason": "The function does have permission to write CloudWatch Logs.",
+ },
+ {
+ "id": "W89",
+ "reason": "The Lambda function does not require any VPC connection at all.",
+ },
+ {
+ "id": "W92",
+ "reason": "The Lambda function does not require ReservedConcurrentExecutions.",
+ },
+ ],
+ },
+ },
+ "Properties": {
+ "Code": {
+ "S3Bucket": {
+ "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}",
+ },
+ "S3Key": "Omitted to remove snapshot dependency on hash",
+ },
+ "Description": "dit (v7.0.1): Performs image edits and manipulations",
+ "Environment": {
+ "Variables": {
+ "AUTO_WEBP": {
+ "Ref": "AutoWebPParameter",
+ },
+ "CORS_ENABLED": {
+ "Ref": "CorsEnabledParameter",
+ },
+ "CORS_ORIGIN": {
+ "Ref": "CorsOriginParameter",
+ },
+ "DEFAULT_FALLBACK_IMAGE_BUCKET": {
+ "Ref": "FallbackImageS3BucketParameter",
+ },
+ "DEFAULT_FALLBACK_IMAGE_KEY": {
+ "Ref": "FallbackImageS3KeyParameter",
+ },
+ "ENABLE_DEFAULT_FALLBACK_IMAGE": {
+ "Ref": "EnableDefaultFallbackImageParameter",
+ },
+ "ENABLE_S3_OBJECT_LAMBDA": {
+ "Ref": "EnableS3ObjectLambdaParameter",
+ },
+ "ENABLE_SIGNATURE": {
+ "Ref": "EnableSignatureParameter",
+ },
+ "REWRITE_MATCH_PATTERN": "",
+ "REWRITE_SUBSTITUTION": "",
+ "SECRETS_MANAGER": {
+ "Ref": "SecretsManagerSecretParameter",
+ },
+ "SECRET_KEY": {
+ "Ref": "SecretsManagerKeyParameter",
+ },
+ "SHARP_SIZE_LIMIT": {
+ "Fn::FindInMap": [
+ "Solution",
+ "Config",
+ "SharpSizeLimit",
+ ],
+ },
+ "SOLUTION_ID": "S0ABC",
+ "SOLUTION_VERSION": "Omitted to remove snapshot dependency on solution version",
+ "SOURCE_BUCKETS": {
+ "Ref": "SourceBucketsParameter",
+ },
+ },
+ },
+ "Handler": "index.handler",
+ "MemorySize": 1024,
+ "Role": {
+ "Fn::GetAtt": [
+ "BackEndImageHandlerFunctionRoleABF81E5C",
+ "Arn",
+ ],
+ },
+ "Runtime": "nodejs22.x",
+ "Tags": [
+ {
+ "Key": "SolutionId",
+ "Value": "S0ABC",
+ },
+ ],
+ "Timeout": 29,
+ },
+ "Type": "AWS::Lambda::Function",
+ },
+ "BackEndImageHandlerLambdaFunctionInvokeOmXtXvfmnVyX0ul6SNprKOdkal6YvZiIw5QCpGsJFo09B7B011": {
+ "Properties": {
+ "Action": "lambda:InvokeFunction",
+ "FunctionName": {
+ "Fn::GetAtt": [
+ "BackEndImageHandlerLambdaFunctionADEF7FF2",
+ "Arn",
+ ],
+ },
+ "Principal": "cloudfront.amazonaws.com",
+ },
+ "Type": "AWS::Lambda::Permission",
+ },
+ "BackEndImageHandlerLogGroupA0941EEC": {
+ "DeletionPolicy": "Retain",
+ "Metadata": {
+ "cfn_nag": {
+ "rules_to_suppress": [
+ {
+ "id": "W84",
+ "reason": "CloudWatch log group is always encrypted by default.",
+ },
+ {
+ "id": "W86",
+ "reason": "Retention days are configured with property override",
+ },
+ ],
+ },
+ },
+ "Properties": {
+ "LogGroupName": {
+ "Fn::Join": [
+ "",
+ [
+ "/aws/lambda/",
+ {
+ "Ref": "BackEndImageHandlerLambdaFunctionADEF7FF2",
+ },
+ ],
+ ],
+ },
+ "RetentionInDays": {
+ "Fn::If": [
+ "CommonResourcesIsLogRetentionPeriodInfinite129C8A82",
+ {
+ "Ref": "AWS::NoValue",
+ },
+ {
+ "Ref": "LogRetentionPeriodParameter",
+ },
+ ],
+ },
+ "Tags": [
+ {
+ "Key": "SolutionId",
+ "Value": "S0ABC",
+ },
+ ],
+ },
+ "Type": "AWS::Logs::LogGroup",
+ "UpdateReplacePolicy": "Retain",
+ },
+ "BackEndObjectLambdaAccessPointBEE6B960": {
+ "Condition": "CommonResourcesEnableS3ObjectLambdaConditionF2C07DCD",
+ "Properties": {
+ "Name": {
+ "Fn::Join": [
+ "",
+ [
+ "sih-olap-",
+ {
+ "Fn::GetAtt": [
+ "CommonResourcesCustomResourcesCustomResourceUuid64E7CCAD",
+ "UUID",
+ ],
+ },
+ ],
+ ],
+ },
+ "ObjectLambdaConfiguration": {
+ "SupportingAccessPoint": {
+ "Fn::GetAtt": [
+ "BackEndAccessPoint6DA9B104",
+ "Arn",
+ ],
+ },
+ "TransformationConfigurations": [
+ {
+ "Actions": [
+ "GetObject",
+ "HeadObject",
+ ],
+ "ContentTransformation": {
+ "AwsLambda": {
+ "FunctionArn": {
+ "Fn::GetAtt": [
+ "BackEndImageHandlerLambdaFunctionADEF7FF2",
+ "Arn",
+ ],
+ },
+ },
+ },
+ },
+ ],
+ },
+ },
+ "Type": "AWS::S3ObjectLambda::AccessPoint",
+ },
+ "BackEndObjectLambdaAccessPointPolicy1FC842E3": {
+ "Condition": "CommonResourcesEnableS3ObjectLambdaConditionF2C07DCD",
+ "Properties": {
+ "ObjectLambdaAccessPoint": {
+ "Ref": "BackEndObjectLambdaAccessPointBEE6B960",
+ },
+ "PolicyDocument": {
+ "Statement": [
+ {
+ "Action": "s3-object-lambda:Get*",
+ "Condition": {
+ "StringEquals": {
+ "aws:SourceArn": {
+ "Fn::Join": [
+ "",
+ [
+ "arn:aws:cloudfront::",
+ {
+ "Ref": "AWS::AccountId",
+ },
+ ":distribution/",
+ {
+ "Fn::If": [
+ "CommonResourcesUseExistingCloudFrontDistributionConditionEBC48184",
+ {
+ "Ref": "ExistingCloudFrontDistributionIdParameter",
+ },
+ {
+ "Ref": "BackEndImageHandlerCloudFrontDistributionB5464C90",
+ },
+ ],
+ },
+ ],
+ ],
+ },
+ },
+ },
+ "Effect": "Allow",
+ "Principal": {
+ "Service": "cloudfront.amazonaws.com",
+ },
+ "Resource": {
+ "Fn::GetAtt": [
+ "BackEndObjectLambdaAccessPointBEE6B960",
+ "Arn",
+ ],
+ },
+ },
+ ],
+ "Version": "2012-10-17",
+ },
+ },
+ "Type": "AWS::S3ObjectLambda::AccessPointPolicy",
+ },
+ "BackEndOlRequestModifierFunction7E5192E3": {
+ "Condition": "CommonResourcesEnableS3ObjectLambdaConditionF2C07DCD",
+ "Properties": {
+ "AutoPublish": true,
+ "FunctionCode": "// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+function handler(event) {
+ // Normalize accept header to only include values used on the backend
+ if(event.request.headers && event.request.headers.accept && event.request.headers.accept.value) {
+ event.request.headers.accept.value = event.request.headers.accept.value.indexOf("image/webp") > -1 ? "image/webp" : ""
+ }
+ event.request.querystring = processQueryParams(event.request.querystring).join('&')
+ return event.request;
+}
+
+function processQueryParams(querystring) {
+ if (querystring == null) {
+ return [];
+ }
+
+ const ALLOWED_PARAMS = ['signature', 'expires', 'format', 'fit', 'width', 'height', 'rotate', 'flip', 'flop', 'grayscale'];
+ const OL_PARAMS = {'signature': 'ol-signature', 'expires': 'ol-expires'};
+
+ let qs = [];
+ for (const key in querystring) {
+ if (!ALLOWED_PARAMS.includes(key)) {
+ continue;
+ }
+ const value = querystring[key];
+ const mappedKey = OL_PARAMS[key] || key;
+ qs.push(
+ value.multiValue
+ ? \`\${mappedKey}=\${value.multiValue[value.multiValue.length - 1].value}\`
+ : \`\${mappedKey}=\${value.value}\`
+ )
+ }
+
+ return qs.sort();
+}",
+ "FunctionConfig": {
+ "Comment": {
+ "Fn::Join": [
+ "",
+ [
+ "sih-ol-request-modifier-",
+ {
+ "Fn::GetAtt": [
+ "CommonResourcesCustomResourcesCustomResourceUuid64E7CCAD",
+ "UUID",
+ ],
+ },
+ ],
+ ],
+ },
+ "Runtime": "cloudfront-js-2.0",
+ },
+ "Name": {
+ "Fn::Join": [
+ "",
+ [
+ "sih-ol-request-modifier-",
+ {
+ "Fn::GetAtt": [
+ "CommonResourcesCustomResourcesCustomResourceUuid64E7CCAD",
+ "UUID",
+ ],
+ },
+ ],
+ ],
+ },
+ },
+ "Type": "AWS::CloudFront::Function",
+ },
+ "BackEndOlResponseModifierFunctionB47B3834": {
+ "Condition": "CommonResourcesEnableS3ObjectLambdaConditionF2C07DCD",
+ "Properties": {
+ "AutoPublish": true,
+ "FunctionCode": "// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+
+function handler(event) {
+ const response = event.response;
+
+ try {
+ Object.keys(response.headers).forEach(key => {
+ if (key.startsWith("x-amz-meta-") && key !== "x-amz-meta-statuscode") {
+ const headerName = key.replace("x-amz-meta-", "");
+ response.headers[headerName] = response.headers[key];
+ delete response.headers[key];
+ }
+ });
+
+ const statusCodeHeader = response.headers["x-amz-meta-statuscode"];
+ if (statusCodeHeader) {
+ const status = parseInt(statusCodeHeader.value);
+ if (status >= 400 && status <= 599) {
+ response.statusCode = status;
+ }
+
+ delete response.headers["x-amz-meta-statuscode"];
+ }
+ } catch (e) {
+ console.log("Error: ", e);
+ }
+ return response;
+}
+",
+ "FunctionConfig": {
+ "Comment": {
+ "Fn::Join": [
+ "",
+ [
+ "sih-ol-response-modifier-",
+ {
+ "Fn::GetAtt": [
+ "CommonResourcesCustomResourcesCustomResourceUuid64E7CCAD",
+ "UUID",
+ ],
+ },
+ ],
+ ],
+ },
+ "Runtime": "cloudfront-js-2.0",
+ },
+ "Name": {
+ "Fn::Join": [
+ "",
+ [
+ "sih-ol-response-modifier-",
+ {
+ "Fn::GetAtt": [
+ "CommonResourcesCustomResourcesCustomResourceUuid64E7CCAD",
+ "UUID",
+ ],
+ },
+ ],
+ ],
+ },
+ },
+ "Type": "AWS::CloudFront::Function",
+ },
+ "BackEndOriginRequestPolicy771345D7": {
+ "Properties": {
+ "OriginRequestPolicyConfig": {
+ "CookiesConfig": {
+ "CookieBehavior": "none",
+ },
+ "HeadersConfig": {
+ "HeaderBehavior": "whitelist",
+ "Headers": [
+ "origin",
+ "accept",
+ ],
+ },
+ "Name": {
+ "Fn::Join": [
+ "",
+ [
+ "ServerlessImageHandler-",
+ {
+ "Fn::GetAtt": [
+ "CommonResourcesCustomResourcesCustomResourceUuid64E7CCAD",
+ "UUID",
+ ],
+ },
+ ],
+ ],
+ },
+ "QueryStringsConfig": {
+ "QueryStringBehavior": "all",
+ },
+ },
+ },
+ "Type": "AWS::CloudFront::OriginRequestPolicy",
+ },
+ "BackEndSIHoriginaccesscontrolAFC8496A": {
+ "Condition": "CommonResourcesEnableS3ObjectLambdaConditionF2C07DCD",
+ "Properties": {
+ "OriginAccessControlConfig": {
+ "Name": {
+ "Fn::Join": [
+ "",
+ [
+ "SIH-origin-access-control-",
+ {
+ "Fn::GetAtt": [
+ "CommonResourcesCustomResourcesCustomResourceUuid64E7CCAD",
+ "UUID",
+ ],
+ },
+ ],
+ ],
+ },
+ "OriginAccessControlOriginType": "s3",
+ "SigningBehavior": "always",
+ "SigningProtocol": "sigv4",
+ },
+ },
+ "Type": "AWS::CloudFront::OriginAccessControl",
+ },
+ "BackEndSolutionMetricsBilledDurationMemorySizeQuery39F16D58": {
+ "Condition": "SendAnonymousStatistics",
+ "Properties": {
+ "LogGroupNames": [
+ {
+ "Ref": "BackEndImageHandlerLogGroupA0941EEC",
+ },
+ ],
+ "Name": {
+ "Fn::Join": [
+ "",
+ [
+ {
+ "Ref": "AWS::StackName",
+ },
+ "-BilledDurationMemorySizeQuery",
+ ],
+ ],
+ },
+ "QueryString": "stats sum(@billedDuration) as AWSLambdaBilledDuration, max(@memorySize) as AWSLambdaMemorySize",
+ },
+ "Type": "AWS::Logs::QueryDefinition",
+ },
+ "BackEndSolutionMetricsEventbridgeRuleToLambdaEventsRule05009025": {
+ "Condition": "SendAnonymousStatistics",
+ "Properties": {
+ "ScheduleExpression": {
+ "Fn::Join": [
+ "",
+ [
+ "cron(0 23 ? * ",
+ {
+ "Fn::If": [
+ "BackEndShortLogRetentionCondition72EA1A33",
+ "*",
+ "MON",
+ ],
+ },
+ " *)",
+ ],
+ ],
+ },
+ "State": "ENABLED",
+ "Tags": [
+ {
+ "Key": "SolutionId",
+ "Value": "S0ABC",
+ },
+ ],
+ "Targets": [
+ {
+ "Arn": {
+ "Fn::GetAtt": [
+ "BackEndSolutionMetricsMetricsLambdaF4FA4AF7",
+ "Arn",
+ ],
+ },
+ "Id": "Target0",
+ "InputTransformer": {
+ "InputPathsMap": {
+ "detail-type": "$.detail-type",
+ "time": "$.time",
+ },
+ "InputTemplate": {
+ "Fn::Join": [
+ "",
+ [
+ "{"detail-type": , "time": , "metrics-data-query": [{"MetricStat":{"Metric":{"Namespace":"AWS/Lambda","Dimensions":[{"Name":"FunctionName","Value":"",
+ {
+ "Ref": "BackEndImageHandlerLambdaFunctionADEF7FF2",
+ },
+ ""}],"MetricName":"Invocations"},"Stat":"Sum","Period":604800},"Id":"id_AWS_Lambda_Invocations"},{"MetricStat":{"Metric":{"Namespace":"AWS/CloudFront","Dimensions":[{"Name":"DistributionId","Value":"",
+ {
+ "Fn::If": [
+ "CommonResourcesUseExistingCloudFrontDistributionConditionEBC48184",
+ {
+ "Ref": "ExistingCloudFrontDistributionIdParameter",
+ },
+ {
+ "Fn::If": [
+ "CommonResourcesEnableS3ObjectLambdaConditionF2C07DCD",
+ {
+ "Ref": "BackEndImageHandlerCloudFrontDistributionB5464C90",
+ },
+ {
+ "Ref": "BackEndImageHandlerCloudFrontApiGatewayLambdaCloudFrontToApiGatewayCloudFrontDistribution03AA31B2",
+ },
+ ],
+ },
+ ],
+ },
+ ""},{"Name":"Region","Value":"Global"}],"MetricName":"Requests"},"Stat":"Sum","Period":604800},"region":"us-east-1","Id":"id_AWS_CloudFront_Requests"},{"MetricStat":{"Metric":{"Namespace":"AWS/CloudFront","Dimensions":[{"Name":"DistributionId","Value":"",
+ {
+ "Fn::If": [
+ "CommonResourcesUseExistingCloudFrontDistributionConditionEBC48184",
+ {
+ "Ref": "ExistingCloudFrontDistributionIdParameter",
+ },
+ {
+ "Fn::If": [
+ "CommonResourcesEnableS3ObjectLambdaConditionF2C07DCD",
+ {
+ "Ref": "BackEndImageHandlerCloudFrontDistributionB5464C90",
+ },
+ {
+ "Ref": "BackEndImageHandlerCloudFrontApiGatewayLambdaCloudFrontToApiGatewayCloudFrontDistribution03AA31B2",
+ },
+ ],
+ },
+ ],
+ },
+ ""},{"Name":"Region","Value":"Global"}],"MetricName":"BytesDownloaded"},"Stat":"Sum","Period":604800},"region":"us-east-1","Id":"id_AWS_CloudFront_BytesDownloaded"}]}",
+ ],
+ ],
+ },
+ },
+ },
+ ],
+ },
+ "Type": "AWS::Events::Rule",
+ },
+ "BackEndSolutionMetricsLambdaToSqsToLambdalambdatosqsqueue60A92083": {
+ "Condition": "SendAnonymousStatistics",
+ "DeletionPolicy": "Delete",
+ "Properties": {
+ "DelaySeconds": 900,
+ "KmsMasterKeyId": "alias/aws/sqs",
+ "MaximumMessageSize": 1024,
+ "MessageRetentionPeriod": 86400,
+ "ReceiveMessageWaitTimeSeconds": 20,
+ "Tags": [
+ {
+ "Key": "SolutionId",
+ "Value": "S0ABC",
+ },
+ ],
+ "VisibilityTimeout": 1020,
+ },
+ "Type": "AWS::SQS::Queue",
+ "UpdateReplacePolicy": "Delete",
+ },
+ "BackEndSolutionMetricsLambdaToSqsToLambdalambdatosqsqueuePolicy5B9B4D7F": {
+ "Condition": "SendAnonymousStatistics",
+ "Properties": {
+ "PolicyDocument": {
+ "Statement": [
+ {
+ "Action": [
+ "sqs:DeleteMessage",
+ "sqs:ReceiveMessage",
+ "sqs:SendMessage",
+ "sqs:GetQueueAttributes",
+ "sqs:RemovePermission",
+ "sqs:AddPermission",
+ "sqs:SetQueueAttributes",
+ ],
+ "Effect": "Allow",
+ "Principal": {
+ "AWS": {
+ "Fn::Join": [
+ "",
+ [
+ "arn:",
+ {
+ "Ref": "AWS::Partition",
+ },
+ ":iam::",
+ {
+ "Ref": "AWS::AccountId",
+ },
+ ":root",
+ ],
+ ],
+ },
+ },
+ "Resource": {
+ "Fn::GetAtt": [
+ "BackEndSolutionMetricsLambdaToSqsToLambdalambdatosqsqueue60A92083",
+ "Arn",
+ ],
+ },
+ "Sid": "QueueOwnerOnlyAccess",
+ },
+ {
+ "Action": "SQS:*",
+ "Condition": {
+ "Bool": {
+ "aws:SecureTransport": "false",
+ },
+ },
+ "Effect": "Deny",
+ "Principal": {
+ "AWS": "*",
+ },
+ "Resource": {
+ "Fn::GetAtt": [
+ "BackEndSolutionMetricsLambdaToSqsToLambdalambdatosqsqueue60A92083",
+ "Arn",
+ ],
+ },
+ "Sid": "HttpsOnly",
+ },
+ ],
+ "Version": "2012-10-17",
+ },
+ "Queues": [
+ {
+ "Ref": "BackEndSolutionMetricsLambdaToSqsToLambdalambdatosqsqueue60A92083",
+ },
+ ],
+ },
+ "Type": "AWS::SQS::QueuePolicy",
+ },
+ "BackEndSolutionMetricsMetricsLambdaAwsEventsLambdaInvokePermission1328BC090": {
+ "Condition": "SendAnonymousStatistics",
+ "Properties": {
+ "Action": "lambda:InvokeFunction",
+ "FunctionName": {
+ "Fn::GetAtt": [
+ "BackEndSolutionMetricsMetricsLambdaF4FA4AF7",
+ "Arn",
+ ],
+ },
+ "Principal": "events.amazonaws.com",
+ "SourceArn": {
+ "Fn::GetAtt": [
+ "BackEndSolutionMetricsEventbridgeRuleToLambdaEventsRule05009025",
+ "Arn",
+ ],
+ },
+ },
+ "Type": "AWS::Lambda::Permission",
+ },
+ "BackEndSolutionMetricsMetricsLambdaF4FA4AF7": {
+ "Condition": "SendAnonymousStatistics",
+ "DependsOn": [
+ "BackEndSolutionMetricsMetricsLambdaServiceRoleDefaultPolicyEBDDA47A",
+ "BackEndSolutionMetricsMetricsLambdaServiceRoleF4BC77CD",
+ ],
+ "Metadata": {
+ "cfn_nag": {
+ "rules_to_suppress": [
+ {
+ "id": "W89",
+ "reason": "Not in vpc",
+ },
+ {
+ "id": "W92",
+ "reason": "No need for ReservedConcurrentExecutions, does not support any application functional logic",
+ },
+ {
+ "id": "W58",
+ "reason": "The function does have permission to write CloudWatch Logs.",
+ },
+ {
+ "id": "W89",
+ "reason": "The Lambda function does not require any VPC connection at all.",
+ },
+ {
+ "id": "W92",
+ "reason": "The Lambda function does not require ReservedConcurrentExecutions.",
+ },
+ ],
+ },
+ },
+ "Properties": {
+ "Code": {
+ "S3Bucket": {
+ "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}",
+ },
+ "S3Key": "Omitted to remove snapshot dependency on hash",
+ },
+ "Description": "Metrics util",
+ "Environment": {
+ "Variables": {
+ "AWS_ACCOUNT_ID": {
+ "Ref": "AWS::AccountId",
+ },
+ "AWS_STACK_ID": {
+ "Ref": "AWS::StackId",
+ },
+ "EXECUTION_DAY": {
+ "Fn::If": [
+ "BackEndShortLogRetentionCondition72EA1A33",
+ "*",
+ "MON",
+ ],
+ },
+ "QUERY_PREFIX": {
+ "Fn::Join": [
+ "",
+ [
+ {
+ "Ref": "AWS::StackName",
+ },
+ "-",
+ ],
+ ],
+ },
+ "SOLUTION_ID": "SO0023",
+ "SOLUTION_NAME": "dynamic-image-transformation-for-amazon-cloudfront",
+ "SOLUTION_VERSION": "Omitted to remove snapshot dependency on solution version",
+ "SQS_QUEUE_URL": {
+ "Ref": "BackEndSolutionMetricsLambdaToSqsToLambdalambdatosqsqueue60A92083",
+ },
+ "UUID": {
+ "Fn::GetAtt": [
+ "CommonResourcesCustomResourcesCustomResourceUuid64E7CCAD",
+ "UUID",
+ ],
+ },
+ },
+ },
+ "Handler": "index.handler",
+ "LoggingConfig": {
+ "LogGroup": {
+ "Ref": "BackEndSolutionMetricsMetricsLambdaLogGroup7A09CAFB",
+ },
+ },
+ "MemorySize": 128,
+ "Role": {
+ "Fn::GetAtt": [
+ "BackEndSolutionMetricsMetricsLambdaServiceRoleF4BC77CD",
+ "Arn",
+ ],
+ },
+ "Runtime": "nodejs22.x",
+ "Tags": [
+ {
+ "Key": "SolutionId",
+ "Value": "S0ABC",
+ },
+ ],
+ "Timeout": 60,
+ },
+ "Type": "AWS::Lambda::Function",
+ },
+ "BackEndSolutionMetricsMetricsLambdaLogGroup7A09CAFB": {
+ "Condition": "SendAnonymousStatistics",
+ "DeletionPolicy": "Retain",
+ "Metadata": {
+ "guard": {
+ "SuppressedRules": [
+ "CLOUDWATCH_LOG_GROUP_ENCRYPTED",
+ ],
+ },
+ },
+ "Properties": {
+ "RetentionInDays": 3653,
+ "Tags": [
+ {
+ "Key": "SolutionId",
+ "Value": "S0ABC",
+ },
+ ],
+ },
+ "Type": "AWS::Logs::LogGroup",
+ "UpdateReplacePolicy": "Retain",
+ },
+ "BackEndSolutionMetricsMetricsLambdaServiceRoleDefaultPolicyEBDDA47A": {
+ "Condition": "SendAnonymousStatistics",
+ "Properties": {
+ "PolicyDocument": {
+ "Statement": [
+ {
+ "Action": [
+ "sqs:SendMessage",
+ "sqs:GetQueueAttributes",
+ "sqs:GetQueueUrl",
+ ],
+ "Effect": "Allow",
+ "Resource": {
+ "Fn::GetAtt": [
+ "BackEndSolutionMetricsLambdaToSqsToLambdalambdatosqsqueue60A92083",
+ "Arn",
+ ],
+ },
+ },
+ {
+ "Action": [
+ "sqs:ReceiveMessage",
+ "sqs:ChangeMessageVisibility",
+ "sqs:GetQueueUrl",
+ "sqs:DeleteMessage",
+ "sqs:GetQueueAttributes",
+ ],
+ "Effect": "Allow",
+ "Resource": {
+ "Fn::GetAtt": [
+ "BackEndSolutionMetricsLambdaToSqsToLambdalambdatosqsqueue60A92083",
+ "Arn",
+ ],
+ },
+ },
+ {
+ "Action": "cloudwatch:GetMetricData",
+ "Effect": "Allow",
+ "Resource": "*",
+ },
+ {
+ "Action": [
+ "logs:StartQuery",
+ "logs:GetQueryResults",
+ ],
+ "Effect": "Allow",
+ "Resource": {
+ "Fn::GetAtt": [
+ "BackEndImageHandlerLogGroupA0941EEC",
+ "Arn",
+ ],
+ },
+ },
+ {
+ "Action": "logs:DescribeQueryDefinitions",
+ "Effect": "Allow",
+ "Resource": "*",
+ },
+ ],
+ "Version": "2012-10-17",
+ },
+ "PolicyName": "BackEndSolutionMetricsMetricsLambdaServiceRoleDefaultPolicyEBDDA47A",
+ "Roles": [
+ {
+ "Ref": "BackEndSolutionMetricsMetricsLambdaServiceRoleF4BC77CD",
+ },
+ ],
+ },
+ "Type": "AWS::IAM::Policy",
+ },
+ "BackEndSolutionMetricsMetricsLambdaServiceRoleF4BC77CD": {
+ "Condition": "SendAnonymousStatistics",
+ "Properties": {
+ "AssumeRolePolicyDocument": {
+ "Statement": [
+ {
+ "Action": "sts:AssumeRole",
+ "Effect": "Allow",
+ "Principal": {
+ "Service": "lambda.amazonaws.com",
+ },
+ },
+ ],
+ "Version": "2012-10-17",
+ },
+ "ManagedPolicyArns": [
+ {
+ "Fn::Join": [
+ "",
+ [
+ "arn:",
+ {
+ "Ref": "AWS::Partition",
+ },
+ ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole",
+ ],
+ ],
+ },
+ ],
+ "Tags": [
+ {
+ "Key": "SolutionId",
+ "Value": "S0ABC",
+ },
+ ],
+ },
+ "Type": "AWS::IAM::Role",
+ },
+ "BackEndSolutionMetricsMetricsLambdaSqsEventSourceTestStackBackEndSolutionMetricsLambdaToSqsToLambdalambdatosqsqueueC02C743365EF89F7": {
+ "Condition": "SendAnonymousStatistics",
+ "DependsOn": [
+ "BackEndEventSourceMappingResolver0ACBB140",
+ ],
+ "Properties": {
+ "EventSourceArn": {
+ "Fn::GetAtt": [
+ "BackEndSolutionMetricsLambdaToSqsToLambdalambdatosqsqueue60A92083",
+ "Arn",
+ ],
+ },
+ "FunctionName": {
+ "Ref": "BackEndSolutionMetricsMetricsLambdaF4FA4AF7",
+ },
+ "Tags": [
+ {
+ "Key": "SolutionId",
+ "Value": "S0ABC",
+ },
+ ],
+ },
+ "Type": "AWS::Lambda::EventSourceMapping",
+ },
+ "BackEndSolutionMetricsRequestInfoQueryB4BC2094": {
+ "Condition": "SendAnonymousStatistics",
+ "Properties": {
+ "LogGroupNames": [
+ {
+ "Ref": "BackEndImageHandlerLogGroupA0941EEC",
+ },
+ ],
+ "Name": {
+ "Fn::Join": [
+ "",
+ [
+ {
+ "Ref": "AWS::StackName",
+ },
+ "-RequestInfoQuery",
+ ],
+ ],
+ },
+ "QueryString": "parse @message "requestType: 'Default'" as DefaultRequests
+| parse @message "requestType: 'Thumbor'" as ThumborRequests
+| parse @message "requestType: 'Custom'" as CustomRequests
+| parse @message "Query param edits:" as QueryParamRequests
+| parse @message "expires" as ExpiresRequests
+| stats count(DefaultRequests) as DefaultRequestsCount, count(ThumborRequests) as ThumborRequestsCount, count(CustomRequests) as CustomRequestsCount, count(QueryParamRequests) as QueryParamRequestsCount, count(ExpiresRequests) as ExpiresRequestsCount",
+ },
+ "Type": "AWS::Logs::QueryDefinition",
+ },
+ "BackEndWriteGetObjectResponsePolicyF3008955": {
+ "Condition": "CommonResourcesEnableS3ObjectLambdaConditionF2C07DCD",
+ "Properties": {
+ "PolicyDocument": {
+ "Statement": [
+ {
+ "Action": "s3-object-lambda:WriteGetObjectResponse",
+ "Effect": "Allow",
+ "Resource": {
+ "Fn::GetAtt": [
+ "BackEndObjectLambdaAccessPointBEE6B960",
+ "Arn",
+ ],
+ },
+ },
+ ],
+ "Version": "2012-10-17",
+ },
+ "PolicyName": "BackEndWriteGetObjectResponsePolicyF3008955",
+ "Roles": [
+ {
+ "Ref": "BackEndImageHandlerFunctionRoleABF81E5C",
+ },
+ ],
+ },
+ "Type": "AWS::IAM::Policy",
+ },
+ "CommonResourcesCustomResourcesCustomResourceAnonymousMetric51363F57": {
+ "DeletionPolicy": "Delete",
+ "Properties": {
+ "AnonymousData": {
+ "Fn::FindInMap": [
+ "Solution",
+ "Config",
+ "AnonymousUsage",
+ ],
+ },
+ "AutoWebP": {
+ "Ref": "AutoWebPParameter",
+ },
+ "CorsEnabled": {
+ "Ref": "CorsEnabledParameter",
+ },
+ "CustomAction": "sendMetric",
+ "DeployDemoUi": {
+ "Ref": "DeployDemoUIParameter",
+ },
+ "EnableDefaultFallbackImage": {
+ "Ref": "EnableDefaultFallbackImageParameter",
+ },
+ "EnableS3ObjectLambda": {
+ "Ref": "EnableS3ObjectLambdaParameter",
+ },
+ "EnableSignature": {
+ "Ref": "EnableSignatureParameter",
+ },
+ "LogRetentionPeriod": {
+ "Ref": "LogRetentionPeriodParameter",
+ },
+ "OriginShieldRegion": {
+ "Ref": "OriginShieldRegionParameter",
+ },
+ "Region": {
+ "Ref": "AWS::Region",
+ },
+ "ServiceToken": {
+ "Fn::GetAtt": [
+ "CommonResourcesCustomResourcesCustomResourceFunction0D924235",
+ "Arn",
+ ],
+ },
+ "SourceBuckets": {
+ "Ref": "SourceBucketsParameter",
+ },
+ "UUID": {
+ "Fn::GetAtt": [
+ "CommonResourcesCustomResourcesCustomResourceUuid64E7CCAD",
+ "UUID",
+ ],
+ },
+ "UseExistingCloudFrontDistribution": {
+ "Ref": "UseExistingCloudFrontDistributionParameter",
+ },
+ },
+ "Type": "AWS::CloudFormation::CustomResource",
+ "UpdateReplacePolicy": "Delete",
+ },
+ "CommonResourcesCustomResourcesCustomResourceCheckFallbackImage6CE45571": {
+ "Condition": "CommonResourcesEnableDefaultFallbackImageConditionD1A10983",
+ "DeletionPolicy": "Delete",
+ "Properties": {
+ "CustomAction": "checkFallbackImage",
+ "FallbackImageS3Bucket": {
+ "Ref": "FallbackImageS3BucketParameter",
+ },
+ "FallbackImageS3Key": {
+ "Ref": "FallbackImageS3KeyParameter",
+ },
+ "ServiceToken": {
+ "Fn::GetAtt": [
+ "CommonResourcesCustomResourcesCustomResourceFunction0D924235",
+ "Arn",
+ ],
+ },
+ },
+ "Type": "AWS::CloudFormation::CustomResource",
+ "UpdateReplacePolicy": "Delete",
+ },
+ "CommonResourcesCustomResourcesCustomResourceCheckFirstBucketRegionE663CC31": {
+ "DeletionPolicy": "Delete",
+ "Properties": {
+ "CustomAction": "checkFirstBucketRegion",
+ "Region": {
+ "Ref": "AWS::Region",
+ },
+ "S3ObjectLambda": {
+ "Ref": "EnableS3ObjectLambdaParameter",
+ },
+ "ServiceToken": {
+ "Fn::GetAtt": [
+ "CommonResourcesCustomResourcesCustomResourceFunction0D924235",
+ "Arn",
+ ],
+ },
+ "SourceBuckets": {
+ "Fn::Select": [
+ 0,
+ {
+ "Fn::Split": [
+ ",",
+ {
+ "Ref": "SourceBucketsParameter",
+ },
+ ],
+ },
+ ],
+ },
+ "UUID": {
+ "Fn::GetAtt": [
+ "CommonResourcesCustomResourcesCustomResourceUuid64E7CCAD",
+ "UUID",
+ ],
+ },
+ },
+ "Type": "AWS::CloudFormation::CustomResource",
+ "UpdateReplacePolicy": "Delete",
+ },
+ "CommonResourcesCustomResourcesCustomResourceCheckSecretsManagerAEEEC776": {
+ "Condition": "CommonResourcesEnableSignatureCondition909DC7A1",
+ "DeletionPolicy": "Delete",
+ "Properties": {
+ "CustomAction": "checkSecretsManager",
+ "SecretsManagerKey": {
+ "Ref": "SecretsManagerKeyParameter",
+ },
+ "SecretsManagerName": {
+ "Ref": "SecretsManagerSecretParameter",
+ },
+ "ServiceToken": {
+ "Fn::GetAtt": [
+ "CommonResourcesCustomResourcesCustomResourceFunction0D924235",
+ "Arn",
+ ],
+ },
+ },
+ "Type": "AWS::CloudFormation::CustomResource",
+ "UpdateReplacePolicy": "Delete",
+ },
+ "CommonResourcesCustomResourcesCustomResourceCheckSourceBucketsA313C9B7": {
+ "DeletionPolicy": "Delete",
+ "Properties": {
+ "CustomAction": "checkSourceBuckets",
+ "Region": {
+ "Ref": "AWS::Region",
+ },
+ "ServiceToken": {
+ "Fn::GetAtt": [
+ "CommonResourcesCustomResourcesCustomResourceFunction0D924235",
+ "Arn",
+ ],
+ },
+ "SourceBuckets": {
+ "Ref": "SourceBucketsParameter",
+ },
+ },
+ "Type": "AWS::CloudFormation::CustomResource",
+ "UpdateReplacePolicy": "Delete",
+ },
+ "CommonResourcesCustomResourcesCustomResourceFunction0D924235": {
+ "DependsOn": [
+ "CommonResourcesCustomResourcesCustomResourceRole8958A1ED",
+ ],
+ "Metadata": {
+ "cfn_nag": {
+ "rules_to_suppress": [
+ {
+ "id": "W58",
+ "reason": "The function does have permission to write CloudWatch Logs.",
+ },
+ {
+ "id": "W89",
+ "reason": "The Lambda function does not require any VPC connection at all.",
+ },
+ {
+ "id": "W92",
+ "reason": "The Lambda function does not require ReservedConcurrentExecutions.",
+ },
+ ],
+ },
+ },
+ "Properties": {
+ "Code": {
+ "S3Bucket": {
+ "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}",
+ },
+ "S3Key": "Omitted to remove snapshot dependency on hash",
+ },
+ "Description": "dit (v7.0.1): Custom resource",
+ "Environment": {
+ "Variables": {
+ "RETRY_SECONDS": "5",
+ "SOLUTION_ID": "S0ABC",
+ "SOLUTION_VERSION": "Omitted to remove snapshot dependency on solution version",
+ },
+ },
+ "Handler": "index.handler",
+ "MemorySize": 128,
+ "Role": {
+ "Fn::GetAtt": [
+ "CommonResourcesCustomResourcesCustomResourceRole8958A1ED",
+ "Arn",
+ ],
+ },
+ "Runtime": "nodejs22.x",
+ "Tags": [
+ {
+ "Key": "SolutionId",
+ "Value": "S0ABC",
+ },
+ ],
+ "Timeout": 60,
+ },
+ "Type": "AWS::Lambda::Function",
+ },
+ "CommonResourcesCustomResourcesCustomResourceRole8958A1ED": {
+ "Metadata": {
+ "cfn_nag": {
+ "rules_to_suppress": [
+ {
+ "id": "W11",
+ "reason": "Allow '*' because it is required for making DescribeRegions API call as it doesn't support resource-level permissions and require to choose all resources.",
+ },
+ {
+ "id": "F10",
+ "reason": "Using inline policy",
+ },
+ ],
+ },
+ },
+ "Properties": {
+ "AssumeRolePolicyDocument": {
+ "Statement": [
+ {
+ "Action": "sts:AssumeRole",
+ "Effect": "Allow",
+ "Principal": {
+ "Service": "lambda.amazonaws.com",
+ },
+ },
+ ],
+ "Version": "2012-10-17",
+ },
+ "Path": "/",
+ "Policies": [
+ {
+ "PolicyDocument": {
+ "Statement": [
+ {
+ "Action": [
+ "logs:CreateLogGroup",
+ "logs:CreateLogStream",
+ "logs:PutLogEvents",
+ ],
+ "Effect": "Allow",
+ "Resource": {
+ "Fn::Join": [
+ "",
+ [
+ "arn:",
+ {
+ "Ref": "AWS::Partition",
+ },
+ ":logs:",
+ {
+ "Ref": "AWS::Region",
+ },
+ ":",
+ {
+ "Ref": "AWS::AccountId",
+ },
+ ":log-group:/aws/lambda/*",
+ ],
+ ],
+ },
+ },
+ ],
+ "Version": "2012-10-17",
+ },
+ "PolicyName": "CloudWatchLogsPolicy",
+ },
+ {
+ "PolicyDocument": {
+ "Statement": [
+ {
+ "Action": [
+ "s3:ListBucket",
+ "s3:GetBucketLocation",
+ ],
+ "Effect": "Allow",
+ "Resource": {
+ "Fn::Split": [
+ ",",
+ {
+ "Fn::Sub": [
+ "arn:aws:s3:::\${rest}",
+ {
+ "rest": {
+ "Fn::Join": [
+ ",arn:aws:s3:::",
+ {
+ "Fn::Split": [
+ ",",
+ {
+ "Fn::Join": [
+ "",
+ {
+ "Fn::Split": [
+ " ",
+ {
+ "Ref": "SourceBucketsParameter",
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ },
+ ],
+ },
+ ],
+ },
+ },
+ {
+ "Action": "s3:GetObject",
+ "Effect": "Allow",
+ "Resource": {
+ "Fn::Join": [
+ "",
+ [
+ "arn:aws:s3:::",
+ {
+ "Ref": "FallbackImageS3BucketParameter",
+ },
+ "/",
+ {
+ "Ref": "FallbackImageS3KeyParameter",
+ },
+ ],
+ ],
+ },
+ },
+ {
+ "Action": [
+ "s3:putBucketAcl",
+ "s3:putEncryptionConfiguration",
+ "s3:putBucketPolicy",
+ "s3:CreateBucket",
+ "s3:PutBucketOwnershipControls",
+ "s3:PutBucketTagging",
+ "s3:PutBucketVersioning",
+ ],
+ "Effect": "Allow",
+ "Resource": {
+ "Fn::Join": [
+ "",
+ [
+ "arn:",
+ {
+ "Ref": "AWS::Partition",
+ },
+ ":s3:::*",
+ ],
+ ],
+ },
+ },
+ {
+ "Action": "s3:ListBucket",
+ "Effect": "Allow",
+ "Resource": "arn:aws:s3:::sih-dummy-*",
+ },
+ ],
+ "Version": "2012-10-17",
+ },
+ "PolicyName": "S3AccessPolicy",
+ },
+ {
+ "PolicyDocument": {
+ "Statement": [
+ {
+ "Action": "ec2:DescribeRegions",
+ "Effect": "Allow",
+ "Resource": "*",
+ },
+ ],
+ "Version": "2012-10-17",
+ },
+ "PolicyName": "EC2Policy",
+ },
+ {
+ "PolicyDocument": {
+ "Statement": [
+ {
+ "Action": "cloudfront:GetDistribution",
+ "Effect": "Allow",
+ "Resource": {
+ "Fn::Join": [
+ "",
+ [
+ "arn:",
+ {
+ "Ref": "AWS::Partition",
+ },
+ ":cloudfront::",
+ {
+ "Ref": "AWS::AccountId",
+ },
+ ":distribution/",
+ {
+ "Ref": "ExistingCloudFrontDistributionIdParameter",
+ },
+ ],
+ ],
+ },
+ },
+ ],
+ "Version": "2012-10-17",
+ },
+ "PolicyName": "ExistingDistributionPolicy",
+ },
+ ],
+ "Tags": [
+ {
+ "Key": "SolutionId",
+ "Value": "S0ABC",
+ },
+ ],
+ },
+ "Type": "AWS::IAM::Role",
+ },
+ "CommonResourcesCustomResourcesCustomResourceUuid64E7CCAD": {
+ "DeletionPolicy": "Delete",
+ "Properties": {
+ "CustomAction": "createUuid",
+ "Region": {
+ "Ref": "AWS::Region",
+ },
+ "ServiceToken": {
+ "Fn::GetAtt": [
+ "CommonResourcesCustomResourcesCustomResourceFunction0D924235",
+ "Arn",
+ ],
+ },
+ },
+ "Type": "AWS::CloudFormation::CustomResource",
+ "UpdateReplacePolicy": "Delete",
+ },
+ "CommonResourcesCustomResourcesCustomResourceValidateExistingDistribution34A6673C": {
+ "Condition": "CommonResourcesUseExistingCloudFrontDistributionConditionEBC48184",
+ "DeletionPolicy": "Delete",
+ "Properties": {
+ "CustomAction": "validateExistingDistribution",
+ "ExistingDistributionID": {
+ "Ref": "ExistingCloudFrontDistributionIdParameter",
+ },
+ "Region": {
+ "Ref": "AWS::Region",
+ },
+ "ServiceToken": {
+ "Fn::GetAtt": [
+ "CommonResourcesCustomResourcesCustomResourceFunction0D924235",
+ "Arn",
+ ],
+ },
+ },
+ "Type": "AWS::CloudFormation::CustomResource",
+ "UpdateReplacePolicy": "Delete",
+ },
+ "CommonResourcesCustomResourcesDeployWebsiteAwsCliLayerBC025F39": {
+ "Condition": "CommonResourcesDeployDemoUICondition308D3B09",
+ "Properties": {
+ "Content": {
+ "S3Bucket": {
+ "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}",
+ },
+ "S3Key": "Omitted to remove snapshot dependency on hash",
+ },
+ "Description": "/opt/awscli/aws",
+ },
+ "Type": "AWS::Lambda::LayerVersion",
+ },
+ "CommonResourcesCustomResourcesDeployWebsiteCustomResourceECB9B136": {
+ "Condition": "CommonResourcesDeployDemoUICondition308D3B09",
+ "DeletionPolicy": "Delete",
+ "Properties": {
+ "DestinationBucketName": {
+ "Ref": "FrontEndDistributionToS3S3Bucket3A171D78",
+ },
+ "Exclude": [
+ "demo-ui-config.js",
+ ],
+ "OutputObjectKeys": true,
+ "Prune": true,
+ "ServiceToken": {
+ "Fn::GetAtt": [
+ "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C81C01536",
+ "Arn",
+ ],
+ },
+ "SourceBucketNames": [
+ {
+ "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}",
+ },
+ ],
+ "SourceObjectKeys": [
+ "Omitted to remove snapshot dependency on demo ui module hash",
+ ],
+ "WaitForDistributionInvalidation": true,
+ },
+ "Type": "Custom::CDKBucketDeployment",
+ "UpdateReplacePolicy": "Delete",
+ },
+ "CommonResourcesCustomResourcesLogBucketCustomResource2445A3AB": {
+ "DeletionPolicy": "Delete",
+ "Properties": {
+ "BucketSuffix": {
+ "Fn::Join": [
+ "",
+ [
+ {
+ "Ref": "AWS::StackName",
+ },
+ "-",
+ {
+ "Ref": "AWS::Region",
+ },
+ "-",
+ {
+ "Ref": "AWS::AccountId",
+ },
+ ],
+ ],
+ },
+ "CustomAction": "createCloudFrontLoggingBucket",
+ "ServiceToken": {
+ "Fn::GetAtt": [
+ "CommonResourcesCustomResourcesCustomResourceFunction0D924235",
+ "Arn",
+ ],
+ },
+ },
+ "Type": "AWS::CloudFormation::CustomResource",
+ "UpdateReplacePolicy": "Delete",
+ },
+ "CommonResourcesCustomResourcesPutWebsiteConfigC4E435F3": {
+ "Condition": "CommonResourcesDeployDemoUICondition308D3B09",
+ "DeletionPolicy": "Delete",
+ "Properties": {
+ "ConfigItem": {
+ "apiEndpoint": {
+ "Fn::If": [
+ "CommonResourcesUseExistingCloudFrontDistributionConditionEBC48184",
+ {
+ "Fn::Join": [
+ "",
+ [
+ "https://",
+ {
+ "Fn::GetAtt": [
+ "CommonResourcesCustomResourcesCustomResourceValidateExistingDistribution34A6673C",
+ "DistributionDomainName",
+ ],
+ },
+ ],
+ ],
+ },
+ {
+ "Fn::If": [
+ "CommonResourcesDisableS3ObjectLambdaCondition017AC33C",
+ {
+ "Fn::Join": [
+ "",
+ [
+ "https://",
+ {
+ "Fn::If": [
+ "CommonResourcesUseExistingCloudFrontDistributionConditionEBC48184",
+ "",
+ {
+ "Fn::GetAtt": [
+ "BackEndImageHandlerCloudFrontApiGatewayLambdaCloudFrontToApiGatewayCloudFrontDistribution03AA31B2",
+ "DomainName",
+ ],
+ },
+ ],
+ },
+ ],
+ ],
+ },
+ {
+ "Fn::Join": [
+ "",
+ [
+ "https://",
+ {
+ "Fn::If": [
+ "CommonResourcesUseExistingCloudFrontDistributionConditionEBC48184",
+ "",
+ {
+ "Fn::GetAtt": [
+ "BackEndImageHandlerCloudFrontDistributionB5464C90",
+ "DomainName",
+ ],
+ },
+ ],
+ },
+ ],
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ },
+ "CustomAction": "putConfigFile",
+ "DestS3Bucket": {
+ "Ref": "FrontEndDistributionToS3S3Bucket3A171D78",
+ },
+ "DestS3key": "demo-ui-config.js",
+ "Region": {
+ "Ref": "AWS::Region",
+ },
+ "ServiceToken": {
+ "Fn::GetAtt": [
+ "CommonResourcesCustomResourcesCustomResourceFunction0D924235",
+ "Arn",
+ ],
+ },
+ },
+ "Type": "AWS::CloudFormation::CustomResource",
+ "UpdateReplacePolicy": "Delete",
+ },
+ "CommonResourcesCustomResourcesWebsiteHostingBucketPolicy3C526944": {
+ "Condition": "CommonResourcesDeployDemoUICondition308D3B09",
+ "Properties": {
+ "PolicyDocument": {
+ "Statement": [
+ {
+ "Action": [
+ "s3:GetObject",
+ "s3:PutObject",
+ ],
+ "Effect": "Allow",
+ "Resource": {
+ "Fn::Join": [
+ "",
+ [
+ {
+ "Fn::GetAtt": [
+ "FrontEndDistributionToS3S3Bucket3A171D78",
+ "Arn",
+ ],
+ },
+ "/*",
+ ],
+ ],
+ },
+ },
+ ],
+ "Version": "2012-10-17",
+ },
+ "PolicyName": "CommonResourcesCustomResourcesWebsiteHostingBucketPolicy3C526944",
+ "Roles": [
+ {
+ "Ref": "CommonResourcesCustomResourcesCustomResourceRole8958A1ED",
+ },
+ ],
+ },
+ "Type": "AWS::IAM::Policy",
+ },
+ "CommonResourcesSecretsManagerPolicy45FE005E": {
+ "Condition": "CommonResourcesEnableSignatureCondition909DC7A1",
+ "Properties": {
+ "PolicyDocument": {
+ "Statement": [
+ {
+ "Action": "secretsmanager:GetSecretValue",
+ "Effect": "Allow",
+ "Resource": {
+ "Fn::Join": [
+ "",
+ [
+ "arn:",
+ {
+ "Ref": "AWS::Partition",
+ },
+ ":secretsmanager:",
+ {
+ "Ref": "AWS::Region",
+ },
+ ":",
+ {
+ "Ref": "AWS::AccountId",
+ },
+ ":secret:",
+ {
+ "Ref": "SecretsManagerSecretParameter",
+ },
+ "*",
+ ],
+ ],
+ },
+ },
+ ],
+ "Version": "2012-10-17",
+ },
+ "PolicyName": "CommonResourcesSecretsManagerPolicy45FE005E",
+ "Roles": [
+ {
+ "Ref": "CommonResourcesCustomResourcesCustomResourceRole8958A1ED",
+ },
+ {
+ "Ref": "BackEndImageHandlerFunctionRoleABF81E5C",
+ },
+ ],
+ },
+ "Type": "AWS::IAM::Policy",
+ },
+ "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C81C01536": {
+ "Condition": "CommonResourcesDeployDemoUICondition308D3B09",
+ "DependsOn": [
+ "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRoleDefaultPolicy88902FDF",
+ "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRole89A01265",
+ ],
+ "Metadata": {
+ "cfn_nag": {
+ "rules_to_suppress": [
+ {
+ "id": "W58",
+ "reason": "The function does have permission to write CloudWatch Logs.",
+ },
+ {
+ "id": "W89",
+ "reason": "The Lambda function does not require any VPC connection at all.",
+ },
+ {
+ "id": "W92",
+ "reason": "The Lambda function does not require ReservedConcurrentExecutions.",
+ },
+ ],
+ },
+ },
+ "Properties": {
+ "Code": {
+ "S3Bucket": {
+ "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}",
+ },
+ "S3Key": "Omitted to remove snapshot dependency on hash",
+ },
+ "Environment": {
+ "Variables": {
+ "AWS_CA_BUNDLE": "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem",
+ },
+ },
+ "Handler": "index.handler",
+ "Layers": [
+ {
+ "Ref": "CommonResourcesCustomResourcesDeployWebsiteAwsCliLayerBC025F39",
+ },
+ ],
+ "Role": {
+ "Fn::GetAtt": [
+ "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRole89A01265",
+ "Arn",
+ ],
+ },
+ "Runtime": "python3.13",
+ "Tags": [
+ {
+ "Key": "SolutionId",
+ "Value": "S0ABC",
+ },
+ ],
+ "Timeout": 900,
+ },
+ "Type": "AWS::Lambda::Function",
+ },
+ "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRole89A01265": {
+ "Condition": "CommonResourcesDeployDemoUICondition308D3B09",
+ "Properties": {
+ "AssumeRolePolicyDocument": {
+ "Statement": [
+ {
+ "Action": "sts:AssumeRole",
+ "Effect": "Allow",
+ "Principal": {
+ "Service": "lambda.amazonaws.com",
+ },
+ },
+ ],
+ "Version": "2012-10-17",
+ },
+ "ManagedPolicyArns": [
+ {
+ "Fn::Join": [
+ "",
+ [
+ "arn:",
+ {
+ "Ref": "AWS::Partition",
+ },
+ ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole",
+ ],
+ ],
+ },
+ ],
+ "Tags": [
+ {
+ "Key": "SolutionId",
+ "Value": "S0ABC",
+ },
+ ],
+ },
+ "Type": "AWS::IAM::Role",
+ },
+ "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRoleDefaultPolicy88902FDF": {
+ "Condition": "CommonResourcesDeployDemoUICondition308D3B09",
+ "Properties": {
+ "PolicyDocument": {
+ "Statement": [
+ {
+ "Action": [
+ "s3:GetObject*",
+ "s3:GetBucket*",
+ "s3:List*",
+ ],
+ "Effect": "Allow",
+ "Resource": [
+ {
+ "Fn::Join": [
+ "",
+ [
+ "arn:",
+ {
+ "Ref": "AWS::Partition",
+ },
+ ":s3:::",
+ {
+ "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}",
+ },
+ ],
+ ],
+ },
+ {
+ "Fn::Join": [
+ "",
+ [
+ "arn:",
+ {
+ "Ref": "AWS::Partition",
+ },
+ ":s3:::",
+ {
+ "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}",
+ },
+ "/*",
+ ],
+ ],
+ },
+ ],
+ },
+ {
+ "Action": [
+ "s3:GetObject*",
+ "s3:GetBucket*",
+ "s3:List*",
+ "s3:DeleteObject*",
+ "s3:PutObject",
+ "s3:PutObjectLegalHold",
+ "s3:PutObjectRetention",
+ "s3:PutObjectTagging",
+ "s3:PutObjectVersionTagging",
+ "s3:Abort*",
+ ],
+ "Effect": "Allow",
+ "Resource": [
+ {
+ "Fn::GetAtt": [
+ "FrontEndDistributionToS3S3Bucket3A171D78",
+ "Arn",
+ ],
+ },
+ {
+ "Fn::Join": [
+ "",
+ [
+ {
+ "Fn::GetAtt": [
+ "FrontEndDistributionToS3S3Bucket3A171D78",
+ "Arn",
+ ],
+ },
+ "/*",
+ ],
+ ],
+ },
+ ],
+ },
+ ],
+ "Version": "2012-10-17",
+ },
+ "PolicyName": "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRoleDefaultPolicy88902FDF",
+ "Roles": [
+ {
+ "Ref": "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRole89A01265",
+ },
+ ],
+ },
+ "Type": "AWS::IAM::Policy",
+ },
+ "FrontEndDistributionToS3CloudFrontDistribution15FE13D0": {
+ "Condition": "CommonResourcesDeployDemoUICondition308D3B09",
+ "Metadata": {
+ "cfn_nag": {
+ "rules_to_suppress": [
+ {
+ "id": "W70",
+ "reason": "Since the distribution uses the CloudFront domain name, CloudFront automatically sets the security policy to TLSv1 regardless of the value of MinimumProtocolVersion",
+ },
+ ],
+ },
+ },
+ "Properties": {
+ "DistributionConfig": {
+ "Comment": "Demo UI Distribution for Dynamic Image Transformation for Amazon CloudFront",
+ "CustomErrorResponses": [
+ {
+ "ErrorCode": 403,
+ "ResponseCode": 200,
+ "ResponsePagePath": "/index.html",
+ },
+ {
+ "ErrorCode": 404,
+ "ResponseCode": 200,
+ "ResponsePagePath": "/index.html",
+ },
+ ],
+ "DefaultCacheBehavior": {
+ "CachePolicyId": "658327ea-f89d-4fab-a63d-7e88639e58f6",
+ "Compress": true,
+ "TargetOriginId": "TestStackFrontEndDistributionToS3CloudFrontDistributionOrigin12FCDC222",
+ "ViewerProtocolPolicy": "redirect-to-https",
+ },
+ "DefaultRootObject": "index.html",
+ "Enabled": true,
+ "HttpVersion": "http2",
+ "IPV6Enabled": true,
+ "Logging": {
+ "Bucket": {
+ "Fn::Join": [
+ "",
+ [
+ {
+ "Fn::GetAtt": [
+ "CommonResourcesCustomResourcesLogBucketCustomResource2445A3AB",
+ "BucketName",
+ ],
+ },
+ ".s3.",
+ {
+ "Fn::GetAtt": [
+ "CommonResourcesCustomResourcesLogBucketCustomResource2445A3AB",
+ "Region",
+ ],
+ },
+ ".",
+ {
+ "Ref": "AWS::URLSuffix",
+ },
+ ],
+ ],
+ },
+ "Prefix": "ui-cloudfront/",
+ },
+ "Origins": [
+ {
+ "DomainName": {
+ "Fn::GetAtt": [
+ "FrontEndDistributionToS3S3Bucket3A171D78",
+ "RegionalDomainName",
+ ],
+ },
+ "Id": "TestStackFrontEndDistributionToS3CloudFrontDistributionOrigin12FCDC222",
+ "OriginAccessControlId": {
+ "Fn::GetAtt": [
+ "FrontEndDistributionToS3CloudFrontOac2BE9C90D",
+ "Id",
+ ],
+ },
+ "S3OriginConfig": {
+ "OriginAccessIdentity": "",
+ },
+ },
+ ],
+ },
+ "Tags": [
+ {
+ "Key": "SolutionId",
+ "Value": "S0ABC",
+ },
+ ],
+ },
+ "Type": "AWS::CloudFront::Distribution",
+ },
+ "FrontEndDistributionToS3CloudFrontOac2BE9C90D": {
+ "Condition": "CommonResourcesDeployDemoUICondition308D3B09",
+ "Properties": {
+ "OriginAccessControlConfig": {
+ "Description": "Origin access control provisioned by aws-cloudfront-s3",
+ "Name": {
+ "Fn::Join": [
+ "",
+ [
+ "aws-cloudfront-s3-DistnToS3-",
+ {
+ "Fn::Select": [
+ 2,
+ {
+ "Fn::Split": [
+ "/",
+ {
+ "Ref": "AWS::StackId",
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ ],
+ },
+ "OriginAccessControlOriginType": "s3",
+ "SigningBehavior": "always",
+ "SigningProtocol": "sigv4",
+ },
+ },
+ "Type": "AWS::CloudFront::OriginAccessControl",
+ },
+ "FrontEndDistributionToS3S3Bucket3A171D78": {
+ "Condition": "CommonResourcesDeployDemoUICondition308D3B09",
+ "DeletionPolicy": "Retain",
+ "Metadata": {
+ "cfn_nag": {
+ "rules_to_suppress": [
+ {
+ "id": "W35",
+ "reason": "This S3 bucket does not require access logging.",
+ },
+ ],
+ },
+ },
+ "Properties": {
+ "BucketEncryption": {
+ "ServerSideEncryptionConfiguration": [
+ {
+ "ServerSideEncryptionByDefault": {
+ "SSEAlgorithm": "AES256",
+ },
+ },
+ ],
+ },
+ "LifecycleConfiguration": {
+ "Rules": [
+ {
+ "NoncurrentVersionTransitions": [
+ {
+ "StorageClass": "GLACIER",
+ "TransitionInDays": 90,
+ },
+ ],
+ "Status": "Enabled",
+ },
+ ],
+ },
+ "PublicAccessBlockConfiguration": {
+ "BlockPublicAcls": true,
+ "BlockPublicPolicy": true,
+ "IgnorePublicAcls": true,
+ "RestrictPublicBuckets": true,
+ },
+ "Tags": [
+ {
+ "Key": "aws-cdk:cr-owned:d2c34063",
+ "Value": "true",
+ },
+ {
+ "Key": "SolutionId",
+ "Value": "S0ABC",
+ },
+ ],
+ "VersioningConfiguration": {
+ "Status": "Enabled",
+ },
+ },
+ "Type": "AWS::S3::Bucket",
+ "UpdateReplacePolicy": "Retain",
+ },
+ "FrontEndDistributionToS3S3BucketPolicyF3A0315A": {
+ "Condition": "CommonResourcesDeployDemoUICondition308D3B09",
+ "Metadata": {
+ "cfn_nag": {
+ "rules_to_suppress": [
+ {
+ "id": "F16",
+ "reason": "Public website bucket policy requires a wildcard principal",
+ },
+ ],
+ },
+ },
+ "Properties": {
+ "Bucket": {
+ "Ref": "FrontEndDistributionToS3S3Bucket3A171D78",
+ },
+ "PolicyDocument": {
+ "Statement": [
+ {
+ "Action": "s3:*",
+ "Condition": {
+ "Bool": {
+ "aws:SecureTransport": "false",
+ },
+ },
+ "Effect": "Deny",
+ "Principal": {
+ "AWS": "*",
+ },
+ "Resource": [
+ {
+ "Fn::GetAtt": [
+ "FrontEndDistributionToS3S3Bucket3A171D78",
+ "Arn",
+ ],
+ },
+ {
+ "Fn::Join": [
+ "",
+ [
+ {
+ "Fn::GetAtt": [
+ "FrontEndDistributionToS3S3Bucket3A171D78",
+ "Arn",
+ ],
+ },
+ "/*",
+ ],
+ ],
+ },
+ ],
+ },
+ {
+ "Action": "s3:GetObject",
+ "Condition": {
+ "StringEquals": {
+ "AWS:SourceArn": {
+ "Fn::Join": [
+ "",
+ [
+ "arn:aws:cloudfront::",
+ {
+ "Ref": "AWS::AccountId",
+ },
+ ":distribution/",
+ {
+ "Ref": "FrontEndDistributionToS3CloudFrontDistribution15FE13D0",
+ },
+ ],
+ ],
+ },
+ },
+ },
+ "Effect": "Allow",
+ "Principal": {
+ "Service": "cloudfront.amazonaws.com",
+ },
+ "Resource": {
+ "Fn::Join": [
+ "",
+ [
+ {
+ "Fn::GetAtt": [
+ "FrontEndDistributionToS3S3Bucket3A171D78",
+ "Arn",
+ ],
+ },
+ "/*",
+ ],
+ ],
+ },
+ },
+ ],
+ "Version": "2012-10-17",
+ },
+ },
+ "Type": "AWS::S3::BucketPolicy",
+ },
+ "OperationalInsightsDashboard00409C46": {
+ "Condition": "DeployCloudWatchDashboard",
+ "Properties": {
+ "DashboardBody": {
+ "Fn::Join": [
+ "",
+ [
+ "{"start":"-P7D","periodOverride":"inherit","widgets":[{"type":"text","width":24,"height":1,"x":0,"y":0,"properties":{"markdown":"# Lambda"}},{"type":"metric","width":8,"height":8,"x":0,"y":1,"properties":{"view":"timeSeries","title":"Lambda Errors","region":"",
+ {
+ "Ref": "AWS::Region",
+ },
+ "","metrics":[["AWS/Lambda","Errors","FunctionName","",
+ {
+ "Ref": "BackEndImageHandlerLambdaFunctionADEF7FF2",
+ },
+ "",{"label":"Lambda Errors","id":"metric","stat":"Sum"}],[{"label":"Total","expression":"RUNNING_SUM(metric)","yAxis":"right"}]],"yAxis":{"left":{"label":"Count","showUnits":false,"min":0},"right":{"label":"Running-Total Count","showUnits":false,"min":0}},"legend":{"position":"bottom"},"liveData":true,"period":86400,"stat":"Sum"}},{"type":"metric","width":8,"height":8,"x":8,"y":1,"properties":{"view":"timeSeries","title":"Lambda Duration","region":"",
+ {
+ "Ref": "AWS::Region",
+ },
+ "","metrics":[["AWS/Lambda","Duration","FunctionName","",
+ {
+ "Ref": "BackEndImageHandlerLambdaFunctionADEF7FF2",
+ },
+ "",{"label":"Lambda Duration","id":"metric","stat":"Sum"}],[{"label":"Total","expression":"RUNNING_SUM(metric)","yAxis":"right"}]],"yAxis":{"left":{"label":"Milliseconds","showUnits":false,"min":0},"right":{"label":"Running-Total Milliseconds","showUnits":false,"min":0}},"legend":{"position":"bottom"},"liveData":true,"period":86400,"stat":"Sum"}},{"type":"metric","width":8,"height":8,"x":16,"y":1,"properties":{"view":"timeSeries","title":"Lambda Invocations","region":"",
+ {
+ "Ref": "AWS::Region",
+ },
+ "","metrics":[["AWS/Lambda","Invocations","FunctionName","",
+ {
+ "Ref": "BackEndImageHandlerLambdaFunctionADEF7FF2",
+ },
+ "",{"label":"Lambda Invocations","id":"metric","stat":"Sum"}],[{"label":"Total","expression":"RUNNING_SUM(metric)","yAxis":"right"}]],"yAxis":{"left":{"label":"Count","showUnits":false,"min":0},"right":{"label":"Running-Total Count","showUnits":false,"min":0}},"legend":{"position":"bottom"},"liveData":true,"period":86400,"stat":"Sum"}},{"type":"text","width":24,"height":1,"x":0,"y":9,"properties":{"markdown":"# CloudFront"}},{"type":"metric","width":12,"height":12,"x":0,"y":10,"properties":{"view":"timeSeries","title":"CloudFront Requests","region":"",
+ {
+ "Ref": "AWS::Region",
+ },
+ "","metrics":[["AWS/CloudFront","Requests","DistributionId","",
+ {
+ "Fn::If": [
+ "CommonResourcesUseExistingCloudFrontDistributionConditionEBC48184",
+ {
+ "Ref": "ExistingCloudFrontDistributionIdParameter",
+ },
+ {
+ "Fn::If": [
+ "CommonResourcesEnableS3ObjectLambdaConditionF2C07DCD",
+ {
+ "Ref": "BackEndImageHandlerCloudFrontDistributionB5464C90",
+ },
+ {
+ "Ref": "BackEndImageHandlerCloudFrontApiGatewayLambdaCloudFrontToApiGatewayCloudFrontDistribution03AA31B2",
+ },
+ ],
+ },
+ ],
+ },
+ "","Region","Global",{"label":"CloudFront Requests","id":"metric","region":"us-east-1","stat":"Sum"}],[{"label":"Total","expression":"RUNNING_SUM(metric)","yAxis":"right"}]],"yAxis":{"left":{"label":"Count","showUnits":false,"min":0},"right":{"label":"Running-Total Count","showUnits":false,"min":0}},"legend":{"position":"bottom"},"liveData":true,"period":86400,"stat":"Sum"}},{"type":"metric","width":12,"height":12,"x":12,"y":10,"properties":{"view":"timeSeries","title":"CloudFront Bytes Downloaded","region":"",
+ {
+ "Ref": "AWS::Region",
+ },
+ "","metrics":[["AWS/CloudFront","BytesDownloaded","DistributionId","",
+ {
+ "Fn::If": [
+ "CommonResourcesUseExistingCloudFrontDistributionConditionEBC48184",
+ {
+ "Ref": "ExistingCloudFrontDistributionIdParameter",
+ },
+ {
+ "Fn::If": [
+ "CommonResourcesEnableS3ObjectLambdaConditionF2C07DCD",
+ {
+ "Ref": "BackEndImageHandlerCloudFrontDistributionB5464C90",
+ },
+ {
+ "Ref": "BackEndImageHandlerCloudFrontApiGatewayLambdaCloudFrontToApiGatewayCloudFrontDistribution03AA31B2",
+ },
+ ],
+ },
+ ],
+ },
+ "","Region","Global",{"label":"CloudFront Bytes Downloaded","id":"metric","region":"us-east-1","stat":"Sum"}],[{"label":"Total","expression":"RUNNING_SUM(metric)","yAxis":"right"}]],"yAxis":{"left":{"label":"Bytes","showUnits":false,"min":0},"right":{"label":"Running-Total Bytes","showUnits":false,"min":0}},"legend":{"position":"bottom"},"liveData":true,"period":86400,"stat":"Sum"}},{"type":"metric","width":12,"height":6,"x":0,"y":22,"properties":{"view":"singleValue","title":"Cache Hit Rate","region":"",
+ {
+ "Ref": "AWS::Region",
+ },
+ "","metrics":[[{"label":"Cache Hit Rate (%)","expression":"100 * (cloudFrontRequests - lambdaInvocations) / (cloudFrontRequests)"}],["AWS/CloudFront","Requests","DistributionId","",
+ {
+ "Fn::If": [
+ "CommonResourcesUseExistingCloudFrontDistributionConditionEBC48184",
+ {
+ "Ref": "ExistingCloudFrontDistributionIdParameter",
+ },
+ {
+ "Fn::If": [
+ "CommonResourcesEnableS3ObjectLambdaConditionF2C07DCD",
+ {
+ "Ref": "BackEndImageHandlerCloudFrontDistributionB5464C90",
+ },
+ {
+ "Ref": "BackEndImageHandlerCloudFrontApiGatewayLambdaCloudFrontToApiGatewayCloudFrontDistribution03AA31B2",
+ },
+ ],
+ },
+ ],
+ },
+ "","Region","Global",{"id":"cloudFrontRequests","visible":false,"region":"us-east-1","stat":"Sum"}],["AWS/Lambda","Invocations","FunctionName","",
+ {
+ "Ref": "BackEndImageHandlerLambdaFunctionADEF7FF2",
+ },
+ "",{"id":"lambdaInvocations","visible":false,"stat":"Sum"}]],"setPeriodToTimeRange":true}},{"type":"metric","width":12,"height":6,"x":12,"y":22,"properties":{"view":"singleValue","title":"Average Image Size","region":"",
+ {
+ "Ref": "AWS::Region",
+ },
+ "","metrics":[[{"label":"Average Image Size (Bytes)","expression":"cloudFrontBytesDownloaded / cloudFrontRequests"}],["AWS/CloudFront","BytesDownloaded","DistributionId","",
+ {
+ "Fn::If": [
+ "CommonResourcesUseExistingCloudFrontDistributionConditionEBC48184",
+ {
+ "Ref": "ExistingCloudFrontDistributionIdParameter",
+ },
+ {
+ "Fn::If": [
+ "CommonResourcesEnableS3ObjectLambdaConditionF2C07DCD",
+ {
+ "Ref": "BackEndImageHandlerCloudFrontDistributionB5464C90",
+ },
+ {
+ "Ref": "BackEndImageHandlerCloudFrontApiGatewayLambdaCloudFrontToApiGatewayCloudFrontDistribution03AA31B2",
+ },
+ ],
+ },
+ ],
+ },
+ "","Region","Global",{"id":"cloudFrontBytesDownloaded","visible":false,"region":"us-east-1","stat":"Sum"}],["AWS/CloudFront","Requests","DistributionId","",
+ {
+ "Fn::If": [
+ "CommonResourcesUseExistingCloudFrontDistributionConditionEBC48184",
+ {
+ "Ref": "ExistingCloudFrontDistributionIdParameter",
+ },
+ {
+ "Fn::If": [
+ "CommonResourcesEnableS3ObjectLambdaConditionF2C07DCD",
+ {
+ "Ref": "BackEndImageHandlerCloudFrontDistributionB5464C90",
+ },
+ {
+ "Ref": "BackEndImageHandlerCloudFrontApiGatewayLambdaCloudFrontToApiGatewayCloudFrontDistribution03AA31B2",
+ },
+ ],
+ },
+ ],
+ },
+ "","Region","Global",{"id":"cloudFrontRequests","visible":false,"region":"us-east-1","stat":"Sum"}]],"setPeriodToTimeRange":true}},{"type":"text","width":24,"height":1,"x":0,"y":28,"properties":{"markdown":"# Overall"}},{"type":"metric","width":24,"height":6,"x":0,"y":29,"properties":{"view":"singleValue","title":"Estimated Cost","region":"",
+ {
+ "Ref": "AWS::Region",
+ },
+ "","metrics":[[{"label":"Estimated Cost($)","expression":"7.916241884231568e-11 * cloudFrontBytesDownloaded + 7.5e-7 * cloudFrontRequests + 1.66667e-8 * lambdaDuration + 2.0000000000000002e-7 * lambdaInvocations"}],["AWS/CloudFront","BytesDownloaded","DistributionId","",
+ {
+ "Fn::If": [
+ "CommonResourcesUseExistingCloudFrontDistributionConditionEBC48184",
+ {
+ "Ref": "ExistingCloudFrontDistributionIdParameter",
+ },
+ {
+ "Fn::If": [
+ "CommonResourcesEnableS3ObjectLambdaConditionF2C07DCD",
+ {
+ "Ref": "BackEndImageHandlerCloudFrontDistributionB5464C90",
+ },
+ {
+ "Ref": "BackEndImageHandlerCloudFrontApiGatewayLambdaCloudFrontToApiGatewayCloudFrontDistribution03AA31B2",
+ },
+ ],
+ },
+ ],
+ },
+ "","Region","Global",{"id":"cloudFrontBytesDownloaded","visible":false,"region":"us-east-1","stat":"Sum"}],["AWS/CloudFront","Requests","DistributionId","",
+ {
+ "Fn::If": [
+ "CommonResourcesUseExistingCloudFrontDistributionConditionEBC48184",
+ {
+ "Ref": "ExistingCloudFrontDistributionIdParameter",
+ },
+ {
+ "Fn::If": [
+ "CommonResourcesEnableS3ObjectLambdaConditionF2C07DCD",
+ {
+ "Ref": "BackEndImageHandlerCloudFrontDistributionB5464C90",
+ },
+ {
+ "Ref": "BackEndImageHandlerCloudFrontApiGatewayLambdaCloudFrontToApiGatewayCloudFrontDistribution03AA31B2",
+ },
+ ],
+ },
+ ],
+ },
+ "","Region","Global",{"id":"cloudFrontRequests","visible":false,"region":"us-east-1","stat":"Sum"}],["AWS/Lambda","Duration","FunctionName","",
+ {
+ "Ref": "BackEndImageHandlerLambdaFunctionADEF7FF2",
+ },
+ "",{"id":"lambdaDuration","visible":false,"stat":"Sum"}],["AWS/Lambda","Invocations","FunctionName","",
+ {
+ "Ref": "BackEndImageHandlerLambdaFunctionADEF7FF2",
+ },
+ "",{"id":"lambdaInvocations","visible":false,"stat":"Sum"}]],"setPeriodToTimeRange":true,"singleValueFullPrecision":true}}]}",
+ ],
+ ],
+ },
+ "DashboardName": {
+ "Fn::Join": [
+ "",
+ [
+ {
+ "Ref": "AWS::StackName",
+ },
+ "-",
+ {
+ "Ref": "AWS::Region",
+ },
+ "-Operational-Insights-Dashboard",
+ ],
+ ],
+ },
+ },
+ "Type": "AWS::CloudWatch::Dashboard",
+ },
+ },
+ "Rules": {
+ "CheckBootstrapVersion": {
+ "Assertions": [
+ {
+ "Assert": {
+ "Fn::Not": [
+ {
+ "Fn::Contains": [
+ [
+ "1",
+ "2",
+ "3",
+ "4",
+ "5",
+ ],
+ {
+ "Ref": "BootstrapVersion",
+ },
+ ],
+ },
+ ],
+ },
+ "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI.",
+ },
+ ],
+ },
+ "ExistingDistributionIdRequiredRule": {
+ "Assertions": [
+ {
+ "Assert": {
+ "Fn::Not": [
+ {
+ "Fn::Equals": [
+ {
+ "Ref": "ExistingCloudFrontDistributionIdParameter",
+ },
+ "",
+ ],
+ },
+ ],
+ },
+ "AssertDescription": "If 'UseExistingCloudFrontDistribution' is set to 'Yes', 'ExistingCloudFrontDistributionId' must be provided.",
+ },
+ ],
+ "RuleCondition": {
+ "Fn::Equals": [
+ {
+ "Ref": "UseExistingCloudFrontDistributionParameter",
+ },
+ "Yes",
+ ],
+ },
+ },
+ },
+}
+`;
diff --git a/source/constructs/test/constructs.test.ts b/source/constructs/test/constructs.test.ts
index c40e53c6f..41a73ff9e 100644
--- a/source/constructs/test/constructs.test.ts
+++ b/source/constructs/test/constructs.test.ts
@@ -1,15 +1,74 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
-import { expect as expectCDK, matchTemplate, MatchStyle } from '@aws-cdk/assert';
-import * as cdk from '@aws-cdk/core';
-import * as Constructs from '../lib/constructs-stack';
-import TestTemplate from './serverless-image-handler-test.json';
-
-test('Serverless Image Handler Stack', () => {
- const app = new cdk.App();
- // WHEN
- const stack = new Constructs.ConstructsStack(app, 'MyTestStack');
- // THEN
- expectCDK(stack).to(matchTemplate(TestTemplate, MatchStyle.EXACT));
+import { Template } from "aws-cdk-lib/assertions";
+import { App } from "aws-cdk-lib";
+
+import { ServerlessImageHandlerStack } from "../lib/serverless-image-stack";
+
+const SUPPORTED_RUNTIMES = ["nodejs22.x", "python3.13"];
+
+describe("ServerlessImageHandlerStack", () => {
+ let app: App;
+ let stack: ServerlessImageHandlerStack;
+ let template: Template;
+
+ beforeEach(() => {
+ app = new App({
+ context: {
+ solutionId: "SO0023",
+ solutionName: "dynamic-image-transformation-for-amazon-cloudfront",
+ solutionVersion: "v7.0.1",
+ },
+ });
+
+ stack = new ServerlessImageHandlerStack(app, "TestStack", {
+ solutionId: "S0ABC",
+ solutionName: "dit",
+ solutionVersion: "v7.0.1",
+ });
+
+ template = Template.fromStack(stack);
+ });
+
+ test("Dynamic Image Transformation for Amazon CloudFront Stack Snapshot", () => {
+ const templateJson = template.toJSON();
+
+ /**
+ * iterate templateJson and for any attribute called S3Key, replace the value for that attribute with "Omitted to remove snapshot dependency on hash",
+ * this is so that the snapshot can be saved and will not change because the hash has been regenerated
+ */
+ Object.keys(templateJson.Resources).forEach((key) => {
+ if (templateJson.Resources[key].Properties?.Code?.S3Key) {
+ templateJson.Resources[key].Properties.Code.S3Key = "Omitted to remove snapshot dependency on hash";
+ }
+ if (templateJson.Resources[key].Properties?.Content?.S3Key) {
+ templateJson.Resources[key].Properties.Content.S3Key = "Omitted to remove snapshot dependency on hash";
+ }
+ if (templateJson.Resources[key].Properties?.SourceObjectKeys) {
+ templateJson.Resources[key].Properties.SourceObjectKeys = [
+ "Omitted to remove snapshot dependency on demo ui module hash",
+ ];
+ }
+ if (templateJson.Resources[key].Properties?.Environment?.Variables?.SOLUTION_VERSION) {
+ templateJson.Resources[key].Properties.Environment.Variables.SOLUTION_VERSION =
+ "Omitted to remove snapshot dependency on solution version";
+ }
+ });
+
+ expect.assertions(1);
+ expect(templateJson).toMatchSnapshot();
+ });
+
+ test("All Lambda functions should use supported runtimes", () => {
+ const lambdaFunctions = template.findResources("AWS::Lambda::Function");
+ const functionNames = Object.keys(lambdaFunctions);
+
+ expect(functionNames.length).toBeGreaterThan(0);
+
+ functionNames.forEach((functionName) => {
+ const runtime = lambdaFunctions[functionName].Properties.Runtime;
+ expect(SUPPORTED_RUNTIMES).toContain(runtime);
+ });
+ });
});
diff --git a/source/constructs/test/serverless-image-handler-test.json b/source/constructs/test/serverless-image-handler-test.json
deleted file mode 100644
index 50497f483..000000000
--- a/source/constructs/test/serverless-image-handler-test.json
+++ /dev/null
@@ -1,1760 +0,0 @@
-{
- "Description": "(SO0023) - Serverless Image Handler with aws-solutions-constructs: This template deploys and configures a serverless architecture that is optimized for dynamic image manipulation and delivery at low latency and cost. Leverages SharpJS for image processing. Template version TEST_VERSION",
- "AWSTemplateFormatVersion": "2010-09-09",
- "Metadata": {
- "AWS::CloudFormation::Interface": {
- "ParameterGroups": [
- {
- "Label": {
- "default": "CORS Options"
- },
- "Parameters": [
- "CorsEnabled",
- "CorsOrigin"
- ]
- },
- {
- "Label": {
- "default": "Image Sources"
- },
- "Parameters": [
- "SourceBuckets"
- ]
- },
- {
- "Label": {
- "default": "Demo UI"
- },
- "Parameters": [
- "DeployDemoUI"
- ]
- },
- {
- "Label": {
- "default": "Event Logging"
- },
- "Parameters": [
- "LogRetentionPeriod"
- ]
- },
- {
- "Label": {
- "default": "Image URL Signature (Note: Enabling signature is not compatible with previous image URLs, which could result in broken image links. Please refer to the implementation guide for details: https://docs.aws.amazon.com/solutions/latest/serverless-image-handler/considerations.html)"
- },
- "Parameters": [
- "EnableSignature",
- "SecretsManagerSecret",
- "SecretsManagerKey"
- ]
- },
- {
- "Label": {
- "default": "Default Fallback Image (Note: Enabling default fallback image returns the default fallback image instead of JSON object when error happens. Please refer to the implementation guide for details: https://docs.aws.amazon.com/solutions/latest/serverless-image-handler/considerations.html)"
- },
- "Parameters": [
- "EnableDefaultFallbackImage",
- "FallbackImageS3Bucket",
- "FallbackImageS3Key"
- ]
- },
- {
- "Label": {
- "default": "Auto WebP"
- },
- "Parameters": [
- "AutoWebP"
- ]
- }
- ]
- }
- },
- "Parameters": {
- "CorsEnabled": {
- "Type": "String",
- "Default": "No",
- "AllowedValues": [
- "Yes",
- "No"
- ],
- "Description": "Would you like to enable Cross-Origin Resource Sharing (CORS) for the image handler API? Select 'Yes' if so."
- },
- "CorsOrigin": {
- "Type": "String",
- "Default": "*",
- "Description": "If you selected 'Yes' above, please specify an origin value here. A wildcard (*) value will support any origin. We recommend specifying an origin (i.e. https://example.domain) to restrict cross-site access to your API."
- },
- "SourceBuckets": {
- "Type": "String",
- "Default": "defaultBucket, bucketNo2, bucketNo3, ...",
- "AllowedPattern": ".+",
- "Description": "(Required) List the buckets (comma-separated) within your account that contain original image files. If you plan to use Thumbor or Custom image requests with this solution, the source bucket for those requests will be the first bucket listed in this field."
- },
- "DeployDemoUI": {
- "Type": "String",
- "Default": "Yes",
- "AllowedValues": [
- "Yes",
- "No"
- ],
- "Description": "Would you like to deploy a demo UI to explore the features and capabilities of this solution? This will create an additional Amazon S3 bucket and Amazon CloudFront distribution in your account."
- },
- "LogRetentionPeriod": {
- "Type": "Number",
- "Default": "1",
- "AllowedValues": [
- "1",
- "3",
- "5",
- "7",
- "14",
- "30",
- "60",
- "90",
- "120",
- "150",
- "180",
- "365",
- "400",
- "545",
- "731",
- "1827",
- "3653"
- ],
- "Description": "This solution automatically logs events to Amazon CloudWatch. Select the amount of time for CloudWatch logs from this solution to be retained (in days)."
- },
- "AutoWebP": {
- "Type": "String",
- "Default": "No",
- "AllowedValues": [
- "Yes",
- "No"
- ],
- "Description": "Would you like to enable automatic WebP based on accept headers? Select 'Yes' if so."
- },
- "EnableSignature": {
- "Type": "String",
- "Default": "No",
- "AllowedValues": [
- "Yes",
- "No"
- ],
- "Description": "Would you like to enable the signature? If so, select 'Yes' and provide SecretsManagerSecret and SecretsManagerKey values."
- },
- "SecretsManagerSecret": {
- "Type": "String",
- "Default": "",
- "Description": "The name of AWS Secrets Manager secret. You need to create your secret under this name."
- },
- "SecretsManagerKey": {
- "Type": "String",
- "Default": "",
- "Description": "The name of AWS Secrets Manager secret key. You need to create secret key with this key name. The secret value would be used to check signature."
- },
- "EnableDefaultFallbackImage": {
- "Type": "String",
- "Default": "No",
- "AllowedValues": [
- "Yes",
- "No"
- ],
- "Description": "Would you like to enable the default fallback image? If so, select 'Yes' and provide FallbackImageS3Bucket and FallbackImageS3Key values."
- },
- "FallbackImageS3Bucket": {
- "Type": "String",
- "Default": "",
- "Description": "The name of the Amazon S3 bucket which contains the default fallback image. e.g. my-fallback-image-bucket"
- },
- "FallbackImageS3Key": {
- "Type": "String",
- "Default": "",
- "Description": "The name of the default fallback image object key including prefix. e.g. prefix/image.jpg"
- }
- },
- "Mappings": {
- "Send": {
- "AnonymousUsage": {
- "Data": "Yes"
- }
- }
- },
- "Conditions": {
- "DeployDemoUICondition": {
- "Fn::Equals": [
- {
- "Ref": "DeployDemoUI"
- },
- "Yes"
- ]
- },
- "EnableCorsCondition": {
- "Fn::Equals": [
- {
- "Ref": "CorsEnabled"
- },
- "Yes"
- ]
- },
- "EnableSignatureCondition": {
- "Fn::Equals": [
- {
- "Ref": "EnableSignature"
- },
- "Yes"
- ]
- },
- "EnableDefaultFallbackImageCondition": {
- "Fn::Equals": [
- {
- "Ref": "EnableDefaultFallbackImage"
- },
- "Yes"
- ]
- },
- "IsOptInRegion": {
- "Fn::Or": [
- {
- "Fn::Equals": [
- "af-south-1",
- {
- "Ref": "AWS::Region"
- }
- ]
- },
- {
- "Fn::Equals": [
- "ap-east-1",
- {
- "Ref": "AWS::Region"
- }
- ]
- },
- {
- "Fn::Equals": [
- "eu-south-1",
- {
- "Ref": "AWS::Region"
- }
- ]
- },
- {
- "Fn::Equals": [
- "me-south-1",
- {
- "Ref": "AWS::Region"
- }
- ]
- }
- ]
- },
- "IsNotOptInRegion": {
- "Fn::Not": [
- {
- "Condition": "IsOptInRegion"
- }
- ]
- }
- },
- "Resources": {
- "ImageHandlerFunctionRole": {
- "Type": "AWS::IAM::Role",
- "Properties": {
- "AssumeRolePolicyDocument": {
- "Statement": [
- {
- "Action": "sts:AssumeRole",
- "Effect": "Allow",
- "Principal": {
- "Service": "lambda.amazonaws.com"
- }
- }
- ],
- "Version": "2012-10-17"
- },
- "Path": "/",
- "RoleName": {
- "Fn::Join": [
- "",
- [
- {
- "Ref": "AWS::StackName"
- },
- "ImageHandlerFunctionRole-",
- {
- "Ref": "AWS::Region"
- }
- ]
- ]
- }
- },
- "Metadata": {
- "cfn_nag": {
- "rules_to_suppress": [
- {
- "id": "W28",
- "reason": "Resource name validated and found to pose no risk to updates that require replacement of this resource."
- }
- ]
- }
- }
- },
- "ImageHandlerPolicy": {
- "Type": "AWS::IAM::Policy",
- "Properties": {
- "PolicyDocument": {
- "Statement": [
- {
- "Action": [
- "logs:CreateLogStream",
- "logs:CreateLogGroup",
- "logs:PutLogEvents"
- ],
- "Effect": "Allow",
- "Resource": {
- "Fn::Join": [
- "",
- [
- "arn:",
- {
- "Ref": "AWS::Partition"
- },
- ":logs:",
- {
- "Ref": "AWS::Region"
- },
- ":",
- {
- "Ref": "AWS::AccountId"
- },
- ":log-group:/aws/lambda/*"
- ]
- ]
- }
- },
- {
- "Action": [
- "s3:GetObject",
- "s3:PutObject",
- "s3:ListBucket"
- ],
- "Effect": "Allow",
- "Resource": {
- "Fn::Join": [
- "",
- [
- "arn:",
- {
- "Ref": "AWS::Partition"
- },
- ":s3:::*"
- ]
- ]
- }
- },
- {
- "Action": [
- "rekognition:DetectFaces",
- "rekognition:DetectModerationLabels"
- ],
- "Effect": "Allow",
- "Resource": "*"
- }
- ],
- "Version": "2012-10-17"
- },
- "PolicyName": {
- "Fn::Join": [
- "",
- [
- {
- "Ref": "AWS::StackName"
- },
- "ImageHandlerPolicy"
- ]
- ]
- },
- "Roles": [
- {
- "Ref": "ImageHandlerFunctionRole"
- }
- ]
- },
- "Metadata": {
- "cfn_nag": {
- "rules_to_suppress": [
- {
- "id": "W12",
- "reason": "rekognition:DetectFaces requires '*' resources."
- }
- ]
- }
- }
- },
- "ImageHandlerFunction": {
- "Type": "AWS::Lambda::Function",
- "Properties": {
- "Code": {
- "S3Bucket": {
- "Fn::Join": [
- "",
- [
- "TEST-",
- {
- "Ref": "AWS::Region"
- }
- ]
- ]
- },
- "S3Key": "serverless-image-handler/TEST_VERSION/image-handler.zip"
- },
- "Handler": "index.handler",
- "Role": {
- "Fn::GetAtt": [
- "ImageHandlerFunctionRole",
- "Arn"
- ]
- },
- "Runtime": "nodejs12.x",
- "Description": "Serverless Image Handler - Function for performing image edits and manipulations.",
- "Environment": {
- "Variables": {
- "AUTO_WEBP": {
- "Ref": "AutoWebP"
- },
- "CORS_ENABLED": {
- "Ref": "CorsEnabled"
- },
- "CORS_ORIGIN": {
- "Ref": "CorsOrigin"
- },
- "SOURCE_BUCKETS": {
- "Ref": "SourceBuckets"
- },
- "REWRITE_MATCH_PATTERN": "",
- "REWRITE_SUBSTITUTION": "",
- "ENABLE_SIGNATURE": {
- "Ref": "EnableSignature"
- },
- "SECRETS_MANAGER": {
- "Ref": "SecretsManagerSecret"
- },
- "SECRET_KEY": {
- "Ref": "SecretsManagerKey"
- },
- "ENABLE_DEFAULT_FALLBACK_IMAGE": {
- "Ref": "EnableDefaultFallbackImage"
- },
- "DEFAULT_FALLBACK_IMAGE_BUCKET": {
- "Ref": "FallbackImageS3Bucket"
- },
- "DEFAULT_FALLBACK_IMAGE_KEY": {
- "Ref": "FallbackImageS3Key"
- }
- }
- },
- "MemorySize": 1024,
- "Timeout": 30
- },
- "DependsOn": [
- "ImageHandlerFunctionRole"
- ],
- "Metadata": {
- "cfn_nag": {
- "rules_to_suppress": [
- {
- "id": "W58",
- "reason": "False alarm: The Lambda function does have the permission to write CloudWatch Logs."
- }
- ]
- }
- }
- },
- "ImageHandlerPermission": {
- "Type": "AWS::Lambda::Permission",
- "Properties": {
- "Action": "lambda:InvokeFunction",
- "FunctionName": {
- "Fn::GetAtt": [
- "ImageHandlerFunction",
- "Arn"
- ]
- },
- "Principal": "apigateway.amazonaws.com",
- "SourceArn": {
- "Fn::Join": [
- "",
- [
- "arn:",
- {
- "Ref": "AWS::Partition"
- },
- ":execute-api:",
- {
- "Ref": "AWS::Region"
- },
- ":",
- {
- "Ref": "AWS::AccountId"
- },
- ":",
- {
- "Ref": "ImageHandlerApi"
- },
- "/*/*/*"
- ]
- ]
- }
- }
- },
- "ImageHandlerLogGroup": {
- "Type": "AWS::Logs::LogGroup",
- "Properties": {
- "LogGroupName": {
- "Fn::Join": [
- "",
- [
- "/aws/lambda/",
- {
- "Ref": "ImageHandlerFunction"
- }
- ]
- ]
- },
- "RetentionInDays": {
- "Ref": "LogRetentionPeriod"
- }
- },
- "UpdateReplacePolicy": "Retain",
- "DeletionPolicy": "Retain",
- "Metadata": {
- "cfn_nag": {
- "rules_to_suppress": [
- {
- "id": "W84",
- "reason": "Used to store store function info"
- }
- ]
- }
- }
- },
- "ApiLogs": {
- "Type": "AWS::Logs::LogGroup",
- "UpdateReplacePolicy": "Retain",
- "DeletionPolicy": "Retain",
- "Metadata": {
- "cfn_nag": {
- "rules_to_suppress": [
- {
- "id": "W84",
- "reason": "Used to store store api log info, not using kms"
- },
- {
- "id": "W86",
- "reason": "Log retention specified in CloudFromation parameters."
- }
- ]
- }
- }
- },
- "ImageHandlerApi": {
- "Type": "AWS::ApiGateway::RestApi",
- "Properties": {
- "Body": {
- "swagger": "2.0",
- "info": {
- "title": "ServerlessImageHandler"
- },
- "basePath": "/image",
- "schemes": [
- "https"
- ],
- "paths": {
- "/{proxy+}": {
- "x-amazon-apigateway-any-method": {
- "produces": [
- "application/json"
- ],
- "parameters": [
- {
- "name": "proxy",
- "in": "path",
- "required": true,
- "type": "string"
- },
- {
- "name": "signature",
- "in": "query",
- "description": "Signature of the image",
- "required": false,
- "type": "string"
- }
- ],
- "responses": {},
- "x-amazon-apigateway-integration": {
- "responses": {
- "default": {
- "statusCode": "200"
- }
- },
- "uri": {
- "Fn::Join": [
- "",
- [
- "arn:aws:apigateway:",
- {
- "Ref": "AWS::Region"
- },
- ":",
- "lambda:path/2015-03-31/functions/",
- {
- "Fn::GetAtt": [
- "ImageHandlerFunction",
- "Arn"
- ]
- },
- "/invocations"
- ]
- ]
- },
- "passthroughBehavior": "when_no_match",
- "httpMethod": "POST",
- "cacheNamespace": "xh7gp9",
- "cacheKeyParameters": [
- "method.request.path.proxy"
- ],
- "contentHandling": "CONVERT_TO_TEXT",
- "type": "aws_proxy"
- }
- }
- }
- },
- "x-amazon-apigateway-binary-media-types": [
- "*/*"
- ]
- },
- "EndpointConfiguration": {
- "Types": [
- "REGIONAL"
- ]
- },
- "Name": "ServerlessImageHandler"
- }
- },
- "ApiLoggingRole": {
- "Type": "AWS::IAM::Role",
- "Properties": {
- "AssumeRolePolicyDocument": {
- "Statement": [
- {
- "Action": "sts:AssumeRole",
- "Effect": "Allow",
- "Principal": {
- "Service": "apigateway.amazonaws.com"
- }
- }
- ],
- "Version": "2012-10-17"
- },
- "Policies": [
- {
- "PolicyDocument": {
- "Statement": [
- {
- "Action": [
- "logs:CreateLogGroup",
- "logs:CreateLogStream",
- "logs:DescribeLogGroups",
- "logs:DescribeLogStreams",
- "logs:PutLogEvents",
- "logs:GetLogEvents",
- "logs:FilterLogEvents"
- ],
- "Effect": "Allow",
- "Resource": {
- "Fn::Join": [
- "",
- [
- "arn:",
- {
- "Ref": "AWS::Partition"
- },
- ":logs:",
- {
- "Ref": "AWS::Region"
- },
- ":",
- {
- "Ref": "AWS::AccountId"
- },
- ":*"
- ]
- ]
- }
- }
- ],
- "Version": "2012-10-17"
- },
- "PolicyName": "LambdaRestApiCloudWatchRolePolicy"
- }
- ]
- }
- },
- "ApiAccountConfig": {
- "Type": "AWS::ApiGateway::Account",
- "Properties": {
- "CloudWatchRoleArn": {
- "Fn::GetAtt": [
- "ApiLoggingRole",
- "Arn"
- ]
- }
- },
- "DependsOn": [
- "ImageHandlerApi"
- ]
- },
- "Logs": {
- "Type": "AWS::S3::Bucket",
- "Properties": {
- "AccessControl": "LogDeliveryWrite",
- "BucketEncryption": {
- "ServerSideEncryptionConfiguration": [
- {
- "ServerSideEncryptionByDefault": {
- "SSEAlgorithm": "AES256"
- }
- }
- ]
- },
- "PublicAccessBlockConfiguration": {
- "BlockPublicAcls": true,
- "BlockPublicPolicy": true,
- "IgnorePublicAcls": true,
- "RestrictPublicBuckets": true
- }
- },
- "UpdateReplacePolicy": "Retain",
- "DeletionPolicy": "Retain",
- "Metadata": {
- "cfn_nag": {
- "rules_to_suppress": [
- {
- "id": "W35",
- "reason": "Used to store access logs for other buckets"
- }
- ]
- }
- },
- "Condition": "IsNotOptInRegion"
- },
- "LogsBucketPolicy": {
- "Type": "AWS::S3::BucketPolicy",
- "Properties": {
- "Bucket": {
- "Ref": "Logs"
- },
- "PolicyDocument": {
- "Statement": [
- {
- "Action": "*",
- "Condition": {
- "Bool": {
- "aws:SecureTransport": "false"
- }
- },
- "Effect": "Deny",
- "Principal": "*",
- "Resource": {
- "Fn::Join": [
- "",
- [
- {
- "Fn::GetAtt": [
- "Logs",
- "Arn"
- ]
- },
- "/*"
- ]
- ]
- },
- "Sid": "HttpsOnly"
- }
- ],
- "Version": "2012-10-17"
- }
- },
- "Condition": "IsNotOptInRegion"
- },
- "ImageHandlerDistribution": {
- "Type": "AWS::CloudFront::Distribution",
- "Properties": {
- "DistributionConfig": {
- "Comment": "Image handler distribution",
- "CustomErrorResponses": [
- {
- "ErrorCachingMinTTL": 10,
- "ErrorCode": 500
- },
- {
- "ErrorCachingMinTTL": 10,
- "ErrorCode": 501
- },
- {
- "ErrorCachingMinTTL": 10,
- "ErrorCode": 502
- },
- {
- "ErrorCachingMinTTL": 10,
- "ErrorCode": 503
- },
- {
- "ErrorCachingMinTTL": 10,
- "ErrorCode": 504
- }
- ],
- "DefaultCacheBehavior": {
- "AllowedMethods": [
- "GET",
- "HEAD"
- ],
- "CachePolicyId": {
- "Ref": "ImageHandlerCachePolicy"
- },
- "OriginRequestPolicyId": {
- "Ref": "ImageHandlerOriginRequestPolicy"
- },
- "TargetOriginId": {
- "Ref": "ImageHandlerApi"
- },
- "ViewerProtocolPolicy": "https-only"
- },
- "Enabled": true,
- "HttpVersion": "http2",
- "Logging": {
- "Bucket": {
- "Fn::If": [
- "IsOptInRegion",
- {
- "Fn::Join": [
- "",
- [
- {
- "Fn::GetAtt": [
- "CustomCFLoggingBucket",
- "bucketName"
- ]
- },
- ".s3.us-east-1.",
- {
- "Ref": "AWS::URLSuffix"
- }
- ]
- ]
- },
- {
- "Fn::GetAtt": [
- "Logs",
- "RegionalDomainName"
- ]
- }
- ]
- },
- "IncludeCookies": false,
- "Prefix": "image-handler-cf-logs/"
- },
- "Origins": [
- {
- "CustomOriginConfig": {
- "HTTPSPort": 443,
- "OriginProtocolPolicy": "https-only",
- "OriginSSLProtocols": [
- "TLSv1.1",
- "TLSv1.2"
- ]
- },
- "DomainName": {
- "Fn::Join": [
- "",
- [
- {
- "Ref": "ImageHandlerApi"
- },
- ".execute-api.",
- {
- "Ref": "AWS::Region"
- },
- ".amazonaws.com"
- ]
- ]
- },
- "Id": {
- "Ref": "ImageHandlerApi"
- },
- "OriginPath": "/image"
- }
- ],
- "PriceClass": "PriceClass_All"
- }
- },
- "Metadata": {
- "cfn_nag": {
- "rules_to_suppress": [
- {
- "id": "W70",
- "reason": "Since the distribution uses the CloudFront domain name, CloudFront automatically sets the security policy to TLSv1 regardless of the value of MinimumProtocolVersion"
- }
- ]
- }
- }
- },
- "ImageHandlerApiDeployment": {
- "Type": "AWS::ApiGateway::Deployment",
- "Properties": {
- "RestApiId": {
- "Ref": "ImageHandlerApi"
- },
- "StageDescription": {
- "AccessLogSetting": {
- "DestinationArn": {
- "Fn::GetAtt": [
- "ApiLogs",
- "Arn"
- ]
- },
- "Format": "$context.identity.sourceIp $context.identity.caller $context.identity.user [$context.requestTime] \"$context.httpMethod $context.resourcePath $context.protocol\" $context.status $context.responseLength $context.requestId"
- }
- },
- "StageName": "image"
- },
- "DependsOn": [
- "ApiAccountConfig"
- ],
- "Metadata": {
- "cfn_nag": {
- "rules_to_suppress": [
- {
- "id": "W68",
- "reason": "The solution does not require the usage plan."
- }
- ]
- }
- }
- },
- "ImageHandlerCachePolicy": {
- "Type": "AWS::CloudFront::CachePolicy",
- "Properties": {
- "CachePolicyConfig": {
- "DefaultTTL": 86400,
- "MaxTTL": 31536000,
- "MinTTL": 1,
- "Name": {
- "Fn::Join": [
- "",
- [
- {
- "Ref": "AWS::StackName"
- },
- "-",
- {
- "Ref": "AWS::Region"
- },
- "-ImageHandlerCachePolicy"
- ]
- ]
- },
- "ParametersInCacheKeyAndForwardedToOrigin": {
- "CookiesConfig": {
- "CookieBehavior": "none"
- },
- "EnableAcceptEncodingGzip": true,
- "HeadersConfig": {
- "HeaderBehavior": "whitelist",
- "Headers": [
- "origin",
- "accept"
- ]
- },
- "QueryStringsConfig": {
- "QueryStringBehavior": "whitelist",
- "QueryStrings": [
- "signature"
- ]
- }
- }
- }
- }
- },
- "ImageHandlerOriginRequestPolicy": {
- "Type": "AWS::CloudFront::OriginRequestPolicy",
- "Properties": {
- "OriginRequestPolicyConfig": {
- "CookiesConfig": {
- "CookieBehavior": "none"
- },
- "HeadersConfig": {
- "HeaderBehavior": "whitelist",
- "Headers": [
- "origin",
- "accept"
- ]
- },
- "Name": {
- "Fn::Join": [
- "",
- [
- {
- "Ref": "AWS::StackName"
- },
- "-",
- {
- "Ref": "AWS::Region"
- },
- "-ImageHandlerOriginRequestPolicy"
- ]
- ]
- },
- "QueryStringsConfig": {
- "QueryStringBehavior": "whitelist",
- "QueryStrings": [
- "signature"
- ]
- }
- }
- }
- },
- "DemoBucket": {
- "Type": "AWS::S3::Bucket",
- "Properties": {
- "AccessControl": "Private",
- "BucketEncryption": {
- "ServerSideEncryptionConfiguration": [
- {
- "ServerSideEncryptionByDefault": {
- "SSEAlgorithm": "AES256"
- }
- }
- ]
- },
- "PublicAccessBlockConfiguration": {
- "BlockPublicAcls": true,
- "BlockPublicPolicy": true,
- "IgnorePublicAcls": true,
- "RestrictPublicBuckets": true
- },
- "WebsiteConfiguration": {
- "ErrorDocument": "index.html",
- "IndexDocument": "index.html"
- }
- },
- "UpdateReplacePolicy": "Retain",
- "DeletionPolicy": "Retain",
- "Metadata": {
- "cfn_nag": {
- "rules_to_suppress": [
- {
- "id": "W35",
- "reason": "This S3 bucket does not require access logging. API calls and image operations are logged to CloudWatch with custom reporting."
- }
- ]
- }
- },
- "Condition": "DeployDemoUICondition"
- },
- "DemoBucketPolicy": {
- "Type": "AWS::S3::BucketPolicy",
- "Properties": {
- "Bucket": {
- "Ref": "DemoBucket"
- },
- "PolicyDocument": {
- "Statement": [
- {
- "Action": [
- "s3:GetObject"
- ],
- "Effect": "Allow",
- "Resource": {
- "Fn::Join": [
- "",
- [
- {
- "Fn::GetAtt": [
- "DemoBucket",
- "Arn"
- ]
- },
- "/*"
- ]
- ]
- },
- "Principal": {
- "CanonicalUser": {
- "Fn::GetAtt": [
- "DemoOriginAccessIdentity",
- "S3CanonicalUserId"
- ]
- }
- }
- }
- ]
- }
- },
- "Condition": "DeployDemoUICondition"
- },
- "DemoOriginAccessIdentity": {
- "Type": "AWS::CloudFront::CloudFrontOriginAccessIdentity",
- "Properties": {
- "CloudFrontOriginAccessIdentityConfig": {
- "Comment": {
- "Fn::Join": [
- "",
- [
- "access-identity-",
- {
- "Ref": "DemoBucket"
- }
- ]
- ]
- }
- }
- },
- "Condition": "DeployDemoUICondition"
- },
- "DemoDistribution": {
- "Type": "AWS::CloudFront::Distribution",
- "Properties": {
- "DistributionConfig": {
- "Comment": "Website distribution for solution",
- "DefaultCacheBehavior": {
- "AllowedMethods": [
- "GET",
- "HEAD"
- ],
- "CachedMethods": [
- "GET",
- "HEAD"
- ],
- "ForwardedValues": {
- "QueryString": false
- },
- "TargetOriginId": "S3-solution-website",
- "ViewerProtocolPolicy": "redirect-to-https"
- },
- "Enabled": true,
- "HttpVersion": "http2",
- "IPV6Enabled": true,
- "Logging": {
- "Bucket": {
- "Fn::If": [
- "IsOptInRegion",
- {
- "Fn::Join": [
- "",
- [
- {
- "Fn::GetAtt": [
- "CustomCFLoggingBucket",
- "bucketName"
- ]
- },
- ".s3.us-east-1.",
- {
- "Ref": "AWS::URLSuffix"
- }
- ]
- ]
- },
- {
- "Fn::GetAtt": [
- "Logs",
- "RegionalDomainName"
- ]
- }
- ]
- },
- "IncludeCookies": false,
- "Prefix": "demo-cf-logs/"
- },
- "Origins": [
- {
- "DomainName": {
- "Fn::GetAtt": [
- "DemoBucket",
- "RegionalDomainName"
- ]
- },
- "Id": "S3-solution-website",
- "S3OriginConfig": {
- "OriginAccessIdentity": {
- "Fn::Join": [
- "",
- [
- "origin-access-identity/cloudfront/",
- {
- "Ref": "DemoOriginAccessIdentity"
- }
- ]
- ]
- }
- }
- }
- ],
- "ViewerCertificate": {
- "CloudFrontDefaultCertificate": true
- }
- }
- },
- "Metadata": {
- "cfn_nag": {
- "rules_to_suppress": [
- {
- "id": "W70",
- "reason": "Since the distribution uses the CloudFront domain name, CloudFront automatically sets the security policy to TLSv1 regardless of the value of MinimumProtocolVersion"
- }
- ]
- }
- },
- "Condition": "DeployDemoUICondition"
- },
- "CustomResourceRole": {
- "Type": "AWS::IAM::Role",
- "Properties": {
- "AssumeRolePolicyDocument": {
- "Statement": [
- {
- "Action": "sts:AssumeRole",
- "Effect": "Allow",
- "Principal": {
- "Service": "lambda.amazonaws.com"
- }
- }
- ],
- "Version": "2012-10-17"
- },
- "Path": "/",
- "RoleName": {
- "Fn::Join": [
- "",
- [
- {
- "Ref": "AWS::StackName"
- },
- "CustomResourceRole-",
- {
- "Ref": "AWS::Region"
- }
- ]
- ]
- }
- },
- "Metadata": {
- "cfn_nag": {
- "rules_to_suppress": [
- {
- "id": "W28",
- "reason": "Resource name validated and found to pose no risk to updates that require replacement of this resource."
- }
- ]
- }
- }
- },
- "CustomResourcePolicy": {
- "Type": "AWS::IAM::Policy",
- "Properties": {
- "PolicyDocument": {
- "Statement": [
- {
- "Action": [
- "logs:CreateLogStream",
- "logs:CreateLogGroup",
- "logs:PutLogEvents"
- ],
- "Effect": "Allow",
- "Resource": {
- "Fn::Join": [
- "",
- [
- "arn:",
- {
- "Ref": "AWS::Partition"
- },
- ":logs:",
- {
- "Ref": "AWS::Region"
- },
- ":",
- {
- "Ref": "AWS::AccountId"
- },
- ":log-group:/aws/lambda/*"
- ]
- ]
- }
- },
- {
- "Action": [
- "s3:putBucketAcl",
- "s3:putEncryptionConfiguration",
- "s3:putBucketPolicy",
- "s3:CreateBucket",
- "s3:GetObject",
- "s3:PutObject",
- "s3:ListBucket"
- ],
- "Effect": "Allow",
- "Resource": {
- "Fn::Join": [
- "",
- [
- "arn:",
- {
- "Ref": "AWS::Partition"
- },
- ":s3:::*"
- ]
- ]
- }
- }
- ],
- "Version": "2012-10-17"
- },
- "PolicyName": {
- "Fn::Join": [
- "",
- [
- {
- "Ref": "AWS::StackName"
- },
- "CustomResourcePolicy"
- ]
- ]
- },
- "Roles": [
- {
- "Ref": "CustomResourceRole"
- }
- ]
- }
- },
- "CustomResourceFunction": {
- "Type": "AWS::Lambda::Function",
- "Properties": {
- "Code": {
- "S3Bucket": {
- "Fn::Join": [
- "",
- [
- "TEST-",
- {
- "Ref": "AWS::Region"
- }
- ]
- ]
- },
- "S3Key": "serverless-image-handler/TEST_VERSION/custom-resource.zip"
- },
- "Handler": "index.handler",
- "Role": {
- "Fn::GetAtt": [
- "CustomResourceRole",
- "Arn"
- ]
- },
- "Runtime": "nodejs12.x",
- "Description": "Serverless Image Handler - Custom resource",
- "Environment": {
- "Variables": {
- "RETRY_SECONDS": "5"
- }
- },
- "MemorySize": 128,
- "Timeout": 60
- },
- "DependsOn": [
- "CustomResourceRole"
- ],
- "Metadata": {
- "cfn_nag": {
- "rules_to_suppress": [
- {
- "id": "W58",
- "reason": "False alarm: The Lambda function does have the permission to write CloudWatch Logs."
- }
- ]
- }
- }
- },
- "CustomResourceLogGroup": {
- "Type": "AWS::Logs::LogGroup",
- "Properties": {
- "LogGroupName": {
- "Fn::Join": [
- "",
- [
- "/aws/lambda/",
- {
- "Ref": "CustomResourceFunction"
- }
- ]
- ]
- },
- "RetentionInDays": {
- "Ref": "LogRetentionPeriod"
- }
- },
- "UpdateReplacePolicy": "Retain",
- "DeletionPolicy": "Retain",
- "Metadata": {
- "cfn_nag": {
- "rules_to_suppress": [
- {
- "id": "W84",
- "reason": "Used to store store function info, no kms used"
- }
- ]
- }
- }
- },
- "CustomResourceCopyS3": {
- "Type": "Custom::CustomResource",
- "Properties": {
- "ServiceToken": {
- "Fn::GetAtt": [
- "CustomResourceFunction",
- "Arn"
- ]
- },
- "Region": {
- "Ref": "AWS::Region"
- },
- "manifestKey": "serverless-image-handler/TEST_VERSION/demo-ui-manifest.json",
- "sourceS3Bucket": {
- "Fn::Join": [
- "",
- [
- "TEST-",
- {
- "Ref": "AWS::Region"
- }
- ]
- ]
- },
- "sourceS3key": "serverless-image-handler/TEST_VERSION/demo-ui",
- "destS3Bucket": {
- "Ref": "DemoBucket"
- },
- "version": "TEST_VERSION",
- "customAction": "copyS3assets"
- },
- "DependsOn": [
- "CustomResourcePolicy",
- "CustomResourceRole"
- ],
- "Condition": "DeployDemoUICondition"
- },
- "CustomResourceConfig": {
- "Type": "Custom::CustomResource",
- "Properties": {
- "ServiceToken": {
- "Fn::GetAtt": [
- "CustomResourceFunction",
- "Arn"
- ]
- },
- "Region": {
- "Ref": "AWS::Region"
- },
- "configItem": {
- "apiEndpoint": {
- "Fn::Join": [
- "",
- [
- "https://",
- {
- "Fn::GetAtt": [
- "ImageHandlerDistribution",
- "DomainName"
- ]
- }
- ]
- ]
- }
- },
- "destS3Bucket": {
- "Ref": "DemoBucket"
- },
- "destS3key": "demo-ui-config.js",
- "customAction": "putConfigFile"
- },
- "DependsOn": [
- "CustomResourcePolicy",
- "CustomResourceRole"
- ],
- "Condition": "DeployDemoUICondition"
- },
- "CustomResourceUuid": {
- "Type": "Custom::CustomResource",
- "Properties": {
- "ServiceToken": {
- "Fn::GetAtt": [
- "CustomResourceFunction",
- "Arn"
- ]
- },
- "Region": {
- "Ref": "AWS::Region"
- },
- "customAction": "createUuid"
- },
- "DependsOn": [
- "CustomResourcePolicy",
- "CustomResourceRole"
- ]
- },
- "CustomResourceAnonymousMetric": {
- "Type": "Custom::CustomResource",
- "Properties": {
- "ServiceToken": {
- "Fn::GetAtt": [
- "CustomResourceFunction",
- "Arn"
- ]
- },
- "Region": {
- "Ref": "AWS::Region"
- },
- "solutionId": "SO0023",
- "UUID": {
- "Fn::GetAtt": [
- "CustomResourceUuid",
- "UUID"
- ]
- },
- "version": "TEST_VERSION",
- "anonymousData": {
- "Fn::FindInMap": [
- "Send",
- "AnonymousUsage",
- "Data"
- ]
- },
- "enableSignature": {
- "Ref": "EnableSignature"
- },
- "enableDefaultFallbackImage": {
- "Ref": "EnableDefaultFallbackImage"
- },
- "customAction": "sendMetric"
- },
- "DependsOn": [
- "CustomResourcePolicy",
- "CustomResourceRole"
- ]
- },
- "CustomResourceCheckSourceBuckets": {
- "Type": "Custom::CustomResource",
- "Properties": {
- "ServiceToken": {
- "Fn::GetAtt": [
- "CustomResourceFunction",
- "Arn"
- ]
- },
- "Region": {
- "Ref": "AWS::Region"
- },
- "sourceBuckets": {
- "Ref": "SourceBuckets"
- },
- "customAction": "checkSourceBuckets"
- },
- "DependsOn": [
- "CustomResourcePolicy",
- "CustomResourceRole"
- ]
- },
- "SecretsManagerPolicy": {
- "Type": "AWS::IAM::Policy",
- "Properties": {
- "PolicyDocument": {
- "Statement": [
- {
- "Action": "secretsmanager:GetSecretValue",
- "Effect": "Allow",
- "Resource": {
- "Fn::Join": [
- "",
- [
- "arn:",
- {
- "Ref": "AWS::Partition"
- },
- ":secretsmanager:",
- {
- "Ref": "AWS::Region"
- },
- ":",
- {
- "Ref": "AWS::AccountId"
- },
- ":secret:",
- {
- "Ref": "SecretsManagerSecret"
- },
- "*"
- ]
- ]
- }
- }
- ],
- "Version": "2012-10-17"
- },
- "PolicyName": "SecretsManagerPolicy",
- "Roles": [
- {
- "Ref": "CustomResourceRole"
- },
- {
- "Ref": "ImageHandlerFunctionRole"
- }
- ]
- },
- "Condition": "EnableSignatureCondition"
- },
- "CustomResourceCheckSecretsManager": {
- "Type": "Custom::CustomResource",
- "Properties": {
- "ServiceToken": {
- "Fn::GetAtt": [
- "CustomResourceFunction",
- "Arn"
- ]
- },
- "customAction": "checkSecretsManager",
- "secretsManagerName": {
- "Ref": "SecretsManagerSecret"
- },
- "secretsManagerKey": {
- "Ref": "SecretsManagerKey"
- }
- },
- "DependsOn": [
- "CustomResourcePolicy",
- "CustomResourceRole",
- "SecretsManagerPolicy"
- ],
- "Condition": "EnableSignatureCondition"
- },
- "CustomResourceCheckFallbackImage": {
- "Type": "Custom::CustomResource",
- "Properties": {
- "ServiceToken": {
- "Fn::GetAtt": [
- "CustomResourceFunction",
- "Arn"
- ]
- },
- "customAction": "checkFallbackImage",
- "fallbackImageS3Bucket": {
- "Ref": "FallbackImageS3Bucket"
- },
- "fallbackImageS3Key": {
- "Ref": "FallbackImageS3Key"
- }
- },
- "DependsOn": [
- "CustomResourcePolicy",
- "CustomResourceRole"
- ],
- "Condition": "EnableDefaultFallbackImageCondition"
- },
- "CustomCFLoggingBucket": {
- "Type": "Custom::CustomResource",
- "Properties": {
- "ServiceToken": {
- "Fn::GetAtt": [
- "CustomResourceFunction",
- "Arn"
- ]
- },
- "customAction": "createCFLoggingBucket",
- "stackName": {
- "Ref": "AWS::StackName"
- },
- "bucketSuffix": {
- "Fn::Join": [
- "",
- [
- {
- "Ref": "AWS::StackName"
- },
- {
- "Ref": "AWS::Region"
- },
- {
- "Ref": "AWS::AccountId"
- }
- ]
- ]
- },
- "policy": {
- "Action": "*",
- "Condition": {
- "Bool": {
- "aws:SecureTransport": "false"
- }
- },
- "Effect": "Deny",
- "Principal": "*",
- "Resource": "",
- "Sid": "HttpsOnly"
- }
- },
- "DependsOn": [
- "CustomResourcePolicy",
- "CustomResourceRole"
- ],
- "Condition": "IsOptInRegion"
- }
- },
- "Outputs": {
- "ApiEndpoint": {
- "Description": "Link to API endpoint for sending image requests to.",
- "Value": {
- "Fn::Sub": "https://${ImageHandlerDistribution.DomainName}"
- }
- },
- "DemoUrl": {
- "Description": "Link to the demo user interface for the solution.",
- "Value": {
- "Fn::Sub": "https://${DemoDistribution.DomainName}/index.html"
- },
- "Condition": "DeployDemoUICondition"
- },
- "SourceBuckets": {
- "Description": "Amazon S3 bucket location containing original image files.",
- "Value": {
- "Ref": "SourceBuckets"
- }
- },
- "CorsEnabled": {
- "Description": "Indicates whether Cross-Origin Resource Sharing (CORS) has been enabled for the image handler API.",
- "Value": {
- "Ref": "CorsEnabled"
- }
- },
- "CorsOrigin": {
- "Description": "Origin value returned in the Access-Control-Allow-Origin header of image handler API responses.",
- "Value": {
- "Ref": "CorsOrigin"
- },
- "Condition": "EnableCorsCondition"
- },
- "LogRetentionPeriod": {
- "Description": "Number of days for event logs from Lambda to be retained in CloudWatch.",
- "Value": {
- "Ref": "LogRetentionPeriod"
- }
- }
- }
-}
\ No newline at end of file
diff --git a/source/constructs/tsconfig.json b/source/constructs/tsconfig.json
index a09f01808..08731a091 100644
--- a/source/constructs/tsconfig.json
+++ b/source/constructs/tsconfig.json
@@ -17,9 +17,10 @@
"inlineSources": true,
"experimentalDecorators": true,
"strictPropertyInitialization": false,
- "typeRoots": ["./node_modules/@types"],
"resolveJsonModule": true,
- "esModuleInterop": true
+ "esModuleInterop": true,
+ "typeRoots": ["./node_modules/@types"],
+ "skipLibCheck": true
},
"exclude": ["cdk.out"]
}
diff --git a/source/constructs/utils/aspects.ts b/source/constructs/utils/aspects.ts
new file mode 100644
index 000000000..9b7a64475
--- /dev/null
+++ b/source/constructs/utils/aspects.ts
@@ -0,0 +1,61 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+import { CfnFunction } from "aws-cdk-lib/aws-lambda";
+import { CfnCondition, CfnResource, IAspect } from "aws-cdk-lib";
+import { IConstruct } from "constructs";
+
+import { addCfnSuppressRules } from "./utils";
+
+/**
+ * CDK Aspect to add common CFN Nag rule suppressions to Lambda functions.
+ */
+export class SuppressLambdaFunctionCfnRulesAspect implements IAspect {
+ /**
+ * Implements IAspect.visit to suppress rules specific to a Lambda function.
+ * @param node Construct node to visit
+ */
+ visit(node: IConstruct): void {
+ const resource = node as CfnResource;
+ if (resource instanceof CfnFunction) {
+ const rules = [
+ {
+ id: "W58",
+ reason: "The function does have permission to write CloudWatch Logs.",
+ },
+ {
+ id: "W89",
+ reason: "The Lambda function does not require any VPC connection at all.",
+ },
+ {
+ id: "W92",
+ reason: "The Lambda function does not require ReservedConcurrentExecutions.",
+ },
+ ];
+
+ addCfnSuppressRules(resource, rules);
+ }
+ }
+}
+
+/**
+ * CDK Aspect implementation to set up conditions to the entire Construct resources.
+ */
+export class ConditionAspect implements IAspect {
+ private readonly condition: CfnCondition;
+
+ constructor(condition: CfnCondition) {
+ this.condition = condition;
+ }
+
+ /**
+ * Implements IAspect.visit to set the condition to whole resources in Construct.
+ * @param node Construct node to visit
+ */
+ visit(node: IConstruct): void {
+ const resource = node as CfnResource;
+ if (resource.cfnOptions) {
+ resource.cfnOptions.condition = this.condition;
+ }
+ }
+}
diff --git a/source/constructs/utils/utils.ts b/source/constructs/utils/utils.ts
new file mode 100644
index 000000000..1e9445001
--- /dev/null
+++ b/source/constructs/utils/utils.ts
@@ -0,0 +1,67 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+import { CfnCondition, CfnResource, Resource } from "aws-cdk-lib";
+
+interface CfnNagSuppressRule {
+ id: string;
+ reason: string;
+}
+
+/**
+ * Adds CFN NAG suppress rules to the CDK resource.
+ * @param resource The CDK resource.
+ * @param rules The CFN NAG suppress rules.
+ */
+export function addCfnSuppressRules(resource: Resource | CfnResource | undefined, rules: CfnNagSuppressRule[]) {
+ if (typeof resource === "undefined") return;
+
+ if (resource instanceof Resource) {
+ resource = resource.node.defaultChild as CfnResource;
+ }
+
+ if (resource.cfnOptions.metadata?.cfn_nag?.rules_to_suppress) {
+ resource.cfnOptions.metadata.cfn_nag.rules_to_suppress.push(...rules);
+ } else {
+ resource.addMetadata("cfn_nag", { rules_to_suppress: rules });
+ }
+}
+interface CfnGuardSuppressRule {
+ id: string;
+ reason: string;
+}
+
+/**
+ * Adds CFN Guard suppress rules to the CDK resource.
+ * @param resource The CDK resource.
+ * @param rules The CFN Guard suppress rules.
+ */
+export function addCfnGuardSuppressRules(resource: Resource | CfnResource | undefined, rules: CfnGuardSuppressRule[]) {
+ if (typeof resource === "undefined") return;
+
+ if (resource instanceof Resource) {
+ resource = resource.node.defaultChild as CfnResource;
+ }
+
+ const ruleNames = rules.map(rule => rule.id);
+
+ if (resource.cfnOptions.metadata?.guard?.SuppressedRules) {
+ resource.cfnOptions.metadata.guard.SuppressedRules.push(...ruleNames);
+ } else {
+ resource.addMetadata("guard", { SuppressedRules: ruleNames });
+ }
+}
+/**
+ * Adds CDK condition to the CDK resource.
+ * @param resource The CDK resource.
+ * @param condition The CDK condition.
+ */
+export function addCfnCondition(resource: Resource | CfnResource | undefined, condition: CfnCondition) {
+ if (typeof resource === "undefined") return;
+
+ if (resource instanceof Resource) {
+ resource = resource.node.defaultChild as CfnResource;
+ }
+
+ resource.cfnOptions.condition = condition;
+}
diff --git a/source/container/.dockerignore b/source/container/.dockerignore
new file mode 100644
index 000000000..a0812063a
--- /dev/null
+++ b/source/container/.dockerignore
@@ -0,0 +1,78 @@
+# Node.js
+node_modules/
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# Build outputs
+dist/
+build/
+*.tsbuildinfo
+
+# Development files
+.env
+.env.local
+.env.development
+.env.test
+.env.production
+
+# IDE and editor files
+.vscode/
+.idea/
+*.swp
+*.swo
+*~
+
+# OS generated files
+.DS_Store
+.DS_Store?
+._*
+.Spotlight-V100
+.Trashes
+ehthumbs.db
+Thumbs.db
+
+# Git
+.git/
+.gitignore
+
+# Docker
+Dockerfile*
+docker-compose*.yml
+.dockerignore
+
+# Testing
+coverage/
+.nyc_output/
+test/
+tests/
+**/*.test.ts
+**/*.test.js
+**/*.spec.ts
+**/*.spec.js
+jest.config.js
+
+# Documentation
+README.md
+CHANGELOG.md
+docs/
+
+# Logs
+logs/
+*.log
+
+# Runtime data
+pids/
+*.pid
+*.seed
+*.pid.lock
+
+# Optional npm cache directory
+.npm
+
+# ESLint cache
+.eslintcache
+
+# Prettier
+.prettierrc*
+.prettierignore
diff --git a/source/container/.eslintrc.json b/source/container/.eslintrc.json
new file mode 100644
index 000000000..c08f49341
--- /dev/null
+++ b/source/container/.eslintrc.json
@@ -0,0 +1,46 @@
+{
+ "root": true,
+ "env": {
+ "jest": true,
+ "node": true
+ },
+ "plugins": ["@typescript-eslint", "import", "header"],
+ "parser": "@typescript-eslint/parser",
+ "parserOptions": {
+ "ecmaVersion": "latest",
+ "sourceType": "module",
+ "project": "**/tsconfig.json"
+ },
+ "ignorePatterns": ["**/*.js", "**/node_modules/**"],
+ "extends": [
+ "eslint:recommended",
+ "plugin:@typescript-eslint/recommended",
+ "plugin:import/recommended",
+ "plugin:import/typescript",
+ "standard",
+ "plugin:jsdoc/recommended",
+ "plugin:prettier/recommended"
+ ],
+ "rules": {
+ "arrow-body-style": ["warn", "as-needed"],
+ "prefer-arrow-callback": ["warn"],
+ "no-inferrable-types": ["off", "ignore-params"],
+ "no-unused-vars": ["off"],
+ "no-useless-constructor": ["off"],
+ "no-throw-literal": ["off"],
+
+ "header/header": ["error", "line", [" Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.", " SPDX-License-Identifier: Apache-2.0"], 2],
+
+ "@typescript-eslint/no-inferrable-types": ["off", { "ignoreParameters": true, "ignoreProperties": true }],
+ "@typescript-eslint/no-useless-constructor": ["off"],
+ "@typescript-eslint/no-unused-vars": ["error", { "args": "none", "argsIgnorePattern": "^_", "varsIgnorePattern": "^_" }],
+ "@typescript-eslint/no-throw-literal": ["error"],
+
+ "jsdoc/require-param-type": ["off"],
+ "jsdoc/require-returns-type": ["off"],
+ "jsdoc/newline-after-description": ["off"],
+
+ "import/no-unresolved": 1, // warn only on Unable to resolve path import/no-unresolved
+ "dot-notation": "off"
+ }
+}
diff --git a/source/container/Dockerfile.dynamodb-local b/source/container/Dockerfile.dynamodb-local
new file mode 100644
index 000000000..c2fd9ae4a
--- /dev/null
+++ b/source/container/Dockerfile.dynamodb-local
@@ -0,0 +1,71 @@
+# DynamoDB Local on Amazon Linux 2023 Minimal + Corretto 17
+# Built from tar.gz instead of official Docker image to:
+# - Eliminate Python/pip/setuptools CVEs (not present in AL2023 minimal)
+# - Patch vulnerable Java dependency JARs shipped with DDBLocal 3.3.0
+#
+# JAR patching strategy:
+# The DynamoDBLocal.jar MANIFEST.MF Class-Path references dependency JARs by filename.
+# Netty JARs use version-stripped names (e.g., netty-codec-http-4.1.jar) — replace in-place.
+# Non-Netty JARs embed the full version in the filename (e.g., jackson-core-2.20.1.jar) —
+# download the fixed version and rename to match the manifest entry. Java resolves by
+# classpath entry, not filename, so the new JAR contents are loaded correctly.
+# Trivy/cdxgen detect versions from the JAR's internal MANIFEST.MF metadata, so the
+# scanner will see the patched version even though the filename hasn't changed.
+
+FROM public.ecr.aws/amazonlinux/amazonlinux:minimal
+
+# Install only the headless JRE + tools — minimal base has no Python, no pip, no setuptools
+# curl-minimal is pre-installed in the minimal base image
+RUN dnf install -y java-17-amazon-corretto-headless tar gzip && \
+ dnf clean all && rm -rf /var/cache/dnf
+
+# Patched dependency versions
+ARG NETTY_VERSION=4.1.132.Final
+ARG JACKSON_CORE_VERSION=2.21.1
+ARG JETTY_SERVER_VERSION=12.0.32
+ARG KOTLIN_STDLIB_VERSION=1.6.0
+
+# DynamoDB Local 3.3.0 — pinned via SHA256 checksum
+# If DDBLocal releases a new version, this build will fail loudly rather than
+# silently breaking the JAR patching below (which depends on specific filenames).
+# To update: download the new tar.gz, verify the new JAR filenames in the manifest,
+# update the patches below, then update this checksum.
+ARG DDBLOCAL_VERSION=3.3.0
+ARG DDBLOCAL_SHA256=c05dc320f4f9a6f90c6597bc4dc7239ab8200a6df0f280d9cbe4d5775943f898
+
+ARG DDBLOCAL_URL=https://d1ni2b6xgvw0s0.cloudfront.net/v2.x/dynamodb_local_latest.tar.gz
+ARG MAVEN=https://repo1.maven.org/maven2
+
+WORKDIR /home/dynamodblocal
+
+# Download and verify DynamoDB Local
+RUN curl -fSL -o dynamodb_local_latest.tar.gz "${DDBLOCAL_URL}" && \
+ echo "${DDBLOCAL_SHA256} dynamodb_local_latest.tar.gz" | sha256sum -c - && \
+ tar xzf dynamodb_local_latest.tar.gz && \
+ rm -f dynamodb_local_latest.tar.gz
+
+# Patch Netty JARs (version-stripped filenames in manifest — direct replacement)
+RUN curl -fSL -o DynamoDBLocal_lib/netty-codec-http-4.1.jar \
+ "${MAVEN}/io/netty/netty-codec-http/${NETTY_VERSION}/netty-codec-http-${NETTY_VERSION}.jar" && \
+ curl -fSL -o DynamoDBLocal_lib/netty-codec-http2-4.1.jar \
+ "${MAVEN}/io/netty/netty-codec-http2/${NETTY_VERSION}/netty-codec-http2-${NETTY_VERSION}.jar" && \
+ curl -fSL -o DynamoDBLocal_lib/netty-codec-smtp-4.1.jar \
+ "${MAVEN}/io/netty/netty-codec-smtp/${NETTY_VERSION}/netty-codec-smtp-${NETTY_VERSION}.jar"
+
+# Patch non-Netty JARs (full version in filename — download new, rename to old filename)
+# jackson-core 2.20.1 -> 2.21.1 (GHSA-72hv-8253-57qq: DoS via async parser)
+RUN curl -fSL -o DynamoDBLocal_lib/jackson-core-2.20.1.jar \
+ "${MAVEN}/com/fasterxml/jackson/core/jackson-core/${JACKSON_CORE_VERSION}/jackson-core-${JACKSON_CORE_VERSION}.jar"
+
+# jetty-server 12.0.31 -> 12.0.32 (CVE-2026-1605: DoS via unreleased JDK Inflater)
+RUN curl -fSL -o DynamoDBLocal_lib/jetty-server-12.0.31.jar \
+ "${MAVEN}/org/eclipse/jetty/jetty-server/${JETTY_SERVER_VERSION}/jetty-server-${JETTY_SERVER_VERSION}.jar"
+
+# kotlin-stdlib 1.5.32 -> 1.6.0 (CVE-2022-24329: dependency lock bypass)
+RUN curl -fSL -o DynamoDBLocal_lib/kotlin-stdlib-1.5.32.jar \
+ "${MAVEN}/org/jetbrains/kotlin/kotlin-stdlib/${KOTLIN_STDLIB_VERSION}/kotlin-stdlib-${KOTLIN_STDLIB_VERSION}.jar"
+
+EXPOSE 8000
+
+ENTRYPOINT ["java", "-Djava.library.path=./DynamoDBLocal_lib", "-jar", "DynamoDBLocal.jar"]
+CMD ["-sharedDb", "-inMemory"]
diff --git a/source/container/docker-compose.test.yml b/source/container/docker-compose.test.yml
new file mode 100644
index 000000000..4d0e42665
--- /dev/null
+++ b/source/container/docker-compose.test.yml
@@ -0,0 +1,14 @@
+version: '3.8'
+services:
+ dynamodb-local:
+ build:
+ context: .
+ dockerfile: Dockerfile.dynamodb-local
+ image: dynamodb-local-patched:latest
+ ports:
+ - "8000:8000"
+ healthcheck:
+ test: ["CMD-SHELL", "curl -f http://localhost:8000/ || exit 1"]
+ interval: 10s
+ timeout: 5s
+ retries: 3
\ No newline at end of file
diff --git a/source/container/dynamodb-checksums.txt b/source/container/dynamodb-checksums.txt
new file mode 100644
index 000000000..9b57622b5
--- /dev/null
+++ b/source/container/dynamodb-checksums.txt
@@ -0,0 +1,6 @@
+1125086301253b89539fa3bdbf1ded0656c596a2d34e0ca3c10af83373e7fd88 *dynamodb_local_3.0.0.tar.gz
+5ab6c54ff5609e10850e52baa1b504fea719ed486e58e8cecaa09fda18c9695a netty-codec-smtp-4.2.7.Final.jar
+c98254983dffa9c62bccb0e39638e1138feb4dd7b46e7a663e790f6a070a9306 netty-codec-http2-4.2.7.Final.jar
+5f369658381789998c042a98f02da71d9c39884bbb4f7fd58282f765e09ca031 netty-codec-4.2.7.Final.jar
+2984dd38420a61c4dd68fcacc51ffc528eb46f73f7795cdafdb3a4d6fcb76862 netty-codec-http-4.2.7.Final.jar
+4eeeae8d20c078abb64b015ec158add383ac581571cddc45c68f0c9ae0230720 commons-lang3-3.18.0.jar
\ No newline at end of file
diff --git a/source/container/jest.config.js b/source/container/jest.config.js
new file mode 100644
index 000000000..e4e24054f
--- /dev/null
+++ b/source/container/jest.config.js
@@ -0,0 +1,36 @@
+/** @type {import('jest').Config} */
+module.exports = {
+ preset: 'ts-jest',
+ testEnvironment: 'node',
+ roots: ['/src'],
+ testMatch: [
+ '**/test/**/docker-health.test.ts', // Docker and container health tests only
+ '**/__tests__/**/*.ts', // Future unit tests
+ '**/?(*.)+(spec|test).ts' // Future unit tests (excluding docker-health.test.ts)
+ ],
+ transform: {
+ '^.+\\.ts$': 'ts-jest',
+ },
+ collectCoverageFrom: [
+ 'src/**/*.ts',
+ '!src/**/*.d.ts',
+ '!src/test/**/*', // Exclude all test files from coverage
+ '!src/**/*.test.ts',
+ '!src/**/*.spec.ts'
+ ],
+ coverageDirectory: 'coverage',
+ coverageReporters: [
+ 'text',
+ ['lcov', { 'projectRoot': '../' }],
+ 'html'
+ ],
+ testTimeout: 90000, // Extended timeout for Docker operations
+ verbose: true,
+ // AWS SDK v3 mocking support (for future unit tests)
+ moduleNameMapper: {
+ '^@dit/(.*)$': '/../node_modules/@dit/$1'
+ },
+ // Clear mocks between tests
+ clearMocks: true,
+ restoreMocks: true
+};
diff --git a/source/container/jest.e2e.config.js b/source/container/jest.e2e.config.js
new file mode 100644
index 000000000..16f406155
--- /dev/null
+++ b/source/container/jest.e2e.config.js
@@ -0,0 +1,13 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+module.exports = {
+ preset: 'ts-jest',
+ testEnvironment: 'node',
+ testMatch: ['**/test/e2e/**/*.e2e.test.ts'],
+ globalSetup: '/test/e2e/setup/global-setup.ts',
+ globalTeardown: '/test/e2e/setup/global-teardown.ts',
+ testTimeout: 60000,
+ maxWorkers: 1,
+ verbose: true
+};
diff --git a/source/container/jest.integration.config.js b/source/container/jest.integration.config.js
new file mode 100644
index 000000000..379389cfe
--- /dev/null
+++ b/source/container/jest.integration.config.js
@@ -0,0 +1,15 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+module.exports = {
+ preset: 'ts-jest',
+ testEnvironment: 'node',
+ testMatch: ['**/test/integration/**/*.test.ts'],
+ setupFilesAfterEnv: ['/test/integration/setup/jest-setup.ts'],
+ testTimeout: 30000,
+ collectCoverageFrom: [
+ 'src/**/*.ts',
+ '!src/**/*.d.ts',
+ ],
+ coverageDirectory: 'coverage/integration'
+};
\ No newline at end of file
diff --git a/source/container/package.json b/source/container/package.json
new file mode 100644
index 000000000..9f10d0d5e
--- /dev/null
+++ b/source/container/package.json
@@ -0,0 +1,68 @@
+{
+ "name": "dit-container",
+ "description": "Dynamic Image Transformation ECS Container",
+ "main": "dist/server.js",
+ "scripts": {
+ "build": "tsc",
+ "start": "node dist/server.js",
+ "dev": "ts-node src/server.ts",
+ "clean": "rm -rf node_modules/ dist/ coverage/",
+ "pretest": "npm run clean && npm ci",
+ "test": "jest --coverage",
+ "test:watch": "jest --watch",
+ "test:coverage": "jest --coverage",
+ "test:integration": "docker build --no-cache -f Dockerfile.dynamodb-local -t dynamodb-local-patched:latest . && docker-compose -f docker-compose.test.yml up -d && NODE_OPTIONS='--experimental-vm-modules' jest --config jest.integration.config.js && docker-compose -f docker-compose.test.yml down",
+ "test:integration:watch": "docker-compose -f docker-compose.test.yml up -d && NODE_OPTIONS='--experimental-vm-modules' jest --config jest.integration.config.js --watch",
+ "test:e2e": "jest --config jest.e2e.config.js",
+ "lint": "eslint src/**/*.ts",
+ "lint:fix": "eslint src/**/*.ts --fix"
+ },
+ "dependencies": {
+ "@aws-sdk/client-dynamodb": "^3.993.0",
+ "@aws-sdk/client-rekognition": "^3.993.0",
+ "@aws-sdk/client-s3": "^3.993.0",
+ "@aws-sdk/lib-dynamodb": "^3.993.0",
+ "@aws-sdk/util-dynamodb": "^3.993.0",
+ "@dit/data-models": "*",
+ "color": "4.2.3",
+ "compression": "^1.7.4",
+ "cors": "^2.8.5",
+ "express": "^4.18.2",
+ "helmet": "^7.1.0",
+ "morgan": "^1.10.1",
+ "qs": "^6.14.2",
+ "sharp": "^0.34.3",
+ "zod": "^4.1.4"
+ },
+ "devDependencies": {
+ "@aws-sdk/client-cloudformation": "^3.993.0",
+ "@aws-sdk/client-ecs": "^3.993.0",
+ "@eslint/js": "^9.0.0",
+ "@types/compression": "^1.7.4",
+ "@types/cors": "^2.8.15",
+ "@types/express": "^4.17.20",
+ "@types/jest": "^29.5.6",
+ "@types/node": "^20.8.0",
+ "@typescript-eslint/eslint-plugin": "^6.9.0",
+ "@typescript-eslint/parser": "^6.9.0",
+ "aws-sdk-client-mock": "^3.0.0",
+ "eslint": "^8.52.0",
+ "jest": "^29.7.0",
+ "ts-jest": "^29.1.1",
+ "ts-node": "^10.9.1",
+ "tsx": "^4.20.6",
+ "typescript": "^5.2.2"
+ },
+ "overrides": {
+ "brace-expansion": "2.0.3",
+ "brace-expansion@1": "1.1.13",
+ "brace-expansion@2": "2.0.3",
+ "picomatch@2": "2.3.2",
+ "picomatch@4": "4.0.4"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "author": "AWS Solutions",
+ "license": "Apache-2.0"
+}
diff --git a/source/container/src/app.ts b/source/container/src/app.ts
new file mode 100644
index 000000000..99eab6b30
--- /dev/null
+++ b/source/container/src/app.ts
@@ -0,0 +1,54 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+import express from 'express';
+import cors from 'cors';
+import helmet from 'helmet';
+import compression from 'compression';
+import morgan from 'morgan';
+import routes from './routes';
+import { initializeContainer } from './services/initialization';
+import { queryTypesMiddleware } from './middleware/query-types';
+
+// Create Express application
+const app = express();
+
+// Security middleware
+app.use(helmet());
+
+// CORS middleware
+app.use(cors());
+
+// Compression middleware
+app.use(compression());
+
+// QS + Query-types custom middleware
+app.use(queryTypesMiddleware())
+
+// Logging middleware
+app.use(morgan('combined'));
+
+// Body parsing middleware
+app.use(express.json({ limit: '10mb' }));
+app.use(express.urlencoded({ extended: true, limit: '10mb' }));
+
+// Initialize container services
+initializeContainer().catch(error => {
+ console.error('Failed to initialize container:', error);
+});
+
+// Use routes from routes directory
+app.use('/', routes);
+
+// Global error handler
+app.use((err: Error, req: express.Request, res: express.Response, next: express.NextFunction) => {
+ console.error('Unhandled error:', err);
+
+ res.status(500).json({
+ error: 'Internal Server Error',
+ message: process.env.NODE_ENV === 'development' ? err.message : 'Something went wrong',
+ timestamp: new Date().toISOString()
+ });
+});
+
+export default app;
diff --git a/source/container/src/middleware/query-types.test.ts b/source/container/src/middleware/query-types.test.ts
new file mode 100644
index 000000000..3a18ec835
--- /dev/null
+++ b/source/container/src/middleware/query-types.test.ts
@@ -0,0 +1,132 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+import { queryTypesMiddleware } from './query-types';
+
+describe('queryTypesMiddleware', () => {
+ const createMockReq = (url: string) => ({ url, query: {} as Record });
+ const mockRes = {};
+ const mockNext = jest.fn();
+
+ beforeEach(() => {
+ mockNext.mockClear();
+ });
+
+ describe('middleware behavior', () => {
+ it('Should call next() after parsing', () => {
+ const req = createMockReq('/path?foo=bar');
+ queryTypesMiddleware()(req, mockRes, mockNext);
+ expect(mockNext).toHaveBeenCalledTimes(1);
+ });
+
+ it('Should handle empty query string', () => {
+ const req = createMockReq('/path');
+ queryTypesMiddleware()(req, mockRes, mockNext);
+ expect(req.query).toEqual({});
+ });
+
+ it('Should handle URL without query params', () => {
+ const req = createMockReq('/path/to/image.jpg');
+ queryTypesMiddleware()(req, mockRes, mockNext);
+ expect(req.query).toEqual({});
+ });
+ });
+
+ describe('type parsing via parseObject', () => {
+ it('Should parse string values unchanged', () => {
+ const req = createMockReq('/path?name=hello');
+ queryTypesMiddleware()(req, mockRes, mockNext);
+ expect(req.query).toEqual({ name: 'hello' });
+ });
+
+ it('Should parse numeric strings to numbers', () => {
+ const req = createMockReq('/path?width=100&height=200');
+ queryTypesMiddleware()(req, mockRes, mockNext);
+ expect(req.query).toEqual({ width: 100, height: 200 });
+ });
+
+ it('Should parse float values', () => {
+ const req = createMockReq('/path?ratio=1.5');
+ queryTypesMiddleware()(req, mockRes, mockNext);
+ expect(req.query).toEqual({ ratio: 1.5 });
+ });
+
+ it('Should parse boolean true', () => {
+ const req = createMockReq('/path?enabled=true');
+ queryTypesMiddleware()(req, mockRes, mockNext);
+ expect(req.query).toEqual({ enabled: true });
+ });
+
+ it('Should parse boolean false', () => {
+ const req = createMockReq('/path?enabled=false');
+ queryTypesMiddleware()(req, mockRes, mockNext);
+ expect(req.query).toEqual({ enabled: false });
+ });
+
+ it('Should parse empty value as null', () => {
+ const req = createMockReq('/path?empty=');
+ queryTypesMiddleware()(req, mockRes, mockNext);
+ expect(req.query).toEqual({ empty: null });
+ });
+
+ it('Should parse mixed types', () => {
+ const req = createMockReq('/path?str=hello&num=42&bool=true');
+ queryTypesMiddleware()(req, mockRes, mockNext);
+ expect(req.query).toEqual({ str: 'hello', num: 42, bool: true });
+ });
+ });
+
+ describe('array parsing', () => {
+ it('Should parse comma-separated values as array', () => {
+ const req = createMockReq('/path?items=a,b,c');
+ queryTypesMiddleware()(req, mockRes, mockNext);
+ expect(req.query).toEqual({ items: ['a', 'b', 'c'] });
+ });
+
+ it('Should parse qs-style arrays', () => {
+ const req = createMockReq('/path?items[0]=a&items[1]=b');
+ queryTypesMiddleware()(req, mockRes, mockNext);
+ expect(req.query).toEqual({ items: ['a', 'b'] });
+ });
+
+ it('Should parse qs-style arrays with numeric values', () => {
+ const req = createMockReq('/path?items[0]=1&items[1]=2&items[2]=3');
+ queryTypesMiddleware()(req, mockRes, mockNext);
+ expect(req.query).toEqual({ items: [1, 2, 3] });
+ });
+ });
+
+ describe('nested object parsing', () => {
+ it('Should parse nested objects', () => {
+ const req = createMockReq('/path?resize[width]=100&resize[height]=200');
+ queryTypesMiddleware()(req, mockRes, mockNext);
+ expect(req.query).toEqual({ resize: { width: 100, height: 200 } });
+ });
+
+ it('Should parse deeply nested objects up to depth limit', () => {
+ const req = createMockReq('/path?a[b][c]=value');
+ queryTypesMiddleware()(req, mockRes, mockNext);
+ expect(req.query).toEqual({ a: { b: { c: 'value' } } });
+ });
+ });
+
+ describe('edge cases', () => {
+ it('Should handle special characters in values', () => {
+ const req = createMockReq('/path?path=/images/test.jpg');
+ queryTypesMiddleware()(req, mockRes, mockNext);
+ expect(req.query.path).toBe('/images/test.jpg');
+ });
+
+ it('Should handle encoded special characters', () => {
+ const req = createMockReq('/path?name=hello%20world');
+ queryTypesMiddleware()(req, mockRes, mockNext);
+ expect(req.query.name).toBe('hello world');
+ });
+
+ it('Should handle string with only comma', () => {
+ const req = createMockReq('/path?val=a,b');
+ queryTypesMiddleware()(req, mockRes, mockNext);
+ expect(req.query).toEqual({ val: ['a', 'b'] });
+ });
+ });
+});
diff --git a/source/container/src/middleware/query-types.ts b/source/container/src/middleware/query-types.ts
new file mode 100644
index 000000000..4862abfce
--- /dev/null
+++ b/source/container/src/middleware/query-types.ts
@@ -0,0 +1,132 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+// Credit to xpepermint: https://github.com/xpepermint/query-types
+const MAX_ARRAY_LENGTH = 25;
+
+function isObject(val) {
+ return val.constructor === Object;
+}
+
+function isNumber(val) {
+ return !isNaN(parseFloat(val)) && isFinite(val);
+}
+
+function isBoolean(val) {
+ return val === 'false' || val === 'true';
+}
+
+function isArray(val) {
+ return Array.isArray(val);
+}
+
+function parseValue(val) {
+ if (typeof val == 'undefined' || val === '') {
+ return null;
+ } else if (typeof val === 'string' && (val.includes('[') || val.includes(','))) {
+ return parseNestedArray(val);
+ } else if (isBoolean(val)) {
+ return parseBoolean(val);
+ } else if (isArray(val)) {
+ return parseArray(val);
+ } else if (isObject(val)) {
+ return parseObject(val);
+ } else if (isNumber(val)) {
+ return parseNumber(val);
+ } else {
+ return val;
+ }
+}
+
+function parseObject(obj) {
+ var result = {};
+ var key, val;
+ for (key in obj) {
+ val = parseValue(obj[key]);
+ result[key] = val;
+ }
+ return result;
+}
+
+function parseArray(arr) {
+ var result = [];
+ for (var i = 0; i < arr.length; i++) {
+ result[i] = parseValue(arr[i]);
+ }
+ return result;
+}
+
+function parseNumber(val) {
+ return Number(val);
+}
+
+function parseBoolean(val) {
+ return val === 'true';
+}
+
+function parseNestedArray(val) {
+ // If no brackets and has comma, treat as simple comma-separated array
+ if (!val.includes('[') && val.includes(',')) {
+ return val.split(',').slice(0, MAX_ARRAY_LENGTH).map(item => parseValue(item.trim()));
+ }
+
+ // Strip outer brackets if entire string is wrapped
+ if (val.startsWith('[') && val.endsWith(']')) {
+ val = val.slice(1, -1);
+ }
+
+ const parts = [];
+ let current = '';
+ let bracketDepth = 0;
+
+ for (let i = 0; i < val.length; i++) {
+ const char = val[i];
+
+ if (char === '[') {
+ bracketDepth++;
+ current += char;
+ } else if (char === ']') {
+ bracketDepth--;
+ current += char;
+ } else if (char === ',' && bracketDepth === 0) {
+ parts.push(current.trim());
+ current = '';
+ } else {
+ current += char;
+ }
+ }
+
+ if (current) parts.push(current.trim());
+
+ const result = parts.map(part => {
+ if (part.startsWith('[') && part.endsWith(']')) {
+ const inner = part.slice(1, -1);
+ return inner.split(',').slice(0, MAX_ARRAY_LENGTH).map(item => parseValue(item.trim()));
+ }
+ return parseValue(part);
+ });
+
+ return result.slice(0, MAX_ARRAY_LENGTH);
+}
+
+function queryTypesMiddleware() {
+ return function(req, res, next) {
+ const qs = require('qs');
+ const queryString = req.url.split('?')[1] || '';
+
+ const MAX_ARRAY_LENGTH = 10;
+
+ const parsedQuery = qs.parse(queryString, {
+ parameterLimit: 50,
+ depth: 2,
+ arrayLimit: MAX_ARRAY_LENGTH,
+ ignoreQueryPrefix: true,
+ comma: false
+ });
+
+ req.query = parseObject(parsedQuery);
+ next();
+ }
+}
+
+export { queryTypesMiddleware };
\ No newline at end of file
diff --git a/source/container/src/routes/health.ts b/source/container/src/routes/health.ts
new file mode 100644
index 000000000..504b69c02
--- /dev/null
+++ b/source/container/src/routes/health.ts
@@ -0,0 +1,68 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+import { Router, Request, Response } from 'express';
+import { initializationState } from '../services/initialization';
+import { CacheRegistry } from '../services/cache/cache-registry';
+
+const router = Router();
+// Health check endpoint
+router.get('/', async (req: Request, res: Response) => {
+ const { status, currentStep, completedCaches, error, startTime, completionTime } = initializationState;
+
+ const baseResponse = {
+ timestamp: new Date().toISOString(),
+ status,
+ };
+
+ if (status === 'HEALTHY') {
+ const duration = completionTime ? completionTime.getTime() - startTime.getTime() : 0;
+ const showCacheContents = process.env.SHOW_CACHE_CONTENTS === 'true';
+
+ //Used for development to display cache contents. Output not effected when flag is ommited or false.
+ let cachedContents = showCacheContents ? await getCacheContents() : null;
+
+ let healthResponse = {
+ ...baseResponse,
+ initializationDuration: `${duration}ms`,
+ completedCaches,
+ ...cachedContents
+ };
+
+ return res.status(200).json(healthResponse);
+ }
+
+ if (status === 'INITIALIZING') {
+ return res.status(503).json({
+ ...baseResponse,
+ currentStep,
+ completedCaches,
+ });
+ }
+
+ if (status === 'UNHEALTHY') {
+ return res.status(503).json({
+ ...baseResponse,
+ error: error?.message,
+ completedCaches,
+ });
+ }
+
+ // UNKNOWN status (default)
+ return res.status(503).json({
+ ...baseResponse,
+ message: 'Container initialization not started',
+ });
+});
+
+const getCacheContents = async () => {
+ const registry = CacheRegistry.getInstance();
+ return {
+ policies: await registry.getPolicyCache().getContents(),
+ origins: await registry.getOriginCache().getContents(),
+ pathMappings: await registry.getPathMappingCache().getContents(),
+ headerMappings: await registry.getHeaderMappingCache().getContents()
+ };
+};
+
+export default router;
diff --git a/source/container/src/routes/image.test.ts b/source/container/src/routes/image.test.ts
new file mode 100644
index 000000000..41bf1a8d9
--- /dev/null
+++ b/source/container/src/routes/image.test.ts
@@ -0,0 +1,161 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+import { handleError, filterClientHeaders } from './image';
+import { ValidationError } from '../services/request-resolver/errors/validation.error';
+import { OriginNotFoundError } from '../services/request-resolver/errors/origin-not-found.error';
+import { ConnectionError } from '../services/request-resolver/errors/connection.error';
+import { PolicyNotFoundError } from '../services/transformation-resolver/errors/policy-not-found.error';
+import { ImageProcessingError } from '../services/image-processing/types';
+
+describe('handleError', () => {
+ const requestId = 'test-request-id';
+ const startTime = Date.now();
+
+ beforeEach(() => {
+ jest.spyOn(console, 'error').mockImplementation();
+ });
+
+ afterEach(() => {
+ jest.restoreAllMocks();
+ });
+
+ it('Should return 400 for ValidationError', () => {
+ const error = new ValidationError('Invalid input', 'Detailed validation message');
+
+ const result = handleError(error, requestId, startTime);
+
+ expect(result.statusCode).toBe(400);
+ expect(result.errorType).toBe('VALIDATION_ERROR');
+ expect(result.clientMessage).toBe('Invalid input');
+ });
+
+ it('Should return status from OriginNotFoundError', () => {
+ const error = new OriginNotFoundError('Origin not found', 404, 'Verbose origin message');
+
+ const result = handleError(error, requestId, startTime);
+
+ expect(result.statusCode).toBe(404);
+ expect(result.errorType).toBe('ORIGIN_NOT_FOUND');
+ expect(result.clientMessage).toBe('Origin not found');
+ });
+
+ it('Should return status and errorType from ConnectionError', () => {
+ const error = new ConnectionError('Connection failed', 'Verbose connection error', 503, 'UPSTREAM_ERROR');
+
+ const result = handleError(error, requestId, startTime);
+
+ expect(result.statusCode).toBe(503);
+ expect(result.errorType).toBe('UPSTREAM_ERROR');
+ expect(result.clientMessage).toBe('Connection failed');
+ });
+
+ it('Should return 404 for PolicyNotFoundError', () => {
+ const error = new PolicyNotFoundError('Policy xyz not found');
+
+ const result = handleError(error, requestId, startTime);
+
+ expect(result.statusCode).toBe(404);
+ expect(result.errorType).toBe('POLICY_NOT_FOUND');
+ expect(result.clientMessage).toBe('Policy xyz not found');
+ });
+
+ it('Should return status and errorType from ImageProcessingError', () => {
+ const originalError = new Error('Sharp failed');
+ const error = new ImageProcessingError(422, 'PROCESSING_FAILED', 'Image processing failed', 'Verbose desc', originalError);
+
+ const result = handleError(error, requestId, startTime);
+
+ expect(result.statusCode).toBe(422);
+ expect(result.errorType).toBe('PROCESSING_FAILED');
+ expect(result.clientMessage).toBe('Image processing failed');
+ });
+
+ it('Should return 500 for generic Error', () => {
+ const error = new Error('Something went wrong');
+
+ const result = handleError(error, requestId, startTime);
+
+ expect(result.statusCode).toBe(500);
+ expect(result.errorType).toBe('INTERNAL_ERROR');
+ expect(result.clientMessage).toBe('An unexpected error occurred while processing your request');
+ });
+
+ it('Should return 500 for non-Error values', () => {
+ const error = 'string error';
+
+ const result = handleError(error, requestId, startTime);
+
+ expect(result.statusCode).toBe(500);
+ expect(result.errorType).toBe('INTERNAL_ERROR');
+ expect(result.clientMessage).toBe('An unexpected error occurred while processing your request');
+ });
+});
+
+describe('filterClientHeaders', () => {
+ it('Should exclude host header', () => {
+ const headers = { host: 'example.com', 'x-custom': 'value' };
+
+ const result = filterClientHeaders(headers);
+
+ expect(result).toEqual({ 'x-custom': 'value' });
+ });
+
+ it('Should exclude accept header', () => {
+ const headers = { accept: 'image/*', 'x-custom': 'value' };
+
+ const result = filterClientHeaders(headers);
+
+ expect(result).toEqual({ 'x-custom': 'value' });
+ });
+
+ it('Should handle case-insensitive exclusion', () => {
+ const headers = { Host: 'example.com', Accept: 'image/*', 'x-custom': 'value' };
+
+ const result = filterClientHeaders(headers);
+
+ expect(result).toEqual({ 'x-custom': 'value' });
+ });
+
+ it('Should limit to 50 headers', () => {
+ const headers: Record = {};
+ for (let i = 0; i < 60; i++) {
+ headers[`header-${i}`] = `value-${i}`;
+ }
+
+ const result = filterClientHeaders(headers);
+
+ expect(Object.keys(result).length).toBe(50);
+ });
+
+ it('Should exclude headers with values exceeding 1024 characters', () => {
+ const longValue = 'x'.repeat(1025);
+ const headers = { 'x-long': longValue, 'x-short': 'ok' };
+
+ const result = filterClientHeaders(headers);
+
+ expect(result).toEqual({ 'x-short': 'ok' });
+ });
+
+ it('Should take first element from array header values', () => {
+ const headers = { 'x-multi': ['first', 'second'] };
+
+ const result = filterClientHeaders(headers);
+
+ expect(result).toEqual({ 'x-multi': 'first' });
+ });
+
+ it('Should return empty object for empty input', () => {
+ const result = filterClientHeaders({});
+
+ expect(result).toEqual({});
+ });
+
+ it('Should exclude headers with empty string values', () => {
+ const headers = { 'x-empty': '', 'x-valid': 'value' };
+
+ const result = filterClientHeaders(headers);
+
+ expect(result).toEqual({ 'x-valid': 'value' });
+ });
+});
diff --git a/source/container/src/routes/image.ts b/source/container/src/routes/image.ts
new file mode 100644
index 000000000..b5beaec8e
--- /dev/null
+++ b/source/container/src/routes/image.ts
@@ -0,0 +1,193 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+import { Router, Request, Response } from 'express';
+import { RequestResolverService } from '../services/request-resolver/request-resolver.service';
+import { TransformationResolverService } from '../services/transformation-resolver/transformation-resolver.service';
+import { ImageProcessorService } from '../services/image-processing/image-processor.service';
+import { ImageProcessingRequest } from '../types/image-processing-request';
+import { randomUUID } from 'crypto';
+import { ValidationError } from '../services/request-resolver/errors/validation.error';
+import { OriginNotFoundError } from '../services/request-resolver/errors/origin-not-found.error';
+import { ConnectionError } from '../services/request-resolver/errors/connection.error';
+import { PolicyNotFoundError } from '../services/transformation-resolver/errors/policy-not-found.error';
+import { ImageProcessingError } from '../services/image-processing/types';
+
+const router = Router();
+
+// Headers to exclude from forwarding
+const EXCLUDED_HEADERS: string[] = ['host', 'accept'];
+
+// Memory protection limits
+const MAX_HEADERS = 50;
+const MAX_HEADER_VALUE_LENGTH = 1024;
+
+// Wildcard route handler for all image requests
+router.get('*', async (req: Request, res: Response) => {
+ const startTime = Date.now();
+ let imageRequest: ImageProcessingRequest | undefined;
+ const { CORS_ORIGIN } = process.env;
+
+ try {
+ // Initialize shared request object
+ imageRequest = {
+ requestId: randomUUID(),
+ timestamp: Date.now(),
+ clientHeaders: filterClientHeaders(req.headers),
+ response: { headers: {} },
+ timings: {}
+ };
+
+ console.log(JSON.stringify({
+ requestId: imageRequest.requestId,
+ component: 'ImageRouter',
+ operation: 'request_start',
+ path: req.path,
+ method: req.method
+ }));
+
+ // Step 1: Request Resolution
+ const requestResolver = RequestResolverService.getInstance();
+ await requestResolver.resolve(req, imageRequest);
+
+ // Step 2: Transformation Resolution
+ const transformationResolver = TransformationResolverService.getInstance();
+ await transformationResolver.resolve(req, imageRequest);
+
+ // Step 3: Image Processing
+ const imageProcessor = ImageProcessorService.getInstance();
+ const processedImage = await imageProcessor.process(imageRequest);
+
+ // Send processed image response
+ res.set(imageRequest.response.headers);
+ if (CORS_ORIGIN) {
+ res.set('Access-Control-Allow-Origin', CORS_ORIGIN);
+ }
+ res.type(imageRequest.response.contentType || 'image/jpeg');
+ res.send(processedImage);
+
+ console.log(JSON.stringify({
+ requestId: imageRequest.requestId,
+ component: 'ImageRouter',
+ operation: 'request_complete',
+ duration: Date.now() - startTime,
+ statusCode: res.statusCode,
+ responseSize: processedImage.length,
+ contentType: imageRequest.response.contentType
+ }));
+
+ // Emit detailed latency breakdown
+ console.log(JSON.stringify({
+ metricType: 'request_latencies',
+ totalDurationMs: Date.now() - startTime,
+ preflightValidationMs: imageRequest.timings?.requestResolution?.preflightValidationMs,
+ transformationResolutionMs: imageRequest.timings?.transformationResolution?.durationMs,
+ originFetchMs: imageRequest.timings?.imageProcessing?.originFetchMs,
+ transformationApplicationMs: imageRequest.timings?.imageProcessing?.transformationApplicationMs,
+ requestId: imageRequest.requestId,
+ }));
+
+ } catch (error) {
+ const requestId = imageRequest?.requestId || 'unknown';
+ const { statusCode, errorType, clientMessage } = handleError(error, requestId, startTime);
+
+ res.status(statusCode).json({
+ error: errorType,
+ message: clientMessage,
+ requestId
+ });
+ }
+});
+
+export function handleError(error: unknown, requestId: string, startTime: number) {
+ let statusCode = 500;
+ let errorType = 'INTERNAL_ERROR';
+ let clientMessage = 'An unexpected error occurred while processing your request';
+ let verboseInfo: any = {};
+
+ if (!(error instanceof Error)) {
+ verboseInfo.unknownError = error;
+ } else {
+ switch (error.constructor) {
+ case ValidationError:
+ statusCode = 400;
+ errorType = 'VALIDATION_ERROR';
+ clientMessage = error.message;
+ verboseInfo.verboseMessage = (error as ValidationError).verboseMessage;
+ break;
+
+ case OriginNotFoundError:
+ statusCode = (error as OriginNotFoundError).statusCode;
+ errorType = 'ORIGIN_NOT_FOUND';
+ clientMessage = error.message;
+ verboseInfo.verboseMessage = (error as OriginNotFoundError).verboseMessage;
+ break;
+
+ case ConnectionError:
+ statusCode = (error as ConnectionError).statusCode;
+ errorType = (error as ConnectionError).errorType;
+ clientMessage = (error as ConnectionError).title;
+ verboseInfo.verboseDescription = (error as ConnectionError).verboseDescription;
+ break;
+
+ case PolicyNotFoundError:
+ statusCode = (error as PolicyNotFoundError).statusCode;
+ errorType = (error as PolicyNotFoundError).errorType;
+ clientMessage = error.message;
+ verboseInfo.verboseDescription = (error as PolicyNotFoundError).verboseDescription;
+ break;
+
+ case ImageProcessingError:
+ statusCode = (error as ImageProcessingError).statusCode;
+ errorType = (error as ImageProcessingError).errorType;
+ clientMessage = error.message;
+ verboseInfo.verboseDescription = (error as ImageProcessingError).verboseDescription;
+ verboseInfo.originalError = (error as ImageProcessingError).originalError?.message;
+ verboseInfo.originalStack = (error as ImageProcessingError).originalError?.stack;
+ break;
+
+ default:
+ verboseInfo.errorMessage = error.message;
+ verboseInfo.stack = error.stack;
+ }
+ }
+
+ console.error(JSON.stringify({
+ requestId,
+ component: 'ImageRouter',
+ operation: 'request_error',
+ duration: Date.now() - startTime,
+ statusCode,
+ errorType,
+ clientMessage,
+ ...verboseInfo,
+ stack: error instanceof Error ? error.stack : undefined
+ }));
+
+ return { statusCode, errorType, clientMessage };
+}
+
+/**
+ * Filters and limits client headers to prevent memory exhaustion attacks
+ */
+export function filterClientHeaders(headers: Record): Record {
+ const filtered: Record = {};
+ let headerCount = 0;
+
+ for (const [name, value] of Object.entries(headers)) {
+ if (headerCount >= MAX_HEADERS) break;
+
+ const lowerName = name.toLowerCase();
+ if (EXCLUDED_HEADERS.includes(lowerName)) continue;
+
+ const stringValue = Array.isArray(value) ? value[0] : value;
+ if (stringValue && stringValue.length <= MAX_HEADER_VALUE_LENGTH) {
+ filtered[name] = stringValue;
+ headerCount++;
+ }
+ }
+
+ return filtered;
+}
+
+export default router;
diff --git a/source/container/src/routes/index.ts b/source/container/src/routes/index.ts
new file mode 100644
index 000000000..807a295c3
--- /dev/null
+++ b/source/container/src/routes/index.ts
@@ -0,0 +1,16 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+import { Router } from 'express';
+import healthRoutes from './health';
+import imageRoutes from './image';
+
+const router = Router();
+
+// Health check route
+router.use('/health', healthRoutes);
+
+// Catch-all route for all image requests
+router.use('/', imageRoutes);
+
+export default router;
diff --git a/source/container/src/server.ts b/source/container/src/server.ts
new file mode 100644
index 000000000..edfb6e6fc
--- /dev/null
+++ b/source/container/src/server.ts
@@ -0,0 +1,60 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+import http from 'http';
+import app from './app';
+
+// Configuration
+const PORT = process.env.PORT || 3000;
+const HOST = process.env.HOST || '0.0.0.0';
+
+// Create HTTP server
+const server = http.createServer(app);
+
+// Server startup
+server.listen({ port: PORT, host: HOST }, () => {
+ console.log(`🚀 Server running on http://${HOST}:${PORT}`);
+ console.log(`📊 Environment: ${process.env.NODE_ENV || 'development'}`);
+ console.log(`🔧 Process ID: ${process.pid}`);
+ console.log(`💾 Memory usage: ${Math.round(process.memoryUsage().heapUsed / 1024 / 1024)} MB`);
+});
+
+// Graceful shutdown handling
+const gracefulShutdown = (signal: string) => {
+ console.log(`\n🛑 Received ${signal}. Starting graceful shutdown...`);
+
+ server.close((err) => {
+ if (err) {
+ console.error('❌ Error during server shutdown:', err);
+ process.exit(1);
+ }
+
+ console.log('✅ HTTP server closed');
+ console.log('👋 Graceful shutdown completed');
+ process.exit(0);
+ });
+
+ // Force shutdown after 30 seconds
+ setTimeout(() => {
+ console.error('⚠️ Forced shutdown after timeout');
+ process.exit(1);
+ }, 30000);
+};
+
+// Handle shutdown signals
+process.on('SIGTERM', () => gracefulShutdown('SIGTERM'));
+process.on('SIGINT', () => gracefulShutdown('SIGINT'));
+
+// Handle uncaught exceptions
+process.on('uncaughtException', (err) => {
+ console.error('💥 Uncaught Exception:', err);
+ gracefulShutdown('uncaughtException');
+});
+
+// Handle unhandled promise rejections
+process.on('unhandledRejection', (reason, promise) => {
+ console.error('💥 Unhandled Rejection at:', promise, 'reason:', reason);
+ gracefulShutdown('unhandledRejection');
+});
+
+export default server;
diff --git a/source/container/src/services/cache/cache-registry.ts b/source/container/src/services/cache/cache-registry.ts
new file mode 100644
index 000000000..3f5b075ef
--- /dev/null
+++ b/source/container/src/services/cache/cache-registry.ts
@@ -0,0 +1,57 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+import { PolicyCache } from './domain/policy-cache';
+import { OriginCache } from './domain/origin-cache';
+import { PathMappingCache } from './domain/path-mapping-cache';
+import { HeaderMappingCache } from './domain/header-mapping-cache';
+
+export class CacheRegistry {
+ private static instance: CacheRegistry;
+ private caches = new Map();
+
+ private constructor() {}
+
+ static getInstance(): CacheRegistry {
+ if (!CacheRegistry.instance) {
+ CacheRegistry.instance = new CacheRegistry();
+ }
+ return CacheRegistry.instance;
+ }
+
+ getPolicyCache(): PolicyCache {
+ return this.getCache('policy');
+ }
+
+ getOriginCache(): OriginCache {
+ return this.getCache('origin');
+ }
+
+ getPathMappingCache(): PathMappingCache {
+ return this.getCache('pathMapping');
+ }
+
+ getHeaderMappingCache(): HeaderMappingCache {
+ return this.getCache('headerMapping');
+ }
+
+ register(name: string, cache: T): void {
+ this.caches.set(name, cache);
+ }
+
+ get(name: string): T | undefined {
+ return this.caches.get(name) as T;
+ }
+
+ clear(): void {
+ this.caches.clear();
+ }
+
+ private getCache(name: string): T {
+ const cache = this.caches.get(name);
+ if (!cache) {
+ throw new Error(`Cache ${name} not found`);
+ }
+ return cache as T;
+ }
+}
\ No newline at end of file
diff --git a/source/container/src/services/cache/config/cache-defaults.ts b/source/container/src/services/cache/config/cache-defaults.ts
new file mode 100644
index 000000000..aeb372e09
--- /dev/null
+++ b/source/container/src/services/cache/config/cache-defaults.ts
@@ -0,0 +1,37 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+export interface CacheConfig {
+ name: string;
+}
+
+export interface TrieCacheConfig extends CacheConfig {
+ maxDepth: number;
+
+ pathSeparator: string;
+
+ /** Whether to allow prefix matching (true) or require exact/wildcard matches only (false) */
+ allowPrefixMatching: boolean;
+}
+
+export const POLICY_CACHE_CONFIG: CacheConfig = {
+ name: 'transformation-policies'
+};
+
+export const ORIGIN_CACHE_CONFIG: CacheConfig = {
+ name: 'origins'
+};
+
+export const HEADER_MAPPING_CACHE_CONFIG: TrieCacheConfig = {
+ name: 'header-mappings',
+ maxDepth: 10,
+ pathSeparator: '.',
+ allowPrefixMatching: false // Exact/wildcard only for security
+};
+
+export const PATH_MAPPING_CACHE_CONFIG: TrieCacheConfig = {
+ name: 'path-mappings',
+ maxDepth: 10,
+ pathSeparator: '/',
+ allowPrefixMatching: true // Allow prefix matching for paths
+};
diff --git a/source/container/src/services/cache/domain/header-mapping-cache.ts b/source/container/src/services/cache/domain/header-mapping-cache.ts
new file mode 100644
index 000000000..b148d6bb4
--- /dev/null
+++ b/source/container/src/services/cache/domain/header-mapping-cache.ts
@@ -0,0 +1,76 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+import { TrieCache } from '../implementations/trie-cache';
+import { HEADER_MAPPING_CACHE_CONFIG } from '../config/cache-defaults';
+import { getCacheKey } from '../utils/simplified-cache-key';
+import { DDBDriver } from '../../database/ddb-driver.interface';
+import { ddbDriver } from '../../database';
+
+/**
+ * Host-header mapping cache manager with transparent DynamoDB fallback.
+ * Uses trie structure for efficient hierarchical host-based lookups.
+ * Handles caching of host header to origin mappings.
+ */
+export class HeaderMappingCache {
+ private cache: TrieCache;
+ private ddbDriver: DDBDriver;
+
+ constructor() {
+ this.cache = new TrieCache(HEADER_MAPPING_CACHE_CONFIG);
+ this.ddbDriver = ddbDriver.instance;
+ }
+
+ /**
+ * Find the best matching header mapping using longest prefix matching
+ * This is the primary method for host-based origin resolution
+ */
+ async findBestMatch(hostHeader: string): Promise {
+ if (!hostHeader || hostHeader.trim() === '') {
+ return null;
+ }
+ return await this.cache.findLongestPrefix(hostHeader);
+ }
+
+ /**
+ * Manually cache a header mapping
+ */
+ async cacheHeaderMapping(mapping: HeaderMapping): Promise {
+ const cacheKey = getCacheKey(mapping.hostPattern);
+ await this.cache.set(cacheKey, mapping);
+ }
+
+ /**
+ * Remove header mapping from cache
+ */
+ async invalidateHeaderMapping(hostPattern: string): Promise {
+ const cacheKey = getCacheKey(hostPattern);
+ await this.cache.delete(cacheKey);
+ }
+
+ async getContents(): Promise {
+ return await this.cache.getAll();
+ }
+
+ async size(): Promise {
+ return await this.cache.size();
+ }
+
+ async warmCache(): Promise {
+ const mappings = await this.ddbDriver.getAllHeaderMappings();
+ for (const mapping of mappings) {
+ await this.cacheHeaderMapping(mapping);
+ }
+ }
+
+
+}
+
+/**
+ * Host-Header-Origin mapping configuration
+ */
+export interface HeaderMapping {
+ hostPattern: string;
+ originId: string;
+ policyId?: string;
+}
diff --git a/source/container/src/services/cache/domain/origin-cache.ts b/source/container/src/services/cache/domain/origin-cache.ts
new file mode 100644
index 000000000..8d30c5f71
--- /dev/null
+++ b/source/container/src/services/cache/domain/origin-cache.ts
@@ -0,0 +1,75 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+import { CacheManager } from '../interfaces/cache-manager';
+import { KeyValueCache } from '../implementations/key-value-cache';
+import { ORIGIN_CACHE_CONFIG } from '../config/cache-defaults';
+import { getCacheKey } from '../utils/simplified-cache-key';
+import { DDBDriver } from '../../database/ddb-driver.interface';
+import { ddbDriver } from '../../database';
+
+/**
+ * Origin cache manager with transparent DynamoDB fallback.
+ * Handles caching of origin configurations for HTTP-accessible image sources.
+ */
+export class OriginCache {
+ private cache: CacheManager;
+ private ddbDriver: DDBDriver;
+
+ constructor() {
+ this.cache = new KeyValueCache(ORIGIN_CACHE_CONFIG);
+ this.ddbDriver = ddbDriver.instance;
+ }
+
+ /**
+ * Get origin configuration by ID from cache only
+ */
+ async getOrigin(originId: string): Promise {
+ const cacheKey = getCacheKey(originId);
+ return await this.cache.get(cacheKey);
+ }
+
+ /**
+ * Manually cache an origin configuration
+ */
+ async cacheOrigin(origin: OriginConfiguration): Promise {
+ const cacheKey = getCacheKey(origin.originId);
+ await this.cache.set(cacheKey, origin);
+ }
+
+ /**
+ * Remove origin from cache
+ */
+ async invalidateOrigin(originId: string): Promise {
+ const cacheKey = getCacheKey(originId);
+ await this.cache.delete(cacheKey);
+ }
+
+ async getContents(): Promise {
+ return await this.cache.getAll();
+ }
+
+ async size(): Promise {
+ return await this.cache.size();
+ }
+
+ async warmCache(): Promise {
+ const origins = await this.ddbDriver.getAllOrigins();
+ for (const origin of origins) {
+ await this.cacheOrigin(origin);
+ }
+ }
+
+
+}
+
+/**
+ * Origin configuration for HTTP-accessible image sources
+ */
+export interface OriginConfiguration {
+ originId: string;
+ originName: string;
+ originDomain: string;
+ originPath?: string;
+ originHeaders?: Record;
+}
diff --git a/source/container/src/services/cache/domain/path-mapping-cache.ts b/source/container/src/services/cache/domain/path-mapping-cache.ts
new file mode 100644
index 000000000..10a7d6d90
--- /dev/null
+++ b/source/container/src/services/cache/domain/path-mapping-cache.ts
@@ -0,0 +1,82 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+import { TrieCache } from '../implementations/trie-cache';
+import { PATH_MAPPING_CACHE_CONFIG } from '../config/cache-defaults';
+import { getPathCacheKey } from '../utils/simplified-cache-key';
+import { DDBDriver } from '../../database/ddb-driver.interface';
+import { ddbDriver } from '../../database';
+
+/**
+ * Path mapping cache manager with transparent DynamoDB fallback.
+ * Uses trie structure for efficient hierarchical path-based lookups.
+ * Handles caching of path-to-policy/origin mappings for request routing.
+ */
+export class PathMappingCache {
+ private cache: TrieCache;
+ private ddbDriver: DDBDriver;
+
+ constructor() {
+ this.cache = new TrieCache(PATH_MAPPING_CACHE_CONFIG);
+ this.ddbDriver = ddbDriver.instance;
+ }
+
+ /**
+ * Find the best matching path mapping using longest prefix matching
+ * This is the primary method for request routing
+ */
+ async findBestMatch(requestPath: string): Promise {
+ return await this.cache.findLongestPrefix(requestPath);
+ }
+
+ /**
+ * Manually cache a path mapping
+ */
+ async cachePathMapping(mapping: PathMapping): Promise {
+ const cacheKey = getPathCacheKey(mapping.pathPattern);
+ await this.cache.set(cacheKey, mapping);
+ }
+
+ /**
+ * Remove path mapping from cache
+ */
+ async invalidatePathMapping(pathPattern: string): Promise {
+ const cacheKey = getPathCacheKey(pathPattern);
+ await this.cache.delete(cacheKey);
+ }
+
+ /**
+ * Bulk cache path mappings (useful for warming cache)
+ */
+ async bulkCachePathMappings(mappings: PathMapping[]): Promise {
+ for (const mapping of mappings) {
+ await this.cachePathMapping(mapping);
+ }
+ }
+
+ async getContents(): Promise {
+ return await this.cache.getAll();
+ }
+
+ async size(): Promise {
+ return await this.cache.size();
+ }
+
+ async warmCache(): Promise {
+ const mappings = await this.ddbDriver.getAllPathMappings();
+ for (const mapping of mappings) {
+ await this.cachePathMapping(mapping);
+ }
+ }
+
+
+}
+
+/**
+ * Path mapping configuration for request routing
+ */
+export interface PathMapping {
+ pathPattern: string;
+ originId: string;
+ policyId?: string;
+}
diff --git a/source/container/src/services/cache/domain/policy-cache.ts b/source/container/src/services/cache/domain/policy-cache.ts
new file mode 100644
index 000000000..ad48a21f2
--- /dev/null
+++ b/source/container/src/services/cache/domain/policy-cache.ts
@@ -0,0 +1,97 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+import { CacheManager } from '../interfaces/cache-manager';
+import { KeyValueCache } from '../implementations/key-value-cache';
+import { POLICY_CACHE_CONFIG } from '../config/cache-defaults';
+import { getCacheKey } from '../utils/simplified-cache-key';
+import { DDBDriver } from '../../database/ddb-driver.interface';
+import { ddbDriver } from '../../database';
+import { TransformationPolicy } from '../../../types/transformation';
+import { TransformationPolicyRecord } from '../../database/types';
+
+/**
+ * Transformation policy cache manager with transparent DynamoDB fallback.
+ * Handles caching of image transformation policies from DynamoDB.
+ */
+export class PolicyCache {
+ private cache: CacheManager;
+ private ddbDriver: DDBDriver;
+ private defaultPolicy: TransformationPolicy | null = null;
+
+ constructor() {
+ this.cache = new KeyValueCache(POLICY_CACHE_CONFIG);
+ this.ddbDriver = ddbDriver.instance;
+ }
+
+ async getPolicy(policyId: string): Promise {
+ const cacheKey = getCacheKey(policyId);
+ return await this.cache.get(cacheKey);
+ }
+
+ async cachePolicy(policy: TransformationPolicy): Promise {
+ const cacheKey = getCacheKey(policy.policyId);
+ await this.cache.set(cacheKey, policy);
+ }
+
+ async invalidatePolicy(policyId: string): Promise {
+ const cacheKey = getCacheKey(policyId);
+ await this.cache.delete(cacheKey);
+ }
+
+ async getContents(): Promise {
+ return await this.cache.getAll();
+ }
+
+ async size(): Promise {
+ return await this.cache.size();
+ }
+
+ async warmCache(): Promise {
+ const policyRecords = await this.ddbDriver.getAllPolicies();
+ for (const record of policyRecords) {
+ const parsedPolicy = this.parsePolicy(record);
+ if (parsedPolicy) {
+ await this.cachePolicy(parsedPolicy);
+ if (parsedPolicy.isDefault) {
+ this.defaultPolicy = parsedPolicy;
+ }
+ }
+ }
+ }
+
+ getDefault(): TransformationPolicy | null {
+ return this.defaultPolicy;
+ }
+
+ private parsePolicy(record: TransformationPolicyRecord): TransformationPolicy | null {
+ try {
+ const parsed = JSON.parse(record.policyJSON);
+ return {
+ policyId: record.policyId,
+ policyName: record.policyName,
+ description: record.description,
+ transformations: (parsed.transformations || []).map((t: any) => {
+ const conditional = t.condition
+ return {
+ type: t.transformation,
+ value: t.value,
+ source: 'policy' as const,
+ ...(conditional && {
+ conditional: {
+ target: conditional.field,
+ operator: Array.isArray(conditional.value) ? 'isIn' as const : 'equals' as const,
+ value: conditional.value
+ }
+ })
+ };
+ }),
+ outputs: parsed.outputs || [],
+ isDefault: record.isDefault
+ };
+ } catch (error) {
+ console.warn(`Failed to parse policy JSON for ${record.policyId}:`, error);
+ return null;
+ }
+ }
+}
diff --git a/source/container/src/services/cache/implementations/key-value-cache.ts b/source/container/src/services/cache/implementations/key-value-cache.ts
new file mode 100644
index 000000000..6e1aacdb9
--- /dev/null
+++ b/source/container/src/services/cache/implementations/key-value-cache.ts
@@ -0,0 +1,63 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+import { CacheManager } from '../interfaces/cache-manager';
+import { CacheConfig } from '../config/cache-defaults';
+
+/**
+ * In-memory key-value cache implementation using Map.
+ * Optimized for transformation policies & origins
+ */
+export class KeyValueCache implements CacheManager {
+ private cache = new Map>();
+ private readonly config: CacheConfig;
+
+ constructor(config: CacheConfig) {
+ this.config = config;
+ }
+
+ async get(key: string): Promise {
+ const item = this.cache.get(key);
+
+ if (!item) {
+ return null;
+ }
+
+ return item.value;
+ }
+
+ async set(key: string, value: T): Promise {
+ const item: CacheItem