diff --git a/.projen/deps.json b/.projen/deps.json index dd9b95a3d..6ef161cbf 100644 --- a/.projen/deps.json +++ b/.projen/deps.json @@ -15,6 +15,14 @@ "version": "2.120.0-alpha.0", "type": "build" }, + { + "name": "@aws-sdk/client-codeartifact", + "type": "build" + }, + { + "name": "@aws-sdk/client-s3", + "type": "build" + }, { "name": "@aws-sdk/client-sfn", "type": "build" @@ -27,6 +35,14 @@ "name": "@octokit/rest", "type": "build" }, + { + "name": "@smithy/types", + "type": "build" + }, + { + "name": "@smithy/util-stream", + "type": "build" + }, { "name": "@types/aws-lambda", "type": "build" @@ -104,6 +120,14 @@ "name": "aws-sdk", "type": "build" }, + { + "name": "aws-sdk-client-mock", + "type": "build" + }, + { + "name": "aws-sdk-client-mock-jest", + "type": "build" + }, { "name": "aws-sdk-mock", "type": "build" diff --git a/.projen/tasks.json b/.projen/tasks.json index e8074169a..66abcb2f8 100644 --- a/.projen/tasks.json +++ b/.projen/tasks.json @@ -225,7 +225,7 @@ "description": "Continuously bundle all AWS Fargate functions", "steps": [ { - "exec": "esbuild --bundle src/backend/transliterator/transliterator.ecs-entrypoint.ts --target=\"node18\" --platform=\"node\" --outbase=\"src\" --outdir=\"lib\" --entry-names=\"[dir]/[name].bundle/index\" --external:aws-sdk --sourcemap --watch" + "exec": "esbuild --bundle src/backend/transliterator/transliterator.ecs-entrypoint.ts --target=\"node20\" --platform=\"node\" --outbase=\"src\" --outdir=\"lib\" --entry-names=\"[dir]/[name].bundle/index\" --external:aws-sdk --sourcemap --watch" } ] }, @@ -1201,13 +1201,13 @@ }, "steps": [ { - "exec": "npx npm-check-updates@16 --upgrade --target=minor --peer --dep=dev --filter=@aws-sdk/client-sfn,@jsii/spec,@octokit/rest,@types/aws-lambda,@types/fs-extra,@types/jest,@types/markdown-it,@types/markdown-it-emoji,@types/semver,@types/streamx,@types/tar-stream,@types/tough-cookie,@types/uuid,async-sema,aws-embedded-metrics,aws-sdk,aws-sdk-mock,aws-xray-sdk-core,case,cdk-dia,cdk-watchful,cdklabs-projen-project-types,chalk,construct-hub-webapp,dotenv,esbuild,eslint-config-prettier,eslint-import-resolver-typescript,eslint-plugin-import,eslint-plugin-prettier,feed,fs-extra,glob,got,jest,jsii-diff,jsii-pacmak,JSONStream,markdown-it,markdown-it-emoji,nock,normalize-registry-metadata,prettier,projen,semver,spdx-license-list,streamcount,streamx,tar-stream,ts-node,uuid,yaml" + "exec": "npx npm-check-updates@16 --upgrade --target=minor --peer --dep=dev --filter=@aws-sdk/client-codeartifact,@aws-sdk/client-s3,@aws-sdk/client-sfn,@jsii/spec,@octokit/rest,@smithy/types,@smithy/util-stream,@types/aws-lambda,@types/fs-extra,@types/jest,@types/markdown-it,@types/markdown-it-emoji,@types/semver,@types/streamx,@types/tar-stream,@types/tough-cookie,@types/uuid,async-sema,aws-embedded-metrics,aws-sdk,aws-sdk-client-mock,aws-sdk-client-mock-jest,aws-sdk-mock,aws-xray-sdk-core,case,cdk-dia,cdk-watchful,cdklabs-projen-project-types,chalk,construct-hub-webapp,dotenv,esbuild,eslint-config-prettier,eslint-import-resolver-typescript,eslint-plugin-import,eslint-plugin-prettier,feed,fs-extra,glob,got,jest,jsii-diff,jsii-pacmak,JSONStream,markdown-it,markdown-it-emoji,nock,normalize-registry-metadata,prettier,projen,semver,spdx-license-list,streamcount,streamx,tar-stream,ts-node,uuid,yaml" }, { "exec": "yarn install --check-files" }, { - "exec": "yarn upgrade @aws-cdk/aws-servicecatalogappregistry-alpha @aws-cdk/integ-runner @aws-cdk/integ-tests-alpha @aws-sdk/client-sfn @jsii/spec @octokit/rest @types/aws-lambda @types/fs-extra @types/jest @types/markdown-it @types/markdown-it-emoji @types/node @types/semver @types/streamx @types/tar-stream @types/tough-cookie @types/uuid @typescript-eslint/eslint-plugin @typescript-eslint/parser async-sema aws-cdk-lib aws-cdk aws-embedded-metrics aws-sdk aws-sdk-mock aws-xray-sdk-core case cdk-dia cdk-watchful cdklabs-projen-project-types chalk commit-and-tag-version construct-hub-webapp dotenv esbuild eslint-config-prettier eslint-import-resolver-typescript eslint-plugin-import eslint-plugin-prettier eslint feed fs-extra glob got jest jest-junit jsii-diff jsii-docgen jsii-pacmak jsii-rosetta jsii JSONStream markdown-it markdown-it-emoji nock normalize-registry-metadata prettier projen semver spdx-license-list streamcount streamx tar-stream ts-node typescript uuid yaml" + "exec": "yarn upgrade @aws-cdk/aws-servicecatalogappregistry-alpha @aws-cdk/integ-runner @aws-cdk/integ-tests-alpha @aws-sdk/client-codeartifact @aws-sdk/client-s3 @aws-sdk/client-sfn @jsii/spec @octokit/rest @smithy/types @smithy/util-stream @types/aws-lambda @types/fs-extra @types/jest @types/markdown-it @types/markdown-it-emoji @types/node @types/semver @types/streamx @types/tar-stream @types/tough-cookie @types/uuid @typescript-eslint/eslint-plugin @typescript-eslint/parser async-sema aws-cdk-lib aws-cdk aws-embedded-metrics aws-sdk aws-sdk-client-mock aws-sdk-client-mock-jest aws-sdk-mock aws-xray-sdk-core case cdk-dia cdk-watchful cdklabs-projen-project-types chalk commit-and-tag-version construct-hub-webapp dotenv esbuild eslint-config-prettier eslint-import-resolver-typescript eslint-plugin-import eslint-plugin-prettier eslint feed fs-extra glob got jest jest-junit jsii-diff jsii-docgen jsii-pacmak jsii-rosetta jsii JSONStream markdown-it markdown-it-emoji nock normalize-registry-metadata prettier projen semver spdx-license-list streamcount streamx tar-stream ts-node typescript uuid yaml" }, { "exec": "npx projen" diff --git a/.projenrc.ts b/.projenrc.ts index ec407897d..1f0c90ab4 100644 --- a/.projenrc.ts +++ b/.projenrc.ts @@ -47,15 +47,21 @@ const project = new CdklabsConstructLibrary({ '@types/tough-cookie', '@types/uuid', cdkCli, - 'aws-embedded-metrics', - 'dotenv', + '@aws-sdk/client-codeartifact', + '@aws-sdk/client-s3', + '@smithy/types', + '@smithy/util-stream', 'async-sema', + 'aws-embedded-metrics', + 'aws-sdk-client-mock', + 'aws-sdk-client-mock-jest', 'aws-sdk-mock', 'aws-sdk', 'aws-xray-sdk-core', 'case', 'cdk-dia', 'chalk', + 'dotenv', 'esbuild', 'feed', 'fs-extra', diff --git a/package.json b/package.json index 6509fe24c..4b3253218 100644 --- a/package.json +++ b/package.json @@ -115,9 +115,13 @@ "@aws-cdk/aws-servicecatalogappregistry-alpha": "2.120.0-alpha.0", "@aws-cdk/integ-runner": "2.120.0-alpha.0", "@aws-cdk/integ-tests-alpha": "2.120.0-alpha.0", + "@aws-sdk/client-codeartifact": "^3.645.0", + "@aws-sdk/client-s3": "^3.645.0", "@aws-sdk/client-sfn": "^3.645.0", "@jsii/spec": "^1.103.1", "@octokit/rest": "^19.0.13", + "@smithy/types": "^3.3.0", + "@smithy/util-stream": "^3.1.4", "@types/aws-lambda": "^8.10.145", "@types/fs-extra": "^11.0.4", "@types/jest": "^29", @@ -136,6 +140,8 @@ "aws-cdk-lib": "2.120.0", "aws-embedded-metrics": "^4.1.1", "aws-sdk": "^2.1691.0", + "aws-sdk-client-mock": "^4.0.1", + "aws-sdk-client-mock-jest": "^4.0.1", "aws-sdk-mock": "5.9.0", "aws-xray-sdk-core": "^3.9.0", "case": "^1.6.3", diff --git a/projenrc/bundle-javascript-for-ecs.exec.ts b/projenrc/bundle-javascript-for-ecs.exec.ts index 38c8f7355..ba6a4a936 100644 --- a/projenrc/bundle-javascript-for-ecs.exec.ts +++ b/projenrc/bundle-javascript-for-ecs.exec.ts @@ -1,6 +1,7 @@ import { basename, dirname, posix } from 'path'; import { Instance as Chalk } from 'chalk'; import * as esbuild from 'esbuild'; +import { ECS_TASK_NODE_VERSION } from './magic-ecs'; const chalk = new Chalk({ level: process.env.NO_COLOR ? 0 : 1, @@ -24,7 +25,7 @@ async function main(args: string[]) { entryPoints: [entrypoint], outfile, sourcemap: true, - target: 'node18', + target: `node${ECS_TASK_NODE_VERSION}`, platform: 'node', metafile: true, diff --git a/projenrc/magic-ecs.ts b/projenrc/magic-ecs.ts index 27ac0eff6..eac3e04aa 100644 --- a/projenrc/magic-ecs.ts +++ b/projenrc/magic-ecs.ts @@ -1,9 +1,10 @@ import { basename, dirname, join, relative } from 'path'; -import Case from 'case'; +import * as Case from 'case'; import * as glob from 'glob'; import { SourceCode } from 'projen'; import { TypeScriptProject } from 'projen/lib/typescript'; +export const ECS_TASK_NODE_VERSION = '20'; const BUNDLE_DIR_ENV = 'BUNDLE_DIR'; const ECS_TASK_MEMORY_LIMIT_DEFINITIONS: { [key: string]: number } = { 'backend/transliterator/transliterator.ecstask.ts': 8192, @@ -208,22 +209,25 @@ function newEcsTask(project: TypeScriptProject, entrypoint: string) { const df = new SourceCode(project, dockerfile); df.line(`# ${df.marker}`); - // Based off amazonlinux:2 for... reasons. (Do not change!) - df.line('FROM public.ecr.aws/amazonlinux/amazonlinux:2'); + // Based off amazonlinux:2023 for... reasons. Slim node images don't work here. + df.line('FROM public.ecr.aws/amazonlinux/amazonlinux:2023'); df.line(); // Install node the regular way... df.line( - 'RUN yum install https://rpm.nodesource.com/pub_16.x/nodistro/repo/nodesource-release-nodistro-1.noarch.rpm -y \\' + `RUN yum install https://rpm.nodesource.com/pub_${ECS_TASK_NODE_VERSION}.x/nodistro/repo/nodesource-release-nodistro-1.noarch.rpm -y \\` ); + df.line(' && yum install nodejs -y \\'); + // @see https://github.com/nodesource/distributions/blob/e42782301931c357cec2a09e1246d7849e084345/scripts/rpm/setup_22.x#L75-L76 df.line( - ' && yum install nodejs -y --setopt=nodesource-nodejs.module_hotfixes=1 \\' + ' --setopt=nodesource-nodejs.gpgkey=https://rpm.nodesource.com/gpgkey/ns-operations-public.key \\' ); - df.line(' && yum update -y \\'); - df.line(' && yum upgrade -y \\'); - df.line(' && yum install -y git lsof nodejs \\'); + df.line(' --setopt=nodesource-nodejs.module_hotfixes=1 \\'); + df.line(' && yum update -y \\'); + df.line(' && yum upgrade -y \\'); + df.line(' && yum install -y git lsof nodejs \\'); // Clean up the yum cache in the interest of image size - df.line(' && yum clean all \\'); - df.line(' && rm -rf /var/cache/yum'); + df.line(' && yum clean all \\'); + df.line(' && rm -rf /var/cache/yum'); df.line(); df.line('COPY . /bundle'); df.line(); @@ -290,7 +294,7 @@ export function discoverEcsTasks(project: TypeScriptProject) { ...entrypoints.map((file) => file.replace('ecstask.ts', 'ecs-entrypoint.ts') ), - '--target="node18"', + `--target="node${ECS_TASK_NODE_VERSION}"`, '--platform="node"', `--outbase="${project.srcdir}"`, `--outdir="${project.libdir}"`, diff --git a/src/__tests__/__snapshots__/construct-hub.test.ts.snap b/src/__tests__/__snapshots__/construct-hub.test.ts.snap index 6a0b15d90..460ffd003 100644 --- a/src/__tests__/__snapshots__/construct-hub.test.ts.snap +++ b/src/__tests__/__snapshots__/construct-hub.test.ts.snap @@ -2210,7 +2210,7 @@ Direct link to the function: /lambda/home#/functions/", "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}", }, - "S3Key": "c609e81e93fe8175f65442b25bf3c9d5dd4a184c6d40c4c2094b14a4ccd893a3.zip", + "S3Key": "92c30ddb1baaf0771dac0f79d4c3b1a6984baf8eac73e12cb0ab04f3f22fd096.zip", }, "Description": "[ConstructHub/Ingestion] Ingests new package versions into the Construct Hub", "Environment": { @@ -6805,7 +6805,7 @@ Warning: messages that resulted in a failed exectuion will NOT be in the DLQ!", ], "Essential": true, "Image": { - "Fn::Sub": "\${AWS::AccountId}.dkr.ecr.\${AWS::Region}.\${AWS::URLSuffix}/cdk-hnb659fds-container-assets-\${AWS::AccountId}-\${AWS::Region}:d879a2b37f21ee9d92e1763519cbbc879549749b1b2fa2498725e8162e40770d", + "Fn::Sub": "\${AWS::AccountId}.dkr.ecr.\${AWS::Region}.\${AWS::URLSuffix}/cdk-hnb659fds-container-assets-\${AWS::AccountId}-\${AWS::Region}:163c30075527137d291e3aef3865f2d7fabc82baf8e77bfcba58e32d2ce57564", }, "LogConfiguration": { "LogDriver": "awslogs", @@ -15030,7 +15030,7 @@ Direct link to the function: /lambda/home#/functions/", "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}", }, - "S3Key": "c609e81e93fe8175f65442b25bf3c9d5dd4a184c6d40c4c2094b14a4ccd893a3.zip", + "S3Key": "92c30ddb1baaf0771dac0f79d4c3b1a6984baf8eac73e12cb0ab04f3f22fd096.zip", }, "Description": "[ConstructHub/Ingestion] Ingests new package versions into the Construct Hub", "Environment": { @@ -19750,7 +19750,7 @@ Warning: messages that resulted in a failed exectuion will NOT be in the DLQ!", ], "Essential": true, "Image": { - "Fn::Sub": "\${AWS::AccountId}.dkr.ecr.\${AWS::Region}.\${AWS::URLSuffix}/cdk-hnb659fds-container-assets-\${AWS::AccountId}-\${AWS::Region}:d879a2b37f21ee9d92e1763519cbbc879549749b1b2fa2498725e8162e40770d", + "Fn::Sub": "\${AWS::AccountId}.dkr.ecr.\${AWS::Region}.\${AWS::URLSuffix}/cdk-hnb659fds-container-assets-\${AWS::AccountId}-\${AWS::Region}:163c30075527137d291e3aef3865f2d7fabc82baf8e77bfcba58e32d2ce57564", }, "LogConfiguration": { "LogDriver": "awslogs", @@ -27764,7 +27764,7 @@ Direct link to the function: /lambda/home#/functions/", "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}", }, - "S3Key": "c609e81e93fe8175f65442b25bf3c9d5dd4a184c6d40c4c2094b14a4ccd893a3.zip", + "S3Key": "92c30ddb1baaf0771dac0f79d4c3b1a6984baf8eac73e12cb0ab04f3f22fd096.zip", }, "Description": "[ConstructHub/Ingestion] Ingests new package versions into the Construct Hub", "Environment": { @@ -32359,7 +32359,7 @@ Warning: messages that resulted in a failed exectuion will NOT be in the DLQ!", ], "Essential": true, "Image": { - "Fn::Sub": "\${AWS::AccountId}.dkr.ecr.\${AWS::Region}.\${AWS::URLSuffix}/cdk-hnb659fds-container-assets-\${AWS::AccountId}-\${AWS::Region}:d879a2b37f21ee9d92e1763519cbbc879549749b1b2fa2498725e8162e40770d", + "Fn::Sub": "\${AWS::AccountId}.dkr.ecr.\${AWS::Region}.\${AWS::URLSuffix}/cdk-hnb659fds-container-assets-\${AWS::AccountId}-\${AWS::Region}:163c30075527137d291e3aef3865f2d7fabc82baf8e77bfcba58e32d2ce57564", }, "LogConfiguration": { "LogDriver": "awslogs", @@ -40454,7 +40454,7 @@ Direct link to the function: /lambda/home#/functions/", "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}", }, - "S3Key": "c609e81e93fe8175f65442b25bf3c9d5dd4a184c6d40c4c2094b14a4ccd893a3.zip", + "S3Key": "92c30ddb1baaf0771dac0f79d4c3b1a6984baf8eac73e12cb0ab04f3f22fd096.zip", }, "Description": "[ConstructHub/Ingestion] Ingests new package versions into the Construct Hub", "Environment": { @@ -45071,7 +45071,7 @@ Warning: messages that resulted in a failed exectuion will NOT be in the DLQ!", ], "Essential": true, "Image": { - "Fn::Sub": "\${AWS::AccountId}.dkr.ecr.\${AWS::Region}.\${AWS::URLSuffix}/cdk-hnb659fds-container-assets-\${AWS::AccountId}-\${AWS::Region}:d879a2b37f21ee9d92e1763519cbbc879549749b1b2fa2498725e8162e40770d", + "Fn::Sub": "\${AWS::AccountId}.dkr.ecr.\${AWS::Region}.\${AWS::URLSuffix}/cdk-hnb659fds-container-assets-\${AWS::AccountId}-\${AWS::Region}:163c30075527137d291e3aef3865f2d7fabc82baf8e77bfcba58e32d2ce57564", }, "LogConfiguration": { "LogDriver": "awslogs", @@ -53353,7 +53353,7 @@ Direct link to the function: /lambda/home#/functions/", "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}", }, - "S3Key": "c609e81e93fe8175f65442b25bf3c9d5dd4a184c6d40c4c2094b14a4ccd893a3.zip", + "S3Key": "92c30ddb1baaf0771dac0f79d4c3b1a6984baf8eac73e12cb0ab04f3f22fd096.zip", }, "Description": "[ConstructHub/Ingestion] Ingests new package versions into the Construct Hub", "Environment": { @@ -57702,7 +57702,7 @@ Warning: messages that resulted in a failed exectuion will NOT be in the DLQ!", ], "Essential": true, "Image": { - "Fn::Sub": "\${AWS::AccountId}.dkr.ecr.\${AWS::Region}.\${AWS::URLSuffix}/cdk-hnb659fds-container-assets-\${AWS::AccountId}-\${AWS::Region}:d879a2b37f21ee9d92e1763519cbbc879549749b1b2fa2498725e8162e40770d", + "Fn::Sub": "\${AWS::AccountId}.dkr.ecr.\${AWS::Region}.\${AWS::URLSuffix}/cdk-hnb659fds-container-assets-\${AWS::AccountId}-\${AWS::Region}:163c30075527137d291e3aef3865f2d7fabc82baf8e77bfcba58e32d2ce57564", }, "LogConfiguration": { "LogDriver": "awslogs", diff --git a/src/__tests__/backend/shared/code-artifact.test.ts b/src/__tests__/backend/shared/code-artifact.test.ts index 79c5688f3..909b0d124 100644 --- a/src/__tests__/backend/shared/code-artifact.test.ts +++ b/src/__tests__/backend/shared/code-artifact.test.ts @@ -2,21 +2,21 @@ import type * as child_process from 'child_process'; import { randomBytes } from 'crypto'; import { EventEmitter } from 'stream'; -import * as AWS from 'aws-sdk'; -import * as AWSMock from 'aws-sdk-mock'; +import { + CodeartifactClient, + GetAuthorizationTokenCommand, +} from '@aws-sdk/client-codeartifact'; +import { mockClient } from 'aws-sdk-client-mock'; +import 'aws-sdk-client-mock-jest'; import { logInWithCodeArtifact } from '../../../backend/shared/code-artifact.lambda-shared'; jest.mock('child_process'); -beforeEach((done) => { - AWSMock.setSDKInstance(AWS); - done(); -}); +const codeArtifactMock = mockClient(CodeartifactClient); -afterEach((done) => { - AWSMock.restore(); - done(); +beforeEach(() => { + codeArtifactMock.reset(); }); test('logInWithCodeArtifact', async () => { @@ -28,23 +28,9 @@ test('logInWithCodeArtifact', async () => { const apiEndpoint = 'https://fake.codeartifact.api.endpoint'; const authorizationToken = randomBytes(64).toString('base64'); - AWSMock.mock( - 'CodeArtifact', - 'getAuthorizationToken', - ( - param: AWS.CodeArtifact.GetAuthorizationTokenRequest, - cb: Response - ) => { - try { - expect(param.domain).toBe(domain); - expect(param.domainOwner).toBe(domainOwner); - expect(param.durationSeconds).toBe(0); - } catch (e: any) { - return cb(e); - } - cb(null, { authorizationToken }); - } - ); + codeArtifactMock.on(GetAuthorizationTokenCommand).resolves({ + authorizationToken, + }); // eslint-disable-next-line @typescript-eslint/no-require-imports const mockSpawn = require('child_process').spawn as jest.MockedFunction< @@ -83,12 +69,19 @@ test('logInWithCodeArtifact', async () => { // THEN await expect( logInWithCodeArtifact({ endpoint, domain, domainOwner, apiEndpoint }) - ).resolves.not.toThrowError(); + ).resolves.not.toThrow(); + expect(Array.from(configToSet)).toEqual([]); // All config was set as expected. + expect(codeArtifactMock).toHaveReceivedCommandWith( + GetAuthorizationTokenCommand, + { + domain, + domainOwner, + durationSeconds: 0, + } + ); }); -type Response = (err: AWS.AWSError | null, data?: T) => void; - class MockChildProcess extends EventEmitter implements child_process.ChildProcess diff --git a/src/__tests__/backend/transliterator/__snapshots__/index.test.ts.snap b/src/__tests__/backend/transliterator/__snapshots__/index.test.ts.snap index 49e37c024..482f246de 100644 --- a/src/__tests__/backend/transliterator/__snapshots__/index.test.ts.snap +++ b/src/__tests__/backend/transliterator/__snapshots__/index.test.ts.snap @@ -118,7 +118,7 @@ exports[`CodeArtifact repository 1`] = ` ], "Essential": true, "Image": { - "Fn::Sub": "\${AWS::AccountId}.dkr.ecr.\${AWS::Region}.\${AWS::URLSuffix}/cdk-hnb659fds-container-assets-\${AWS::AccountId}-\${AWS::Region}:d879a2b37f21ee9d92e1763519cbbc879549749b1b2fa2498725e8162e40770d", + "Fn::Sub": "\${AWS::AccountId}.dkr.ecr.\${AWS::Region}.\${AWS::URLSuffix}/cdk-hnb659fds-container-assets-\${AWS::AccountId}-\${AWS::Region}:163c30075527137d291e3aef3865f2d7fabc82baf8e77bfcba58e32d2ce57564", }, "LogConfiguration": { "LogDriver": "awslogs", @@ -2426,7 +2426,7 @@ exports[`VPC Endpoints 1`] = ` ], "Essential": true, "Image": { - "Fn::Sub": "\${AWS::AccountId}.dkr.ecr.\${AWS::Region}.\${AWS::URLSuffix}/cdk-hnb659fds-container-assets-\${AWS::AccountId}-\${AWS::Region}:d879a2b37f21ee9d92e1763519cbbc879549749b1b2fa2498725e8162e40770d", + "Fn::Sub": "\${AWS::AccountId}.dkr.ecr.\${AWS::Region}.\${AWS::URLSuffix}/cdk-hnb659fds-container-assets-\${AWS::AccountId}-\${AWS::Region}:163c30075527137d291e3aef3865f2d7fabc82baf8e77bfcba58e32d2ce57564", }, "LogConfiguration": { "LogDriver": "awslogs", @@ -4785,7 +4785,7 @@ exports[`VPC Endpoints and CodeArtifact repository 1`] = ` ], "Essential": true, "Image": { - "Fn::Sub": "\${AWS::AccountId}.dkr.ecr.\${AWS::Region}.\${AWS::URLSuffix}/cdk-hnb659fds-container-assets-\${AWS::AccountId}-\${AWS::Region}:d879a2b37f21ee9d92e1763519cbbc879549749b1b2fa2498725e8162e40770d", + "Fn::Sub": "\${AWS::AccountId}.dkr.ecr.\${AWS::Region}.\${AWS::URLSuffix}/cdk-hnb659fds-container-assets-\${AWS::AccountId}-\${AWS::Region}:163c30075527137d291e3aef3865f2d7fabc82baf8e77bfcba58e32d2ce57564", }, "LogConfiguration": { "LogDriver": "awslogs", @@ -7089,7 +7089,7 @@ exports[`basic use 1`] = ` ], "Essential": true, "Image": { - "Fn::Sub": "\${AWS::AccountId}.dkr.ecr.\${AWS::Region}.\${AWS::URLSuffix}/cdk-hnb659fds-container-assets-\${AWS::AccountId}-\${AWS::Region}:d879a2b37f21ee9d92e1763519cbbc879549749b1b2fa2498725e8162e40770d", + "Fn::Sub": "\${AWS::AccountId}.dkr.ecr.\${AWS::Region}.\${AWS::URLSuffix}/cdk-hnb659fds-container-assets-\${AWS::AccountId}-\${AWS::Region}:163c30075527137d291e3aef3865f2d7fabc82baf8e77bfcba58e32d2ce57564", }, "LogConfiguration": { "LogDriver": "awslogs", diff --git a/src/__tests__/backend/transliterator/transliterator.ecstask.test.ts b/src/__tests__/backend/transliterator/transliterator.ecstask.test.ts index e75c782f0..4f7bc2140 100644 --- a/src/__tests__/backend/transliterator/transliterator.ecstask.test.ts +++ b/src/__tests__/backend/transliterator/transliterator.ecstask.test.ts @@ -1,8 +1,15 @@ +import { Readable } from 'node:stream'; +import { + DeleteObjectCommand, + GetObjectCommand, + NotFound, + PutObjectCommand, + S3Client, +} from '@aws-sdk/client-s3'; import * as spec from '@jsii/spec'; +import { sdkStreamMixin } from '@smithy/util-stream'; -import * as AWS from 'aws-sdk'; -import type { AWSError } from 'aws-sdk'; -import * as AWSMock from 'aws-sdk-mock'; +import { mockClient } from 'aws-sdk-client-mock'; import { LanguageNotSupportedError, UnInstallablePackageError, @@ -16,7 +23,6 @@ import { MarkdownRenderer } from 'jsii-docgen/lib/docgen/render/markdown-render' import { Documentation } from 'jsii-docgen/lib/docgen/view/documentation'; import type { TransliteratorInput } from '../../../backend/payload-schema'; -import { reset } from '../../../backend/shared/aws.lambda-shared'; import * as constants from '../../../backend/shared/constants'; import { DocumentationLanguage } from '../../../backend/shared/language'; import { @@ -42,17 +48,10 @@ mockWriteFile.mockImplementation(async (filePath: string) => { return Promise.resolve(); }); -type Response = (err: AWS.AWSError | null, data?: T) => void; - -beforeEach((done) => { - AWSMock.setSDKInstance(AWS); - done(); -}); +const mockS3 = mockClient(S3Client); -afterEach((done) => { - AWSMock.restore(); - reset(); - done(); +beforeEach(() => { + mockS3.reset(); }); describe('VPC Endpoints', () => { @@ -125,12 +124,12 @@ describe('VPC Endpoints', () => { targets: { python: {} }, } as any; - // mock the s3ObjectExists call - mockHeadRequest('package.tgz'); - // mock the assembly and tarball requests mockFetchRequests(assembly, Buffer.from('fake-tarball', 'utf8')); + // nothing to delete + mockDeleteRequest(); + // mock the file uploads mockPutRequest( ...DocumentationLanguage.ALL.map( @@ -208,12 +207,12 @@ test('uninstallable package marker is uploaded', async () => { targets: { python: {} }, } as any; - // mock the s3ObjectExists call - mockHeadRequest('package.tgz'); - // mock the assembly and tarball requests mockFetchRequests(assembly, Buffer.from('fake-tarball', 'utf8')); + // nothing to delete + mockDeleteRequest(); + mockPutRequest('/uninstallable'); const { created } = await transliterate(event); @@ -256,12 +255,12 @@ test('corrupt assembly marker is uploaded for the necessary languages', async () const assembly: spec.Assembly = {} as any; - // mock the s3ObjectExists call - mockHeadRequest('package.tgz'); - // mock the assembly and tarball requests mockFetchRequests(assembly, Buffer.from('fake-tarball', 'utf8')); + // nothing to delete + mockDeleteRequest(); + mockPutRequest(constants.CORRUPT_ASSEMBLY_SUFFIX); const { created } = await transliterate(event); @@ -313,13 +312,6 @@ test('corrupt assembly and uninstallable markers are deleted', async () => { const assembly: spec.Assembly = {} as any; - // mock the s3ObjectExists call - mockHeadRequest( - 'package.tgz', - constants.CORRUPT_ASSEMBLY_SUFFIX, - constants.UNINSTALLABLE_PACKAGE_SUFFIX - ); - // mock the assembly and tarball requests mockFetchRequests(assembly, Buffer.from('fake-tarball', 'utf8')); @@ -375,12 +367,12 @@ test('uploads a file per language (scoped package)', async () => { targets: { python: {} }, } as any; - // mock the s3ObjectExists call - mockHeadRequest('package.tgz'); - // mock the assembly and tarball requests mockFetchRequests(assembly, Buffer.from('fake-tarball', 'utf8')); + // nothing to delete + mockDeleteRequest(); + // mock the file uploads mockPutRequest('/docs-typescript.json', '/docs-typescript.md'); @@ -427,12 +419,12 @@ test('uploads a file per submodule (unscoped package)', async () => { }, } as any; - // mock the s3ObjectExists call - mockHeadRequest('package.tgz'); - // mock the assembly and tarball requests mockFetchRequests(assembly, Buffer.from('fake-tarball', 'utf8')); + // nothing to delete + mockDeleteRequest(); + // mock the file uploads mockPutRequest( '/docs-typescript.md', @@ -498,15 +490,15 @@ test.each([true, false])( ), } as any; - // mock the s3ObjectExists call - mockHeadRequest('package.tgz'); - // mock the assembly and tarball requests mockFetchRequests(assembly, Buffer.from('fake-tarball', 'utf8')); // mock the file uploads const writtenKeys = mockPutRequestCollectAll(); + // nothing to delete + mockDeleteRequest(); + // WHEN const result = await handler(event); @@ -555,9 +547,6 @@ describe('markers for un-supported languages', () => { submodules: { 'package-name.sub1': {}, 'package-name.sub2': {} }, } as any; - // mock the s3ObjectExists call - mockHeadRequest('package.tgz'); - // mock the assembly and tarball requests mockFetchRequests(assembly, Buffer.from('fake-tarball', 'utf8')); @@ -571,6 +560,9 @@ describe('markers for un-supported languages', () => { `/docs-sub2-python.json${constants.NOT_SUPPORTED_SUFFIX}` ); + // nothing to delete + mockDeleteRequest(); + const { created } = await transliterate(event); expect(created).toEqual([ @@ -594,97 +586,60 @@ class MockDocumentation { } function mockFetchRequests(assembly: spec.Assembly, tarball: Buffer) { - AWSMock.mock( - 'S3', - 'getObject', - ( - request: AWS.S3.GetObjectRequest, - callback: Response - ) => { - if (request.Key.endsWith(constants.ASSEMBLY_KEY_SUFFIX)) { - callback(null, { - Body: JSON.stringify(assembly), - }); - } else if (request.Key.endsWith(constants.PACKAGE_KEY_SUFFIX)) { - callback(null, { - Body: JSON.stringify(tarball), - }); - } else { - throw new Error(`Unexpected GET request: ${request.Key}`); - } - } - ); -} - -function mockHeadRequest(...suffixes: string[]) { - AWSMock.mock( - 'S3', - 'headObject', - ( - request: AWS.S3.HeadObjectRequest, - cb: Response - ) => { - if (suffixes.filter((s) => request.Key.endsWith(s)).length > 0) { - return cb(null, {}); - } - class NotFound extends Error implements AWSError { - public code = 'NotFound'; - public message = 'Not Found'; - public time = new Date(); - } - return cb(new NotFound()); + mockS3.on(GetObjectCommand).callsFake((request) => { + if (request.Key.endsWith(constants.ASSEMBLY_KEY_SUFFIX)) { + const stream = new Readable(); + stream.push(JSON.stringify(assembly)); + stream.push(null); + return { + Body: sdkStreamMixin(stream), + }; + } else if (request.Key.endsWith(constants.PACKAGE_KEY_SUFFIX)) { + const stream = new Readable(); + stream.push(tarball); + stream.push(null); + return { + Body: sdkStreamMixin(stream), + }; + } else { + throw new NotFound({ + message: `NotFound GET request: ${request.Key}`, + $metadata: {}, + }); } - ); + }); } function mockPutRequest(...suffixes: string[]) { - AWSMock.mock( - 'S3', - 'putObject', - ( - request: AWS.S3.PutObjectRequest, - callback: Response - ) => { - if (suffixes.filter((s) => request.Key.endsWith(s)).length > 0) { - callback(null, { VersionId: `versionId-${request.Key}` }); - } else { - throw new Error(`Unexpected PUT request: ${request.Key}`); - } + mockS3.on(PutObjectCommand).callsFake((request) => { + if (suffixes.filter((s) => request.Key.endsWith(s)).length > 0) { + return { VersionId: `versionId-${request.Key}` }; + } else { + throw new Error(`Unexpected PUT request: ${request.Key}`); } - ); + }); } function mockPutRequestCollectAll() { const ret = new Array(); - AWSMock.mock( - 'S3', - 'putObject', - ( - request: AWS.S3.PutObjectRequest, - callback: Response - ) => { - ret.push(request.Key); - callback(null, { VersionId: `versionId-${request.Key}` }); - } - ); + mockS3.on(PutObjectCommand).callsFake((request) => { + ret.push(request.Key); + return { VersionId: `versionId-${request.Key}` }; + }); return ret; } function mockDeleteRequest(...suffixes: string[]) { - AWSMock.mock( - 'S3', - 'deleteObject', - ( - request: AWS.S3.DeleteObjectRequest, - callback: Response - ) => { - if (suffixes.filter((s) => request.Key.endsWith(s)).length > 0) { - callback(null, { VersionId: `versionId-${request.Key}` }); - } else { - throw new Error(`Unexpected PUT request: ${request.Key}`); - } + mockS3.on(DeleteObjectCommand).callsFake((request) => { + if (suffixes.filter((s) => request.Key.endsWith(s)).length > 0) { + return { VersionId: `versionId-${request.Key}` }; + } else { + throw new NotFound({ + message: `NotFound DELETE request: ${request.Key}`, + $metadata: {}, + }); } - ); + }); } function range(n: number): number[] { diff --git a/src/__tests__/devapp/__snapshots__/snapshot.test.ts.snap b/src/__tests__/devapp/__snapshots__/snapshot.test.ts.snap index 27d105bc8..7877f8b97 100644 --- a/src/__tests__/devapp/__snapshots__/snapshot.test.ts.snap +++ b/src/__tests__/devapp/__snapshots__/snapshot.test.ts.snap @@ -2665,7 +2665,7 @@ Direct link to the function: /lambda/home#/functions/", "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}", }, - "S3Key": "c609e81e93fe8175f65442b25bf3c9d5dd4a184c6d40c4c2094b14a4ccd893a3.zip", + "S3Key": "92c30ddb1baaf0771dac0f79d4c3b1a6984baf8eac73e12cb0ab04f3f22fd096.zip", }, "Description": "[ConstructHub/Ingestion] Ingests new package versions into the Construct Hub", "Environment": { @@ -7071,7 +7071,7 @@ Warning: messages that resulted in a failed exectuion will NOT be in the DLQ!", ], "Essential": true, "Image": { - "Fn::Sub": "\${AWS::AccountId}.dkr.ecr.\${AWS::Region}.\${AWS::URLSuffix}/cdk-hnb659fds-container-assets-\${AWS::AccountId}-\${AWS::Region}:d879a2b37f21ee9d92e1763519cbbc879549749b1b2fa2498725e8162e40770d", + "Fn::Sub": "\${AWS::AccountId}.dkr.ecr.\${AWS::Region}.\${AWS::URLSuffix}/cdk-hnb659fds-container-assets-\${AWS::AccountId}-\${AWS::Region}:163c30075527137d291e3aef3865f2d7fabc82baf8e77bfcba58e32d2ce57564", }, "LogConfiguration": { "LogDriver": "awslogs", diff --git a/src/backend/shared/code-artifact.lambda-shared.ts b/src/backend/shared/code-artifact.lambda-shared.ts index efb05a20c..85a69bfb8 100644 --- a/src/backend/shared/code-artifact.lambda-shared.ts +++ b/src/backend/shared/code-artifact.lambda-shared.ts @@ -1,7 +1,11 @@ +import { rmSync } from 'node:fs'; +import * as fs from 'node:fs/promises'; import { tmpdir } from 'os'; import { join } from 'path'; -import { CodeArtifact } from 'aws-sdk'; -import { mkdtemp, remove, writeFile } from 'fs-extra'; +import { + CodeartifactClient, + GetAuthorizationTokenCommand, +} from '@aws-sdk/client-codeartifact'; import { shellOut, shellOutWithOutput } from './shell-out.lambda-shared'; export interface CodeArtifactProps { @@ -40,15 +44,15 @@ export async function logInWithCodeArtifact({ // Remove the protocol part of the endpoint URL, keeping the rest intact. const protoRelativeEndpoint = endpoint.replace(/^[^:]+:/, ''); - const { authorizationToken } = await new CodeArtifact({ + const { authorizationToken } = await new CodeartifactClient({ endpoint: apiEndpoint, - }) - .getAuthorizationToken({ + }).send( + new GetAuthorizationTokenCommand({ domain, domainOwner, durationSeconds: 0, // Expires at the same time as the temporary credentials in use. }) - .promise(); + ); await shellOut('npm', 'config', 'set', `registry=${endpoint}`); await shellOut( @@ -69,20 +73,20 @@ export async function logInWithCodeArtifact({ * Publishes the provided tarball to the specified CodeArtifact repository. * * @param tarball a Buffer containing the tarball for the published package. - * @param opts the informations about the CodeArtifact repository. + * @param opts the information about the CodeArtifact repository. */ export async function codeArtifactPublishPackage( tarball: Buffer, opts: CodeArtifactProps ) { // Working in a temporary directory, so we can log into CodeArtifact and not leave traces. - const cwd = await mkdtemp(join(tmpdir(), 'npm-publish-')); + const cwd = await fs.mkdtemp(join(tmpdir(), 'npm-publish-')); const oldHome = process.env.HOME; try { process.env.HOME = cwd; await logInWithCodeArtifact(opts); const tarballPath = join(cwd, 'tarball.tgz'); - await writeFile(tarballPath, tarball); + await fs.writeFile(tarballPath, tarball); const { exitCode, signal, stdout } = await shellOutWithOutput( 'npm', 'publish', @@ -110,6 +114,6 @@ export async function codeArtifactPublishPackage( } finally { // Restore the previous environment, and remove temporary directory process.env.HOME = oldHome; - await remove(cwd); + rmSync(cwd, { recursive: true, force: true }); } } diff --git a/src/backend/transliterator/transliterator.ecstask.ts b/src/backend/transliterator/transliterator.ecstask.ts index 31251a875..574449f68 100644 --- a/src/backend/transliterator/transliterator.ecstask.ts +++ b/src/backend/transliterator/transliterator.ecstask.ts @@ -1,18 +1,24 @@ +import { rmSync } from 'node:fs'; +import * as fs from 'node:fs/promises'; import * as os from 'os'; import * as path from 'path'; +import { + DeleteObjectCommand, + DeleteObjectCommandOutput, + GetObjectCommand, + NotFound, + PutObjectCommand, + PutObjectCommandOutput, + S3Client, +} from '@aws-sdk/client-s3'; import { Assembly } from '@jsii/spec'; +import { StreamingBlobPayloadInputTypes } from '@smithy/types'; import { Sema } from 'async-sema'; import { metricScope, Unit } from 'aws-embedded-metrics'; -import type { PromiseResult } from 'aws-sdk/lib/request'; -import * as fs from 'fs-extra'; import * as docgen from 'jsii-docgen'; - -import { MarkdownRenderer } from 'jsii-docgen/lib/docgen/render/markdown-render'; -import { JsiiEntity } from 'jsii-docgen/lib/docgen/schema'; import { MetricName, METRICS_NAMESPACE } from './constants'; import { writeFile } from './util'; import type { S3ObjectVersion, TransliteratorInput } from '../payload-schema'; -import * as aws from '../shared/aws.lambda-shared'; import { logInWithCodeArtifact } from '../shared/code-artifact.lambda-shared'; import { compressContent } from '../shared/compress-content.lambda-shared'; import * as constants from '../shared/constants'; @@ -29,6 +35,12 @@ const S3_SEMAPHORE = new Sema( parseInt(process.env.MAX_CONCURRENT_S3_REQUESTS ?? '16', 10) ); +const S3_CLIENT = new S3Client({ + // https://docs.aws.amazon.com/sdkref/latest/guide/feature-retry-behavior.html#standardvsadaptive + // This works because S3 throttles requests based on prefix + retryMode: 'ADAPTIVE', +}); + /** * This function receives an S3 event, and for each record, proceeds to download * the `.jsii` assembly the event refers to, transliterates it to the language, @@ -94,7 +106,7 @@ export function transliterate( const npmCacheDir = process.env.NPM_CACHE; if (npmCacheDir) { // Create it if it does not exist yet... - await fs.mkdirp(npmCacheDir); + await fs.mkdir(npmCacheDir, { recursive: true }); console.log(`Using shared NPM cache at: ${npmCacheDir}`); await shellOut('npm', 'config', 'set', `cache=${npmCacheDir}`); } @@ -117,11 +129,9 @@ export function transliterate( console.log(`Source Version: ${event.assembly.versionId}`); console.log(`Fetching assembly: ${event.assembly.key}`); - const assemblyResponse = await retry(() => - aws - .s3() - .getObject({ Bucket: event.bucket, Key: event.assembly.key }) - .promise() + + const assemblyResponse = await S3_CLIENT.send( + new GetObjectCommand({ Bucket: event.bucket, Key: event.assembly.key }) ); if (!assemblyResponse.Body) { throw new Error( @@ -129,40 +139,41 @@ export function transliterate( ); } - const assembly = JSON.parse( - assemblyResponse.Body.toString('utf-8') - ) as Assembly; + const assembly = (await assemblyResponse.Body.transformToString( + 'utf-8' + ).then(JSON.parse)) as Assembly; const submoduleFqns = Object.keys(assembly.submodules ?? {}); console.log( `Assembly ${assembly.name} has ${submoduleFqns.length} submodules.` ); console.log(`Fetching package: ${event.package.key}`); - const tarballExists = await aws.s3ObjectExists( - event.bucket, - event.package.key - ); - if (!tarballExists) { - throw new Error( - `Tarball does not exist at key ${event.package.key} in bucket ${event.bucket}.` + + const tmpdir = await fs.mkdtemp(path.join(os.tmpdir(), 'packages-')); + const tarball = path.join(tmpdir, 'package.tgz'); + + try { + const tarballResponse = await S3_CLIENT.send( + new GetObjectCommand({ Bucket: event.bucket, Key: event.package.key }) ); + if (!tarballResponse.Body) { + throw new Error( + `Tarball has no body at key ${event.package.key} in bucket ${event.bucket}.` + ); + } + + await writeFile(tarball, tarballResponse.Body!); + } catch (error: any) { + if (error instanceof NotFound || error.name === 'NotFound') { + throw new Error( + `Tarball does not exist at key ${event.package.key} in bucket ${event.bucket}.` + ); + } + throw error; } - const readStream = aws - .s3() - .getObject({ Bucket: event.bucket, Key: event.package.key }) - .createReadStream(); - const tmpdir = fs.mkdtempSync(path.join(os.tmpdir(), 'packages-')); - const tarball = path.join(tmpdir, 'package.tgz'); - await writeFile(tarball, readStream); - const uploads = new Map< - string, - Promise> - >(); - const deletions = new Map< - string, - Promise> - >(); + const uploads = new Map>(); + const deletions = new Map>(); let unprocessable: boolean = false; @@ -179,12 +190,15 @@ export function transliterate( async function unmarkPackage(marker: string) { const key = event.assembly.key.replace(/\/[^/]+$/, marker); - const marked = await aws.s3ObjectExists(event.bucket, key); - if (!marked) { - return; + try { + const deletion = await deleteFile(event.bucket, key); + deletions.set(key, Promise.resolve(deletion)); + } catch (error: any) { + if (error instanceof NotFound || error.name === 'NotFound') { + return; + } + deletions.set(key, Promise.reject(error)); } - const deletion = deleteFile(event.bucket, key); - deletions.set(key, deletion); } console.log(`Generating documentation for ${packageFqn}...`); @@ -250,10 +264,13 @@ export function transliterate( ); uploads.set(jsonKey, jsonUpload); - const markdown = MarkdownRenderer.fromSchema(json.content, { - anchorFormatter, - linkFormatter: linkFormatter(docgenLang), - }); + const markdown = docgen.MarkdownRenderer.fromSchema( + json.content, + { + anchorFormatter, + linkFormatter: linkFormatter(docgenLang), + } + ); const page = Buffer.from(markdown.render()); metrics.putMetric( @@ -416,7 +433,7 @@ async function ensureWritableHome(cb: () => Promise): Promise { return await cb(); } finally { process.env.HOME = oldHome; - await fs.remove(fakeHome); + rmSync(fakeHome, { recursive: true, force: true }); console.log(`Cleaned-up temporary $HOME directory: ${fakeHome}`); } } @@ -425,9 +442,9 @@ async function uploadFile( bucket: string, key: string, sourceVersionId?: string, - body?: AWS.S3.Body, + body?: StreamingBlobPayloadInputTypes, contentEncoding?: 'gzip' -) { +): Promise { const contentType = key.endsWith('.md') ? 'text/markdown; charset=UTF-8' : key.endsWith('.json') @@ -436,49 +453,52 @@ async function uploadFile( await S3_SEMAPHORE.acquire(); try { - console.log(S3_SEMAPHORE.nrWaiting() + ' S3 calls are waiting'); - return await retry(() => - aws - .s3() - .putObject({ - Bucket: bucket, - Key: key, - Body: body, - // We may not import anything that uses 'aws-cdk-lib' here - CacheControl: - 'public, max-age=300, must-revalidate, s-maxage=60, proxy-revalidate', - ContentEncoding: contentEncoding, - ContentType: contentType, - Metadata: { - 'Origin-Version-Id': sourceVersionId ?? 'N/A', - }, - }) - .promise() + logSemaphoreQueue('uploadFile'); + return await S3_CLIENT.send( + new PutObjectCommand({ + Bucket: bucket, + Key: key, + Body: body, + // We may not import anything that uses 'aws-cdk-lib' here + CacheControl: + 'public, max-age=300, must-revalidate, s-maxage=60, proxy-revalidate', + ContentEncoding: contentEncoding, + ContentType: contentType, + Metadata: { + 'Origin-Version-Id': sourceVersionId ?? 'N/A', + }, + }) ); } finally { S3_SEMAPHORE.release(); } } -async function deleteFile(bucket: string, key: string) { +async function deleteFile( + bucket: string, + key: string +): Promise { await S3_SEMAPHORE.acquire(); try { - console.log(S3_SEMAPHORE.nrWaiting() + ' S3 calls are waiting'); - return await retry(() => - aws - .s3() - .deleteObject({ - Bucket: bucket, - Key: key, - }) - .promise() + logSemaphoreQueue('deleteFile'); + return await S3_CLIENT.send( + new DeleteObjectCommand({ + Bucket: bucket, + Key: key, + }) ); } finally { S3_SEMAPHORE.release(); } } -function anchorFormatter(type: JsiiEntity) { +function logSemaphoreQueue(source: string) { + if (S3_SEMAPHORE.nrWaiting() >= 1) { + console.log(`${source}: ${S3_SEMAPHORE.nrWaiting()} S3 calls are waiting`); + } +} + +function anchorFormatter(type: docgen.JsiiEntity) { const name = getAssemblyRelativeName(type); // BucketProps.Initializer.parameter.accessControl const [base, ...rest] = name.split('.'); if (rest.length > 0) { @@ -501,7 +521,7 @@ function formatArtifactKey( } function linkFormatter(lang: docgen.Language) { - const formatter = (type: JsiiEntity) => { + const formatter = (type: docgen.JsiiEntity) => { const name = getAssemblyRelativeName(type); // BucketProps.Initializer.parameter.accessControl const [baseName, ...rest] = name.split('.'); const hash = '#' + rest.join('.'); // #Initializer.parameter.accessControl @@ -516,7 +536,7 @@ function linkFormatter(lang: docgen.Language) { * Converts a type's id to an assembly-relative version, e.g.: * `aws-cdk-lib.aws_s3.Bucket.parameter.accessControl` => `Bucket.parameter.accessControl` */ -function getAssemblyRelativeName(type: JsiiEntity): string { +function getAssemblyRelativeName(type: docgen.JsiiEntity): string { let name = type.id; if (!name.startsWith(type.packageName)) { throw new Error( @@ -545,44 +565,3 @@ interface S3Object { readonly key: string; readonly versionId?: string; } - -/** - * Retry a function a number of times if it happens to get throttled - */ -async function retry(cb: () => Promise): Promise { - const deadline = Date.now() + 60_000; // one minute - let sleepMs = 20; - while (true) { - try { - return await cb(); - } catch (e) { - if (!isRetryableError(e)) { - console.log(`Error is not retryable`); - throw e; - } - - if (Date.now() >= deadline) { - console.log(`Retry wait time reached limit: ${sleepMs}`); - throw e; - } - - await sleep(Math.floor(Math.random() * sleepMs)); - sleepMs *= 2; - } - } -} - -function isRetryableError(e: any) { - // Prepare for AWS SDK v3 already - return ( - e.code === 'SlowDown' || - e.name === 'SlowDown' || - e.code === 503 || - e.statusCode === 503 || - e.retryable === true - ); -} - -function sleep(ms: number): Promise { - return new Promise((ok) => setTimeout(ok, ms)); -} diff --git a/test/integ.transliterator.ecstask.ts.snapshot/TransliteratorEcsTaskInteg.assets.json b/test/integ.transliterator.ecstask.ts.snapshot/TransliteratorEcsTaskInteg.assets.json index 7e3e1af86..2b5b7e228 100644 --- a/test/integ.transliterator.ecstask.ts.snapshot/TransliteratorEcsTaskInteg.assets.json +++ b/test/integ.transliterator.ecstask.ts.snapshot/TransliteratorEcsTaskInteg.assets.json @@ -40,7 +40,7 @@ } } }, - "7fe8899c59ab75778ab2535f72f25b7cff45d3ed9e3e30ba5a0aff7efa2f47fd": { + "5734d7ab060d267f335136d0ba9378f40a5698385392dee3bdcd54caf075dadc": { "source": { "path": "TransliteratorEcsTaskInteg.template.json", "packaging": "file" @@ -48,22 +48,22 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "7fe8899c59ab75778ab2535f72f25b7cff45d3ed9e3e30ba5a0aff7efa2f47fd.json", + "objectKey": "5734d7ab060d267f335136d0ba9378f40a5698385392dee3bdcd54caf075dadc.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } } }, "dockerImages": { - "86da6370fa2a9edc85ac82ca6da4eef84b25b5f6d2227bdd0ef2e3c838c3af78": { + "163c30075527137d291e3aef3865f2d7fabc82baf8e77bfcba58e32d2ce57564": { "source": { - "directory": "asset.86da6370fa2a9edc85ac82ca6da4eef84b25b5f6d2227bdd0ef2e3c838c3af78.bundle", + "directory": "asset.163c30075527137d291e3aef3865f2d7fabc82baf8e77bfcba58e32d2ce57564.bundle", "platform": "linux/arm64" }, "destinations": { "current_account-current_region": { "repositoryName": "cdk-hnb659fds-container-assets-${AWS::AccountId}-${AWS::Region}", - "imageTag": "86da6370fa2a9edc85ac82ca6da4eef84b25b5f6d2227bdd0ef2e3c838c3af78", + "imageTag": "163c30075527137d291e3aef3865f2d7fabc82baf8e77bfcba58e32d2ce57564", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-image-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/test/integ.transliterator.ecstask.ts.snapshot/TransliteratorEcsTaskInteg.template.json b/test/integ.transliterator.ecstask.ts.snapshot/TransliteratorEcsTaskInteg.template.json index 12a8bd2b5..4192459ba 100644 --- a/test/integ.transliterator.ecstask.ts.snapshot/TransliteratorEcsTaskInteg.template.json +++ b/test/integ.transliterator.ecstask.ts.snapshot/TransliteratorEcsTaskInteg.template.json @@ -1485,7 +1485,7 @@ ], "Essential": true, "Image": { - "Fn::Sub": "${AWS::AccountId}.dkr.ecr.${AWS::Region}.${AWS::URLSuffix}/cdk-hnb659fds-container-assets-${AWS::AccountId}-${AWS::Region}:86da6370fa2a9edc85ac82ca6da4eef84b25b5f6d2227bdd0ef2e3c838c3af78" + "Fn::Sub": "${AWS::AccountId}.dkr.ecr.${AWS::Region}.${AWS::URLSuffix}/cdk-hnb659fds-container-assets-${AWS::AccountId}-${AWS::Region}:163c30075527137d291e3aef3865f2d7fabc82baf8e77bfcba58e32d2ce57564" }, "LogConfiguration": { "LogDriver": "awslogs", diff --git a/test/integ.transliterator.ecstask.ts.snapshot/manifest.json b/test/integ.transliterator.ecstask.ts.snapshot/manifest.json index b5435163e..83cdd520c 100644 --- a/test/integ.transliterator.ecstask.ts.snapshot/manifest.json +++ b/test/integ.transliterator.ecstask.ts.snapshot/manifest.json @@ -18,7 +18,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/7fe8899c59ab75778ab2535f72f25b7cff45d3ed9e3e30ba5a0aff7efa2f47fd.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/5734d7ab060d267f335136d0ba9378f40a5698385392dee3bdcd54caf075dadc.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -330,7 +330,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/8ccc2450b513f94c5f172d306dfb8aea1e4bd56ed425a474ce70e91151bcc656.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/c58e15f764cc8151a7d2c4b0acf232e94fca93b829e20ef090a20cf5517bf58c.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ diff --git a/test/integ.transliterator.ecstask.ts.snapshot/transliteratorintegDefaultTestDeployAssert109DC8B0.assets.json b/test/integ.transliterator.ecstask.ts.snapshot/transliteratorintegDefaultTestDeployAssert109DC8B0.assets.json index 68d6c89ab..88d2c401a 100644 --- a/test/integ.transliterator.ecstask.ts.snapshot/transliteratorintegDefaultTestDeployAssert109DC8B0.assets.json +++ b/test/integ.transliterator.ecstask.ts.snapshot/transliteratorintegDefaultTestDeployAssert109DC8B0.assets.json @@ -14,7 +14,7 @@ } } }, - "8ccc2450b513f94c5f172d306dfb8aea1e4bd56ed425a474ce70e91151bcc656": { + "c58e15f764cc8151a7d2c4b0acf232e94fca93b829e20ef090a20cf5517bf58c": { "source": { "path": "transliteratorintegDefaultTestDeployAssert109DC8B0.template.json", "packaging": "file" @@ -22,7 +22,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "8ccc2450b513f94c5f172d306dfb8aea1e4bd56ed425a474ce70e91151bcc656.json", + "objectKey": "c58e15f764cc8151a7d2c4b0acf232e94fca93b829e20ef090a20cf5517bf58c.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/test/integ.transliterator.ecstask.ts.snapshot/transliteratorintegDefaultTestDeployAssert109DC8B0.template.json b/test/integ.transliterator.ecstask.ts.snapshot/transliteratorintegDefaultTestDeployAssert109DC8B0.template.json index dd7b0092c..f8bf1fd0f 100644 --- a/test/integ.transliterator.ecstask.ts.snapshot/transliteratorintegDefaultTestDeployAssert109DC8B0.template.json +++ b/test/integ.transliterator.ecstask.ts.snapshot/transliteratorintegDefaultTestDeployAssert109DC8B0.template.json @@ -41,7 +41,7 @@ "outputPaths": [ "executionArn" ], - "salt": "1725650721068" + "salt": "1725967583740" }, "UpdateReplacePolicy": "Delete", "DeletionPolicy": "Delete" @@ -158,7 +158,7 @@ } }, "flattenResponse": "false", - "salt": "1725650721069" + "salt": "1725967583741" }, "UpdateReplacePolicy": "Delete", "DeletionPolicy": "Delete" diff --git a/test/integ.transliterator.ecstask.ts.snapshot/tree.json b/test/integ.transliterator.ecstask.ts.snapshot/tree.json index 014e3d7c8..0e7124fec 100644 --- a/test/integ.transliterator.ecstask.ts.snapshot/tree.json +++ b/test/integ.transliterator.ecstask.ts.snapshot/tree.json @@ -1875,7 +1875,7 @@ { "essential": true, "image": { - "Fn::Sub": "${AWS::AccountId}.dkr.ecr.${AWS::Region}.${AWS::URLSuffix}/cdk-hnb659fds-container-assets-${AWS::AccountId}-${AWS::Region}:86da6370fa2a9edc85ac82ca6da4eef84b25b5f6d2227bdd0ef2e3c838c3af78" + "Fn::Sub": "${AWS::AccountId}.dkr.ecr.${AWS::Region}.${AWS::URLSuffix}/cdk-hnb659fds-container-assets-${AWS::AccountId}-${AWS::Region}:163c30075527137d291e3aef3865f2d7fabc82baf8e77bfcba58e32d2ce57564" }, "name": "Resource", "logConfiguration": { diff --git a/yarn.lock b/yarn.lock index 413cc39cf..8842ca785 100644 --- a/yarn.lock +++ b/yarn.lock @@ -95,6 +95,36 @@ dependencies: "@cdklabs/tskb" "^0.0.3" +"@aws-crypto/crc32@5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/crc32/-/crc32-5.2.0.tgz#cfcc22570949c98c6689cfcbd2d693d36cdae2e1" + integrity sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg== + dependencies: + "@aws-crypto/util" "^5.2.0" + "@aws-sdk/types" "^3.222.0" + tslib "^2.6.2" + +"@aws-crypto/crc32c@5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/crc32c/-/crc32c-5.2.0.tgz#4e34aab7f419307821509a98b9b08e84e0c1917e" + integrity sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag== + dependencies: + "@aws-crypto/util" "^5.2.0" + "@aws-sdk/types" "^3.222.0" + tslib "^2.6.2" + +"@aws-crypto/sha1-browser@5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/sha1-browser/-/sha1-browser-5.2.0.tgz#b0ee2d2821d3861f017e965ef3b4cb38e3b6a0f4" + integrity sha512-OH6lveCFfcDjX4dbAvCFSYUjJZjDr/3XJ3xHtjn3Oj5b9RjojQo8npoLeA/bNwkOkrSQ0wgrHzXk4tDRxGKJeg== + dependencies: + "@aws-crypto/supports-web-crypto" "^5.2.0" + "@aws-crypto/util" "^5.2.0" + "@aws-sdk/types" "^3.222.0" + "@aws-sdk/util-locate-window" "^3.0.0" + "@smithy/util-utf8" "^2.0.0" + tslib "^2.6.2" + "@aws-crypto/sha256-browser@5.2.0": version "5.2.0" resolved "https://registry.yarnpkg.com/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz#153895ef1dba6f9fce38af550e0ef58988eb649e" @@ -133,6 +163,118 @@ "@smithy/util-utf8" "^2.0.0" tslib "^2.6.2" +"@aws-sdk/client-codeartifact@^3.645.0": + version "3.645.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-codeartifact/-/client-codeartifact-3.645.0.tgz#27a2eb009612f37f12e9699feb795315d9008e38" + integrity sha512-HMBj6seciJTDc8xQEC6SotLJKmy0JNOrITxOxZnF9WUidGMBQWpt9mcrouwbyGaCHnyn+I465RIMPOiZ6HsNAg== + dependencies: + "@aws-crypto/sha256-browser" "5.2.0" + "@aws-crypto/sha256-js" "5.2.0" + "@aws-sdk/client-sso-oidc" "3.645.0" + "@aws-sdk/client-sts" "3.645.0" + "@aws-sdk/core" "3.635.0" + "@aws-sdk/credential-provider-node" "3.645.0" + "@aws-sdk/middleware-host-header" "3.620.0" + "@aws-sdk/middleware-logger" "3.609.0" + "@aws-sdk/middleware-recursion-detection" "3.620.0" + "@aws-sdk/middleware-user-agent" "3.645.0" + "@aws-sdk/region-config-resolver" "3.614.0" + "@aws-sdk/types" "3.609.0" + "@aws-sdk/util-endpoints" "3.645.0" + "@aws-sdk/util-user-agent-browser" "3.609.0" + "@aws-sdk/util-user-agent-node" "3.614.0" + "@smithy/config-resolver" "^3.0.5" + "@smithy/core" "^2.4.0" + "@smithy/fetch-http-handler" "^3.2.4" + "@smithy/hash-node" "^3.0.3" + "@smithy/invalid-dependency" "^3.0.3" + "@smithy/middleware-content-length" "^3.0.5" + "@smithy/middleware-endpoint" "^3.1.0" + "@smithy/middleware-retry" "^3.0.15" + "@smithy/middleware-serde" "^3.0.3" + "@smithy/middleware-stack" "^3.0.3" + "@smithy/node-config-provider" "^3.1.4" + "@smithy/node-http-handler" "^3.1.4" + "@smithy/protocol-http" "^4.1.0" + "@smithy/smithy-client" "^3.2.0" + "@smithy/types" "^3.3.0" + "@smithy/url-parser" "^3.0.3" + "@smithy/util-base64" "^3.0.0" + "@smithy/util-body-length-browser" "^3.0.0" + "@smithy/util-body-length-node" "^3.0.0" + "@smithy/util-defaults-mode-browser" "^3.0.15" + "@smithy/util-defaults-mode-node" "^3.0.15" + "@smithy/util-endpoints" "^2.0.5" + "@smithy/util-middleware" "^3.0.3" + "@smithy/util-retry" "^3.0.3" + "@smithy/util-stream" "^3.1.3" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/client-s3@^3.645.0": + version "3.645.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-s3/-/client-s3-3.645.0.tgz#a0d201248ee711e79f3e515d870b02547a652102" + integrity sha512-RjT/mfNv4yr1uv/+aEXgSIxC5EB+yHPSU7hH0KZOZrvZEFASLl0i4FeoHzbMEOH5KdKGAi0uu3zRP3D1y45sKg== + dependencies: + "@aws-crypto/sha1-browser" "5.2.0" + "@aws-crypto/sha256-browser" "5.2.0" + "@aws-crypto/sha256-js" "5.2.0" + "@aws-sdk/client-sso-oidc" "3.645.0" + "@aws-sdk/client-sts" "3.645.0" + "@aws-sdk/core" "3.635.0" + "@aws-sdk/credential-provider-node" "3.645.0" + "@aws-sdk/middleware-bucket-endpoint" "3.620.0" + "@aws-sdk/middleware-expect-continue" "3.620.0" + "@aws-sdk/middleware-flexible-checksums" "3.620.0" + "@aws-sdk/middleware-host-header" "3.620.0" + "@aws-sdk/middleware-location-constraint" "3.609.0" + "@aws-sdk/middleware-logger" "3.609.0" + "@aws-sdk/middleware-recursion-detection" "3.620.0" + "@aws-sdk/middleware-sdk-s3" "3.635.0" + "@aws-sdk/middleware-ssec" "3.609.0" + "@aws-sdk/middleware-user-agent" "3.645.0" + "@aws-sdk/region-config-resolver" "3.614.0" + "@aws-sdk/signature-v4-multi-region" "3.635.0" + "@aws-sdk/types" "3.609.0" + "@aws-sdk/util-endpoints" "3.645.0" + "@aws-sdk/util-user-agent-browser" "3.609.0" + "@aws-sdk/util-user-agent-node" "3.614.0" + "@aws-sdk/xml-builder" "3.609.0" + "@smithy/config-resolver" "^3.0.5" + "@smithy/core" "^2.4.0" + "@smithy/eventstream-serde-browser" "^3.0.6" + "@smithy/eventstream-serde-config-resolver" "^3.0.3" + "@smithy/eventstream-serde-node" "^3.0.5" + "@smithy/fetch-http-handler" "^3.2.4" + "@smithy/hash-blob-browser" "^3.1.2" + "@smithy/hash-node" "^3.0.3" + "@smithy/hash-stream-node" "^3.1.2" + "@smithy/invalid-dependency" "^3.0.3" + "@smithy/md5-js" "^3.0.3" + "@smithy/middleware-content-length" "^3.0.5" + "@smithy/middleware-endpoint" "^3.1.0" + "@smithy/middleware-retry" "^3.0.15" + "@smithy/middleware-serde" "^3.0.3" + "@smithy/middleware-stack" "^3.0.3" + "@smithy/node-config-provider" "^3.1.4" + "@smithy/node-http-handler" "^3.1.4" + "@smithy/protocol-http" "^4.1.0" + "@smithy/smithy-client" "^3.2.0" + "@smithy/types" "^3.3.0" + "@smithy/url-parser" "^3.0.3" + "@smithy/util-base64" "^3.0.0" + "@smithy/util-body-length-browser" "^3.0.0" + "@smithy/util-body-length-node" "^3.0.0" + "@smithy/util-defaults-mode-browser" "^3.0.15" + "@smithy/util-defaults-mode-node" "^3.0.15" + "@smithy/util-endpoints" "^2.0.5" + "@smithy/util-middleware" "^3.0.3" + "@smithy/util-retry" "^3.0.3" + "@smithy/util-stream" "^3.1.3" + "@smithy/util-utf8" "^3.0.0" + "@smithy/util-waiter" "^3.1.2" + tslib "^2.6.2" + "@aws-sdk/client-sfn@^3.645.0": version "3.645.0" resolved "https://registry.yarnpkg.com/@aws-sdk/client-sfn/-/client-sfn-3.645.0.tgz#882d85894664e34cd644d3635a6d96389aac7e21" @@ -426,6 +568,43 @@ "@smithy/types" "^3.3.0" tslib "^2.6.2" +"@aws-sdk/middleware-bucket-endpoint@3.620.0": + version "3.620.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.620.0.tgz#c5dc0e98b6209a91479cad6c2c74fbc5a3429fab" + integrity sha512-eGLL0W6L3HDb3OACyetZYOWpHJ+gLo0TehQKeQyy2G8vTYXqNTeqYhuI6up9HVjBzU9eQiULVQETmgQs7TFaRg== + dependencies: + "@aws-sdk/types" "3.609.0" + "@aws-sdk/util-arn-parser" "3.568.0" + "@smithy/node-config-provider" "^3.1.4" + "@smithy/protocol-http" "^4.1.0" + "@smithy/types" "^3.3.0" + "@smithy/util-config-provider" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-expect-continue@3.620.0": + version "3.620.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.620.0.tgz#6a362c0f0696dc6749108a33de9998e0fa6b50ec" + integrity sha512-QXeRFMLfyQ31nAHLbiTLtk0oHzG9QLMaof5jIfqcUwnOkO8YnQdeqzakrg1Alpy/VQ7aqzIi8qypkBe2KXZz0A== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/protocol-http" "^4.1.0" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-flexible-checksums@3.620.0": + version "3.620.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.620.0.tgz#42cd48cdc0ad9639545be000bf537969210ce8c5" + integrity sha512-ftz+NW7qka2sVuwnnO1IzBku5ccP+s5qZGeRTPgrKB7OzRW85gthvIo1vQR2w+OwHFk7WJbbhhWwbCbktnP4UA== + dependencies: + "@aws-crypto/crc32" "5.2.0" + "@aws-crypto/crc32c" "5.2.0" + "@aws-sdk/types" "3.609.0" + "@smithy/is-array-buffer" "^3.0.0" + "@smithy/protocol-http" "^4.1.0" + "@smithy/types" "^3.3.0" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + "@aws-sdk/middleware-host-header@3.620.0": version "3.620.0" resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-host-header/-/middleware-host-header-3.620.0.tgz#b561d419a08a984ba364c193376b482ff5224d74" @@ -436,6 +615,15 @@ "@smithy/types" "^3.3.0" tslib "^2.6.2" +"@aws-sdk/middleware-location-constraint@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.609.0.tgz#7ed82d71e5ddcd50683ef2bbde10d1cc2492057e" + integrity sha512-xzsdoTkszGVqGVPjUmgoP7TORiByLueMHieI1fhQL888WPdqctwAx3ES6d/bA9Q/i8jnc6hs+Fjhy8UvBTkE9A== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + "@aws-sdk/middleware-logger@3.609.0": version "3.609.0" resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-logger/-/middleware-logger-3.609.0.tgz#ed44d201f091b8bac908cbf14724c7a4d492553f" @@ -455,6 +643,35 @@ "@smithy/types" "^3.3.0" tslib "^2.6.2" +"@aws-sdk/middleware-sdk-s3@3.635.0": + version "3.635.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.635.0.tgz#be7f61c6033a803cde59ec5a29db266b42fdbc01" + integrity sha512-RLdYJPEV4JL/7NBoFUs7VlP90X++5FlJdxHz0DzCjmiD3qCviKy+Cym3qg1gBgHwucs5XisuClxDrGokhAdTQw== + dependencies: + "@aws-sdk/core" "3.635.0" + "@aws-sdk/types" "3.609.0" + "@aws-sdk/util-arn-parser" "3.568.0" + "@smithy/core" "^2.4.0" + "@smithy/node-config-provider" "^3.1.4" + "@smithy/protocol-http" "^4.1.0" + "@smithy/signature-v4" "^4.1.0" + "@smithy/smithy-client" "^3.2.0" + "@smithy/types" "^3.3.0" + "@smithy/util-config-provider" "^3.0.0" + "@smithy/util-middleware" "^3.0.3" + "@smithy/util-stream" "^3.1.3" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-ssec@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-ssec/-/middleware-ssec-3.609.0.tgz#b87a8bc6133f3f6bdc6801183d0f9dad3f93cf9f" + integrity sha512-GZSD1s7+JswWOTamVap79QiDaIV7byJFssBW68GYjyRS5EBjNfwA/8s+6uE6g39R3ojyTbYOmvcANoZEhSULXg== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + "@aws-sdk/middleware-user-agent@3.645.0": version "3.645.0" resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.645.0.tgz#a6b5792a1f617c749839734213a8e7f920631245" @@ -478,6 +695,18 @@ "@smithy/util-middleware" "^3.0.3" tslib "^2.6.2" +"@aws-sdk/signature-v4-multi-region@3.635.0": + version "3.635.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.635.0.tgz#76e8eb66bfd9b661b4f9768b18aca2e04dd781a2" + integrity sha512-J6QY4/invOkpogCHjSaDON1hF03viPpOnsrzVuCvJMmclS/iG62R4EY0wq1alYll0YmSdmKlpJwHMWwGtqK63Q== + dependencies: + "@aws-sdk/middleware-sdk-s3" "3.635.0" + "@aws-sdk/types" "3.609.0" + "@smithy/protocol-http" "^4.1.0" + "@smithy/signature-v4" "^4.1.0" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + "@aws-sdk/token-providers@3.614.0": version "3.614.0" resolved "https://registry.yarnpkg.com/@aws-sdk/token-providers/-/token-providers-3.614.0.tgz#88da04f6d4ce916b0b0f6e045676d04201fb47fd" @@ -497,6 +726,13 @@ "@smithy/types" "^3.3.0" tslib "^2.6.2" +"@aws-sdk/util-arn-parser@3.568.0": + version "3.568.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-arn-parser/-/util-arn-parser-3.568.0.tgz#6a19a8c6bbaa520b6be1c278b2b8c17875b91527" + integrity sha512-XUKJWWo+KOB7fbnPP0+g/o5Ulku/X53t7i/h+sPHr5xxYTJJ9CYnbToo95mzxe7xWvkLrsNtJ8L+MnNn9INs2w== + dependencies: + tslib "^2.6.2" + "@aws-sdk/util-endpoints@3.645.0": version "3.645.0" resolved "https://registry.yarnpkg.com/@aws-sdk/util-endpoints/-/util-endpoints-3.645.0.tgz#43dba3d4b4cc9762d590903ef6bd8947aba68e1e" @@ -534,6 +770,14 @@ "@smithy/types" "^3.3.0" tslib "^2.6.2" +"@aws-sdk/xml-builder@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/xml-builder/-/xml-builder-3.609.0.tgz#eeb3d5cde000a23cfeeefe0354b6193440dc7d87" + integrity sha512-l9XxNcA4HX98rwCC2/KoiWcmEiRfZe4G+mYwDbCFT87JIMj6GBhLDkAzr/W8KAaA2IDr8Vc6J8fZPgVulxxfMA== + dependencies: + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.24.7": version "7.24.7" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.7.tgz#882fd9e09e8ee324e496bd040401c6f046ef4465" @@ -2224,7 +2468,7 @@ dependencies: type-detect "4.0.8" -"@sinonjs/fake-timers@^10.0.2": +"@sinonjs/fake-timers@^10.0.2", "@sinonjs/fake-timers@^10.3.0": version "10.3.0" resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz#55fdff1ecab9f354019129daf4df0dd4d923ea66" integrity sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA== @@ -2260,6 +2504,29 @@ "@smithy/types" "^3.3.0" tslib "^2.6.2" +"@smithy/abort-controller@^3.1.2": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@smithy/abort-controller/-/abort-controller-3.1.2.tgz#95ac6b07480d0d2afbcface3f0f1ddc3ae6373d7" + integrity sha512-b5g+PNujlfqIib9BjkNB108NyO5aZM/RXjfOCXRCqXQ1oPnIkfvdORrztbGgCZdPe/BN/MKDlrGA7PafKPM2jw== + dependencies: + "@smithy/types" "^3.4.0" + tslib "^2.6.2" + +"@smithy/chunked-blob-reader-native@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-3.0.0.tgz#f1104b30030f76f9aadcbd3cdca4377bd1ba2695" + integrity sha512-VDkpCYW+peSuM4zJip5WDfqvg2Mo/e8yxOv3VF1m11y7B8KKMKVFtmZWDe36Fvk8rGuWrPZHHXZ7rR7uM5yWyg== + dependencies: + "@smithy/util-base64" "^3.0.0" + tslib "^2.6.2" + +"@smithy/chunked-blob-reader@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/chunked-blob-reader/-/chunked-blob-reader-3.0.0.tgz#e5d3b04e9b273ba8b7ede47461e2aa96c8aa49e0" + integrity sha512-sbnURCwjF0gSToGlsBiAmd1lRCmSn72nu9axfJu5lIx6RUEgHu6GwTMbqCdhQSi0Pumcm5vFxsi9XWXb2mTaoA== + dependencies: + tslib "^2.6.2" + "@smithy/config-resolver@^3.0.5": version "3.0.5" resolved "https://registry.yarnpkg.com/@smithy/config-resolver/-/config-resolver-3.0.5.tgz#727978bba7ace754c741c259486a19d3083431fd" @@ -2298,6 +2565,51 @@ "@smithy/url-parser" "^3.0.3" tslib "^2.6.2" +"@smithy/eventstream-codec@^3.1.2": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-codec/-/eventstream-codec-3.1.2.tgz#4a1c72b34400631b829241151984a1ad8c4f963c" + integrity sha512-0mBcu49JWt4MXhrhRAlxASNy0IjDRFU+aWNDRal9OtUJvJNiwDuyKMUONSOjLjSCeGwZaE0wOErdqULer8r7yw== + dependencies: + "@aws-crypto/crc32" "5.2.0" + "@smithy/types" "^3.3.0" + "@smithy/util-hex-encoding" "^3.0.0" + tslib "^2.6.2" + +"@smithy/eventstream-serde-browser@^3.0.6": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-3.0.6.tgz#a4ab4f7cfbd137bcaa54c375276f9214e568fd8f" + integrity sha512-2hM54UWQUOrki4BtsUI1WzmD13/SeaqT/AB3EUJKbcver/WgKNaiJ5y5F5XXuVe6UekffVzuUDrBZVAA3AWRpQ== + dependencies: + "@smithy/eventstream-serde-universal" "^3.0.5" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/eventstream-serde-config-resolver@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-3.0.3.tgz#f852e096d0ad112363b4685e1d441088d1fce67a" + integrity sha512-NVTYjOuYpGfrN/VbRQgn31x73KDLfCXCsFdad8DiIc3IcdxL+dYA9zEQPyOP7Fy2QL8CPy2WE4WCUD+ZsLNfaQ== + dependencies: + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/eventstream-serde-node@^3.0.5": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-node/-/eventstream-serde-node-3.0.5.tgz#2bbf5c9312a28f23bc55ae284efa9499f8b8f982" + integrity sha512-+upXvnHNyZP095s11jF5dhGw/Ihzqwl5G+/KtMnoQOpdfC3B5HYCcDVG9EmgkhJMXJlM64PyN5gjJl0uXFQehQ== + dependencies: + "@smithy/eventstream-serde-universal" "^3.0.5" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/eventstream-serde-universal@^3.0.5": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-3.0.5.tgz#e1cc2f71f4d174a03e00ce4b563395a81dd17bec" + integrity sha512-5u/nXbyoh1s4QxrvNre9V6vfyoLWuiVvvd5TlZjGThIikc3G+uNiG9uOTCWweSRjv1asdDIWK7nOmN7le4RYHQ== + dependencies: + "@smithy/eventstream-codec" "^3.1.2" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + "@smithy/fetch-http-handler@^3.2.4": version "3.2.4" resolved "https://registry.yarnpkg.com/@smithy/fetch-http-handler/-/fetch-http-handler-3.2.4.tgz#c754de7e0ff2541b73ac9ba7cc955940114b3d62" @@ -2309,6 +2621,27 @@ "@smithy/util-base64" "^3.0.0" tslib "^2.6.2" +"@smithy/fetch-http-handler@^3.2.5": + version "3.2.5" + resolved "https://registry.yarnpkg.com/@smithy/fetch-http-handler/-/fetch-http-handler-3.2.5.tgz#c9a6c6c35895ffdfd98b992ecebb1344418d1932" + integrity sha512-DjRtGmK8pKQMIo9+JlAKUt14Z448bg8nAN04yKIvlrrpmpRSG57s5d2Y83npks1r4gPtTRNbAFdQCoj9l3P2KQ== + dependencies: + "@smithy/protocol-http" "^4.1.1" + "@smithy/querystring-builder" "^3.0.4" + "@smithy/types" "^3.4.0" + "@smithy/util-base64" "^3.0.0" + tslib "^2.6.2" + +"@smithy/hash-blob-browser@^3.1.2": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@smithy/hash-blob-browser/-/hash-blob-browser-3.1.2.tgz#90281c1f183d93686fb4f26107f1819644d68829" + integrity sha512-hAbfqN2UbISltakCC2TP0kx4LqXBttEv2MqSPE98gVuDFMf05lU+TpC41QtqGP3Ff5A3GwZMPfKnEy0VmEUpmg== + dependencies: + "@smithy/chunked-blob-reader" "^3.0.0" + "@smithy/chunked-blob-reader-native" "^3.0.0" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + "@smithy/hash-node@^3.0.3": version "3.0.3" resolved "https://registry.yarnpkg.com/@smithy/hash-node/-/hash-node-3.0.3.tgz#82c5cb7b0f1a29ee7319081853d2d158c07dff24" @@ -2319,6 +2652,15 @@ "@smithy/util-utf8" "^3.0.0" tslib "^2.6.2" +"@smithy/hash-stream-node@^3.1.2": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@smithy/hash-stream-node/-/hash-stream-node-3.1.2.tgz#89f0290ae44b113863878e75b10c484ff48af71c" + integrity sha512-PBgDMeEdDzi6JxKwbfBtwQG9eT9cVwsf0dZzLXoJF4sHKHs5HEo/3lJWpn6jibfJwT34I1EBXpBnZE8AxAft6g== + dependencies: + "@smithy/types" "^3.3.0" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + "@smithy/invalid-dependency@^3.0.3": version "3.0.3" resolved "https://registry.yarnpkg.com/@smithy/invalid-dependency/-/invalid-dependency-3.0.3.tgz#8d9fd70e3a94b565a4eba4ffbdc95238e1930528" @@ -2341,6 +2683,15 @@ dependencies: tslib "^2.6.2" +"@smithy/md5-js@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@smithy/md5-js/-/md5-js-3.0.3.tgz#55ee40aa24075b096c39f7910590c18ff7660c98" + integrity sha512-O/SAkGVwpWmelpj/8yDtsaVe6sINHLB1q8YE/+ZQbDxIw3SRLbTZuRaI10K12sVoENdnHqzPp5i3/H+BcZ3m3Q== + dependencies: + "@smithy/types" "^3.3.0" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + "@smithy/middleware-content-length@^3.0.5": version "3.0.5" resolved "https://registry.yarnpkg.com/@smithy/middleware-content-length/-/middleware-content-length-3.0.5.tgz#1680aa4fb2a1c0505756103c9a5c2916307d9035" @@ -2415,6 +2766,17 @@ "@smithy/types" "^3.3.0" tslib "^2.6.2" +"@smithy/node-http-handler@^3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@smithy/node-http-handler/-/node-http-handler-3.2.0.tgz#0473f3cfb88779dacdcbafa877dbf74aac4f1c82" + integrity sha512-5TFqaABbiY7uJMKbqR4OARjwI/l4TRoysDJ75pLpVQyO3EcmeloKYwDGyCtgB9WJniFx3BMkmGCB9+j+QiB+Ww== + dependencies: + "@smithy/abort-controller" "^3.1.2" + "@smithy/protocol-http" "^4.1.1" + "@smithy/querystring-builder" "^3.0.4" + "@smithy/types" "^3.4.0" + tslib "^2.6.2" + "@smithy/property-provider@^3.1.3": version "3.1.3" resolved "https://registry.yarnpkg.com/@smithy/property-provider/-/property-provider-3.1.3.tgz#afd57ea82a3f6c79fbda95e3cb85c0ee0a79f39a" @@ -2431,6 +2793,14 @@ "@smithy/types" "^3.3.0" tslib "^2.6.2" +"@smithy/protocol-http@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@smithy/protocol-http/-/protocol-http-4.1.1.tgz#ffd9c3f8ada9b25add3277b7de84c22dc320f1a6" + integrity sha512-Fm5+8LkeIus83Y8jTL1XHsBGP8sPvE1rEVyKf/87kbOPTbzEDMcgOlzcmYXat2h+nC3wwPtRy8hFqtJS71+Wow== + dependencies: + "@smithy/types" "^3.4.0" + tslib "^2.6.2" + "@smithy/querystring-builder@^3.0.3": version "3.0.3" resolved "https://registry.yarnpkg.com/@smithy/querystring-builder/-/querystring-builder-3.0.3.tgz#6b0e566f885bb84938d077c69e8f8555f686af13" @@ -2440,6 +2810,15 @@ "@smithy/util-uri-escape" "^3.0.0" tslib "^2.6.2" +"@smithy/querystring-builder@^3.0.4": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@smithy/querystring-builder/-/querystring-builder-3.0.4.tgz#1124dfe533e60fd131acffbf78656b8db0a38bbf" + integrity sha512-NEoPAsZPdpfVbF98qm8i5k1XMaRKeEnO47CaL5ja6Y1Z2DgJdwIJuJkTJypKm/IKfp8gc0uimIFLwhml8+/pAw== + dependencies: + "@smithy/types" "^3.4.0" + "@smithy/util-uri-escape" "^3.0.0" + tslib "^2.6.2" + "@smithy/querystring-parser@^3.0.3": version "3.0.3" resolved "https://registry.yarnpkg.com/@smithy/querystring-parser/-/querystring-parser-3.0.3.tgz#272a6b83f88dfcbbec8283d72a6bde850cc00091" @@ -2510,6 +2889,13 @@ dependencies: tslib "^2.6.2" +"@smithy/types@^3.4.0": + version "3.4.0" + resolved "https://registry.yarnpkg.com/@smithy/types/-/types-3.4.0.tgz#08b7b3d6af30c66fd0682c73c206a5baf8b40a63" + integrity sha512-0shOWSg/pnFXPcsSU8ZbaJ4JBHZJPPzLCJxafJvbMVFo9l1w81CqpgUqjlKGNHVrVB7fhIs+WS82JDTyzaLyLA== + dependencies: + tslib "^2.6.2" + "@smithy/url-parser@^3.0.3": version "3.0.3" resolved "https://registry.yarnpkg.com/@smithy/url-parser/-/url-parser-3.0.3.tgz#e8a060d9810b24b1870385fc2b02485b8a6c5955" @@ -2636,6 +3022,20 @@ "@smithy/util-utf8" "^3.0.0" tslib "^2.6.2" +"@smithy/util-stream@^3.1.4": + version "3.1.4" + resolved "https://registry.yarnpkg.com/@smithy/util-stream/-/util-stream-3.1.4.tgz#f4041a979dfafcbccdc64fa7ee8c376e39c8dc41" + integrity sha512-txU3EIDLhrBZdGfon6E9V6sZz/irYnKFMblz4TLVjyq8hObNHNS2n9a2t7GIrl7d85zgEPhwLE0gANpZsvpsKg== + dependencies: + "@smithy/fetch-http-handler" "^3.2.5" + "@smithy/node-http-handler" "^3.2.0" + "@smithy/types" "^3.4.0" + "@smithy/util-base64" "^3.0.0" + "@smithy/util-buffer-from" "^3.0.0" + "@smithy/util-hex-encoding" "^3.0.0" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + "@smithy/util-uri-escape@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@smithy/util-uri-escape/-/util-uri-escape-3.0.0.tgz#e43358a78bf45d50bb736770077f0f09195b6f54" @@ -2659,6 +3059,15 @@ "@smithy/util-buffer-from" "^3.0.0" tslib "^2.6.2" +"@smithy/util-waiter@^3.1.2": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@smithy/util-waiter/-/util-waiter-3.1.2.tgz#2d40c3312f3537feee763459a19acafab4c75cf3" + integrity sha512-4pP0EV3iTsexDx+8PPGAKCQpd/6hsQBaQhqWzU4hqKPHN5epPsxKbvUTIiYIHTxaKt6/kEaqPBpu/ufvfbrRzw== + dependencies: + "@smithy/abort-controller" "^3.1.1" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + "@szmarczak/http-timer@^4.0.5": version "4.0.6" resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-4.0.6.tgz#b4a914bb62e7c272d4e5989fe4440f812ab1d807" @@ -2953,6 +3362,18 @@ resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.8.tgz#8268a8c57a3e4abd25c165ecd36237db7948a55e" integrity sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ== +"@types/sinon@^10.0.10": + version "10.0.20" + resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-10.0.20.tgz#f1585debf4c0d99f9938f4111e5479fb74865146" + integrity sha512-2APKKruFNCAZgx3daAyACGzWuJ028VVCUDk6o2rw/Z4PXT0ogwdV4KUegW0MwVs0Zu59auPXbbuBJHF12Sx1Eg== + dependencies: + "@types/sinonjs__fake-timers" "*" + +"@types/sinonjs__fake-timers@*": + version "8.1.5" + resolved "https://registry.yarnpkg.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.5.tgz#5fd3592ff10c1e9695d377020c033116cc2889f2" + integrity sha512-mQkU2jY8jJEF7YHjHvsQO8+3ughTL1mcnn96igfhONmR+fUPSKIkefQYpSe8bsly2Ep7oQbn/6VG5/9/0qcArQ== + "@types/stack-utils@^2.0.0": version "2.0.3" resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8" @@ -3395,6 +3816,23 @@ aws-embedded-metrics@^4.1.1: dependencies: "@datastructures-js/heap" "^4.0.2" +aws-sdk-client-mock-jest@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/aws-sdk-client-mock-jest/-/aws-sdk-client-mock-jest-4.0.1.tgz#5b04ca83481b348a43e985f4d6ec3333b753dce8" + integrity sha512-PilgESg/u2sJvHg0+4C8/ty7w2+/pMhBYpdfPlCysnsjNfFk6a7eW7fwfIWoL93BCvcEblPdLyVL/vYTRCNFYA== + dependencies: + expect ">28.1.3" + tslib "^2.1.0" + +aws-sdk-client-mock@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/aws-sdk-client-mock/-/aws-sdk-client-mock-4.0.1.tgz#51e5a877c46ad21a7e51d3b7840006b7255bbd39" + integrity sha512-yD2mmgy73Xce097G5hIpr1k7j50qzvJ49/+6osGZiCyk4m6cwhb+2x7kKFY1gEMwTzaS8+m8fXv9SB29SkRYyQ== + dependencies: + "@types/sinon" "^10.0.10" + sinon "^16.1.3" + tslib "^2.1.0" + aws-sdk-mock@5.9.0: version "5.9.0" resolved "https://registry.yarnpkg.com/aws-sdk-mock/-/aws-sdk-mock-5.9.0.tgz#80e5cdef33a8357899c77d1378316e9ed777b4fa" @@ -4403,7 +4841,7 @@ diff@^4.0.1: resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== -diff@^5.2.0: +diff@^5.1.0, diff@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/diff/-/diff-5.2.0.tgz#26ded047cd1179b78b9537d5ef725503ce1ae531" integrity sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A== @@ -4864,7 +5302,7 @@ exit@^0.1.2: resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== -expect@^29.0.0, expect@^29.7.0: +expect@>28.1.3, expect@^29.0.0, expect@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/expect/-/expect-29.7.0.tgz#578874590dcb3214514084c08115d8aee61e11bc" integrity sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw== @@ -7169,7 +7607,7 @@ neo-async@^2.6.2: resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== -nise@^5.1.9: +nise@^5.1.4, nise@^5.1.9: version "5.1.9" resolved "https://registry.yarnpkg.com/nise/-/nise-5.1.9.tgz#0cb73b5e4499d738231a473cd89bd8afbb618139" integrity sha512-qOnoujW4SV6e40dYxJOb3uvuoPHtmLzIk4TFo+j0jPJoC+5Z9xja5qH5JZobEPsa8+YYphMrOSwnrshEhG2qww== @@ -8308,6 +8746,18 @@ signal-exit@^4.0.1: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== +sinon@^16.1.3: + version "16.1.3" + resolved "https://registry.yarnpkg.com/sinon/-/sinon-16.1.3.tgz#b760ddafe785356e2847502657b4a0da5501fba8" + integrity sha512-mjnWWeyxcAf9nC0bXcPmiDut+oE8HYridTNzBbF98AYVLmWwGRp2ISEpyhYflG1ifILT+eNn3BmKUJPxjXUPlA== + dependencies: + "@sinonjs/commons" "^3.0.0" + "@sinonjs/fake-timers" "^10.3.0" + "@sinonjs/samsam" "^8.0.0" + diff "^5.1.0" + nise "^5.1.4" + supports-color "^7.2.0" + sinon@^17.0.0: version "17.0.2" resolved "https://registry.yarnpkg.com/sinon/-/sinon-17.0.2.tgz#470894bcc2d24b01bad539722ea46da949892405" @@ -8627,7 +9077,7 @@ supports-color@^5.3.0: dependencies: has-flag "^3.0.0" -supports-color@^7, supports-color@^7.0.0, supports-color@^7.1.0: +supports-color@^7, supports-color@^7.0.0, supports-color@^7.1.0, supports-color@^7.2.0: version "7.2.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==