From ad2df53a48ecf441da3a4eed1e838cfd861bdccd Mon Sep 17 00:00:00 2001 From: Adam Hall Date: Mon, 31 Jul 2023 12:19:07 +0930 Subject: [PATCH 01/27] Add distribution and bucket as read only class properties so that they can be referenced by other resources --- packages/static-hosting/lib/static-hosting.ts | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/packages/static-hosting/lib/static-hosting.ts b/packages/static-hosting/lib/static-hosting.ts index 9bd963f0..39cf94e3 100644 --- a/packages/static-hosting/lib/static-hosting.ts +++ b/packages/static-hosting/lib/static-hosting.ts @@ -1,6 +1,7 @@ import { Construct, CfnOutput, RemovalPolicy } from "@aws-cdk/core"; import { Bucket, + IBucket, BucketEncryption, BlockPublicAccess, BucketProps, @@ -19,6 +20,7 @@ import { CfnDistribution, ResponseHeadersPolicy, HttpVersion, + IDistribution, } from "@aws-cdk/aws-cloudfront"; import { HostedZone, ARecord } from "@aws-cdk/aws-route53"; import { User, Group, Policy, PolicyStatement, Effect } from "@aws-cdk/aws-iam"; @@ -106,6 +108,9 @@ export interface ResponseHeaderMappings { } export class StaticHosting extends Construct { + public readonly distribution: IDistribution; + public readonly bucket: IBucket; + private staticFiles = [ "js", "css", @@ -157,7 +162,7 @@ export class StaticHosting extends Construct { }); } - const bucket = new Bucket(this, "ContentBucket", { + this.bucket = new Bucket(this, "ContentBucket", { bucketName: siteName, encryption: BucketEncryption.S3_MANAGED, blockPublicAccess: BlockPublicAccess.BLOCK_ALL, @@ -168,7 +173,7 @@ export class StaticHosting extends Construct { new CfnOutput(this, "Bucket", { description: "BucketName", - value: bucket.bucketName, + value: this.bucket.bucketName, exportName: `${exportPrefix}BucketName`, }); @@ -176,7 +181,7 @@ export class StaticHosting extends Construct { comment: "Allow CloudFront to access S3", }); - bucket.grantRead(oai); + this.bucket.grantRead(oai); const publisherUser = props.createPublisherUser ? new User(this, "PublisherUser", { @@ -197,7 +202,7 @@ export class StaticHosting extends Construct { : undefined; if (publisherGroup) { - bucket.grantReadWrite(publisherGroup); + this.bucket.grantReadWrite(publisherGroup); new CfnOutput(this, "PublisherGroupName", { description: "PublisherGroup", @@ -256,7 +261,7 @@ export class StaticHosting extends Construct { // Create default origin originConfigs.push({ s3OriginSource: { - s3BucketSource: bucket, + s3BucketSource: this.bucket, originAccessIdentity: oai, }, // if behaviors have been passed via props use them instead @@ -328,7 +333,7 @@ export class StaticHosting extends Construct { }; } - const distribution = new CloudFrontWebDistribution( + this.distribution = new CloudFrontWebDistribution( this, "BucketCdn", distributionProps @@ -346,7 +351,7 @@ export class StaticHosting extends Construct { }, }); - const cfnDistribution = distribution.node.defaultChild as CfnDistribution; + const cfnDistribution = this.distribution.node.defaultChild as CfnDistribution; // In the current version of CDK there's no nice way to do this... // Instead just override the CloudFormation property directly cfnDistribution.addOverride( @@ -367,7 +372,7 @@ export class StaticHosting extends Construct { * the cache behaviors */ if (props.responseHeadersPolicies) { - const cfnDistribution = distribution.node.defaultChild as CfnDistribution; + const cfnDistribution = this.distribution.node.defaultChild as CfnDistribution; /** * If we prepend custom origin configs, @@ -452,7 +457,7 @@ export class StaticHosting extends Construct { "cloudfront:ListInvalidations", ], resources: [ - `arn:aws:cloudfront::*:distribution/${distribution.distributionId}`, + `arn:aws:cloudfront::*:distribution/${this.distribution.distributionId}`, ], }); @@ -467,12 +472,12 @@ export class StaticHosting extends Construct { } new CfnOutput(this, "DistributionId", { description: "DistributionId", - value: distribution.distributionId, + value: this.distribution.distributionId, exportName: `${exportPrefix}DistributionID`, }); new CfnOutput(this, "DistributionDomainName", { description: "DistributionDomainName", - value: distribution.distributionDomainName, + value: this.distribution.distributionDomainName, exportName: `${exportPrefix}DistributionName`, }); @@ -483,7 +488,7 @@ export class StaticHosting extends Construct { new ARecord(this, "SiteAliasRecord", { recordName: siteName, - target: RecordTarget.fromAlias(new CloudFrontTarget(distribution)), + target: RecordTarget.fromAlias(new CloudFrontTarget(this.distribution)), zone: zone, }); } From 9ff54c2eb8b4c5fa7c08b2975a3de67ce0cc6bab Mon Sep 17 00:00:00 2001 From: Adam Hall Date: Mon, 31 Jul 2023 13:46:23 +0930 Subject: [PATCH 02/27] Run format fixes --- packages/static-hosting/lib/static-hosting.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/static-hosting/lib/static-hosting.ts b/packages/static-hosting/lib/static-hosting.ts index 39cf94e3..7cef92a5 100644 --- a/packages/static-hosting/lib/static-hosting.ts +++ b/packages/static-hosting/lib/static-hosting.ts @@ -202,7 +202,7 @@ export class StaticHosting extends Construct { : undefined; if (publisherGroup) { - this.bucket.grantReadWrite(publisherGroup); + this.bucket.grantReadWrite(publisherGroup); new CfnOutput(this, "PublisherGroupName", { description: "PublisherGroup", @@ -351,7 +351,8 @@ export class StaticHosting extends Construct { }, }); - const cfnDistribution = this.distribution.node.defaultChild as CfnDistribution; + const cfnDistribution = this.distribution.node + .defaultChild as CfnDistribution; // In the current version of CDK there's no nice way to do this... // Instead just override the CloudFormation property directly cfnDistribution.addOverride( @@ -372,7 +373,8 @@ export class StaticHosting extends Construct { * the cache behaviors */ if (props.responseHeadersPolicies) { - const cfnDistribution = this.distribution.node.defaultChild as CfnDistribution; + const cfnDistribution = this.distribution.node + .defaultChild as CfnDistribution; /** * If we prepend custom origin configs, From 63d125823b12321675e10353b76f5025a1f29dec Mon Sep 17 00:00:00 2001 From: Krishan Thisera Date: Tue, 15 Aug 2023 11:32:41 +0930 Subject: [PATCH 03/27] DO-1495: expose prerender proxy props for individiual construct --- packages/prerender-proxy/index.ts | 18 +++++++++++++++--- .../prerender-proxy/lib/handlers/prerender.ts | 1 - 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/packages/prerender-proxy/index.ts b/packages/prerender-proxy/index.ts index 9181546a..fc41368b 100644 --- a/packages/prerender-proxy/index.ts +++ b/packages/prerender-proxy/index.ts @@ -1,7 +1,16 @@ -import { PrerenderLambda } from "./lib/prerender-lambda-construct"; -import { PrerenderFunction } from "./lib/prerender-construct"; +import { + PrerenderLambda, + PrerenderLambdaProps, +} from "./lib/prerender-lambda-construct"; +import { + PrerenderFunction, + PrerenderFunctionOptions, +} from "./lib/prerender-construct"; import { PrerenderCheckFunction } from "./lib/prerender-check-construct"; -import { ErrorResponseFunction } from "./lib/error-response-construct"; +import { + ErrorResponseFunction, + ErrorResponseFunctionOptions, +} from "./lib/error-response-construct"; import { CloudFrontCacheControl, CloudFrontCacheControlOptions, @@ -14,4 +23,7 @@ export { ErrorResponseFunction, CloudFrontCacheControl, CloudFrontCacheControlOptions, + ErrorResponseFunctionOptions, + PrerenderFunctionOptions, + PrerenderLambdaProps, }; diff --git a/packages/prerender-proxy/lib/handlers/prerender.ts b/packages/prerender-proxy/lib/handlers/prerender.ts index 27cdb06f..1f9af75a 100644 --- a/packages/prerender-proxy/lib/handlers/prerender.ts +++ b/packages/prerender-proxy/lib/handlers/prerender.ts @@ -49,4 +49,3 @@ export const handler = async ( return request; }; -1; From 3970edbeb9f9f154758769d45212bbbd121f2121 Mon Sep 17 00:00:00 2001 From: Krishan Thisera Date: Tue, 10 Oct 2023 10:27:27 +1030 Subject: [PATCH 04/27] chore: migrate prerender fargate --- packages/prerender-fargate/.gitignore | 1 + packages/prerender-fargate/.npmignore | 11 + packages/prerender-fargate/README.md | 18 + packages/prerender-fargate/index.ts | 3 + .../lib/prerender-fargate.ts | 118 +++++ .../lib/prerender/Dockerfile | 25 + .../lib/prerender/package.json | 13 + .../prerender-fargate/lib/prerender/server.js | 137 ++++++ packages/prerender-fargate/package-lock.json | 426 ++++++++++++++++++ packages/prerender-fargate/package.json | 24 + packages/prerender-fargate/tsconfig.json | 3 + 11 files changed, 779 insertions(+) create mode 100644 packages/prerender-fargate/.gitignore create mode 100644 packages/prerender-fargate/.npmignore create mode 100644 packages/prerender-fargate/README.md create mode 100644 packages/prerender-fargate/index.ts create mode 100644 packages/prerender-fargate/lib/prerender-fargate.ts create mode 100644 packages/prerender-fargate/lib/prerender/Dockerfile create mode 100644 packages/prerender-fargate/lib/prerender/package.json create mode 100644 packages/prerender-fargate/lib/prerender/server.js create mode 100644 packages/prerender-fargate/package-lock.json create mode 100644 packages/prerender-fargate/package.json create mode 100644 packages/prerender-fargate/tsconfig.json diff --git a/packages/prerender-fargate/.gitignore b/packages/prerender-fargate/.gitignore new file mode 100644 index 00000000..ec769510 --- /dev/null +++ b/packages/prerender-fargate/.gitignore @@ -0,0 +1 @@ +!lib/prerender/* diff --git a/packages/prerender-fargate/.npmignore b/packages/prerender-fargate/.npmignore new file mode 100644 index 00000000..bfd115ba --- /dev/null +++ b/packages/prerender-fargate/.npmignore @@ -0,0 +1,11 @@ +*.ts +!lib/handlers/*.ts +!*.d.ts +!*.js + +# CDK asset staging directory +.cdk.staging +cdk.out + +# Samples +sample/ diff --git a/packages/prerender-fargate/README.md b/packages/prerender-fargate/README.md new file mode 100644 index 00000000..97c9cae6 --- /dev/null +++ b/packages/prerender-fargate/README.md @@ -0,0 +1,18 @@ +# Prerender in Fargate + +A construct to host [Prerender](https://github.com/prerender/prerender) in Fargate. + +## Props + +- `prerenderName`: Name of the Prerender service +- `domainName`: Domain name for Prerender +- `vpcId`: VPC to host Prerender in +- `bucketName`: Optional S3 bucket name +- `expirationDays`: Optional days until items expire in bucket (default to 7 days) +- `tokenList`: List of tokens to accept as authentication +- `certificateArn`: Certificate arn to match the domain +- `desiredInstanceCount`: Number of Prerender instances to run (default 1) +- `maxInstanceCount`: Maximum number of Prerender instances to run (default 2) +- `instanceCPU`: CPU to allocate to each instance (default 512) +- `instanceMemory`: Amount of memory to allocate to each instance (default 1024) +- `enableRedirectCache`: Cache 301 and 302 responses, too (default false) diff --git a/packages/prerender-fargate/index.ts b/packages/prerender-fargate/index.ts new file mode 100644 index 00000000..c0523747 --- /dev/null +++ b/packages/prerender-fargate/index.ts @@ -0,0 +1,3 @@ +import { PrerenderFargate, PrerenderOptions } from "./lib/prerender-fargate"; + +export { PrerenderFargate, PrerenderOptions }; diff --git a/packages/prerender-fargate/lib/prerender-fargate.ts b/packages/prerender-fargate/lib/prerender-fargate.ts new file mode 100644 index 00000000..acb8113c --- /dev/null +++ b/packages/prerender-fargate/lib/prerender-fargate.ts @@ -0,0 +1,118 @@ +import { Construct } from 'constructs'; +import * as ecs from 'aws-cdk-lib/aws-ecs'; +import * as ecsPatterns from 'aws-cdk-lib/aws-ecs-patterns'; +import * as ec2 from 'aws-cdk-lib/aws-ec2'; +import { Certificate } from 'aws-cdk-lib/aws-certificatemanager'; +import { HostedZone } from 'aws-cdk-lib/aws-route53'; +import { Bucket, BlockPublicAccess } from 'aws-cdk-lib/aws-s3' +import * as ecrAssets from 'aws-cdk-lib/aws-ecr-assets'; +import { AccessKey, User } from 'aws-cdk-lib/aws-iam'; +import { Duration, RemovalPolicy, Stack } from 'aws-cdk-lib'; +import * as path from 'path'; + +export interface PrerenderOptions { + prerenderName: string, + domainName: string, + vpcId?: string, + bucketName?: string, + expirationDays?: number, + tokenList: Array, + certificateArn: string, + desiredInstanceCount?: number, + maxInstanceCount?: number, + instanceCPU?: number, + instanceMemory?: number + enableRedirectCache?: string +} + +export class PrerenderFargate extends Construct { + readonly bucket: Bucket; + + constructor(scope: Construct, id: string, props: PrerenderOptions) { + super(scope, id); + + // Create bucket for prerender storage + this.bucket = new Bucket(this, `${props.prerenderName}-bucket`, { + bucketName: props.bucketName, + lifecycleRules: [{ + enabled: true, + expiration: Duration.days(props.expirationDays || 7) // Default to 7 day expiration + }], + removalPolicy: RemovalPolicy.DESTROY, + autoDeleteObjects: true, + blockPublicAccess: BlockPublicAccess.BLOCK_ALL, + }); + + // Configure access to the bucket for the container + const user = new User(this, 'PrerenderAccess'); + this.bucket.grantReadWrite(user); + + const accessKey = new AccessKey(this, 'PrerenderAccessKey', { + user: user, + serial: 1 + }); + + const vpcLookup = props.vpcId ? { vpcId: props.vpcId } : { isDefault: true }; + const vpc = ec2.Vpc.fromLookup(this, "vpc", vpcLookup); + + const cluster = new ecs.Cluster(this, `${props.prerenderName}-cluster`, { vpc: vpc }); + + const directory = path.join(__dirname, 'prerender'); + const asset = new ecrAssets.DockerImageAsset(this, `${props.prerenderName}-image`, { + directory, + }); + + // Create a load-balanced Fargate service + const fargateService = new ecsPatterns.ApplicationLoadBalancedFargateService( + this, + `${props.prerenderName}-service`, + { + cluster, + serviceName: `${props.prerenderName}-service`, + desiredCount: props.desiredInstanceCount || 1, + cpu: props.instanceCPU || 512, // 0.5 vCPU default + memoryLimitMiB: props.instanceMemory || 1024, // 1 GB default to give Chrome enough memory + taskImageOptions: { + image: ecs.ContainerImage.fromDockerImageAsset(asset), + enableLogging: true, + containerPort: 3000, + environment: { + S3_BUCKET_NAME: this.bucket.bucketName, + AWS_ACCESS_KEY_ID: accessKey.accessKeyId, + AWS_SECRET_ACCESS_KEY: accessKey.secretAccessKey.unsafeUnwrap(), + AWS_REGION: Stack.of(this).region, + ENABLE_REDIRECT_CACHE: props.enableRedirectCache || "false", + TOKEN_LIST: props.tokenList.toString() + } + }, + healthCheckGracePeriod: Duration.seconds(20), + publicLoadBalancer: true, + assignPublicIp: true, + listenerPort: 443, + redirectHTTP: true, + domainName: props.domainName, + domainZone: new HostedZone(this, 'hosted-zone', { zoneName: props.domainName }), + certificate: Certificate.fromCertificateArn(this, 'cert', props.certificateArn) + } + ); + + // As the prerender service will return a 401 on all unauthorised requests + // it should be considered healthy when receiving a 401 response + fargateService.targetGroup.configureHealthCheck({ + path: "/health", + interval: Duration.seconds(120), + unhealthyThresholdCount: 5, + healthyHttpCodes: '401' + }); + + // Setup AutoScaling policy + const scaling = fargateService.service.autoScaleTaskCount({ + maxCapacity: props.maxInstanceCount || 2, + }); + scaling.scaleOnCpuUtilization(`${props.prerenderName}-scaling`, { + targetUtilizationPercent: 50, + scaleInCooldown: Duration.seconds(60), + scaleOutCooldown: Duration.seconds(60), + }); + } +} diff --git a/packages/prerender-fargate/lib/prerender/Dockerfile b/packages/prerender-fargate/lib/prerender/Dockerfile new file mode 100644 index 00000000..b92a339e --- /dev/null +++ b/packages/prerender-fargate/lib/prerender/Dockerfile @@ -0,0 +1,25 @@ +FROM node:16-alpine + +ENV CHROME_BIN=/usr/bin/chromium-browser +ENV CHROME_PATH=/usr/lib/chromium/ +ENV MEMORY_CACHE=0 + +# install chromium, tini and clear cache +RUN apk add --update-cache chromium tini \ + && rm -rf /var/cache/apk/* /tmp/* + +USER node +WORKDIR "/home/node" + +COPY ./package.json . +COPY ./server.js . + +# install npm packages +RUN npm install --no-package-lock + +EXPOSE 3000 + +HEALTHCHECK CMD netstat -ltn | grep -c 3000 + +ENTRYPOINT ["tini", "--"] +CMD ["node", "server.js"] diff --git a/packages/prerender-fargate/lib/prerender/package.json b/packages/prerender-fargate/lib/prerender/package.json new file mode 100644 index 00000000..62d6b33a --- /dev/null +++ b/packages/prerender-fargate/lib/prerender/package.json @@ -0,0 +1,13 @@ +{ + "name": "prerender-alpine", + "version": "6.5.0", + "description": "lightweight prerender container built on alpine linux", + "main": "server.js", + "scripts": { + "start": "node server.js" + }, + "dependencies": { + "prerender": "5.20.0", + "prerender-aws-s3-cache": "1.0.1" + } +} diff --git a/packages/prerender-fargate/lib/prerender/server.js b/packages/prerender-fargate/lib/prerender/server.js new file mode 100644 index 00000000..e248cc76 --- /dev/null +++ b/packages/prerender-fargate/lib/prerender/server.js @@ -0,0 +1,137 @@ +'use strict'; + +const prerender = require('prerender'); +const crypto = require('crypto'); +const s3Cache = require('prerender-aws-s3-cache'); + +const server = prerender({ + chromeFlags: ['--no-sandbox', '--headless', '--disable-gpu', '--remote-debugging-port=9222', '--hide-scrollbars', '--disable-dev-shm-usage'], + forwardHeaders: true, + chromeLocation: '/usr/bin/chromium-browser' +}); + +server.use({ + requestReceived: (req, res, next) => { + let auth = req.headers['x-prerender-token']; + if (!auth) return res.send(401); + + // compare credentials in header to list of allowed credentials + const tokenAllowList = process.env.TOKEN_LIST.toString().split(','); + + let authenticated = false; + for (const token of tokenAllowList) { + authenticated = auth === token; + + if (authenticated) break; + } + if (!authenticated) return res.send(401); + + return next(); + }, + // Append a custom header to indicate the response is from Prerender + beforeSend: function(req, res, next) { + res.setHeader('x-prerender-requestid', crypto.randomUUID()); + return next(); + } +}); + +server.use(prerender.blacklist()); + +if (process.env.ENABLE_REDIRECT_CACHE.toLowerCase() === 'true'){ + var he = require('he'); + var s3 = new (require('aws-sdk')).S3({params:{Bucket: process.env.S3_BUCKET_NAME}}); + server.use({ + // The requestReceived and pageLoaded functions are a modified version of + // httpHeader plugin - https://github.com/prerender/prerender/blob/478fa6d0a5196ea29c88c69e64e72eb5507b6d2c/lib/plugins/httpHeaders.js combined with + // s3cache plugin - https://github.com/prerender/prerender-aws-s3-cache/blob/98707fa0f787de83aa41583682cd2c2d330a9cca/index.js + requestReceived: function(req, res, next) { + if(req.method !== 'GET' && req.method !== 'HEAD') { + return next(); + } + + var key = req.prerender.url; + + if (process.env.S3_PREFIX_KEY) { + key = process.env.S3_PREFIX_KEY + '/' + key; + } + + s3.getObject({ + Key: key + }, function (err, result) { + + if (!err && result) { + console.log("Found cached object: " + key); + if (result.Metadata.location){ + res.setHeader('Location', result.Metadata.location); + } + // default 200 for legacy objects that do not have Metadata.httpreturncode defined + return res.send(result.Metadata.httpreturncode || 200, result.Body); + } else { + console.error(err); + } + + next(); + }); + }, + + pageLoaded: function(req, res, next) { + const statusCodesToCache = ['200', '301', '302']; + var s3Metadata = {} + + // Inspect prerender meta tags and update response accordingly + if (req.prerender.content && req.prerender.renderType == 'html') { + const statusMatchRegex = /]*(?:name=['"]prerender-status-code['"][^<>]*content=['"]([0-9]{3})['"]|content=['"]([0-9]{3})['"][^<>]*name=['"]prerender-status-code['"])[^<>]*>/i; + const headerMatchRegex = /]*(?:name=['"]prerender-header['"][^<>]*content=['"]([^'"]*?): ?([^'"]*?)['"]|content=['"]([^'"]*?): ?([^'"]*?)['"][^<>]*name=['"]prerender-header['"])[^<>]*>/gi + const head = req.prerender.content.toString().split('', 1).pop() + + const statusMatch = statusMatchRegex.exec(head) + if (statusMatch) { + req.prerender.statusCode = statusMatch[1] || statusMatch[2]; + req.prerender.content = req.prerender.content.toString().replace(statusMatch[0], ''); + } + + let headerMatch = headerMatchRegex.exec(head) + while (headerMatch) { + s3Metadata.location = he.decode(headerMatch[2] || headerMatch[4]); + res.setHeader(headerMatch[1] || headerMatch[3], s3Metadata.location); + req.prerender.content = req.prerender.content.toString().replace(headerMatch[0], ''); + headerMatch = headerMatchRegex.exec(head) + } + + // Skip caching for the http response codes not in the list, such as 404 + if ( ! statusCodesToCache.includes(req.prerender.statusCode.toString()) ) { + console.log(`StatusCode ${req.prerender.statusCode} for ${req.prerender.url} is not in the cachable code list. Returning without caching the result.`); + return res.send(req.prerender.statusCode, req.prerender.content); + } + } + s3Metadata.httpreturncode = req.prerender.statusCode.toString() + + console.log(`Caching the object ${req.prerender.url} with statusCode ${req.prerender.statusCode}`); + var key = req.prerender.url; + + if (process.env.S3_PREFIX_KEY) { + key = process.env.S3_PREFIX_KEY + '/' + key; + } + + s3.putObject({ + Key: key, + ContentType: 'text/html;charset=UTF-8', + StorageClass: 'REDUCED_REDUNDANCY', + Body: req.prerender.content, + Metadata: s3Metadata + }, function(err, result) { + console.log(result); + if (err) console.error(err); + + next(); + }); + } + }); + server.use(prerender.removeScriptTags()); +} else { + server.use(prerender.httpHeaders()); + server.use(prerender.removeScriptTags()); + server.use(s3Cache); +} + +server.start(); diff --git a/packages/prerender-fargate/package-lock.json b/packages/prerender-fargate/package-lock.json new file mode 100644 index 00000000..b1ba86e9 --- /dev/null +++ b/packages/prerender-fargate/package-lock.json @@ -0,0 +1,426 @@ +{ + "name": "@aligent/cdk-prerender-fargate", + "version": "0.0.1", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "@aligent/cdk-prerender-fargate", + "version": "0.0.1", + "license": "GPL-3.0-only", + "dependencies": { + "@aws-cdk/aws-apigatewayv2-alpha": "2.30.0-alpha.0", + "@aws-cdk/aws-apigatewayv2-authorizers-alpha": "2.30.0-alpha.0", + "@aws-cdk/aws-apigatewayv2-integrations-alpha": "2.30.0-alpha.0" + } + }, + "node_modules/@aws-cdk/aws-apigatewayv2-alpha": { + "version": "2.30.0-alpha.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-apigatewayv2-alpha/-/aws-apigatewayv2-alpha-2.30.0-alpha.0.tgz", + "integrity": "sha512-D5AB4x7Ayicbb87gb7wVJGuyFrqjelw48gvMADvNecw8md5aOSJ7jvwlSEGMZMiJ1UhjNhea7AWSNdAOI2SfBQ==", + "engines": { + "node": ">= 14.15.0" + }, + "peerDependencies": { + "aws-cdk-lib": "^2.30.0", + "constructs": "^10.0.0" + } + }, + "node_modules/@aws-cdk/aws-apigatewayv2-authorizers-alpha": { + "version": "2.30.0-alpha.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-apigatewayv2-authorizers-alpha/-/aws-apigatewayv2-authorizers-alpha-2.30.0-alpha.0.tgz", + "integrity": "sha512-/oIxg3boxN+a4qqRQHEZ5LgjSgMFDukMx5pbTcJ4lEoEe9FpJaJ/FY8IJ0ZR1TfpfxGhVNwHUpMprkqRh9SYSA==", + "engines": { + "node": ">= 14.15.0" + }, + "peerDependencies": { + "@aws-cdk/aws-apigatewayv2-alpha": "2.30.0-alpha.0", + "aws-cdk-lib": "^2.30.0", + "constructs": "^10.0.0" + } + }, + "node_modules/@aws-cdk/aws-apigatewayv2-integrations-alpha": { + "version": "2.30.0-alpha.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-apigatewayv2-integrations-alpha/-/aws-apigatewayv2-integrations-alpha-2.30.0-alpha.0.tgz", + "integrity": "sha512-2/NAb0AFGwZQjNqpViiagJxKa8u0hy09GV7W/AKSEzLmQp1H2Jmg8oSGLudXVTF/VtsgjQUAL4MuxTRAXFtJoQ==", + "engines": { + "node": ">= 14.15.0" + }, + "peerDependencies": { + "@aws-cdk/aws-apigatewayv2-alpha": "2.30.0-alpha.0", + "aws-cdk-lib": "^2.30.0", + "constructs": "^10.0.0" + } + }, + "node_modules/aws-cdk-lib": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/aws-cdk-lib/-/aws-cdk-lib-2.30.0.tgz", + "integrity": "sha512-e9KKwRF4vPzPpOXPq8dtzUdn6j2tmTrrSZmQu2tOiZni0eB1vhiOVwaxc/8aEUrz8wUZ8t2gEitYdJmtm/GWhQ==", + "bundleDependencies": [ + "@balena/dockerignore", + "case", + "fs-extra", + "ignore", + "jsonschema", + "minimatch", + "punycode", + "semver", + "yaml" + ], + "peer": true, + "dependencies": { + "@balena/dockerignore": "^1.0.2", + "case": "1.6.3", + "fs-extra": "^9.1.0", + "ignore": "^5.2.0", + "jsonschema": "^1.4.1", + "minimatch": "^3.1.2", + "punycode": "^2.1.1", + "semver": "^7.3.7", + "yaml": "1.10.2" + }, + "engines": { + "node": ">= 14.15.0" + }, + "peerDependencies": { + "constructs": "^10.0.0" + } + }, + "node_modules/aws-cdk-lib/node_modules/@balena/dockerignore": { + "version": "1.0.2", + "inBundle": true, + "license": "Apache-2.0", + "peer": true + }, + "node_modules/aws-cdk-lib/node_modules/at-least-node": { + "version": "1.0.0", + "inBundle": true, + "license": "ISC", + "peer": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/aws-cdk-lib/node_modules/balanced-match": { + "version": "1.0.2", + "inBundle": true, + "license": "MIT", + "peer": true + }, + "node_modules/aws-cdk-lib/node_modules/brace-expansion": { + "version": "1.1.11", + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/aws-cdk-lib/node_modules/case": { + "version": "1.6.3", + "inBundle": true, + "license": "(MIT OR GPL-3.0-or-later)", + "peer": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/aws-cdk-lib/node_modules/concat-map": { + "version": "0.0.1", + "inBundle": true, + "license": "MIT", + "peer": true + }, + "node_modules/aws-cdk-lib/node_modules/fs-extra": { + "version": "9.1.0", + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/aws-cdk-lib/node_modules/graceful-fs": { + "version": "4.2.10", + "inBundle": true, + "license": "ISC", + "peer": true + }, + "node_modules/aws-cdk-lib/node_modules/ignore": { + "version": "5.2.0", + "inBundle": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/aws-cdk-lib/node_modules/jsonfile": { + "version": "6.1.0", + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/aws-cdk-lib/node_modules/jsonschema": { + "version": "1.4.1", + "inBundle": true, + "license": "MIT", + "peer": true, + "engines": { + "node": "*" + } + }, + "node_modules/aws-cdk-lib/node_modules/lru-cache": { + "version": "6.0.0", + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/aws-cdk-lib/node_modules/minimatch": { + "version": "3.1.2", + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/aws-cdk-lib/node_modules/punycode": { + "version": "2.1.1", + "inBundle": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/aws-cdk-lib/node_modules/semver": { + "version": "7.3.7", + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/aws-cdk-lib/node_modules/universalify": { + "version": "2.0.0", + "inBundle": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/aws-cdk-lib/node_modules/yallist": { + "version": "4.0.0", + "inBundle": true, + "license": "ISC", + "peer": true + }, + "node_modules/aws-cdk-lib/node_modules/yaml": { + "version": "1.10.2", + "inBundle": true, + "license": "ISC", + "peer": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/constructs": { + "version": "10.1.43", + "resolved": "https://registry.npmjs.org/constructs/-/constructs-10.1.43.tgz", + "integrity": "sha512-I7CEsYPmcsTpmf+tT3DZq5klCzk2d0Gb6X67P5XxYq0an4+JiWrf8/LCIHV3xqOhnGLAbM/aGZ3bigUNTWeliA==", + "peer": true, + "engines": { + "node": ">= 14.17.0" + } + } + }, + "dependencies": { + "@aws-cdk/aws-apigatewayv2-alpha": { + "version": "2.30.0-alpha.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-apigatewayv2-alpha/-/aws-apigatewayv2-alpha-2.30.0-alpha.0.tgz", + "integrity": "sha512-D5AB4x7Ayicbb87gb7wVJGuyFrqjelw48gvMADvNecw8md5aOSJ7jvwlSEGMZMiJ1UhjNhea7AWSNdAOI2SfBQ==", + "requires": {} + }, + "@aws-cdk/aws-apigatewayv2-authorizers-alpha": { + "version": "2.30.0-alpha.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-apigatewayv2-authorizers-alpha/-/aws-apigatewayv2-authorizers-alpha-2.30.0-alpha.0.tgz", + "integrity": "sha512-/oIxg3boxN+a4qqRQHEZ5LgjSgMFDukMx5pbTcJ4lEoEe9FpJaJ/FY8IJ0ZR1TfpfxGhVNwHUpMprkqRh9SYSA==", + "requires": {} + }, + "@aws-cdk/aws-apigatewayv2-integrations-alpha": { + "version": "2.30.0-alpha.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-apigatewayv2-integrations-alpha/-/aws-apigatewayv2-integrations-alpha-2.30.0-alpha.0.tgz", + "integrity": "sha512-2/NAb0AFGwZQjNqpViiagJxKa8u0hy09GV7W/AKSEzLmQp1H2Jmg8oSGLudXVTF/VtsgjQUAL4MuxTRAXFtJoQ==", + "requires": {} + }, + "aws-cdk-lib": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/aws-cdk-lib/-/aws-cdk-lib-2.30.0.tgz", + "integrity": "sha512-e9KKwRF4vPzPpOXPq8dtzUdn6j2tmTrrSZmQu2tOiZni0eB1vhiOVwaxc/8aEUrz8wUZ8t2gEitYdJmtm/GWhQ==", + "peer": true, + "requires": { + "@balena/dockerignore": "^1.0.2", + "case": "1.6.3", + "fs-extra": "^9.1.0", + "ignore": "^5.2.0", + "jsonschema": "^1.4.1", + "minimatch": "^3.1.2", + "punycode": "^2.1.1", + "semver": "^7.3.7", + "yaml": "1.10.2" + }, + "dependencies": { + "@balena/dockerignore": { + "version": "1.0.2", + "bundled": true, + "peer": true + }, + "at-least-node": { + "version": "1.0.0", + "bundled": true, + "peer": true + }, + "balanced-match": { + "version": "1.0.2", + "bundled": true, + "peer": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "peer": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "case": { + "version": "1.6.3", + "bundled": true, + "peer": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "peer": true + }, + "fs-extra": { + "version": "9.1.0", + "bundled": true, + "peer": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "graceful-fs": { + "version": "4.2.10", + "bundled": true, + "peer": true + }, + "ignore": { + "version": "5.2.0", + "bundled": true, + "peer": true + }, + "jsonfile": { + "version": "6.1.0", + "bundled": true, + "peer": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "jsonschema": { + "version": "1.4.1", + "bundled": true, + "peer": true + }, + "lru-cache": { + "version": "6.0.0", + "bundled": true, + "peer": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "minimatch": { + "version": "3.1.2", + "bundled": true, + "peer": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "punycode": { + "version": "2.1.1", + "bundled": true, + "peer": true + }, + "semver": { + "version": "7.3.7", + "bundled": true, + "peer": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "universalify": { + "version": "2.0.0", + "bundled": true, + "peer": true + }, + "yallist": { + "version": "4.0.0", + "bundled": true, + "peer": true + }, + "yaml": { + "version": "1.10.2", + "bundled": true, + "peer": true + } + } + }, + "constructs": { + "version": "10.1.43", + "resolved": "https://registry.npmjs.org/constructs/-/constructs-10.1.43.tgz", + "integrity": "sha512-I7CEsYPmcsTpmf+tT3DZq5klCzk2d0Gb6X67P5XxYq0an4+JiWrf8/LCIHV3xqOhnGLAbM/aGZ3bigUNTWeliA==", + "peer": true + } + } +} diff --git a/packages/prerender-fargate/package.json b/packages/prerender-fargate/package.json new file mode 100644 index 00000000..b99a0c12 --- /dev/null +++ b/packages/prerender-fargate/package.json @@ -0,0 +1,24 @@ +{ + "name": "@aligent/cdk-prerender-fargate", + "version": "0.0.1", + "description": "A construct to host Prerender in Fargate", + "main": "index.js", + "scripts": { + "build": "tsc", + "prepublish": "tsc" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/aligent/cdk-constructs.git" + }, + "license": "GPL-3.0-only", + "bugs": { + "url": "https://github.com/aligent/cdk-constructs/issues" + }, + "homepage": "https://github.com/aligent/cdk-constructs/tree/main/packages/prerender-fargate#readme", + "dependencies": { + "@aws-cdk/aws-apigatewayv2-alpha": "2.30.0-alpha.0", + "@aws-cdk/aws-apigatewayv2-authorizers-alpha": "2.30.0-alpha.0", + "@aws-cdk/aws-apigatewayv2-integrations-alpha": "2.30.0-alpha.0" + } +} diff --git a/packages/prerender-fargate/tsconfig.json b/packages/prerender-fargate/tsconfig.json new file mode 100644 index 00000000..4082f16a --- /dev/null +++ b/packages/prerender-fargate/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "../../tsconfig.json" +} From 34847f52a2ff6c8b206369eaa11a995098451fa4 Mon Sep 17 00:00:00 2001 From: Chris Park Date: Fri, 6 Oct 2023 09:10:25 +1030 Subject: [PATCH 05/27] DO-1484: reorganise the sequence to fix the bug not stripping script tags properly --- packages/prerender-fargate/lib/prerender/server.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/prerender-fargate/lib/prerender/server.js b/packages/prerender-fargate/lib/prerender/server.js index e248cc76..a4913bf2 100644 --- a/packages/prerender-fargate/lib/prerender/server.js +++ b/packages/prerender-fargate/lib/prerender/server.js @@ -72,8 +72,9 @@ if (process.env.ENABLE_REDIRECT_CACHE.toLowerCase() === 'true'){ next(); }); - }, - + }}); + server.use(prerender.removeScriptTags()); + server.use({ pageLoaded: function(req, res, next) { const statusCodesToCache = ['200', '301', '302']; var s3Metadata = {} @@ -127,7 +128,6 @@ if (process.env.ENABLE_REDIRECT_CACHE.toLowerCase() === 'true'){ }); } }); - server.use(prerender.removeScriptTags()); } else { server.use(prerender.httpHeaders()); server.use(prerender.removeScriptTags()); From ceeaedf14dc5bca51cbf2ba69de1240bd0967853 Mon Sep 17 00:00:00 2001 From: Chris Park Date: Fri, 6 Oct 2023 09:10:58 +1030 Subject: [PATCH 06/27] DO-1484: make user-agent visible for easier debugging --- packages/prerender-fargate/lib/prerender/server.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/prerender-fargate/lib/prerender/server.js b/packages/prerender-fargate/lib/prerender/server.js index a4913bf2..463ee56f 100644 --- a/packages/prerender-fargate/lib/prerender/server.js +++ b/packages/prerender-fargate/lib/prerender/server.js @@ -12,8 +12,12 @@ const server = prerender({ server.use({ requestReceived: (req, res, next) => { + console.log(`${new Date().toISOString()} User-Agent: "${req.get('user-agent')}" ${req.prerender.reqId} ${req.prerender.url}`); let auth = req.headers['x-prerender-token']; - if (!auth) return res.send(401); + if (!auth) { + console.log(`${new Date().toISOString()} "${req.get('user-agent')}" ${req.prerender.reqId} Authentication header not found.`); + return res.send(401); + } // compare credentials in header to list of allowed credentials const tokenAllowList = process.env.TOKEN_LIST.toString().split(','); @@ -24,7 +28,10 @@ server.use({ if (authenticated) break; } - if (!authenticated) return res.send(401); + if (!authenticated) { + console.log(`${new Date().toISOString()} "${req.get('user-agent')}" ${req.prerender.reqId} Authentication Failed.`); + return res.send(401); + } return next(); }, From 382f7a05229553b9317ba90f18fdba7f0b4af5fa Mon Sep 17 00:00:00 2001 From: Krishan Thisera Date: Wed, 11 Oct 2023 12:02:35 +1030 Subject: [PATCH 07/27] DO-1544: enable s3 endpoint for VPC --- packages/prerender-fargate/lib/prerender-fargate.ts | 12 ++++++++++++ tsconfig.json | 3 ++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/packages/prerender-fargate/lib/prerender-fargate.ts b/packages/prerender-fargate/lib/prerender-fargate.ts index acb8113c..98d6eaeb 100644 --- a/packages/prerender-fargate/lib/prerender-fargate.ts +++ b/packages/prerender-fargate/lib/prerender-fargate.ts @@ -23,6 +23,7 @@ export interface PrerenderOptions { instanceCPU?: number, instanceMemory?: number enableRedirectCache?: string + enableS3Endpoint?: boolean } export class PrerenderFargate extends Construct { @@ -114,5 +115,16 @@ export class PrerenderFargate extends Construct { scaleInCooldown: Duration.seconds(60), scaleOutCooldown: Duration.seconds(60), }); + + /** + * Enable VPC Endpoints for S3 + * This would create S3 endpoints in all the PUBLIC subnets of the VPC + */ + if (props.enableS3Endpoint) { + vpc.addGatewayEndpoint("S3Endpoint", { + service: ec2.GatewayVpcEndpointAwsService.S3, + subnets: [{ subnetType: ec2.SubnetType.PUBLIC }], + }); + } } } diff --git a/tsconfig.json b/tsconfig.json index 4119ec45..882d25f3 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,7 +3,8 @@ "target": "ES2018", "module": "commonjs", "lib": ["es2018"], - "declaration": true, + "declaration": false, + "noEmit": true, "strict": true, "noImplicitAny": true, "strictNullChecks": true, From 74dd0d3d45bc318c3d0039ef12b0ea74cfa43eb1 Mon Sep 17 00:00:00 2001 From: Krishan Thisera Date: Wed, 11 Oct 2023 16:40:06 +1030 Subject: [PATCH 08/27] M2C-5239: code cleanup --- .../lib/prerender-fargate.ts | 281 +++++++++++------- 1 file changed, 170 insertions(+), 111 deletions(-) diff --git a/packages/prerender-fargate/lib/prerender-fargate.ts b/packages/prerender-fargate/lib/prerender-fargate.ts index 98d6eaeb..b6ccafbb 100644 --- a/packages/prerender-fargate/lib/prerender-fargate.ts +++ b/packages/prerender-fargate/lib/prerender-fargate.ts @@ -1,130 +1,189 @@ -import { Construct } from 'constructs'; -import * as ecs from 'aws-cdk-lib/aws-ecs'; -import * as ecsPatterns from 'aws-cdk-lib/aws-ecs-patterns'; -import * as ec2 from 'aws-cdk-lib/aws-ec2'; -import { Certificate } from 'aws-cdk-lib/aws-certificatemanager'; -import { HostedZone } from 'aws-cdk-lib/aws-route53'; -import { Bucket, BlockPublicAccess } from 'aws-cdk-lib/aws-s3' -import * as ecrAssets from 'aws-cdk-lib/aws-ecr-assets'; -import { AccessKey, User } from 'aws-cdk-lib/aws-iam'; -import { Duration, RemovalPolicy, Stack } from 'aws-cdk-lib'; -import * as path from 'path'; +import { Construct } from "constructs"; +import * as ecs from "aws-cdk-lib/aws-ecs"; +import * as ecsPatterns from "aws-cdk-lib/aws-ecs-patterns"; +import * as ec2 from "aws-cdk-lib/aws-ec2"; +import { Certificate } from "aws-cdk-lib/aws-certificatemanager"; +import { HostedZone } from "aws-cdk-lib/aws-route53"; +import { Bucket, BlockPublicAccess } from "aws-cdk-lib/aws-s3"; +import * as ecrAssets from "aws-cdk-lib/aws-ecr-assets"; +import { AccessKey, User } from "aws-cdk-lib/aws-iam"; +import { Duration, RemovalPolicy, Stack } from "aws-cdk-lib"; +import * as path from "path"; +/** + * Options for configuring the Prerender Fargate construct. + */ export interface PrerenderOptions { - prerenderName: string, - domainName: string, - vpcId?: string, - bucketName?: string, - expirationDays?: number, - tokenList: Array, - certificateArn: string, - desiredInstanceCount?: number, - maxInstanceCount?: number, - instanceCPU?: number, - instanceMemory?: number - enableRedirectCache?: string - enableS3Endpoint?: boolean + /** + * The name of the Prerender service. + */ + prerenderName: string; + /** + * The domain name to prerender. + */ + domainName: string; + /** + * The ID of the VPC to deploy the Fargate service in. + */ + vpcId?: string; + /** + * The name of the S3 bucket to store prerendered pages in. + */ + bucketName?: string; + /** + * The number of days to keep prerendered pages in the S3 bucket before expiring them. + */ + expirationDays?: number; + /** + * A list of tokens to use for authentication with the Prerender service. + */ + tokenList: Array; + /** + * The ARN of the SSL certificate to use for HTTPS connections. + */ + certificateArn: string; + /** + * The desired number of Fargate instances to run. + */ + desiredInstanceCount?: number; + /** + * The maximum number of Fargate instances to run. + */ + maxInstanceCount?: number; + /** + * The amount of CPU to allocate to each Fargate instance. + */ + instanceCPU?: number; + /** + * The amount of memory to allocate to each Fargate instance. + */ + instanceMemory?: number; + /** + * Whether to enable caching of HTTP redirects. + */ + enableRedirectCache?: string; + /** + * Whether to enable the S3 endpoint for the VPC. + */ + enableS3Endpoint?: boolean; } export class PrerenderFargate extends Construct { - readonly bucket: Bucket; + readonly bucket: Bucket; - constructor(scope: Construct, id: string, props: PrerenderOptions) { - super(scope, id); + constructor(scope: Construct, id: string, props: PrerenderOptions) { + super(scope, id); - // Create bucket for prerender storage - this.bucket = new Bucket(this, `${props.prerenderName}-bucket`, { - bucketName: props.bucketName, - lifecycleRules: [{ - enabled: true, - expiration: Duration.days(props.expirationDays || 7) // Default to 7 day expiration - }], - removalPolicy: RemovalPolicy.DESTROY, - autoDeleteObjects: true, - blockPublicAccess: BlockPublicAccess.BLOCK_ALL, - }); + // Create bucket for prerender storage + this.bucket = new Bucket(this, `${props.prerenderName}-bucket`, { + bucketName: props.bucketName, + lifecycleRules: [ + { + enabled: true, + expiration: Duration.days(props.expirationDays || 7), // Default to 7 day expiration + }, + ], + removalPolicy: RemovalPolicy.DESTROY, + autoDeleteObjects: true, + blockPublicAccess: BlockPublicAccess.BLOCK_ALL, + }); - // Configure access to the bucket for the container - const user = new User(this, 'PrerenderAccess'); - this.bucket.grantReadWrite(user); + // Configure access to the bucket for the container + const user = new User(this, "PrerenderAccess"); + this.bucket.grantReadWrite(user); - const accessKey = new AccessKey(this, 'PrerenderAccessKey', { - user: user, - serial: 1 - }); + const accessKey = new AccessKey(this, "PrerenderAccessKey", { + user: user, + serial: 1, + }); - const vpcLookup = props.vpcId ? { vpcId: props.vpcId } : { isDefault: true }; - const vpc = ec2.Vpc.fromLookup(this, "vpc", vpcLookup); + const vpcLookup = props.vpcId + ? { vpcId: props.vpcId } + : { isDefault: true }; + const vpc = ec2.Vpc.fromLookup(this, "vpc", vpcLookup); - const cluster = new ecs.Cluster(this, `${props.prerenderName}-cluster`, { vpc: vpc }); + const cluster = new ecs.Cluster(this, `${props.prerenderName}-cluster`, { + vpc: vpc, + }); - const directory = path.join(__dirname, 'prerender'); - const asset = new ecrAssets.DockerImageAsset(this, `${props.prerenderName}-image`, { - directory, - }); + const directory = path.join(__dirname, "prerender"); + const asset = new ecrAssets.DockerImageAsset( + this, + `${props.prerenderName}-image`, + { + directory, + } + ); - // Create a load-balanced Fargate service - const fargateService = new ecsPatterns.ApplicationLoadBalancedFargateService( + // Create a load-balanced Fargate service + const fargateService = + new ecsPatterns.ApplicationLoadBalancedFargateService( + this, + `${props.prerenderName}-service`, + { + cluster, + serviceName: `${props.prerenderName}-service`, + desiredCount: props.desiredInstanceCount || 1, + cpu: props.instanceCPU || 512, // 0.5 vCPU default + memoryLimitMiB: props.instanceMemory || 1024, // 1 GB default to give Chrome enough memory + taskImageOptions: { + image: ecs.ContainerImage.fromDockerImageAsset(asset), + enableLogging: true, + containerPort: 3000, + environment: { + S3_BUCKET_NAME: this.bucket.bucketName, + AWS_ACCESS_KEY_ID: accessKey.accessKeyId, + AWS_SECRET_ACCESS_KEY: accessKey.secretAccessKey.unsafeUnwrap(), + AWS_REGION: Stack.of(this).region, + ENABLE_REDIRECT_CACHE: props.enableRedirectCache || "false", + TOKEN_LIST: props.tokenList.toString(), + }, + }, + healthCheckGracePeriod: Duration.seconds(20), + publicLoadBalancer: true, + assignPublicIp: true, + listenerPort: 443, + redirectHTTP: true, + domainName: props.domainName, + domainZone: new HostedZone(this, "hosted-zone", { + zoneName: props.domainName, + }), + certificate: Certificate.fromCertificateArn( this, - `${props.prerenderName}-service`, - { - cluster, - serviceName: `${props.prerenderName}-service`, - desiredCount: props.desiredInstanceCount || 1, - cpu: props.instanceCPU || 512, // 0.5 vCPU default - memoryLimitMiB: props.instanceMemory || 1024, // 1 GB default to give Chrome enough memory - taskImageOptions: { - image: ecs.ContainerImage.fromDockerImageAsset(asset), - enableLogging: true, - containerPort: 3000, - environment: { - S3_BUCKET_NAME: this.bucket.bucketName, - AWS_ACCESS_KEY_ID: accessKey.accessKeyId, - AWS_SECRET_ACCESS_KEY: accessKey.secretAccessKey.unsafeUnwrap(), - AWS_REGION: Stack.of(this).region, - ENABLE_REDIRECT_CACHE: props.enableRedirectCache || "false", - TOKEN_LIST: props.tokenList.toString() - } - }, - healthCheckGracePeriod: Duration.seconds(20), - publicLoadBalancer: true, - assignPublicIp: true, - listenerPort: 443, - redirectHTTP: true, - domainName: props.domainName, - domainZone: new HostedZone(this, 'hosted-zone', { zoneName: props.domainName }), - certificate: Certificate.fromCertificateArn(this, 'cert', props.certificateArn) - } - ); + "cert", + props.certificateArn + ), + } + ); - // As the prerender service will return a 401 on all unauthorised requests - // it should be considered healthy when receiving a 401 response - fargateService.targetGroup.configureHealthCheck({ - path: "/health", - interval: Duration.seconds(120), - unhealthyThresholdCount: 5, - healthyHttpCodes: '401' - }); + // As the prerender service will return a 401 on all unauthorised requests + // it should be considered healthy when receiving a 401 response + fargateService.targetGroup.configureHealthCheck({ + path: "/health", + interval: Duration.seconds(120), + unhealthyThresholdCount: 5, + healthyHttpCodes: "401", + }); - // Setup AutoScaling policy - const scaling = fargateService.service.autoScaleTaskCount({ - maxCapacity: props.maxInstanceCount || 2, - }); - scaling.scaleOnCpuUtilization(`${props.prerenderName}-scaling`, { - targetUtilizationPercent: 50, - scaleInCooldown: Duration.seconds(60), - scaleOutCooldown: Duration.seconds(60), - }); + // Setup AutoScaling policy + const scaling = fargateService.service.autoScaleTaskCount({ + maxCapacity: props.maxInstanceCount || 2, + }); + scaling.scaleOnCpuUtilization(`${props.prerenderName}-scaling`, { + targetUtilizationPercent: 50, + scaleInCooldown: Duration.seconds(60), + scaleOutCooldown: Duration.seconds(60), + }); - /** - * Enable VPC Endpoints for S3 - * This would create S3 endpoints in all the PUBLIC subnets of the VPC - */ - if (props.enableS3Endpoint) { - vpc.addGatewayEndpoint("S3Endpoint", { - service: ec2.GatewayVpcEndpointAwsService.S3, - subnets: [{ subnetType: ec2.SubnetType.PUBLIC }], - }); - } + /** + * Enable VPC Endpoints for S3 + * This would create S3 endpoints in all the PUBLIC subnets of the VPC + */ + if (props.enableS3Endpoint) { + vpc.addGatewayEndpoint("S3Endpoint", { + service: ec2.GatewayVpcEndpointAwsService.S3, + subnets: [{ subnetType: ec2.SubnetType.PUBLIC }], + }); } + } } From 518eff63ee4ecacb4a1fb144adab248aaf844680 Mon Sep 17 00:00:00 2001 From: Krishan Thisera Date: Thu, 12 Oct 2023 09:49:40 +1030 Subject: [PATCH 09/27] DO-1545: regenerate the lockfile --- package-lock.json | 70 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 63 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index ba543ed6..bfc990fc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -46,6 +46,10 @@ "resolved": "packages/lambda-at-edge-handlers", "link": true }, + "node_modules/@aligent/cdk-prerender-fargate": { + "resolved": "packages/prerender-fargate", + "link": true + }, "node_modules/@aligent/cdk-prerender-proxy": { "resolved": "packages/prerender-proxy", "link": true @@ -98,6 +102,44 @@ "resolved": "https://registry.npmjs.org/@aws-cdk/asset-node-proxy-agent-v6/-/asset-node-proxy-agent-v6-2.0.1.tgz", "integrity": "sha512-DDt4SLdLOwWCjGtltH4VCST7hpOI5DzieuhGZsBpZ+AgJdSI2GCjklCXm0GCTwJG/SolkL5dtQXyUKgg9luBDg==" }, + "node_modules/@aws-cdk/aws-apigatewayv2-alpha": { + "version": "2.30.0-alpha.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-apigatewayv2-alpha/-/aws-apigatewayv2-alpha-2.30.0-alpha.0.tgz", + "integrity": "sha512-D5AB4x7Ayicbb87gb7wVJGuyFrqjelw48gvMADvNecw8md5aOSJ7jvwlSEGMZMiJ1UhjNhea7AWSNdAOI2SfBQ==", + "engines": { + "node": ">= 14.15.0" + }, + "peerDependencies": { + "aws-cdk-lib": "^2.30.0", + "constructs": "^10.0.0" + } + }, + "node_modules/@aws-cdk/aws-apigatewayv2-authorizers-alpha": { + "version": "2.30.0-alpha.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-apigatewayv2-authorizers-alpha/-/aws-apigatewayv2-authorizers-alpha-2.30.0-alpha.0.tgz", + "integrity": "sha512-/oIxg3boxN+a4qqRQHEZ5LgjSgMFDukMx5pbTcJ4lEoEe9FpJaJ/FY8IJ0ZR1TfpfxGhVNwHUpMprkqRh9SYSA==", + "engines": { + "node": ">= 14.15.0" + }, + "peerDependencies": { + "@aws-cdk/aws-apigatewayv2-alpha": "2.30.0-alpha.0", + "aws-cdk-lib": "^2.30.0", + "constructs": "^10.0.0" + } + }, + "node_modules/@aws-cdk/aws-apigatewayv2-integrations-alpha": { + "version": "2.30.0-alpha.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-apigatewayv2-integrations-alpha/-/aws-apigatewayv2-integrations-alpha-2.30.0-alpha.0.tgz", + "integrity": "sha512-2/NAb0AFGwZQjNqpViiagJxKa8u0hy09GV7W/AKSEzLmQp1H2Jmg8oSGLudXVTF/VtsgjQUAL4MuxTRAXFtJoQ==", + "engines": { + "node": ">= 14.15.0" + }, + "peerDependencies": { + "@aws-cdk/aws-apigatewayv2-alpha": "2.30.0-alpha.0", + "aws-cdk-lib": "^2.30.0", + "constructs": "^10.0.0" + } + }, "node_modules/@babel/code-frame": { "version": "7.22.13", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", @@ -1723,7 +1765,8 @@ "node_modules/@types/aws-lambda": { "version": "8.10.122", "resolved": "https://registry.npmjs.org/@types/aws-lambda/-/aws-lambda-8.10.122.tgz", - "integrity": "sha512-vBkIh9AY22kVOCEKo5CJlyCgmSWvasC+SWUxL/x/vOwRobMpI/HG1xp/Ae3AqmSiZeLUbOhW0FCD3ZjqqUxmXw==" + "integrity": "sha512-vBkIh9AY22kVOCEKo5CJlyCgmSWvasC+SWUxL/x/vOwRobMpI/HG1xp/Ae3AqmSiZeLUbOhW0FCD3ZjqqUxmXw==", + "dev": true }, "node_modules/@types/babel__core": { "version": "7.20.2", @@ -5910,13 +5953,13 @@ "version": "2.0.0", "license": "GPL-3.0-only", "dependencies": { - "@types/aws-lambda": "^8.10.122", "aws-cdk-lib": "2.97.0", "constructs": "^10.0.0", "esbuild": "^0.17.0", "source-map-support": "^0.5.21" }, "devDependencies": { + "@types/aws-lambda": "^8.10.122", "@types/jest": "^29.5.5", "@types/node": "20.6.3", "aws-cdk": "2.97.0", @@ -5930,12 +5973,12 @@ "name": "@aligent/cdk-cloudfront-security-headers", "version": "2.0.0", "dependencies": { - "@types/aws-lambda": "^8.10.122", "aws-cdk-lib": "2.97.0", "constructs": "^10.0.0", "source-map-support": "^0.5.21" }, "devDependencies": { + "@types/aws-lambda": "^8.10.122", "@types/jest": "^29.5.5", "@types/node": "20.6.3", "aws-cdk": "2.97.0", @@ -5970,12 +6013,12 @@ "version": "0.1.0", "license": "GPL-3.0-only", "dependencies": { - "@types/aws-lambda": "^8.10.122", "aws-cdk-lib": "2.97.0", "constructs": "^10.0.0", "source-map-support": "^0.5.21" }, "devDependencies": { + "@types/aws-lambda": "^8.10.122", "@types/jest": "^29.5.5", "@types/node": "20.6.3", "aws-cdk": "2.97.0", @@ -5986,12 +6029,25 @@ } }, "packages/lambda-at-edge-handlers": { + "name": "@aligent/cdk-lambda-at-edge-handlers", "version": "0.1.0", "license": "GPL-3.0-only", "dependencies": { - "@types/aws-lambda": "^8.10.122", "axios": "^1.5.1", "source-map-support": "^0.5.21" + }, + "devDependencies": { + "@types/aws-lambda": "^8.10.122" + } + }, + "packages/prerender-fargate": { + "name": "@aligent/cdk-prerender-fargate", + "version": "0.0.1", + "license": "GPL-3.0-only", + "dependencies": { + "@aws-cdk/aws-apigatewayv2-alpha": "2.30.0-alpha.0", + "@aws-cdk/aws-apigatewayv2-authorizers-alpha": "2.30.0-alpha.0", + "@aws-cdk/aws-apigatewayv2-integrations-alpha": "2.30.0-alpha.0" } }, "packages/prerender-proxy": { @@ -5999,7 +6055,6 @@ "version": "2.0.0", "license": "GPL-3.0-only", "dependencies": { - "@types/aws-lambda": "^8.10.122", "aws-cdk-lib": "2.97.0", "axios": "^1.5.1", "constructs": "^10.0.0", @@ -6007,6 +6062,7 @@ "source-map-support": "^0.5.21" }, "devDependencies": { + "@types/aws-lambda": "^8.10.122", "@types/jest": "^29.5.5", "@types/node": "20.6.3", "aws-cdk": "2.97.0", @@ -6058,13 +6114,13 @@ "version": "2.0.0", "license": "GPL-3.0-only", "dependencies": { - "@types/aws-lambda": "^8.10.122", "aws-cdk-lib": "2.97.0", "constructs": "^10.0.0", "esbuild": "^0.17.0", "source-map-support": "^0.5.21" }, "devDependencies": { + "@types/aws-lambda": "^8.10.122", "@types/jest": "^29.5.5", "@types/node": "20.6.3", "aws-cdk": "2.97.0", From 6c1788a2fd227bd2ac0affa59979face78505d19 Mon Sep 17 00:00:00 2001 From: Krishan Thisera Date: Thu, 12 Oct 2023 14:00:11 +1030 Subject: [PATCH 10/27] DO-1546: prerender recaching implementation --- .eslintrc.json | 11 +- .../lib/prerender-fargate.ts | 51 +++- .../prerender-recache-api-construct.api.ts | 226 ++++++++++++++++++ ...rerender-recache-api-construct.consumer.ts | 21 ++ .../prerender-recache-api-construct.ts | 98 ++++++++ .../lib/recaching/prerender-tokens.ts | 53 ++++ packages/prerender-fargate/package.json | 5 + 7 files changed, 461 insertions(+), 4 deletions(-) create mode 100644 packages/prerender-fargate/lib/recaching/prerender-recache-api-construct.api.ts create mode 100644 packages/prerender-fargate/lib/recaching/prerender-recache-api-construct.consumer.ts create mode 100644 packages/prerender-fargate/lib/recaching/prerender-recache-api-construct.ts create mode 100644 packages/prerender-fargate/lib/recaching/prerender-tokens.ts diff --git a/.eslintrc.json b/.eslintrc.json index 319c5d29..a26ca0ea 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -11,5 +11,14 @@ "ecmaVersion": "latest" }, "plugins": ["@typescript-eslint", "prettier"], - "rules": {} + "rules": { + "@typescript-eslint/no-unused-vars": [ + "warn", // or "error" + { + "argsIgnorePattern": "^_", + "varsIgnorePattern": "^_", + "caughtErrorsIgnorePattern": "^_" + } + ] + } } diff --git a/packages/prerender-fargate/lib/prerender-fargate.ts b/packages/prerender-fargate/lib/prerender-fargate.ts index acb8113c..5daca9a7 100644 --- a/packages/prerender-fargate/lib/prerender-fargate.ts +++ b/packages/prerender-fargate/lib/prerender-fargate.ts @@ -9,7 +9,8 @@ import * as ecrAssets from 'aws-cdk-lib/aws-ecr-assets'; import { AccessKey, User } from 'aws-cdk-lib/aws-iam'; import { Duration, RemovalPolicy, Stack } from 'aws-cdk-lib'; import * as path from 'path'; - +import { PrerenderRecacheApi } from "./recaching/prerender-recache-api-construct"; +import { PrerenderTokenUrlAssociation, PrerenderTokensUrlAssociation } from './recaching/prerender-tokens'; export interface PrerenderOptions { prerenderName: string, domainName: string, @@ -23,11 +24,18 @@ export interface PrerenderOptions { instanceCPU?: number, instanceMemory?: number enableRedirectCache?: string + tokenUrlAssociation?: PrerenderTokenUrlAssociation, } export class PrerenderFargate extends Construct { readonly bucket: Bucket; + /** + * Constructs a new Prerender Fargate service. + * @param scope The scope of the construct. + * @param id The ID of the construct. + * @param props The properties of the Prerender Fargate service. + */ constructor(scope: Construct, id: string, props: PrerenderOptions) { super(scope, id); @@ -62,6 +70,12 @@ export class PrerenderFargate extends Construct { directory, }); + /** + * This provide backward compatibility for the tokenList property + * If tokenUrlAssociation is provided, tokenList will be ignored + */ + const tokenList = props.tokenUrlAssociation ? Object.keys(props.tokenUrlAssociation.tokenUrlAssociation) : props.tokenList.toString(); + // Create a load-balanced Fargate service const fargateService = new ecsPatterns.ApplicationLoadBalancedFargateService( this, @@ -82,7 +96,7 @@ export class PrerenderFargate extends Construct { AWS_SECRET_ACCESS_KEY: accessKey.secretAccessKey.unsafeUnwrap(), AWS_REGION: Stack.of(this).region, ENABLE_REDIRECT_CACHE: props.enableRedirectCache || "false", - TOKEN_LIST: props.tokenList.toString() + TOKEN_LIST: tokenList.toString() } }, healthCheckGracePeriod: Duration.seconds(20), @@ -114,5 +128,36 @@ export class PrerenderFargate extends Construct { scaleInCooldown: Duration.seconds(60), scaleOutCooldown: Duration.seconds(60), }); + + /** + * Recache API + * Recaching is enable by default + */ + if (props.tokenUrlAssociation) { + /** + * Create the token-url association + * This is used for managing prerender tokens in prerender re-caching. + * Example: + * { + * tokenUrlAssociation: { + * token1: [url1, url2], + * token2: [url3, url4]}, + * ssmPathPrefix: /prerender/recache/tokens + * } + */ + new PrerenderTokensUrlAssociation(this, `${props.prerenderName}-token-url-association`, { + tokenUrlAssociation: props.tokenUrlAssociation.tokenUrlAssociation, + ssmPathPrefix: props.tokenUrlAssociation.ssmPathPrefix + }); + + /** + * Create the recache API + * This would create the API that can be used to trigger recaching of URLs. + */ + new PrerenderRecacheApi(this, `${props.prerenderName}-recache-api`, { + prerenderS3Bucket: this.bucket, + tokenList: Object.keys(props.tokenUrlAssociation.tokenUrlAssociation), + }); + } } -} +} \ No newline at end of file diff --git a/packages/prerender-fargate/lib/recaching/prerender-recache-api-construct.api.ts b/packages/prerender-fargate/lib/recaching/prerender-recache-api-construct.api.ts new file mode 100644 index 00000000..175fde67 --- /dev/null +++ b/packages/prerender-fargate/lib/recaching/prerender-recache-api-construct.api.ts @@ -0,0 +1,226 @@ +import { Context, APIGatewayEvent, APIGatewayProxyResult } from "aws-lambda"; +import { + S3Client, + DeleteObjectsCommand, + DeleteObjectsCommandOutput, + ObjectIdentifier, +} from "@aws-sdk/client-s3"; +import { + SQSClient, + SendMessageBatchCommand, + SendMessageBatchRequestEntry, +} from "@aws-sdk/client-sqs"; +import { SSMClient, GetParameterCommand } from "@aws-sdk/client-ssm"; +import { md5hash } from "aws-cdk-lib/core/lib/helpers-internal"; + +/** + * Interface for the request body of the PreRender API recache endpoint. + */ +interface PreRenderRequestBody { + /** + * The prerender token used to authenticate the request. + */ + prerenderToken: string; + /** + * The URL to recache. Optional if `urls` is provided. + */ + url?: string; + /** + * An array of URLs to recache. Optional if `url` is provided. + */ + urls?: string[]; +} + +const QueueUrl = process.env.SQS_QUEUE_URL; +const Bucket = process.env.PRERENDER_CACHE_BUCKET; + + +export const MAX_URLS = 1000; +export const PARAM_PREFIX = "prerender/recache/tokens"; + +const sqsClient = new SQSClient({}); +const s3Client = new S3Client({}); +const ssmClient = new SSMClient({}); + +const tokens: Map = new Map(); + +/** + * Handles the recaching of URLs and returns a response with the recached URLs. + * @param {APIGatewayEvent} event - The event object passed by AWS API Gateway. + * @param {Context} _context - The context object passed by AWS Lambda. + * @returns {Promise} - A promise that resolves to an APIGatewayProxyResult object. + */ +export const handler = async ( + event: APIGatewayEvent, + _context: Context +): Promise => { + let urlsToRecache: string[]; + + try { + urlsToRecache = await getUrlsToRecache(event.body || ""); + console.log(urlsToRecache); + } catch (error) { + return { + statusCode: 403, + body: JSON.stringify({ + error, + message: `Token does not exist or is misconfigured`, + }), + }; + } + + if (urlsToRecache.length > MAX_URLS) { + console.log( + `Too many urls, received ${urlsToRecache.length}, maximum is ${MAX_URLS}` + ); + return { + statusCode: 400, + body: JSON.stringify({ + error: `Too many urls, maximum is ${MAX_URLS}`, + }), + }; + } + + if (urlsToRecache.length === 0) { + console.log("No valid urls to recache"); + return { + statusCode: 200, + body: JSON.stringify({ + message: "No urls to recache", + }), + }; + } + + console.log(await deleteCacheContentForUrls(urlsToRecache)); + await queueRecachineUrls(urlsToRecache); + + return { + statusCode: 200, + body: JSON.stringify({ + urlsToRecache, + }), + }; +}; + +/** + * Parses the given request body and returns an array of URLs to recache. + * @param body - The request body to parse. + * @returns An array of URLs to recache. + * @throws An error if the token is not valid or if no parameters are returned. + */ +const getUrlsToRecache = async (body: string): Promise => { + const requestBody: PreRenderRequestBody = JSON.parse(body); + + let urls: string[]; + if (requestBody.urls !== undefined) { + urls = requestBody.urls; + } else if (requestBody.url !== undefined) { + urls = [requestBody.url]; + } else { + urls = []; + } + + const token = requestBody.prerenderToken; + + if (!tokens.has(token)) { + const Name = `/${PARAM_PREFIX}/${token}`; + console.log(`Looking for allowed urls in ssm:${Name}`); + + const getAllowedUrls = new GetParameterCommand({ Name }); + console.log(getAllowedUrls); + + const ssmResponse = await ssmClient.send(getAllowedUrls); + + if (ssmResponse.Parameter === undefined) { + throw "No parameters returned"; + } + + const allowedUrlsResult = ssmResponse.Parameter; + if (allowedUrlsResult.Type === undefined) { + throw "Token not valid"; + } + + if (allowedUrlsResult.Type !== "StringList") { + throw `Token data is not a string list, ${Name} is ${allowedUrlsResult.Type}`; + } + + tokens.set(token, allowedUrlsResult.Value?.split(",") || []); + } + + const allowedUrls = tokens.get(token) || []; + + console.log(`Allowed urls for ${token}: ${allowedUrls.join(", ")}`); + + const isValidUrlForToken = (url: string): boolean => + allowedUrls.find(a => url.includes(a)) !== undefined; + + return urls.filter(isValidUrlForToken); +}; + +/** + * Deletes the cache content for the given URLs from the S3 bucket. + * @param urlsToRecache - An array of URLs to delete from the cache. + * @returns A Promise that resolves to the output of the DeleteObjectsCommand. + */ +const deleteCacheContentForUrls = async ( + urlsToRecache: string[] +): Promise => { + const mapUrlToKey = (Key: string): ObjectIdentifier => { + return { Key }; + }; + + console.log(`Deleting ${urlsToRecache.length} objects from ${Bucket}`); + + const deleteObjects = new DeleteObjectsCommand({ + Bucket, + Delete: { + Objects: urlsToRecache.map(mapUrlToKey), + Quiet: true, + }, + }); + + return await s3Client.send(deleteObjects); +}; + +/** + * Queues the given URLs for recaching. + * @param urlsToRecache An array of URLs to recache. + */ +const queueRecachineUrls = async (urlsToRecache: string[]) => { + const generateEntry = (url: string): SendMessageBatchRequestEntry => { + return { + DelaySeconds: 1, + Id: md5hash(url) + url.replace(/[^A-Z0-9_-]+/gi, "_").slice(-47), + MessageBody: url, + }; + }; + + const urlsToRequest = chunkUrls(urlsToRecache, 10); + + const messages = urlsToRequest.map((urls: string[]) => { + return new SendMessageBatchCommand({ + QueueUrl, + Entries: urls.map(generateEntry), + }); + }); + + console.log(`Sending ${messages.length} recaching message batches`); + + await Promise.all(messages.map(m => sqsClient.send(m))); +}; + +/** + * Splits an array of strings into smaller arrays of a specified size. + * @param array - The array of strings to be split. + * @param chunkSize - The maximum size of each chunk. + * @returns An array of arrays, where each inner array contains a maximum of `chunkSize` strings. + */ +const chunkUrls = (array: string[], chunkSize: number): string[][] => { + const chunks: string[][] = []; + for (let i = 0; i < array.length; i += chunkSize) { + const chunk = array.slice(i, i + chunkSize); + chunks.push(chunk); + } + + return chunks; +}; diff --git a/packages/prerender-fargate/lib/recaching/prerender-recache-api-construct.consumer.ts b/packages/prerender-fargate/lib/recaching/prerender-recache-api-construct.consumer.ts new file mode 100644 index 00000000..58ddbaef --- /dev/null +++ b/packages/prerender-fargate/lib/recaching/prerender-recache-api-construct.consumer.ts @@ -0,0 +1,21 @@ +import { Context, SQSEvent, SQSRecord } from "aws-lambda"; +import axios from "axios"; + +const userAgent = "prerender / Googlebot recaching request"; + +/** + * Handles the recaching of URLs received via SQS event. + * @param event - The SQS event containing the URLs to recache. + * @param context - The AWS Lambda context object. + */ +export const handler = async (event: SQSEvent, _context: Context) => { + event.Records.forEach(async (record: SQSRecord) => { + const url = record.body; + console.log(`Fetching ${url} for recaching`); + await axios.get(url, { + headers: { + "User-Agent": userAgent, + }, + }); + }); +}; diff --git a/packages/prerender-fargate/lib/recaching/prerender-recache-api-construct.ts b/packages/prerender-fargate/lib/recaching/prerender-recache-api-construct.ts new file mode 100644 index 00000000..b812174f --- /dev/null +++ b/packages/prerender-fargate/lib/recaching/prerender-recache-api-construct.ts @@ -0,0 +1,98 @@ +import { Construct } from "constructs"; +import { LambdaRestApi } from "aws-cdk-lib/aws-apigateway"; +import { LambdaToSqsToLambda } from "@aws-solutions-constructs/aws-lambda-sqs-lambda"; +import { NodejsFunction } from "aws-cdk-lib/aws-lambda-nodejs"; +import * as iam from "aws-cdk-lib/aws-iam"; +import { Bucket } from "aws-cdk-lib/aws-s3"; +import { Duration } from "aws-cdk-lib"; + +/** + * Options for the Prerender Recache API. + */ +export interface PrerenderRecacheApiOptions { + /** + * The S3 bucket where prerendered pages are stored. + */ + prerenderS3Bucket: Bucket; + /** + * A list of tokens used to authenticate API requests. + */ + tokenList: string[]; +} + +/** + * Represents an API for recaching prerendered pages. + */ +export class PrerenderRecacheApi extends Construct { + readonly api: LambdaRestApi; + + constructor( + scope: Construct, + id: string, + options: PrerenderRecacheApiOptions + ) { + super(scope, id); + + const apiHandler = createApiLambdaFunction(this, options); + + this.api = new LambdaRestApi(this, "prerenderRecacheApi", { + handler: apiHandler, + proxy: false, + }); + + options.tokenList.forEach(k => this.api.addApiKey(k)); + + const recache = this.api.root.addResource("recache"); + recache.addMethod("POST"); + + new LambdaToSqsToLambda(this, "prerenderRequestQueue", { + existingProducerLambdaObj: apiHandler, + existingConsumerLambdaObj: new NodejsFunction(this, "consumer", { + timeout: Duration.seconds(60), + }), + deployDeadLetterQueue: false, + queueProps: { visibilityTimeout: Duration.minutes(60) }, + }); + } +} + +/** + * Creates a NodejsFunction that handles the Prerender Recache API. + * @param scope - The Construct scope. + * @param options - The options for the Prerender Recache API. + * @returns The NodejsFunction that handles the Prerender Recache API. + */ +const createApiLambdaFunction = ( + scope: Construct, + options: PrerenderRecacheApiOptions +): NodejsFunction => { + const apiHandler = new NodejsFunction(scope, "api", { + timeout: Duration.seconds(60), + }); + + apiHandler.addEnvironment( + "PRERENDER_CACHE_BUCKET", + options.prerenderS3Bucket.bucketName + ); + + const ssmGetParameterPolicy = new iam.PolicyStatement({ + actions: ["ssm:GetParameter"], + resources: ["*"], + }); // should be arn:aws:ssm:::parameter/prerender/recache/tokens/*, but can't make that work + + const ssmDescribeParameterPolicy = new iam.PolicyStatement({ + actions: ["ssm:DescribeParameters"], + resources: ["*"], + }); + + const s3DeleteObjectPolicy = new iam.PolicyStatement({ + actions: ["s3:DeleteObject"], + resources: [`${options.prerenderS3Bucket.bucketArn}/*`], + }); + + apiHandler.addToRolePolicy(ssmGetParameterPolicy); + apiHandler.addToRolePolicy(ssmDescribeParameterPolicy); + apiHandler.addToRolePolicy(s3DeleteObjectPolicy); + + return apiHandler; +}; diff --git a/packages/prerender-fargate/lib/recaching/prerender-tokens.ts b/packages/prerender-fargate/lib/recaching/prerender-tokens.ts new file mode 100644 index 00000000..af040d1c --- /dev/null +++ b/packages/prerender-fargate/lib/recaching/prerender-tokens.ts @@ -0,0 +1,53 @@ +import { Stack, StackProps } from "aws-cdk-lib"; +import { Construct } from "constructs"; +import { StringListParameter } from "aws-cdk-lib/aws-ssm"; + +/** + * An interface representing a mapping of URLs to an array of associated tokens. + */ +interface TokenUrlAssociation { + [url: string]: string[]; +} + +/** + * Interface for associating a token with a URL for prerendering. + */ +export interface PrerenderTokenUrlAssociation extends StackProps { + /** + * Object containing the token and its associated URL. + */ + tokenUrlAssociation: TokenUrlAssociation; + /** + * Prefix for the SSM parameter path where the token value is stored. + */ + ssmPathPrefix: string; +} + +/** + * This is used for managing prerender tokens in prerender re-caching. + * It takes a mapping between URLs and prerender tokens as input, and + * creates an SSM parameter for each token that contains a list of domain + * names associated with the token. + * The constructor loops through the tokenUrlAssociation object and + * creates an SSM parameter for each token. + */ +export class PrerenderTokensUrlAssociation extends Stack { + constructor( + scope: Construct, + id: string, + props: PrerenderTokenUrlAssociation + ) { + super(scope, id, props); + + const { tokenUrlAssociation, ssmPathPrefix } = props; + + // Loop through the tokenDomains + for (const [token, domains] of Object.entries(tokenUrlAssociation)) { + // Create an SSM parameter for each token + new StringListParameter(this, `prerender-${domains[0]}`, { + parameterName: `${ssmPathPrefix.replace(/\/$/, "")}/${token}`, + stringListValue: domains, + }); + } + } +} diff --git a/packages/prerender-fargate/package.json b/packages/prerender-fargate/package.json index b99a0c12..64543be1 100644 --- a/packages/prerender-fargate/package.json +++ b/packages/prerender-fargate/package.json @@ -17,6 +17,11 @@ }, "homepage": "https://github.com/aligent/cdk-constructs/tree/main/packages/prerender-fargate#readme", "dependencies": { + "@aligent/cdk-prerender-fargate": "0.1.10", + "@aws-sdk/client-s3": "^3.421.0", + "@aws-sdk/client-sqs": "^3.421.0", + "@aws-sdk/client-ssm": "^3.421.0", + "@aws-solutions-constructs/aws-lambda-sqs-lambda": "^2.44.0", "@aws-cdk/aws-apigatewayv2-alpha": "2.30.0-alpha.0", "@aws-cdk/aws-apigatewayv2-authorizers-alpha": "2.30.0-alpha.0", "@aws-cdk/aws-apigatewayv2-integrations-alpha": "2.30.0-alpha.0" From 56a145cf36cf28104155dc106e1805197a7a8699 Mon Sep 17 00:00:00 2001 From: Krishan Thisera Date: Thu, 12 Oct 2023 18:19:47 +1030 Subject: [PATCH 11/27] DO-1546: including prerender re-cache functionality and update the docs --- package-lock.json | 4528 ++++++++++++----- packages/prerender-fargate/index.ts | 5 +- .../lib/prerender-fargate-options.ts | 81 + .../lib/prerender-fargate.ts | 286 +- .../prerender-recache-api-construct.api.ts | 5 +- .../lib/recaching/prerender-tokens.ts | 22 +- 6 files changed, 3612 insertions(+), 1315 deletions(-) create mode 100644 packages/prerender-fargate/lib/prerender-fargate-options.ts diff --git a/package-lock.json b/package-lock.json index bfc990fc..296b5f27 100644 --- a/package-lock.json +++ b/package-lock.json @@ -140,1604 +140,3737 @@ "constructs": "^10.0.0" } }, - "node_modules/@babel/code-frame": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", - "dev": true, + "node_modules/@aws-crypto/crc32": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-3.0.0.tgz", + "integrity": "sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==", "dependencies": { - "@babel/highlight": "^7.22.13", - "chalk": "^2.4.2" - }, - "engines": { - "node": ">=6.9.0" + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^1.11.1" } }, - "node_modules/@babel/code-frame/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, + "node_modules/@aws-crypto/crc32c": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32c/-/crc32c-3.0.0.tgz", + "integrity": "sha512-ENNPPManmnVJ4BTXlOjAgD7URidbAznURqD0KvfREyc4o20DPYdEldU1f5cQ7Jbj0CJJSPaMIk/9ZshdB3210w==", "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^1.11.1" } }, - "node_modules/@babel/code-frame/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, + "node_modules/@aws-crypto/ie11-detection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/ie11-detection/-/ie11-detection-3.0.0.tgz", + "integrity": "sha512-341lBBkiY1DfDNKai/wXM3aujNBkXR7tq1URPQDL9wi3AUbI80NR74uF1TXHMm7po1AcnFk8iu2S2IeU/+/A+Q==", "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" + "tslib": "^1.11.1" } }, - "node_modules/@babel/code-frame/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, + "node_modules/@aws-crypto/sha1-browser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha1-browser/-/sha1-browser-3.0.0.tgz", + "integrity": "sha512-NJth5c997GLHs6nOYTzFKTbYdMNA6/1XlKVgnZoaZcQ7z7UJlOgj2JdbHE8tiYLS3fzXNCguct77SPGat2raSw==", "dependencies": { - "color-name": "1.1.3" + "@aws-crypto/ie11-detection": "^3.0.0", + "@aws-crypto/supports-web-crypto": "^3.0.0", + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@aws-sdk/util-utf8-browser": "^3.0.0", + "tslib": "^1.11.1" } }, - "node_modules/@babel/code-frame/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true + "node_modules/@aws-crypto/sha256-browser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-3.0.0.tgz", + "integrity": "sha512-8VLmW2B+gjFbU5uMeqtQM6Nj0/F1bro80xQXCW6CQBWgosFWXTx77aeOF5CAIAmbOK64SdMBJdNr6J41yP5mvQ==", + "dependencies": { + "@aws-crypto/ie11-detection": "^3.0.0", + "@aws-crypto/sha256-js": "^3.0.0", + "@aws-crypto/supports-web-crypto": "^3.0.0", + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@aws-sdk/util-utf8-browser": "^3.0.0", + "tslib": "^1.11.1" + } }, - "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" + "node_modules/@aws-crypto/sha256-js": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-3.0.0.tgz", + "integrity": "sha512-PnNN7os0+yd1XvXAy23CFOmTbMaDxgxXtTKHybrJ39Y8kGzBATgBFibWJKH6BhytLI/Zyszs87xCOBNyBig6vQ==", + "dependencies": { + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^1.11.1" } }, - "node_modules/@babel/code-frame/node_modules/has-flag": { + "node_modules/@aws-crypto/supports-web-crypto": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" + "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-3.0.0.tgz", + "integrity": "sha512-06hBdMwUAb2WFTuGG73LSC0wfPu93xWwo5vL2et9eymgmu3Id5vFAHBbajVWiGhPO37qcsdCap/FqXvJGJWPIg==", + "dependencies": { + "tslib": "^1.11.1" } }, - "node_modules/@babel/code-frame/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, + "node_modules/@aws-crypto/util": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-3.0.0.tgz", + "integrity": "sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w==", + "dependencies": { + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-utf8-browser": "^3.0.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-sdk/client-s3": { + "version": "3.427.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.427.0.tgz", + "integrity": "sha512-YKjJ9zgn0oE393HURKgvjNoX6lxUjb+dkTBE1GymFnGCPl6VxQbKXajXWNqUyN+oPPlZ2osEiljPaN0RserUjA==", + "dependencies": { + "@aws-crypto/sha1-browser": "3.0.0", + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/client-sts": "3.427.0", + "@aws-sdk/credential-provider-node": "3.427.0", + "@aws-sdk/middleware-bucket-endpoint": "3.425.0", + "@aws-sdk/middleware-expect-continue": "3.425.0", + "@aws-sdk/middleware-flexible-checksums": "3.425.0", + "@aws-sdk/middleware-host-header": "3.425.0", + "@aws-sdk/middleware-location-constraint": "3.425.0", + "@aws-sdk/middleware-logger": "3.425.0", + "@aws-sdk/middleware-recursion-detection": "3.425.0", + "@aws-sdk/middleware-sdk-s3": "3.427.0", + "@aws-sdk/middleware-signing": "3.425.0", + "@aws-sdk/middleware-ssec": "3.425.0", + "@aws-sdk/middleware-user-agent": "3.427.0", + "@aws-sdk/region-config-resolver": "3.425.0", + "@aws-sdk/signature-v4-multi-region": "3.425.0", + "@aws-sdk/types": "3.425.0", + "@aws-sdk/util-endpoints": "3.427.0", + "@aws-sdk/util-user-agent-browser": "3.425.0", + "@aws-sdk/util-user-agent-node": "3.425.0", + "@aws-sdk/xml-builder": "3.310.0", + "@smithy/config-resolver": "^2.0.11", + "@smithy/eventstream-serde-browser": "^2.0.10", + "@smithy/eventstream-serde-config-resolver": "^2.0.10", + "@smithy/eventstream-serde-node": "^2.0.10", + "@smithy/fetch-http-handler": "^2.2.1", + "@smithy/hash-blob-browser": "^2.0.10", + "@smithy/hash-node": "^2.0.10", + "@smithy/hash-stream-node": "^2.0.10", + "@smithy/invalid-dependency": "^2.0.10", + "@smithy/md5-js": "^2.0.10", + "@smithy/middleware-content-length": "^2.0.12", + "@smithy/middleware-endpoint": "^2.0.10", + "@smithy/middleware-retry": "^2.0.13", + "@smithy/middleware-serde": "^2.0.10", + "@smithy/middleware-stack": "^2.0.4", + "@smithy/node-config-provider": "^2.0.13", + "@smithy/node-http-handler": "^2.1.6", + "@smithy/protocol-http": "^3.0.6", + "@smithy/smithy-client": "^2.1.9", + "@smithy/types": "^2.3.4", + "@smithy/url-parser": "^2.0.10", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.13", + "@smithy/util-defaults-mode-node": "^2.0.15", + "@smithy/util-retry": "^2.0.3", + "@smithy/util-stream": "^2.0.14", + "@smithy/util-utf8": "^2.0.0", + "@smithy/util-waiter": "^2.0.10", + "fast-xml-parser": "4.2.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/client-sqs": { + "version": "3.427.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sqs/-/client-sqs-3.427.0.tgz", + "integrity": "sha512-oVgRdqdxugywhjAOzu+S5QqVF8BdaXF109VRb7rWtLU44Yd8yDDWJtbJAbTPF2N0M3VVdOhG0i6AsT7F44qXyA==", + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/client-sts": "3.427.0", + "@aws-sdk/credential-provider-node": "3.427.0", + "@aws-sdk/middleware-host-header": "3.425.0", + "@aws-sdk/middleware-logger": "3.425.0", + "@aws-sdk/middleware-recursion-detection": "3.425.0", + "@aws-sdk/middleware-sdk-sqs": "3.425.0", + "@aws-sdk/middleware-signing": "3.425.0", + "@aws-sdk/middleware-user-agent": "3.427.0", + "@aws-sdk/region-config-resolver": "3.425.0", + "@aws-sdk/types": "3.425.0", + "@aws-sdk/util-endpoints": "3.427.0", + "@aws-sdk/util-user-agent-browser": "3.425.0", + "@aws-sdk/util-user-agent-node": "3.425.0", + "@smithy/config-resolver": "^2.0.11", + "@smithy/fetch-http-handler": "^2.2.1", + "@smithy/hash-node": "^2.0.10", + "@smithy/invalid-dependency": "^2.0.10", + "@smithy/md5-js": "^2.0.10", + "@smithy/middleware-content-length": "^2.0.12", + "@smithy/middleware-endpoint": "^2.0.10", + "@smithy/middleware-retry": "^2.0.13", + "@smithy/middleware-serde": "^2.0.10", + "@smithy/middleware-stack": "^2.0.4", + "@smithy/node-config-provider": "^2.0.13", + "@smithy/node-http-handler": "^2.1.6", + "@smithy/protocol-http": "^3.0.6", + "@smithy/smithy-client": "^2.1.9", + "@smithy/types": "^2.3.4", + "@smithy/url-parser": "^2.0.10", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.13", + "@smithy/util-defaults-mode-node": "^2.0.15", + "@smithy/util-retry": "^2.0.3", + "@smithy/util-utf8": "^2.0.0", + "fast-xml-parser": "4.2.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-sqs/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/client-ssm": { + "version": "3.427.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-ssm/-/client-ssm-3.427.0.tgz", + "integrity": "sha512-wKEO5olofXue2EFv5tMMZkDGWeapvdX7aaYpMjTz3KV2LXSl/KApqcv4G5jMNovbaFkVpBCbztBVW6S8VzHu/w==", + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/client-sts": "3.427.0", + "@aws-sdk/credential-provider-node": "3.427.0", + "@aws-sdk/middleware-host-header": "3.425.0", + "@aws-sdk/middleware-logger": "3.425.0", + "@aws-sdk/middleware-recursion-detection": "3.425.0", + "@aws-sdk/middleware-signing": "3.425.0", + "@aws-sdk/middleware-user-agent": "3.427.0", + "@aws-sdk/region-config-resolver": "3.425.0", + "@aws-sdk/types": "3.425.0", + "@aws-sdk/util-endpoints": "3.427.0", + "@aws-sdk/util-user-agent-browser": "3.425.0", + "@aws-sdk/util-user-agent-node": "3.425.0", + "@smithy/config-resolver": "^2.0.11", + "@smithy/fetch-http-handler": "^2.2.1", + "@smithy/hash-node": "^2.0.10", + "@smithy/invalid-dependency": "^2.0.10", + "@smithy/middleware-content-length": "^2.0.12", + "@smithy/middleware-endpoint": "^2.0.10", + "@smithy/middleware-retry": "^2.0.13", + "@smithy/middleware-serde": "^2.0.10", + "@smithy/middleware-stack": "^2.0.4", + "@smithy/node-config-provider": "^2.0.13", + "@smithy/node-http-handler": "^2.1.6", + "@smithy/protocol-http": "^3.0.6", + "@smithy/smithy-client": "^2.1.9", + "@smithy/types": "^2.3.4", + "@smithy/url-parser": "^2.0.10", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.13", + "@smithy/util-defaults-mode-node": "^2.0.15", + "@smithy/util-retry": "^2.0.3", + "@smithy/util-utf8": "^2.0.0", + "@smithy/util-waiter": "^2.0.10", + "tslib": "^2.5.0", + "uuid": "^8.3.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-ssm/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/client-sso": { + "version": "3.427.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.427.0.tgz", + "integrity": "sha512-sFVFEmsQ1rmgYO1SgrOTxE/MTKpeE4hpOkm1WqhLQK7Ij136vXpjCxjH1JYZiHiUzO1wr9t4ex4dlB5J3VS/Xg==", + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/middleware-host-header": "3.425.0", + "@aws-sdk/middleware-logger": "3.425.0", + "@aws-sdk/middleware-recursion-detection": "3.425.0", + "@aws-sdk/middleware-user-agent": "3.427.0", + "@aws-sdk/region-config-resolver": "3.425.0", + "@aws-sdk/types": "3.425.0", + "@aws-sdk/util-endpoints": "3.427.0", + "@aws-sdk/util-user-agent-browser": "3.425.0", + "@aws-sdk/util-user-agent-node": "3.425.0", + "@smithy/config-resolver": "^2.0.11", + "@smithy/fetch-http-handler": "^2.2.1", + "@smithy/hash-node": "^2.0.10", + "@smithy/invalid-dependency": "^2.0.10", + "@smithy/middleware-content-length": "^2.0.12", + "@smithy/middleware-endpoint": "^2.0.10", + "@smithy/middleware-retry": "^2.0.13", + "@smithy/middleware-serde": "^2.0.10", + "@smithy/middleware-stack": "^2.0.4", + "@smithy/node-config-provider": "^2.0.13", + "@smithy/node-http-handler": "^2.1.6", + "@smithy/protocol-http": "^3.0.6", + "@smithy/smithy-client": "^2.1.9", + "@smithy/types": "^2.3.4", + "@smithy/url-parser": "^2.0.10", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.13", + "@smithy/util-defaults-mode-node": "^2.0.15", + "@smithy/util-retry": "^2.0.3", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-sso/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/client-sts": { + "version": "3.427.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.427.0.tgz", + "integrity": "sha512-le2wLJKILyWuRfPz2HbyaNtu5kEki+ojUkTqCU6FPDRrqUvEkaaCBH9Awo/2AtrCfRkiobop8RuTTj6cAnpiJg==", + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/credential-provider-node": "3.427.0", + "@aws-sdk/middleware-host-header": "3.425.0", + "@aws-sdk/middleware-logger": "3.425.0", + "@aws-sdk/middleware-recursion-detection": "3.425.0", + "@aws-sdk/middleware-sdk-sts": "3.425.0", + "@aws-sdk/middleware-signing": "3.425.0", + "@aws-sdk/middleware-user-agent": "3.427.0", + "@aws-sdk/region-config-resolver": "3.425.0", + "@aws-sdk/types": "3.425.0", + "@aws-sdk/util-endpoints": "3.427.0", + "@aws-sdk/util-user-agent-browser": "3.425.0", + "@aws-sdk/util-user-agent-node": "3.425.0", + "@smithy/config-resolver": "^2.0.11", + "@smithy/fetch-http-handler": "^2.2.1", + "@smithy/hash-node": "^2.0.10", + "@smithy/invalid-dependency": "^2.0.10", + "@smithy/middleware-content-length": "^2.0.12", + "@smithy/middleware-endpoint": "^2.0.10", + "@smithy/middleware-retry": "^2.0.13", + "@smithy/middleware-serde": "^2.0.10", + "@smithy/middleware-stack": "^2.0.4", + "@smithy/node-config-provider": "^2.0.13", + "@smithy/node-http-handler": "^2.1.6", + "@smithy/protocol-http": "^3.0.6", + "@smithy/smithy-client": "^2.1.9", + "@smithy/types": "^2.3.4", + "@smithy/url-parser": "^2.0.10", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.13", + "@smithy/util-defaults-mode-node": "^2.0.15", + "@smithy/util-retry": "^2.0.3", + "@smithy/util-utf8": "^2.0.0", + "fast-xml-parser": "4.2.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-sts/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/credential-provider-env": { + "version": "3.425.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.425.0.tgz", + "integrity": "sha512-J20etnLvMKXRVi5FK4F8yOCNm2RTaQn5psQTGdDEPWJNGxohcSpzzls8U2KcMyUJ+vItlrThr4qwgpHG3i/N0w==", + "dependencies": { + "@aws-sdk/types": "3.425.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/types": "^2.3.4", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-env/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.427.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.427.0.tgz", + "integrity": "sha512-NmH1cO/w98CKMltYec3IrJIIco19wRjATFNiw83c+FGXZ+InJwReqBnruxIOmKTx2KDzd6fwU1HOewS7UjaaaQ==", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.425.0", + "@aws-sdk/credential-provider-process": "3.425.0", + "@aws-sdk/credential-provider-sso": "3.427.0", + "@aws-sdk/credential-provider-web-identity": "3.425.0", + "@aws-sdk/types": "3.425.0", + "@smithy/credential-provider-imds": "^2.0.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/types": "^2.3.4", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-ini/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/credential-provider-node": { + "version": "3.427.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.427.0.tgz", + "integrity": "sha512-wYYbQ57nKL8OfgRbl8k6uXcdnYml+p3LSSfDUAuUEp1HKlQ8lOXFJ3BdLr5qrk7LhpyppSRnWBmh2c3kWa7ANQ==", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.425.0", + "@aws-sdk/credential-provider-ini": "3.427.0", + "@aws-sdk/credential-provider-process": "3.425.0", + "@aws-sdk/credential-provider-sso": "3.427.0", + "@aws-sdk/credential-provider-web-identity": "3.425.0", + "@aws-sdk/types": "3.425.0", + "@smithy/credential-provider-imds": "^2.0.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/types": "^2.3.4", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-node/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/credential-provider-process": { + "version": "3.425.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.425.0.tgz", + "integrity": "sha512-YY6tkLdvtb1Fgofp3b1UWO+5vwS14LJ/smGmuGpSba0V7gFJRdcrJ9bcb9vVgAGuMdjzRJ+bUKlLLtqXkaykEw==", "dependencies": { - "has-flag": "^3.0.0" + "@aws-sdk/types": "3.425.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/types": "^2.3.4", + "tslib": "^2.5.0" }, "engines": { - "node": ">=4" + "node": ">=14.0.0" } }, - "node_modules/@babel/compat-data": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.20.tgz", - "integrity": "sha512-BQYjKbpXjoXwFW5jGqiizJQQT/aC7pFm9Ok1OWssonuguICi264lbgMzRp2ZMmRSlfkX6DsWDDcsrctK8Rwfiw==", - "dev": true, + "node_modules/@aws-sdk/credential-provider-process/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.427.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.427.0.tgz", + "integrity": "sha512-c+tXyS/i49erHs4bAp6vKNYeYlyQ0VNMBgoco0LCn1rL0REtHbfhWMnqDLF6c2n3yIWDOTrQu0D73Idnpy16eA==", + "dependencies": { + "@aws-sdk/client-sso": "3.427.0", + "@aws-sdk/token-providers": "3.427.0", + "@aws-sdk/types": "3.425.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/types": "^2.3.4", + "tslib": "^2.5.0" + }, "engines": { - "node": ">=6.9.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/core": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.0.tgz", - "integrity": "sha512-97z/ju/Jy1rZmDxybphrBuI+jtJjFVoz7Mr9yUQVVVi+DNZE333uFQeMOqcCIy1x3WYBIbWftUSLmbNXNT7qFQ==", - "dev": true, + "node_modules/@aws-sdk/credential-provider-sso/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.425.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.425.0.tgz", + "integrity": "sha512-/0R65TgRzL01JU3SzloivWNwdkbIhr06uY/F5pBHf/DynQqaspKNfdHn6AiozgSVDfwRHFjKBTUy6wvf3QFkuA==", "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.0", - "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-module-transforms": "^7.23.0", - "@babel/helpers": "^7.23.0", - "@babel/parser": "^7.23.0", - "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.0", - "@babel/types": "^7.23.0", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" + "@aws-sdk/types": "3.425.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/types": "^2.3.4", + "tslib": "^2.5.0" }, "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" + "node": ">=14.0.0" } }, - "node_modules/@babel/core/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, - "bin": { - "semver": "bin/semver.js" - } + "node_modules/@aws-sdk/credential-provider-web-identity/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, - "node_modules/@babel/generator": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", - "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", - "dev": true, + "node_modules/@aws-sdk/middleware-bucket-endpoint": { + "version": "3.425.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.425.0.tgz", + "integrity": "sha512-7UTfA10fmDw9cgHLApxRUNPywZTG4S/1TNZgTxndO/1OM9ZHtIatw1iLbqJD35gHrpEYI8Vo14YvcnD2ITuiMw==", "dependencies": { - "@babel/types": "^7.23.0", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" + "@aws-sdk/types": "3.425.0", + "@aws-sdk/util-arn-parser": "3.310.0", + "@smithy/node-config-provider": "^2.0.13", + "@smithy/protocol-http": "^3.0.6", + "@smithy/types": "^2.3.4", + "@smithy/util-config-provider": "^2.0.0", + "tslib": "^2.5.0" }, "engines": { - "node": ">=6.9.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz", - "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==", - "dev": true, + "node_modules/@aws-sdk/middleware-bucket-endpoint/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/middleware-expect-continue": { + "version": "3.425.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.425.0.tgz", + "integrity": "sha512-CqAmnDST2o7+sKKw2/ffHKiYKE+jZb/Ce9U0P//ZYzqp9R1Wb016ID+W6DoxufyPJAS9dpRMcUDnAssmMIC/EA==", "dependencies": { - "@babel/compat-data": "^7.22.9", - "@babel/helper-validator-option": "^7.22.15", - "browserslist": "^4.21.9", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" + "@aws-sdk/types": "3.425.0", + "@smithy/protocol-http": "^3.0.6", + "@smithy/types": "^2.3.4", + "tslib": "^2.5.0" }, "engines": { - "node": ">=6.9.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/helper-compilation-targets/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, + "node_modules/@aws-sdk/middleware-expect-continue/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/middleware-flexible-checksums": { + "version": "3.425.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.425.0.tgz", + "integrity": "sha512-BDwn2vVVsC/AzmHXQlaZhEpKXL7GfKFpH7ZFccZuwEQBcyn8lVCcwtfaRe5P1mEe2wklVzOXd1dw8bt0+BOUPA==", "dependencies": { - "yallist": "^3.0.2" + "@aws-crypto/crc32": "3.0.0", + "@aws-crypto/crc32c": "3.0.0", + "@aws-sdk/types": "3.425.0", + "@smithy/is-array-buffer": "^2.0.0", + "@smithy/protocol-http": "^3.0.6", + "@smithy/types": "^2.3.4", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@babel/helper-compilation-targets/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, - "bin": { - "semver": "bin/semver.js" + "node_modules/@aws-sdk/middleware-flexible-checksums/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/middleware-host-header": { + "version": "3.425.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.425.0.tgz", + "integrity": "sha512-E5Gt41LObQ+cr8QnLthwsH3MtVSNXy1AKJMowDr85h0vzqA/FHUkgHyOGntgozzjXT5M0MaSRYxS0xwTR5D4Ew==", + "dependencies": { + "@aws-sdk/types": "3.425.0", + "@smithy/protocol-http": "^3.0.6", + "@smithy/types": "^2.3.4", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true + "node_modules/@aws-sdk/middleware-host-header/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", - "dev": true, + "node_modules/@aws-sdk/middleware-location-constraint": { + "version": "3.425.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.425.0.tgz", + "integrity": "sha512-3rt0LpGmL1LCRFuEObS1yERd9OEV+AEIAvhY7b53M7u7SyrjWQtpntWkI365L/QljhgMXQBfps2qO4JtrhQnsA==", + "dependencies": { + "@aws-sdk/types": "3.425.0", + "@smithy/types": "^2.3.4", + "tslib": "^2.5.0" + }, "engines": { - "node": ">=6.9.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/helper-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", - "dev": true, + "node_modules/@aws-sdk/middleware-location-constraint/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/middleware-logger": { + "version": "3.425.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.425.0.tgz", + "integrity": "sha512-INE9XWRXx2f4a/r2vOU0tAmgctVp7nEaEasemNtVBYhqbKLZvr9ndLBSgKGgJ8LIcXAoISipaMuFiqIGkFsm7A==", "dependencies": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" + "@aws-sdk/types": "3.425.0", + "@smithy/types": "^2.3.4", + "tslib": "^2.5.0" }, "engines": { - "node": ">=6.9.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", - "dev": true, + "node_modules/@aws-sdk/middleware-logger/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/middleware-recursion-detection": { + "version": "3.425.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.425.0.tgz", + "integrity": "sha512-77gnzJ5b91bgD75L/ugpOyerx6lR3oyS4080X1YI58EzdyBMkDrHM4FbMcY2RynETi3lwXCFzLRyZjWXY1mRlw==", "dependencies": { - "@babel/types": "^7.22.5" + "@aws-sdk/types": "3.425.0", + "@smithy/protocol-http": "^3.0.6", + "@smithy/types": "^2.3.4", + "tslib": "^2.5.0" }, "engines": { - "node": ">=6.9.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/helper-module-imports": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", - "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", - "dev": true, + "node_modules/@aws-sdk/middleware-recursion-detection/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/middleware-sdk-s3": { + "version": "3.427.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.427.0.tgz", + "integrity": "sha512-virGCf9vsqYCLpmngLOZOVSYgVr2cCOCvTuRoT9vf5tD/63JwaC173jnbdoJO6CWI7ID5Iz0eNdgITXVQ2mpew==", "dependencies": { - "@babel/types": "^7.22.15" + "@aws-sdk/types": "3.425.0", + "@aws-sdk/util-arn-parser": "3.310.0", + "@smithy/protocol-http": "^3.0.6", + "@smithy/smithy-client": "^2.1.9", + "@smithy/types": "^2.3.4", + "tslib": "^2.5.0" }, "engines": { - "node": ">=6.9.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz", - "integrity": "sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==", - "dev": true, + "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/middleware-sdk-sqs": { + "version": "3.425.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sqs/-/middleware-sdk-sqs-3.425.0.tgz", + "integrity": "sha512-c+8SQmxs9NMgaCea0o2RSsonYlDXbsYf7SODqiYKmPbHic7oa+rUmIWq7cLjxcMT8W2WKFkpvLHJZ8ex+BOHXQ==", "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-simple-access": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.20" + "@aws-sdk/types": "3.425.0", + "@smithy/types": "^2.3.4", + "@smithy/util-hex-encoding": "^2.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", - "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", - "dev": true, + "node_modules/@aws-sdk/middleware-sdk-sqs/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/middleware-sdk-sts": { + "version": "3.425.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.425.0.tgz", + "integrity": "sha512-JFojrg76oKAoBknnr9EL5N2aJ1mRCtBqXoZYST58GSx8uYdFQ89qS65VNQ8JviBXzsrCNAn4vDhZ5Ch5E6TxGQ==", + "dependencies": { + "@aws-sdk/middleware-signing": "3.425.0", + "@aws-sdk/types": "3.425.0", + "@smithy/types": "^2.3.4", + "tslib": "^2.5.0" + }, "engines": { - "node": ">=6.9.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/helper-simple-access": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", - "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", - "dev": true, + "node_modules/@aws-sdk/middleware-sdk-sts/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/middleware-signing": { + "version": "3.425.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.425.0.tgz", + "integrity": "sha512-ZpOfgJHk7ovQ0sSwg3tU4NxFOnz53lJlkJRf7S+wxQALHM0P2MJ6LYBrZaFMVsKiJxNIdZBXD6jclgHg72ZW6Q==", "dependencies": { - "@babel/types": "^7.22.5" + "@aws-sdk/types": "3.425.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/protocol-http": "^3.0.6", + "@smithy/signature-v4": "^2.0.0", + "@smithy/types": "^2.3.4", + "@smithy/util-middleware": "^2.0.3", + "tslib": "^2.5.0" }, "engines": { - "node": ">=6.9.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "dev": true, + "node_modules/@aws-sdk/middleware-signing/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/middleware-ssec": { + "version": "3.425.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.425.0.tgz", + "integrity": "sha512-9HTuXnHYAZWkwPC8x9tElsQjFPxDT//orbIFauS7VF5HkLCKn9J6O6lW1wKMxrEnDwfN/Vi3nw479MoPj5Ss0Q==", "dependencies": { - "@babel/types": "^7.22.5" + "@aws-sdk/types": "3.425.0", + "@smithy/types": "^2.3.4", + "tslib": "^2.5.0" }, "engines": { - "node": ">=6.9.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/helper-string-parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", - "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", - "dev": true, + "node_modules/@aws-sdk/middleware-ssec/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/middleware-user-agent": { + "version": "3.427.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.427.0.tgz", + "integrity": "sha512-y9HxYsNvnA3KqDl8w1jHeCwz4P9CuBEtu/G+KYffLeAMBsMZmh4SIkFFCO9wE/dyYg6+yo07rYcnnIfy7WA0bw==", + "dependencies": { + "@aws-sdk/types": "3.425.0", + "@aws-sdk/util-endpoints": "3.427.0", + "@smithy/protocol-http": "^3.0.6", + "@smithy/types": "^2.3.4", + "tslib": "^2.5.0" + }, "engines": { - "node": ">=6.9.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", - "dev": true, + "node_modules/@aws-sdk/middleware-user-agent/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/region-config-resolver": { + "version": "3.425.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.425.0.tgz", + "integrity": "sha512-u7uv/iUOapIJdRgRkO3wnpYsUgV6ponsZJQgVg/8L+n+Vo5PQL5gAcIuAOwcYSKQPFaeK+KbmByI4SyOK203Vw==", + "dependencies": { + "@smithy/node-config-provider": "^2.0.13", + "@smithy/types": "^2.3.4", + "@smithy/util-config-provider": "^2.0.0", + "@smithy/util-middleware": "^2.0.3", + "tslib": "^2.5.0" + }, "engines": { - "node": ">=6.9.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/helper-validator-option": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz", - "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } + "node_modules/@aws-sdk/region-config-resolver/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, - "node_modules/@babel/helpers": { - "version": "7.23.1", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.1.tgz", - "integrity": "sha512-chNpneuK18yW5Oxsr+t553UZzzAs3aZnFm4bxhebsNTeshrC95yA7l5yl7GBAG+JG1rF0F7zzD2EixK9mWSDoA==", - "dev": true, + "node_modules/@aws-sdk/signature-v4-multi-region": { + "version": "3.425.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.425.0.tgz", + "integrity": "sha512-7n2FRPE9rLaVa26xXQJ8TExrt53dWN824axQd1a0r5va0SmMQYG/iV5LBmwUlAntUSq46Lse4Q5YnbOVedGOmw==", "dependencies": { - "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.0", - "@babel/types": "^7.23.0" + "@aws-sdk/types": "3.425.0", + "@smithy/protocol-http": "^3.0.6", + "@smithy/signature-v4": "^2.0.0", + "@smithy/types": "^2.3.4", + "tslib": "^2.5.0" }, "engines": { - "node": ">=6.9.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/highlight": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", - "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", - "dev": true, + "node_modules/@aws-sdk/signature-v4-multi-region/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/token-providers": { + "version": "3.427.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.427.0.tgz", + "integrity": "sha512-4E5E+4p8lJ69PBY400dJXF06LUHYx5lkKzBEsYqWWhoZcoftrvi24ltIhUDoGVLkrLcTHZIWSdFAWSos4hXqeg==", "dependencies": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0" + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/middleware-host-header": "3.425.0", + "@aws-sdk/middleware-logger": "3.425.0", + "@aws-sdk/middleware-recursion-detection": "3.425.0", + "@aws-sdk/middleware-user-agent": "3.427.0", + "@aws-sdk/types": "3.425.0", + "@aws-sdk/util-endpoints": "3.427.0", + "@aws-sdk/util-user-agent-browser": "3.425.0", + "@aws-sdk/util-user-agent-node": "3.425.0", + "@smithy/config-resolver": "^2.0.11", + "@smithy/fetch-http-handler": "^2.2.1", + "@smithy/hash-node": "^2.0.10", + "@smithy/invalid-dependency": "^2.0.10", + "@smithy/middleware-content-length": "^2.0.12", + "@smithy/middleware-endpoint": "^2.0.10", + "@smithy/middleware-retry": "^2.0.13", + "@smithy/middleware-serde": "^2.0.10", + "@smithy/middleware-stack": "^2.0.4", + "@smithy/node-config-provider": "^2.0.13", + "@smithy/node-http-handler": "^2.1.6", + "@smithy/property-provider": "^2.0.0", + "@smithy/protocol-http": "^3.0.6", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/smithy-client": "^2.1.9", + "@smithy/types": "^2.3.4", + "@smithy/url-parser": "^2.0.10", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.13", + "@smithy/util-defaults-mode-node": "^2.0.15", + "@smithy/util-retry": "^2.0.3", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" }, "engines": { - "node": ">=6.9.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, + "node_modules/@aws-sdk/token-providers/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/types": { + "version": "3.425.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.425.0.tgz", + "integrity": "sha512-6lqbmorwerN4v+J5dqbHPAsjynI0mkEF+blf+69QTaKKGaxBBVaXgqoqul9RXYcK5MMrrYRbQIMd0zYOoy90kA==", "dependencies": { - "color-convert": "^1.9.0" + "@smithy/types": "^2.3.4", + "tslib": "^2.5.0" }, "engines": { - "node": ">=4" + "node": ">=14.0.0" } }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, + "node_modules/@aws-sdk/types/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/util-arn-parser": { + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.310.0.tgz", + "integrity": "sha512-jL8509owp/xB9+Or0pvn3Fe+b94qfklc2yPowZZIFAkFcCSIdkIglz18cPDWnYAcy9JGewpMS1COXKIUhZkJsA==", "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "tslib": "^2.5.0" }, "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" + "node": ">=14.0.0" } }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true + "node_modules/@aws-sdk/util-arn-parser/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, + "node_modules/@aws-sdk/util-endpoints": { + "version": "3.427.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.427.0.tgz", + "integrity": "sha512-rSyiAIFF/EVvity/+LWUqoTMJ0a25RAc9iqx0WZ4tf1UjuEXRRXxZEb+jEZg1bk+pY84gdLdx9z5E+MSJCZxNQ==", + "dependencies": { + "@aws-sdk/types": "3.425.0", + "@smithy/node-config-provider": "^2.0.13", + "tslib": "^2.5.0" + }, "engines": { - "node": ">=0.8.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } + "node_modules/@aws-sdk/util-endpoints/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, + "node_modules/@aws-sdk/util-locate-window": { + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.310.0.tgz", + "integrity": "sha512-qo2t/vBTnoXpjKxlsC2e1gBrRm80M3bId27r0BRB2VniSSe7bL1mmzM+/HFtujm0iAxtPM+aLEflLJlJeDPg0w==", "dependencies": { - "has-flag": "^3.0.0" + "tslib": "^2.5.0" }, "engines": { - "node": ">=4" + "node": ">=14.0.0" } }, - "node_modules/@babel/parser": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", - "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", - "dev": true, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } + "node_modules/@aws-sdk/util-locate-window/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, - "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, + "node_modules/@aws-sdk/util-user-agent-browser": { + "version": "3.425.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.425.0.tgz", + "integrity": "sha512-22Y9iMtjGcFjGILR6/xdp1qRezlHVLyXtnpEsbuPTiernRCPk6zfAnK/ATH77r02MUjU057tdxVkd5umUBTn9Q==", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@aws-sdk/types": "3.425.0", + "@smithy/types": "^2.3.4", + "bowser": "^2.11.0", + "tslib": "^2.5.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, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "node_modules/@aws-sdk/util-user-agent-browser/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, - "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, + "node_modules/@aws-sdk/util-user-agent-node": { + "version": "3.425.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.425.0.tgz", + "integrity": "sha512-SIR4F5uQeeVAi8lv4OgRirtdtNi5zeyogTuQgGi9su8F/WP1N6JqxofcwpUY5f8/oJ2UlXr/tx1f09UHfJJzvA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" + "@aws-sdk/types": "3.425.0", + "@smithy/node-config-provider": "^2.0.13", + "@smithy/types": "^2.3.4", + "tslib": "^2.5.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, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" + "engines": { + "node": ">=14.0.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "aws-crt": ">=1.0.0" + }, + "peerDependenciesMeta": { + "aws-crt": { + "optional": true + } } }, - "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, + "node_modules/@aws-sdk/util-user-agent-node/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/util-utf8-browser": { + "version": "3.259.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz", + "integrity": "sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "tslib": "^2.3.1" } }, - "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", - "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", - "dev": true, + "node_modules/@aws-sdk/util-utf8-browser/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/xml-builder": { + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.310.0.tgz", + "integrity": "sha512-TqELu4mOuSIKQCqj63fGVs86Yh+vBx5nHRpWKNUNhB2nPTpfbziTs5c1X358be3peVWA4wPxW7Nt53KIg1tnNw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "tslib": "^2.5.0" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=14.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, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "node_modules/@aws-sdk/xml-builder/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, - "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, + "node_modules/@aws-solutions-constructs/aws-lambda-sqs": { + "version": "2.44.0", + "resolved": "https://registry.npmjs.org/@aws-solutions-constructs/aws-lambda-sqs/-/aws-lambda-sqs-2.44.0.tgz", + "integrity": "sha512-HZdMz4CmmIVndbZnz8wbUk6g8r9yUfb5Liv9E9bSrS1YLtJ8htDJaOM4ZYK6uD7ia3HsagRiXjduOjeANYbFcQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@aws-solutions-constructs/core": "2.44.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@aws-solutions-constructs/core": "2.44.0", + "aws-cdk-lib": "^2.82.0", + "constructs": "^10.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, + "node_modules/@aws-solutions-constructs/aws-lambda-sqs-lambda": { + "version": "2.44.0", + "resolved": "https://registry.npmjs.org/@aws-solutions-constructs/aws-lambda-sqs-lambda/-/aws-lambda-sqs-lambda-2.44.0.tgz", + "integrity": "sha512-/mDRhu1c6VMU5OMQZetwCQ9GTDIZud0x+5oDcCg1UFgDrqn+9Jo0DPFrwk6IHpovkL+mRtqrXH0kmk8qZV4nqA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" + "@aws-solutions-constructs/aws-lambda-sqs": "2.44.0", + "@aws-solutions-constructs/aws-sqs-lambda": "2.44.0", + "@aws-solutions-constructs/core": "2.44.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@aws-solutions-constructs/aws-lambda-sqs": "2.44.0", + "@aws-solutions-constructs/aws-sqs-lambda": "2.44.0", + "@aws-solutions-constructs/core": "2.44.0", + "aws-cdk-lib": "^2.82.0", + "constructs": "^10.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, + "node_modules/@aws-solutions-constructs/aws-sqs-lambda": { + "version": "2.44.0", + "resolved": "https://registry.npmjs.org/@aws-solutions-constructs/aws-sqs-lambda/-/aws-sqs-lambda-2.44.0.tgz", + "integrity": "sha512-kyNj6+70STsXcjPcMmsu8VMWMtUnk8g7f3n3UfISje8/tchFwMoQ0v+KD8IoWXZmYb7EXKxt+06iz2OihMwC8g==", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@aws-solutions-constructs/core": "2.44.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@aws-solutions-constructs/core": "2.44.0", + "aws-cdk-lib": "^2.82.0", + "constructs": "^10.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, + "node_modules/@aws-solutions-constructs/core": { + "version": "2.44.0", + "resolved": "https://registry.npmjs.org/@aws-solutions-constructs/core/-/core-2.44.0.tgz", + "integrity": "sha512-mNXi/msdPzV+Y3msnrkKadJKUc3ZSHbQjCxud95elmu/s9H7q38wZxzL+Tp7bhgDaZFMLzb9Qcm56DGldXll5w==", + "bundleDependencies": [ + "deepmerge", + "npmlog", + "deep-diff" + ], "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "deep-diff": "^1.0.2", + "deepmerge": "^4.0.0", + "npmlog": "^4.1.2" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "aws-cdk-lib": "^2.82.0", + "constructs": "^10.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, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node_modules/@aws-solutions-constructs/core/node_modules/ansi-regex": { + "version": "2.1.1", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=0.10.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, + "node_modules/@aws-solutions-constructs/core/node_modules/aproba": { + "version": "1.2.0", + "inBundle": true, + "license": "ISC" + }, + "node_modules/@aws-solutions-constructs/core/node_modules/are-we-there-yet": { + "version": "1.1.7", + "inBundle": true, + "license": "ISC", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" } }, - "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz", - "integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" - }, + "node_modules/@aws-solutions-constructs/core/node_modules/code-point-at": { + "version": "1.1.0", + "inBundle": true, + "license": "MIT", "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=0.10.0" } }, - "node_modules/@babel/template": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", - "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", - "dev": true, + "node_modules/@aws-solutions-constructs/core/node_modules/console-control-strings": { + "version": "1.1.0", + "inBundle": true, + "license": "ISC" + }, + "node_modules/@aws-solutions-constructs/core/node_modules/core-util-is": { + "version": "1.0.3", + "inBundle": true, + "license": "MIT" + }, + "node_modules/@aws-solutions-constructs/core/node_modules/deep-diff": { + "version": "1.0.2", + "inBundle": true, + "license": "MIT" + }, + "node_modules/@aws-solutions-constructs/core/node_modules/deepmerge": { + "version": "4.3.1", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@aws-solutions-constructs/core/node_modules/delegates": { + "version": "1.0.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/@aws-solutions-constructs/core/node_modules/emoji-regex": { + "version": "8.0.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/@aws-solutions-constructs/core/node_modules/gauge": { + "version": "2.7.4", + "inBundle": true, + "license": "ISC", "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" + "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", + "inBundle": true, + "license": "ISC" + }, + "node_modules/@aws-solutions-constructs/core/node_modules/inherits": { + "version": "2.0.4", + "inBundle": true, + "license": "ISC" + }, + "node_modules/@aws-solutions-constructs/core/node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "number-is-nan": "^1.0.0" }, "engines": { - "node": ">=6.9.0" + "node": ">=0.10.0" } }, - "node_modules/@babel/traverse": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.0.tgz", - "integrity": "sha512-t/QaEvyIoIkwzpiZ7aoSKK8kObQYeF7T2v+dazAYCb8SXtp58zEVkWW7zAnju8FNKNdr4ScAOEDmMItbyOmEYw==", - "dev": true, + "node_modules/@aws-solutions-constructs/core/node_modules/isarray": { + "version": "1.0.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/@aws-solutions-constructs/core/node_modules/npmlog": { + "version": "4.1.2", + "inBundle": true, + "license": "ISC", "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.0", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.0", - "@babel/types": "^7.23.0", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, + "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", + "inBundle": true, + "license": "MIT", "engines": { - "node": ">=6.9.0" + "node": ">=0.10.0" } }, - "node_modules/@babel/traverse/node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, + "node_modules/@aws-solutions-constructs/core/node_modules/object-assign": { + "version": "4.1.1", + "inBundle": true, + "license": "MIT", "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/@babel/types": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", - "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", - "dev": true, + "node_modules/@aws-solutions-constructs/core/node_modules/process-nextick-args": { + "version": "2.0.1", + "inBundle": true, + "license": "MIT" + }, + "node_modules/@aws-solutions-constructs/core/node_modules/readable-stream": { + "version": "2.3.8", + "inBundle": true, + "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" + "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", + "inBundle": true, + "license": "MIT" + }, + "node_modules/@aws-solutions-constructs/core/node_modules/set-blocking": { + "version": "2.0.0", + "inBundle": true, + "license": "ISC" + }, + "node_modules/@aws-solutions-constructs/core/node_modules/signal-exit": { + "version": "3.0.7", + "inBundle": true, + "license": "ISC" + }, + "node_modules/@aws-solutions-constructs/core/node_modules/string_decoder": { + "version": "1.1.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/@aws-solutions-constructs/core/node_modules/string-width": { + "version": "1.0.2", + "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": ">=6.9.0" + "node": ">=0.10.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 - }, - "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, + "node_modules/@aws-solutions-constructs/core/node_modules/strip-ansi": { + "version": "3.0.1", + "inBundle": true, + "license": "MIT", "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" + "ansi-regex": "^2.0.0" }, "engines": { - "node": ">=12" + "node": ">=0.10.0" } }, - "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, + "node_modules/@aws-solutions-constructs/core/node_modules/util-deprecate": { + "version": "1.0.2", + "inBundle": true, + "license": "MIT" + }, + "node_modules/@aws-solutions-constructs/core/node_modules/wide-align": { + "version": "1.1.5", + "inBundle": true, + "license": "ISC", "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" + "string-width": "^1.0.2 || 2 || 3 || 4" } }, - "node_modules/@esbuild/android-arm": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.19.tgz", - "integrity": "sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "android" - ], + "node_modules/@aws-solutions-constructs/core/node_modules/wide-align/node_modules/ansi-regex": { + "version": "5.0.1", + "inBundle": true, + "license": "MIT", "engines": { - "node": ">=12" + "node": ">=8" } }, - "node_modules/@esbuild/android-arm64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.19.tgz", - "integrity": "sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "android" - ], + "node_modules/@aws-solutions-constructs/core/node_modules/wide-align/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "inBundle": true, + "license": "MIT", "engines": { - "node": ">=12" + "node": ">=8" } }, - "node_modules/@esbuild/android-x64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.19.tgz", - "integrity": "sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "android" - ], + "node_modules/@aws-solutions-constructs/core/node_modules/wide-align/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": ">=12" + "node": ">=8" } }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.19.tgz", - "integrity": "sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "darwin" - ], + "node_modules/@aws-solutions-constructs/core/node_modules/wide-align/node_modules/strip-ansi": { + "version": "6.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, "engines": { - "node": ">=12" + "node": ">=8" } }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.19.tgz", - "integrity": "sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ], + "node_modules/@babel/code-frame": { + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" + }, "engines": { - "node": ">=12" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.19.tgz", - "integrity": "sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==", - "cpu": [ + "node_modules/@babel/code-frame/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/code-frame/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/code-frame/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.20.tgz", + "integrity": "sha512-BQYjKbpXjoXwFW5jGqiizJQQT/aC7pFm9Ok1OWssonuguICi264lbgMzRp2ZMmRSlfkX6DsWDDcsrctK8Rwfiw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.0.tgz", + "integrity": "sha512-97z/ju/Jy1rZmDxybphrBuI+jtJjFVoz7Mr9yUQVVVi+DNZE333uFQeMOqcCIy1x3WYBIbWftUSLmbNXNT7qFQ==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helpers": "^7.23.0", + "@babel/parser": "^7.23.0", + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.0", + "@babel/types": "^7.23.0", + "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/core/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, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", + "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.23.0", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz", + "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.22.9", + "@babel/helper-validator-option": "^7.22.15", + "browserslist": "^4.21.9", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/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, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/@babel/helper-compilation-targets/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, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "dev": true, + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz", + "integrity": "sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz", + "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.23.1", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.1.tgz", + "integrity": "sha512-chNpneuK18yW5Oxsr+t553UZzzAs3aZnFm4bxhebsNTeshrC95yA7l5yl7GBAG+JG1rF0F7zzD2EixK9mWSDoA==", + "dev": true, + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.0", + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", + "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", + "dev": true, + "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, + "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, + "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, + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "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, + "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, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", + "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "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, + "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, + "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, + "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, + "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, + "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, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.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, + "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.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz", + "integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.0.tgz", + "integrity": "sha512-t/QaEvyIoIkwzpiZ7aoSKK8kObQYeF7T2v+dazAYCb8SXtp58zEVkWW7zAnju8FNKNdr4ScAOEDmMItbyOmEYw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/types": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", + "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + }, + "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 + }, + "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, + "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, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.19.tgz", + "integrity": "sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.19.tgz", + "integrity": "sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==", + "cpu": [ "arm64" ], "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.19.tgz", + "integrity": "sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.19.tgz", + "integrity": "sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.19.tgz", + "integrity": "sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.19.tgz", + "integrity": "sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.19.tgz", + "integrity": "sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==", + "cpu": [ + "x64" + ], + "optional": true, "os": [ "freebsd" ], "engines": { - "node": ">=12" + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.19.tgz", + "integrity": "sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.19.tgz", + "integrity": "sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.19.tgz", + "integrity": "sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.19.tgz", + "integrity": "sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==", + "cpu": [ + "loong64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.19.tgz", + "integrity": "sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==", + "cpu": [ + "mips64el" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.19.tgz", + "integrity": "sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.19.tgz", + "integrity": "sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.19.tgz", + "integrity": "sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.19.tgz", + "integrity": "sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.19.tgz", + "integrity": "sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.19.tgz", + "integrity": "sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.19.tgz", + "integrity": "sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.19.tgz", + "integrity": "sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.19.tgz", + "integrity": "sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.19.tgz", + "integrity": "sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.8.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.8.2.tgz", + "integrity": "sha512-0MGxAVt1m/ZK+LTJp/j0qF7Hz97D9O/FH9Ms3ltnyIdDD57cbb1ACIQTkbHvNXtWDv5TPq7w5Kq56+cNukbo7g==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", + "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "8.50.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.50.0.tgz", + "integrity": "sha512-NCC3zz2+nvYd+Ckfh87rA47zfu2QsQpvc6k1yzTk+b9KzRj0wkGa8LSoGOXN6Zv4lRf/EIoZ80biDh9HOI+RNQ==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.11", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz", + "integrity": "sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "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, + "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/load-nyc-config/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, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@istanbuljs/load-nyc-config/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, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@istanbuljs/load-nyc-config/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, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/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, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@istanbuljs/load-nyc-config/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, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/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, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "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, + "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, + "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, + "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/@esbuild/freebsd-x64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.19.tgz", - "integrity": "sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "freebsd" - ], + "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, + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, "engines": { - "node": ">=12" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@esbuild/linux-arm": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.19.tgz", - "integrity": "sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "linux" - ], + "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, + "dependencies": { + "jest-get-type": "^29.6.3" + }, "engines": { - "node": ">=12" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.19.tgz", - "integrity": "sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], + "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, + "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": ">=12" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.19.tgz", - "integrity": "sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "linux" - ], + "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, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, "engines": { - "node": ">=12" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.19.tgz", - "integrity": "sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==", - "cpu": [ - "loong64" - ], - "optional": true, - "os": [ - "linux" - ], + "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, + "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, + "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, + "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, + "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, + "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, + "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, + "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.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, "engines": { - "node": ">=12" + "node": ">=6.0.0" } }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.19.tgz", - "integrity": "sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==", - "cpu": [ - "mips64el" - ], - "optional": true, - "os": [ - "linux" - ], + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "dev": true, "engines": { - "node": ">=12" + "node": ">=6.0.0" } }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.19.tgz", - "integrity": "sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==", - "cpu": [ - "ppc64" - ], - "optional": true, - "os": [ - "linux" - ], + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true, "engines": { - "node": ">=12" + "node": ">=6.0.0" } }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.19.tgz", - "integrity": "sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==", - "cpu": [ - "riscv64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", + "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.19.tgz", - "integrity": "sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==", - "cpu": [ - "s390x" - ], - "optional": true, - "os": [ - "linux" - ], + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, "engines": { - "node": ">=12" + "node": ">= 8" } }, - "node_modules/@esbuild/linux-x64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.19.tgz", - "integrity": "sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, "engines": { - "node": ">=12" + "node": ">= 8" } }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.19.tgz", - "integrity": "sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "netbsd" - ], + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, "engines": { - "node": ">=12" + "node": ">= 8" } }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.19.tgz", - "integrity": "sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", + "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" } }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.19.tgz", - "integrity": "sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" + "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, + "dependencies": { + "@sinonjs/commons": "^3.0.0" } }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.19.tgz", - "integrity": "sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "win32" - ], + "node_modules/@smithy/abort-controller": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-2.0.11.tgz", + "integrity": "sha512-MSzE1qR2JNyb7ot3blIOT3O3H0Jn06iNDEgHRaqZUwBgx5EG+VIx24Y21tlKofzYryIOcWpIohLrIIyocD6LMA==", + "dependencies": { + "@smithy/types": "^2.3.5", + "tslib": "^2.5.0" + }, "engines": { - "node": ">=12" + "node": ">=14.0.0" } }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.19.tgz", - "integrity": "sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" + "node_modules/@smithy/abort-controller/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/chunked-blob-reader": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader/-/chunked-blob-reader-2.0.0.tgz", + "integrity": "sha512-k+J4GHJsMSAIQPChGBrjEmGS+WbPonCXesoqP9fynIqjn7rdOThdH8FAeCmokP9mxTYKQAKoHCLPzNlm6gh7Wg==", + "dependencies": { + "tslib": "^2.5.0" } }, - "node_modules/@esbuild/win32-x64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.19.tgz", - "integrity": "sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" + "node_modules/@smithy/chunked-blob-reader-native": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-2.0.0.tgz", + "integrity": "sha512-HM8V2Rp1y8+1343tkZUKZllFhEQPNmpNdgFAncbTsxkZ18/gqjk23XXv3qGyXWp412f3o43ZZ1UZHVcHrpRnCQ==", + "dependencies": { + "@smithy/util-base64": "^2.0.0", + "tslib": "^2.5.0" } }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, + "node_modules/@smithy/chunked-blob-reader-native/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/chunked-blob-reader/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/config-resolver": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-2.0.14.tgz", + "integrity": "sha512-K1K+FuWQoy8j/G7lAmK85o03O89s2Vvh6kMFmzEmiHUoQCRH1rzbDtMnGNiaMHeSeYJ6y79IyTusdRG+LuWwtg==", "dependencies": { - "eslint-visitor-keys": "^3.3.0" + "@smithy/node-config-provider": "^2.1.1", + "@smithy/types": "^2.3.5", + "@smithy/util-config-provider": "^2.0.0", + "@smithy/util-middleware": "^2.0.4", + "tslib": "^2.5.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + "node": ">=14.0.0" } }, - "node_modules/@eslint-community/regexpp": { - "version": "4.8.2", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.8.2.tgz", - "integrity": "sha512-0MGxAVt1m/ZK+LTJp/j0qF7Hz97D9O/FH9Ms3ltnyIdDD57cbb1ACIQTkbHvNXtWDv5TPq7w5Kq56+cNukbo7g==", - "dev": true, + "node_modules/@smithy/config-resolver/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/credential-provider-imds": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-2.0.16.tgz", + "integrity": "sha512-tKa2xF+69TvGxJT+lnJpGrKxUuAZDLYXFhqnPEgnHz+psTpkpcB4QRjHj63+uj83KaeFJdTfW201eLZeRn6FfA==", + "dependencies": { + "@smithy/node-config-provider": "^2.1.1", + "@smithy/property-provider": "^2.0.12", + "@smithy/types": "^2.3.5", + "@smithy/url-parser": "^2.0.11", + "tslib": "^2.5.0" + }, "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + "node": ">=14.0.0" } }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", - "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", - "dev": true, + "node_modules/@smithy/credential-provider-imds/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/eventstream-codec": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-2.0.11.tgz", + "integrity": "sha512-BQCTjxhCYRZIfXapa2LmZSaH8QUBGwMZw7XRN83hrdixbLjIcj+o549zjkedFS07Ve2TlvWUI6BTzP+nv7snBA==", "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" + "@aws-crypto/crc32": "3.0.0", + "@smithy/types": "^2.3.5", + "@smithy/util-hex-encoding": "^2.0.0", + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/eventstream-codec/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/eventstream-serde-browser": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-2.0.11.tgz", + "integrity": "sha512-p9IK4uvwT6B3pT1VGlODvcVBfPVikjBFHAcKpvvNF+7lAEI+YiC6d0SROPkpjnvCgVBYyGXa3ciqrWnFze6mwQ==", + "dependencies": { + "@smithy/eventstream-serde-universal": "^2.0.11", + "@smithy/types": "^2.3.5", + "tslib": "^2.5.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=14.0.0" } }, - "node_modules/@eslint/js": { - "version": "8.50.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.50.0.tgz", - "integrity": "sha512-NCC3zz2+nvYd+Ckfh87rA47zfu2QsQpvc6k1yzTk+b9KzRj0wkGa8LSoGOXN6Zv4lRf/EIoZ80biDh9HOI+RNQ==", - "dev": true, + "node_modules/@smithy/eventstream-serde-browser/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/eventstream-serde-config-resolver": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-2.0.11.tgz", + "integrity": "sha512-vN32E8yExo0Z8L7kXhlU9KRURrhqOpPdLxQMp3MwfMThrjiqbr1Sk5srUXc1ed2Ygl/l0TEN9vwNG0bQHg6AjQ==", + "dependencies": { + "@smithy/types": "^2.3.5", + "tslib": "^2.5.0" + }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=14.0.0" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.11", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz", - "integrity": "sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==", - "dev": true, + "node_modules/@smithy/eventstream-serde-config-resolver/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/eventstream-serde-node": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-2.0.11.tgz", + "integrity": "sha512-Gjqbpg7UmD+YzkpgNShNcDNZcUpBWIkvX2XCGptz5PoxJU/UQbuF9eSc93ZlIb7j4aGjtFfqk23HUMW8Hopg2Q==", "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.5" + "@smithy/eventstream-serde-universal": "^2.0.11", + "@smithy/types": "^2.3.5", + "tslib": "^2.5.0" }, "engines": { - "node": ">=10.10.0" + "node": ">=14.0.0" } }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, + "node_modules/@smithy/eventstream-serde-node/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/eventstream-serde-universal": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-2.0.11.tgz", + "integrity": "sha512-F8FsxLTbFN4+Esgpo+nNKcEajrgRZJ+pG9c8+MhLM4Odp5ejLHw2GMCXd81cGsgmfcbnzdDEXazPPVzOwj89MQ==", + "dependencies": { + "@smithy/eventstream-codec": "^2.0.11", + "@smithy/types": "^2.3.5", + "tslib": "^2.5.0" + }, "engines": { - "node": ">=12.22" + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-universal/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/fetch-http-handler": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-2.2.3.tgz", + "integrity": "sha512-0G9sePU+0R+8d7cie+OXzNbbkjnD4RfBlVCs46ZEuQAMcxK8OniemYXSSkOc80CCk8Il4DnlYZcUSvsIs2OB2w==", + "dependencies": { + "@smithy/protocol-http": "^3.0.7", + "@smithy/querystring-builder": "^2.0.11", + "@smithy/types": "^2.3.5", + "@smithy/util-base64": "^2.0.0", + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/fetch-http-handler/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/hash-blob-browser": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-2.0.11.tgz", + "integrity": "sha512-/6vq/NiH2EN3mWdwcLdjVohP+VCng+ZA1GnlUdx959egsfgIlLWQvCyjnB2ze9Hr6VHV5XEFLLpLQH2dHA6Sgw==", + "dependencies": { + "@smithy/chunked-blob-reader": "^2.0.0", + "@smithy/chunked-blob-reader-native": "^2.0.0", + "@smithy/types": "^2.3.5", + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/hash-blob-browser/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/hash-node": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-2.0.11.tgz", + "integrity": "sha512-PbleVugN2tbhl1ZoNWVrZ1oTFFas/Hq+s6zGO8B9bv4w/StTriTKA9W+xZJACOj9X7zwfoTLbscM+avCB1KqOQ==", + "dependencies": { + "@smithy/types": "^2.3.5", + "@smithy/util-buffer-from": "^2.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true + "node_modules/@smithy/hash-node/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, - "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, + "node_modules/@smithy/hash-stream-node": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-2.0.11.tgz", + "integrity": "sha512-Jn2yl+Dn0kvwKvSavvR1/BFVYa2wIkaJKWeTH48kno89gqHAJxMh1hrtBN6SJ7F8VhodNZTiNOlQVqCSfLheNQ==", "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" + "@smithy/types": "^2.3.5", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" }, "engines": { - "node": ">=8" + "node": ">=14.0.0" } }, - "node_modules/@istanbuljs/load-nyc-config/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, + "node_modules/@smithy/hash-stream-node/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/invalid-dependency": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-2.0.11.tgz", + "integrity": "sha512-zazq99ujxYv/NOf9zh7xXbNgzoVLsqE0wle8P/1zU/XdhPi/0zohTPKWUzIxjGdqb5hkkwfBkNkl5H+LE0mvgw==", "dependencies": { - "sprintf-js": "~1.0.2" + "@smithy/types": "^2.3.5", + "tslib": "^2.5.0" } }, - "node_modules/@istanbuljs/load-nyc-config/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, + "node_modules/@smithy/invalid-dependency/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/is-array-buffer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.0.0.tgz", + "integrity": "sha512-z3PjFjMyZNI98JFRJi/U0nGoLWMSJlDjAW4QUX2WNZLas5C0CmVV6LJ01JI0k90l7FvpmixjWxPFmENSClQ7ug==", "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "tslib": "^2.5.0" }, "engines": { - "node": ">=8" + "node": ">=14.0.0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, + "node_modules/@smithy/is-array-buffer/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/md5-js": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-2.0.11.tgz", + "integrity": "sha512-YBIv+e95qeGvQA05ucwstmTeQ/bUzWgU+nO2Ffmif5awu6IzSR0Jfk3XLYh4mdy7f8DCgsn8qA63u7N9Lu0+5A==", "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "@smithy/types": "^2.3.5", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" } }, - "node_modules/@istanbuljs/load-nyc-config/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, + "node_modules/@smithy/md5-js/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/middleware-content-length": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-2.0.13.tgz", + "integrity": "sha512-Md2kxWpaec3bXp1oERFPQPBhOXCkGSAF7uc1E+4rkwjgw3/tqAXRtbjbggu67HJdwaif76As8AV6XxbD1HzqTQ==", "dependencies": { - "p-locate": "^4.1.0" + "@smithy/protocol-http": "^3.0.7", + "@smithy/types": "^2.3.5", + "tslib": "^2.5.0" }, "engines": { - "node": ">=8" + "node": ">=14.0.0" } }, - "node_modules/@istanbuljs/load-nyc-config/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, + "node_modules/@smithy/middleware-content-length/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/middleware-endpoint": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-2.1.0.tgz", + "integrity": "sha512-e6HZbfrp9CNTJqIPSgkydB9mNQXiq5pkHF3ZB6rOzPPR9PkJBoGFo9TcM7FaaKFUaH4Kc20AX6WwwVyIlNhXTA==", "dependencies": { - "p-try": "^2.0.0" + "@smithy/middleware-serde": "^2.0.11", + "@smithy/node-config-provider": "^2.1.1", + "@smithy/types": "^2.3.5", + "@smithy/url-parser": "^2.0.11", + "@smithy/util-middleware": "^2.0.4", + "tslib": "^2.5.0" }, "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=14.0.0" } }, - "node_modules/@istanbuljs/load-nyc-config/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, + "node_modules/@smithy/middleware-endpoint/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/middleware-retry": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-2.0.16.tgz", + "integrity": "sha512-Br5+0yoiMS0ugiOAfJxregzMMGIRCbX4PYo1kDHtLgvkA/d++aHbnHB819m5zOIAMPvPE7AThZgcsoK+WOsUTA==", "dependencies": { - "p-limit": "^2.2.0" + "@smithy/node-config-provider": "^2.1.1", + "@smithy/protocol-http": "^3.0.7", + "@smithy/service-error-classification": "^2.0.4", + "@smithy/types": "^2.3.5", + "@smithy/util-middleware": "^2.0.4", + "@smithy/util-retry": "^2.0.4", + "tslib": "^2.5.0", + "uuid": "^8.3.2" }, "engines": { - "node": ">=8" + "node": ">=14.0.0" } }, - "node_modules/@istanbuljs/load-nyc-config/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, + "node_modules/@smithy/middleware-retry/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/middleware-serde": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-2.0.11.tgz", + "integrity": "sha512-NuxnjMyf4zQqhwwdh0OTj5RqpnuT6HcH5Xg5GrPijPcKzc2REXVEVK4Yyk8ckj8ez1XSj/bCmJ+oNjmqB02GWA==", + "dependencies": { + "@smithy/types": "^2.3.5", + "tslib": "^2.5.0" + }, "engines": { - "node": ">=8" + "node": ">=14.0.0" } }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true, + "node_modules/@smithy/middleware-serde/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/middleware-stack": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-2.0.5.tgz", + "integrity": "sha512-bVQU/rZzBY7CbSxIrDTGZYnBWKtIw+PL/cRc9B7etZk1IKSOe0NvKMJyWllfhfhrTeMF6eleCzOihIQympAvPw==", + "dependencies": { + "@smithy/types": "^2.3.5", + "tslib": "^2.5.0" + }, "engines": { - "node": ">=8" + "node": ">=14.0.0" } }, - "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, + "node_modules/@smithy/middleware-stack/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/node-config-provider": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-2.1.1.tgz", + "integrity": "sha512-1lF6s1YWBi1LBu2O30tD3jyTgMtuvk/Z1twzXM4GPYe4dmZix4nNREPJIPOcfFikNU2o0eTYP80+izx5F2jIJA==", "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" + "@smithy/property-provider": "^2.0.12", + "@smithy/shared-ini-file-loader": "^2.2.0", + "@smithy/types": "^2.3.5", + "tslib": "^2.5.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=14.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, + "node_modules/@smithy/node-config-provider/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/node-http-handler": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-2.1.7.tgz", + "integrity": "sha512-PQIKZXlp3awCDn/xNlCSTFE7aYG/5Tx33M05NfQmWYeB5yV1GZZOSz4dXpwiNJYTXb9jPqjl+ueXXkwtEluFFA==", "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" + "@smithy/abort-controller": "^2.0.11", + "@smithy/protocol-http": "^3.0.7", + "@smithy/querystring-builder": "^2.0.11", + "@smithy/types": "^2.3.5", + "tslib": "^2.5.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": ">=14.0.0" } }, - "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, + "node_modules/@smithy/node-http-handler/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/property-provider": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-2.0.12.tgz", + "integrity": "sha512-Un/OvvuQ1Kg8WYtoMCicfsFFuHb/TKL3pCA6ZIo/WvNTJTR94RtoRnL7mY4XkkUAoFMyf6KjcQJ76y1FX7S5rw==", "dependencies": { - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0" + "@smithy/types": "^2.3.5", + "tslib": "^2.5.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=14.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, + "node_modules/@smithy/property-provider/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/protocol-http": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-3.0.7.tgz", + "integrity": "sha512-HnZW8y+r66ntYueCDbLqKwWcMNWW8o3eVpSrHNluwtBJ/EUWfQHRKSiu6vZZtc6PGfPQWgVfucoCE/C3QufMAA==", "dependencies": { - "expect": "^29.7.0", - "jest-snapshot": "^29.7.0" + "@smithy/types": "^2.3.5", + "tslib": "^2.5.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=14.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, + "node_modules/@smithy/protocol-http/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/querystring-builder": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-2.0.11.tgz", + "integrity": "sha512-b4kEbVMxpmfv2VWUITn2otckTi7GlMteZQxi+jlwedoATOGEyrCJPfRcYQJjbCi3fZ2QTfh3PcORvB27+j38Yg==", "dependencies": { - "jest-get-type": "^29.6.3" + "@smithy/types": "^2.3.5", + "@smithy/util-uri-escape": "^2.0.0", + "tslib": "^2.5.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=14.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, + "node_modules/@smithy/querystring-builder/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/querystring-parser": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-2.0.11.tgz", + "integrity": "sha512-YXe7jhi7s3dQ0Fu9dLoY/gLu6NCyy8tBWJL/v2c9i7/RLpHgKT+uT96/OqZkHizCJ4kr0ZD46tzMjql/o60KLg==", "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" + "@smithy/types": "^2.3.5", + "tslib": "^2.5.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=14.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, - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/types": "^29.6.3", - "jest-mock": "^29.7.0" + "node_modules/@smithy/querystring-parser/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/service-error-classification": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-2.0.4.tgz", + "integrity": "sha512-77506l12I5gxTZqBkx3Wb0RqMG81bMYLaVQ+EqIWFwQDJRs5UFeXogKxSKojCmz1wLUziHZQXm03MBzPQiumQw==", + "dependencies": { + "@smithy/types": "^2.3.5" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=14.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, + "node_modules/@smithy/shared-ini-file-loader": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-2.2.0.tgz", + "integrity": "sha512-xFXqs4vAb5BdkzHSRrTapFoaqS4/3m/CGZzdw46fBjYZ0paYuLAoMY60ICCn1FfGirG+PiJ3eWcqJNe4/SkfyA==", "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" + "@smithy/types": "^2.3.5", + "tslib": "^2.5.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/shared-ini-file-loader/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/signature-v4": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-2.0.11.tgz", + "integrity": "sha512-EFVU1dT+2s8xi227l1A9O27edT/GNKvyAK6lZnIZ0zhIHq/jSLznvkk15aonGAM1kmhmZBVGpI7Tt0odueZK9A==", + "dependencies": { + "@smithy/eventstream-codec": "^2.0.11", + "@smithy/is-array-buffer": "^2.0.0", + "@smithy/types": "^2.3.5", + "@smithy/util-hex-encoding": "^2.0.0", + "@smithy/util-middleware": "^2.0.4", + "@smithy/util-uri-escape": "^2.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "engines": { + "node": ">=14.0.0" } }, - "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, + "node_modules/@smithy/signature-v4/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/smithy-client": { + "version": "2.1.11", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-2.1.11.tgz", + "integrity": "sha512-okjMbuBBCTiieK665OFN/ap6u9+Z9z55PMphS5FYCsS6Zfp137Q3qlnt0OgBAnUVnH/mNGyoJV0LBX9gkTWptg==", "dependencies": { - "@sinclair/typebox": "^0.27.8" + "@smithy/middleware-stack": "^2.0.5", + "@smithy/types": "^2.3.5", + "@smithy/util-stream": "^2.0.16", + "tslib": "^2.5.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=14.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, + "node_modules/@smithy/smithy-client/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/types": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.3.5.tgz", + "integrity": "sha512-ehyDt8M9hehyxrLQGoA1BGPou8Js1Ocoh5M0ngDhJMqbFmNK5N6Xhr9/ZExWkyIW8XcGkiMPq3ZUEE0ScrhbuQ==", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.18", - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9" + "tslib": "^2.5.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=14.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, + "node_modules/@smithy/types/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/url-parser": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-2.0.11.tgz", + "integrity": "sha512-h89yXMCCF+S5k9XIoKltMIWTYj+FcEkU/IIFZ6RtE222fskOTL4Iak6ZRG+ehSvZDt8yKEcxqheTDq7JvvtK3g==", "dependencies": { - "@jest/console": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" + "@smithy/querystring-parser": "^2.0.11", + "@smithy/types": "^2.3.5", + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/url-parser/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/util-base64": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-2.0.0.tgz", + "integrity": "sha512-Zb1E4xx+m5Lud8bbeYi5FkcMJMnn+1WUnJF3qD7rAdXpaL7UjkFQLdmW5fHadoKbdHpwH9vSR8EyTJFHJs++tA==", + "dependencies": { + "@smithy/util-buffer-from": "^2.0.0", + "tslib": "^2.5.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=14.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, + "node_modules/@smithy/util-base64/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/util-body-length-browser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-2.0.0.tgz", + "integrity": "sha512-JdDuS4ircJt+FDnaQj88TzZY3+njZ6O+D3uakS32f2VNnDo3vyEuNdBOh/oFd8Df1zSZOuH1HEChk2AOYDezZg==", "dependencies": { - "@jest/test-result": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "slash": "^3.0.0" + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/util-body-length-browser/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/util-body-length-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-2.1.0.tgz", + "integrity": "sha512-/li0/kj/y3fQ3vyzn36NTLGmUwAICb7Jbe/CsWCktW363gh1MOcpEcSO3mJ344Gv2dqz8YJCLQpb6hju/0qOWw==", + "dependencies": { + "tslib": "^2.5.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=14.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, + "node_modules/@smithy/util-body-length-node/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/util-buffer-from": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.0.0.tgz", + "integrity": "sha512-/YNnLoHsR+4W4Vf2wL5lGv0ksg8Bmk3GEGxn2vEQt52AQaPSCuaO5PM5VM7lP1K9qHRKHwrPGktqVoAHKWHxzw==", "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" + "@smithy/is-array-buffer": "^2.0.0", + "tslib": "^2.5.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=14.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, + "node_modules/@smithy/util-buffer-from/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/util-config-provider": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-2.0.0.tgz", + "integrity": "sha512-xCQ6UapcIWKxXHEU4Mcs2s7LcFQRiU3XEluM2WcCjjBtQkUN71Tb+ydGmJFPxMUrW/GWMgQEEGipLym4XG0jZg==", "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" + "tslib": "^2.5.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=14.0.0" } }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", - "dev": true, + "node_modules/@smithy/util-config-provider/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/util-defaults-mode-browser": { + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-2.0.15.tgz", + "integrity": "sha512-2raMZOYKSuke7QlDg/HDcxQdrp0zteJ8z+S0B9Rn23J55ZFNK1+IjG4HkN6vo/0u3Xy/JOdJ93ibiBSB8F7kOw==", "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@smithy/property-provider": "^2.0.12", + "@smithy/smithy-client": "^2.1.11", + "@smithy/types": "^2.3.5", + "bowser": "^2.11.0", + "tslib": "^2.5.0" }, "engines": { - "node": ">=6.0.0" + "node": ">= 10.0.0" } }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", - "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", - "dev": true, + "node_modules/@smithy/util-defaults-mode-browser/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/util-defaults-mode-node": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-2.0.19.tgz", + "integrity": "sha512-7pScU4jBFADB2MBYKM3zb5onMh6Nn0X3IfaFVLYPyCarTIZDLUtUl1GtruzEUJPmDzP+uGeqOtU589HDY0Ni6g==", + "dependencies": { + "@smithy/config-resolver": "^2.0.14", + "@smithy/credential-provider-imds": "^2.0.16", + "@smithy/node-config-provider": "^2.1.1", + "@smithy/property-provider": "^2.0.12", + "@smithy/smithy-client": "^2.1.11", + "@smithy/types": "^2.3.5", + "tslib": "^2.5.0" + }, "engines": { - "node": ">=6.0.0" + "node": ">= 10.0.0" } }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true, + "node_modules/@smithy/util-defaults-mode-node/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/util-hex-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-2.0.0.tgz", + "integrity": "sha512-c5xY+NUnFqG6d7HFh1IFfrm3mGl29lC+vF+geHv4ToiuJCBmIfzx6IeHLg+OgRdPFKDXIw6pvi+p3CsscaMcMA==", + "dependencies": { + "tslib": "^2.5.0" + }, "engines": { - "node": ">=6.0.0" + "node": ">=14.0.0" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true + "node_modules/@smithy/util-hex-encoding/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", - "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", - "dev": true, + "node_modules/@smithy/util-middleware": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-2.0.4.tgz", + "integrity": "sha512-Pbu6P4MBwRcjrLgdTR1O4Y3c0sTZn2JdOiJNcgL7EcIStcQodj+6ZTXtbyU/WTEU3MV2NMA10LxFc3AWHZ3+4A==", "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "@smithy/types": "^2.3.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, + "node_modules/@smithy/util-middleware/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/util-retry": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-2.0.4.tgz", + "integrity": "sha512-b+n1jBBKc77C1E/zfBe1Zo7S9OXGBiGn55N0apfhZHxPUP/fMH5AhFUUcWaJh7NAnah284M5lGkBKuhnr3yK5w==", "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" + "@smithy/service-error-classification": "^2.0.4", + "@smithy/types": "^2.3.5", + "tslib": "^2.5.0" }, "engines": { - "node": ">= 8" + "node": ">= 14.0.0" } }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, + "node_modules/@smithy/util-retry/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/util-stream": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-2.0.16.tgz", + "integrity": "sha512-b5ZSRh1KzUzC7LoJcpfk7+iXGoRr3WylEfmPd4FnBLm90OwxSB9VgK1fDZwicfYxSEvWHdYXgvvjPtenEYBBhw==", + "dependencies": { + "@smithy/fetch-http-handler": "^2.2.3", + "@smithy/node-http-handler": "^2.1.7", + "@smithy/types": "^2.3.5", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-buffer-from": "^2.0.0", + "@smithy/util-hex-encoding": "^2.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" + }, "engines": { - "node": ">= 8" + "node": ">=14.0.0" } }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, + "node_modules/@smithy/util-stream/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/util-uri-escape": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-2.0.0.tgz", + "integrity": "sha512-ebkxsqinSdEooQduuk9CbKcI+wheijxEb3utGXkCoYQkJnwTnLbH1JXGimJtUkQwNQbsbuYwG2+aFVyZf5TLaw==", "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" + "tslib": "^2.5.0" }, "engines": { - "node": ">= 8" + "node": ">=14.0.0" } }, - "node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true + "node_modules/@smithy/util-uri-escape/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, - "node_modules/@sinonjs/commons": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", - "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", - "dev": true, + "node_modules/@smithy/util-utf8": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.0.0.tgz", + "integrity": "sha512-rctU1VkziY84n5OXe3bPNpKR001ZCME2JCaBBFgtiM2hfKbHFudc/BkMuPab8hRbLd0j3vbnBTTZ1igBf0wgiQ==", "dependencies": { - "type-detect": "4.0.8" + "@smithy/util-buffer-from": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" } }, - "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, + "node_modules/@smithy/util-utf8/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/util-waiter": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-2.0.11.tgz", + "integrity": "sha512-8SJWUl9O1YhjC77EccgltI3q4XZQp3vp9DGEW6o0OdkUcwqm/H4qOLnMkA2n+NDojuM5Iia2jWoCdbluIiG7TA==", "dependencies": { - "@sinonjs/commons": "^3.0.0" + "@smithy/abort-controller": "^2.0.11", + "@smithy/types": "^2.3.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" } }, + "node_modules/@smithy/util-waiter/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, "node_modules/@tsconfig/node10": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", @@ -2702,6 +4835,11 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/bowser": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", + "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==" + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -3496,6 +5634,27 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, + "node_modules/fast-xml-parser": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.2.5.tgz", + "integrity": "sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g==", + "funding": [ + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + }, + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, "node_modules/fastq": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", @@ -5536,6 +7695,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/strnum": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==" + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -5696,8 +7860,7 @@ "node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/tsutils": { "version": "3.21.0", @@ -5799,6 +7962,14 @@ "punycode": "^2.1.0" } }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "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", @@ -6044,6 +8215,21 @@ "name": "@aligent/cdk-prerender-fargate", "version": "0.0.1", "license": "GPL-3.0-only", + "dependencies": { + "@aligent/cdk-prerender-fargate": "0.1.10", + "@aws-cdk/aws-apigatewayv2-alpha": "2.30.0-alpha.0", + "@aws-cdk/aws-apigatewayv2-authorizers-alpha": "2.30.0-alpha.0", + "@aws-cdk/aws-apigatewayv2-integrations-alpha": "2.30.0-alpha.0", + "@aws-sdk/client-s3": "^3.421.0", + "@aws-sdk/client-sqs": "^3.421.0", + "@aws-sdk/client-ssm": "^3.421.0", + "@aws-solutions-constructs/aws-lambda-sqs-lambda": "^2.44.0" + } + }, + "packages/prerender-fargate/node_modules/@aligent/cdk-prerender-fargate": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/@aligent/cdk-prerender-fargate/-/cdk-prerender-fargate-0.1.10.tgz", + "integrity": "sha512-kOGzpoaOfPxL3uYpr0TouSbLdKZb/zxKiKJ0PNzErSnc+ajqZEvTWuGnTw2uPExm2bLjEI5BxNcHGpshv2WD1g==", "dependencies": { "@aws-cdk/aws-apigatewayv2-alpha": "2.30.0-alpha.0", "@aws-cdk/aws-apigatewayv2-authorizers-alpha": "2.30.0-alpha.0", diff --git a/packages/prerender-fargate/index.ts b/packages/prerender-fargate/index.ts index c0523747..ea3f8229 100644 --- a/packages/prerender-fargate/index.ts +++ b/packages/prerender-fargate/index.ts @@ -1,3 +1,4 @@ -import { PrerenderFargate, PrerenderOptions } from "./lib/prerender-fargate"; +import { PrerenderFargate } from "./lib/prerender-fargate"; +import { PrerenderFargateOptions } from "./lib/prerender-fargate-options"; -export { PrerenderFargate, PrerenderOptions }; +export { PrerenderFargate, PrerenderFargateOptions }; diff --git a/packages/prerender-fargate/lib/prerender-fargate-options.ts b/packages/prerender-fargate/lib/prerender-fargate-options.ts new file mode 100644 index 00000000..029c1f47 --- /dev/null +++ b/packages/prerender-fargate/lib/prerender-fargate-options.ts @@ -0,0 +1,81 @@ +import { PrerenderTokenUrlAssociationProps } from "./recaching/prerender-tokens"; + +/** + * Options for configuring the Prerender Fargate construct. + */ +export interface PrerenderFargateOptions { + /** + * The name of the Prerender service. + */ + prerenderName: string; + /** + * The domain name to prerender. + */ + domainName: string; + /** + * The ID of the VPC to deploy the Fargate service in. + */ + vpcId?: string; + /** + * The name of the S3 bucket to store prerendered pages in. + */ + bucketName?: string; + /** + * The number of days to keep prerendered pages in the S3 bucket before expiring them. + */ + expirationDays?: number; + /** + * A list of tokens to use for authentication with the Prerender service. + * This parameter is deprecated and will be removed in a future release. + * Please use the `tokenUrlAssociation` parameter instead. + * __If `tokenUrlAssociation` is provided, `tokenList` will be ignored__ + */ + tokenList: Array; + /** + * The ARN of the SSL certificate to use for HTTPS connections. + */ + certificateArn: string; + /** + * The desired number of Fargate instances to run. + */ + desiredInstanceCount?: number; + /** + * The maximum number of Fargate instances to run. + */ + maxInstanceCount?: number; + /** + * The amount of CPU to allocate to each Fargate instance. + */ + instanceCPU?: number; + /** + * The amount of memory to allocate to each Fargate instance. + */ + instanceMemory?: number; + /** + * Whether to enable caching of HTTP redirects. + */ + enableRedirectCache?: string; + /** + * Whether to enable the S3 endpoint for the VPC. + */ + enableS3Endpoint?: boolean; + /** + * Configuration for associating tokens with specific domain URLs. + * During the reacaching process, these tokens will be used to validate the request. + * ### Example: + * ```typescript + * { + * tokenUrlAssociation: { + * token1: [ + * "https://example.com", + * "https://acme.example.com"], + * token2: [ + * "https://example1.com", + * "https://acme.example1.com"] + * }, + * ssmPathPrefix: "/prerender/recache/tokens" + * } + * ``` + */ + tokenUrlAssociation?: PrerenderTokenUrlAssociationProps; +} diff --git a/packages/prerender-fargate/lib/prerender-fargate.ts b/packages/prerender-fargate/lib/prerender-fargate.ts index 48c0cce0..bd8e0b49 100644 --- a/packages/prerender-fargate/lib/prerender-fargate.ts +++ b/packages/prerender-fargate/lib/prerender-fargate.ts @@ -9,84 +9,105 @@ import * as ecrAssets from "aws-cdk-lib/aws-ecr-assets"; import { AccessKey, User } from "aws-cdk-lib/aws-iam"; import { Duration, RemovalPolicy, Stack } from "aws-cdk-lib"; import * as path from "path"; +import { PrerenderTokenUrlAssociation } from "./recaching/prerender-tokens"; +import { PrerenderRecacheApi } from "./recaching/prerender-recache-api-construct"; +import { PrerenderFargateOptions } from "./prerender-fargate-options"; /** - * Options for configuring the Prerender Fargate construct. + * `PrerenderFargate` construct sets up an AWS Fargate service to run a + * Prerender service in an ECS cluster. + * + * Prerender is a node server that uses Headless Chrome to render HTML, + * screenshots, PDFs, and HAR files out of any web page. The Prerender server + * listens for an http request, takes the URL and loads it in Headless Chrome, + * waits for the page to finish loading by waiting for the network to be idle, + * and then returns your content to the requesting client. + * + * ### AWS Resources Created/Configured by this Class: + * - **S3 Bucket**: For storing prerendered web pages. + * - **Fargate Service**: For running the Prerender service.. + * - **ECR Asset**: For managing the Docker image of Prerender service. + * - **VPC & VPC Endpoints**: For network configuration and enabling direct access to S3. + * - **Recache API**: (optional) To trigger recaching of URLs. + * + * ### Usage + * The class is utilized by instantiating it with suitable `PrerenderFargateOptions` + * and placing it within a CDK stack. The `PrerenderOptions` parameter allows the + * developer to customize various aspects of the Prerender service. + * + * ### Example + * ```typescript + * new PrerenderFargate(this, 'PrerenderService', { + * prerenderName: 'myPrerender', + * bucketName: 'myPrerenderBucket', + * expirationDays: 7, + * vpcId: 'vpc-xxxxxxxx', + * desiredInstanceCount: 1, + * instanceCPU: 512, + * instanceMemory: 1024, + * domainName: 'prerender.mydomain.com', + * certificateArn: 'arn:aws:acm:region:account:certificate/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', + * enableRedirectCache: 'false', + * maxInstanceCount: 2, + * enableS3Endpoint: true, + * tokenUrlAssociation: { + * tokenUrlAssociation: { + * token1: [ + * "https://example.com", + * "https://acme.example.com" + * ], + * token2: [ + * "https://example1.com", + * "https://acme.example1.com" + * ] + * }, + * ssmPathPrefix: "/prerender/recache/tokens" + * } + * }); + * ``` + * + * @param {Construct} scope The scope of the construct. + * @param {string} id The ID of the construct. + * @param {PrerenderFargateOptions} props The properties of the Prerender Fargate service. + * + * @returns {PrerenderFargate} An instance of the PrerenderFargate class. */ -export interface PrerenderOptions { - /** - * The name of the Prerender service. - */ - prerenderName: string; - /** - * The domain name to prerender. - */ - domainName: string; - /** - * The ID of the VPC to deploy the Fargate service in. - */ - vpcId?: string; - /** - * The name of the S3 bucket to store prerendered pages in. - */ - bucketName?: string; - /** - * The number of days to keep prerendered pages in the S3 bucket before expiring them. - */ - expirationDays?: number; - /** - * A list of tokens to use for authentication with the Prerender service. - */ - tokenList: Array; - /** - * The ARN of the SSL certificate to use for HTTPS connections. - */ - certificateArn: string; - /** - * The desired number of Fargate instances to run. - */ - desiredInstanceCount?: number; - /** - * The maximum number of Fargate instances to run. - */ - maxInstanceCount?: number; - /** - * The amount of CPU to allocate to each Fargate instance. - */ - instanceCPU?: number; - /** - * The amount of memory to allocate to each Fargate instance. - */ - instanceMemory?: number; - /** - * Whether to enable caching of HTTP redirects. - */ - enableRedirectCache?: string; - /** - * Whether to enable the S3 endpoint for the VPC. - */ - enableS3Endpoint?: boolean; -} export class PrerenderFargate extends Construct { readonly bucket: Bucket; - /** - * Constructs a new Prerender Fargate service. - * @param scope The scope of the construct. - * @param id The ID of the construct. - * @param props The properties of the Prerender Fargate service. - */ - constructor(scope: Construct, id: string, props: PrerenderOptions) { - super(scope, id); + /** + * Constructs a new Prerender Fargate service. + * @param scope The scope of the construct. + * @param id The ID of the construct. + * @param props The properties of the Prerender Fargate service. + */ + constructor(scope: Construct, id: string, props: PrerenderFargateOptions) { + super(scope, id); + + const { + tokenUrlAssociation, + certificateArn, + vpcId, + maxInstanceCount, + instanceMemory, + instanceCPU, + expirationDays, + enableS3Endpoint, + enableRedirectCache, + desiredInstanceCount, + bucketName, + domainName, + prerenderName, + } = props; // Create bucket for prerender storage - this.bucket = new Bucket(this, `${props.prerenderName}-bucket`, { - bucketName: props.bucketName, + this.bucket = new Bucket(this, `${prerenderName}-bucket`, { + bucketName: bucketName, lifecycleRules: [ { enabled: true, - expiration: Duration.days(props.expirationDays || 7), // Default to 7 day expiration + expiration: Duration.days(expirationDays || 7), // Default to 7 day expiration }, ], removalPolicy: RemovalPolicy.DESTROY, @@ -103,41 +124,41 @@ export class PrerenderFargate extends Construct { serial: 1, }); - const vpcLookup = props.vpcId - ? { vpcId: props.vpcId } - : { isDefault: true }; + const vpcLookup = vpcId ? { vpcId: vpcId } : { isDefault: true }; const vpc = ec2.Vpc.fromLookup(this, "vpc", vpcLookup); - const cluster = new ecs.Cluster(this, `${props.prerenderName}-cluster`, { + const cluster = new ecs.Cluster(this, `${prerenderName}-cluster`, { vpc: vpc, }); const directory = path.join(__dirname, "prerender"); const asset = new ecrAssets.DockerImageAsset( this, - `${props.prerenderName}-image`, + `${prerenderName}-image`, { directory, } ); - /** - * This provide backward compatibility for the tokenList property - * If tokenUrlAssociation is provided, tokenList will be ignored - */ - const tokenList = props.tokenUrlAssociation ? Object.keys(props.tokenUrlAssociation.tokenUrlAssociation) : props.tokenList.toString(); + /** + * This provide backward compatibility for the tokenList property + * If tokenUrlAssociation is provided, tokenList will be ignored + */ + const tokenList = tokenUrlAssociation + ? Object.keys(tokenUrlAssociation.tokenUrlAssociation) + : props.tokenList.toString(); // Create a load-balanced Fargate service const fargateService = new ecsPatterns.ApplicationLoadBalancedFargateService( this, - `${props.prerenderName}-service`, + `${prerenderName}-service`, { cluster, - serviceName: `${props.prerenderName}-service`, - desiredCount: props.desiredInstanceCount || 1, - cpu: props.instanceCPU || 512, // 0.5 vCPU default - memoryLimitMiB: props.instanceMemory || 1024, // 1 GB default to give Chrome enough memory + serviceName: `${prerenderName}-service`, + desiredCount: desiredInstanceCount || 1, + cpu: instanceCPU || 512, // 0.5 vCPU default + memoryLimitMiB: instanceMemory || 1024, // 1 GB default to give Chrome enough memory taskImageOptions: { image: ecs.ContainerImage.fromDockerImageAsset(asset), enableLogging: true, @@ -147,7 +168,7 @@ export class PrerenderFargate extends Construct { AWS_ACCESS_KEY_ID: accessKey.accessKeyId, AWS_SECRET_ACCESS_KEY: accessKey.secretAccessKey.unsafeUnwrap(), AWS_REGION: Stack.of(this).region, - ENABLE_REDIRECT_CACHE: props.enableRedirectCache || "false", + ENABLE_REDIRECT_CACHE: enableRedirectCache || "false", TOKEN_LIST: tokenList.toString(), }, }, @@ -156,20 +177,20 @@ export class PrerenderFargate extends Construct { assignPublicIp: true, listenerPort: 443, redirectHTTP: true, - domainName: props.domainName, + domainName: domainName, domainZone: new HostedZone(this, "hosted-zone", { - zoneName: props.domainName, + zoneName: domainName, }), certificate: Certificate.fromCertificateArn( this, "cert", - props.certificateArn + certificateArn ), } ); // As the prerender service will return a 401 on all unauthorised requests - // it should be considered healthy when receiving a 401 response + // It should be considered healthy when receiving a 401 response fargateService.targetGroup.configureHealthCheck({ path: "/health", interval: Duration.seconds(120), @@ -177,56 +198,53 @@ export class PrerenderFargate extends Construct { healthyHttpCodes: "401", }); - // Setup AutoScaling policy - const scaling = fargateService.service.autoScaleTaskCount({ - maxCapacity: props.maxInstanceCount || 2, - }); - scaling.scaleOnCpuUtilization(`${props.prerenderName}-scaling`, { - targetUtilizationPercent: 50, - scaleInCooldown: Duration.seconds(60), - scaleOutCooldown: Duration.seconds(60), - }); - - /** + // Setup AutoScaling policy + const scaling = fargateService.service.autoScaleTaskCount({ + maxCapacity: maxInstanceCount || 2, + }); + scaling.scaleOnCpuUtilization(`${prerenderName}-scaling`, { + targetUtilizationPercent: 50, + scaleInCooldown: Duration.seconds(60), + scaleOutCooldown: Duration.seconds(60), + }); + + /** * Enable VPC Endpoints for S3 * This would create S3 endpoints in all the PUBLIC subnets of the VPC */ - if (props.enableS3Endpoint) { - vpc.addGatewayEndpoint("S3Endpoint", { - service: ec2.GatewayVpcEndpointAwsService.S3, - subnets: [{ subnetType: ec2.SubnetType.PUBLIC }], - }); - } - - /** - * Recache API - * Recaching is enable by default - */ - if (props.tokenUrlAssociation) { - /** - * Create the token-url association - * This is used for managing prerender tokens in prerender re-caching. - * Example: - * { - * tokenUrlAssociation: { - * token1: [url1, url2], - * token2: [url3, url4]}, - * ssmPathPrefix: /prerender/recache/tokens - * } - */ - new PrerenderTokensUrlAssociation(this, `${props.prerenderName}-token-url-association`, { - tokenUrlAssociation: props.tokenUrlAssociation.tokenUrlAssociation, - ssmPathPrefix: props.tokenUrlAssociation.ssmPathPrefix - }); - - /** - * Create the recache API - * This would create the API that can be used to trigger recaching of URLs. - */ - new PrerenderRecacheApi(this, `${props.prerenderName}-recache-api`, { - prerenderS3Bucket: this.bucket, - tokenList: Object.keys(props.tokenUrlAssociation.tokenUrlAssociation), - }); + if (enableS3Endpoint) { + vpc.addGatewayEndpoint("S3Endpoint", { + service: ec2.GatewayVpcEndpointAwsService.S3, + subnets: [{ subnetType: ec2.SubnetType.PUBLIC }], + }); + } + + /** + * Recache API + * Recaching is enable by default + */ + if (tokenUrlAssociation) { + /** + * Create the token-url association + * This is used for managing prerender tokens in prerender re-caching + */ + new PrerenderTokenUrlAssociation( + this, + `${prerenderName}-token-url-association`, + { + tokenUrlAssociation: tokenUrlAssociation.tokenUrlAssociation, + ssmPathPrefix: tokenUrlAssociation.ssmPathPrefix, } + ); + + /** + * Create the recache API + * This would create the API that is used to trigger recaching of the URLs + */ + new PrerenderRecacheApi(this, `${prerenderName}-recache-api`, { + prerenderS3Bucket: this.bucket, + tokenList: Object.keys(tokenUrlAssociation.tokenUrlAssociation), + }); } -} \ No newline at end of file + } +} diff --git a/packages/prerender-fargate/lib/recaching/prerender-recache-api-construct.api.ts b/packages/prerender-fargate/lib/recaching/prerender-recache-api-construct.api.ts index 175fde67..d404c222 100644 --- a/packages/prerender-fargate/lib/recaching/prerender-recache-api-construct.api.ts +++ b/packages/prerender-fargate/lib/recaching/prerender-recache-api-construct.api.ts @@ -34,9 +34,8 @@ interface PreRenderRequestBody { const QueueUrl = process.env.SQS_QUEUE_URL; const Bucket = process.env.PRERENDER_CACHE_BUCKET; - export const MAX_URLS = 1000; -export const PARAM_PREFIX = "prerender/recache/tokens"; +export const PARAM_PREFIX = "prerender/recache/tokens"; const sqsClient = new SQSClient({}); const s3Client = new S3Client({}); @@ -52,7 +51,7 @@ const tokens: Map = new Map(); */ export const handler = async ( event: APIGatewayEvent, - _context: Context + _context: Context ): Promise => { let urlsToRecache: string[]; diff --git a/packages/prerender-fargate/lib/recaching/prerender-tokens.ts b/packages/prerender-fargate/lib/recaching/prerender-tokens.ts index af040d1c..0153f4c5 100644 --- a/packages/prerender-fargate/lib/recaching/prerender-tokens.ts +++ b/packages/prerender-fargate/lib/recaching/prerender-tokens.ts @@ -12,15 +12,26 @@ interface TokenUrlAssociation { /** * Interface for associating a token with a URL for prerendering. */ -export interface PrerenderTokenUrlAssociation extends StackProps { +export interface PrerenderTokenUrlAssociationProps extends StackProps { /** * Object containing the token and its associated URL. + * ### Example + * ```typescript + * tokenUrlAssociation: { + * token1: [ + * "https://example.com", + * "https://acme.example.com"], + * token2: [ + * "https://example1.com", + * "https://acme.example1.com"] + * } + * ``` */ tokenUrlAssociation: TokenUrlAssociation; /** * Prefix for the SSM parameter path where the token value is stored. */ - ssmPathPrefix: string; + ssmPathPrefix?: string; } /** @@ -31,15 +42,16 @@ export interface PrerenderTokenUrlAssociation extends StackProps { * The constructor loops through the tokenUrlAssociation object and * creates an SSM parameter for each token. */ -export class PrerenderTokensUrlAssociation extends Stack { +export class PrerenderTokenUrlAssociation extends Stack { constructor( scope: Construct, id: string, - props: PrerenderTokenUrlAssociation + props: PrerenderTokenUrlAssociationProps ) { super(scope, id, props); - const { tokenUrlAssociation, ssmPathPrefix } = props; + const { tokenUrlAssociation, ssmPathPrefix = "/prerender/recache/tokens" } = + props; // Loop through the tokenDomains for (const [token, domains] of Object.entries(tokenUrlAssociation)) { From 074192605158f75cbe867375a34af490638f272d Mon Sep 17 00:00:00 2001 From: Krishan Thisera Date: Thu, 12 Oct 2023 18:22:12 +1030 Subject: [PATCH 12/27] DO-1546: include fargate option ts --- packages/prerender-fargate/lib/prerender-fargate-options.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/prerender-fargate/lib/prerender-fargate-options.ts b/packages/prerender-fargate/lib/prerender-fargate-options.ts index 029c1f47..e71f728f 100644 --- a/packages/prerender-fargate/lib/prerender-fargate-options.ts +++ b/packages/prerender-fargate/lib/prerender-fargate-options.ts @@ -28,7 +28,7 @@ export interface PrerenderFargateOptions { * A list of tokens to use for authentication with the Prerender service. * This parameter is deprecated and will be removed in a future release. * Please use the `tokenUrlAssociation` parameter instead. - * __If `tokenUrlAssociation` is provided, `tokenList` will be ignored__ + * *If `tokenUrlAssociation` is provided, `tokenList` will be ignored* */ tokenList: Array; /** From 0520fb3b65572d3aa71a6277326a282d9e039635 Mon Sep 17 00:00:00 2001 From: Daniel Van Der Ploeg Date: Tue, 29 Aug 2023 14:18:12 +0930 Subject: [PATCH 13/27] feat: add initial construct for mesh hosting --- .gitignore | 4 + README.md | 3 + packages/graphql-mesh-server/.npmignore | 11 + packages/graphql-mesh-server/README.md | 15 ++ packages/graphql-mesh-server/index.ts | 3 + packages/graphql-mesh-server/lib/fargate.ts | 220 ++++++++++++++++++ .../lib/graphql-mesh-server.ts | 95 ++++++++ packages/graphql-mesh-server/lib/pipeline.ts | 91 ++++++++ .../lib/redis-construct.ts | 96 ++++++++ .../lib/web-application-firewall.ts | 164 +++++++++++++ packages/graphql-mesh-server/package.json | 23 ++ packages/graphql-mesh-server/tsconfig.json | 3 + 12 files changed, 728 insertions(+) create mode 100644 packages/graphql-mesh-server/.npmignore create mode 100644 packages/graphql-mesh-server/README.md create mode 100644 packages/graphql-mesh-server/index.ts create mode 100644 packages/graphql-mesh-server/lib/fargate.ts create mode 100644 packages/graphql-mesh-server/lib/graphql-mesh-server.ts create mode 100644 packages/graphql-mesh-server/lib/pipeline.ts create mode 100644 packages/graphql-mesh-server/lib/redis-construct.ts create mode 100644 packages/graphql-mesh-server/lib/web-application-firewall.ts create mode 100644 packages/graphql-mesh-server/package.json create mode 100644 packages/graphql-mesh-server/tsconfig.json diff --git a/.gitignore b/.gitignore index 8f77f768..8f11aef6 100644 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,9 @@ dist/ # JetBrains IDE .idea/ +# VSCode IDE +.vscode/ + # Unit test reports TEST*.xml @@ -53,6 +56,7 @@ Thumbs.db # CDK asset staging directory .cdk.staging cdk.out +*.tsbuildinfo *.d.ts *.js diff --git a/README.md b/README.md index 0ea9aeab..e3934567 100644 --- a/README.md +++ b/README.md @@ -34,3 +34,6 @@ When making a release (including experimental releases), the release tag should |---------------|---------------| | Experimental | 1.1.0-beta | | Final | 1.1.0 | + +## Testing locally + diff --git a/packages/graphql-mesh-server/.npmignore b/packages/graphql-mesh-server/.npmignore new file mode 100644 index 00000000..bfd115ba --- /dev/null +++ b/packages/graphql-mesh-server/.npmignore @@ -0,0 +1,11 @@ +*.ts +!lib/handlers/*.ts +!*.d.ts +!*.js + +# CDK asset staging directory +.cdk.staging +cdk.out + +# Samples +sample/ diff --git a/packages/graphql-mesh-server/README.md b/packages/graphql-mesh-server/README.md new file mode 100644 index 00000000..4263295b --- /dev/null +++ b/packages/graphql-mesh-server/README.md @@ -0,0 +1,15 @@ +# Prerender in Fargate +A construct host [GraphQL Mesh](https://the-guild.dev/graphql/mesh) server in Fargate. + +## Props + - `vpc?`: VPC to attach Redis and Fargate instances to (default: create a vpc) + - `vpcName?`: If no VPC is provided create one with this name (default: 'graphql-server-vpc') + - `cacheNodeType?`: Cache node type (default: 'cache.t2.micro') + - `repository?`: Repository to pull the container image from + - `certificateArn:` ARN of the certificate to add to the load balancer + - `minCapacity?`: Minimum number of Fargate instances + - `maxCapacity?`: Maximum number of Fargate instances + - `cpu?`: Amount of vCPU per Fargate instance (default: 512) + - `memory?`: Amount of memory per Fargate instance (default: 1024) + - `redis?`: Redis instance to use for mesh caching + - `secrets?`: SSM values to pass through to the container as secrets diff --git a/packages/graphql-mesh-server/index.ts b/packages/graphql-mesh-server/index.ts new file mode 100644 index 00000000..cd739cad --- /dev/null +++ b/packages/graphql-mesh-server/index.ts @@ -0,0 +1,3 @@ +import { MeshHosting } from "./lib/graphql-mesh-server"; + +export { MeshHosting }; diff --git a/packages/graphql-mesh-server/lib/fargate.ts b/packages/graphql-mesh-server/lib/fargate.ts new file mode 100644 index 00000000..7a36cfb6 --- /dev/null +++ b/packages/graphql-mesh-server/lib/fargate.ts @@ -0,0 +1,220 @@ +import { Construct } from 'constructs'; +import { Duration } from 'aws-cdk-lib'; +import { RemovalPolicy } from 'aws-cdk-lib'; +import * as acm from 'aws-cdk-lib/aws-certificatemanager'; +import * as ecs from 'aws-cdk-lib/aws-ecs'; +import * as ecr from 'aws-cdk-lib/aws-ecr'; +import * as ecsPatterns from 'aws-cdk-lib/aws-ecs-patterns'; +import * as iam from 'aws-cdk-lib/aws-iam'; +import * as ssm from 'aws-cdk-lib/aws-ssm'; +import * as auto_scaling from 'aws-cdk-lib/aws-autoscaling'; +import { Port, SecurityGroup, Vpc } from 'aws-cdk-lib/aws-ec2'; +import { RedisService } from './redis-construct'; +import { ManagedRule, Scope, WebApplicationFirewall } from './web-application-firewall'; + +export interface MeshServiceProps { + /** + * VPC to attach Redis instance to + */ + vpc?: Vpc; + /** + * Repository to pull the container image from + */ + repository?: ecr.Repository; + /** + * ARN of the certificate to add to the load balancer + */ + certificateArn: string; + /** + * Minimum number of Fargate instances + */ + minCapacity?: number; + /** + * Maximum number of Fargate instances + */ + maxCapacity?: number; + /** + * Amount of vCPU per instance (default: 512) + */ + cpu?: number; + /** + * Amount of memory per instance (default: 1024) + */ + memory?: number; + /** + * Redis instance to use for mesh caching + */ + redis: RedisService; + /** + * SSM values to pass through to the container as secrets + */ + secrets?: {[key: string]: ssm.IStringParameter | ssm.IStringListParameter}; +} + +export class MeshService extends Construct { + public readonly vpc: Vpc; + public readonly repository: ecr.Repository; + public readonly service: ecs.FargateService; + public readonly firewall: WebApplicationFirewall; + + constructor(scope: Construct, id: string, props: MeshServiceProps) { + super(scope, id); + + const certificate = acm.Certificate.fromCertificateArn( + this, + `certificate`, + props.certificateArn + ); + + this.vpc = + props.vpc || + new Vpc(this, 'vpc', { + natGateways: 1, + }); + + this.repository = + props.repository || + new ecr.Repository(this, 'repo', { + removalPolicy: RemovalPolicy.DESTROY, + autoDeleteImages: true, + }); + + if (!props.repository) { + // Delete all images older than 90 days BUT keep 10 from the latest tag + this.repository.addLifecycleRule({ + tagPrefixList: ['latest'], + maxImageCount: 10, + }); + this.repository.addLifecycleRule({ + maxImageAge: Duration.days(90), + }); + } + + // Create a deploy user to push images to ECR + const deployUser = new iam.User(this, 'deploy-user'); + + const deployPolicy = new iam.Policy(this, 'deploy-policy'); + deployPolicy.addStatements( + new iam.PolicyStatement({ + effect: iam.Effect.ALLOW, + actions: [ + 'ecr:CompleteLayerUpload', + 'ecr:UploadLayerPart', + 'ecr:InitiateLayerUpload', + 'ecr:BatchCheckLayerAvailability', + 'ecr:PutImage', + ], + resources: [this.repository.repositoryArn], + }), + new iam.PolicyStatement({ + effect: iam.Effect.ALLOW, + actions: ['ecr:GetAuthorizationToken'], + resources: ['*'], + }) + ); + + deployUser.attachInlinePolicy(deployPolicy); + + const securityGroup = new SecurityGroup(this, 'security-group', { + vpc: this.vpc, + }); + + const cluster = new ecs.Cluster(this, `cluster`, { + vpc: this.vpc, + }); + + const environment: { [key: string]: string } = {}; + + // If using Redis configure security group and pass connection string to container + if (props.redis) { + props.redis.securityGroup.addIngressRule( + securityGroup, + Port.tcp(Number(props.redis.connectionPort)) + ); + + environment['REDIS_ENDPOINT'] = props.redis.connectionEndPoint; + environment['REDIS_PORT'] = props.redis.connectionPort; + } + + // Construct secrets from provided ssm values + const secrets: {[key: string]: ecs.Secret} = {}; + props.secrets = props.secrets || {}; + for (const [key, ssm] of Object.entries(props.secrets)) { + secrets[key] = ecs.Secret.fromSsmParameter(ssm); + } + // Create a load-balanced Fargate service and make it public + const fargateService = + new ecsPatterns.ApplicationLoadBalancedFargateService( + this, + `fargate`, + { + cluster, + certificate, + enableExecuteCommand: true, + cpu: props.cpu || 512, // 0.5 vCPU + memoryLimitMiB: props.memory || 1024, // 1 GB + taskImageOptions: { + image: ecs.ContainerImage.fromEcrRepository( + this.repository + ), + enableLogging: true, // default + containerPort: 4000, // graphql mesh gateway port + secrets: secrets, + environment: environment, + }, + publicLoadBalancer: true, // default, + taskSubnets: { + subnets: [...this.vpc.privateSubnets], + }, + securityGroups: [securityGroup], + } + ); + + this.service = fargateService.service; + + this.firewall = new WebApplicationFirewall(this, 'waf', { + scope: Scope.REGIONAL, + visibilityConfig: { + cloudWatchMetricsEnabled: true, + metricName: "firewall-request", + sampledRequestsEnabled: true + }, + managedRules: [ + { + name: ManagedRule.COMMON_RULE_SET, + excludedRules: [ + { + name: 'SizeRestrictions_QUERYSTRING' + } + ] + }, + { + name: ManagedRule.KNOWN_BAD_INPUTS_RULE_SET, + } + ] + }); + + this.firewall.addAssociation('loadbalancer-association', fargateService.loadBalancer.loadBalancerArn); + + fargateService.targetGroup.configureHealthCheck({ + path: '/healthcheck', + }); + + // Setup auto scaling policy + const scaling = fargateService.service.autoScaleTaskCount({ + minCapacity: props.minCapacity || 1, + maxCapacity: props.maxCapacity || 5, + }); + + const cpuUtilization = fargateService.service.metricCpuUtilization(); + scaling.scaleOnMetric('auto-scale-cpu', { + metric: cpuUtilization, + scalingSteps: [ + { upper: 30, change: -1 }, + { lower: 50, change: +1 }, + { lower: 85, change: +3 }, + ], + adjustmentType: auto_scaling.AdjustmentType.CHANGE_IN_CAPACITY, + }); + } +} diff --git a/packages/graphql-mesh-server/lib/graphql-mesh-server.ts b/packages/graphql-mesh-server/lib/graphql-mesh-server.ts new file mode 100644 index 00000000..cec04774 --- /dev/null +++ b/packages/graphql-mesh-server/lib/graphql-mesh-server.ts @@ -0,0 +1,95 @@ +import { Construct } from 'constructs'; +import { MeshService, MeshServiceProps } from './fargate'; +import { RedisService, RedisServiceProps } from './redis-construct'; +import { CodePipelineService } from './pipeline'; +import { SecurityGroup, Vpc } from 'aws-cdk-lib/aws-ec2'; +import { Repository } from 'aws-cdk-lib/aws-ecr'; +import { FargateService } from 'aws-cdk-lib/aws-ecs'; +import { CfnCacheCluster } from 'aws-cdk-lib/aws-elasticache'; +import * as ssm from 'aws-cdk-lib/aws-ssm'; + +export type MeshHostingProps = { + /** + * VPC to attach Redis and Fargate instances to (default: create a vpc) + */ + vpc?: Vpc; + /** + * If no VPC is provided create one with this name (default: 'graphql-server-vpc') + */ + vpcName?: string; + /** + * Cache node type (default: 'cache.t2.micro') + */ + cacheNodeType?: string; + /** + * Repository to pull the container image from + */ + repository?: Repository; + /** + * ARN of the certificate to add to the load balancer + */ + certificateArn: string; + /** + * Minimum number of Fargate instances + */ + minCapacity?: number; + /** + * Maximum number of Fargate instances + */ + maxCapacity?: number; + /** + * Amount of vCPU per Fargate instance (default: 512) + */ + cpu?: number; + /** + * Amount of memory per Fargate instance (default: 1024) + */ + memory?: number; + /** + * Redis instance to use for mesh caching + */ + redis?: RedisService; + /** + * SSM values to pass through to the container as secrets + */ + secrets?: {[key: string]: ssm.IStringParameter | ssm.IStringListParameter}; +}; + +export class MeshHosting extends Construct { + public readonly vpc: Vpc; + public readonly repository: Repository; + public readonly service: FargateService; + public readonly cacheCluster: CfnCacheCluster; + public readonly securityGroup: SecurityGroup; + + constructor(scope: Construct, id: string, props: MeshHostingProps) { + super(scope, id); + + this.vpc = props.vpc || new Vpc(this, 'graphql-server-vpc', { + vpcName: props.vpcName || 'graphql-server-vpc', + natGateways: 1 + }); + + const redis = props.redis || new RedisService(this, 'redis', { + ...props, + vpc: this.vpc + }); + + this.cacheCluster = redis.cacheCluster; + this.securityGroup = redis.securityGroup; + + const mesh = new MeshService(this, 'mesh', { + ...props, + vpc: this.vpc, + redis, + }); + + this.service = mesh.service; + this.repository = mesh.repository; + + new CodePipelineService(this, 'pipeline', { + repository: this.repository, + service: this.service, + }); + } +} diff --git a/packages/graphql-mesh-server/lib/pipeline.ts b/packages/graphql-mesh-server/lib/pipeline.ts new file mode 100644 index 00000000..a6189049 --- /dev/null +++ b/packages/graphql-mesh-server/lib/pipeline.ts @@ -0,0 +1,91 @@ +import { Duration } from 'aws-cdk-lib'; +import { Artifact, Pipeline } from 'aws-cdk-lib/aws-codepipeline'; +import { Repository } from 'aws-cdk-lib/aws-ecr'; +import { FargateService } from 'aws-cdk-lib/aws-ecs'; +import * as pipe_actions from 'aws-cdk-lib/aws-codepipeline-actions'; +import * as codebuild from 'aws-cdk-lib/aws-codebuild'; +import { Construct } from 'constructs'; +import * as fs from 'fs'; +import * as path from 'path'; +import * as YAML from 'yaml'; + +export interface CodePipelineServiceProps { + /** + * Repository the code container is pushed too + */ + repository: Repository; + + /** + * Services to deploy Code container updates to + */ + service: FargateService; + + /** + * Path to buildspec.yml (default: '../assets/buildspec.yml') + */ + buildspecPath?: string; +} + +export class CodePipelineService extends Construct { + public readonly pipeline: Pipeline; + + constructor(scope: Construct, id: string, props: CodePipelineServiceProps) { + super(scope, id); + + this.pipeline = new Pipeline(this, 'deploy-pipeline'); + + const sourceOutput = new Artifact(); + const sourceAction = new pipe_actions.EcrSourceAction({ + actionName: 'ECR', + repository: props.repository, + output: sourceOutput, + }); + + this.pipeline.addStage({ + stageName: 'Source', + actions: [sourceAction], + }); + + const file = fs.readFileSync( + path.resolve(__dirname, props.buildspecPath || '../assets/buildspec.yml'), + 'utf8' + ); + const project: codebuild.PipelineProject = + new codebuild.PipelineProject(this, 'project', { + buildSpec: codebuild.BuildSpec.fromObject(YAML.parse(file)), + }); + + const buildOutput = new Artifact(); + this.pipeline.addStage({ + stageName: 'Build', + actions: [ + new pipe_actions.CodeBuildAction({ + actionName: 'CodeBuild', + project, + input: sourceOutput, + outputs: [buildOutput], + environmentVariables: { + IMAGE_URI: { + value: sourceAction.variables.imageUri, + }, + CONTAINER_NAME: { + value: props.service.taskDefinition.defaultContainer + ?.containerName, + }, + }, + }), + ], + }); + this.pipeline.addStage({ + stageName: 'Deploy', + actions: [ + new pipe_actions.EcsDeployAction({ + actionName: 'DeployAction', + service: props.service, + input: buildOutput, + deploymentTimeout: Duration.minutes(10), + }), + ], + }); + } +} diff --git a/packages/graphql-mesh-server/lib/redis-construct.ts b/packages/graphql-mesh-server/lib/redis-construct.ts new file mode 100644 index 00000000..a0319f43 --- /dev/null +++ b/packages/graphql-mesh-server/lib/redis-construct.ts @@ -0,0 +1,96 @@ +import { SecurityGroup, Vpc } from 'aws-cdk-lib/aws-ec2'; +import { + CfnCacheCluster, + CfnSubnetGroup, + CfnParameterGroup, +} from 'aws-cdk-lib/aws-elasticache'; +import { CfnOutput } from 'aws-cdk-lib'; +import { Construct } from 'constructs'; + +export interface RedisServiceProps { + /** + * VPC to attach Redis instance to + */ + vpc: Vpc; + /** + * Cache node type (default: 'cache.t2.micro') + */ + cacheNodeType?: string; +} + +export class RedisService extends Construct { + public readonly cacheCluster: CfnCacheCluster; + public readonly vpc: Vpc; + public readonly securityGroup: SecurityGroup; + + constructor(scope: Construct, id: string, props: RedisServiceProps) { + super(scope, id); + + this.vpc = props.vpc; + + this.securityGroup = new SecurityGroup(this, 'RedisSecurityGroup', { + vpc: this.vpc, + }); + + const privateSubnets: string[] = this.vpc.privateSubnets.map( + (subnet) => { + return subnet.subnetId; + } + ); + + const cacheSubnetGroup = new CfnSubnetGroup(this, 'CacheSubnetGroup', { + description: 'Subnet Group for Mesh Cache', + subnetIds: privateSubnets, + }); + + const cacheParameterGroup = new CfnParameterGroup( + this, + 'CacheParameterGroup', + { + cacheParameterGroupFamily: 'redis7', + description: 'Parameter Group for Mesh Cache', + properties: { + 'maxmemory-policy': 'allkeys-lru', + }, + } + ); + + this.cacheCluster = new CfnCacheCluster(this, 'cache-cluster', { + cacheNodeType: props.cacheNodeType || 'cache.t2.micro', + engine: 'redis', + numCacheNodes: 1, + autoMinorVersionUpgrade: true, + vpcSecurityGroupIds: [this.securityGroup.securityGroupId], + cacheSubnetGroupName: cacheSubnetGroup.ref, + cacheParameterGroupName: cacheParameterGroup.ref, + }); + + this.cacheCluster.addDependency(cacheParameterGroup); + this.cacheCluster.addDependency(cacheSubnetGroup); + + new CfnOutput(this, 'RedisConnectionString', { + description: 'RedisConnectionString', + value: this.cacheConnectionString, + }); + } + + public get cacheConnectionString(): string { + return `redis://${this.cacheCluster + .getAtt('RedisEndpoint.Address') + .toString()}:${this.cacheCluster + .getAtt('RedisEndpoint.Port') + .toString()}`; + } + + public get connectionEndPoint(): string { + return this.cacheCluster + .getAtt('RedisEndpoint.Address') + .toString(); + } + + public get connectionPort(): string { + return this.cacheCluster + .getAtt('RedisEndpoint.Port') + .toString(); + } +} diff --git a/packages/graphql-mesh-server/lib/web-application-firewall.ts b/packages/graphql-mesh-server/lib/web-application-firewall.ts new file mode 100644 index 00000000..57e3c6ce --- /dev/null +++ b/packages/graphql-mesh-server/lib/web-application-firewall.ts @@ -0,0 +1,164 @@ +import { CfnWebACL, CfnWebACLAssociation } from "aws-cdk-lib/aws-wafv2"; +import { Construct } from "constructs"; + +export enum Action { + BLOCK = 'BLOCK', + ALLOW = 'ALLOW', +} + +export enum Scope { + CLOUDFRONT = 'CLOUDFRONT', + REGIONAL = 'REGIONAL', +} + +export enum ManagedRule { + BOT_CONTROL_RULE_SET = "AWSManagedRulesBotControlRuleSet", + KNOWN_BAD_INPUTS_RULE_SET = "AWSManagedRulesKnownBadInputsRuleSet", + COMMON_RULE_SET = "AWSManagedRulesCommonRuleSet", + ANNONYMOUS_IP_LIST = "AWSManagedRulesAnonymousIpList", + AMAZON_IP_REPUTATION_LIST = "AWSManagedRulesAmazonIpReputationList", + ADMIN_PROTECTION_RULE_SET = "AWSManagedRulesAdminProtectionRuleSet", + SQLI_RULE_SET = "AWSManagedRulesSQLiRuleSet", + PHP_RULE_SET = "AWSManagedRulesPHPRuleSet" +} + +export interface VisibilityConfig { + /** + * Whether cloudwatch metrics are enabled or nor + */ + cloudWatchMetricsEnabled: boolean, + + /** + * Name of the metric in cloudwatch + */ + metricName: string, + + /** + * Whether to keep samples of blocked requests + */ + sampledRequestsEnabled: boolean +} + +export interface AWSManagedRule { + /** + * Which AWS Rule to add + */ + name: ManagedRule, + + /** + * @default to the name property + */ + metricName?: string, + + /** + * @default false + */ + sampledRequestsEnabled?: boolean, + + /** + * Any rules from this ruleset you wish to disable/exclude + */ + excludedRules?: Array<{ + name: string + }>, + + /** + * Whether to override the default action to COUNT + */ + count?: boolean +} + +export interface WebApplicationFirewallProps { + /** + * Name of the WAF + */ + name?: string, + + /** + * The action to perform if none of the `Rules` contained in the `WebACL` match. + * @default Action.ALLOW + */ + defaultAction?: Action, + + /** + * Specifies whether this is for an Amazon CloudFront distribution or for a regional application. + * @default Scope.REGIONAL + */ + scope?: Scope + + /** + * Default visibility configuration + */ + visibilityConfig: VisibilityConfig, + + /** + * List of AWS Managed rules to add to the WAF + */ + managedRules?: AWSManagedRule[], + + /** + * List of custom rules + */ + rules?: CfnWebACL.RuleProperty[] +} + +export class WebApplicationFirewall extends Construct { + readonly acl: CfnWebACL; + readonly associations: CfnWebACLAssociation[]; + + constructor(scope: Construct, id: string, props: WebApplicationFirewallProps) { + super(scope, id); + + let defaultAction: CfnWebACL.DefaultActionProperty = { allow: {} }; + + if (props.defaultAction == Action.BLOCK) { + defaultAction = { block: {} }; + } + + this.associations = []; + + const rules: CfnWebACL.RuleProperty[] = props.rules || []; + + // Convert from our AWSManagedRule type to a CfnWebACL.RuleProperty + if (props.managedRules) { + props.managedRules.forEach((rule, index) => { + rules.push({ + name: rule.name, + priority: index, + visibilityConfig: { + // if no metric name is passed then don't enable metrics + cloudWatchMetricsEnabled: rule.metricName ? true : false, + // Default to the rule name if a metric name isn't passed + metricName: rule.metricName || rule.name, + sampledRequestsEnabled: rule.sampledRequestsEnabled || false + }, + statement: { + managedRuleGroupStatement: { + name: rule.name, + vendorName: "AWS", + excludedRules: rule.excludedRules || [], + } + }, + overrideAction: rule.count ? { count: {} } : { none: {} } + }) + }); + } + + this.acl = new CfnWebACL(this, "WebAcl", { + name: props.name, + defaultAction, + scope: props.scope || Scope.REGIONAL, + visibilityConfig: props.visibilityConfig, + rules: rules + }); + } + + public addAssociation(id: string, resourceArn: string) { + this.associations.push( + new CfnWebACLAssociation(this, id, { + webAclArn: this.acl.attrArn, + resourceArn + }) + ); + } +} \ No newline at end of file diff --git a/packages/graphql-mesh-server/package.json b/packages/graphql-mesh-server/package.json new file mode 100644 index 00000000..a2368821 --- /dev/null +++ b/packages/graphql-mesh-server/package.json @@ -0,0 +1,23 @@ +{ + "name": "@aligent/cdk-graphql-mesh-server", + "version": "0.0.1", + "description": "A construct to host Prerender in Fargate", + "main": "index.js", + "scripts": { + "build": "tsc", + "prepublish": "tsc" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/aligent/cdk-constructs.git" + }, + "license": "GPL-3.0-only", + "bugs": { + "url": "https://github.com/aligent/cdk-constructs/issues" + }, + "homepage": "https://github.com/aligent/cdk-constructs/tree/main/packages/prerender-fargate#readme", + "dependencies": { + "@types/yaml": "^1.9.7", + "yaml": "^2.3.1" + } +} diff --git a/packages/graphql-mesh-server/tsconfig.json b/packages/graphql-mesh-server/tsconfig.json new file mode 100644 index 00000000..4082f16a --- /dev/null +++ b/packages/graphql-mesh-server/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "../../tsconfig.json" +} From ad275fa0576c4949391ac8b2d619fc9759126e4e Mon Sep 17 00:00:00 2001 From: Daniel Van Der Ploeg Date: Tue, 29 Aug 2023 14:22:47 +0930 Subject: [PATCH 14/27] chore: update package name and homepage --- packages/graphql-mesh-server/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/graphql-mesh-server/package.json b/packages/graphql-mesh-server/package.json index a2368821..1e0ef0b7 100644 --- a/packages/graphql-mesh-server/package.json +++ b/packages/graphql-mesh-server/package.json @@ -1,7 +1,7 @@ { "name": "@aligent/cdk-graphql-mesh-server", "version": "0.0.1", - "description": "A construct to host Prerender in Fargate", + "description": "A construct to host Graphql Mesh in Fargate", "main": "index.js", "scripts": { "build": "tsc", @@ -15,7 +15,7 @@ "bugs": { "url": "https://github.com/aligent/cdk-constructs/issues" }, - "homepage": "https://github.com/aligent/cdk-constructs/tree/main/packages/prerender-fargate#readme", + "homepage": "https://github.com/aligent/cdk-constructs/tree/main/packages/graphql-mesh-server#readme", "dependencies": { "@types/yaml": "^1.9.7", "yaml": "^2.3.1" From 17457679fe82386cce2ebbd7dbcef31319dd646f Mon Sep 17 00:00:00 2001 From: Daniel Van Der Ploeg Date: Tue, 29 Aug 2023 14:32:18 +0930 Subject: [PATCH 15/27] chore: remove title from README --- README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/README.md b/README.md index e3934567..0ea9aeab 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,3 @@ When making a release (including experimental releases), the release tag should |---------------|---------------| | Experimental | 1.1.0-beta | | Final | 1.1.0 | - -## Testing locally - From 741a8394193b33280ccc86a4475dee5e5aa4b82c Mon Sep 17 00:00:00 2001 From: Adam Hall Date: Thu, 31 Aug 2023 14:07:07 +0930 Subject: [PATCH 16/27] Add missing buildspec for pipeline --- packages/graphql-mesh-server/assets/buildspec.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 packages/graphql-mesh-server/assets/buildspec.yml diff --git a/packages/graphql-mesh-server/assets/buildspec.yml b/packages/graphql-mesh-server/assets/buildspec.yml new file mode 100644 index 00000000..c2db9f73 --- /dev/null +++ b/packages/graphql-mesh-server/assets/buildspec.yml @@ -0,0 +1,10 @@ +version: 0.2 + +phases: + build: + commands: + - jq -n --arg image_uri $IMAGE_URI --arg container_name $CONTAINER_NAME '[{"name":"\($container_name)","imageUri":"\($image_uri)"}]' > imagedefinitions.json +artifacts: + files: + - 'imagedefinitions.json' + name: images-$(date +%Y-%m-%d) From 433283ee6b7a8d1852e31ef3505276f54430573b Mon Sep 17 00:00:00 2001 From: Adam Hall Date: Fri, 1 Sep 2023 11:10:20 +0930 Subject: [PATCH 17/27] Update connection strings to use tokens for attribute references as they are evaluating to null when using the toString() method --- packages/graphql-mesh-server/lib/fargate.ts | 6 +++--- packages/graphql-mesh-server/lib/redis-construct.ts | 12 ++++-------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/packages/graphql-mesh-server/lib/fargate.ts b/packages/graphql-mesh-server/lib/fargate.ts index 7a36cfb6..10081be1 100644 --- a/packages/graphql-mesh-server/lib/fargate.ts +++ b/packages/graphql-mesh-server/lib/fargate.ts @@ -1,5 +1,5 @@ import { Construct } from 'constructs'; -import { Duration } from 'aws-cdk-lib'; +import { Duration, Token } from 'aws-cdk-lib'; import { RemovalPolicy } from 'aws-cdk-lib'; import * as acm from 'aws-cdk-lib/aws-certificatemanager'; import * as ecs from 'aws-cdk-lib/aws-ecs'; @@ -129,11 +129,11 @@ export class MeshService extends Construct { if (props.redis) { props.redis.securityGroup.addIngressRule( securityGroup, - Port.tcp(Number(props.redis.connectionPort)) + Port.tcp(props.redis.connectionPort) ); environment['REDIS_ENDPOINT'] = props.redis.connectionEndPoint; - environment['REDIS_PORT'] = props.redis.connectionPort; + environment['REDIS_PORT'] = props.redis.connectionPort.toString(); } // Construct secrets from provided ssm values diff --git a/packages/graphql-mesh-server/lib/redis-construct.ts b/packages/graphql-mesh-server/lib/redis-construct.ts index a0319f43..f88526b0 100644 --- a/packages/graphql-mesh-server/lib/redis-construct.ts +++ b/packages/graphql-mesh-server/lib/redis-construct.ts @@ -4,7 +4,7 @@ import { CfnSubnetGroup, CfnParameterGroup, } from 'aws-cdk-lib/aws-elasticache'; -import { CfnOutput } from 'aws-cdk-lib'; +import { CfnOutput, Reference, Token } from 'aws-cdk-lib'; import { Construct } from 'constructs'; export interface RedisServiceProps { @@ -83,14 +83,10 @@ export class RedisService extends Construct { } public get connectionEndPoint(): string { - return this.cacheCluster - .getAtt('RedisEndpoint.Address') - .toString(); + return Token.asString(this.cacheCluster.getAtt('RedisEndpoint.Address')) } - public get connectionPort(): string { - return this.cacheCluster - .getAtt('RedisEndpoint.Port') - .toString(); + public get connectionPort(): number { + return Token.asNumber(this.cacheCluster.getAtt('RedisEndpoint.Port')); } } From e9d89914ec807a9b7ab48cc7a9458b384f75a63f Mon Sep 17 00:00:00 2001 From: Adam Hall Date: Fri, 13 Oct 2023 13:17:49 +1030 Subject: [PATCH 18/27] Bring dependencies inline --- package-lock.json | 42 +++++++++++++++++++++++ packages/graphql-mesh-server/package.json | 17 +++++++-- 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index bfc990fc..6d4adf6c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -42,6 +42,10 @@ "resolved": "packages/geoip-redirect", "link": true }, + "node_modules/@aligent/cdk-graphql-mesh-server": { + "resolved": "packages/graphql-mesh-server", + "link": true + }, "node_modules/@aligent/cdk-lambda-at-edge-handlers": { "resolved": "packages/lambda-at-edge-handlers", "link": true @@ -1876,6 +1880,15 @@ "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", "dev": true }, + "node_modules/@types/yaml": { + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@types/yaml/-/yaml-1.9.7.tgz", + "integrity": "sha512-8WMXRDD1D+wCohjfslHDgICd2JtMATZU8CkhH8LVJqcJs6dyYj5TGptzP8wApbmEullGBSsCEzzap73DQ1HJaA==", + "deprecated": "This is a stub types definition. yaml provides its own type definitions, so you do not need this installed.", + "dependencies": { + "yaml": "*" + } + }, "node_modules/@types/yargs": { "version": "17.0.25", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.25.tgz", @@ -5900,6 +5913,14 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, + "node_modules/yaml": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.2.tgz", + "integrity": "sha512-N/lyzTPaJasoDmfV7YTrYCI0G/3ivm/9wdG0aHuheKowWQwGTsK0Eoiw6utmzAnI6pkJa0DUVygvp3spqqEKXg==", + "engines": { + "node": ">= 14" + } + }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", @@ -6028,6 +6049,27 @@ "typescript": "~5.2.2" } }, + "packages/graphql-mesh-server": { + "version": "0.0.1", + "license": "GPL-3.0-only", + "dependencies": { + "@types/yaml": "^1.9.7", + "aws-cdk-lib": "2.97.0", + "constructs": "^10.0.0", + "source-map-support": "^0.5.21", + "yaml": "^2.3.1" + }, + "devDependencies": { + "@types/aws-lambda": "^8.10.122", + "@types/jest": "^29.5.5", + "@types/node": "20.6.3", + "aws-cdk": "2.97.0", + "jest": "^29.7.0", + "ts-jest": "^29.1.1", + "ts-node": "^10.9.1", + "typescript": "~5.2.2" + } + }, "packages/lambda-at-edge-handlers": { "name": "@aligent/cdk-lambda-at-edge-handlers", "version": "0.1.0", diff --git a/packages/graphql-mesh-server/package.json b/packages/graphql-mesh-server/package.json index 1e0ef0b7..bd3b73bd 100644 --- a/packages/graphql-mesh-server/package.json +++ b/packages/graphql-mesh-server/package.json @@ -15,9 +15,22 @@ "bugs": { "url": "https://github.com/aligent/cdk-constructs/issues" }, - "homepage": "https://github.com/aligent/cdk-constructs/tree/main/packages/graphql-mesh-server#readme", + "homepage": "https://github.com/aligent/cdk-constructs#readme", + "devDependencies": { + "@types/jest": "^29.5.5", + "@types/node": "20.6.3", + "@types/aws-lambda": "^8.10.122", + "aws-cdk": "2.97.0", + "jest": "^29.7.0", + "ts-jest": "^29.1.1", + "ts-node": "^10.9.1", + "typescript": "~5.2.2" + }, "dependencies": { "@types/yaml": "^1.9.7", - "yaml": "^2.3.1" + "yaml": "^2.3.1", + "aws-cdk-lib": "2.97.0", + "constructs": "^10.0.0", + "source-map-support": "^0.5.21" } } From 89d3898567dfe4047d9920642ae52c6458237265 Mon Sep 17 00:00:00 2001 From: Adam Hall Date: Fri, 13 Oct 2023 13:25:53 +1030 Subject: [PATCH 19/27] Move types to devDependencies --- package-lock.json | 4 +++- packages/graphql-mesh-server/package.json | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6d4adf6c..adc7dce3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1885,6 +1885,7 @@ "resolved": "https://registry.npmjs.org/@types/yaml/-/yaml-1.9.7.tgz", "integrity": "sha512-8WMXRDD1D+wCohjfslHDgICd2JtMATZU8CkhH8LVJqcJs6dyYj5TGptzP8wApbmEullGBSsCEzzap73DQ1HJaA==", "deprecated": "This is a stub types definition. yaml provides its own type definitions, so you do not need this installed.", + "dev": true, "dependencies": { "yaml": "*" } @@ -6050,10 +6051,10 @@ } }, "packages/graphql-mesh-server": { + "name": "@aligent/cdk-graphql-mesh-server", "version": "0.0.1", "license": "GPL-3.0-only", "dependencies": { - "@types/yaml": "^1.9.7", "aws-cdk-lib": "2.97.0", "constructs": "^10.0.0", "source-map-support": "^0.5.21", @@ -6063,6 +6064,7 @@ "@types/aws-lambda": "^8.10.122", "@types/jest": "^29.5.5", "@types/node": "20.6.3", + "@types/yaml": "^1.9.7", "aws-cdk": "2.97.0", "jest": "^29.7.0", "ts-jest": "^29.1.1", diff --git a/packages/graphql-mesh-server/package.json b/packages/graphql-mesh-server/package.json index bd3b73bd..b3a40c28 100644 --- a/packages/graphql-mesh-server/package.json +++ b/packages/graphql-mesh-server/package.json @@ -17,6 +17,7 @@ }, "homepage": "https://github.com/aligent/cdk-constructs#readme", "devDependencies": { + "@types/yaml": "^1.9.7", "@types/jest": "^29.5.5", "@types/node": "20.6.3", "@types/aws-lambda": "^8.10.122", @@ -27,7 +28,6 @@ "typescript": "~5.2.2" }, "dependencies": { - "@types/yaml": "^1.9.7", "yaml": "^2.3.1", "aws-cdk-lib": "2.97.0", "constructs": "^10.0.0", From 3e596957c9cd3c4f3b53fb5fe18f72c0a9ce8dd3 Mon Sep 17 00:00:00 2001 From: Adam Hall Date: Fri, 13 Oct 2023 13:28:14 +1030 Subject: [PATCH 20/27] Formatting pass --- packages/graphql-mesh-server/lib/fargate.ts | 427 +++++++++--------- .../lib/graphql-mesh-server.ts | 168 +++---- packages/graphql-mesh-server/lib/pipeline.ts | 157 +++---- .../lib/redis-construct.ts | 144 +++--- .../lib/web-application-firewall.ts | 282 ++++++------ 5 files changed, 594 insertions(+), 584 deletions(-) diff --git a/packages/graphql-mesh-server/lib/fargate.ts b/packages/graphql-mesh-server/lib/fargate.ts index 10081be1..b4a13e25 100644 --- a/packages/graphql-mesh-server/lib/fargate.ts +++ b/packages/graphql-mesh-server/lib/fargate.ts @@ -1,220 +1,221 @@ -import { Construct } from 'constructs'; -import { Duration, Token } from 'aws-cdk-lib'; -import { RemovalPolicy } from 'aws-cdk-lib'; -import * as acm from 'aws-cdk-lib/aws-certificatemanager'; -import * as ecs from 'aws-cdk-lib/aws-ecs'; -import * as ecr from 'aws-cdk-lib/aws-ecr'; -import * as ecsPatterns from 'aws-cdk-lib/aws-ecs-patterns'; -import * as iam from 'aws-cdk-lib/aws-iam'; -import * as ssm from 'aws-cdk-lib/aws-ssm'; -import * as auto_scaling from 'aws-cdk-lib/aws-autoscaling'; -import { Port, SecurityGroup, Vpc } from 'aws-cdk-lib/aws-ec2'; -import { RedisService } from './redis-construct'; -import { ManagedRule, Scope, WebApplicationFirewall } from './web-application-firewall'; +import { Construct } from "constructs"; +import { Duration, Token } from "aws-cdk-lib"; +import { RemovalPolicy } from "aws-cdk-lib"; +import * as acm from "aws-cdk-lib/aws-certificatemanager"; +import * as ecs from "aws-cdk-lib/aws-ecs"; +import * as ecr from "aws-cdk-lib/aws-ecr"; +import * as ecsPatterns from "aws-cdk-lib/aws-ecs-patterns"; +import * as iam from "aws-cdk-lib/aws-iam"; +import * as ssm from "aws-cdk-lib/aws-ssm"; +import * as auto_scaling from "aws-cdk-lib/aws-autoscaling"; +import { Port, SecurityGroup, Vpc } from "aws-cdk-lib/aws-ec2"; +import { RedisService } from "./redis-construct"; +import { + ManagedRule, + Scope, + WebApplicationFirewall, +} from "./web-application-firewall"; export interface MeshServiceProps { - /** - * VPC to attach Redis instance to - */ - vpc?: Vpc; - /** - * Repository to pull the container image from - */ - repository?: ecr.Repository; - /** - * ARN of the certificate to add to the load balancer - */ - certificateArn: string; - /** - * Minimum number of Fargate instances - */ - minCapacity?: number; - /** - * Maximum number of Fargate instances - */ - maxCapacity?: number; - /** - * Amount of vCPU per instance (default: 512) - */ - cpu?: number; - /** - * Amount of memory per instance (default: 1024) - */ - memory?: number; - /** - * Redis instance to use for mesh caching - */ - redis: RedisService; - /** - * SSM values to pass through to the container as secrets - */ - secrets?: {[key: string]: ssm.IStringParameter | ssm.IStringListParameter}; + /** + * VPC to attach Redis instance to + */ + vpc?: Vpc; + /** + * Repository to pull the container image from + */ + repository?: ecr.Repository; + /** + * ARN of the certificate to add to the load balancer + */ + certificateArn: string; + /** + * Minimum number of Fargate instances + */ + minCapacity?: number; + /** + * Maximum number of Fargate instances + */ + maxCapacity?: number; + /** + * Amount of vCPU per instance (default: 512) + */ + cpu?: number; + /** + * Amount of memory per instance (default: 1024) + */ + memory?: number; + /** + * Redis instance to use for mesh caching + */ + redis: RedisService; + /** + * SSM values to pass through to the container as secrets + */ + secrets?: { [key: string]: ssm.IStringParameter | ssm.IStringListParameter }; } export class MeshService extends Construct { - public readonly vpc: Vpc; - public readonly repository: ecr.Repository; - public readonly service: ecs.FargateService; - public readonly firewall: WebApplicationFirewall; - - constructor(scope: Construct, id: string, props: MeshServiceProps) { - super(scope, id); - - const certificate = acm.Certificate.fromCertificateArn( - this, - `certificate`, - props.certificateArn - ); - - this.vpc = - props.vpc || - new Vpc(this, 'vpc', { - natGateways: 1, - }); - - this.repository = - props.repository || - new ecr.Repository(this, 'repo', { - removalPolicy: RemovalPolicy.DESTROY, - autoDeleteImages: true, - }); - - if (!props.repository) { - // Delete all images older than 90 days BUT keep 10 from the latest tag - this.repository.addLifecycleRule({ - tagPrefixList: ['latest'], - maxImageCount: 10, - }); - this.repository.addLifecycleRule({ - maxImageAge: Duration.days(90), - }); - } - - // Create a deploy user to push images to ECR - const deployUser = new iam.User(this, 'deploy-user'); - - const deployPolicy = new iam.Policy(this, 'deploy-policy'); - deployPolicy.addStatements( - new iam.PolicyStatement({ - effect: iam.Effect.ALLOW, - actions: [ - 'ecr:CompleteLayerUpload', - 'ecr:UploadLayerPart', - 'ecr:InitiateLayerUpload', - 'ecr:BatchCheckLayerAvailability', - 'ecr:PutImage', - ], - resources: [this.repository.repositoryArn], - }), - new iam.PolicyStatement({ - effect: iam.Effect.ALLOW, - actions: ['ecr:GetAuthorizationToken'], - resources: ['*'], - }) - ); - - deployUser.attachInlinePolicy(deployPolicy); - - const securityGroup = new SecurityGroup(this, 'security-group', { - vpc: this.vpc, - }); - - const cluster = new ecs.Cluster(this, `cluster`, { - vpc: this.vpc, - }); - - const environment: { [key: string]: string } = {}; - - // If using Redis configure security group and pass connection string to container - if (props.redis) { - props.redis.securityGroup.addIngressRule( - securityGroup, - Port.tcp(props.redis.connectionPort) - ); - - environment['REDIS_ENDPOINT'] = props.redis.connectionEndPoint; - environment['REDIS_PORT'] = props.redis.connectionPort.toString(); - } - - // Construct secrets from provided ssm values - const secrets: {[key: string]: ecs.Secret} = {}; - props.secrets = props.secrets || {}; - for (const [key, ssm] of Object.entries(props.secrets)) { - secrets[key] = ecs.Secret.fromSsmParameter(ssm); - } - // Create a load-balanced Fargate service and make it public - const fargateService = - new ecsPatterns.ApplicationLoadBalancedFargateService( - this, - `fargate`, - { - cluster, - certificate, - enableExecuteCommand: true, - cpu: props.cpu || 512, // 0.5 vCPU - memoryLimitMiB: props.memory || 1024, // 1 GB - taskImageOptions: { - image: ecs.ContainerImage.fromEcrRepository( - this.repository - ), - enableLogging: true, // default - containerPort: 4000, // graphql mesh gateway port - secrets: secrets, - environment: environment, - }, - publicLoadBalancer: true, // default, - taskSubnets: { - subnets: [...this.vpc.privateSubnets], - }, - securityGroups: [securityGroup], - } - ); - - this.service = fargateService.service; - - this.firewall = new WebApplicationFirewall(this, 'waf', { - scope: Scope.REGIONAL, - visibilityConfig: { - cloudWatchMetricsEnabled: true, - metricName: "firewall-request", - sampledRequestsEnabled: true - }, - managedRules: [ - { - name: ManagedRule.COMMON_RULE_SET, - excludedRules: [ - { - name: 'SizeRestrictions_QUERYSTRING' - } - ] - }, - { - name: ManagedRule.KNOWN_BAD_INPUTS_RULE_SET, - } - ] - }); - - this.firewall.addAssociation('loadbalancer-association', fargateService.loadBalancer.loadBalancerArn); - - fargateService.targetGroup.configureHealthCheck({ - path: '/healthcheck', - }); - - // Setup auto scaling policy - const scaling = fargateService.service.autoScaleTaskCount({ - minCapacity: props.minCapacity || 1, - maxCapacity: props.maxCapacity || 5, - }); - - const cpuUtilization = fargateService.service.metricCpuUtilization(); - scaling.scaleOnMetric('auto-scale-cpu', { - metric: cpuUtilization, - scalingSteps: [ - { upper: 30, change: -1 }, - { lower: 50, change: +1 }, - { lower: 85, change: +3 }, - ], - adjustmentType: auto_scaling.AdjustmentType.CHANGE_IN_CAPACITY, - }); + public readonly vpc: Vpc; + public readonly repository: ecr.Repository; + public readonly service: ecs.FargateService; + public readonly firewall: WebApplicationFirewall; + + constructor(scope: Construct, id: string, props: MeshServiceProps) { + super(scope, id); + + const certificate = acm.Certificate.fromCertificateArn( + this, + `certificate`, + props.certificateArn + ); + + this.vpc = + props.vpc || + new Vpc(this, "vpc", { + natGateways: 1, + }); + + this.repository = + props.repository || + new ecr.Repository(this, "repo", { + removalPolicy: RemovalPolicy.DESTROY, + autoDeleteImages: true, + }); + + if (!props.repository) { + // Delete all images older than 90 days BUT keep 10 from the latest tag + this.repository.addLifecycleRule({ + tagPrefixList: ["latest"], + maxImageCount: 10, + }); + this.repository.addLifecycleRule({ + maxImageAge: Duration.days(90), + }); + } + + // Create a deploy user to push images to ECR + const deployUser = new iam.User(this, "deploy-user"); + + const deployPolicy = new iam.Policy(this, "deploy-policy"); + deployPolicy.addStatements( + new iam.PolicyStatement({ + effect: iam.Effect.ALLOW, + actions: [ + "ecr:CompleteLayerUpload", + "ecr:UploadLayerPart", + "ecr:InitiateLayerUpload", + "ecr:BatchCheckLayerAvailability", + "ecr:PutImage", + ], + resources: [this.repository.repositoryArn], + }), + new iam.PolicyStatement({ + effect: iam.Effect.ALLOW, + actions: ["ecr:GetAuthorizationToken"], + resources: ["*"], + }) + ); + + deployUser.attachInlinePolicy(deployPolicy); + + const securityGroup = new SecurityGroup(this, "security-group", { + vpc: this.vpc, + }); + + const cluster = new ecs.Cluster(this, `cluster`, { + vpc: this.vpc, + }); + + const environment: { [key: string]: string } = {}; + + // If using Redis configure security group and pass connection string to container + if (props.redis) { + props.redis.securityGroup.addIngressRule( + securityGroup, + Port.tcp(props.redis.connectionPort) + ); + + environment["REDIS_ENDPOINT"] = props.redis.connectionEndPoint; + environment["REDIS_PORT"] = props.redis.connectionPort.toString(); } + + // Construct secrets from provided ssm values + const secrets: { [key: string]: ecs.Secret } = {}; + props.secrets = props.secrets || {}; + for (const [key, ssm] of Object.entries(props.secrets)) { + secrets[key] = ecs.Secret.fromSsmParameter(ssm); + } + // Create a load-balanced Fargate service and make it public + const fargateService = + new ecsPatterns.ApplicationLoadBalancedFargateService(this, `fargate`, { + cluster, + certificate, + enableExecuteCommand: true, + cpu: props.cpu || 512, // 0.5 vCPU + memoryLimitMiB: props.memory || 1024, // 1 GB + taskImageOptions: { + image: ecs.ContainerImage.fromEcrRepository(this.repository), + enableLogging: true, // default + containerPort: 4000, // graphql mesh gateway port + secrets: secrets, + environment: environment, + }, + publicLoadBalancer: true, // default, + taskSubnets: { + subnets: [...this.vpc.privateSubnets], + }, + securityGroups: [securityGroup], + }); + + this.service = fargateService.service; + + this.firewall = new WebApplicationFirewall(this, "waf", { + scope: Scope.REGIONAL, + visibilityConfig: { + cloudWatchMetricsEnabled: true, + metricName: "firewall-request", + sampledRequestsEnabled: true, + }, + managedRules: [ + { + name: ManagedRule.COMMON_RULE_SET, + excludedRules: [ + { + name: "SizeRestrictions_QUERYSTRING", + }, + ], + }, + { + name: ManagedRule.KNOWN_BAD_INPUTS_RULE_SET, + }, + ], + }); + + this.firewall.addAssociation( + "loadbalancer-association", + fargateService.loadBalancer.loadBalancerArn + ); + + fargateService.targetGroup.configureHealthCheck({ + path: "/healthcheck", + }); + + // Setup auto scaling policy + const scaling = fargateService.service.autoScaleTaskCount({ + minCapacity: props.minCapacity || 1, + maxCapacity: props.maxCapacity || 5, + }); + + const cpuUtilization = fargateService.service.metricCpuUtilization(); + scaling.scaleOnMetric("auto-scale-cpu", { + metric: cpuUtilization, + scalingSteps: [ + { upper: 30, change: -1 }, + { lower: 50, change: +1 }, + { lower: 85, change: +3 }, + ], + adjustmentType: auto_scaling.AdjustmentType.CHANGE_IN_CAPACITY, + }); + } } diff --git a/packages/graphql-mesh-server/lib/graphql-mesh-server.ts b/packages/graphql-mesh-server/lib/graphql-mesh-server.ts index cec04774..399c2457 100644 --- a/packages/graphql-mesh-server/lib/graphql-mesh-server.ts +++ b/packages/graphql-mesh-server/lib/graphql-mesh-server.ts @@ -1,95 +1,99 @@ -import { Construct } from 'constructs'; -import { MeshService, MeshServiceProps } from './fargate'; -import { RedisService, RedisServiceProps } from './redis-construct'; -import { CodePipelineService } from './pipeline'; -import { SecurityGroup, Vpc } from 'aws-cdk-lib/aws-ec2'; -import { Repository } from 'aws-cdk-lib/aws-ecr'; -import { FargateService } from 'aws-cdk-lib/aws-ecs'; -import { CfnCacheCluster } from 'aws-cdk-lib/aws-elasticache'; -import * as ssm from 'aws-cdk-lib/aws-ssm'; +import { Construct } from "constructs"; +import { MeshService, MeshServiceProps } from "./fargate"; +import { RedisService, RedisServiceProps } from "./redis-construct"; +import { CodePipelineService } from "./pipeline"; +import { SecurityGroup, Vpc } from "aws-cdk-lib/aws-ec2"; +import { Repository } from "aws-cdk-lib/aws-ecr"; +import { FargateService } from "aws-cdk-lib/aws-ecs"; +import { CfnCacheCluster } from "aws-cdk-lib/aws-elasticache"; +import * as ssm from "aws-cdk-lib/aws-ssm"; export type MeshHostingProps = { - /** - * VPC to attach Redis and Fargate instances to (default: create a vpc) - */ - vpc?: Vpc; - /** - * If no VPC is provided create one with this name (default: 'graphql-server-vpc') - */ - vpcName?: string; - /** - * Cache node type (default: 'cache.t2.micro') - */ - cacheNodeType?: string; - /** - * Repository to pull the container image from - */ - repository?: Repository; - /** - * ARN of the certificate to add to the load balancer - */ - certificateArn: string; - /** - * Minimum number of Fargate instances - */ - minCapacity?: number; - /** - * Maximum number of Fargate instances - */ - maxCapacity?: number; - /** - * Amount of vCPU per Fargate instance (default: 512) - */ - cpu?: number; - /** - * Amount of memory per Fargate instance (default: 1024) - */ - memory?: number; - /** - * Redis instance to use for mesh caching - */ - redis?: RedisService; - /** - * SSM values to pass through to the container as secrets - */ - secrets?: {[key: string]: ssm.IStringParameter | ssm.IStringListParameter}; + /** + * VPC to attach Redis and Fargate instances to (default: create a vpc) + */ + vpc?: Vpc; + /** + * If no VPC is provided create one with this name (default: 'graphql-server-vpc') + */ + vpcName?: string; + /** + * Cache node type (default: 'cache.t2.micro') + */ + cacheNodeType?: string; + /** + * Repository to pull the container image from + */ + repository?: Repository; + /** + * ARN of the certificate to add to the load balancer + */ + certificateArn: string; + /** + * Minimum number of Fargate instances + */ + minCapacity?: number; + /** + * Maximum number of Fargate instances + */ + maxCapacity?: number; + /** + * Amount of vCPU per Fargate instance (default: 512) + */ + cpu?: number; + /** + * Amount of memory per Fargate instance (default: 1024) + */ + memory?: number; + /** + * Redis instance to use for mesh caching + */ + redis?: RedisService; + /** + * SSM values to pass through to the container as secrets + */ + secrets?: { [key: string]: ssm.IStringParameter | ssm.IStringListParameter }; }; export class MeshHosting extends Construct { - public readonly vpc: Vpc; - public readonly repository: Repository; - public readonly service: FargateService; - public readonly cacheCluster: CfnCacheCluster; - public readonly securityGroup: SecurityGroup; + public readonly vpc: Vpc; + public readonly repository: Repository; + public readonly service: FargateService; + public readonly cacheCluster: CfnCacheCluster; + public readonly securityGroup: SecurityGroup; - constructor(scope: Construct, id: string, props: MeshHostingProps) { - super(scope, id); + constructor(scope: Construct, id: string, props: MeshHostingProps) { + super(scope, id); - this.vpc = props.vpc || new Vpc(this, 'graphql-server-vpc', { - vpcName: props.vpcName || 'graphql-server-vpc', - natGateways: 1 - }); + this.vpc = + props.vpc || + new Vpc(this, "graphql-server-vpc", { + vpcName: props.vpcName || "graphql-server-vpc", + natGateways: 1, + }); - const redis = props.redis || new RedisService(this, 'redis', { - ...props, - vpc: this.vpc - }); + const redis = + props.redis || + new RedisService(this, "redis", { + ...props, + vpc: this.vpc, + }); - this.cacheCluster = redis.cacheCluster; - this.securityGroup = redis.securityGroup; + this.cacheCluster = redis.cacheCluster; + this.securityGroup = redis.securityGroup; - const mesh = new MeshService(this, 'mesh', { - ...props, - vpc: this.vpc, - redis, - }); + const mesh = new MeshService(this, "mesh", { + ...props, + vpc: this.vpc, + redis, + }); - this.service = mesh.service; - this.repository = mesh.repository; + this.service = mesh.service; + this.repository = mesh.repository; - new CodePipelineService(this, 'pipeline', { - repository: this.repository, - service: this.service, - }); - } + new CodePipelineService(this, "pipeline", { + repository: this.repository, + service: this.service, + }); + } } diff --git a/packages/graphql-mesh-server/lib/pipeline.ts b/packages/graphql-mesh-server/lib/pipeline.ts index a6189049..a4e7c7c6 100644 --- a/packages/graphql-mesh-server/lib/pipeline.ts +++ b/packages/graphql-mesh-server/lib/pipeline.ts @@ -1,91 +1,94 @@ -import { Duration } from 'aws-cdk-lib'; -import { Artifact, Pipeline } from 'aws-cdk-lib/aws-codepipeline'; -import { Repository } from 'aws-cdk-lib/aws-ecr'; -import { FargateService } from 'aws-cdk-lib/aws-ecs'; -import * as pipe_actions from 'aws-cdk-lib/aws-codepipeline-actions'; -import * as codebuild from 'aws-cdk-lib/aws-codebuild'; -import { Construct } from 'constructs'; -import * as fs from 'fs'; -import * as path from 'path'; -import * as YAML from 'yaml'; +import { Duration } from "aws-cdk-lib"; +import { Artifact, Pipeline } from "aws-cdk-lib/aws-codepipeline"; +import { Repository } from "aws-cdk-lib/aws-ecr"; +import { FargateService } from "aws-cdk-lib/aws-ecs"; +import * as pipe_actions from "aws-cdk-lib/aws-codepipeline-actions"; +import * as codebuild from "aws-cdk-lib/aws-codebuild"; +import { Construct } from "constructs"; +import * as fs from "fs"; +import * as path from "path"; +import * as YAML from "yaml"; export interface CodePipelineServiceProps { - /** - * Repository the code container is pushed too - */ - repository: Repository; + /** + * Repository the code container is pushed too + */ + repository: Repository; - /** - * Services to deploy Code container updates to - */ - service: FargateService; + /** + * Services to deploy Code container updates to + */ + service: FargateService; - /** - * Path to buildspec.yml (default: '../assets/buildspec.yml') - */ - buildspecPath?: string; + /** + * Path to buildspec.yml (default: '../assets/buildspec.yml') + */ + buildspecPath?: string; } export class CodePipelineService extends Construct { - public readonly pipeline: Pipeline; + public readonly pipeline: Pipeline; - constructor(scope: Construct, id: string, props: CodePipelineServiceProps) { - super(scope, id); + constructor(scope: Construct, id: string, props: CodePipelineServiceProps) { + super(scope, id); - this.pipeline = new Pipeline(this, 'deploy-pipeline'); + this.pipeline = new Pipeline(this, "deploy-pipeline"); - const sourceOutput = new Artifact(); - const sourceAction = new pipe_actions.EcrSourceAction({ - actionName: 'ECR', - repository: props.repository, - output: sourceOutput, - }); + const sourceOutput = new Artifact(); + const sourceAction = new pipe_actions.EcrSourceAction({ + actionName: "ECR", + repository: props.repository, + output: sourceOutput, + }); - this.pipeline.addStage({ - stageName: 'Source', - actions: [sourceAction], - }); + this.pipeline.addStage({ + stageName: "Source", + actions: [sourceAction], + }); - const file = fs.readFileSync( - path.resolve(__dirname, props.buildspecPath || '../assets/buildspec.yml'), - 'utf8' - ); - const project: codebuild.PipelineProject = - new codebuild.PipelineProject(this, 'project', { - buildSpec: codebuild.BuildSpec.fromObject(YAML.parse(file)), - }); + const file = fs.readFileSync( + path.resolve(__dirname, props.buildspecPath || "../assets/buildspec.yml"), + "utf8" + ); + const project: codebuild.PipelineProject = new codebuild.PipelineProject( + this, + "project", + { + buildSpec: codebuild.BuildSpec.fromObject(YAML.parse(file)), + } + ); - const buildOutput = new Artifact(); - this.pipeline.addStage({ - stageName: 'Build', - actions: [ - new pipe_actions.CodeBuildAction({ - actionName: 'CodeBuild', - project, - input: sourceOutput, - outputs: [buildOutput], - environmentVariables: { - IMAGE_URI: { - value: sourceAction.variables.imageUri, - }, - CONTAINER_NAME: { - value: props.service.taskDefinition.defaultContainer - ?.containerName, - }, - }, - }), - ], - }); - this.pipeline.addStage({ - stageName: 'Deploy', - actions: [ - new pipe_actions.EcsDeployAction({ - actionName: 'DeployAction', - service: props.service, - input: buildOutput, - deploymentTimeout: Duration.minutes(10), - }), - ], - }); - } + const buildOutput = new Artifact(); + this.pipeline.addStage({ + stageName: "Build", + actions: [ + new pipe_actions.CodeBuildAction({ + actionName: "CodeBuild", + project, + input: sourceOutput, + outputs: [buildOutput], + environmentVariables: { + IMAGE_URI: { + value: sourceAction.variables.imageUri, + }, + CONTAINER_NAME: { + value: + props.service.taskDefinition.defaultContainer?.containerName, + }, + }, + }), + ], + }); + this.pipeline.addStage({ + stageName: "Deploy", + actions: [ + new pipe_actions.EcsDeployAction({ + actionName: "DeployAction", + service: props.service, + input: buildOutput, + deploymentTimeout: Duration.minutes(10), + }), + ], + }); + } } diff --git a/packages/graphql-mesh-server/lib/redis-construct.ts b/packages/graphql-mesh-server/lib/redis-construct.ts index f88526b0..5a9ba5b0 100644 --- a/packages/graphql-mesh-server/lib/redis-construct.ts +++ b/packages/graphql-mesh-server/lib/redis-construct.ts @@ -1,92 +1,90 @@ -import { SecurityGroup, Vpc } from 'aws-cdk-lib/aws-ec2'; +import { SecurityGroup, Vpc } from "aws-cdk-lib/aws-ec2"; import { - CfnCacheCluster, - CfnSubnetGroup, - CfnParameterGroup, -} from 'aws-cdk-lib/aws-elasticache'; -import { CfnOutput, Reference, Token } from 'aws-cdk-lib'; -import { Construct } from 'constructs'; + CfnCacheCluster, + CfnSubnetGroup, + CfnParameterGroup, +} from "aws-cdk-lib/aws-elasticache"; +import { CfnOutput, Reference, Token } from "aws-cdk-lib"; +import { Construct } from "constructs"; export interface RedisServiceProps { - /** - * VPC to attach Redis instance to - */ - vpc: Vpc; - /** - * Cache node type (default: 'cache.t2.micro') - */ - cacheNodeType?: string; + /** + * VPC to attach Redis instance to + */ + vpc: Vpc; + /** + * Cache node type (default: 'cache.t2.micro') + */ + cacheNodeType?: string; } export class RedisService extends Construct { - public readonly cacheCluster: CfnCacheCluster; - public readonly vpc: Vpc; - public readonly securityGroup: SecurityGroup; + public readonly cacheCluster: CfnCacheCluster; + public readonly vpc: Vpc; + public readonly securityGroup: SecurityGroup; - constructor(scope: Construct, id: string, props: RedisServiceProps) { - super(scope, id); + constructor(scope: Construct, id: string, props: RedisServiceProps) { + super(scope, id); - this.vpc = props.vpc; + this.vpc = props.vpc; - this.securityGroup = new SecurityGroup(this, 'RedisSecurityGroup', { - vpc: this.vpc, - }); + this.securityGroup = new SecurityGroup(this, "RedisSecurityGroup", { + vpc: this.vpc, + }); - const privateSubnets: string[] = this.vpc.privateSubnets.map( - (subnet) => { - return subnet.subnetId; - } - ); + const privateSubnets: string[] = this.vpc.privateSubnets.map(subnet => { + return subnet.subnetId; + }); - const cacheSubnetGroup = new CfnSubnetGroup(this, 'CacheSubnetGroup', { - description: 'Subnet Group for Mesh Cache', - subnetIds: privateSubnets, - }); + const cacheSubnetGroup = new CfnSubnetGroup(this, "CacheSubnetGroup", { + description: "Subnet Group for Mesh Cache", + subnetIds: privateSubnets, + }); - const cacheParameterGroup = new CfnParameterGroup( - this, - 'CacheParameterGroup', - { - cacheParameterGroupFamily: 'redis7', - description: 'Parameter Group for Mesh Cache', - properties: { - 'maxmemory-policy': 'allkeys-lru', - }, - } - ); + const cacheParameterGroup = new CfnParameterGroup( + this, + "CacheParameterGroup", + { + cacheParameterGroupFamily: "redis7", + description: "Parameter Group for Mesh Cache", + properties: { + "maxmemory-policy": "allkeys-lru", + }, + } + ); - this.cacheCluster = new CfnCacheCluster(this, 'cache-cluster', { - cacheNodeType: props.cacheNodeType || 'cache.t2.micro', - engine: 'redis', - numCacheNodes: 1, - autoMinorVersionUpgrade: true, - vpcSecurityGroupIds: [this.securityGroup.securityGroupId], - cacheSubnetGroupName: cacheSubnetGroup.ref, - cacheParameterGroupName: cacheParameterGroup.ref, - }); + this.cacheCluster = new CfnCacheCluster(this, "cache-cluster", { + cacheNodeType: props.cacheNodeType || "cache.t2.micro", + engine: "redis", + numCacheNodes: 1, + autoMinorVersionUpgrade: true, + vpcSecurityGroupIds: [this.securityGroup.securityGroupId], + cacheSubnetGroupName: cacheSubnetGroup.ref, + cacheParameterGroupName: cacheParameterGroup.ref, + }); - this.cacheCluster.addDependency(cacheParameterGroup); - this.cacheCluster.addDependency(cacheSubnetGroup); + this.cacheCluster.addDependency(cacheParameterGroup); + this.cacheCluster.addDependency(cacheSubnetGroup); - new CfnOutput(this, 'RedisConnectionString', { - description: 'RedisConnectionString', - value: this.cacheConnectionString, - }); - } + new CfnOutput(this, "RedisConnectionString", { + description: "RedisConnectionString", + value: this.cacheConnectionString, + }); + } - public get cacheConnectionString(): string { - return `redis://${this.cacheCluster - .getAtt('RedisEndpoint.Address') - .toString()}:${this.cacheCluster - .getAtt('RedisEndpoint.Port') - .toString()}`; - } + public get cacheConnectionString(): string { + return `redis://${this.cacheCluster + .getAtt("RedisEndpoint.Address") + .toString()}:${this.cacheCluster + .getAtt("RedisEndpoint.Port") + .toString()}`; + } - public get connectionEndPoint(): string { - return Token.asString(this.cacheCluster.getAtt('RedisEndpoint.Address')) - } + public get connectionEndPoint(): string { + return Token.asString(this.cacheCluster.getAtt("RedisEndpoint.Address")); + } - public get connectionPort(): number { - return Token.asNumber(this.cacheCluster.getAtt('RedisEndpoint.Port')); - } + public get connectionPort(): number { + return Token.asNumber(this.cacheCluster.getAtt("RedisEndpoint.Port")); + } } diff --git a/packages/graphql-mesh-server/lib/web-application-firewall.ts b/packages/graphql-mesh-server/lib/web-application-firewall.ts index 57e3c6ce..98837990 100644 --- a/packages/graphql-mesh-server/lib/web-application-firewall.ts +++ b/packages/graphql-mesh-server/lib/web-application-firewall.ts @@ -2,163 +2,167 @@ import { CfnWebACL, CfnWebACLAssociation } from "aws-cdk-lib/aws-wafv2"; import { Construct } from "constructs"; export enum Action { - BLOCK = 'BLOCK', - ALLOW = 'ALLOW', + BLOCK = "BLOCK", + ALLOW = "ALLOW", } export enum Scope { - CLOUDFRONT = 'CLOUDFRONT', - REGIONAL = 'REGIONAL', + CLOUDFRONT = "CLOUDFRONT", + REGIONAL = "REGIONAL", } export enum ManagedRule { - BOT_CONTROL_RULE_SET = "AWSManagedRulesBotControlRuleSet", - KNOWN_BAD_INPUTS_RULE_SET = "AWSManagedRulesKnownBadInputsRuleSet", - COMMON_RULE_SET = "AWSManagedRulesCommonRuleSet", - ANNONYMOUS_IP_LIST = "AWSManagedRulesAnonymousIpList", - AMAZON_IP_REPUTATION_LIST = "AWSManagedRulesAmazonIpReputationList", - ADMIN_PROTECTION_RULE_SET = "AWSManagedRulesAdminProtectionRuleSet", - SQLI_RULE_SET = "AWSManagedRulesSQLiRuleSet", - PHP_RULE_SET = "AWSManagedRulesPHPRuleSet" + BOT_CONTROL_RULE_SET = "AWSManagedRulesBotControlRuleSet", + KNOWN_BAD_INPUTS_RULE_SET = "AWSManagedRulesKnownBadInputsRuleSet", + COMMON_RULE_SET = "AWSManagedRulesCommonRuleSet", + ANNONYMOUS_IP_LIST = "AWSManagedRulesAnonymousIpList", + AMAZON_IP_REPUTATION_LIST = "AWSManagedRulesAmazonIpReputationList", + ADMIN_PROTECTION_RULE_SET = "AWSManagedRulesAdminProtectionRuleSet", + SQLI_RULE_SET = "AWSManagedRulesSQLiRuleSet", + PHP_RULE_SET = "AWSManagedRulesPHPRuleSet", } export interface VisibilityConfig { - /** - * Whether cloudwatch metrics are enabled or nor - */ - cloudWatchMetricsEnabled: boolean, - - /** - * Name of the metric in cloudwatch - */ - metricName: string, - - /** - * Whether to keep samples of blocked requests - */ - sampledRequestsEnabled: boolean + /** + * Whether cloudwatch metrics are enabled or nor + */ + cloudWatchMetricsEnabled: boolean; + + /** + * Name of the metric in cloudwatch + */ + metricName: string; + + /** + * Whether to keep samples of blocked requests + */ + sampledRequestsEnabled: boolean; } export interface AWSManagedRule { - /** - * Which AWS Rule to add - */ - name: ManagedRule, - - /** - * @default to the name property - */ - metricName?: string, - - /** - * @default false - */ - sampledRequestsEnabled?: boolean, - - /** - * Any rules from this ruleset you wish to disable/exclude - */ - excludedRules?: Array<{ - name: string - }>, - - /** - * Whether to override the default action to COUNT - */ - count?: boolean + /** + * Which AWS Rule to add + */ + name: ManagedRule; + + /** + * @default to the name property + */ + metricName?: string; + + /** + * @default false + */ + sampledRequestsEnabled?: boolean; + + /** + * Any rules from this ruleset you wish to disable/exclude + */ + excludedRules?: Array<{ + name: string; + }>; + + /** + * Whether to override the default action to COUNT + */ + count?: boolean; } export interface WebApplicationFirewallProps { - /** - * Name of the WAF - */ - name?: string, - - /** - * The action to perform if none of the `Rules` contained in the `WebACL` match. - * @default Action.ALLOW - */ - defaultAction?: Action, - - /** - * Specifies whether this is for an Amazon CloudFront distribution or for a regional application. - * @default Scope.REGIONAL - */ - scope?: Scope - - /** - * Default visibility configuration - */ - visibilityConfig: VisibilityConfig, - - /** - * List of AWS Managed rules to add to the WAF - */ - managedRules?: AWSManagedRule[], - - /** - * List of custom rules - */ - rules?: CfnWebACL.RuleProperty[] + /** + * Name of the WAF + */ + name?: string; + + /** + * The action to perform if none of the `Rules` contained in the `WebACL` match. + * @default Action.ALLOW + */ + defaultAction?: Action; + + /** + * Specifies whether this is for an Amazon CloudFront distribution or for a regional application. + * @default Scope.REGIONAL + */ + scope?: Scope; + + /** + * Default visibility configuration + */ + visibilityConfig: VisibilityConfig; + + /** + * List of AWS Managed rules to add to the WAF + */ + managedRules?: AWSManagedRule[]; + + /** + * List of custom rules + */ + rules?: CfnWebACL.RuleProperty[]; } export class WebApplicationFirewall extends Construct { - readonly acl: CfnWebACL; - readonly associations: CfnWebACLAssociation[]; - - constructor(scope: Construct, id: string, props: WebApplicationFirewallProps) { - super(scope, id); - - let defaultAction: CfnWebACL.DefaultActionProperty = { allow: {} }; - - if (props.defaultAction == Action.BLOCK) { - defaultAction = { block: {} }; - } - - this.associations = []; - - const rules: CfnWebACL.RuleProperty[] = props.rules || []; - - // Convert from our AWSManagedRule type to a CfnWebACL.RuleProperty - if (props.managedRules) { - props.managedRules.forEach((rule, index) => { - rules.push({ - name: rule.name, - priority: index, - visibilityConfig: { - // if no metric name is passed then don't enable metrics - cloudWatchMetricsEnabled: rule.metricName ? true : false, - // Default to the rule name if a metric name isn't passed - metricName: rule.metricName || rule.name, - sampledRequestsEnabled: rule.sampledRequestsEnabled || false - }, - statement: { - managedRuleGroupStatement: { - name: rule.name, - vendorName: "AWS", - excludedRules: rule.excludedRules || [], - } - }, - overrideAction: rule.count ? { count: {} } : { none: {} } - }) - }); - } - - this.acl = new CfnWebACL(this, "WebAcl", { - name: props.name, - defaultAction, - scope: props.scope || Scope.REGIONAL, - visibilityConfig: props.visibilityConfig, - rules: rules - }); + readonly acl: CfnWebACL; + readonly associations: CfnWebACLAssociation[]; + + constructor( + scope: Construct, + id: string, + props: WebApplicationFirewallProps + ) { + super(scope, id); + + let defaultAction: CfnWebACL.DefaultActionProperty = { allow: {} }; + + if (props.defaultAction == Action.BLOCK) { + defaultAction = { block: {} }; } - public addAssociation(id: string, resourceArn: string) { - this.associations.push( - new CfnWebACLAssociation(this, id, { - webAclArn: this.acl.attrArn, - resourceArn - }) - ); + this.associations = []; + + const rules: CfnWebACL.RuleProperty[] = props.rules || []; + + // Convert from our AWSManagedRule type to a CfnWebACL.RuleProperty + if (props.managedRules) { + props.managedRules.forEach((rule, index) => { + rules.push({ + name: rule.name, + priority: index, + visibilityConfig: { + // if no metric name is passed then don't enable metrics + cloudWatchMetricsEnabled: rule.metricName ? true : false, + // Default to the rule name if a metric name isn't passed + metricName: rule.metricName || rule.name, + sampledRequestsEnabled: rule.sampledRequestsEnabled || false, + }, + statement: { + managedRuleGroupStatement: { + name: rule.name, + vendorName: "AWS", + excludedRules: rule.excludedRules || [], + }, + }, + overrideAction: rule.count ? { count: {} } : { none: {} }, + }); + }); } -} \ No newline at end of file + + this.acl = new CfnWebACL(this, "WebAcl", { + name: props.name, + defaultAction, + scope: props.scope || Scope.REGIONAL, + visibilityConfig: props.visibilityConfig, + rules: rules, + }); + } + + public addAssociation(id: string, resourceArn: string) { + this.associations.push( + new CfnWebACLAssociation(this, id, { + webAclArn: this.acl.attrArn, + resourceArn, + }) + ); + } +} From dde62e4506f4dfd464035ededf8f4f394c36b3ed Mon Sep 17 00:00:00 2001 From: Adam Hall Date: Fri, 13 Oct 2023 14:02:03 +1030 Subject: [PATCH 21/27] Switch to use IVpc so we can import vpc from attributes and add optional redis database config and env var so we can share redis clusters between mesh instances. --- packages/graphql-mesh-server/lib/fargate.ts | 24 +++++++++++-------- .../lib/graphql-mesh-server.ts | 24 ++++++++++++------- .../lib/redis-construct.ts | 6 ++--- 3 files changed, 32 insertions(+), 22 deletions(-) diff --git a/packages/graphql-mesh-server/lib/fargate.ts b/packages/graphql-mesh-server/lib/fargate.ts index b4a13e25..0fef4854 100644 --- a/packages/graphql-mesh-server/lib/fargate.ts +++ b/packages/graphql-mesh-server/lib/fargate.ts @@ -1,5 +1,5 @@ import { Construct } from "constructs"; -import { Duration, Token } from "aws-cdk-lib"; +import { Duration } from "aws-cdk-lib"; import { RemovalPolicy } from "aws-cdk-lib"; import * as acm from "aws-cdk-lib/aws-certificatemanager"; import * as ecs from "aws-cdk-lib/aws-ecs"; @@ -8,7 +8,7 @@ import * as ecsPatterns from "aws-cdk-lib/aws-ecs-patterns"; import * as iam from "aws-cdk-lib/aws-iam"; import * as ssm from "aws-cdk-lib/aws-ssm"; import * as auto_scaling from "aws-cdk-lib/aws-autoscaling"; -import { Port, SecurityGroup, Vpc } from "aws-cdk-lib/aws-ec2"; +import { Port, SecurityGroup, IVpc, Vpc } from "aws-cdk-lib/aws-ec2"; import { RedisService } from "./redis-construct"; import { ManagedRule, @@ -20,7 +20,7 @@ export interface MeshServiceProps { /** * VPC to attach Redis instance to */ - vpc?: Vpc; + vpc?: IVpc; /** * Repository to pull the container image from */ @@ -46,9 +46,12 @@ export interface MeshServiceProps { */ memory?: number; /** - * Redis instance to use for mesh caching + * Redis configuration to use for mesh caching */ - redis: RedisService; + redis: { + service: RedisService; + database?: string; + }; /** * SSM values to pass through to the container as secrets */ @@ -56,7 +59,7 @@ export interface MeshServiceProps { } export class MeshService extends Construct { - public readonly vpc: Vpc; + public readonly vpc: IVpc; public readonly repository: ecr.Repository; public readonly service: ecs.FargateService; public readonly firewall: WebApplicationFirewall; @@ -131,13 +134,14 @@ export class MeshService extends Construct { // If using Redis configure security group and pass connection string to container if (props.redis) { - props.redis.securityGroup.addIngressRule( + props.redis.service.securityGroup.addIngressRule( securityGroup, - Port.tcp(props.redis.connectionPort) + Port.tcp(props.redis.service.connectionPort) ); - environment["REDIS_ENDPOINT"] = props.redis.connectionEndPoint; - environment["REDIS_PORT"] = props.redis.connectionPort.toString(); + environment["REDIS_ENDPOINT"] = props.redis.service.connectionEndPoint; + environment["REDIS_PORT"] = props.redis.service.connectionPort.toString(); + environment["REDIS_DATABASE"] = props.redis.database ?? "0"; } // Construct secrets from provided ssm values diff --git a/packages/graphql-mesh-server/lib/graphql-mesh-server.ts b/packages/graphql-mesh-server/lib/graphql-mesh-server.ts index 399c2457..fa696280 100644 --- a/packages/graphql-mesh-server/lib/graphql-mesh-server.ts +++ b/packages/graphql-mesh-server/lib/graphql-mesh-server.ts @@ -1,8 +1,8 @@ import { Construct } from "constructs"; -import { MeshService, MeshServiceProps } from "./fargate"; -import { RedisService, RedisServiceProps } from "./redis-construct"; +import { MeshService } from "./fargate"; +import { RedisService } from "./redis-construct"; import { CodePipelineService } from "./pipeline"; -import { SecurityGroup, Vpc } from "aws-cdk-lib/aws-ec2"; +import { SecurityGroup, IVpc, Vpc } from "aws-cdk-lib/aws-ec2"; import { Repository } from "aws-cdk-lib/aws-ecr"; import { FargateService } from "aws-cdk-lib/aws-ecs"; import { CfnCacheCluster } from "aws-cdk-lib/aws-elasticache"; @@ -12,7 +12,7 @@ export type MeshHostingProps = { /** * VPC to attach Redis and Fargate instances to (default: create a vpc) */ - vpc?: Vpc; + vpc?: IVpc; /** * If no VPC is provided create one with this name (default: 'graphql-server-vpc') */ @@ -46,9 +46,12 @@ export type MeshHostingProps = { */ memory?: number; /** - * Redis instance to use for mesh caching + * Redis configuration to use for mesh caching */ - redis?: RedisService; + redis?: { + service: RedisService; + database?: string; + }; /** * SSM values to pass through to the container as secrets */ @@ -56,7 +59,7 @@ export type MeshHostingProps = { }; export class MeshHosting extends Construct { - public readonly vpc: Vpc; + public readonly vpc: IVpc; public readonly repository: Repository; public readonly service: FargateService; public readonly cacheCluster: CfnCacheCluster; @@ -73,7 +76,7 @@ export class MeshHosting extends Construct { }); const redis = - props.redis || + props.redis?.service || new RedisService(this, "redis", { ...props, vpc: this.vpc, @@ -85,7 +88,10 @@ export class MeshHosting extends Construct { const mesh = new MeshService(this, "mesh", { ...props, vpc: this.vpc, - redis, + redis: { + service: redis, + database: props.redis?.database, + }, }); this.service = mesh.service; diff --git a/packages/graphql-mesh-server/lib/redis-construct.ts b/packages/graphql-mesh-server/lib/redis-construct.ts index 5a9ba5b0..b450ca37 100644 --- a/packages/graphql-mesh-server/lib/redis-construct.ts +++ b/packages/graphql-mesh-server/lib/redis-construct.ts @@ -1,4 +1,4 @@ -import { SecurityGroup, Vpc } from "aws-cdk-lib/aws-ec2"; +import { SecurityGroup, IVpc } from "aws-cdk-lib/aws-ec2"; import { CfnCacheCluster, CfnSubnetGroup, @@ -11,7 +11,7 @@ export interface RedisServiceProps { /** * VPC to attach Redis instance to */ - vpc: Vpc; + vpc: IVpc; /** * Cache node type (default: 'cache.t2.micro') */ @@ -20,7 +20,7 @@ export interface RedisServiceProps { export class RedisService extends Construct { public readonly cacheCluster: CfnCacheCluster; - public readonly vpc: Vpc; + public readonly vpc: IVpc; public readonly securityGroup: SecurityGroup; constructor(scope: Construct, id: string, props: RedisServiceProps) { From 319bea32053f21cc1dd5b88d7612eabce32ac2ba Mon Sep 17 00:00:00 2001 From: Adam Hall Date: Fri, 15 Sep 2023 14:39:00 +0930 Subject: [PATCH 22/27] MICRO-196: Slack Notifications Create a cross account supported way of sending slack notifications whenever GraphQl mesh is deployed --- packages/graphql-mesh-server/README.md | 5 +- .../graphql-mesh-server/assets/notify-sns.ts | 20 +++ .../lib/graphql-mesh-server.ts | 101 ++++++------- packages/graphql-mesh-server/lib/pipeline.ts | 133 ++++++++++++------ 4 files changed, 167 insertions(+), 92 deletions(-) create mode 100644 packages/graphql-mesh-server/assets/notify-sns.ts diff --git a/packages/graphql-mesh-server/README.md b/packages/graphql-mesh-server/README.md index 4263295b..2eca2cf7 100644 --- a/packages/graphql-mesh-server/README.md +++ b/packages/graphql-mesh-server/README.md @@ -1,6 +1,8 @@ -# Prerender in Fargate +# GraphQL Mesh in Fargate A construct host [GraphQL Mesh](https://the-guild.dev/graphql/mesh) server in Fargate. +## Deployment notifications +If notificationArn is set this construct creates a CodeStar notification rule, SNS topic and Lambda function to receive notifications for codepipeline executions and forward them to another SNS topic. This is so that you can setup AWS Chatbot either in this account OR another account and forward the notifications there. ## Props - `vpc?`: VPC to attach Redis and Fargate instances to (default: create a vpc) - `vpcName?`: If no VPC is provided create one with this name (default: 'graphql-server-vpc') @@ -13,3 +15,4 @@ A construct host [GraphQL Mesh](https://the-guild.dev/graphql/mesh) server in Fa - `memory?`: Amount of memory per Fargate instance (default: 1024) - `redis?`: Redis instance to use for mesh caching - `secrets?`: SSM values to pass through to the container as secrets + - `notificationArn?`: SNS Topic ARN to publish deployment notifications to \ No newline at end of file diff --git a/packages/graphql-mesh-server/assets/notify-sns.ts b/packages/graphql-mesh-server/assets/notify-sns.ts new file mode 100644 index 00000000..b7be432b --- /dev/null +++ b/packages/graphql-mesh-server/assets/notify-sns.ts @@ -0,0 +1,20 @@ +import { PublishCommand, SNSClient } from '@aws-sdk/client-sns'; +import { SNSEvent } from 'aws-lambda'; + +const client = new SNSClient({ region: process.env.AWS_REGION }); + +export const handler = async (event: SNSEvent): Promise => { + const record = event.Records[0]; + const message = record.Sns.Message; + + const command = new PublishCommand({ + TopicArn: process.env.SNS_TOPIC, + Message: message, + }); + + try { + await client.send(command); + } catch (e) { + console.log(e); + } +}; diff --git a/packages/graphql-mesh-server/lib/graphql-mesh-server.ts b/packages/graphql-mesh-server/lib/graphql-mesh-server.ts index 399c2457..268d2974 100644 --- a/packages/graphql-mesh-server/lib/graphql-mesh-server.ts +++ b/packages/graphql-mesh-server/lib/graphql-mesh-server.ts @@ -9,50 +9,54 @@ import { CfnCacheCluster } from "aws-cdk-lib/aws-elasticache"; import * as ssm from "aws-cdk-lib/aws-ssm"; export type MeshHostingProps = { - /** - * VPC to attach Redis and Fargate instances to (default: create a vpc) - */ - vpc?: Vpc; - /** - * If no VPC is provided create one with this name (default: 'graphql-server-vpc') - */ - vpcName?: string; - /** - * Cache node type (default: 'cache.t2.micro') - */ - cacheNodeType?: string; - /** - * Repository to pull the container image from - */ - repository?: Repository; - /** - * ARN of the certificate to add to the load balancer - */ - certificateArn: string; - /** - * Minimum number of Fargate instances - */ - minCapacity?: number; - /** - * Maximum number of Fargate instances - */ - maxCapacity?: number; - /** - * Amount of vCPU per Fargate instance (default: 512) - */ - cpu?: number; - /** - * Amount of memory per Fargate instance (default: 1024) - */ - memory?: number; - /** - * Redis instance to use for mesh caching - */ - redis?: RedisService; - /** - * SSM values to pass through to the container as secrets - */ - secrets?: { [key: string]: ssm.IStringParameter | ssm.IStringListParameter }; + /** + * VPC to attach Redis and Fargate instances to (default: create a vpc) + */ + vpc?: Vpc; + /** + * If no VPC is provided create one with this name (default: 'graphql-server-vpc') + */ + vpcName?: string; + /** + * Cache node type (default: 'cache.t2.micro') + */ + cacheNodeType?: string; + /** + * Repository to pull the container image from + */ + repository?: Repository; + /** + * ARN of the certificate to add to the load balancer + */ + certificateArn: string; + /** + * Minimum number of Fargate instances + */ + minCapacity?: number; + /** + * Maximum number of Fargate instances + */ + maxCapacity?: number; + /** + * Amount of vCPU per Fargate instance (default: 512) + */ + cpu?: number; + /** + * Amount of memory per Fargate instance (default: 1024) + */ + memory?: number; + /** + * Redis instance to use for mesh caching + */ + redis?: RedisService; + /** + * SSM values to pass through to the container as secrets + */ + secrets?: {[key: string]: ssm.IStringParameter | ssm.IStringListParameter}; + /** + * ARN of the SNS Topic to send deployment notifications to + */ + notificationArn?: string; }; export class MeshHosting extends Construct { @@ -91,9 +95,10 @@ export class MeshHosting extends Construct { this.service = mesh.service; this.repository = mesh.repository; - new CodePipelineService(this, "pipeline", { - repository: this.repository, - service: this.service, - }); + new CodePipelineService(this, 'pipeline', { + repository: this.repository, + service: this.service, + notificationArn: props.notificationArn + }); } } diff --git a/packages/graphql-mesh-server/lib/pipeline.ts b/packages/graphql-mesh-server/lib/pipeline.ts index a4e7c7c6..0b7cdd54 100644 --- a/packages/graphql-mesh-server/lib/pipeline.ts +++ b/packages/graphql-mesh-server/lib/pipeline.ts @@ -1,13 +1,19 @@ -import { Duration } from "aws-cdk-lib"; -import { Artifact, Pipeline } from "aws-cdk-lib/aws-codepipeline"; -import { Repository } from "aws-cdk-lib/aws-ecr"; -import { FargateService } from "aws-cdk-lib/aws-ecs"; -import * as pipe_actions from "aws-cdk-lib/aws-codepipeline-actions"; -import * as codebuild from "aws-cdk-lib/aws-codebuild"; -import { Construct } from "constructs"; -import * as fs from "fs"; -import * as path from "path"; -import * as YAML from "yaml"; +import { Duration } from 'aws-cdk-lib'; +import { Artifact, Pipeline } from 'aws-cdk-lib/aws-codepipeline'; +import { Repository } from 'aws-cdk-lib/aws-ecr'; +import { FargateService } from 'aws-cdk-lib/aws-ecs'; +import * as pipe_actions from 'aws-cdk-lib/aws-codepipeline-actions'; +import * as codebuild from 'aws-cdk-lib/aws-codebuild'; +import { Construct } from 'constructs'; +import * as fs from 'fs'; +import * as path from 'path'; +import * as YAML from 'yaml'; +import { NodejsFunction } from 'aws-cdk-lib/aws-lambda-nodejs'; +import { Runtime } from 'aws-cdk-lib/aws-lambda'; +import { Effect, PolicyStatement } from 'aws-cdk-lib/aws-iam'; +import { Topic } from 'aws-cdk-lib/aws-sns'; +import { LambdaSubscription } from 'aws-cdk-lib/aws-sns-subscriptions'; +import { DetailType, NotificationRule } from 'aws-cdk-lib/aws-codestarnotifications'; export interface CodePipelineServiceProps { /** @@ -24,6 +30,11 @@ export interface CodePipelineServiceProps { * Path to buildspec.yml (default: '../assets/buildspec.yml') */ buildspecPath?: string; + + /** + * ARN of the SNS Topic to send deployment notifications to + */ + notificationArn?: string; } export class CodePipelineService extends Construct { @@ -58,37 +69,73 @@ export class CodePipelineService extends Construct { } ); - const buildOutput = new Artifact(); - this.pipeline.addStage({ - stageName: "Build", - actions: [ - new pipe_actions.CodeBuildAction({ - actionName: "CodeBuild", - project, - input: sourceOutput, - outputs: [buildOutput], - environmentVariables: { - IMAGE_URI: { - value: sourceAction.variables.imageUri, - }, - CONTAINER_NAME: { - value: - props.service.taskDefinition.defaultContainer?.containerName, - }, - }, - }), - ], - }); - this.pipeline.addStage({ - stageName: "Deploy", - actions: [ - new pipe_actions.EcsDeployAction({ - actionName: "DeployAction", - service: props.service, - input: buildOutput, - deploymentTimeout: Duration.minutes(10), - }), - ], - }); - } + const buildOutput = new Artifact(); + this.pipeline.addStage({ + stageName: 'Build', + actions: [ + new pipe_actions.CodeBuildAction({ + actionName: 'CodeBuild', + project, + input: sourceOutput, + outputs: [buildOutput], + environmentVariables: { + IMAGE_URI: { + value: sourceAction.variables.imageUri, + }, + CONTAINER_NAME: { + value: props.service.taskDefinition.defaultContainer + ?.containerName, + }, + }, + }), + ], + }); + this.pipeline.addStage({ + stageName: 'Deploy', + actions: [ + new pipe_actions.EcsDeployAction({ + actionName: 'DeployAction', + service: props.service, + input: buildOutput, + deploymentTimeout: Duration.minutes(10), + }), + ], + }); + + if (props.notificationArn) { + const notifier = new NodejsFunction(this, 'NotifierLambda', { + entry: path.resolve(__dirname, '../assets/notify-sns.ts'), + description: 'Lambda function to forward SNS messages to another account.', + runtime: Runtime.NODEJS_18_X, + handler: 'index.handler', + timeout: Duration.seconds(10), + environment: { + SNS_TOPIC: props.notificationArn + } + }); + + notifier.addToRolePolicy(new PolicyStatement({ + actions: ['sns:publish'], + resources: [props.notificationArn], + effect: Effect.ALLOW + })); + + const topic = new Topic(this, 'NotifierTopic'); + topic.addSubscription(new LambdaSubscription(notifier)); + + new NotificationRule(this, 'CodeStarNotificationRule', { + detailType: DetailType.FULL, + events: [ + 'codepipeline-pipeline-pipeline-execution-failed', + 'codepipeline-pipeline-pipeline-execution-canceled', + 'codepipeline-pipeline-pipeline-execution-started', + 'codepipeline-pipeline-pipeline-execution-resumed', + 'codepipeline-pipeline-pipeline-execution-succeeded', + 'codepipeline-pipeline-pipeline-execution-superseded', + ], + targets: [topic], + source: this.pipeline, + }); + } + } } From 1e9262ea0c40e3a5be0e741e01ae5c041e58af1f Mon Sep 17 00:00:00 2001 From: Adam Hall Date: Fri, 13 Oct 2023 14:33:18 +1030 Subject: [PATCH 23/27] Add SNS client dependency --- packages/graphql-mesh-server/package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/graphql-mesh-server/package.json b/packages/graphql-mesh-server/package.json index b3a40c28..df512e91 100644 --- a/packages/graphql-mesh-server/package.json +++ b/packages/graphql-mesh-server/package.json @@ -31,6 +31,7 @@ "yaml": "^2.3.1", "aws-cdk-lib": "2.97.0", "constructs": "^10.0.0", - "source-map-support": "^0.5.21" + "source-map-support": "^0.5.21", + "@aws-sdk/client-sns": "^3.413.0" } } From 9f2aed80e1b3dc57726139d1ad045d2b6545fa67 Mon Sep 17 00:00:00 2001 From: Adam Hall Date: Mon, 18 Sep 2023 09:26:31 +0930 Subject: [PATCH 24/27] Ensure handler is included in package --- packages/graphql-mesh-server/.npmignore | 2 +- .../graphql-mesh-server/assets/{ => handlers}/notify-sns.ts | 0 packages/graphql-mesh-server/lib/pipeline.ts | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename packages/graphql-mesh-server/assets/{ => handlers}/notify-sns.ts (100%) diff --git a/packages/graphql-mesh-server/.npmignore b/packages/graphql-mesh-server/.npmignore index bfd115ba..96724112 100644 --- a/packages/graphql-mesh-server/.npmignore +++ b/packages/graphql-mesh-server/.npmignore @@ -1,5 +1,5 @@ *.ts -!lib/handlers/*.ts +!assets/handlers/*.ts !*.d.ts !*.js diff --git a/packages/graphql-mesh-server/assets/notify-sns.ts b/packages/graphql-mesh-server/assets/handlers/notify-sns.ts similarity index 100% rename from packages/graphql-mesh-server/assets/notify-sns.ts rename to packages/graphql-mesh-server/assets/handlers/notify-sns.ts diff --git a/packages/graphql-mesh-server/lib/pipeline.ts b/packages/graphql-mesh-server/lib/pipeline.ts index 0b7cdd54..68efe7fb 100644 --- a/packages/graphql-mesh-server/lib/pipeline.ts +++ b/packages/graphql-mesh-server/lib/pipeline.ts @@ -104,7 +104,7 @@ export class CodePipelineService extends Construct { if (props.notificationArn) { const notifier = new NodejsFunction(this, 'NotifierLambda', { - entry: path.resolve(__dirname, '../assets/notify-sns.ts'), + entry: path.resolve(__dirname, '../assets/handlers/notify-sns.ts'), description: 'Lambda function to forward SNS messages to another account.', runtime: Runtime.NODEJS_18_X, handler: 'index.handler', From b34d404f7067f870924fc14efb07e6ccbfd8451e Mon Sep 17 00:00:00 2001 From: Adam Hall Date: Fri, 13 Oct 2023 14:41:17 +1030 Subject: [PATCH 25/27] Update package-lock with new depnedencies --- package-lock.json | 1356 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 1354 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index adc7dce3..82decd22 100644 --- a/package-lock.json +++ b/package-lock.json @@ -144,6 +144,646 @@ "constructs": "^10.0.0" } }, + "node_modules/@aws-crypto/crc32": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-3.0.0.tgz", + "integrity": "sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==", + "dependencies": { + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/ie11-detection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/ie11-detection/-/ie11-detection-3.0.0.tgz", + "integrity": "sha512-341lBBkiY1DfDNKai/wXM3aujNBkXR7tq1URPQDL9wi3AUbI80NR74uF1TXHMm7po1AcnFk8iu2S2IeU/+/A+Q==", + "dependencies": { + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/sha256-browser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-3.0.0.tgz", + "integrity": "sha512-8VLmW2B+gjFbU5uMeqtQM6Nj0/F1bro80xQXCW6CQBWgosFWXTx77aeOF5CAIAmbOK64SdMBJdNr6J41yP5mvQ==", + "dependencies": { + "@aws-crypto/ie11-detection": "^3.0.0", + "@aws-crypto/sha256-js": "^3.0.0", + "@aws-crypto/supports-web-crypto": "^3.0.0", + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@aws-sdk/util-utf8-browser": "^3.0.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/sha256-js": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-3.0.0.tgz", + "integrity": "sha512-PnNN7os0+yd1XvXAy23CFOmTbMaDxgxXtTKHybrJ39Y8kGzBATgBFibWJKH6BhytLI/Zyszs87xCOBNyBig6vQ==", + "dependencies": { + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/supports-web-crypto": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-3.0.0.tgz", + "integrity": "sha512-06hBdMwUAb2WFTuGG73LSC0wfPu93xWwo5vL2et9eymgmu3Id5vFAHBbajVWiGhPO37qcsdCap/FqXvJGJWPIg==", + "dependencies": { + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/util": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-3.0.0.tgz", + "integrity": "sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w==", + "dependencies": { + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-utf8-browser": "^3.0.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-sdk/client-sns": { + "version": "3.428.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sns/-/client-sns-3.428.0.tgz", + "integrity": "sha512-B21ytodIQFDSDWoJNw+5ZuG0TAbHDLcRSE+Wz2GngiQi7rDKOZTUPdEeNIc4Y1MEYgDbpD+pYmSbPxxoGT8c6A==", + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/client-sts": "3.428.0", + "@aws-sdk/credential-provider-node": "3.428.0", + "@aws-sdk/middleware-host-header": "3.428.0", + "@aws-sdk/middleware-logger": "3.428.0", + "@aws-sdk/middleware-recursion-detection": "3.428.0", + "@aws-sdk/middleware-signing": "3.428.0", + "@aws-sdk/middleware-user-agent": "3.428.0", + "@aws-sdk/region-config-resolver": "3.428.0", + "@aws-sdk/types": "3.428.0", + "@aws-sdk/util-endpoints": "3.428.0", + "@aws-sdk/util-user-agent-browser": "3.428.0", + "@aws-sdk/util-user-agent-node": "3.428.0", + "@smithy/config-resolver": "^2.0.14", + "@smithy/fetch-http-handler": "^2.2.3", + "@smithy/hash-node": "^2.0.11", + "@smithy/invalid-dependency": "^2.0.11", + "@smithy/middleware-content-length": "^2.0.13", + "@smithy/middleware-endpoint": "^2.1.0", + "@smithy/middleware-retry": "^2.0.16", + "@smithy/middleware-serde": "^2.0.11", + "@smithy/middleware-stack": "^2.0.5", + "@smithy/node-config-provider": "^2.1.1", + "@smithy/node-http-handler": "^2.1.7", + "@smithy/protocol-http": "^3.0.7", + "@smithy/smithy-client": "^2.1.11", + "@smithy/types": "^2.3.5", + "@smithy/url-parser": "^2.0.11", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.15", + "@smithy/util-defaults-mode-node": "^2.0.19", + "@smithy/util-retry": "^2.0.4", + "@smithy/util-utf8": "^2.0.0", + "fast-xml-parser": "4.2.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-sns/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/client-sso": { + "version": "3.428.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.428.0.tgz", + "integrity": "sha512-6BuY7cd1licnCZTKuI/IK3ycKATIgsG53TuaK1hZcikwUB2Oiu2z6K+aWpmO9mJuJ6qAoE4dLlAy6lBBBkG6yQ==", + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/middleware-host-header": "3.428.0", + "@aws-sdk/middleware-logger": "3.428.0", + "@aws-sdk/middleware-recursion-detection": "3.428.0", + "@aws-sdk/middleware-user-agent": "3.428.0", + "@aws-sdk/region-config-resolver": "3.428.0", + "@aws-sdk/types": "3.428.0", + "@aws-sdk/util-endpoints": "3.428.0", + "@aws-sdk/util-user-agent-browser": "3.428.0", + "@aws-sdk/util-user-agent-node": "3.428.0", + "@smithy/config-resolver": "^2.0.14", + "@smithy/fetch-http-handler": "^2.2.3", + "@smithy/hash-node": "^2.0.11", + "@smithy/invalid-dependency": "^2.0.11", + "@smithy/middleware-content-length": "^2.0.13", + "@smithy/middleware-endpoint": "^2.1.0", + "@smithy/middleware-retry": "^2.0.16", + "@smithy/middleware-serde": "^2.0.11", + "@smithy/middleware-stack": "^2.0.5", + "@smithy/node-config-provider": "^2.1.1", + "@smithy/node-http-handler": "^2.1.7", + "@smithy/protocol-http": "^3.0.7", + "@smithy/smithy-client": "^2.1.11", + "@smithy/types": "^2.3.5", + "@smithy/url-parser": "^2.0.11", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.15", + "@smithy/util-defaults-mode-node": "^2.0.19", + "@smithy/util-retry": "^2.0.4", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-sso/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/client-sts": { + "version": "3.428.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.428.0.tgz", + "integrity": "sha512-ko9hgmIkS5FNPYtT3pntGGmp+yi+VXBEgePUBoplEKjCxsX/aTgFcq2Rs9duD9/CzkThd42Z0l0fWsVAErVxWQ==", + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/credential-provider-node": "3.428.0", + "@aws-sdk/middleware-host-header": "3.428.0", + "@aws-sdk/middleware-logger": "3.428.0", + "@aws-sdk/middleware-recursion-detection": "3.428.0", + "@aws-sdk/middleware-sdk-sts": "3.428.0", + "@aws-sdk/middleware-signing": "3.428.0", + "@aws-sdk/middleware-user-agent": "3.428.0", + "@aws-sdk/region-config-resolver": "3.428.0", + "@aws-sdk/types": "3.428.0", + "@aws-sdk/util-endpoints": "3.428.0", + "@aws-sdk/util-user-agent-browser": "3.428.0", + "@aws-sdk/util-user-agent-node": "3.428.0", + "@smithy/config-resolver": "^2.0.14", + "@smithy/fetch-http-handler": "^2.2.3", + "@smithy/hash-node": "^2.0.11", + "@smithy/invalid-dependency": "^2.0.11", + "@smithy/middleware-content-length": "^2.0.13", + "@smithy/middleware-endpoint": "^2.1.0", + "@smithy/middleware-retry": "^2.0.16", + "@smithy/middleware-serde": "^2.0.11", + "@smithy/middleware-stack": "^2.0.5", + "@smithy/node-config-provider": "^2.1.1", + "@smithy/node-http-handler": "^2.1.7", + "@smithy/protocol-http": "^3.0.7", + "@smithy/smithy-client": "^2.1.11", + "@smithy/types": "^2.3.5", + "@smithy/url-parser": "^2.0.11", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.15", + "@smithy/util-defaults-mode-node": "^2.0.19", + "@smithy/util-retry": "^2.0.4", + "@smithy/util-utf8": "^2.0.0", + "fast-xml-parser": "4.2.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-sts/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/credential-provider-env": { + "version": "3.428.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.428.0.tgz", + "integrity": "sha512-e6fbY174Idzw0r5ZMT1qkDh+dpOp1DX3ickhr7J6ipo3cUGLI45Y5lnR9nYXWfB5o/wiNv4zXgN+Y3ORJJHzyA==", + "dependencies": { + "@aws-sdk/types": "3.428.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/types": "^2.3.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-env/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.428.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.428.0.tgz", + "integrity": "sha512-JPc0pVAsP8fOfMxhmPhp7PjddqHaPGBwgVI+wgbkFRUDOmeKCVhoxCB8Womx0R07qRqD5ZCUKBS2NHQ2b3MFRQ==", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.428.0", + "@aws-sdk/credential-provider-process": "3.428.0", + "@aws-sdk/credential-provider-sso": "3.428.0", + "@aws-sdk/credential-provider-web-identity": "3.428.0", + "@aws-sdk/types": "3.428.0", + "@smithy/credential-provider-imds": "^2.0.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/types": "^2.3.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-ini/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/credential-provider-node": { + "version": "3.428.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.428.0.tgz", + "integrity": "sha512-o8toLXf6/sklBpw2e1mzAUq6SvXQzT6iag7Xbg9E0Z2EgVeXLTnWeVto3ilU3cmhTHXBp6wprwUUq2jbjTxMcg==", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.428.0", + "@aws-sdk/credential-provider-ini": "3.428.0", + "@aws-sdk/credential-provider-process": "3.428.0", + "@aws-sdk/credential-provider-sso": "3.428.0", + "@aws-sdk/credential-provider-web-identity": "3.428.0", + "@aws-sdk/types": "3.428.0", + "@smithy/credential-provider-imds": "^2.0.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/types": "^2.3.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-node/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/credential-provider-process": { + "version": "3.428.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.428.0.tgz", + "integrity": "sha512-UG2S2/4Wrskbkbgt9fBlnzwQ2hfTXvLJwUgGOluSOf6+mGCcoDku4zzc9EQdk1MwN5Us+ziyMrIMNY5sbdLg6g==", + "dependencies": { + "@aws-sdk/types": "3.428.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/types": "^2.3.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-process/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.428.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.428.0.tgz", + "integrity": "sha512-sW2+kSlICSNntsNhLV5apqJkIOXH5hFISCjwVfyB9JXJQDAj8rzkiFfRsKwQ3aTlTYCysrGesIn46+GRP5AgZw==", + "dependencies": { + "@aws-sdk/client-sso": "3.428.0", + "@aws-sdk/token-providers": "3.428.0", + "@aws-sdk/types": "3.428.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/types": "^2.3.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-sso/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.428.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.428.0.tgz", + "integrity": "sha512-ueuUPPlrJFvtDUVTGnClUGt1wxCbEiKArknah/w9cfcc/c1HtFd/M7x/z2Sm0gSItR45sVcK54qjzmhm29DMzg==", + "dependencies": { + "@aws-sdk/types": "3.428.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/types": "^2.3.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-web-identity/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/middleware-host-header": { + "version": "3.428.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.428.0.tgz", + "integrity": "sha512-iIHbW5Ym60ol9Q6vsLnaiNdeUIa9DA0OuoOe9LiHC8SYUYVAAhE+xJXUhn1qk/J7z+4qGOkDnVyEvnSaqRPL/w==", + "dependencies": { + "@aws-sdk/types": "3.428.0", + "@smithy/protocol-http": "^3.0.7", + "@smithy/types": "^2.3.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-host-header/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/middleware-logger": { + "version": "3.428.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.428.0.tgz", + "integrity": "sha512-1P0V0quL9u2amdNOn6yYT7/ToQUmkLJqCKHPxsRyDB829vBThWndvvH5MkoItj/VgE1zWqMtrzN3xtzD7zx6Qg==", + "dependencies": { + "@aws-sdk/types": "3.428.0", + "@smithy/types": "^2.3.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-logger/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/middleware-recursion-detection": { + "version": "3.428.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.428.0.tgz", + "integrity": "sha512-xC0OMduCByyRdiQz324RXy4kunnCG4LUJCfvdoegM33Elp9ex0D3fcfO1mUgV8qiLwSennIsSRVXHuhNxE2HZA==", + "dependencies": { + "@aws-sdk/types": "3.428.0", + "@smithy/protocol-http": "^3.0.7", + "@smithy/types": "^2.3.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-recursion-detection/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/middleware-sdk-sts": { + "version": "3.428.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.428.0.tgz", + "integrity": "sha512-Uutl2niYXTnNP8v84v6umWDHD5no7d5/OqkZE1DsmeKR/dje90J5unJWf7MOsqvYm0JGDEWF4lk9xGVyqsw+Aw==", + "dependencies": { + "@aws-sdk/middleware-signing": "3.428.0", + "@aws-sdk/types": "3.428.0", + "@smithy/types": "^2.3.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-sts/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/middleware-signing": { + "version": "3.428.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.428.0.tgz", + "integrity": "sha512-oMSerTPwtsQAR7fIU/G0b0BA30wF+MC4gZSrJjbypF8MK8nPC2yMfKLR8+QavGOGEW7rUMQ0uklThMTTwQEXNQ==", + "dependencies": { + "@aws-sdk/types": "3.428.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/protocol-http": "^3.0.7", + "@smithy/signature-v4": "^2.0.0", + "@smithy/types": "^2.3.5", + "@smithy/util-middleware": "^2.0.4", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-signing/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/middleware-user-agent": { + "version": "3.428.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.428.0.tgz", + "integrity": "sha512-+GAhObeHRick2D5jr3YkPckjcggt5v6uUVtEUQW2AdD65cE5PjIvmksv6FuM/mME/9nNA+wufQnHbLI8teLeaw==", + "dependencies": { + "@aws-sdk/types": "3.428.0", + "@aws-sdk/util-endpoints": "3.428.0", + "@smithy/protocol-http": "^3.0.7", + "@smithy/types": "^2.3.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-user-agent/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/region-config-resolver": { + "version": "3.428.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.428.0.tgz", + "integrity": "sha512-VqyHZ/Hoz3WrXXMx8cAhFBl8IpjodbRsTjBI117QPq1YRCegxNdGvqmGZnJj8N2Ef9MP1iU30ZWQB+sviDcogA==", + "dependencies": { + "@smithy/node-config-provider": "^2.1.1", + "@smithy/types": "^2.3.5", + "@smithy/util-config-provider": "^2.0.0", + "@smithy/util-middleware": "^2.0.4", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/region-config-resolver/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/token-providers": { + "version": "3.428.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.428.0.tgz", + "integrity": "sha512-Jciofr//rB1v1FLxADkXoHOCmYyiv2HVNlOq3z5Zkch9ipItOfD6X7f4G4n+IZzElIFzwe4OKoBtJfcnnfo3Pg==", + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/middleware-host-header": "3.428.0", + "@aws-sdk/middleware-logger": "3.428.0", + "@aws-sdk/middleware-recursion-detection": "3.428.0", + "@aws-sdk/middleware-user-agent": "3.428.0", + "@aws-sdk/types": "3.428.0", + "@aws-sdk/util-endpoints": "3.428.0", + "@aws-sdk/util-user-agent-browser": "3.428.0", + "@aws-sdk/util-user-agent-node": "3.428.0", + "@smithy/config-resolver": "^2.0.14", + "@smithy/fetch-http-handler": "^2.2.3", + "@smithy/hash-node": "^2.0.11", + "@smithy/invalid-dependency": "^2.0.11", + "@smithy/middleware-content-length": "^2.0.13", + "@smithy/middleware-endpoint": "^2.1.0", + "@smithy/middleware-retry": "^2.0.16", + "@smithy/middleware-serde": "^2.0.11", + "@smithy/middleware-stack": "^2.0.5", + "@smithy/node-config-provider": "^2.1.1", + "@smithy/node-http-handler": "^2.1.7", + "@smithy/property-provider": "^2.0.0", + "@smithy/protocol-http": "^3.0.7", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/smithy-client": "^2.1.11", + "@smithy/types": "^2.3.5", + "@smithy/url-parser": "^2.0.11", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.15", + "@smithy/util-defaults-mode-node": "^2.0.19", + "@smithy/util-retry": "^2.0.4", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/token-providers/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/types": { + "version": "3.428.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.428.0.tgz", + "integrity": "sha512-4T0Ps2spjg3qbWE6ZK13Vd3FnzpfliaiotqjxUK5YhjDrKXeT36HJp46JhDupElQuHtTkpdiJOSYk2lvY2H4IA==", + "dependencies": { + "@smithy/types": "^2.3.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/types/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/util-endpoints": { + "version": "3.428.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.428.0.tgz", + "integrity": "sha512-ToKMhYlUWJ0YrbggpJLZeyZZNDXtQ4NITxqo/oeGltTT9KG4o/LqVY59EveV0f8P32ObDyj9Vh1mnjxeo3DxGw==", + "dependencies": { + "@aws-sdk/types": "3.428.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/util-endpoints/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/util-locate-window": { + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.310.0.tgz", + "integrity": "sha512-qo2t/vBTnoXpjKxlsC2e1gBrRm80M3bId27r0BRB2VniSSe7bL1mmzM+/HFtujm0iAxtPM+aLEflLJlJeDPg0w==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/util-locate-window/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/util-user-agent-browser": { + "version": "3.428.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.428.0.tgz", + "integrity": "sha512-qlc2UoGsmCpuh1ErY3VayZuAGl74TWWcLmhhQMkeByFSb6KooBlwOmDpDzJRtgwJoe0KXnyHBO6lzl9iczcozg==", + "dependencies": { + "@aws-sdk/types": "3.428.0", + "@smithy/types": "^2.3.5", + "bowser": "^2.11.0", + "tslib": "^2.5.0" + } + }, + "node_modules/@aws-sdk/util-user-agent-browser/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/util-user-agent-node": { + "version": "3.428.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.428.0.tgz", + "integrity": "sha512-s721C3H8TkNd0usWLPEAy7yW2lEglR8QAYojdQGzE0e0wymc671nZAFePSZFRtmqZiFOSfk0R602L5fDbP3a8Q==", + "dependencies": { + "@aws-sdk/types": "3.428.0", + "@smithy/node-config-provider": "^2.1.1", + "@smithy/types": "^2.3.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "aws-crt": ">=1.0.0" + }, + "peerDependenciesMeta": { + "aws-crt": { + "optional": true + } + } + }, + "node_modules/@aws-sdk/util-user-agent-node/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/util-utf8-browser": { + "version": "3.259.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz", + "integrity": "sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==", + "dependencies": { + "tslib": "^2.3.1" + } + }, + "node_modules/@aws-sdk/util-utf8-browser/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, "node_modules/@babel/code-frame": { "version": "7.22.13", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", @@ -1742,6 +2382,679 @@ "@sinonjs/commons": "^3.0.0" } }, + "node_modules/@smithy/abort-controller": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-2.0.11.tgz", + "integrity": "sha512-MSzE1qR2JNyb7ot3blIOT3O3H0Jn06iNDEgHRaqZUwBgx5EG+VIx24Y21tlKofzYryIOcWpIohLrIIyocD6LMA==", + "dependencies": { + "@smithy/types": "^2.3.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/abort-controller/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/config-resolver": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-2.0.14.tgz", + "integrity": "sha512-K1K+FuWQoy8j/G7lAmK85o03O89s2Vvh6kMFmzEmiHUoQCRH1rzbDtMnGNiaMHeSeYJ6y79IyTusdRG+LuWwtg==", + "dependencies": { + "@smithy/node-config-provider": "^2.1.1", + "@smithy/types": "^2.3.5", + "@smithy/util-config-provider": "^2.0.0", + "@smithy/util-middleware": "^2.0.4", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/config-resolver/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/credential-provider-imds": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-2.0.16.tgz", + "integrity": "sha512-tKa2xF+69TvGxJT+lnJpGrKxUuAZDLYXFhqnPEgnHz+psTpkpcB4QRjHj63+uj83KaeFJdTfW201eLZeRn6FfA==", + "dependencies": { + "@smithy/node-config-provider": "^2.1.1", + "@smithy/property-provider": "^2.0.12", + "@smithy/types": "^2.3.5", + "@smithy/url-parser": "^2.0.11", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/credential-provider-imds/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/eventstream-codec": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-2.0.11.tgz", + "integrity": "sha512-BQCTjxhCYRZIfXapa2LmZSaH8QUBGwMZw7XRN83hrdixbLjIcj+o549zjkedFS07Ve2TlvWUI6BTzP+nv7snBA==", + "dependencies": { + "@aws-crypto/crc32": "3.0.0", + "@smithy/types": "^2.3.5", + "@smithy/util-hex-encoding": "^2.0.0", + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/eventstream-codec/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/fetch-http-handler": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-2.2.3.tgz", + "integrity": "sha512-0G9sePU+0R+8d7cie+OXzNbbkjnD4RfBlVCs46ZEuQAMcxK8OniemYXSSkOc80CCk8Il4DnlYZcUSvsIs2OB2w==", + "dependencies": { + "@smithy/protocol-http": "^3.0.7", + "@smithy/querystring-builder": "^2.0.11", + "@smithy/types": "^2.3.5", + "@smithy/util-base64": "^2.0.0", + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/fetch-http-handler/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/hash-node": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-2.0.11.tgz", + "integrity": "sha512-PbleVugN2tbhl1ZoNWVrZ1oTFFas/Hq+s6zGO8B9bv4w/StTriTKA9W+xZJACOj9X7zwfoTLbscM+avCB1KqOQ==", + "dependencies": { + "@smithy/types": "^2.3.5", + "@smithy/util-buffer-from": "^2.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/hash-node/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/invalid-dependency": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-2.0.11.tgz", + "integrity": "sha512-zazq99ujxYv/NOf9zh7xXbNgzoVLsqE0wle8P/1zU/XdhPi/0zohTPKWUzIxjGdqb5hkkwfBkNkl5H+LE0mvgw==", + "dependencies": { + "@smithy/types": "^2.3.5", + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/invalid-dependency/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/is-array-buffer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.0.0.tgz", + "integrity": "sha512-z3PjFjMyZNI98JFRJi/U0nGoLWMSJlDjAW4QUX2WNZLas5C0CmVV6LJ01JI0k90l7FvpmixjWxPFmENSClQ7ug==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/is-array-buffer/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/middleware-content-length": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-2.0.13.tgz", + "integrity": "sha512-Md2kxWpaec3bXp1oERFPQPBhOXCkGSAF7uc1E+4rkwjgw3/tqAXRtbjbggu67HJdwaif76As8AV6XxbD1HzqTQ==", + "dependencies": { + "@smithy/protocol-http": "^3.0.7", + "@smithy/types": "^2.3.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/middleware-content-length/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/middleware-endpoint": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-2.1.1.tgz", + "integrity": "sha512-YAqGagBvHqDEew4EGz9BrQ7M+f+u7ck9EL4zzYirOhIcXeBS/+q4A5+ObHDDwEp38lD6t88YUtFy3OptqEaDQg==", + "dependencies": { + "@smithy/middleware-serde": "^2.0.11", + "@smithy/node-config-provider": "^2.1.1", + "@smithy/shared-ini-file-loader": "^2.2.0", + "@smithy/types": "^2.3.5", + "@smithy/url-parser": "^2.0.11", + "@smithy/util-middleware": "^2.0.4", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/middleware-endpoint/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/middleware-retry": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-2.0.16.tgz", + "integrity": "sha512-Br5+0yoiMS0ugiOAfJxregzMMGIRCbX4PYo1kDHtLgvkA/d++aHbnHB819m5zOIAMPvPE7AThZgcsoK+WOsUTA==", + "dependencies": { + "@smithy/node-config-provider": "^2.1.1", + "@smithy/protocol-http": "^3.0.7", + "@smithy/service-error-classification": "^2.0.4", + "@smithy/types": "^2.3.5", + "@smithy/util-middleware": "^2.0.4", + "@smithy/util-retry": "^2.0.4", + "tslib": "^2.5.0", + "uuid": "^8.3.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/middleware-retry/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/middleware-serde": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-2.0.11.tgz", + "integrity": "sha512-NuxnjMyf4zQqhwwdh0OTj5RqpnuT6HcH5Xg5GrPijPcKzc2REXVEVK4Yyk8ckj8ez1XSj/bCmJ+oNjmqB02GWA==", + "dependencies": { + "@smithy/types": "^2.3.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/middleware-serde/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/middleware-stack": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-2.0.5.tgz", + "integrity": "sha512-bVQU/rZzBY7CbSxIrDTGZYnBWKtIw+PL/cRc9B7etZk1IKSOe0NvKMJyWllfhfhrTeMF6eleCzOihIQympAvPw==", + "dependencies": { + "@smithy/types": "^2.3.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/middleware-stack/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/node-config-provider": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-2.1.1.tgz", + "integrity": "sha512-1lF6s1YWBi1LBu2O30tD3jyTgMtuvk/Z1twzXM4GPYe4dmZix4nNREPJIPOcfFikNU2o0eTYP80+izx5F2jIJA==", + "dependencies": { + "@smithy/property-provider": "^2.0.12", + "@smithy/shared-ini-file-loader": "^2.2.0", + "@smithy/types": "^2.3.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/node-config-provider/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/node-http-handler": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-2.1.7.tgz", + "integrity": "sha512-PQIKZXlp3awCDn/xNlCSTFE7aYG/5Tx33M05NfQmWYeB5yV1GZZOSz4dXpwiNJYTXb9jPqjl+ueXXkwtEluFFA==", + "dependencies": { + "@smithy/abort-controller": "^2.0.11", + "@smithy/protocol-http": "^3.0.7", + "@smithy/querystring-builder": "^2.0.11", + "@smithy/types": "^2.3.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/node-http-handler/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/property-provider": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-2.0.12.tgz", + "integrity": "sha512-Un/OvvuQ1Kg8WYtoMCicfsFFuHb/TKL3pCA6ZIo/WvNTJTR94RtoRnL7mY4XkkUAoFMyf6KjcQJ76y1FX7S5rw==", + "dependencies": { + "@smithy/types": "^2.3.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/property-provider/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/protocol-http": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-3.0.7.tgz", + "integrity": "sha512-HnZW8y+r66ntYueCDbLqKwWcMNWW8o3eVpSrHNluwtBJ/EUWfQHRKSiu6vZZtc6PGfPQWgVfucoCE/C3QufMAA==", + "dependencies": { + "@smithy/types": "^2.3.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/protocol-http/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/querystring-builder": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-2.0.11.tgz", + "integrity": "sha512-b4kEbVMxpmfv2VWUITn2otckTi7GlMteZQxi+jlwedoATOGEyrCJPfRcYQJjbCi3fZ2QTfh3PcORvB27+j38Yg==", + "dependencies": { + "@smithy/types": "^2.3.5", + "@smithy/util-uri-escape": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/querystring-builder/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/querystring-parser": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-2.0.11.tgz", + "integrity": "sha512-YXe7jhi7s3dQ0Fu9dLoY/gLu6NCyy8tBWJL/v2c9i7/RLpHgKT+uT96/OqZkHizCJ4kr0ZD46tzMjql/o60KLg==", + "dependencies": { + "@smithy/types": "^2.3.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/querystring-parser/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/service-error-classification": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-2.0.4.tgz", + "integrity": "sha512-77506l12I5gxTZqBkx3Wb0RqMG81bMYLaVQ+EqIWFwQDJRs5UFeXogKxSKojCmz1wLUziHZQXm03MBzPQiumQw==", + "dependencies": { + "@smithy/types": "^2.3.5" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/shared-ini-file-loader": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-2.2.0.tgz", + "integrity": "sha512-xFXqs4vAb5BdkzHSRrTapFoaqS4/3m/CGZzdw46fBjYZ0paYuLAoMY60ICCn1FfGirG+PiJ3eWcqJNe4/SkfyA==", + "dependencies": { + "@smithy/types": "^2.3.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/shared-ini-file-loader/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/signature-v4": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-2.0.11.tgz", + "integrity": "sha512-EFVU1dT+2s8xi227l1A9O27edT/GNKvyAK6lZnIZ0zhIHq/jSLznvkk15aonGAM1kmhmZBVGpI7Tt0odueZK9A==", + "dependencies": { + "@smithy/eventstream-codec": "^2.0.11", + "@smithy/is-array-buffer": "^2.0.0", + "@smithy/types": "^2.3.5", + "@smithy/util-hex-encoding": "^2.0.0", + "@smithy/util-middleware": "^2.0.4", + "@smithy/util-uri-escape": "^2.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/signature-v4/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/smithy-client": { + "version": "2.1.11", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-2.1.11.tgz", + "integrity": "sha512-okjMbuBBCTiieK665OFN/ap6u9+Z9z55PMphS5FYCsS6Zfp137Q3qlnt0OgBAnUVnH/mNGyoJV0LBX9gkTWptg==", + "dependencies": { + "@smithy/middleware-stack": "^2.0.5", + "@smithy/types": "^2.3.5", + "@smithy/util-stream": "^2.0.16", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/smithy-client/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/types": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.3.5.tgz", + "integrity": "sha512-ehyDt8M9hehyxrLQGoA1BGPou8Js1Ocoh5M0ngDhJMqbFmNK5N6Xhr9/ZExWkyIW8XcGkiMPq3ZUEE0ScrhbuQ==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/types/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/url-parser": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-2.0.11.tgz", + "integrity": "sha512-h89yXMCCF+S5k9XIoKltMIWTYj+FcEkU/IIFZ6RtE222fskOTL4Iak6ZRG+ehSvZDt8yKEcxqheTDq7JvvtK3g==", + "dependencies": { + "@smithy/querystring-parser": "^2.0.11", + "@smithy/types": "^2.3.5", + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/url-parser/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/util-base64": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-2.0.0.tgz", + "integrity": "sha512-Zb1E4xx+m5Lud8bbeYi5FkcMJMnn+1WUnJF3qD7rAdXpaL7UjkFQLdmW5fHadoKbdHpwH9vSR8EyTJFHJs++tA==", + "dependencies": { + "@smithy/util-buffer-from": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-base64/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/util-body-length-browser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-2.0.0.tgz", + "integrity": "sha512-JdDuS4ircJt+FDnaQj88TzZY3+njZ6O+D3uakS32f2VNnDo3vyEuNdBOh/oFd8Df1zSZOuH1HEChk2AOYDezZg==", + "dependencies": { + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/util-body-length-browser/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/util-body-length-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-2.1.0.tgz", + "integrity": "sha512-/li0/kj/y3fQ3vyzn36NTLGmUwAICb7Jbe/CsWCktW363gh1MOcpEcSO3mJ344Gv2dqz8YJCLQpb6hju/0qOWw==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-body-length-node/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/util-buffer-from": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.0.0.tgz", + "integrity": "sha512-/YNnLoHsR+4W4Vf2wL5lGv0ksg8Bmk3GEGxn2vEQt52AQaPSCuaO5PM5VM7lP1K9qHRKHwrPGktqVoAHKWHxzw==", + "dependencies": { + "@smithy/is-array-buffer": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-buffer-from/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/util-config-provider": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-2.0.0.tgz", + "integrity": "sha512-xCQ6UapcIWKxXHEU4Mcs2s7LcFQRiU3XEluM2WcCjjBtQkUN71Tb+ydGmJFPxMUrW/GWMgQEEGipLym4XG0jZg==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-config-provider/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/util-defaults-mode-browser": { + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-2.0.15.tgz", + "integrity": "sha512-2raMZOYKSuke7QlDg/HDcxQdrp0zteJ8z+S0B9Rn23J55ZFNK1+IjG4HkN6vo/0u3Xy/JOdJ93ibiBSB8F7kOw==", + "dependencies": { + "@smithy/property-provider": "^2.0.12", + "@smithy/smithy-client": "^2.1.11", + "@smithy/types": "^2.3.5", + "bowser": "^2.11.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@smithy/util-defaults-mode-browser/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/util-defaults-mode-node": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-2.0.19.tgz", + "integrity": "sha512-7pScU4jBFADB2MBYKM3zb5onMh6Nn0X3IfaFVLYPyCarTIZDLUtUl1GtruzEUJPmDzP+uGeqOtU589HDY0Ni6g==", + "dependencies": { + "@smithy/config-resolver": "^2.0.14", + "@smithy/credential-provider-imds": "^2.0.16", + "@smithy/node-config-provider": "^2.1.1", + "@smithy/property-provider": "^2.0.12", + "@smithy/smithy-client": "^2.1.11", + "@smithy/types": "^2.3.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@smithy/util-defaults-mode-node/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/util-hex-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-2.0.0.tgz", + "integrity": "sha512-c5xY+NUnFqG6d7HFh1IFfrm3mGl29lC+vF+geHv4ToiuJCBmIfzx6IeHLg+OgRdPFKDXIw6pvi+p3CsscaMcMA==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-hex-encoding/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/util-middleware": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-2.0.4.tgz", + "integrity": "sha512-Pbu6P4MBwRcjrLgdTR1O4Y3c0sTZn2JdOiJNcgL7EcIStcQodj+6ZTXtbyU/WTEU3MV2NMA10LxFc3AWHZ3+4A==", + "dependencies": { + "@smithy/types": "^2.3.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-middleware/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/util-retry": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-2.0.4.tgz", + "integrity": "sha512-b+n1jBBKc77C1E/zfBe1Zo7S9OXGBiGn55N0apfhZHxPUP/fMH5AhFUUcWaJh7NAnah284M5lGkBKuhnr3yK5w==", + "dependencies": { + "@smithy/service-error-classification": "^2.0.4", + "@smithy/types": "^2.3.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@smithy/util-retry/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/util-stream": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-2.0.16.tgz", + "integrity": "sha512-b5ZSRh1KzUzC7LoJcpfk7+iXGoRr3WylEfmPd4FnBLm90OwxSB9VgK1fDZwicfYxSEvWHdYXgvvjPtenEYBBhw==", + "dependencies": { + "@smithy/fetch-http-handler": "^2.2.3", + "@smithy/node-http-handler": "^2.1.7", + "@smithy/types": "^2.3.5", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-buffer-from": "^2.0.0", + "@smithy/util-hex-encoding": "^2.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-stream/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/util-uri-escape": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-2.0.0.tgz", + "integrity": "sha512-ebkxsqinSdEooQduuk9CbKcI+wheijxEb3utGXkCoYQkJnwTnLbH1JXGimJtUkQwNQbsbuYwG2+aFVyZf5TLaw==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-uri-escape/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/util-utf8": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.0.0.tgz", + "integrity": "sha512-rctU1VkziY84n5OXe3bPNpKR001ZCME2JCaBBFgtiM2hfKbHFudc/BkMuPab8hRbLd0j3vbnBTTZ1igBf0wgiQ==", + "dependencies": { + "@smithy/util-buffer-from": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-utf8/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, "node_modules/@tsconfig/node10": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", @@ -2716,6 +4029,11 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/bowser": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", + "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==" + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -3510,6 +4828,27 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, + "node_modules/fast-xml-parser": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.2.5.tgz", + "integrity": "sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g==", + "funding": [ + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + }, + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, "node_modules/fastq": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", @@ -5550,6 +6889,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/strnum": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==" + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -5710,8 +7054,7 @@ "node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/tsutils": { "version": "3.21.0", @@ -5813,6 +7156,14 @@ "punycode": "^2.1.0" } }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "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", @@ -6055,6 +7406,7 @@ "version": "0.0.1", "license": "GPL-3.0-only", "dependencies": { + "@aws-sdk/client-sns": "^3.413.0", "aws-cdk-lib": "2.97.0", "constructs": "^10.0.0", "source-map-support": "^0.5.21", From 85e2138d0315d6fba01ca5156151cebc123bbb03 Mon Sep 17 00:00:00 2001 From: Krishan Thisera Date: Fri, 13 Oct 2023 15:54:52 +1030 Subject: [PATCH 26/27] DO-1550: revert the changes to the tsconfig from #1106 and remove prebuild script --- package.json | 1 - tsconfig.json | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/package.json b/package.json index c0870056..8b20a7af 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,6 @@ "homepage": "https://github.com/aligent/aws-cdk-constructs#readme", "scripts": { "build": "tsc", - "prepublish": "tsc", "lint": "eslint --ignore-path .eslintignore --ext .ts .", "lint:check": "npm run lint", "lint:fix": "npm run lint --fix", diff --git a/tsconfig.json b/tsconfig.json index 882d25f3..064f8c63 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,8 +3,7 @@ "target": "ES2018", "module": "commonjs", "lib": ["es2018"], - "declaration": false, - "noEmit": true, + "noEmit": false, "strict": true, "noImplicitAny": true, "strictNullChecks": true, From bbdc768fc7de6fc5555ba8197becc4659bbf38ce Mon Sep 17 00:00:00 2001 From: Krishan Thisera Date: Fri, 13 Oct 2023 16:11:34 +1030 Subject: [PATCH 27/27] DO-1550: make declaration true --- tsconfig.json | 1 + 1 file changed, 1 insertion(+) diff --git a/tsconfig.json b/tsconfig.json index 064f8c63..a9f72ce6 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,6 +4,7 @@ "module": "commonjs", "lib": ["es2018"], "noEmit": false, + "declaration": true, "strict": true, "noImplicitAny": true, "strictNullChecks": true,