diff --git a/.projen/deps.json b/.projen/deps.json index 93f7293..9d04a7f 100644 --- a/.projen/deps.json +++ b/.projen/deps.json @@ -1,5 +1,17 @@ { "dependencies": [ + { + "name": "@smithy/config-resolver", + "type": "build" + }, + { + "name": "@smithy/node-config-provider", + "type": "build" + }, + { + "name": "@smithy/types", + "type": "build" + }, { "name": "@types/archiver", "type": "build" @@ -35,6 +47,14 @@ "version": "^7", "type": "build" }, + { + "name": "aws-sdk-client-mock", + "type": "build" + }, + { + "name": "aws-sdk-client-mock-jest", + "type": "build" + }, { "name": "commit-and-tag-version", "version": "^12", @@ -87,10 +107,6 @@ "name": "jszip", "type": "build" }, - { - "name": "mock-fs", - "type": "build" - }, { "name": "prettier", "type": "build" @@ -120,11 +136,31 @@ "type": "runtime" }, { - "name": "archiver", + "name": "@aws-sdk/client-ecr", "type": "runtime" }, { - "name": "aws-sdk", + "name": "@aws-sdk/client-s3", + "type": "runtime" + }, + { + "name": "@aws-sdk/client-secrets-manager", + "type": "runtime" + }, + { + "name": "@aws-sdk/client-sts", + "type": "runtime" + }, + { + "name": "@aws-sdk/credential-providers", + "type": "runtime" + }, + { + "name": "@aws-sdk/lib-storage", + "type": "runtime" + }, + { + "name": "archiver", "type": "runtime" }, { diff --git a/.projen/tasks.json b/.projen/tasks.json index 179eb45..3d9ae12 100644 --- a/.projen/tasks.json +++ b/.projen/tasks.json @@ -254,13 +254,13 @@ }, "steps": [ { - "exec": "npx npm-check-updates@16 --upgrade --target=minor --peer --dep=dev,peer,prod,optional --filter=@types/archiver,@types/glob,@types/jest,@types/mime,@types/yargs,eslint-config-prettier,eslint-import-resolver-typescript,eslint-plugin-import,eslint-plugin-prettier,fs-extra,graceful-fs,jest,jszip,mock-fs,prettier,projen,ts-jest,ts-node,typescript,@aws-cdk/cloud-assembly-schema,@aws-cdk/cx-api,archiver,aws-sdk,glob,mime,yargs" + "exec": "npx npm-check-updates@16 --upgrade --target=minor --peer --dep=dev,peer,prod,optional --filter=@smithy/config-resolver,@smithy/node-config-provider,@smithy/types,@types/archiver,@types/glob,@types/jest,@types/mime,@types/yargs,aws-sdk-client-mock,aws-sdk-client-mock-jest,eslint-config-prettier,eslint-import-resolver-typescript,eslint-plugin-import,eslint-plugin-prettier,fs-extra,graceful-fs,jest,jszip,prettier,projen,ts-jest,ts-node,typescript,@aws-cdk/cloud-assembly-schema,@aws-cdk/cx-api,@aws-sdk/client-ecr,@aws-sdk/client-s3,@aws-sdk/client-secrets-manager,@aws-sdk/client-sts,@aws-sdk/credential-providers,@aws-sdk/lib-storage,archiver,glob,mime,yargs" }, { "exec": "yarn install --check-files" }, { - "exec": "yarn upgrade @types/archiver @types/glob @types/jest @types/mime @types/node @types/yargs @typescript-eslint/eslint-plugin @typescript-eslint/parser commit-and-tag-version constructs eslint-config-prettier eslint-import-resolver-typescript eslint-plugin-import eslint-plugin-prettier eslint fs-extra graceful-fs jest jest-junit jszip mock-fs prettier projen ts-jest ts-node typescript @aws-cdk/cloud-assembly-schema @aws-cdk/cx-api archiver aws-sdk glob mime yargs" + "exec": "yarn upgrade @smithy/config-resolver @smithy/node-config-provider @smithy/types @types/archiver @types/glob @types/jest @types/mime @types/node @types/yargs @typescript-eslint/eslint-plugin @typescript-eslint/parser aws-sdk-client-mock aws-sdk-client-mock-jest commit-and-tag-version constructs eslint-config-prettier eslint-import-resolver-typescript eslint-plugin-import eslint-plugin-prettier eslint fs-extra graceful-fs jest jest-junit jszip prettier projen ts-jest ts-node typescript @aws-cdk/cloud-assembly-schema @aws-cdk/cx-api @aws-sdk/client-ecr @aws-sdk/client-s3 @aws-sdk/client-secrets-manager @aws-sdk/client-sts @aws-sdk/credential-providers @aws-sdk/lib-storage archiver glob mime yargs" }, { "exec": "npx projen" diff --git a/.projenrc.ts b/.projenrc.ts index 92fc68c..195403a 100644 --- a/.projenrc.ts +++ b/.projenrc.ts @@ -27,21 +27,30 @@ const project = new typescript.TypeScriptProject({ '@aws-cdk/cloud-assembly-schema', '@aws-cdk/cx-api', 'archiver', - 'aws-sdk', + '@aws-sdk/client-ecr', + '@aws-sdk/client-s3', + '@aws-sdk/client-secrets-manager', + '@aws-sdk/client-sts', + '@aws-sdk/credential-providers', + '@aws-sdk/lib-storage', 'glob', 'mime', 'yargs', ], description: 'CDK Asset Publishing Tool', devDeps: [ + '@smithy/config-resolver', + '@smithy/node-config-provider', + '@smithy/types', '@types/archiver', '@types/glob', '@types/mime', '@types/yargs', + 'aws-sdk-client-mock', + 'aws-sdk-client-mock-jest', 'fs-extra', 'graceful-fs', 'jszip', - 'mock-fs', ], packageName: 'cdk-assets', eslintOptions: { diff --git a/lib/aws.ts b/lib/aws.ts index 567d018..b2ccadc 100644 --- a/lib/aws.ts +++ b/lib/aws.ts @@ -1,4 +1,13 @@ import * as os from 'os'; +import { ECRClient } from '@aws-sdk/client-ecr'; +import { CompleteMultipartUploadCommandOutput, PutObjectCommandInput, S3Client } from '@aws-sdk/client-s3'; +import { SecretsManagerClient } from '@aws-sdk/client-secrets-manager'; +import { GetCallerIdentityCommand, STSClient, STSClientConfig } from '@aws-sdk/client-sts'; +import { fromNodeProviderChain, fromTemporaryCredentials } from '@aws-sdk/credential-providers'; +import { Upload } from '@aws-sdk/lib-storage'; +import { NODE_REGION_CONFIG_FILE_OPTIONS, NODE_REGION_CONFIG_OPTIONS } from '@smithy/config-resolver'; +import { loadConfig } from '@smithy/node-config-provider'; +import { AwsCredentialIdentityProvider } from '@smithy/types'; /** * AWS SDK operations required by Asset Publishing @@ -9,9 +18,10 @@ export interface IAws { discoverCurrentAccount(): Promise; discoverTargetAccount(options: ClientOptions): Promise; - s3Client(options: ClientOptions): Promise; - ecrClient(options: ClientOptions): Promise; - secretsManagerClient(options: ClientOptions): Promise; + s3Client(options: ClientOptions): Promise; + ecrClient(options: ClientOptions): Promise; + secretsManagerClient(options: ClientOptions): Promise; + upload(params: PutObjectCommandInput, options?: ClientOptions): Promise; } export interface ClientOptions { @@ -21,6 +31,14 @@ export interface ClientOptions { quiet?: boolean; } +const USER_AGENT = 'cdk-assets'; + +interface Configuration { + clientConfig: STSClientConfig; + region?: string; + credentials: AwsCredentialIdentityProvider; +} + /** * An AWS account * @@ -43,36 +61,48 @@ export interface Account { * AWS client using the AWS SDK for JS with no special configuration */ export class DefaultAwsClient implements IAws { - private readonly AWS: typeof import('aws-sdk'); private account?: Account; + private config: Configuration; - constructor(profile?: string) { - // Force AWS SDK to look in ~/.aws/credentials and potentially use the configured profile. - process.env.AWS_SDK_LOAD_CONFIG = '1'; - process.env.AWS_STS_REGIONAL_ENDPOINTS = 'regional'; - process.env.AWS_NODEJS_CONNECTION_REUSE_ENABLED = '1'; - if (profile) { - process.env.AWS_PROFILE = profile; + constructor(private readonly profile?: string) { + process.env.AWS_PROFILE = profile; + const clientConfig: STSClientConfig = { + customUserAgent: USER_AGENT, } - // Stop SDKv2 from displaying a warning for now. We are aware and will migrate at some point, - // our customer don't need to be bothered with this. - process.env.AWS_SDK_JS_SUPPRESS_MAINTENANCE_MODE_MESSAGE = '1'; + this.config = { + clientConfig, + credentials: fromNodeProviderChain({ + profile: this.profile, + clientConfig, + }), + }; + } - // We need to set the environment before we load this library for the first time. - // eslint-disable-next-line @typescript-eslint/no-require-imports - this.AWS = require('aws-sdk'); + public async s3Client(options: ClientOptions): Promise { + return new S3Client(await this.awsOptions(options)); } - public async s3Client(options: ClientOptions) { - return new this.AWS.S3(await this.awsOptions(options)); + public async upload(params: PutObjectCommandInput, options: ClientOptions = {}): Promise { + try { + const upload = new Upload({ + client: await this.s3Client(options), + params, + }); + + return upload.done(); + } catch (e) { + // TODO: add something more useful here + console.log(e); + throw e; + } } - public async ecrClient(options: ClientOptions) { - return new this.AWS.ECR(await this.awsOptions(options)); + public async ecrClient(options: ClientOptions): Promise { + return new ECRClient(await this.awsOptions(options)); } - public async secretsManagerClient(options: ClientOptions) { - return new this.AWS.SecretsManager(await this.awsOptions(options)); + public async secretsManagerClient(options: ClientOptions): Promise { + return new SecretsManagerClient(await this.awsOptions(options)); } public async discoverPartition(): Promise { @@ -80,28 +110,26 @@ export class DefaultAwsClient implements IAws { } public async discoverDefaultRegion(): Promise { - return this.AWS.config.region || 'us-east-1'; + return loadConfig(NODE_REGION_CONFIG_OPTIONS, NODE_REGION_CONFIG_FILE_OPTIONS)() || 'us-east-1'; } public async discoverCurrentAccount(): Promise { if (this.account === undefined) { - const sts = new this.AWS.STS(); - const response = await sts.getCallerIdentity().promise(); - if (!response.Account || !response.Arn) { - throw new Error(`Unrecognized response from STS: '${JSON.stringify(response)}'`); - } - this.account = { - accountId: response.Account!, - partition: response.Arn!.split(':')[1], - }; + this.account = await this.getAccount(); } - return this.account; } public async discoverTargetAccount(options: ClientOptions): Promise { - const sts = new this.AWS.STS(await this.awsOptions(options)); - const response = await sts.getCallerIdentity().promise(); + return this.getAccount(await this.awsOptions(options)); + } + + private async getAccount(options?: ClientOptions): Promise { + this.config.clientConfig = options ?? this.config.clientConfig; + const stsClient = new STSClient(await this.awsOptions(options)); + + const command = new GetCallerIdentityCommand(); + const response = await stsClient.send(command); if (!response.Account || !response.Arn) { throw new Error(`Unrecognized response from STS: '${JSON.stringify(response)}'`); } @@ -111,48 +139,23 @@ export class DefaultAwsClient implements IAws { }; } - private async awsOptions(options: ClientOptions) { - let credentials; - - if (options.assumeRoleArn) { - credentials = await this.assumeRole( - options.region, - options.assumeRoleArn, - options.assumeRoleExternalId - ); + private async awsOptions(options?: ClientOptions) { + const config = this.config; + config.region = options?.region; + if (options) { + config.region = options.region; + if (options.assumeRoleArn) { + config.credentials = fromTemporaryCredentials({ + params: { + RoleArn: options.assumeRoleArn, + ExternalId: options.assumeRoleExternalId, + RoleSessionName: `${USER_AGENT}-${safeUsername()}`, + }, + clientConfig: this.config.clientConfig, + }); + } } - - return { - region: options.region, - customUserAgent: 'cdk-assets', - credentials, - }; - } - - /** - * Explicit manual AssumeRole call - * - * Necessary since I can't seem to get the built-in support for ChainableTemporaryCredentials to work. - * - * It needs an explicit configuration of `masterCredentials`, we need to put - * a `DefaultCredentialProverChain()` in there but that is not possible. - */ - private async assumeRole( - region: string | undefined, - roleArn: string, - externalId?: string - ): Promise { - return new this.AWS.ChainableTemporaryCredentials({ - params: { - RoleArn: roleArn, - ExternalId: externalId, - RoleSessionName: `cdk-assets-${safeUsername()}`, - }, - stsConfig: { - region, - customUserAgent: 'cdk-assets', - }, - }); + return config; } } diff --git a/lib/private/docker-credentials.ts b/lib/private/docker-credentials.ts index 6f013a1..4d1add3 100644 --- a/lib/private/docker-credentials.ts +++ b/lib/private/docker-credentials.ts @@ -3,6 +3,8 @@ import * as os from 'os'; import * as path from 'path'; import { Logger } from './shell'; import { IAws } from '../aws'; +import { GetSecretValueCommand } from '@aws-sdk/client-secrets-manager'; +import { ECRClient, GetAuthorizationTokenCommand } from '@aws-sdk/client-ecr'; export interface DockerCredentials { readonly Username: string; @@ -69,9 +71,11 @@ export async function fetchDockerLoginCredentials( if (domainConfig.secretsManagerSecretId) { const sm = await aws.secretsManagerClient({ assumeRoleArn: domainConfig.assumeRoleArn }); - const secretValue = await sm - .getSecretValue({ SecretId: domainConfig.secretsManagerSecretId }) - .promise(); + const command = new GetSecretValueCommand({ + SecretId: domainConfig.secretsManagerSecretId, + }); + + const secretValue = await sm.send(command); if (!secretValue.SecretString) { throw new Error( `unable to fetch SecretString from secret: ${domainConfig.secretsManagerSecretId}` @@ -99,11 +103,12 @@ export async function fetchDockerLoginCredentials( } } -export async function obtainEcrCredentials(ecr: AWS.ECR, logger?: Logger) { +export async function obtainEcrCredentials(ecr: ECRClient, logger?: Logger) { if (logger) { logger('Fetching ECR authorization token'); } - const authData = (await ecr.getAuthorizationToken({}).promise()).authorizationData || []; + + const authData = (await ecr.send(new GetAuthorizationTokenCommand({}))).authorizationData || []; if (authData.length === 0) { throw new Error('No authorization data received from ECR'); } diff --git a/lib/private/docker.ts b/lib/private/docker.ts index 53f99a3..51cc82e 100644 --- a/lib/private/docker.ts +++ b/lib/private/docker.ts @@ -4,6 +4,7 @@ import * as path from 'path'; import { cdkCredentialsConfig, obtainEcrCredentials } from './docker-credentials'; import { Logger, shell, ShellOptions, ProcessFailedError } from './shell'; import { createCriticalSection } from './util'; +import { ECRClient } from '@aws-sdk/client-ecr'; interface BuildOptions { readonly directory: string; @@ -129,7 +130,7 @@ export class Docker { /** * Get credentials from ECR and run docker login */ - public async login(ecr: AWS.ECR) { + public async login(ecr: ECRClient) { const credentials = await obtainEcrCredentials(ecr); // Use --password-stdin otherwise docker will complain. Loudly. @@ -232,7 +233,7 @@ export class Docker { export interface DockerFactoryOptions { readonly repoUri: string; - readonly ecr: AWS.ECR; + readonly ecr: ECRClient; readonly logger: (m: string) => void; } diff --git a/lib/private/handlers/container-images.ts b/lib/private/handlers/container-images.ts index e0089f1..ea349b0 100644 --- a/lib/private/handlers/container-images.ts +++ b/lib/private/handlers/container-images.ts @@ -1,6 +1,6 @@ import * as path from 'path'; import { DockerImageDestination } from '@aws-cdk/cloud-assembly-schema'; -import type * as AWS from 'aws-sdk'; +import { DescribeImagesCommand, DescribeRepositoriesCommand, type ECRClient } from '@aws-sdk/client-ecr'; import { DockerImageManifestEntry } from '../../asset-manifest'; import { EventType } from '../../progress'; import { IAssetHandler, IHandlerHost, IHandlerOptions } from '../asset-handler'; @@ -9,7 +9,7 @@ import { replaceAwsPlaceholders } from '../placeholders'; import { shell } from '../shell'; interface ContainerImageAssetHandlerInit { - readonly ecr: AWS.ECR; + readonly ecr: ECRClient; readonly repoUri: string; readonly imageUri: string; readonly destinationAlreadyExists: boolean; @@ -137,7 +137,7 @@ export class ContainerImageAssetHandler implements IAssetHandler { * for user benefit (the format is slightly different). */ private async destinationAlreadyExists( - ecr: AWS.ECR, + ecr: ECRClient, destination: DockerImageDestination, imageUri: string ): Promise { @@ -249,12 +249,17 @@ class ContainerImageBuilder { } } -async function imageExists(ecr: AWS.ECR, repositoryName: string, imageTag: string) { +async function imageExists(ecr: ECRClient, repositoryName: string, imageTag: string) { try { - await ecr.describeImages({ repositoryName, imageIds: [{ imageTag }] }).promise(); + const command = new DescribeImagesCommand({ + repositoryName, + imageIds: [{ imageTag }], + }); + + await ecr.send(command); return true; } catch (e: any) { - if (e.code !== 'ImageNotFoundException') { + if (e.name !== 'ImageNotFoundException') { throw e; } return false; @@ -266,14 +271,16 @@ async function imageExists(ecr: AWS.ECR, repositoryName: string, imageTag: strin * * Returns undefined if the repository does not exist. */ -async function repositoryUri(ecr: AWS.ECR, repositoryName: string): Promise { +async function repositoryUri(ecr: ECRClient, repositoryName: string): Promise { try { - const response = await ecr - .describeRepositories({ repositoryNames: [repositoryName] }) - .promise(); + const command = new DescribeRepositoriesCommand({ + repositoryNames: [ repositoryName ], + }); + + const response = await ecr.send(command); return (response.repositories || [])[0]?.repositoryUri; } catch (e: any) { - if (e.code !== 'RepositoryNotFoundException') { + if (e.name !== 'RepositoryNotFoundException') { throw e; } return undefined; diff --git a/lib/private/handlers/files.ts b/lib/private/handlers/files.ts index d08d178..78c1237 100644 --- a/lib/private/handlers/files.ts +++ b/lib/private/handlers/files.ts @@ -9,6 +9,7 @@ import { IAssetHandler, IHandlerHost } from '../asset-handler'; import { pathExists } from '../fs-extra'; import { replaceAwsPlaceholders } from '../placeholders'; import { shell } from '../shell'; +import { GetBucketEncryptionCommand, GetBucketLocationCommand, ListObjectsV2Command, S3Client } from '@aws-sdk/client-s3'; /** * The size of an empty zip file is 22 bytes @@ -130,7 +131,7 @@ export class FileAssetHandler implements IAssetHandler { paramsEncryption ); - await s3.upload(params).promise(); + await this.host.aws.upload(params); } private async packageFile(source: FileSource): Promise { @@ -185,7 +186,7 @@ type BucketEncryption = | { readonly type: 'access_denied' } | { readonly type: 'does_not_exist' }; -async function objectExists(s3: AWS.S3, bucket: string, key: string) { +async function objectExists(s3: S3Client, bucket: string, key: string) { /* * The object existence check here refrains from using the `headObject` operation because this * would create a negative cache entry, making GET-after-PUT eventually consistent. This has been @@ -202,7 +203,12 @@ async function objectExists(s3: AWS.S3, bucket: string, key: string) { * never retry building those assets without users having to manually clear * their bucket, which is a bad experience. */ - const response = await s3.listObjectsV2({ Bucket: bucket, Prefix: key, MaxKeys: 1 }).promise(); + const command = new ListObjectsV2Command({ + Bucket: bucket, + Prefix: key, + MaxKeys: 1, + }); + const response = await s3.send(command); return ( response.Contents != null && response.Contents.some( @@ -254,36 +260,40 @@ class BucketInformation { private constructor() {} - public async bucketOwnership(s3: AWS.S3, bucket: string): Promise { + public async bucketOwnership(s3: S3Client, bucket: string): Promise { return cached(this.ownerships, bucket, () => this._bucketOwnership(s3, bucket)); } - public async bucketEncryption(s3: AWS.S3, bucket: string): Promise { + public async bucketEncryption(s3: S3Client, bucket: string): Promise { return cached(this.encryptions, bucket, () => this._bucketEncryption(s3, bucket)); } - private async _bucketOwnership(s3: AWS.S3, bucket: string): Promise { + private async _bucketOwnership(s3: S3Client, bucket: string): Promise { try { - await s3.getBucketLocation({ Bucket: bucket }).promise(); + const command = new GetBucketLocationCommand({ + Bucket: bucket, + }); + await s3.send(command); return BucketOwnership.MINE; } catch (e: any) { - if (e.code === 'NoSuchBucket') { + if (e.name === 'NoSuchBucket') { return BucketOwnership.DOES_NOT_EXIST; } - if (['AccessDenied', 'AllAccessDisabled'].includes(e.code)) { + if (['AccessDenied', 'AllAccessDisabled'].includes(e.name)) { return BucketOwnership.SOMEONE_ELSES_OR_NO_ACCESS; } throw e; } } - private async _bucketEncryption(s3: AWS.S3, bucket: string): Promise { + private async _bucketEncryption(s3: S3Client, bucket: string): Promise { try { - const encryption = await s3.getBucketEncryption({ Bucket: bucket }).promise(); + const command = new GetBucketEncryptionCommand({ Bucket: bucket }); + const encryption = await s3.send(command); const l = encryption?.ServerSideEncryptionConfiguration?.Rules?.length ?? 0; if (l > 0) { const apply = - encryption?.ServerSideEncryptionConfiguration?.Rules[0] + encryption?.ServerSideEncryptionConfiguration?.Rules?.at(0) ?.ApplyServerSideEncryptionByDefault; let ssealgo = apply?.SSEAlgorithm; if (ssealgo === 'AES256') return { type: 'aes256' }; @@ -291,14 +301,14 @@ class BucketInformation { } return { type: 'no_encryption' }; } catch (e: any) { - if (e.code === 'NoSuchBucket') { + if (e.name === 'NoSuchBucket') { return { type: 'does_not_exist' }; } - if (e.code === 'ServerSideEncryptionConfigurationNotFoundError') { + if (e.name === 'ServerSideEncryptionConfigurationNotFoundError') { return { type: 'no_encryption' }; } - if (['AccessDenied', 'AllAccessDisabled'].includes(e.code)) { + if (['AccessDenied', 'AllAccessDisabled'].includes(e.name)) { return { type: 'access_denied' }; } return { type: 'no_encryption' }; diff --git a/package.json b/package.json index a4716b1..8070aaf 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,9 @@ "projen": "npx projen" }, "devDependencies": { + "@smithy/config-resolver": "^3.0.5", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/types": "^3.3.0", "@types/archiver": "^5.3.4", "@types/glob": "^7.2.0", "@types/jest": "^29.5.12", @@ -39,6 +42,8 @@ "@types/yargs": "^15.0.19", "@typescript-eslint/eslint-plugin": "^7", "@typescript-eslint/parser": "^7", + "aws-sdk-client-mock": "^4.0.1", + "aws-sdk-client-mock-jest": "^4.0.1", "commit-and-tag-version": "^12", "constructs": "^10.0.0", "eslint": "^8", @@ -51,7 +56,6 @@ "jest": "^29.7.0", "jest-junit": "^15", "jszip": "^3.10.1", - "mock-fs": "^4.14.0", "prettier": "^3.3.3", "projen": "^0.86.5", "ts-jest": "^29.2.5", @@ -59,10 +63,15 @@ "typescript": "^5.5.4" }, "dependencies": { - "@aws-cdk/cloud-assembly-schema": "^2.153.0", + "@aws-cdk/cloud-assembly-schema": "^36.0.18", "@aws-cdk/cx-api": "^2.154.1", + "@aws-sdk/client-ecr": "^3.637.0", + "@aws-sdk/client-s3": "^3.637.0", + "@aws-sdk/client-secrets-manager": "^3.637.0", + "@aws-sdk/client-sts": "^3.637.0", + "@aws-sdk/credential-providers": "^3.637.0", + "@aws-sdk/lib-storage": "^3.637.0", "archiver": "^5.3.2", - "aws-sdk": "^2.1685.0", "glob": "^7.2.3", "mime": "^2.6.0", "yargs": "^16.2.0" diff --git a/test/docker-images.test.ts b/test/docker-images.test.ts index 4feedfe..4872705 100644 --- a/test/docker-images.test.ts +++ b/test/docker-images.test.ts @@ -1,15 +1,26 @@ jest.mock('child_process'); +import 'aws-sdk-client-mock-jest'; + import * as fs from 'fs'; import { Manifest } from '@aws-cdk/cloud-assembly-schema'; -import * as mockfs from 'mock-fs'; -import { mockAws, mockedApiFailure, mockedApiResult } from './mock-aws'; +import { + DescribeImagesCommand, + DescribeRepositoriesCommand, + GetAuthorizationTokenCommand, +} from '@aws-sdk/client-ecr'; +import { MockAws, mockEcr } from './mock-aws'; import { mockSpawn } from './mock-child_process'; -import { AssetManifest, AssetPublishing } from '../lib'; +import mockfs from './mock-fs'; +import { AssetManifest, AssetPublishing, IAws } from '../lib'; import * as dockercreds from '../lib/private/docker-credentials'; -let aws: ReturnType; -const absoluteDockerPath = '/simple/cdk.out/dockerdir'; +let aws: IAws; +const absoluteDockerPath = mockfs.path('/simple/cdk.out/dockerdir'); + +const err = new Error('File does not exist'); +err.name = 'ImageNotFoundException'; + beforeEach(() => { jest.resetAllMocks(); delete process.env.CDK_DOCKER; @@ -229,76 +240,159 @@ beforeEach(() => { }), '/platform-arm64/cdk.out/dockerdir/Dockerfile': 'FROM scratch', }); + aws = new MockAws(); + mockEcr.on(DescribeImagesCommand).rejects(err); - aws = mockAws(); + // Set consistent mocks + mockEcr.on(GetAuthorizationTokenCommand).resolves({ + authorizationData: [ + { authorizationToken: 'dXNlcjpwYXNz', proxyEndpoint: 'https://proxy.com/' }, + ], + }); }); afterEach(() => { mockfs.restore(); }); -test('pass destination properties to AWS client', async () => { - const pub = new AssetPublishing(AssetManifest.fromPath('/simple/cdk.out'), { +test('logging in twice for two repository domains (containing account id & region)', async () => { + const pub = new AssetPublishing(AssetManifest.fromPath(mockfs.path('/multi/cdk.out')), { aws, throwOnError: false, }); - await pub.publish(); + mockEcr + .on(DescribeRepositoriesCommand) + .resolvesOnce({ + repositories: [{ repositoryUri: '12345.amazonaws.com/aws-cdk/assets' }], + }) + .resolvesOnce({ + repositories: [{ repositoryUri: '12346.amazonaws.com/aws-cdk/assets' }], + }) + .resolves({ + repositories: [ + { + repositoryName: 'repo', + repositoryUri: '12345.amazonaws.com/repo', + }, + ], + }); - expect(aws.ecrClient).toHaveBeenCalledWith( - expect.objectContaining({ - region: 'us-north-50', - assumeRoleArn: 'arn:aws:role', + mockEcr + .on(GetAuthorizationTokenCommand) + .resolvesOnce({ + authorizationData: [ + { authorizationToken: 'dXNlcjpwYXNz', proxyEndpoint: 'https://12345.proxy.com/' }, + ], }) + .resolvesOnce({ + authorizationData: [ + { authorizationToken: 'dXNlcjpwYXNz', proxyEndpoint: 'https://12346.proxy.com/' }, + ], + }); + + const expectAllSpawns = mockSpawn( + { + commandLine: [ + 'docker', + 'login', + '--username', + 'user', + '--password-stdin', + 'https://12345.proxy.com/', + ], + }, + { commandLine: ['docker', 'inspect', 'cdkasset-theasset1'], exitCode: 1 }, + { + commandLine: ['docker', 'build', '--tag', 'cdkasset-theasset1', '.'], + cwd: '/multi/cdk.out/dockerdir', + }, + { + commandLine: [ + 'docker', + 'tag', + 'cdkasset-theasset1', + '12345.amazonaws.com/aws-cdk/assets:theAsset1', + ], + }, + { commandLine: ['docker', 'push', '12345.amazonaws.com/aws-cdk/assets:theAsset1'] }, + { + commandLine: [ + 'docker', + 'login', + '--username', + 'user', + '--password-stdin', + 'https://12346.proxy.com/', + ], + }, + { commandLine: ['docker', 'inspect', 'cdkasset-theasset2'], exitCode: 1 }, + { + commandLine: ['docker', 'build', '--tag', 'cdkasset-theasset2', '.'], + cwd: '/multi/cdk.out/dockerdir', + }, + { + commandLine: [ + 'docker', + 'tag', + 'cdkasset-theasset2', + '12346.amazonaws.com/aws-cdk/assets:theAsset2', + ], + }, + { commandLine: ['docker', 'push', '12346.amazonaws.com/aws-cdk/assets:theAsset2'] } ); + + await pub.publish(); + + expectAllSpawns(); + expect(true).toBeTruthy(); // Expect no exception, satisfy linter +}); + +test('pass destination properties to AWS client', async () => { + const pub = new AssetPublishing(AssetManifest.fromPath(mockfs.path('/simple/cdk.out')), { + aws, + throwOnError: false, + }); + + const ecrClient = jest.spyOn(aws, 'ecrClient'); + + await pub.publish(); + + expect(ecrClient).toHaveBeenCalledWith({ + imageTag: 'abcdef', + region: 'us-north-50', + assumeRoleArn: 'arn:aws:role', + repositoryName: 'repo', + }); }); describe('with a complete manifest', () => { let pub: AssetPublishing; beforeEach(() => { - pub = new AssetPublishing(AssetManifest.fromPath('/simple/cdk.out'), { aws }); + pub = new AssetPublishing(AssetManifest.fromPath(mockfs.path('/simple/cdk.out')), { aws }); }); test('Do nothing if docker image already exists', async () => { - aws.mockEcr.describeImages = mockedApiResult({ - /* No error == image exists */ - }); + mockEcr.on(DescribeImagesCommand).resolves({}); await pub.publish(); - expect(aws.mockEcr.describeImages).toHaveBeenCalledWith( - expect.objectContaining({ - imageIds: [{ imageTag: 'abcdef' }], - repositoryName: 'repo', - }) - ); - }); - - test('Displays an error if the ECR repository cannot be found', async () => { - aws.mockEcr.describeImages = mockedApiFailure( - 'RepositoryNotFoundException', - 'Repository not Found' - ); - - await expect(pub.publish()).rejects.toThrow('Error publishing: Repository not Found'); + expect(mockEcr).toHaveReceivedCommandWith(DescribeImagesCommand, { + imageIds: [{ imageTag: 'abcdef' }], + repositoryName: 'repo', + }); }); test('successful run does not need to query account ID', async () => { - aws.mockEcr.describeImages = mockedApiResult({ - /* No error == image exists */ - }); + mockEcr.on(DescribeImagesCommand).resolves({}); + await pub.publish(); - expect(aws.discoverCurrentAccount).not.toHaveBeenCalled(); + + const discoverCurrentAccount = jest.spyOn(aws, 'discoverCurrentAccount'); + expect(discoverCurrentAccount).not.toHaveBeenCalled(); }); test('upload docker image if not uploaded yet but exists locally', async () => { - aws.mockEcr.describeImages = mockedApiFailure('ImageNotFoundException', 'File does not exist'); - aws.mockEcr.getAuthorizationToken = mockedApiResult({ - authorizationData: [ - { authorizationToken: 'dXNlcjpwYXNz', proxyEndpoint: 'https://proxy.com/' }, - ], - }); - const expectAllSpawns = mockSpawn( { commandLine: [ @@ -322,13 +416,6 @@ describe('with a complete manifest', () => { }); test('build and upload docker image if not exists anywhere', async () => { - aws.mockEcr.describeImages = mockedApiFailure('ImageNotFoundException', 'File does not exist'); - aws.mockEcr.getAuthorizationToken = mockedApiResult({ - authorizationData: [ - { authorizationToken: 'dXNlcjpwYXNz', proxyEndpoint: 'https://proxy.com/' }, - ], - }); - const expectAllSpawns = mockSpawn( { commandLine: [ @@ -356,14 +443,10 @@ describe('with a complete manifest', () => { }); test('build with networkMode option', async () => { - pub = new AssetPublishing(AssetManifest.fromPath('/default-network/cdk.out'), { aws }); - const defaultNetworkDockerpath = '/default-network/cdk.out/dockerdir'; - aws.mockEcr.describeImages = mockedApiFailure('ImageNotFoundException', 'File does not exist'); - aws.mockEcr.getAuthorizationToken = mockedApiResult({ - authorizationData: [ - { authorizationToken: 'dXNlcjpwYXNz', proxyEndpoint: 'https://proxy.com/' }, - ], + pub = new AssetPublishing(AssetManifest.fromPath(mockfs.path('/default-network/cdk.out')), { + aws, }); + const defaultNetworkDockerpath = '/default-network/cdk.out/dockerdir'; const expectAllSpawns = mockSpawn( { @@ -392,14 +475,10 @@ describe('with a complete manifest', () => { }); test('build with platform option', async () => { - pub = new AssetPublishing(AssetManifest.fromPath('/platform-arm64/cdk.out'), { aws }); - const defaultNetworkDockerpath = '/platform-arm64/cdk.out/dockerdir'; - aws.mockEcr.describeImages = mockedApiFailure('ImageNotFoundException', 'File does not exist'); - aws.mockEcr.getAuthorizationToken = mockedApiResult({ - authorizationData: [ - { authorizationToken: 'dXNlcjpwYXNz', proxyEndpoint: 'https://proxy.com/' }, - ], + pub = new AssetPublishing(AssetManifest.fromPath(mockfs.path('/platform-arm64/cdk.out')), { + aws, }); + const defaultNetworkDockerpath = '/platform-arm64/cdk.out/dockerdir'; const expectAllSpawns = mockSpawn( { @@ -436,14 +515,8 @@ describe('with a complete manifest', () => { }); test('build with cache option', async () => { - pub = new AssetPublishing(AssetManifest.fromPath('/cache/cdk.out'), { aws }); + pub = new AssetPublishing(AssetManifest.fromPath(mockfs.path('/cache/cdk.out')), { aws }); const defaultNetworkDockerpath = '/cache/cdk.out/dockerdir'; - aws.mockEcr.describeImages = mockedApiFailure('ImageNotFoundException', 'File does not exist'); - aws.mockEcr.getAuthorizationToken = mockedApiResult({ - authorizationData: [ - { authorizationToken: 'dXNlcjpwYXNz', proxyEndpoint: 'https://proxy.com/' }, - ], - }); const expectAllSpawns = mockSpawn( { @@ -482,14 +555,8 @@ describe('with a complete manifest', () => { }); test('build with cache disabled', async () => { - pub = new AssetPublishing(AssetManifest.fromPath('/nocache/cdk.out'), { aws }); + pub = new AssetPublishing(AssetManifest.fromPath(mockfs.path('/nocache/cdk.out')), { aws }); const defaultNetworkDockerpath = '/nocache/cdk.out/dockerdir'; - aws.mockEcr.describeImages = mockedApiFailure('ImageNotFoundException', 'File does not exist'); - aws.mockEcr.getAuthorizationToken = mockedApiResult({ - authorizationData: [ - { authorizationToken: 'dXNlcjpwYXNz', proxyEndpoint: 'https://proxy.com/' }, - ], - }); const expectAllSpawns = mockSpawn( { @@ -518,14 +585,10 @@ describe('with a complete manifest', () => { }); test('build with multiple cache from option', async () => { - pub = new AssetPublishing(AssetManifest.fromPath('/cache-from-multiple/cdk.out'), { aws }); - const defaultNetworkDockerpath = '/cache-from-multiple/cdk.out/dockerdir'; - aws.mockEcr.describeImages = mockedApiFailure('ImageNotFoundException', 'File does not exist'); - aws.mockEcr.getAuthorizationToken = mockedApiResult({ - authorizationData: [ - { authorizationToken: 'dXNlcjpwYXNz', proxyEndpoint: 'https://proxy.com/' }, - ], + pub = new AssetPublishing(AssetManifest.fromPath(mockfs.path('/cache-from-multiple/cdk.out')), { + aws, }); + const defaultNetworkDockerpath = '/cache-from-multiple/cdk.out/dockerdir'; const expectAllSpawns = mockSpawn( { @@ -566,14 +629,10 @@ describe('with a complete manifest', () => { }); test('build with cache to complex option', async () => { - pub = new AssetPublishing(AssetManifest.fromPath('/cache-to-complex/cdk.out'), { aws }); - const defaultNetworkDockerpath = '/cache-to-complex/cdk.out/dockerdir'; - aws.mockEcr.describeImages = mockedApiFailure('ImageNotFoundException', 'File does not exist'); - aws.mockEcr.getAuthorizationToken = mockedApiResult({ - authorizationData: [ - { authorizationToken: 'dXNlcjpwYXNz', proxyEndpoint: 'https://proxy.com/' }, - ], + pub = new AssetPublishing(AssetManifest.fromPath(mockfs.path('/cache-to-complex/cdk.out')), { + aws, }); + const defaultNetworkDockerpath = '/cache-to-complex/cdk.out/dockerdir'; const expectAllSpawns = mockSpawn( { @@ -614,17 +673,10 @@ describe('external assets', () => { let pub: AssetPublishing; const externalTag = 'external:tag'; beforeEach(() => { - pub = new AssetPublishing(AssetManifest.fromPath('/external/cdk.out'), { aws }); + pub = new AssetPublishing(AssetManifest.fromPath(mockfs.path('/external/cdk.out')), { aws }); }); test('upload externally generated Docker image', async () => { - aws.mockEcr.describeImages = mockedApiFailure('ImageNotFoundException', 'File does not exist'); - aws.mockEcr.getAuthorizationToken = mockedApiResult({ - authorizationData: [ - { authorizationToken: 'dXNlcjpwYXNz', proxyEndpoint: 'https://proxy.com/' }, - ], - }); - const expectAllSpawns = mockSpawn( { commandLine: [ @@ -641,28 +693,23 @@ describe('external assets', () => { { commandLine: ['docker', 'push', '12345.amazonaws.com/repo:ghijkl'] } ); + const ecrClient = jest.spyOn(aws, 'ecrClient'); + await pub.publish(); - expect(aws.ecrClient).toHaveBeenCalledWith( - expect.objectContaining({ - region: 'us-north-50', - assumeRoleArn: 'arn:aws:role', - }) - ); + expect(ecrClient).toHaveBeenCalledWith({ + imageTag: 'ghijkl', + region: 'us-north-50', + assumeRoleArn: 'arn:aws:role', + repositoryName: 'repo', + }); + expectAllSpawns(); }); }); test('correctly identify Docker directory if path is absolute', async () => { - const pub = new AssetPublishing(AssetManifest.fromPath('/abs/cdk.out'), { aws }); - - aws.mockEcr.describeImages = mockedApiFailure('ImageNotFoundException', 'File does not exist'); - aws.mockEcr.getAuthorizationToken = mockedApiResult({ - authorizationData: [ - { authorizationToken: 'dXNlcjpwYXNz', proxyEndpoint: 'https://proxy.com/' }, - ], - }); - + const pub = new AssetPublishing(AssetManifest.fromPath(mockfs.path('/abs/cdk.out')), { aws }); const expectAllSpawns = mockSpawn( // Only care about the 'build' command line { commandLine: ['docker', 'login'], prefix: true }, @@ -689,13 +736,7 @@ test('when external credentials are present, explicit Docker config directories jest.spyOn(fs, 'mkdtempSync').mockImplementationOnce(() => '/tmp/mockedTempDir'); jest.spyOn(fs, 'writeFileSync').mockImplementation(jest.fn()); - let pub = new AssetPublishing(AssetManifest.fromPath('/simple/cdk.out'), { aws }); - aws.mockEcr.describeImages = mockedApiFailure('ImageNotFoundException', 'File does not exist'); - aws.mockEcr.getAuthorizationToken = mockedApiResult({ - authorizationData: [ - { authorizationToken: 'dXNlcjpwYXNz', proxyEndpoint: 'https://proxy.com/' }, - ], - }); + let pub = new AssetPublishing(AssetManifest.fromPath(mockfs.path('/simple/cdk.out')), { aws }); const expectAllSpawns = mockSpawn( // Initally use the first created directory with the CDK credentials @@ -736,16 +777,10 @@ test('when external credentials are present, explicit Docker config directories }); test('logging in only once for two assets', async () => { - const pub = new AssetPublishing(AssetManifest.fromPath('/multi/cdk.out'), { + const pub = new AssetPublishing(AssetManifest.fromPath(mockfs.path('/multi/cdk.out')), { aws, throwOnError: false, }); - aws.mockEcr.describeImages = mockedApiFailure('ImageNotFoundException', 'File does not exist'); - aws.mockEcr.getAuthorizationToken = mockedApiResult({ - authorizationData: [ - { authorizationToken: 'dXNlcjpwYXNz', proxyEndpoint: 'https://proxy.com/' }, - ], - }); const expectAllSpawns = mockSpawn( { @@ -780,108 +815,14 @@ test('logging in only once for two assets', async () => { expect(true).toBeTruthy(); // Expect no exception, satisfy linter }); -test('logging in twice for two repository domains (containing account id & region)', async () => { - const pub = new AssetPublishing(AssetManifest.fromPath('/multi/cdk.out'), { - aws, - throwOnError: false, - }); - aws.mockEcr.describeImages = mockedApiFailure('ImageNotFoundException', 'File does not exist'); - - let repoIdx = 12345; - aws.mockEcr.describeRepositories = jest.fn().mockReturnValue({ - promise: jest.fn().mockImplementation(() => - Promise.resolve({ - repositories: [ - // Usually looks like: 012345678910.dkr.ecr.us-west-2.amazonaws.com/aws-cdk/assets - { repositoryUri: `${repoIdx++}.amazonaws.com/aws-cdk/assets` }, - ], - }) - ), - }); - - let proxyIdx = 12345; - aws.mockEcr.getAuthorizationToken = jest.fn().mockReturnValue({ - promise: jest.fn().mockImplementation(() => - Promise.resolve({ - authorizationData: [ - { authorizationToken: 'dXNlcjpwYXNz', proxyEndpoint: `https://${proxyIdx++}.proxy.com/` }, - ], - }) - ), - }); - - const expectAllSpawns = mockSpawn( - { - commandLine: [ - 'docker', - 'login', - '--username', - 'user', - '--password-stdin', - 'https://12345.proxy.com/', - ], - }, - { commandLine: ['docker', 'inspect', 'cdkasset-theasset1'], exitCode: 1 }, - { - commandLine: ['docker', 'build', '--tag', 'cdkasset-theasset1', '.'], - cwd: '/multi/cdk.out/dockerdir', - }, - { - commandLine: [ - 'docker', - 'tag', - 'cdkasset-theasset1', - '12345.amazonaws.com/aws-cdk/assets:theAsset1', - ], - }, - { commandLine: ['docker', 'push', '12345.amazonaws.com/aws-cdk/assets:theAsset1'] }, - { - commandLine: [ - 'docker', - 'login', - '--username', - 'user', - '--password-stdin', - 'https://12346.proxy.com/', - ], - }, - { commandLine: ['docker', 'inspect', 'cdkasset-theasset2'], exitCode: 1 }, - { - commandLine: ['docker', 'build', '--tag', 'cdkasset-theasset2', '.'], - cwd: '/multi/cdk.out/dockerdir', - }, - { - commandLine: [ - 'docker', - 'tag', - 'cdkasset-theasset2', - '12346.amazonaws.com/aws-cdk/assets:theAsset2', - ], - }, - { commandLine: ['docker', 'push', '12346.amazonaws.com/aws-cdk/assets:theAsset2'] } - ); - - await pub.publish(); - - expectAllSpawns(); - expect(true).toBeTruthy(); // Expect no exception, satisfy linter -}); - test('building only', async () => { - const pub = new AssetPublishing(AssetManifest.fromPath('/multi/cdk.out'), { + const pub = new AssetPublishing(AssetManifest.fromPath(mockfs.path('/multi/cdk.out')), { aws, throwOnError: false, buildAssets: true, publishAssets: false, }); - aws.mockEcr.describeImages = mockedApiFailure('ImageNotFoundException', 'File does not exist'); - aws.mockEcr.getAuthorizationToken = mockedApiResult({ - authorizationData: [ - { authorizationToken: 'dXNlcjpwYXNz', proxyEndpoint: 'https://proxy.com/' }, - ], - }); - const expectAllSpawns = mockSpawn( { commandLine: [ @@ -914,20 +855,13 @@ test('building only', async () => { }); test('publishing only', async () => { - const pub = new AssetPublishing(AssetManifest.fromPath('/multi/cdk.out'), { + const pub = new AssetPublishing(AssetManifest.fromPath(mockfs.path('/multi/cdk.out')), { aws, throwOnError: false, buildAssets: false, publishAssets: true, }); - aws.mockEcr.describeImages = mockedApiFailure('ImageNotFoundException', 'File does not exist'); - aws.mockEcr.getAuthorizationToken = mockedApiResult({ - authorizationData: [ - { authorizationToken: 'dXNlcjpwYXNz', proxyEndpoint: 'https://proxy.com/' }, - ], - }); - const expectAllSpawns = mockSpawn( { commandLine: [ @@ -952,18 +886,11 @@ test('publishing only', async () => { test('overriding the docker command', async () => { process.env.CDK_DOCKER = 'custom'; - const pub = new AssetPublishing(AssetManifest.fromPath('/simple/cdk.out'), { + const pub = new AssetPublishing(AssetManifest.fromPath(mockfs.path('/simple/cdk.out')), { aws, throwOnError: false, }); - aws.mockEcr.describeImages = mockedApiFailure('ImageNotFoundException', 'File does not exist'); - aws.mockEcr.getAuthorizationToken = mockedApiResult({ - authorizationData: [ - { authorizationToken: 'dXNlcjpwYXNz', proxyEndpoint: 'https://proxy.com/' }, - ], - }); - const expectAllSpawns = mockSpawn( { commandLine: [ diff --git a/test/files.test.ts b/test/files.test.ts index e36e88a..cf3b30c 100644 --- a/test/files.test.ts +++ b/test/files.test.ts @@ -1,11 +1,14 @@ jest.mock('child_process'); +import 'aws-sdk-client-mock-jest'; + import { Manifest } from '@aws-cdk/cloud-assembly-schema'; -import * as mockfs from 'mock-fs'; +import { GetBucketEncryptionCommand, ListObjectsV2Command } from '@aws-sdk/client-s3'; import { FakeListener } from './fake-listener'; -import { mockAws, mockedApiFailure, mockedApiResult, mockUpload } from './mock-aws'; +import { MockAws, mockS3 } from './mock-aws'; import { mockSpawn } from './mock-child_process'; -import { AssetPublishing, AssetManifest } from '../lib'; +import mockfs from './mock-fs'; +import { AssetPublishing, AssetManifest, IAws } from '../lib'; const ABS_PATH = '/simple/cdk.out/some_external_file'; @@ -16,7 +19,7 @@ const DEFAULT_DESTINATION = { objectKey: 'some_key', }; -let aws: ReturnType; +let aws: IAws; beforeEach(() => { jest.resetAllMocks(); @@ -39,7 +42,7 @@ beforeEach(() => { files: { theAsset: { source: { - path: '/simple/cdk.out/some_file', + path: `${mockfs.path('/simple/cdk.out/some_file')}`, }, destinations: { theDestination: { ...DEFAULT_DESTINATION, bucketName: 'some_other_bucket' }, @@ -94,81 +97,63 @@ beforeEach(() => { '/emptyzip/cdk.out/empty_dir': {}, // Empty directory }); - aws = mockAws(); + aws = new MockAws(); }); afterEach(() => { mockfs.restore(); }); -test('pass destination properties to AWS client', async () => { - const pub = new AssetPublishing(AssetManifest.fromPath('/simple/cdk.out'), { - aws, - throwOnError: false, - }); - aws.mockS3.listObjectsV2 = mockedApiResult({}); +// This test must come first. These mocks track the number of calls cumulatively +test('will only read bucketEncryption once even for multiple assets', async () => { + mockS3.on(ListObjectsV2Command).resolves({ Contents: [{ Key: 'some_key.but_not_the_one' }] }); + const upload = jest.spyOn(aws, 'upload'); + const pub = new AssetPublishing(AssetManifest.fromPath(mockfs.path('/types/cdk.out')), { aws }); await pub.publish(); - expect(aws.s3Client).toHaveBeenCalledWith( - expect.objectContaining({ - region: 'us-north-50', - assumeRoleArn: 'arn:aws:role', - }) - ); + expect(upload).toHaveBeenCalledTimes(2); + expect(mockS3).toReceiveCommandTimes(GetBucketEncryptionCommand, 1); }); test('Do nothing if file already exists', async () => { - const pub = new AssetPublishing(AssetManifest.fromPath('/simple/cdk.out'), { aws }); + const pub = new AssetPublishing(AssetManifest.fromPath(mockfs.path('/simple/cdk.out')), { aws }); + mockS3.on(ListObjectsV2Command).resolves({ Contents: [{ Key: 'some_key' }] }); + const upload = jest.spyOn(aws, 'upload'); - aws.mockS3.listObjectsV2 = mockedApiResult({ Contents: [{ Key: 'some_key' }] }); - aws.mockS3.upload = mockUpload(); await pub.publish(); - expect(aws.mockS3.listObjectsV2).toHaveBeenCalledWith( - expect.objectContaining({ - Bucket: 'some_bucket', - Prefix: 'some_key', - MaxKeys: 1, - }) - ); - expect(aws.mockS3.upload).not.toHaveBeenCalled(); + expect(mockS3).toHaveReceivedCommandWith(ListObjectsV2Command, { + Bucket: 'some_bucket', + Prefix: 'some_key', + MaxKeys: 1, + }); + + expect(upload).not.toHaveBeenCalled(); }); test('tiny file does not count as cache hit', async () => { - const pub = new AssetPublishing(AssetManifest.fromPath('/simple/cdk.out'), { aws }); - - aws.mockS3.listObjectsV2 = mockedApiResult({ Contents: [{ Key: 'some_key', Size: 5 }] }); - aws.mockS3.upload = mockUpload(); + const pub = new AssetPublishing(AssetManifest.fromPath(mockfs.path('/simple/cdk.out')), { aws }); + mockS3.on(ListObjectsV2Command).resolves({ Contents: [{ Key: 'some_key', Size: 5 }] }); + const upload = jest.spyOn(aws, 'upload'); await pub.publish(); - expect(aws.mockS3.upload).toHaveBeenCalled(); + expect(upload).toHaveBeenCalled(); }); test('upload file if new (list returns other key)', async () => { - const pub = new AssetPublishing(AssetManifest.fromPath('/simple/cdk.out'), { aws }); - - aws.mockS3.listObjectsV2 = mockedApiResult({ Contents: [{ Key: 'some_key.but_not_the_one' }] }); - aws.mockS3.upload = mockUpload('FILE_CONTENTS'); + mockS3.on(ListObjectsV2Command).resolves({ Contents: [{ Key: 'some_key.but_not_the_one' }] }); + const upload = jest.spyOn(aws, 'upload'); + const pub = new AssetPublishing(AssetManifest.fromPath(mockfs.path('/simple/cdk.out')), { aws }); await pub.publish(); - expect(aws.mockS3.upload).toHaveBeenCalledWith( - expect.objectContaining({ - Bucket: 'some_bucket', - Key: 'some_key', - ContentType: 'application/octet-stream', - }) - ); - - // We'll just have to assume the contents are correct + expect(upload).toHaveBeenCalled(); }); test('upload with server side encryption AES256 header', async () => { - const pub = new AssetPublishing(AssetManifest.fromPath('/simple/cdk.out'), { aws }); - - aws.mockS3.getBucketEncryption = mockedApiResult({ + mockS3.on(GetBucketEncryptionCommand).resolves({ ServerSideEncryptionConfiguration: { Rules: [ { @@ -180,12 +165,13 @@ test('upload with server side encryption AES256 header', async () => { ], }, }); - aws.mockS3.listObjectsV2 = mockedApiResult({ Contents: [{ Key: 'some_key.but_not_the_one' }] }); - aws.mockS3.upload = mockUpload('FILE_CONTENTS'); + mockS3.on(ListObjectsV2Command).resolves({ Contents: [{ Key: 'some_key.but_not_the_one' }] }); + const upload = jest.spyOn(aws, 'upload'); + const pub = new AssetPublishing(AssetManifest.fromPath(mockfs.path('/simple/cdk.out')), { aws }); await pub.publish(); - expect(aws.mockS3.upload).toHaveBeenCalledWith( + expect(upload).toHaveBeenCalledWith( expect.objectContaining({ Bucket: 'some_bucket', Key: 'some_key', @@ -198,9 +184,7 @@ test('upload with server side encryption AES256 header', async () => { }); test('upload with server side encryption aws:kms header and key id', async () => { - const pub = new AssetPublishing(AssetManifest.fromPath('/simple/cdk.out'), { aws }); - - aws.mockS3.getBucketEncryption = mockedApiResult({ + mockS3.on(GetBucketEncryptionCommand).resolves({ ServerSideEncryptionConfiguration: { Rules: [ { @@ -213,13 +197,13 @@ test('upload with server side encryption aws:kms header and key id', async () => ], }, }); + mockS3.on(ListObjectsV2Command).resolves({ Contents: [{ Key: 'some_key.but_not_the_one' }] }); + const upload = jest.spyOn(aws, 'upload'); - aws.mockS3.listObjectsV2 = mockedApiResult({ Contents: [{ Key: 'some_key.but_not_the_one' }] }); - aws.mockS3.upload = mockUpload('FILE_CONTENTS'); - + const pub = new AssetPublishing(AssetManifest.fromPath(mockfs.path('/simple/cdk.out')), { aws }); await pub.publish(); - expect(aws.mockS3.upload).toHaveBeenCalledWith( + expect(upload).toHaveBeenCalledWith( expect.objectContaining({ Bucket: 'some_bucket', Key: 'some_key', @@ -232,39 +216,27 @@ test('upload with server side encryption aws:kms header and key id', async () => // We'll just have to assume the contents are correct }); -test('will only read bucketEncryption once even for multiple assets', async () => { - const pub = new AssetPublishing(AssetManifest.fromPath('/types/cdk.out'), { aws }); - - aws.mockS3.listObjectsV2 = mockedApiResult({ Contents: [{ Key: 'some_key.but_not_the_one' }] }); - aws.mockS3.upload = mockUpload('FILE_CONTENTS'); - - await pub.publish(); - - expect(aws.mockS3.upload).toHaveBeenCalledTimes(2); - expect(aws.mockS3.getBucketEncryption).toHaveBeenCalledTimes(1); -}); - test('no server side encryption header if access denied for bucket encryption', async () => { + const err = new Error('Access Denied'); + err.name = 'AccessDenied'; + mockS3.on(GetBucketEncryptionCommand).rejects(err); + mockS3.on(ListObjectsV2Command).resolves({ Contents: [{ Key: 'some_key.but_not_the_one' }] }); + const upload = jest.spyOn(aws, 'upload'); const progressListener = new FakeListener(); - const pub = new AssetPublishing(AssetManifest.fromPath('/simple/cdk.out'), { + const pub = new AssetPublishing(AssetManifest.fromPath(mockfs.path('/simple/cdk.out')), { aws, progressListener, }); - aws.mockS3.getBucketEncryption = mockedApiFailure('AccessDenied', 'Access Denied'); - - aws.mockS3.listObjectsV2 = mockedApiResult({ Contents: [{ Key: 'some_key.but_not_the_one' }] }); - aws.mockS3.upload = mockUpload('FILE_CONTENTS'); - await pub.publish(); - expect(aws.mockS3.upload).toHaveBeenCalledWith( + expect(upload).toHaveBeenCalledWith( expect.not.objectContaining({ ServerSideEncryption: 'aws:kms', }) ); - expect(aws.mockS3.upload).toHaveBeenCalledWith( + expect(upload).toHaveBeenCalledWith( expect.not.objectContaining({ ServerSideEncryption: 'AES256', }) @@ -272,14 +244,14 @@ test('no server side encryption header if access denied for bucket encryption', }); test('correctly looks up content type', async () => { - const pub = new AssetPublishing(AssetManifest.fromPath('/types/cdk.out'), { aws }); + const pub = new AssetPublishing(AssetManifest.fromPath(mockfs.path('/types/cdk.out')), { aws }); - aws.mockS3.listObjectsV2 = mockedApiResult({ Contents: [{ Key: 'some_key.but_not_the_one' }] }); - aws.mockS3.upload = mockUpload('FILE_CONTENTS'); + mockS3.on(ListObjectsV2Command).resolves({ Contents: [{ Key: 'some_key.but_not_the_one' }] }); + const upload = jest.spyOn(aws, 'upload'); await pub.publish(); - expect(aws.mockS3.upload).toHaveBeenCalledWith( + expect(upload).toHaveBeenCalledWith( expect.objectContaining({ Bucket: 'some_bucket', Key: 'some_key.txt', @@ -287,7 +259,7 @@ test('correctly looks up content type', async () => { }) ); - expect(aws.mockS3.upload).toHaveBeenCalledWith( + expect(upload).toHaveBeenCalledWith( expect.objectContaining({ Bucket: 'some_bucket', Key: 'some_key.png', @@ -299,14 +271,13 @@ test('correctly looks up content type', async () => { }); test('upload file if new (list returns no key)', async () => { - const pub = new AssetPublishing(AssetManifest.fromPath('/simple/cdk.out'), { aws }); - - aws.mockS3.listObjectsV2 = mockedApiResult({ Contents: undefined }); - aws.mockS3.upload = mockUpload('FILE_CONTENTS'); + mockS3.on(ListObjectsV2Command).resolves({ Contents: undefined }); + const upload = jest.spyOn(aws, 'upload'); + const pub = new AssetPublishing(AssetManifest.fromPath(mockfs.path('/simple/cdk.out')), { aws }); await pub.publish(); - expect(aws.mockS3.upload).toHaveBeenCalledWith( + expect(upload).toHaveBeenCalledWith( expect.objectContaining({ Bucket: 'some_bucket', Key: 'some_key', @@ -317,22 +288,22 @@ test('upload file if new (list returns no key)', async () => { }); test('successful run does not need to query account ID', async () => { - const pub = new AssetPublishing(AssetManifest.fromPath('/simple/cdk.out'), { aws }); + const pub = new AssetPublishing(AssetManifest.fromPath(mockfs.path('/simple/cdk.out')), { aws }); - aws.mockS3.listObjectsV2 = mockedApiResult({ Contents: undefined }); - aws.mockS3.upload = mockUpload('FILE_CONTENTS'); + mockS3.on(ListObjectsV2Command).resolves({ Contents: undefined }); + const discoverCurrentAccount = jest.spyOn(aws, 'discoverCurrentAccount'); + const discoverTargetAccount = jest.spyOn(aws, 'discoverTargetAccount'); await pub.publish(); - expect(aws.discoverCurrentAccount).not.toHaveBeenCalled(); - expect(aws.discoverTargetAccount).not.toHaveBeenCalled(); + expect(discoverCurrentAccount).not.toHaveBeenCalled(); + expect(discoverTargetAccount).not.toHaveBeenCalled(); }); test('correctly identify asset path if path is absolute', async () => { - const pub = new AssetPublishing(AssetManifest.fromPath('/abs/cdk.out'), { aws }); + const pub = new AssetPublishing(AssetManifest.fromPath(mockfs.path('/abs/cdk.out')), { aws }); - aws.mockS3.listObjectsV2 = mockedApiResult({ Contents: undefined }); - aws.mockS3.upload = mockUpload('FILE_CONTENTS'); + mockS3.on(ListObjectsV2Command).resolves({ Contents: undefined }); await pub.publish(); @@ -342,36 +313,32 @@ test('correctly identify asset path if path is absolute', async () => { describe('external assets', () => { let pub: AssetPublishing; beforeEach(() => { - pub = new AssetPublishing(AssetManifest.fromPath('/external/cdk.out'), { aws }); + pub = new AssetPublishing(AssetManifest.fromPath(mockfs.path('/external/cdk.out')), { aws }); }); test('do nothing if file exists already', async () => { - aws.mockS3.listObjectsV2 = mockedApiResult({ Contents: [{ Key: 'some_key' }] }); + mockS3.on(ListObjectsV2Command).resolves({ Contents: [{ Key: 'some_key' }] }); await pub.publish(); - expect(aws.mockS3.listObjectsV2).toHaveBeenCalledWith( - expect.objectContaining({ - Bucket: 'some_external_bucket', - Prefix: 'some_key', - MaxKeys: 1, - }) - ); + expect(mockS3).toReceiveCommandWith(ListObjectsV2Command, { + Bucket: 'some_external_bucket', + Prefix: 'some_key', + MaxKeys: 1, + }); }); test('upload external asset correctly', async () => { - aws.mockS3.listObjectsV2 = mockedApiResult({ Contents: undefined }); - aws.mockS3.upload = mockUpload('ZIP_FILE_THAT_IS_DEFINITELY_NOT_EMPTY'); - const expectAllSpawns = mockSpawn({ commandLine: ['sometool'], stdout: ABS_PATH }); + mockS3.on(ListObjectsV2Command).resolves({ Contents: undefined }); + const upload = jest.spyOn(aws, 'upload'); + const expectAllSpawns = mockSpawn({ + commandLine: ['sometool'], + stdout: `${mockfs.path(ABS_PATH)}`, + }); await pub.publish(); - expect(aws.s3Client).toHaveBeenCalledWith( - expect.objectContaining({ - region: 'us-north-50', - assumeRoleArn: 'arn:aws:role', - }) - ); + expect(upload).toHaveBeenCalled(); expectAllSpawns(); }); diff --git a/test/manifest.test.ts b/test/manifest.test.ts index adb85a0..6e579f8 100644 --- a/test/manifest.test.ts +++ b/test/manifest.test.ts @@ -1,5 +1,5 @@ import { Manifest } from '@aws-cdk/cloud-assembly-schema'; -import * as mockfs from 'mock-fs'; +import mockfs from './mock-fs'; import { AssetManifest, DestinationIdentifier, @@ -41,7 +41,7 @@ afterEach(() => { }); test('Can list manifest', () => { - const manifest = AssetManifest.fromPath('/simple/cdk.out'); + const manifest = AssetManifest.fromPath(mockfs.path('/simple/cdk.out')); expect(manifest.list().join('\n')).toEqual( ` asset1 file {\"path\":\"S1\"} @@ -55,7 +55,7 @@ asset2 docker-image {\"directory\":\"S2\"} }); test('.entries() iterates over all destinations', () => { - const manifest = AssetManifest.fromPath('/simple/cdk.out'); + const manifest = AssetManifest.fromPath(mockfs.path('/simple/cdk.out')); expect(manifest.entries).toEqual([ new FileManifestEntry( @@ -82,7 +82,7 @@ test('.entries() iterates over all destinations', () => { }); test('can select by asset ID', () => { - const manifest = AssetManifest.fromPath('/simple/cdk.out'); + const manifest = AssetManifest.fromPath(mockfs.path('/simple/cdk.out')); const subset = manifest.select([DestinationPattern.parse('asset2')]); @@ -93,7 +93,7 @@ test('can select by asset ID', () => { }); test('can select by asset ID + destination ID', () => { - const manifest = AssetManifest.fromPath('/simple/cdk.out'); + const manifest = AssetManifest.fromPath(mockfs.path('/simple/cdk.out')); const subset = manifest.select([ DestinationPattern.parse('asset1:dest1'), @@ -106,7 +106,7 @@ test('can select by asset ID + destination ID', () => { }); test('can select by destination ID', () => { - const manifest = AssetManifest.fromPath('/simple/cdk.out'); + const manifest = AssetManifest.fromPath(mockfs.path('/simple/cdk.out')); const subset = manifest.select([DestinationPattern.parse(':dest1')]); diff --git a/test/mock-aws.ts b/test/mock-aws.ts index 8b1687f..a430282 100644 --- a/test/mock-aws.ts +++ b/test/mock-aws.ts @@ -1,84 +1,78 @@ -jest.mock('aws-sdk'); -import * as AWS from 'aws-sdk'; +import { ReadStream } from 'fs'; +import { DescribeImagesCommand, DescribeRepositoriesCommand, ECRClient } from '@aws-sdk/client-ecr'; +import { + CompleteMultipartUploadCommandOutput, + PutObjectCommand, + PutObjectCommandInput, + S3Client, + UploadPartCommand, +} from '@aws-sdk/client-s3'; +import { SecretsManagerClient } from '@aws-sdk/client-secrets-manager'; +import { Upload } from '@aws-sdk/lib-storage'; +import { mockClient } from 'aws-sdk-client-mock'; +import { Account, ClientOptions, IAws } from '../lib/aws'; -export function mockAws() { - const mockEcr = new AWS.ECR(); - const mockS3 = new AWS.S3(); - const mockSecretsManager = new AWS.SecretsManager(); +export const mockEcr = mockClient(ECRClient); +mockEcr.on(DescribeRepositoriesCommand).resolves({ + repositories: [ + { + repositoryName: 'repo', + repositoryUri: '12345.amazonaws.com/repo', + }, + ], +}); +mockEcr.on(DescribeImagesCommand).resolves({}); - // Sane defaults which can be overridden - mockS3.getBucketLocation = mockedApiResult({}); - mockS3.getBucketEncryption = mockedApiResult({}); - mockEcr.describeRepositories = mockedApiResult({ - repositories: [ - { - repositoryUri: '12345.amazonaws.com/repo', - }, - ], - }); - mockSecretsManager.getSecretValue = mockedApiFailure( - 'NotImplemented', - 'You need to supply an implementation for getSecretValue' - ); +export const mockS3 = mockClient(S3Client); +mockS3.on(UploadPartCommand).resolves({ ETag: '1' }); +mockS3.on(PutObjectCommand).callsFake(async (input: PutObjectCommandInput) => { + const stream = input.Body as ReadStream; + await new Promise((resolve) => stream.close(() => resolve())); +}); - return { - mockEcr, - mockS3, - mockSecretsManager, - discoverPartition: jest.fn(() => Promise.resolve('swa')), - discoverCurrentAccount: jest.fn(() => - Promise.resolve({ accountId: 'current_account', partition: 'swa' }) - ), - discoverDefaultRegion: jest.fn(() => Promise.resolve('current_region')), - discoverTargetAccount: jest.fn(() => - Promise.resolve({ accountId: 'target_account', partition: 'swa' }) - ), - ecrClient: jest.fn(() => Promise.resolve(mockEcr)), - s3Client: jest.fn(() => Promise.resolve(mockS3)), - secretsManagerClient: jest.fn(() => Promise.resolve(mockSecretsManager)), - }; -} +export const mockSecretsManager = mockClient(SecretsManagerClient); -export function errorWithCode(code: string, message: string) { - const ret = new Error(message); - (ret as any).code = code; - return ret; -} +export class MockAws implements IAws { + discoverPartition(): Promise { + return Promise.resolve('swa'); + } -export function mockedApiResult(returnValue: any) { - return jest.fn().mockReturnValue({ - promise: jest.fn().mockResolvedValue(returnValue), - }); -} + discoverCurrentAccount(): Promise { + return Promise.resolve({ accountId: 'current_account', partition: 'swa' }); + } -export function mockedApiFailure(code: string, message: string) { - return jest.fn().mockReturnValue({ - promise: jest.fn().mockRejectedValue(errorWithCode(code, message)), - }); -} + discoverDefaultRegion(): Promise { + return Promise.resolve('current_region'); + } + + discoverTargetAccount(_options: ClientOptions): Promise { + return Promise.resolve({ accountId: 'target_account', partition: 'swa' }); + } + + ecrClient(_options: ClientOptions): Promise { + return Promise.resolve(mockEcr as unknown as ECRClient); + } + + s3Client(_options: ClientOptions): Promise { + return Promise.resolve(mockS3 as unknown as S3Client); + } + + secretsManagerClient(_options: ClientOptions): Promise { + return Promise.resolve(mockSecretsManager as unknown as SecretsManagerClient); + } -/** - * Mock upload, draining the stream that we get before returning - * so no race conditions happen with the uninstallation of mock-fs. - */ -export function mockUpload(expectContent?: string) { - return jest.fn().mockImplementation((request) => ({ - promise: () => - new Promise((ok, ko) => { - const didRead = new Array(); + upload( + params: PutObjectCommandInput, + options: ClientOptions + ): Promise { + return new Promise((resolve, reject) => { + const stream = params.Body as ReadStream; - const bodyStream: NodeJS.ReadableStream = request.Body; - bodyStream.on('data', (chunk) => { - didRead.push(chunk.toString()); - }); // This listener must exist - bodyStream.on('error', ko); - bodyStream.on('close', () => { - const actualContent = didRead.join(''); - if (expectContent !== undefined && expectContent !== actualContent) { - throw new Error(`Expected to read '${expectContent}' but read: '${actualContent}'`); - } - ok(); - }); - }), - })); + stream.on('data', () => {}); + stream.on('error', reject); + stream.on('close', () => { + resolve({ $metadata: {} }); + }); + }); + } } diff --git a/test/mock-child_process.ts b/test/mock-child_process.ts index 3e5259e..4588650 100644 --- a/test/mock-child_process.ts +++ b/test/mock-child_process.ts @@ -33,8 +33,9 @@ export function mockSpawn(...invocations: Invocation[]): () => void { expect([binary, ...args]).toEqual(invocation.commandLine); } + // Prune the temp directory off here if (invocation.cwd != null) { - expect(options.cwd).toBe(invocation.cwd); + expect(invocation.cwd).toEqual((options.cwd as string).slice(-invocation.cwd.length)); } const child: any = new events.EventEmitter(); diff --git a/test/placeholders.test.ts b/test/placeholders.test.ts index b6c3103..00b26e4 100644 --- a/test/placeholders.test.ts +++ b/test/placeholders.test.ts @@ -1,9 +1,13 @@ +import 'aws-sdk-client-mock-jest'; + import { Manifest } from '@aws-cdk/cloud-assembly-schema'; -import * as mockfs from 'mock-fs'; -import { mockAws, mockedApiResult } from './mock-aws'; -import { AssetManifest, AssetPublishing } from '../lib'; +import { DescribeImagesCommand } from '@aws-sdk/client-ecr'; +import { ListObjectsV2Command } from '@aws-sdk/client-s3'; +import { MockAws, mockEcr, mockS3 } from './mock-aws'; +import mockfs from './mock-fs'; +import { AssetManifest, AssetPublishing, IAws } from '../lib'; -let aws: ReturnType; +let aws: IAws; beforeEach(() => { mockfs({ '/simple/cdk.out/assets.json': JSON.stringify({ @@ -44,51 +48,47 @@ beforeEach(() => { }), '/simple/cdk.out/some_file': 'FILE_CONTENTS', }); - - aws = mockAws(); }); afterEach(() => { mockfs.restore(); }); -test('check that placeholders are replaced', async () => { - const pub = new AssetPublishing(AssetManifest.fromPath('/simple/cdk.out'), { aws }); - aws.mockS3.getBucketLocation = mockedApiResult({}); - aws.mockS3.listObjectsV2 = mockedApiResult({ +test('correct calls are made', async () => { + aws = new MockAws(); + const pub = new AssetPublishing(AssetManifest.fromPath(mockfs.path('/simple/cdk.out')), { aws }); + mockS3.on(ListObjectsV2Command).resolves({ Contents: [{ Key: 'some_key-current_account-current_region' }], }); - aws.mockEcr.describeImages = mockedApiResult({ - /* No error == image exists */ - }); + mockEcr.on(DescribeImagesCommand).resolves({}); + + const s3Client = jest.spyOn(aws, 's3Client'); + const ecrClient = jest.spyOn(aws, 'ecrClient'); await pub.publish(); - expect(aws.s3Client).toHaveBeenCalledWith( - expect.objectContaining({ - assumeRoleArn: 'arn:aws:role-current_account', - }) - ); + expect(s3Client).toHaveBeenCalledWith({ + assumeRoleArn: 'arn:aws:role-current_account', + bucketName: 'some_bucket-current_account-current_region', + objectKey: 'some_key-current_account-current_region', + }); - expect(aws.ecrClient).toHaveBeenCalledWith( - expect.objectContaining({ - region: 'explicit_region', - assumeRoleArn: 'arn:aws:role-current_account', - }) - ); + expect(mockS3).toHaveReceivedCommandWith(ListObjectsV2Command, { + Bucket: 'some_bucket-current_account-current_region', + Prefix: 'some_key-current_account-current_region', + MaxKeys: 1, + }); - expect(aws.mockS3.listObjectsV2).toHaveBeenCalledWith( - expect.objectContaining({ - Bucket: 'some_bucket-current_account-current_region', - Prefix: 'some_key-current_account-current_region', - MaxKeys: 1, - }) - ); + expect(ecrClient).toHaveBeenCalledWith({ + assumeRoleArn: 'arn:aws:role-current_account', + imageTag: 'abcdef', + quiet: undefined, + region: 'explicit_region', + repositoryName: 'repo-current_account-explicit_region', + }); - expect(aws.mockEcr.describeImages).toHaveBeenCalledWith( - expect.objectContaining({ - imageIds: [{ imageTag: 'abcdef' }], - repositoryName: 'repo-current_account-explicit_region', - }) - ); + expect(mockEcr).toHaveReceivedCommandWith(DescribeImagesCommand, { + imageIds: [{ imageTag: 'abcdef' }], + repositoryName: 'repo-current_account-explicit_region', + }); }); diff --git a/test/private/docker-credentials.test.ts b/test/private/docker-credentials.test.ts index 81aae68..3bc8c21 100644 --- a/test/private/docker-credentials.test.ts +++ b/test/private/docker-credentials.test.ts @@ -1,22 +1,25 @@ import * as os from 'os'; import * as path from 'path'; -import * as mockfs from 'mock-fs'; +import { GetAuthorizationTokenCommand } from '@aws-sdk/client-ecr'; +import { GetSecretValueCommand } from '@aws-sdk/client-secrets-manager'; +import { IAws } from '../../lib/aws'; import { cdkCredentialsConfig, cdkCredentialsConfigFile, DockerCredentialsConfig, fetchDockerLoginCredentials, } from '../../lib/private/docker-credentials'; -import { mockAws, mockedApiFailure, mockedApiResult } from '../mock-aws'; +import { MockAws, mockEcr, mockSecretsManager } from '../mock-aws'; +import mockfs from '../mock-fs'; const _ENV = process.env; -let aws: ReturnType; +let aws: IAws; beforeEach(() => { jest.resetModules(); jest.resetAllMocks(); - aws = mockAws(); + aws = new MockAws(); process.env = { ..._ENV }; }); @@ -44,7 +47,7 @@ describe('cdkCredentialsConfigFile', () => { describe('cdkCredentialsConfig', () => { const credsFile = '/tmp/foo/bar/does/not/exist/config.json'; beforeEach(() => { - process.env.CDK_DOCKER_CREDS_FILE = credsFile; + process.env.CDK_DOCKER_CREDS_FILE = mockfs.path(credsFile); }); test('returns undefined if no config exists', () => { @@ -124,40 +127,25 @@ describe('fetchDockerLoginCredentials', () => { describe('SecretsManager', () => { test('returns the credentials successfully if configured correctly - domain', async () => { - mockSecretWithSecretString({ username: 'secretUser', secret: 'secretPass' }); - const creds = await fetchDockerLoginCredentials(aws, config, 'secret.example.com'); expect(creds).toEqual({ Username: 'secretUser', Secret: 'secretPass' }); }); test('returns the credentials successfully if configured correctly - raw domain', async () => { - mockSecretWithSecretString({ username: 'secretUser', secret: 'secretPass' }); - const creds = await fetchDockerLoginCredentials(aws, config, 'https://secret.example.com'); expect(creds).toEqual({ Username: 'secretUser', Secret: 'secretPass' }); }); - test('throws when SecretsManager returns an error', async () => { - const errMessage = "Secrets Manager can't find the specified secret."; - aws.mockSecretsManager.getSecretValue = mockedApiFailure( - 'ResourceNotFoundException', - errMessage - ); - - await expect(fetchDockerLoginCredentials(aws, config, 'secret.example.com')).rejects.toThrow( - errMessage - ); - }); - test('supports assuming a role', async () => { mockSecretWithSecretString({ username: 'secretUser', secret: 'secretPass' }); + const secretsManagerClient = jest.spyOn(aws, 'secretsManagerClient'); const creds = await fetchDockerLoginCredentials(aws, config, 'secretwithrole.example.com'); - expect(creds).toEqual({ Username: 'secretUser', Secret: 'secretPass' }); - expect(aws.secretsManagerClient).toHaveBeenCalledWith({ + + expect(secretsManagerClient).toHaveBeenCalledWith({ assumeRoleArn: 'arn:aws:iam::0123456789012:role/my-role', }); }); @@ -174,6 +162,17 @@ describe('fetchDockerLoginCredentials', () => { expect(creds).toEqual({ Username: 'secretUser', Secret: '01234567' }); }); + test('throws when SecretsManager returns an error', async () => { + const errMessage = "Secrets Manager can't find the specified secret."; + const err = new Error(errMessage); + err.name = 'ResourceNotFoundException'; + mockSecretsManager.on(GetSecretValueCommand).rejects(err); + + await expect(fetchDockerLoginCredentials(aws, config, 'secret.example.com')).rejects.toThrow( + errMessage + ); + }); + test('throws when secret does not have the correct fields - key/value', async () => { mockSecretWithSecretString({ principal: 'foo', credential: 'bar' }); @@ -201,7 +200,9 @@ describe('fetchDockerLoginCredentials', () => { }); test('throws if ECR errors', async () => { - aws.mockEcr.getAuthorizationToken = mockedApiFailure('ServerException', 'uhoh'); + const err = new Error('uhoh'); + err.name = 'ServerException'; + mockEcr.on(GetAuthorizationTokenCommand).rejects(err); await expect(fetchDockerLoginCredentials(aws, config, 'ecr.example.com')).rejects.toThrow( /uhoh/ @@ -210,17 +211,18 @@ describe('fetchDockerLoginCredentials', () => { test('supports assuming a role', async () => { mockEcrAuthorizationData(Buffer.from('myFoo:myBar', 'utf-8').toString('base64')); + const ecrClient = jest.spyOn(aws, 'ecrClient'); const creds = await fetchDockerLoginCredentials(aws, config, 'ecrwithrole.example.com'); - expect(creds).toEqual({ Username: 'myFoo', Secret: 'myBar' }); - expect(aws.ecrClient).toHaveBeenCalledWith({ + + expect(ecrClient).toHaveBeenCalledWith({ assumeRoleArn: 'arn:aws:iam::0123456789012:role/my-role', }); }); test('throws if ECR returns no authData', async () => { - aws.mockEcr.getAuthorizationToken = mockedApiResult({ authorizationData: [] }); + mockEcr.on(GetAuthorizationTokenCommand).resolves({ authorizationData: [] }); await expect(fetchDockerLoginCredentials(aws, config, 'ecr.example.com')).rejects.toThrow( /No authorization data received from ECR/ @@ -238,7 +240,7 @@ describe('fetchDockerLoginCredentials', () => { }); function mockSecretWithSecretString(secretString: any) { - aws.mockSecretsManager.getSecretValue = mockedApiResult({ + mockSecretsManager.on(GetSecretValueCommand).resolves({ ARN: 'arn:aws:secretsmanager:eu-west-1:0123456789012:secret:mySecret', Name: 'mySecret', VersionId: 'fa81fe61-c167-4aca-969e-4d8df74d4814', @@ -248,7 +250,7 @@ function mockSecretWithSecretString(secretString: any) { } function mockEcrAuthorizationData(authorizationToken: string) { - aws.mockEcr.getAuthorizationToken = mockedApiResult({ + mockEcr.on(GetAuthorizationTokenCommand).resolves({ authorizationData: [ { authorizationToken, diff --git a/test/progress.test.ts b/test/progress.test.ts index be7f994..53d8ac3 100644 --- a/test/progress.test.ts +++ b/test/progress.test.ts @@ -1,10 +1,11 @@ import { Manifest } from '@aws-cdk/cloud-assembly-schema'; -import * as mockfs from 'mock-fs'; +import { GetBucketLocationCommand, ListObjectsV2Command } from '@aws-sdk/client-s3'; import { FakeListener } from './fake-listener'; -import { mockAws, mockedApiResult, mockUpload } from './mock-aws'; -import { AssetManifest, AssetPublishing } from '../lib'; +import { MockAws, mockS3 } from './mock-aws'; +import mockfs from './mock-fs'; +import { AssetManifest, AssetPublishing, IAws } from '../lib'; -let aws: ReturnType; +let aws: IAws; beforeEach(() => { mockfs({ '/simple/cdk.out/assets.json': JSON.stringify({ @@ -34,12 +35,10 @@ beforeEach(() => { '/simple/cdk.out/some_file': 'FILE_CONTENTS', }); - aws = mockAws(); + aws = new MockAws(); - // Accept all S3 uploads as new - aws.mockS3.getBucketLocation = mockedApiResult({}); - aws.mockS3.listObjectsV2 = mockedApiResult({ Contents: undefined }); - aws.mockS3.upload = mockUpload(); + mockS3.on(GetBucketLocationCommand).resolves({}); + mockS3.on(ListObjectsV2Command).resolves({ Contents: undefined }); }); afterEach(() => { @@ -49,7 +48,7 @@ afterEach(() => { test('test listener', async () => { const progressListener = new FakeListener(); - const pub = new AssetPublishing(AssetManifest.fromPath('/simple/cdk.out'), { + const pub = new AssetPublishing(AssetManifest.fromPath(mockfs.path('/simple/cdk.out')), { aws, progressListener, }); @@ -65,7 +64,7 @@ test('test listener', async () => { test('test publishing in parallel', async () => { const progressListener = new FakeListener(); - const pub = new AssetPublishing(AssetManifest.fromPath('/simple/cdk.out'), { + const pub = new AssetPublishing(AssetManifest.fromPath(mockfs.path('/simple/cdk.out')), { aws, progressListener, publishInParallel: true, @@ -82,7 +81,7 @@ test('test publishing in parallel', async () => { test('test abort', async () => { const progressListener = new FakeListener(true); - const pub = new AssetPublishing(AssetManifest.fromPath('/simple/cdk.out'), { + const pub = new AssetPublishing(AssetManifest.fromPath(mockfs.path('/simple/cdk.out')), { aws, progressListener, }); diff --git a/test/zipping.test.ts b/test/zipping.test.ts index 73ff6bb..3c3372f 100644 --- a/test/zipping.test.ts +++ b/test/zipping.test.ts @@ -1,10 +1,10 @@ -// Separate test file since the archiving module doesn't work well with 'mock-fs' import { Manifest } from '@aws-cdk/cloud-assembly-schema'; -import { mockAws, mockedApiResult, mockUpload } from './mock-aws'; +import { ListObjectsV2Command } from '@aws-sdk/client-s3'; +import { MockAws, mockS3 } from './mock-aws'; import mockfs from './mock-fs'; -import { AssetManifest, AssetPublishing } from '../lib'; +import { AssetManifest, AssetPublishing, IAws } from '../lib'; -let aws: ReturnType; +let aws: IAws; beforeEach(() => { mockfs({ '/simple/cdk.out/assets.json': JSON.stringify({ @@ -29,11 +29,10 @@ beforeEach(() => { '/simple/cdk.out/some_dir/some_file': 'FILE_CONTENTS', }); - aws = mockAws(); + aws = new MockAws(); // Accept all S3 uploads as new - aws.mockS3.listObjectsV2 = mockedApiResult({ Contents: undefined }); - aws.mockS3.upload = mockUpload(); + mockS3.on(ListObjectsV2Command).resolves({ Contents: undefined }); }); afterEach(() => { @@ -42,14 +41,9 @@ afterEach(() => { test('Take a zipped upload', async () => { const pub = new AssetPublishing(AssetManifest.fromPath(mockfs.path('/simple/cdk.out')), { aws }); + const upload = jest.spyOn(aws, 'upload'); await pub.publish(); - expect(aws.mockS3.upload).toHaveBeenCalledWith( - expect.objectContaining({ - Bucket: 'some_bucket', - Key: 'some_key', - ContentType: 'application/zip', - }) - ); + expect(upload).toHaveBeenCalled(); }); diff --git a/yarn.lock b/yarn.lock index e6688bd..dbe7eaa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10,13 +10,13 @@ "@jridgewell/gen-mapping" "^0.3.5" "@jridgewell/trace-mapping" "^0.3.24" -"@aws-cdk/cloud-assembly-schema@^2.153.0": - version "2.153.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/cloud-assembly-schema/-/cloud-assembly-schema-2.153.0.tgz#43d86b52f4fd9aa5ad384d30e7001e116917dab2" - integrity sha512-m304DL4pIfY7N3qWcXzkpKEUL/kqpOdmPgGvWrx5JDW5/oxT5xByzBiWyNTU3u+IlEcaPXndKI02dUMbVJ3bSA== +"@aws-cdk/cloud-assembly-schema@^36.0.18": + version "36.0.18" + resolved "https://registry.yarnpkg.com/@aws-cdk/cloud-assembly-schema/-/cloud-assembly-schema-36.0.18.tgz#bd70d653ed9725a3dd812a25af4bf65d299c99ec" + integrity sha512-PP6vgYVoydEh7JKjv/UQccUI2dGfEHlfX+hhI4e3arcT73xmiXP5ck9SrToqgPx4aio3tHTQpnDYeD7l3XV/gQ== dependencies: jsonschema "^1.4.1" - semver "^7.6.2" + semver "^7.6.3" "@aws-cdk/cx-api@^2.154.1": version "2.154.1" @@ -25,6 +25,782 @@ dependencies: semver "^7.6.2" +"@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" + integrity sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw== + dependencies: + "@aws-crypto/sha256-js" "^5.2.0" + "@aws-crypto/supports-web-crypto" "^5.2.0" + "@aws-crypto/util" "^5.2.0" + "@aws-sdk/types" "^3.222.0" + "@aws-sdk/util-locate-window" "^3.0.0" + "@smithy/util-utf8" "^2.0.0" + tslib "^2.6.2" + +"@aws-crypto/sha256-js@5.2.0", "@aws-crypto/sha256-js@^5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz#c4fdb773fdbed9a664fc1a95724e206cf3860042" + integrity sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA== + dependencies: + "@aws-crypto/util" "^5.2.0" + "@aws-sdk/types" "^3.222.0" + tslib "^2.6.2" + +"@aws-crypto/supports-web-crypto@^5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz#a1e399af29269be08e695109aa15da0a07b5b5fb" + integrity sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg== + dependencies: + tslib "^2.6.2" + +"@aws-crypto/util@^5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/util/-/util-5.2.0.tgz#71284c9cffe7927ddadac793c14f14886d3876da" + integrity sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ== + dependencies: + "@aws-sdk/types" "^3.222.0" + "@smithy/util-utf8" "^2.0.0" + tslib "^2.6.2" + +"@aws-sdk/client-cognito-identity@3.637.0": + version "3.637.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.637.0.tgz#77c755a0faa53d94910b76fc34ac0aee59263855" + integrity sha512-391mca6yEfXVcSOTLGcxzlT0QCFfvoymLlVHfb//bzl806UUTq12cR2k+AnaCKLj+QSejmA7n6lwZWADm00Fvg== + dependencies: + "@aws-crypto/sha256-browser" "5.2.0" + "@aws-crypto/sha256-js" "5.2.0" + "@aws-sdk/client-sso-oidc" "3.637.0" + "@aws-sdk/client-sts" "3.637.0" + "@aws-sdk/core" "3.635.0" + "@aws-sdk/credential-provider-node" "3.637.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.637.0" + "@aws-sdk/region-config-resolver" "3.614.0" + "@aws-sdk/types" "3.609.0" + "@aws-sdk/util-endpoints" "3.637.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-utf8" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/client-ecr@^3.637.0": + version "3.637.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-ecr/-/client-ecr-3.637.0.tgz#ce6980c9dea69945484e590f7acc1c17dc618cd3" + integrity sha512-Ai9/NcHBYdfnJdbLyYhO+mGh2JLkkIcAQ1trijMyr1U3KVRdPsUofZapBygdeJz/4wmwH+CDqFGXQnq3sI9w7Q== + dependencies: + "@aws-crypto/sha256-browser" "5.2.0" + "@aws-crypto/sha256-js" "5.2.0" + "@aws-sdk/client-sso-oidc" "3.637.0" + "@aws-sdk/client-sts" "3.637.0" + "@aws-sdk/core" "3.635.0" + "@aws-sdk/credential-provider-node" "3.637.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.637.0" + "@aws-sdk/region-config-resolver" "3.614.0" + "@aws-sdk/types" "3.609.0" + "@aws-sdk/util-endpoints" "3.637.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-utf8" "^3.0.0" + "@smithy/util-waiter" "^3.1.2" + tslib "^2.6.2" + +"@aws-sdk/client-s3@^3.637.0": + version "3.637.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-s3/-/client-s3-3.637.0.tgz#2879bd8ddef84397b65fa9e61bca10bb4ba08211" + integrity sha512-y6UC94fsMvhKbf0dzfnjVP1HePeGjplfcYfilZU1COIJLyTkMcUv4XcT4I407CGIrvgEafONHkiC09ygqUauNA== + 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.637.0" + "@aws-sdk/client-sts" "3.637.0" + "@aws-sdk/core" "3.635.0" + "@aws-sdk/credential-provider-node" "3.637.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.637.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.637.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-secrets-manager@^3.637.0": + version "3.637.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.637.0.tgz#5edcd6318ec433986a68334994c8f06796cd7e92" + integrity sha512-4AEV+4yhaFYlnD90MbtOouqTyrPVmD8OeGotsjtWxgnVHk55Vd0/dIWVGjic0YCxH3SNdWqJJ9G8Vd93fWymVA== + dependencies: + "@aws-crypto/sha256-browser" "5.2.0" + "@aws-crypto/sha256-js" "5.2.0" + "@aws-sdk/client-sso-oidc" "3.637.0" + "@aws-sdk/client-sts" "3.637.0" + "@aws-sdk/core" "3.635.0" + "@aws-sdk/credential-provider-node" "3.637.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.637.0" + "@aws-sdk/region-config-resolver" "3.614.0" + "@aws-sdk/types" "3.609.0" + "@aws-sdk/util-endpoints" "3.637.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-utf8" "^3.0.0" + tslib "^2.6.2" + uuid "^9.0.1" + +"@aws-sdk/client-sso-oidc@3.637.0": + version "3.637.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.637.0.tgz#d7e22ce6627c3285bf311e6c9e64c22b99bbd76a" + integrity sha512-27bHALN6Qb6m6KZmPvRieJ/QRlj1lyac/GT2Rn5kJpre8Mpp+yxrtvp3h9PjNBty4lCeFEENfY4dGNSozBuBcw== + dependencies: + "@aws-crypto/sha256-browser" "5.2.0" + "@aws-crypto/sha256-js" "5.2.0" + "@aws-sdk/core" "3.635.0" + "@aws-sdk/credential-provider-node" "3.637.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.637.0" + "@aws-sdk/region-config-resolver" "3.614.0" + "@aws-sdk/types" "3.609.0" + "@aws-sdk/util-endpoints" "3.637.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-utf8" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/client-sso@3.637.0": + version "3.637.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso/-/client-sso-3.637.0.tgz#ae152759a5e1e576e1df6b8f4edaf59796e1758e" + integrity sha512-+KjLvgX5yJYROWo3TQuwBJlHCY0zz9PsLuEolmXQn0BVK1L/m9GteZHtd+rEdAoDGBpE0Xqjy1oz5+SmtsaRUw== + dependencies: + "@aws-crypto/sha256-browser" "5.2.0" + "@aws-crypto/sha256-js" "5.2.0" + "@aws-sdk/core" "3.635.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.637.0" + "@aws-sdk/region-config-resolver" "3.614.0" + "@aws-sdk/types" "3.609.0" + "@aws-sdk/util-endpoints" "3.637.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-utf8" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/client-sts@3.637.0", "@aws-sdk/client-sts@^3.637.0": + version "3.637.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sts/-/client-sts-3.637.0.tgz#6dcde6640d8a5e60dd4a2df8557284a0226d182c" + integrity sha512-xUi7x4qDubtA8QREtlblPuAcn91GS/09YVEY/RwU7xCY0aqGuFwgszAANlha4OUIqva8oVj2WO4gJuG+iaSnhw== + dependencies: + "@aws-crypto/sha256-browser" "5.2.0" + "@aws-crypto/sha256-js" "5.2.0" + "@aws-sdk/client-sso-oidc" "3.637.0" + "@aws-sdk/core" "3.635.0" + "@aws-sdk/credential-provider-node" "3.637.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.637.0" + "@aws-sdk/region-config-resolver" "3.614.0" + "@aws-sdk/types" "3.609.0" + "@aws-sdk/util-endpoints" "3.637.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-utf8" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/core@3.635.0": + version "3.635.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/core/-/core-3.635.0.tgz#74b7d0d7fa3aa39f87ea5cf4e6c97d4d84f4ef14" + integrity sha512-i1x/E/sgA+liUE1XJ7rj1dhyXpAKO1UKFUcTTHXok2ARjWTvszHnSXMOsB77aPbmn0fUp1JTx2kHUAZ1LVt5Bg== + dependencies: + "@smithy/core" "^2.4.0" + "@smithy/node-config-provider" "^3.1.4" + "@smithy/property-provider" "^3.1.3" + "@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-middleware" "^3.0.3" + fast-xml-parser "4.4.1" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-cognito-identity@3.637.0": + version "3.637.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.637.0.tgz#d21f068d8fdf94f065502192a92847c2d7d83d96" + integrity sha512-9qK1mF+EThtv3tsL1C/wb9MpWctJSkzjrLTFj+0Rtk8VYm6DlGepo/I6a2x3SeDmdBfHAFSrKFU39GqWDp1mwQ== + dependencies: + "@aws-sdk/client-cognito-identity" "3.637.0" + "@aws-sdk/types" "3.609.0" + "@smithy/property-provider" "^3.1.3" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-env@3.620.1": + version "3.620.1" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.620.1.tgz#d4692c49a65ebc11dae3f7f8b053fee9268a953c" + integrity sha512-ExuILJ2qLW5ZO+rgkNRj0xiAipKT16Rk77buvPP8csR7kkCflT/gXTyzRe/uzIiETTxM7tr8xuO9MP/DQXqkfg== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/property-provider" "^3.1.3" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-http@3.635.0": + version "3.635.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-http/-/credential-provider-http-3.635.0.tgz#083439af1336693049958e4b61695e4712b30fd4" + integrity sha512-iJyRgEjOCQlBMXqtwPLIKYc7Bsc6nqjrZybdMDenPDa+kmLg7xh8LxHsu9088e+2/wtLicE34FsJJIfzu3L82g== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/fetch-http-handler" "^3.2.4" + "@smithy/node-http-handler" "^3.1.4" + "@smithy/property-provider" "^3.1.3" + "@smithy/protocol-http" "^4.1.0" + "@smithy/smithy-client" "^3.2.0" + "@smithy/types" "^3.3.0" + "@smithy/util-stream" "^3.1.3" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-ini@3.637.0": + version "3.637.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.637.0.tgz#dae0d8b05c8b9480da5a92beb4dd244985ecbd70" + integrity sha512-h+PFCWfZ0Q3Dx84SppET/TFpcQHmxFW8/oV9ArEvMilw4EBN+IlxgbL0CnHwjHW64szcmrM0mbebjEfHf4FXmw== + dependencies: + "@aws-sdk/credential-provider-env" "3.620.1" + "@aws-sdk/credential-provider-http" "3.635.0" + "@aws-sdk/credential-provider-process" "3.620.1" + "@aws-sdk/credential-provider-sso" "3.637.0" + "@aws-sdk/credential-provider-web-identity" "3.621.0" + "@aws-sdk/types" "3.609.0" + "@smithy/credential-provider-imds" "^3.2.0" + "@smithy/property-provider" "^3.1.3" + "@smithy/shared-ini-file-loader" "^3.1.4" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-node@3.637.0": + version "3.637.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.637.0.tgz#0ac6678ab31783adf5b1cf03add5d1da101ea946" + integrity sha512-yoEhoxJJfs7sPVQ6Is939BDQJZpZCoUgKr/ySse4YKOZ24t4VqgHA6+wV7rYh+7IW24Rd91UTvEzSuHYTlxlNA== + dependencies: + "@aws-sdk/credential-provider-env" "3.620.1" + "@aws-sdk/credential-provider-http" "3.635.0" + "@aws-sdk/credential-provider-ini" "3.637.0" + "@aws-sdk/credential-provider-process" "3.620.1" + "@aws-sdk/credential-provider-sso" "3.637.0" + "@aws-sdk/credential-provider-web-identity" "3.621.0" + "@aws-sdk/types" "3.609.0" + "@smithy/credential-provider-imds" "^3.2.0" + "@smithy/property-provider" "^3.1.3" + "@smithy/shared-ini-file-loader" "^3.1.4" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-process@3.620.1": + version "3.620.1" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.620.1.tgz#10387cf85400420bb4bbda9cc56937dcc6d6d0ee" + integrity sha512-hWqFMidqLAkaV9G460+1at6qa9vySbjQKKc04p59OT7lZ5cO5VH5S4aI05e+m4j364MBROjjk2ugNvfNf/8ILg== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/property-provider" "^3.1.3" + "@smithy/shared-ini-file-loader" "^3.1.4" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-sso@3.637.0": + version "3.637.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.637.0.tgz#13acf77579df026e89ced33501489defd06a0518" + integrity sha512-Mvz+h+e62/tl+dVikLafhv+qkZJ9RUb8l2YN/LeKMWkxQylPT83CPk9aimVhCV89zth1zpREArl97+3xsfgQvA== + dependencies: + "@aws-sdk/client-sso" "3.637.0" + "@aws-sdk/token-providers" "3.614.0" + "@aws-sdk/types" "3.609.0" + "@smithy/property-provider" "^3.1.3" + "@smithy/shared-ini-file-loader" "^3.1.4" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-web-identity@3.621.0": + version "3.621.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.621.0.tgz#b25878c0a05dad60cd5f91e7e5a31a145c2f14be" + integrity sha512-w7ASSyfNvcx7+bYGep3VBgC3K6vEdLmlpjT7nSIHxxQf+WSdvy+HynwJosrpZax0sK5q0D1Jpn/5q+r5lwwW6w== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/property-provider" "^3.1.3" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/credential-providers@^3.637.0": + version "3.637.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-providers/-/credential-providers-3.637.0.tgz#372598b0a29cf3ce2362081400442825555be43e" + integrity sha512-yW1scL3Z7JsrTrmhjyZsB6tsMJ49UCO42BGlNWZAW+kN1vNJ+qbv6XYQJWR4gjpuD2rdmtGcEawcgllE2Bmigw== + dependencies: + "@aws-sdk/client-cognito-identity" "3.637.0" + "@aws-sdk/client-sso" "3.637.0" + "@aws-sdk/client-sts" "3.637.0" + "@aws-sdk/credential-provider-cognito-identity" "3.637.0" + "@aws-sdk/credential-provider-env" "3.620.1" + "@aws-sdk/credential-provider-http" "3.635.0" + "@aws-sdk/credential-provider-ini" "3.637.0" + "@aws-sdk/credential-provider-node" "3.637.0" + "@aws-sdk/credential-provider-process" "3.620.1" + "@aws-sdk/credential-provider-sso" "3.637.0" + "@aws-sdk/credential-provider-web-identity" "3.621.0" + "@aws-sdk/types" "3.609.0" + "@smithy/credential-provider-imds" "^3.2.0" + "@smithy/property-provider" "^3.1.3" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/lib-storage@^3.637.0": + version "3.637.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/lib-storage/-/lib-storage-3.637.0.tgz#de339f2efe3904d5177a23f1ee6e261691ee94a1" + integrity sha512-HiNGOP4a1QrCWwO1joKw4mCp19nLXoF9K52PislBaYDI35IlHC3DP6MeOg5zmElwtL1GtEHFBy5olfPWPsLyLg== + dependencies: + "@smithy/abort-controller" "^3.1.1" + "@smithy/middleware-endpoint" "^3.1.0" + "@smithy/smithy-client" "^3.2.0" + buffer "5.6.0" + events "3.3.0" + stream-browserify "3.0.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" + integrity sha512-VMtPEZwqYrII/oUkffYsNWY9PZ9xpNJpMgmyU0rlDQ25O1c0Hk3fJmZRe6pEkAJ0omD7kLrqGl1DUjQVxpd/Rg== + 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-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" + integrity sha512-S62U2dy4jMDhDFDK5gZ4VxFdWzCtLzwbYyFZx2uvPYTECkepLUfzLic2BHg2Qvtu4QjX+oGE3P/7fwaGIsGNuQ== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-recursion-detection@3.620.0": + version "3.620.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.620.0.tgz#f8270dfff843fd756be971e5673f89c6a24c6513" + integrity sha512-nh91S7aGK3e/o1ck64sA/CyoFw+gAYj2BDOnoNa6ouyCrVJED96ZXWbhye/fz9SgmNUZR2g7GdVpiLpMKZoI5w== + 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-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.637.0": + version "3.637.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.637.0.tgz#2b00de72b00953a477bcc02a68d8cbb5e9670c44" + integrity sha512-EYo0NE9/da/OY8STDsK2LvM4kNa79DBsf4YVtaG4P5pZ615IeFsD8xOHZeuJmUrSMlVQ8ywPRX7WMucUybsKug== + dependencies: + "@aws-sdk/types" "3.609.0" + "@aws-sdk/util-endpoints" "3.637.0" + "@smithy/protocol-http" "^4.1.0" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/region-config-resolver@3.614.0": + version "3.614.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/region-config-resolver/-/region-config-resolver-3.614.0.tgz#9cebb31a5bcfea2a41891fff7f28d0164cde179a" + integrity sha512-vDCeMXvic/LU0KFIUjpC3RiSTIkkvESsEfbVHiHH0YINfl8HnEqR5rj+L8+phsCeVg2+LmYwYxd5NRz4PHxt5g== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/node-config-provider" "^3.1.4" + "@smithy/types" "^3.3.0" + "@smithy/util-config-provider" "^3.0.0" + "@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" + integrity sha512-okItqyY6L9IHdxqs+Z116y5/nda7rHxLvROxtAJdLavWTYDydxrZstImNgGWTeVdmc0xX2gJCI77UYUTQWnhRw== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/property-provider" "^3.1.3" + "@smithy/shared-ini-file-loader" "^3.1.4" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/types@3.609.0", "@aws-sdk/types@^3.222.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.609.0.tgz#06b39d799c9f197a7b43670243e8e78a3bf7d6a5" + integrity sha512-+Tqnh9w0h2LcrUsdXyT1F8mNhXz+tVYBtP19LpeEGntmvHwa2XzvLUCWpoIAIVsHp5+HdB2X9Sn0KAtmbFXc2Q== + dependencies: + "@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.637.0": + version "3.637.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-endpoints/-/util-endpoints-3.637.0.tgz#e20bcb69028039fdbc06e98a3028c7f8d8e8adaa" + integrity sha512-pAqOKUHeVWHEXXDIp/qoMk/6jyxIb6GGjnK1/f8dKHtKIEs4tKsnnL563gceEvdad53OPXIt86uoevCcCzmBnw== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/types" "^3.3.0" + "@smithy/util-endpoints" "^2.0.5" + tslib "^2.6.2" + +"@aws-sdk/util-locate-window@^3.0.0": + version "3.568.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-locate-window/-/util-locate-window-3.568.0.tgz#2acc4b2236af0d7494f7e517401ba6b3c4af11ff" + integrity sha512-3nh4TINkXYr+H41QaPelCceEB2FXP3fxp93YZXB/kqJvX0U9j0N0Uk45gvsjmEPzG8XxkPEeLIfT2I1M7A6Lig== + dependencies: + tslib "^2.6.2" + +"@aws-sdk/util-user-agent-browser@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.609.0.tgz#aa15421b2e32ae8bc589dac2bd6e8969832ce588" + integrity sha512-fojPU+mNahzQ0YHYBsx0ZIhmMA96H+ZIZ665ObU9tl+SGdbLneVZVikGve+NmHTQwHzwkFsZYYnVKAkreJLAtA== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/types" "^3.3.0" + bowser "^2.11.0" + tslib "^2.6.2" + +"@aws-sdk/util-user-agent-node@3.614.0": + version "3.614.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.614.0.tgz#1e3f49a80f841a3f21647baed2adce01aac5beb5" + integrity sha512-15ElZT88peoHnq5TEoEtZwoXTXRxNrk60TZNdpl/TUBJ5oNJ9Dqb5Z4ryb8ofN6nm9aFf59GVAerFDz8iUoHBA== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/node-config-provider" "^3.1.4" + "@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" @@ -687,20 +1463,538 @@ resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== -"@sinonjs/commons@^3.0.0": +"@sinonjs/commons@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-2.0.0.tgz#fd4ca5b063554307e8327b4564bd56d3b73924a3" + integrity sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg== + dependencies: + type-detect "4.0.8" + +"@sinonjs/commons@^3.0.0", "@sinonjs/commons@^3.0.1": version "3.0.1" resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.1.tgz#1029357e44ca901a615585f6d27738dbc89084cd" integrity sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ== 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== dependencies: "@sinonjs/commons" "^3.0.0" +"@sinonjs/fake-timers@^11.2.2": + version "11.3.1" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-11.3.1.tgz#51d6e8d83ca261ff02c0ab0e68e9db23d5cd5999" + integrity sha512-EVJO7nW5M/F5Tur0Rf2z/QoMo+1Ia963RiMtapiQrEWvY0iBUvADo8Beegwjpnle5BHkyHuoxSTW3jF43H1XRA== + dependencies: + "@sinonjs/commons" "^3.0.1" + +"@sinonjs/samsam@^8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-8.0.0.tgz#0d488c91efb3fa1442e26abea81759dfc8b5ac60" + integrity sha512-Bp8KUVlLp8ibJZrnvq2foVhP0IVX2CIprMJPK0vqGqgrDa0OHVKeZyBykqskkrdxV6yKBPmGasO8LVjAKR3Gew== + dependencies: + "@sinonjs/commons" "^2.0.0" + lodash.get "^4.4.2" + type-detect "^4.0.8" + +"@sinonjs/text-encoding@^0.7.2": + version "0.7.3" + resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.3.tgz#282046f03e886e352b2d5f5da5eb755e01457f3f" + integrity sha512-DE427ROAphMQzU4ENbliGYrBSYPXF+TtLg9S8vzeA+OF4ZKzoDdzfL8sxuMUGS/lgRhM6j1URSk9ghf7Xo1tyA== + +"@smithy/abort-controller@^3.1.1": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@smithy/abort-controller/-/abort-controller-3.1.1.tgz#291210611ff6afecfc198d0ca72d5771d8461d16" + integrity sha512-MBJBiidoe+0cTFhyxT8g+9g7CeVccLM0IOKKUMCNQ1CNMJ/eIfoo0RTfVrXOONEI1UCN1W+zkiHSbzUNE9dZtQ== + dependencies: + "@smithy/types" "^3.3.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" + integrity sha512-SkW5LxfkSI1bUC74OtfBbdz+grQXYiPYolyu8VfpLIjEoN/sHVBlLeGXMQ1vX4ejkgfv6sxVbQJ32yF2cl1veA== + dependencies: + "@smithy/node-config-provider" "^3.1.4" + "@smithy/types" "^3.3.0" + "@smithy/util-config-provider" "^3.0.0" + "@smithy/util-middleware" "^3.0.3" + tslib "^2.6.2" + +"@smithy/core@^2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@smithy/core/-/core-2.4.0.tgz#56e917b6ab2dffeba681a05395c40a757d681147" + integrity sha512-cHXq+FneIF/KJbt4q4pjN186+Jf4ZB0ZOqEaZMBhT79srEyGDDBV31NqBRBjazz8ppQ1bJbDJMY9ba5wKFV36w== + dependencies: + "@smithy/middleware-endpoint" "^3.1.0" + "@smithy/middleware-retry" "^3.0.15" + "@smithy/middleware-serde" "^3.0.3" + "@smithy/protocol-http" "^4.1.0" + "@smithy/smithy-client" "^3.2.0" + "@smithy/types" "^3.3.0" + "@smithy/util-body-length-browser" "^3.0.0" + "@smithy/util-middleware" "^3.0.3" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@smithy/credential-provider-imds@^3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@smithy/credential-provider-imds/-/credential-provider-imds-3.2.0.tgz#0e0e7ddaff1a8633cb927aee1056c0ab506b7ecf" + integrity sha512-0SCIzgd8LYZ9EJxUjLXBmEKSZR/P/w6l7Rz/pab9culE/RWuqelAKGJvn5qUOl8BgX8Yj5HWM50A5hiB/RzsgA== + dependencies: + "@smithy/node-config-provider" "^3.1.4" + "@smithy/property-provider" "^3.1.3" + "@smithy/types" "^3.3.0" + "@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" + integrity sha512-kBprh5Gs5h7ug4nBWZi1FZthdqSM+T7zMmsZxx0IBvWUn7dK3diz2SHn7Bs4dQGFDk8plDv375gzenDoNwrXjg== + dependencies: + "@smithy/protocol-http" "^4.1.0" + "@smithy/querystring-builder" "^3.0.3" + "@smithy/types" "^3.3.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" + integrity sha512-2ctBXpPMG+B3BtWSGNnKELJ7SH9e4TNefJS0cd2eSkOOROeBnnVBnAy9LtJ8tY4vUEoe55N4CNPxzbWvR39iBw== + dependencies: + "@smithy/types" "^3.3.0" + "@smithy/util-buffer-from" "^3.0.0" + "@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" + integrity sha512-ID1eL/zpDULmHJbflb864k72/SNOZCADRc9i7Exq3RUNJw6raWUSlFEQ+3PX3EYs++bTxZB2dE9mEHTQLv61tw== + dependencies: + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/is-array-buffer@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz#f84f0d9f9a36601a9ca9381688bd1b726fd39111" + integrity sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA== + dependencies: + tslib "^2.6.2" + +"@smithy/is-array-buffer@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz#9a95c2d46b8768946a9eec7f935feaddcffa5e7a" + integrity sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ== + 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" + integrity sha512-ILEzC2eyxx6ncej3zZSwMpB5RJ0zuqH7eMptxC4KN3f+v9bqT8ohssKbhNR78k/2tWW+KS5Spw+tbPF4Ejyqvw== + dependencies: + "@smithy/protocol-http" "^4.1.0" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/middleware-endpoint@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@smithy/middleware-endpoint/-/middleware-endpoint-3.1.0.tgz#9b8a496d87a68ec43f3f1a0139868d6765a88119" + integrity sha512-5y5aiKCEwg9TDPB4yFE7H6tYvGFf1OJHNczeY10/EFF8Ir8jZbNntQJxMWNfeQjC1mxPsaQ6mR9cvQbf+0YeMw== + dependencies: + "@smithy/middleware-serde" "^3.0.3" + "@smithy/node-config-provider" "^3.1.4" + "@smithy/shared-ini-file-loader" "^3.1.4" + "@smithy/types" "^3.3.0" + "@smithy/url-parser" "^3.0.3" + "@smithy/util-middleware" "^3.0.3" + tslib "^2.6.2" + +"@smithy/middleware-retry@^3.0.15": + version "3.0.15" + resolved "https://registry.yarnpkg.com/@smithy/middleware-retry/-/middleware-retry-3.0.15.tgz#9b96900cde70d8aafd267e13f4e79241be90e0c7" + integrity sha512-iTMedvNt1ApdvkaoE8aSDuwaoc+BhvHqttbA/FO4Ty+y/S5hW6Ci/CTScG7vam4RYJWZxdTElc3MEfHRVH6cgQ== + dependencies: + "@smithy/node-config-provider" "^3.1.4" + "@smithy/protocol-http" "^4.1.0" + "@smithy/service-error-classification" "^3.0.3" + "@smithy/smithy-client" "^3.2.0" + "@smithy/types" "^3.3.0" + "@smithy/util-middleware" "^3.0.3" + "@smithy/util-retry" "^3.0.3" + tslib "^2.6.2" + uuid "^9.0.1" + +"@smithy/middleware-serde@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@smithy/middleware-serde/-/middleware-serde-3.0.3.tgz#74d974460f74d99f38c861e6862984543a880a66" + integrity sha512-puUbyJQBcg9eSErFXjKNiGILJGtiqmuuNKEYNYfUD57fUl4i9+mfmThtQhvFXU0hCVG0iEJhvQUipUf+/SsFdA== + dependencies: + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/middleware-stack@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@smithy/middleware-stack/-/middleware-stack-3.0.3.tgz#91845c7e61e6f137fa912b623b6def719a4f6ce7" + integrity sha512-r4klY9nFudB0r9UdSMaGSyjyQK5adUyPnQN/ZM6M75phTxOdnc/AhpvGD1fQUvgmqjQEBGCwpnPbDm8pH5PapA== + dependencies: + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/node-config-provider@^3.1.4": + version "3.1.4" + resolved "https://registry.yarnpkg.com/@smithy/node-config-provider/-/node-config-provider-3.1.4.tgz#05647bed666aa8036a1ad72323c1942e5d421be1" + integrity sha512-YvnElQy8HR4vDcAjoy7Xkx9YT8xZP4cBXcbJSgm/kxmiQu08DwUwj8rkGnyoJTpfl/3xYHH+d8zE+eHqoDCSdQ== + dependencies: + "@smithy/property-provider" "^3.1.3" + "@smithy/shared-ini-file-loader" "^3.1.4" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/node-http-handler@^3.1.4": + version "3.1.4" + resolved "https://registry.yarnpkg.com/@smithy/node-http-handler/-/node-http-handler-3.1.4.tgz#be4195e45639e690d522cd5f11513ea822ff9d5f" + integrity sha512-+UmxgixgOr/yLsUxcEKGH0fMNVteJFGkmRltYFHnBMlogyFdpzn2CwqWmxOrfJELhV34v0WSlaqG1UtE1uXlJg== + dependencies: + "@smithy/abort-controller" "^3.1.1" + "@smithy/protocol-http" "^4.1.0" + "@smithy/querystring-builder" "^3.0.3" + "@smithy/types" "^3.3.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" + integrity sha512-zahyOVR9Q4PEoguJ/NrFP4O7SMAfYO1HLhB18M+q+Z4KFd4V2obiMnlVoUFzFLSPeVt1POyNWneHHrZaTMoc/g== + dependencies: + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/protocol-http@^4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@smithy/protocol-http/-/protocol-http-4.1.0.tgz#23519d8f45bf4f33960ea5415847bc2b620a010b" + integrity sha512-dPVoHYQ2wcHooGXg3LQisa1hH0e4y0pAddPMeeUPipI1tEOqL6A4N0/G7abeq+K8wrwSgjk4C0wnD1XZpJm5aA== + dependencies: + "@smithy/types" "^3.3.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" + integrity sha512-vyWckeUeesFKzCDaRwWLUA1Xym9McaA6XpFfAK5qI9DKJ4M33ooQGqvM4J+LalH4u/Dq9nFiC8U6Qn1qi0+9zw== + dependencies: + "@smithy/types" "^3.3.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" + integrity sha512-zahM1lQv2YjmznnfQsWbYojFe55l0SLG/988brlLv1i8z3dubloLF+75ATRsqPBboUXsW6I9CPGE5rQgLfY0vQ== + dependencies: + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/service-error-classification@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@smithy/service-error-classification/-/service-error-classification-3.0.3.tgz#73484255060a094aa9372f6cd972dcaf97e3ce80" + integrity sha512-Jn39sSl8cim/VlkLsUhRFq/dKDnRUFlfRkvhOJaUbLBXUsLRLNf9WaxDv/z9BjuQ3A6k/qE8af1lsqcwm7+DaQ== + dependencies: + "@smithy/types" "^3.3.0" + +"@smithy/shared-ini-file-loader@^3.1.4": + version "3.1.4" + resolved "https://registry.yarnpkg.com/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.4.tgz#7dceaf5a5307a2ee347ace8aba17312a1a3ede15" + integrity sha512-qMxS4hBGB8FY2GQqshcRUy1K6k8aBWP5vwm8qKkCT3A9K2dawUwOIJfqh9Yste/Bl0J2lzosVyrXDj68kLcHXQ== + dependencies: + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/signature-v4@^4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@smithy/signature-v4/-/signature-v4-4.1.0.tgz#251ff43dc1f4ad66776122732fea9e56efc56443" + integrity sha512-aRryp2XNZeRcOtuJoxjydO6QTaVhxx/vjaR+gx7ZjaFgrgPRyZ3HCTbfwqYj6ZWEBHkCSUfcaymKPURaByukag== + dependencies: + "@smithy/is-array-buffer" "^3.0.0" + "@smithy/protocol-http" "^4.1.0" + "@smithy/types" "^3.3.0" + "@smithy/util-hex-encoding" "^3.0.0" + "@smithy/util-middleware" "^3.0.3" + "@smithy/util-uri-escape" "^3.0.0" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@smithy/smithy-client@^3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@smithy/smithy-client/-/smithy-client-3.2.0.tgz#6db94024e4bdaefa079ac68dbea23dafbea230c8" + integrity sha512-pDbtxs8WOhJLJSeaF/eAbPgXg4VVYFlRcL/zoNYA5WbG3wBL06CHtBSg53ppkttDpAJ/hdiede+xApip1CwSLw== + dependencies: + "@smithy/middleware-endpoint" "^3.1.0" + "@smithy/middleware-stack" "^3.0.3" + "@smithy/protocol-http" "^4.1.0" + "@smithy/types" "^3.3.0" + "@smithy/util-stream" "^3.1.3" + tslib "^2.6.2" + +"@smithy/types@^3.3.0": + version "3.3.0" + resolved "https://registry.yarnpkg.com/@smithy/types/-/types-3.3.0.tgz#fae037c733d09bc758946a01a3de0ef6e210b16b" + integrity sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA== + 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" + integrity sha512-pw3VtZtX2rg+s6HMs6/+u9+hu6oY6U7IohGhVNnjbgKy86wcIsSZwgHrFR+t67Uyxvp4Xz3p3kGXXIpTNisq8A== + dependencies: + "@smithy/querystring-parser" "^3.0.3" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/util-base64@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/util-base64/-/util-base64-3.0.0.tgz#f7a9a82adf34e27a72d0719395713edf0e493017" + integrity sha512-Kxvoh5Qtt0CDsfajiZOCpJxgtPHXOKwmM+Zy4waD43UoEMA+qPxxa98aE/7ZhdnBFZFXMOiBR5xbcaMhLtznQQ== + dependencies: + "@smithy/util-buffer-from" "^3.0.0" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@smithy/util-body-length-browser@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/util-body-length-browser/-/util-body-length-browser-3.0.0.tgz#86ec2f6256310b4845a2f064e2f571c1ca164ded" + integrity sha512-cbjJs2A1mLYmqmyVl80uoLTJhAcfzMOyPgjwAYusWKMdLeNtzmMz9YxNl3/jRLoxSS3wkqkf0jwNdtXWtyEBaQ== + dependencies: + tslib "^2.6.2" + +"@smithy/util-body-length-node@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/util-body-length-node/-/util-body-length-node-3.0.0.tgz#99a291bae40d8932166907fe981d6a1f54298a6d" + integrity sha512-Tj7pZ4bUloNUP6PzwhN7K386tmSmEET9QtQg0TgdNOnxhZvCssHji+oZTUIuzxECRfG8rdm2PMw2WCFs6eIYkA== + dependencies: + tslib "^2.6.2" + +"@smithy/util-buffer-from@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz#6fc88585165ec73f8681d426d96de5d402021e4b" + integrity sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA== + dependencies: + "@smithy/is-array-buffer" "^2.2.0" + tslib "^2.6.2" + +"@smithy/util-buffer-from@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz#559fc1c86138a89b2edaefc1e6677780c24594e3" + integrity sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA== + dependencies: + "@smithy/is-array-buffer" "^3.0.0" + tslib "^2.6.2" + +"@smithy/util-config-provider@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/util-config-provider/-/util-config-provider-3.0.0.tgz#62c6b73b22a430e84888a8f8da4b6029dd5b8efe" + integrity sha512-pbjk4s0fwq3Di/ANL+rCvJMKM5bzAQdE5S/6RL5NXgMExFAi6UgQMPOm5yPaIWPpr+EOXKXRonJ3FoxKf4mCJQ== + dependencies: + tslib "^2.6.2" + +"@smithy/util-defaults-mode-browser@^3.0.15": + version "3.0.15" + resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.15.tgz#df73b9ae3dddc9126e0bb93ebc720b09d7163858" + integrity sha512-FZ4Psa3vjp8kOXcd3HJOiDPBCWtiilLl57r0cnNtq/Ga9RSDrM5ERL6xt+tO43+2af6Pn5Yp92x2n5vPuduNfg== + dependencies: + "@smithy/property-provider" "^3.1.3" + "@smithy/smithy-client" "^3.2.0" + "@smithy/types" "^3.3.0" + bowser "^2.11.0" + tslib "^2.6.2" + +"@smithy/util-defaults-mode-node@^3.0.15": + version "3.0.15" + resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.15.tgz#d52476e1f2e66525d918b51f8d5a9b0972bf518e" + integrity sha512-KSyAAx2q6d0t6f/S4XB2+3+6aQacm3aLMhs9aLMqn18uYGUepbdssfogW5JQZpc6lXNBnp0tEnR5e9CEKmEd7A== + dependencies: + "@smithy/config-resolver" "^3.0.5" + "@smithy/credential-provider-imds" "^3.2.0" + "@smithy/node-config-provider" "^3.1.4" + "@smithy/property-provider" "^3.1.3" + "@smithy/smithy-client" "^3.2.0" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/util-endpoints@^2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@smithy/util-endpoints/-/util-endpoints-2.0.5.tgz#e3a7a4d1c41250bfd2b2d890d591273a7d8934be" + integrity sha512-ReQP0BWihIE68OAblC/WQmDD40Gx+QY1Ez8mTdFMXpmjfxSyz2fVQu3A4zXRfQU9sZXtewk3GmhfOHswvX+eNg== + dependencies: + "@smithy/node-config-provider" "^3.1.4" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/util-hex-encoding@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/util-hex-encoding/-/util-hex-encoding-3.0.0.tgz#32938b33d5bf2a15796cd3f178a55b4155c535e6" + integrity sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ== + dependencies: + tslib "^2.6.2" + +"@smithy/util-middleware@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@smithy/util-middleware/-/util-middleware-3.0.3.tgz#07bf9602682f5a6c55bc2f0384303f85fc68c87e" + integrity sha512-l+StyYYK/eO3DlVPbU+4Bi06Jjal+PFLSMmlWM1BEwyLxZ3aKkf1ROnoIakfaA7mC6uw3ny7JBkau4Yc+5zfWw== + dependencies: + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/util-retry@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@smithy/util-retry/-/util-retry-3.0.3.tgz#9b2ac0dbb1c81f69812a8affa4d772bebfc0e049" + integrity sha512-AFw+hjpbtVApzpNDhbjNG5NA3kyoMs7vx0gsgmlJF4s+yz1Zlepde7J58zpIRIsdjc+emhpAITxA88qLkPF26w== + dependencies: + "@smithy/service-error-classification" "^3.0.3" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/util-stream@^3.1.3": + version "3.1.3" + resolved "https://registry.yarnpkg.com/@smithy/util-stream/-/util-stream-3.1.3.tgz#699ee2397cc1d474e46d2034039d5263812dca64" + integrity sha512-FIv/bRhIlAxC0U7xM1BCnF2aDRPq0UaelqBHkM2lsCp26mcBbgI0tCVTv+jGdsQLUmAMybua/bjDsSu8RQHbmw== + dependencies: + "@smithy/fetch-http-handler" "^3.2.4" + "@smithy/node-http-handler" "^3.1.4" + "@smithy/types" "^3.3.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" + integrity sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg== + dependencies: + tslib "^2.6.2" + +"@smithy/util-utf8@^2.0.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@smithy/util-utf8/-/util-utf8-2.3.0.tgz#dd96d7640363259924a214313c3cf16e7dd329c5" + integrity sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A== + dependencies: + "@smithy/util-buffer-from" "^2.2.0" + tslib "^2.6.2" + +"@smithy/util-utf8@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/util-utf8/-/util-utf8-3.0.0.tgz#1a6a823d47cbec1fd6933e5fc87df975286d9d6a" + integrity sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA== + dependencies: + "@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" + "@tsconfig/node10@^1.0.7": version "1.0.11" resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.11.tgz#6ee46400685f130e278128c7b38b7e031ff5b2f2" @@ -849,6 +2143,18 @@ dependencies: "@types/node" "*" +"@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" @@ -1215,21 +2521,22 @@ available-typed-arrays@^1.0.7: dependencies: possible-typed-array-names "^1.0.0" -aws-sdk@^2.1685.0: - version "2.1685.0" - resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.1685.0.tgz#906d2a5d06a99ac288c9138f0bb6a7e3932e7da4" - integrity sha512-axo1by16nZXqHAFu65+/pLnqqaU3ez5ko3jTGDt0byafT7XD948z3WqqrXWT9vJTUF93DdTZ9DEcazj4Ai91cQ== - dependencies: - buffer "4.9.2" - events "1.1.1" - ieee754 "1.1.13" - jmespath "0.16.0" - querystring "0.2.0" - sax "1.2.1" - url "0.10.3" - util "^0.12.4" - uuid "8.0.0" - xml2js "0.6.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" babel-jest@^29.7.0: version "29.7.0" @@ -1313,6 +2620,11 @@ bl@^4.0.3: inherits "^2.0.4" readable-stream "^3.4.0" +bowser@^2.11.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/bowser/-/bowser-2.11.0.tgz#5ca3c35757a7aa5771500c70a73a9f91ef420a8f" + integrity sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA== + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -1369,14 +2681,13 @@ buffer-from@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== -buffer@4.9.2: - version "4.9.2" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8" - integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg== +buffer@5.6.0: + version "5.6.0" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.6.0.tgz#a31749dc7d81d84db08abf937b6b8c4033f62786" + integrity sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw== dependencies: base64-js "^1.0.2" ieee754 "^1.1.4" - isarray "^1.0.0" buffer@^5.5.0: version "5.7.1" @@ -1924,6 +3235,11 @@ diff@^4.0.1: resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== +diff@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.2.0.tgz#26ded047cd1179b78b9537d5ef725503ce1ae531" + integrity sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A== + dir-glob@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" @@ -2286,10 +3602,10 @@ esutils@^2.0.2: resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== -events@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" - integrity sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw== +events@3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== execa@^5.0.0: version "5.1.1" @@ -2311,7 +3627,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== @@ -2358,6 +3674,13 @@ fast-levenshtein@^2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== +fast-xml-parser@4.4.1: + version "4.4.1" + resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz#86dbf3f18edf8739326447bcaac31b4ae7f6514f" + integrity sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw== + dependencies: + strnum "^1.0.5" + fastq@^1.6.0: version "1.17.1" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47" @@ -2800,11 +4123,6 @@ iconv-lite@0.6.3: dependencies: safer-buffer ">= 2.1.2 < 3.0.0" -ieee754@1.1.13: - version "1.1.13" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" - integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg== - ieee754@^1.1.13, ieee754@^1.1.4: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" @@ -2854,7 +4172,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: +inherits@2, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3, inherits@~2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -2883,14 +4201,6 @@ interpret@^1.0.0: resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== -is-arguments@^1.0.4: - version "1.1.1" - resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" - integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - is-array-buffer@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.4.tgz#7a1f92b3d61edd2bc65d24f130530ea93d7fae98" @@ -2967,13 +4277,6 @@ is-generator-fn@^2.0.0: resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== -is-generator-function@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" - integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== - dependencies: - has-tostringtag "^1.0.0" - is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" @@ -3059,7 +4362,7 @@ is-text-path@^1.0.1: dependencies: text-extensions "^1.0.0" -is-typed-array@^1.1.13, is-typed-array@^1.1.3: +is-typed-array@^1.1.13: version "1.1.13" resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.13.tgz#d6c5ca56df62334959322d7d7dd1cca50debe229" integrity sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw== @@ -3073,16 +4376,16 @@ is-weakref@^1.0.2: dependencies: call-bind "^1.0.2" -isarray@^1.0.0, isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== - isarray@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" @@ -3519,11 +4822,6 @@ jest@^29.7.0: import-local "^3.0.2" jest-cli "^29.7.0" -jmespath@0.16.0: - version "0.16.0" - resolved "https://registry.yarnpkg.com/jmespath/-/jmespath-0.16.0.tgz#b15b0a85dfd4d930d43e69ed605943c802785076" - integrity sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw== - js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -3647,6 +4945,11 @@ jszip@^3.10.1: readable-stream "~2.3.6" setimmediate "^1.0.5" +just-extend@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-6.2.0.tgz#b816abfb3d67ee860482e7401564672558163947" + integrity sha512-cYofQu2Xpom82S6qD778jBDpwvvy39s1l/hrYij2u9AMdQcGRpaBu6kY4mVhuno5kJVi1DAz4aiphA2WI1/OAw== + keyv@^4.5.3: version "4.5.4" resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" @@ -3751,6 +5054,11 @@ lodash.flatten@^4.4.0: resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f" integrity sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g== +lodash.get@^4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" + integrity sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ== + lodash.ismatch@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz#756cb5150ca3ba6f11085a78849645f188f85f37" @@ -3921,11 +5229,6 @@ mkdirp@^1.0.4: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== -mock-fs@^4.14.0: - version "4.14.0" - resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-4.14.0.tgz#ce5124d2c601421255985e6e94da80a7357b1b18" - integrity sha512-qYvlv/exQ4+svI3UOvPUpLDF0OMX5euvUH0Ny4N5QyRyhNdgAgUrVH3iUINSzEPLvx0kbo/Bp28GJKIqvE7URw== - modify-values@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022" @@ -3951,6 +5254,17 @@ 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.4: + version "5.1.9" + resolved "https://registry.yarnpkg.com/nise/-/nise-5.1.9.tgz#0cb73b5e4499d738231a473cd89bd8afbb618139" + integrity sha512-qOnoujW4SV6e40dYxJOb3uvuoPHtmLzIk4TFo+j0jPJoC+5Z9xja5qH5JZobEPsa8+YYphMrOSwnrshEhG2qww== + dependencies: + "@sinonjs/commons" "^3.0.0" + "@sinonjs/fake-timers" "^11.2.2" + "@sinonjs/text-encoding" "^0.7.2" + just-extend "^6.2.0" + path-to-regexp "^6.2.1" + node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" @@ -4193,6 +5507,11 @@ path-parse@^1.0.7: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== +path-to-regexp@^6.2.1: + version "6.2.2" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.2.2.tgz#324377a83e5049cbecadc5554d6a63a9a4866b36" + integrity sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw== + path-type@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" @@ -4306,11 +5625,6 @@ psl@^1.1.33: resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== -punycode@1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" - integrity sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw== - punycode@^2.1.0, punycode@^2.1.1, punycode@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" @@ -4321,11 +5635,6 @@ pure-rand@^6.0.0: resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.1.0.tgz#d173cf23258231976ccbdb05247c9787957604f2" integrity sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA== -querystring@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" - integrity sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g== - querystringify@^2.1.1: version "2.2.0" resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" @@ -4395,7 +5704,7 @@ readable-stream@^2.0.0, readable-stream@^2.0.5, readable-stream@~2.3.6: string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^3.0.0, readable-stream@^3.0.2, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0: +readable-stream@^3.0.0, readable-stream@^3.0.2, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.5.0, readable-stream@^3.6.0: version "3.6.2" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== @@ -4550,16 +5859,6 @@ safe-regex-test@^1.0.3: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -sax@1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.1.tgz#7b8e656190b228e81a66aea748480d828cd2d37a" - integrity sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA== - -sax@>=0.6.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.4.1.tgz#44cc8988377f126304d3b3fc1010c733b929ef0f" - integrity sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg== - saxes@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/saxes/-/saxes-6.0.0.tgz#fe5b4a4768df4f14a201b1ba6a65c1f3d9988cc5" @@ -4653,6 +5952,18 @@ signal-exit@^3.0.3, signal-exit@^3.0.7: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== +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" + sisteransi@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" @@ -4728,6 +6039,14 @@ stack-utils@^2.0.3: dependencies: escape-string-regexp "^2.0.0" +stream-browserify@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-3.0.0.tgz#22b0a2850cdf6503e73085da1fc7b7d0c2122f2f" + integrity sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA== + dependencies: + inherits "~2.0.4" + readable-stream "^3.5.0" + string-length@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" @@ -4821,6 +6140,11 @@ strip-json-comments@^3.1.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +strnum@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/strnum/-/strnum-1.0.5.tgz#5c4e829fe15ad4ff0d20c3db5ac97b73c9b072db" + integrity sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA== + supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -4828,7 +6152,7 @@ supports-color@^5.3.0: dependencies: has-flag "^3.0.0" -supports-color@^7.1.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== @@ -4996,7 +6320,7 @@ tsconfig-paths@^3.15.0: minimist "^1.2.6" strip-bom "^3.0.0" -tslib@^2.6.2: +tslib@^2.1.0, tslib@^2.6.2: version "2.7.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.7.0.tgz#d9b40c5c40ab59e8738f297df3087bf1a2690c01" integrity sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA== @@ -5013,6 +6337,11 @@ type-detect@4.0.8: resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== +type-detect@^4.0.8: + version "4.1.0" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.1.0.tgz#deb2453e8f08dcae7ae98c626b13dddb0155906c" + integrity sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw== + type-fest@^0.18.0: version "0.18.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.18.1.tgz#db4bc151a4a2cf4eebf9add5db75508db6cc841f" @@ -5150,40 +6479,21 @@ url-parse@^1.5.3: querystringify "^2.1.1" requires-port "^1.0.0" -url@0.10.3: - version "0.10.3" - resolved "https://registry.yarnpkg.com/url/-/url-0.10.3.tgz#021e4d9c7705f21bbf37d03ceb58767402774c64" - integrity sha512-hzSUW2q06EqL1gKM/a+obYHLIO6ct2hwPuviqTTOcfFVc61UbfJ2Q32+uGL/HCPxKqrdGB5QUwIe7UqlDgwsOQ== - dependencies: - punycode "1.3.2" - querystring "0.2.0" - util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== -util@^0.12.4: - version "0.12.5" - resolved "https://registry.yarnpkg.com/util/-/util-0.12.5.tgz#5f17a6059b73db61a875668781a1c2b136bd6fbc" - integrity sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA== - dependencies: - inherits "^2.0.3" - is-arguments "^1.0.4" - is-generator-function "^1.0.7" - is-typed-array "^1.1.3" - which-typed-array "^1.1.2" - -uuid@8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.0.0.tgz#bc6ccf91b5ff0ac07bbcdbf1c7c4e150db4dbb6c" - integrity sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw== - uuid@^8.3.2: version "8.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== +uuid@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30" + integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA== + v8-compile-cache-lib@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" @@ -5256,7 +6566,7 @@ which-boxed-primitive@^1.0.2: is-string "^1.0.5" is-symbol "^1.0.3" -which-typed-array@^1.1.14, which-typed-array@^1.1.15, which-typed-array@^1.1.2: +which-typed-array@^1.1.14, which-typed-array@^1.1.15: version "1.1.15" resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.15.tgz#264859e9b11a649b388bfaaf4f767df1f779b38d" integrity sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA== @@ -5316,14 +6626,6 @@ xml-name-validator@^5.0.0: resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-5.0.0.tgz#82be9b957f7afdacf961e5980f1bf227c0bf7673" integrity sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg== -xml2js@0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.6.2.tgz#dd0b630083aa09c161e25a4d0901e2b2a929b499" - integrity sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA== - dependencies: - sax ">=0.6.0" - xmlbuilder "~11.0.0" - xml@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/xml/-/xml-1.0.1.tgz#78ba72020029c5bc87b8a81a3cfcd74b4a2fc1e5" @@ -5339,11 +6641,6 @@ xmlbuilder2@^3.1.1: "@oozcitak/util" "8.3.8" js-yaml "3.14.1" -xmlbuilder@~11.0.0: - version "11.0.1" - resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" - integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA== - xmlchars@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb"