diff --git a/.projen/deps.json b/.projen/deps.json index 96ec0eccc..7befb077e 100644 --- a/.projen/deps.json +++ b/.projen/deps.json @@ -23,7 +23,7 @@ }, { "name": "@types/node", - "version": "ts5.6", + "version": "ts5.8", "type": "build" }, { @@ -98,7 +98,7 @@ }, { "name": "typescript", - "version": "5.6", + "version": "5.8", "type": "build" } ], diff --git a/.projenrc.ts b/.projenrc.ts index a903b1a5a..1e1b88a90 100644 --- a/.projenrc.ts +++ b/.projenrc.ts @@ -19,9 +19,10 @@ import { TypecheckTests } from './projenrc/TypecheckTests'; // #region shared config -// 5.7 sometimes gives a weird error in `ts-jest` in `@aws-cdk/cli-lib-alpha` -// https://github.com/microsoft/TypeScript/issues/60159 -const TYPESCRIPT_VERSION = '5.6'; +const TYPESCRIPT_VERSION = '5.8'; + +// This is a temporary aws-cdk-lib version until this PR is released: https://github.com/aws/aws-cdk/pull/34919 +const AWS_CDK_LIB_VERSION = '2.203.0'; /** * When adding an SDK dependency for a library, use this function @@ -672,6 +673,10 @@ const cdkAssetsLib = configureProject( // Append a specific version string for testing nextVersionCommand: 'tsx ../../../projenrc/next-version.ts neverMajor maybeRc', + + releasableCommits: transitiveFeaturesAndFixes('@aws-cdk/cdk-assets-lib', [ + '@aws-cdk/cloud-assembly-schema', + ]), }), ); @@ -744,6 +749,11 @@ const cdkAssetsCli = configureProject( // Append a specific version string for testing nextVersionCommand: 'tsx ../../projenrc/next-version.ts maybeRc', + + releasableCommits: transitiveFeaturesAndFixes('cdk-assets', [ + '@aws-cdk/cdk-assets-lib', + '@aws-cdk/cloud-assembly-schema', + ]), }), ); @@ -844,7 +854,7 @@ const toolkitLib = configureProject( '@smithy/util-stream', '@types/fs-extra', '@types/split2', - 'aws-cdk-lib', + `aws-cdk-lib@${AWS_CDK_LIB_VERSION}`, 'aws-sdk-client-mock', 'aws-sdk-client-mock-jest', 'fast-check', @@ -1042,7 +1052,7 @@ toolkitLib.gitignore.addPatterns( const apiExtractorDocsTask = toolkitLib.addTask('docs', { exec: [ // Run api-extractor to generate the API model - 'api-extractor run || true', + 'api-extractor run', // Create a directory for the API model 'mkdir -p dist/api-extractor-docs/cdk/api/toolkit-lib', // Copy the API model to the directory (with error handling) @@ -1630,6 +1640,7 @@ const cliInteg = configureProject( '@aws-sdk/client-sns', '@aws-sdk/client-sso', '@aws-sdk/client-sts', + '@aws-sdk/client-secrets-manager', '@aws-sdk/credential-providers', '@cdklabs/cdk-atmosphere-client', '@smithy/util-retry', // smithy packages don't have the same major version as SDK packages @@ -1637,7 +1648,7 @@ const cliInteg = configureProject( 'axios@^1', 'chalk@^4', 'fs-extra@^9', - 'glob@^7', + 'glob@^9', 'make-runnable@^1', 'mockttp@^3', 'npm@^10', @@ -1651,6 +1662,7 @@ const cliInteg = configureProject( 'jest@^29', 'jest-junit@^15', 'ts-jest@^29', + 'proxy-agent', 'node-pty', ], devDeps: [ @@ -1659,7 +1671,6 @@ const cliInteg = configureProject( '@types/semver@^7', '@types/yargs@^16', '@types/fs-extra@^9', - '@types/glob@^7', ], bin: { 'run-suite': 'bin/run-suite', diff --git a/package.json b/package.json index b3b565834..9dfaa8f1a 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "@aws-sdk/lib-storage": "^3", "@cdklabs/eslint-plugin": "^1.3.2", "@stylistic/eslint-plugin": "^3", - "@types/node": "ts5.6", + "@types/node": "ts5.8", "@typescript-eslint/eslint-plugin": "^8", "@typescript-eslint/parser": "^8", "cdklabs-projen-project-types": "^0.3.1", @@ -40,10 +40,10 @@ "jest-junit": "^16", "nx": "^20.8.2", "prettier": "^2.8", - "projen": "^0.94.0", + "projen": "^0.94.2", "semver": "^7.7.2", "ts-node": "^10.9.2", - "typescript": "5.6" + "typescript": "5.8" }, "engines": { "node": ">= 18.0.0" diff --git a/packages/@aws-cdk-testing/cli-integ/.projen/deps.json b/packages/@aws-cdk-testing/cli-integ/.projen/deps.json index 3e9747525..fbb03f7a0 100644 --- a/packages/@aws-cdk-testing/cli-integ/.projen/deps.json +++ b/packages/@aws-cdk-testing/cli-integ/.projen/deps.json @@ -22,11 +22,6 @@ "version": "^9", "type": "build" }, - { - "name": "@types/glob", - "version": "^7", - "type": "build" - }, { "name": "@types/jest", "type": "build" @@ -119,7 +114,7 @@ }, { "name": "typescript", - "version": "5.6", + "version": "5.8", "type": "build" }, { @@ -158,6 +153,10 @@ "name": "@aws-sdk/client-s3", "type": "runtime" }, + { + "name": "@aws-sdk/client-secrets-manager", + "type": "runtime" + }, { "name": "@aws-sdk/client-sns", "type": "runtime" @@ -208,7 +207,7 @@ }, { "name": "glob", - "version": "^7", + "version": "^9", "type": "runtime" }, { @@ -245,6 +244,10 @@ "version": "^6", "type": "runtime" }, + { + "name": "proxy-agent", + "type": "runtime" + }, { "name": "semver", "version": "^7", diff --git a/packages/@aws-cdk-testing/cli-integ/.projen/tasks.json b/packages/@aws-cdk-testing/cli-integ/.projen/tasks.json index 043997614..ff64e20b3 100644 --- a/packages/@aws-cdk-testing/cli-integ/.projen/tasks.json +++ b/packages/@aws-cdk-testing/cli-integ/.projen/tasks.json @@ -53,7 +53,7 @@ }, "steps": [ { - "exec": "npx npm-check-updates@16 --upgrade --target=minor --peer --no-deprecated --dep=dev,peer,prod,optional --filter=@cdklabs/eslint-plugin,@types/jest,eslint-config-prettier,eslint-import-resolver-typescript,eslint-plugin-import,eslint-plugin-jest,eslint-plugin-jsdoc,eslint-plugin-prettier,jest,license-checker,ts-jest,@aws-sdk/client-cloudformation,@aws-sdk/client-codeartifact,@aws-sdk/client-ecr,@aws-sdk/client-ecr-public,@aws-sdk/client-ecs,@aws-sdk/client-iam,@aws-sdk/client-lambda,@aws-sdk/client-s3,@aws-sdk/client-sns,@aws-sdk/client-sso,@aws-sdk/client-sts,@aws-sdk/credential-providers,@cdklabs/cdk-atmosphere-client,@smithy/types,@smithy/util-retry,node-pty" + "exec": "npx npm-check-updates@16 --upgrade --target=minor --peer --no-deprecated --dep=dev,peer,prod,optional --filter=@cdklabs/eslint-plugin,@types/jest,eslint-config-prettier,eslint-import-resolver-typescript,eslint-plugin-import,eslint-plugin-jest,eslint-plugin-jsdoc,eslint-plugin-prettier,jest,license-checker,ts-jest,@aws-sdk/client-cloudformation,@aws-sdk/client-codeartifact,@aws-sdk/client-ecr,@aws-sdk/client-ecr-public,@aws-sdk/client-ecs,@aws-sdk/client-iam,@aws-sdk/client-lambda,@aws-sdk/client-s3,@aws-sdk/client-secrets-manager,@aws-sdk/client-sns,@aws-sdk/client-sso,@aws-sdk/client-sts,@aws-sdk/credential-providers,@cdklabs/cdk-atmosphere-client,@smithy/types,@smithy/util-retry,node-pty,proxy-agent" } ] }, diff --git a/packages/@aws-cdk-testing/cli-integ/lib/aws.ts b/packages/@aws-cdk-testing/cli-integ/lib/aws.ts index 0bd882510..301de7f8b 100644 --- a/packages/@aws-cdk-testing/cli-integ/lib/aws.ts +++ b/packages/@aws-cdk-testing/cli-integ/lib/aws.ts @@ -8,7 +8,7 @@ import { import { DeleteRepositoryCommand, ECRClient } from '@aws-sdk/client-ecr'; import { ECRPUBLICClient } from '@aws-sdk/client-ecr-public'; import { ECSClient } from '@aws-sdk/client-ecs'; -import { IAMClient } from '@aws-sdk/client-iam'; +import { CreateRoleCommand, DeleteRoleCommand, DeleteRolePolicyCommand, IAMClient, ListRolePoliciesCommand, PutRolePolicyCommand } from '@aws-sdk/client-iam'; import { LambdaClient } from '@aws-sdk/client-lambda'; import { S3Client, @@ -17,27 +17,31 @@ import { type ObjectIdentifier, DeleteBucketCommand, } from '@aws-sdk/client-s3'; +import { SecretsManagerClient } from '@aws-sdk/client-secrets-manager'; import { SNSClient } from '@aws-sdk/client-sns'; import { SSOClient } from '@aws-sdk/client-sso'; -import { STSClient, GetCallerIdentityCommand } from '@aws-sdk/client-sts'; +import { AssumeRoleCommand, STSClient, GetCallerIdentityCommand } from '@aws-sdk/client-sts'; import { fromIni, fromNodeProviderChain } from '@aws-sdk/credential-providers'; -import type { AwsCredentialIdentity, AwsCredentialIdentityProvider } from '@smithy/types'; +import type { AwsCredentialIdentity, AwsCredentialIdentityProvider, NodeHttpHandlerOptions } from '@smithy/types'; import { ConfiguredRetryStrategy } from '@smithy/util-retry'; + interface ClientConfig { readonly credentials: AwsCredentialIdentityProvider | AwsCredentialIdentity; readonly region: string; readonly retryStrategy: ConfiguredRetryStrategy; + readonly requestHandler?: NodeHttpHandlerOptions; } export class AwsClients { - public static async forIdentity(region: string, identity: AwsCredentialIdentity, output: NodeJS.WritableStream) { - return new AwsClients(region, output, identity); + public static async forIdentity(randomString: string, region: string, identity: AwsCredentialIdentity, output: NodeJS.WritableStream) { + return new AwsClients(randomString, region, output, identity); } - public static async forRegion(region: string, output: NodeJS.WritableStream) { - return new AwsClients(region, output); + public static async forRegion(randomString: string, region: string, output: NodeJS.WritableStream) { + return new AwsClients(randomString, region, output); } + private readonly cleanup: (() => Promise)[] = []; private readonly config: ClientConfig; public readonly cloudFormation: CloudFormationClient; @@ -50,8 +54,11 @@ export class AwsClients { public readonly iam: IAMClient; public readonly lambda: LambdaClient; public readonly sts: STSClient; + public readonly secretsManager: SecretsManagerClient; - constructor( + private constructor( + /** A random string to use for temporary resources, like roles (should preferably match unique test-specific randomString) */ + private readonly randomString: string, public readonly region: string, private readonly output: NodeJS.WritableStream, public readonly identity?: AwsCredentialIdentity) { @@ -60,6 +67,7 @@ export class AwsClients { region: this.region, retryStrategy: new ConfiguredRetryStrategy(9, (attempt: number) => attempt ** 500), }; + this.cloudFormation = new CloudFormationClient(this.config); this.s3 = new S3Client(this.config); this.ecr = new ECRClient(this.config); @@ -70,6 +78,22 @@ export class AwsClients { this.iam = new IAMClient(this.config); this.lambda = new LambdaClient(this.config); this.sts = new STSClient(this.config); + this.secretsManager = new SecretsManagerClient(this.config); + } + + public addCleanup(cleanup: () => Promise) { + this.cleanup.push(cleanup); + } + + public async dispose() { + for (const cleanup of this.cleanup) { + try { + await cleanup(); + } catch (e: any) { + this.output.write(`⚠️ Error during cleanup: ${e.message}\n`); + } + } + this.cleanup.splice(0, this.cleanup.length); } public async account(): Promise { @@ -219,6 +243,79 @@ export class AwsClients { throw e; } } + + /** + * Create a role that will be cleaned up when the AwsClients object is cleaned up + */ + public async temporaryRole(namePrefix: string, assumeRolePolicyStatements: any[], policyStatements: any[]) { + const response = await this.iam.send(new CreateRoleCommand({ + RoleName: `${namePrefix}-${this.randomString}`, + AssumeRolePolicyDocument: JSON.stringify({ + Version: '2012-10-17', + Statement: assumeRolePolicyStatements, + }, undefined, 2), + Tags: [ + { + Key: 'deleteme', + Value: 'true', + }, + ], + })); + await this.iam.send(new PutRolePolicyCommand({ + RoleName: `${namePrefix}-${this.randomString}`, + PolicyName: 'DefaultPolicy', + PolicyDocument: JSON.stringify({ + Version: '2012-10-17', + Statement: policyStatements, + }, undefined, 2), + })); + + this.addCleanup(() => this.deleteRole(response.Role!.RoleName!)); + + return response.Role?.Arn ?? '*CreateRole did not return an ARN*'; + } + + public async waitForAssumeRole(roleArn: string) { + // Wait until the role has replicated + const deadline = Date.now() + 60_000; + let lastError: Error | undefined; + while (Date.now() < deadline) { + try { + await this.sts.send(new AssumeRoleCommand({ + RoleArn: roleArn, + RoleSessionName: 'test-existence', + })); + return; + } catch (e: any) { + lastError = e; + + if (e.name === 'AccessDenied') { + continue; + } + + throw e; + } + } + + throw new Error(`Timed out waiting for role ${roleArn} to become assumable: ${lastError}`); + } + + public async deleteRole(name: string) { + const policiesResponse = await this.iam.send(new ListRolePoliciesCommand({ + RoleName: name, + })); + + for (const policyName of policiesResponse.PolicyNames ?? []) { + await this.iam.send(new DeleteRolePolicyCommand({ + RoleName: name, + PolicyName: policyName, + })); + } + + await this.iam.send(new DeleteRoleCommand({ + RoleName: name, + })); + } } export function isStackMissingError(e: Error) { diff --git a/packages/@aws-cdk-testing/cli-integ/lib/cli/run-suite.ts b/packages/@aws-cdk-testing/cli-integ/lib/cli/run-suite.ts index 643c368b3..a0ba8a8ef 100644 --- a/packages/@aws-cdk-testing/cli-integ/lib/cli/run-suite.ts +++ b/packages/@aws-cdk-testing/cli-integ/lib/cli/run-suite.ts @@ -11,6 +11,9 @@ import { RunnerLibraryPreinstalledSource } from '../package-sources/library-prei import type { IRunnerSource, ITestCliSource, ITestLibrarySource } from '../package-sources/source'; import { serializeSources } from '../package-sources/subprocess'; +const CLI_PACKAGE_NAME = 'aws-cdk'; +const CDK_ASSETS_PACKAGE_NAME = 'cdk-assets'; + async function main() { const args = await yargs .command('* ', 'default command', y => y @@ -41,6 +44,11 @@ async function main() { alias: 'l', type: 'string', }) + .options('cdk-assets-version', { + describe: 'cdk-assets version to use.', + alias: 'a', + type: 'string', + }) .option('use-source', { descripton: 'Use TypeScript packages from the given source repository (or "auto")', type: 'string', @@ -105,25 +113,55 @@ async function main() { const suiteName = args.SUITENAME; // So many ways to specify this, and with various ways to spell the same flag (o_O) + // Also, some of them depend on each other for convenience. const cliSource = new UniqueOption>('CLI version'); + const cdkAssetsSource = new UniqueOption>('cdk-assets version'); + + // Specific CLI version for (const flagAlias of ['cli-version', 'use-cli-release'] as const) { if (args[flagAlias]) { - cliSource.set(new RunnerCliNpmSource(args[flagAlias]), `--${flagAlias}`); + cliSource.set(new RunnerCliNpmSource(CLI_PACKAGE_NAME, args[flagAlias]), `--${flagAlias}`); } } + + // Specific cdk-assets version + if (args['cdk-assets-version']) { + cdkAssetsSource.set(new RunnerCliNpmSource(CDK_ASSETS_PACKAGE_NAME, args['cdk-assets-version']), '--cdk-assets-version'); + } + + // Specifically use a source location for (const flagAlias of ['cli-source', 'use-source'] as const) { if (args[flagAlias]) { const root = args[flagAlias] === 'auto' ? await autoFindRepoRoot() : args[flagAlias]; - cliSource.set(new RunnerCliRepoSource(root), `--${flagAlias}`); + cliSource.set(new RunnerCliRepoSource(CLI_PACKAGE_NAME, root), `--${flagAlias}`); + cdkAssetsSource.set(new RunnerCliRepoSource(CDK_ASSETS_PACKAGE_NAME, root), `--${flagAlias}`); } } + + // Specifically request that a source location is given, or we didn't find a CLI yet. + // A CLI source is required, so if this fails that's alright. if (args['auto-source'] || !cliSource.isSet()) { - cliSource.set(new RunnerCliRepoSource(await autoFindRepoRoot()), '--auto-source'); + cliSource.set(new RunnerCliRepoSource(CLI_PACKAGE_NAME, await autoFindRepoRoot()), '--auto-source'); + } + + // If the CLI is taken from the source, and cdk-assets is not set, we can copy the cdk-assets source from the CLI source. + if (!cdkAssetsSource.isSet()) { + const cliSrc = cliSource.assert(); + if (cliSrc instanceof RunnerCliRepoSource) { + cdkAssetsSource.set(new RunnerCliRepoSource(CDK_ASSETS_PACKAGE_NAME, cliSrc.repoRoot), 'copied from CLI source'); + } } + // If cdk-assets is still not configured, fall back to the latest version that is available + if (!cdkAssetsSource.isSet()) { + cdkAssetsSource.set(new RunnerCliNpmSource(CDK_ASSETS_PACKAGE_NAME, 'latest'), '--cdk-assets-version not set'); + } + + // Library source is either the given one, or 'latest' (nice and simple) const librarySource: IRunnerSource = new RunnerLibraryNpmSource('aws-cdk-lib', args['framework-version'] ? args['framework-version'] : 'latest'); + // Toolkit lib source is either the given one, or the one that's being brought by 'package.json' already, or 'latest' const toolkitLibPackage = '@aws-cdk/toolkit-lib'; let toolkitSource: IRunnerSource | undefined; if (args['toolkit-lib-version']) { @@ -141,6 +179,7 @@ async function main() { console.log(` CLI source: ${cliSource.assert().sourceDescription}`); console.log(` Library source: ${librarySource.sourceDescription}`); console.log(` Toolkit lib source: ${toolkitSource.sourceDescription}`); + console.log(` cdk-assets source: ${cdkAssetsSource.assert().sourceDescription}`); if (args.verbose) { process.env.VERBOSE = '1'; @@ -171,10 +210,15 @@ async function main() { disposables.push(toolkitLib); console.log(` Toolkit library: ${toolkitLib.version}`); + const cdkAssets = await cdkAssetsSource.assert().runnerPrepare(); + disposables.push(cdkAssets); + console.log(` cdk-assets: ${cdkAssets.version}`); + serializeSources({ cli, library, toolkitLib, + cdkAssets, }); const jestConfig = path.resolve(__dirname, '..', '..', 'resources', 'integ.jest.config.js'); diff --git a/packages/@aws-cdk-testing/cli-integ/lib/npm.ts b/packages/@aws-cdk-testing/cli-integ/lib/npm.ts index c51f373b1..82c96a5f8 100644 --- a/packages/@aws-cdk-testing/cli-integ/lib/npm.ts +++ b/packages/@aws-cdk-testing/cli-integ/lib/npm.ts @@ -7,6 +7,7 @@ const MINIMUM_VERSION = '3.9'; export async function npmMostRecentMatching(packageName: string, range: string) { const output = JSON.parse(await shell(['node', require.resolve('npm'), '--silent', 'view', `${packageName}@${range}`, 'version', '--json'], { show: 'error', + captureStderr: false, })); if (typeof output === 'string') { diff --git a/packages/@aws-cdk-testing/cli-integ/lib/package-sources/cli-npm-source.ts b/packages/@aws-cdk-testing/cli-integ/lib/package-sources/cli-npm-source.ts index d092bef0b..8c548b9a8 100644 --- a/packages/@aws-cdk-testing/cli-integ/lib/package-sources/cli-npm-source.ts +++ b/packages/@aws-cdk-testing/cli-integ/lib/package-sources/cli-npm-source.ts @@ -8,7 +8,7 @@ import { addToShellPath, rimraf, shell } from '../shell'; export class RunnerCliNpmSource implements IRunnerSource { public readonly sourceDescription: string; - constructor(private readonly range: string) { + constructor(private readonly packageName: string, private readonly range: string) { this.sourceDescription = `${this.range} (npm)`; } @@ -16,12 +16,12 @@ export class RunnerCliNpmSource implements IRunnerSource { const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'tmpcdk')); fs.mkdirSync(tempDir, { recursive: true }); - await shell(['node', require.resolve('npm'), 'install', `aws-cdk@${this.range}`], { + await shell(['node', require.resolve('npm'), 'install', `${this.packageName}@${this.range}`], { cwd: tempDir, show: 'error', outputs: [process.stderr], }); - const installedVersion = await npmQueryInstalledVersion('aws-cdk', tempDir); + const installedVersion = await npmQueryInstalledVersion(this.packageName, tempDir); return { version: installedVersion, diff --git a/packages/@aws-cdk-testing/cli-integ/lib/package-sources/cli-repo-source.ts b/packages/@aws-cdk-testing/cli-integ/lib/package-sources/cli-repo-source.ts index 02f4dc9b6..101b2364d 100644 --- a/packages/@aws-cdk-testing/cli-integ/lib/package-sources/cli-repo-source.ts +++ b/packages/@aws-cdk-testing/cli-integ/lib/package-sources/cli-repo-source.ts @@ -12,8 +12,8 @@ export class RunnerCliRepoSource implements IRunnerSource { public readonly sourceDescription: string; private readonly cliBinPath: string; - constructor(private readonly repoRoot: string) { - this.cliBinPath = path.join(this.repoRoot, 'packages', 'aws-cdk', 'bin'); + constructor(private readonly packageName: string, public readonly repoRoot: string) { + this.cliBinPath = path.join(this.repoRoot, 'packages', this.packageName, 'bin'); this.sourceDescription = this.cliBinPath; } diff --git a/packages/@aws-cdk-testing/cli-integ/lib/package-sources/subprocess.ts b/packages/@aws-cdk-testing/cli-integ/lib/package-sources/subprocess.ts index 1fa5c9c13..4ebebbef6 100644 --- a/packages/@aws-cdk-testing/cli-integ/lib/package-sources/subprocess.ts +++ b/packages/@aws-cdk-testing/cli-integ/lib/package-sources/subprocess.ts @@ -7,6 +7,7 @@ export interface PreparedSources { readonly cli: IPreparedRunnerSource; readonly library: IPreparedRunnerSource; readonly toolkitLib: IPreparedRunnerSource; + readonly cdkAssets: IPreparedRunnerSource; } type SourceType = A extends IPreparedRunnerSource ? T : unknown; diff --git a/packages/@aws-cdk-testing/cli-integ/lib/shell.ts b/packages/@aws-cdk-testing/cli-integ/lib/shell.ts index 937e08fca..3353082f5 100644 --- a/packages/@aws-cdk-testing/cli-integ/lib/shell.ts +++ b/packages/@aws-cdk-testing/cli-integ/lib/shell.ts @@ -227,7 +227,10 @@ export class ShellHelper { constructor( private readonly _cwd: string, private readonly _output: NodeJS.WritableStream) { + } + public get dockerConfigDir() { + return path.join(this._cwd, '.docker'); } public async shell(command: string[], options: Omit = {}): Promise { @@ -238,7 +241,7 @@ export class ShellHelper { modEnv: { // give every shell its own docker config directory // so that parallel runs don't interfere with each other. - DOCKER_CONFIG: path.join(this._cwd, '.docker'), + DOCKER_CONFIG: this.dockerConfigDir, ...options.modEnv, }, }); diff --git a/packages/@aws-cdk-testing/cli-integ/lib/with-aws.ts b/packages/@aws-cdk-testing/cli-integ/lib/with-aws.ts index 7d7d7db5f..b118c5316 100644 --- a/packages/@aws-cdk-testing/cli-integ/lib/with-aws.ts +++ b/packages/@aws-cdk-testing/cli-integ/lib/with-aws.ts @@ -44,32 +44,39 @@ export function withAws( const start = Date.now(); const allocation = await atmosphere.acquire({ pool: atmospherePool(), requester: context.name, timeoutSeconds: 60 * 30 }); + let outcome = 'success'; context.reportWaitTime(Date.now() - start); - const aws = await AwsClients.forIdentity(allocation.environment.region, { - accessKeyId: allocation.credentials.accessKeyId, - secretAccessKey: allocation.credentials.secretAccessKey, - sessionToken: allocation.credentials.sessionToken, - accountId: allocation.environment.account, - }, context.output); - - await sanityCheck(aws); - - let outcome = 'success'; try { - return await block({ ...context, disableBootstrap, aws }); - } catch (e: any) { - outcome = 'failure'; - throw e; + const aws = await AwsClients.forIdentity(context.randomString, allocation.environment.region, { + accessKeyId: allocation.credentials.accessKeyId, + secretAccessKey: allocation.credentials.secretAccessKey, + sessionToken: allocation.credentials.sessionToken, + accountId: allocation.environment.account, + }, context.output); + await sanityCheck(aws); + + try { + return await block({ ...context, disableBootstrap, aws }); + } catch (e: any) { + outcome = 'failure'; + throw e; + } finally { + await aws.dispose(); + } } finally { await atmosphere.release(allocation.id, outcome); } } else { return regionPool().using(async (region) => { - const aws = await AwsClients.forRegion(region, context.output); - await sanityCheck(aws); + const aws = await AwsClients.forRegion(context.randomString, region, context.output); + try { + await sanityCheck(aws); - return block({ ...context, disableBootstrap, aws }); + return await block({ ...context, disableBootstrap, aws }); + } finally { + await aws.dispose(); + } }); } }; diff --git a/packages/@aws-cdk-testing/cli-integ/lib/with-cdk-app.ts b/packages/@aws-cdk-testing/cli-integ/lib/with-cdk-app.ts index 91c2bb056..0d0e56be4 100644 --- a/packages/@aws-cdk-testing/cli-integ/lib/with-cdk-app.ts +++ b/packages/@aws-cdk-testing/cli-integ/lib/with-cdk-app.ts @@ -319,6 +319,7 @@ export class TestFixture extends ShellHelper { public readonly qualifier: string; private readonly bucketsToDelete = new Array(); public readonly cli: ITestCliSource; + public readonly cdkAssets: ITestCliSource; public readonly library: ITestLibrarySource; constructor( @@ -331,6 +332,7 @@ export class TestFixture extends ShellHelper { this.qualifier = this.randomString.slice(0, 10); this.cli = testSource('cli'); + this.cdkAssets = testSource('cdkAssets'); this.library = testSource('library'); } diff --git a/packages/@aws-cdk-testing/cli-integ/package.json b/packages/@aws-cdk-testing/cli-integ/package.json index 04c341aae..40ae7f841 100644 --- a/packages/@aws-cdk-testing/cli-integ/package.json +++ b/packages/@aws-cdk-testing/cli-integ/package.json @@ -44,7 +44,6 @@ "@cdklabs/eslint-plugin": "^1.3.2", "@stylistic/eslint-plugin": "^3", "@types/fs-extra": "^9", - "@types/glob": "^7", "@types/jest": "^29.5.14", "@types/node": "^16", "@types/semver": "^7", @@ -65,29 +64,30 @@ "license-checker": "^25.0.1", "prettier": "^2.8", "ts-jest": "^29.2.5", - "typescript": "5.6" + "typescript": "5.8" }, "dependencies": { - "@aws-sdk/client-cloudformation": "3.839.0", - "@aws-sdk/client-codeartifact": "3.839.0", - "@aws-sdk/client-ecr": "3.839.0", - "@aws-sdk/client-ecr-public": "3.839.0", - "@aws-sdk/client-ecs": "3.839.0", - "@aws-sdk/client-iam": "3.839.0", - "@aws-sdk/client-lambda": "3.839.0", - "@aws-sdk/client-s3": "3.839.0", - "@aws-sdk/client-sns": "3.839.0", - "@aws-sdk/client-sso": "3.839.0", - "@aws-sdk/client-sts": "3.839.0", - "@aws-sdk/credential-providers": "3.839.0", - "@cdklabs/cdk-atmosphere-client": "^0.0.56", + "@aws-sdk/client-cloudformation": "^3.846.0", + "@aws-sdk/client-codeartifact": "^3.846.0", + "@aws-sdk/client-ecr": "^3.846.0", + "@aws-sdk/client-ecr-public": "^3.846.0", + "@aws-sdk/client-ecs": "^3.846.0", + "@aws-sdk/client-iam": "^3.846.0", + "@aws-sdk/client-lambda": "^3.846.0", + "@aws-sdk/client-s3": "^3.846.0", + "@aws-sdk/client-secrets-manager": "^3.846.0", + "@aws-sdk/client-sns": "^3.846.0", + "@aws-sdk/client-sso": "^3.846.0", + "@aws-sdk/client-sts": "^3.846.0", + "@aws-sdk/credential-providers": "^3.846.0", + "@cdklabs/cdk-atmosphere-client": "^0.0.58", "@octokit/rest": "^20", "@smithy/types": "^4.3.1", "@smithy/util-retry": "^4.0.6", "axios": "^1", "chalk": "^4", "fs-extra": "^9", - "glob": "^7", + "glob": "^9", "jest": "^29", "jest-junit": "^15", "make-runnable": "^1", @@ -95,6 +95,7 @@ "node-pty": "^1.0.0", "npm": "^10", "p-queue": "^6", + "proxy-agent": "^6.5.0", "semver": "^7", "sinon": "^9", "ts-jest": "^29", diff --git a/packages/@aws-cdk-testing/cli-integ/tests/cli-integ-tests/cdk-assets/asset_helpers.ts b/packages/@aws-cdk-testing/cli-integ/tests/cli-integ-tests/cdk-assets/asset_helpers.ts new file mode 100644 index 000000000..3197cdd33 --- /dev/null +++ b/packages/@aws-cdk-testing/cli-integ/tests/cli-integ-tests/cdk-assets/asset_helpers.ts @@ -0,0 +1,49 @@ +import { promises as fs } from 'fs'; +import * as path from 'path'; +import type { TestFixture } from '../../../lib/with-cdk-app'; + +export async function writeFileAsset(fixture: TestFixture) { + const account = await fixture.aws.account(); + const region = fixture.aws.region; + + const relativeAssetFile = 'testfile.txt'; + for (const toCreate of [relativeAssetFile]) { + await fs.writeFile(path.join(fixture.integTestDir, toCreate), 'some asset file'); + } + const bucketName = `cdk-hnb659fds-assets-${account}-${region}`; + const assumeRoleArn = `arn:\${AWS::Partition}:iam::${account}:role/cdk-hnb659fds-file-publishing-role-${account}-${region}`; + + return { + relativeAssetFile, + bucketName, + assumeRoleArn, + }; +} + +export async function writeDockerAsset(fixture: TestFixture) { + const relativeImageDir = 'imagedir'; + const absoluteImageDir = path.join(fixture.integTestDir, relativeImageDir); + await fs.mkdir(absoluteImageDir, { recursive: true }); + + for (const toCreate of [`${absoluteImageDir}/datafile.txt`]) { + await fs.writeFile(toCreate, 'some asset file'); + } + + await fs.writeFile(path.join(absoluteImageDir, 'Dockerfile'), [ + 'FROM scratch', + 'ADD datafile.txt datafile.txt', + ].join('\n')); + + const account = await fixture.aws.account(); + const region = fixture.aws.region; + const repositoryName = `cdk-hnb659fds-container-assets-${account}-${region}`; + const assumeRoleArn = `arn:\${AWS::Partition}:iam::${account}:role/cdk-hnb659fds-image-publishing-role-${account}-${region}`; + const repositoryDomain = `${account}.dkr.ecr.${region}.amazonaws.com`; + + return { + repositoryName, + assumeRoleArn, + relativeImageDir, + repositoryDomain, + }; +} diff --git a/packages/@aws-cdk-testing/cli-integ/tests/cli-integ-tests/cdk-assets/cdk-assets-can-read-lib-output.integtest.ts b/packages/@aws-cdk-testing/cli-integ/tests/cli-integ-tests/cdk-assets/cdk-assets-can-read-lib-output.integtest.ts new file mode 100644 index 000000000..b16cd4cdf --- /dev/null +++ b/packages/@aws-cdk-testing/cli-integ/tests/cli-integ-tests/cdk-assets/cdk-assets-can-read-lib-output.integtest.ts @@ -0,0 +1,14 @@ +import * as path from 'path'; +import { integTest } from '../../../lib/integ-test'; +import { withDefaultFixture } from '../../../lib/with-cdk-app'; + +integTest('cdk-assets can read lib output', withDefaultFixture(async (fixture) => { + await fixture.cdkSynth(); + + await fixture.cdkAssets.makeCliAvailable(); + + const assetManifestFile = path.join(fixture.integTestDir, 'cdk.out', `${fixture.fullStackName('test-1')}.assets.json`); + + // Should not fail + await fixture.shell(['cdk-assets', '--path', assetManifestFile, 'ls']); +})); diff --git a/packages/@aws-cdk-testing/cli-integ/tests/cli-integ-tests/cdk-assets/cdk-assets-docker-credential.integtest.ts b/packages/@aws-cdk-testing/cli-integ/tests/cli-integ-tests/cdk-assets/cdk-assets-docker-credential.integtest.ts index 8da62e728..d42238f7d 100644 --- a/packages/@aws-cdk-testing/cli-integ/tests/cli-integ-tests/cdk-assets/cdk-assets-docker-credential.integtest.ts +++ b/packages/@aws-cdk-testing/cli-integ/tests/cli-integ-tests/cdk-assets/cdk-assets-docker-credential.integtest.ts @@ -1,39 +1,100 @@ import * as fs from 'fs'; import * as path from 'path'; +// import { CreateSecretCommand, DeleteSecretCommand } from '@aws-sdk/client-secrets-manager'; import { GetCallerIdentityCommand } from '@aws-sdk/client-sts'; +// eslint-disable-next-line import/no-relative-packages +import type { DockerDomainCredentialSource } from '../../../../../@aws-cdk/cdk-assets-lib/lib/private/docker-credentials'; +import type { TestFixture } from '../../../lib'; import { integTest, withDefaultFixture } from '../../../lib'; jest.setTimeout(2 * 60 * 60_000); // Includes the time to acquire locks, worst-case single-threaded runtime integTest( - 'docker-credential-cdk-assets can be invoked as a program', + 'docker-credential-cdk-assets can assume role and fetch ECR credentials', withDefaultFixture(async (fixture) => { - await fixture.shell(['npm', 'init', '-y']); - await fixture.shell(['npm', 'install', 'cdk-assets@latest']); - - const caller = await fixture.aws.sts.send(new GetCallerIdentityCommand()); - const domain = 'integ.test.domain'; - const credsFilePath = path.join(fixture.integTestDir, 'cdk-docker-creds.json'); - - fs.writeFileSync(credsFilePath, JSON.stringify({ - version: '1.0', - domainCredentials: { - [domain]: { - ecrRepository: true, - roleArn: caller.Arn, - }, + const caller = await fixture.aws.sts.send(new GetCallerIdentityCommand({})); + + const roleArn = await fixture.aws.temporaryRole('ecr-repo-role', [ + { + Action: 'sts:AssumeRole', + Effect: 'Allow', + Principal: { AWS: caller.Account }, }, - })); + ], [ + { + Effect: 'Allow', + Resource: '*', + Action: ['ecr:GetAuthorizationToken'], + }, + ]); - const input = path.join(fixture.integTestDir, 'input.txt'); - fs.writeFileSync(input, `${domain}\n`); + await fixture.aws.waitForAssumeRole(roleArn); - await fixture.shell(['node', './node_modules/cdk-assets/bin/docker-credential-cdk-assets', 'get'], { - modEnv: { - ...fixture.cdkShellEnv(), - CDK_DOCKER_CREDS_FILE: credsFilePath, - }, - stdio: [fs.openSync(input, 'r')], + await testDockerCredential(fixture, { + ecrRepository: true, + // This role must have permissions to call `ecr:GetAuthorizationToken` + assumeRoleArn: roleArn, + }); + }), +); + +/* + +// SKIPPED FOR NOW +// Requires SecretsManager permissions on the role that's executing this, and that's +// too much to set up right now. + +integTest( + 'docker-credential-cdk-assets read from SecretsManager', + withDefaultFixture(async (fixture) => { + const secret = await fixture.aws.secretsManager.send(new CreateSecretCommand({ + Name: `our-secret-${fixture.randomString}`, + SecretString: JSON.stringify({ + username: 'test-user', + password: 'test-password', + }), + })); + fixture.aws.addCleanup(() => fixture.aws.secretsManager.send(new DeleteSecretCommand({ + SecretId: secret.ARN, + }))); + + await testDockerCredential(fixture, { + secretsManagerSecretId: secret.ARN, + secretsUsernameField: 'username', + secretsPasswordField: 'password', }); }), ); + +*/ + +async function testDockerCredential(fixture: TestFixture, credSource: DockerDomainCredentialSource) { + const domain = 'integ.test.domain'; + const credsFilePath = path.join(fixture.integTestDir, 'cdk-docker-creds.json'); + + fs.writeFileSync(credsFilePath, JSON.stringify({ + version: '1.0', + domainCredentials: { + [domain]: credSource, + }, + })); + + const input = path.join(fixture.integTestDir, 'input.txt'); + fs.writeFileSync(input, `${domain}\n`); + + await fixture.cdkAssets.makeCliAvailable(); + const output = await fixture.shell(['docker-credential-cdk-assets', 'get'], { + modEnv: { + ...fixture.cdkShellEnv(), + CDK_DOCKER_CREDS_FILE: credsFilePath, + }, + stdio: [fs.openSync(input, 'r')], + captureStderr: false, + }); + + const response = JSON.parse(output); + expect(response).toMatchObject({ + Username: expect.anything(), + Secret: expect.anything(), + }); +} diff --git a/packages/@aws-cdk-testing/cli-integ/tests/cli-integ-tests/cdk-assets/cdk-assets-uses-profile.integtest.ts b/packages/@aws-cdk-testing/cli-integ/tests/cli-integ-tests/cdk-assets/cdk-assets-uses-profile.integtest.ts index cc2edb97b..0d50424a6 100644 --- a/packages/@aws-cdk-testing/cli-integ/tests/cli-integ-tests/cdk-assets/cdk-assets-uses-profile.integtest.ts +++ b/packages/@aws-cdk-testing/cli-integ/tests/cli-integ-tests/cdk-assets/cdk-assets-uses-profile.integtest.ts @@ -8,8 +8,7 @@ jest.setTimeout(2 * 60 * 60_000); // Includes the time to acquire locks, worst-c integTest('cdk-assets uses profile when specified', withDefaultFixture(async (fixture) => { const currentCreds = await fixture.aws.credentials(); - await fixture.shell(['npm', 'init', '-y']); - await fixture.shell(['npm', 'install', 'cdk-assets@latest']); + await fixture.cdkAssets.makeCliAvailable(); const account = await fixture.aws.account(); const region = fixture.aws.region; @@ -73,7 +72,7 @@ aws_secret_access_key=${currentCreds.secretAccessKey} aws_session_token=${currentCreds.sessionToken}`); await fs.writeFile(path.join(fixture.integTestDir, 'assets.json'), JSON.stringify(assetsJson, undefined, 2)); - await fixture.shell(['npx', 'cdk-assets', '--path', 'assets.json', 'publish', '--profile', profile], { + await fixture.shell(['cdk-assets', '--path', 'assets.json', 'publish', '--profile', profile], { modEnv: { ...fixture.cdkShellEnv(), AWS_SHARED_CREDENTIALS_FILE: credentialsFile, diff --git a/packages/@aws-cdk-testing/cli-integ/tests/cli-integ-tests/cdk-assets/smoketest.integtest.ts b/packages/@aws-cdk-testing/cli-integ/tests/cli-integ-tests/cdk-assets/smoketest.integtest.ts index d2009acc0..be61f7b69 100644 --- a/packages/@aws-cdk-testing/cli-integ/tests/cli-integ-tests/cdk-assets/smoketest.integtest.ts +++ b/packages/@aws-cdk-testing/cli-integ/tests/cli-integ-tests/cdk-assets/smoketest.integtest.ts @@ -3,6 +3,7 @@ */ import { promises as fs } from 'fs'; import * as path from 'path'; +import { writeDockerAsset, writeFileAsset } from './asset_helpers'; import { integTest, withDefaultFixture } from '../../../lib'; jest.setTimeout(2 * 60 * 60_000); // Includes the time to acquire locks, worst-case single-threaded runtime @@ -13,25 +14,10 @@ integTest( await fixture.shell(['npm', 'init', '-y']); await fixture.shell(['npm', 'install', 'cdk-assets@latest']); - const account = await fixture.aws.account(); const region = fixture.aws.region; - const bucketName = `cdk-hnb659fds-assets-${account}-${region}`; - const repositoryName = `cdk-hnb659fds-container-assets-${account}-${region}`; - const imageDir = 'imagedir'; - await fs.mkdir(path.join(fixture.integTestDir, imageDir), { recursive: true }); - - // Write an asset file and a data file for the Docker image - const assetFile = 'testfile.txt'; - for (const toCreate of [assetFile, `${imageDir}/datafile.txt`]) { - await fs.writeFile(path.join(fixture.integTestDir, toCreate), 'some asset file'); - } - - // Write a Dockerfile for the image build with a data file in it - await fs.writeFile(path.join(fixture.integTestDir, imageDir, 'Dockerfile'), [ - 'FROM scratch', - 'ADD datafile.txt datafile.txt', - ].join('\n')); + const fileAsset = await writeFileAsset(fixture); + const imageAsset = await writeDockerAsset(fixture); // Write an asset JSON file to publish to the bootstrapped environment const assetsJson = { @@ -39,14 +25,14 @@ integTest( files: { testfile: { source: { - path: assetFile, + path: fileAsset.relativeAssetFile, packaging: 'file', }, destinations: { current: { region, - assumeRoleArn: `arn:\${AWS::Partition}:iam::${account}:role/cdk-hnb659fds-file-publishing-role-${account}-${region}`, - bucketName, + assumeRoleArn: fileAsset.assumeRoleArn, + bucketName: fileAsset.bucketName, objectKey: `test-file-${Date.now()}.json`, }, }, @@ -55,13 +41,13 @@ integTest( dockerImages: { testimage: { source: { - directory: imageDir, + directory: imageAsset.relativeImageDir, }, destinations: { current: { region, - assumeRoleArn: `arn:\${AWS::Partition}:iam::${account}:role/cdk-hnb659fds-image-publishing-role-${account}-${region}`, - repositoryName, + assumeRoleArn: imageAsset.assumeRoleArn, + repositoryName: imageAsset.repositoryName, imageTag: 'test-image', // Not fresh on every run because we'll run out of tags too easily }, }, @@ -73,9 +59,6 @@ integTest( await fixture.shell(['npx', 'cdk-assets', '--path', 'assets.json', '--verbose', 'publish'], { modEnv: { ...fixture.cdkShellEnv(), - // This is necessary for cdk-assets v2, if the credentials are supplied via - // config file (which they are on the CodeBuild canaries). - AWS_SDK_LOAD_CONFIG: '1', }, }); }), diff --git a/packages/@aws-cdk/cdk-assets-lib/.projen/deps.json b/packages/@aws-cdk/cdk-assets-lib/.projen/deps.json index 75eee7491..8905f5774 100644 --- a/packages/@aws-cdk/cdk-assets-lib/.projen/deps.json +++ b/packages/@aws-cdk/cdk-assets-lib/.projen/deps.json @@ -130,7 +130,7 @@ }, { "name": "typescript", - "version": "5.6", + "version": "5.8", "type": "build" }, { diff --git a/packages/@aws-cdk/cdk-assets-lib/.projen/tasks.json b/packages/@aws-cdk/cdk-assets-lib/.projen/tasks.json index c67285b96..f5eff63af 100644 --- a/packages/@aws-cdk/cdk-assets-lib/.projen/tasks.json +++ b/packages/@aws-cdk/cdk-assets-lib/.projen/tasks.json @@ -33,7 +33,7 @@ "VERSIONRCOPTIONS": "{\"path\":\".\"}", "BUMP_PACKAGE": "commit-and-tag-version@^12", "NEXT_VERSION_COMMAND": "tsx ../../../projenrc/next-version.ts neverMajor maybeRc", - "RELEASABLE_COMMITS": "git log --no-merges --oneline $LATEST_TAG..HEAD -E --grep \"^(feat|fix){1}(\\([^()[:space:]]+\\))?(!)?:[[:blank:]]+.+\" -- .", + "RELEASABLE_COMMITS": "git log --no-merges --oneline $LATEST_TAG..HEAD -E --grep \"^(feat|fix){1}(\\([^()[:space:]]+\\))?(!)?:[[:blank:]]+.+\" -- . ../cloud-assembly-schema", "MAJOR": "1" }, "steps": [ @@ -196,7 +196,7 @@ "VERSIONRCOPTIONS": "{\"path\":\".\"}", "BUMP_PACKAGE": "commit-and-tag-version@^12", "NEXT_VERSION_COMMAND": "tsx ../../../projenrc/next-version.ts neverMajor maybeRc", - "RELEASABLE_COMMITS": "git log --no-merges --oneline $LATEST_TAG..HEAD -E --grep \"^(feat|fix){1}(\\([^()[:space:]]+\\))?(!)?:[[:blank:]]+.+\" -- ." + "RELEASABLE_COMMITS": "git log --no-merges --oneline $LATEST_TAG..HEAD -E --grep \"^(feat|fix){1}(\\([^()[:space:]]+\\))?(!)?:[[:blank:]]+.+\" -- . ../cloud-assembly-schema" }, "steps": [ { diff --git a/packages/@aws-cdk/cdk-assets-lib/package.json b/packages/@aws-cdk/cdk-assets-lib/package.json index d3197950b..dbef8d687 100644 --- a/packages/@aws-cdk/cdk-assets-lib/package.json +++ b/packages/@aws-cdk/cdk-assets-lib/package.json @@ -49,18 +49,18 @@ "eslint-import-resolver-typescript": "^4.4.4", "eslint-plugin-import": "^2.32.0", "eslint-plugin-jest": "^28.14.0", - "eslint-plugin-jsdoc": "^51.2.3", + "eslint-plugin-jsdoc": "^51.4.0", "eslint-plugin-prettier": "^5.5.1", "fs-extra": "^11.3.0", "graceful-fs": "^4.2.11", - "jest": "^30.0.3", + "jest": "^30.0.4", "jest-junit": "^16", "jszip": "^3.10.1", "license-checker": "^25.0.1", "mock-fs": "^5", "prettier": "^2.8", "ts-jest": "^29.4.0", - "typescript": "5.6" + "typescript": "5.8" }, "dependencies": { "@aws-cdk/cloud-assembly-schema": "^0.0.0", diff --git a/packages/@aws-cdk/cdk-cli-wrapper/.projen/deps.json b/packages/@aws-cdk/cdk-cli-wrapper/.projen/deps.json index 2baca877c..9e9a5a864 100644 --- a/packages/@aws-cdk/cdk-cli-wrapper/.projen/deps.json +++ b/packages/@aws-cdk/cdk-cli-wrapper/.projen/deps.json @@ -82,7 +82,7 @@ }, { "name": "typescript", - "version": "5.6", + "version": "5.8", "type": "build" }, { diff --git a/packages/@aws-cdk/cdk-cli-wrapper/package.json b/packages/@aws-cdk/cdk-cli-wrapper/package.json index bbc9b4759..1e4c232fe 100644 --- a/packages/@aws-cdk/cdk-cli-wrapper/package.json +++ b/packages/@aws-cdk/cdk-cli-wrapper/package.json @@ -48,7 +48,7 @@ "jest-junit": "^16", "prettier": "^2.8", "ts-jest": "^29.4.0", - "typescript": "5.6" + "typescript": "5.8" }, "dependencies": { "@aws-cdk/cloud-assembly-schema": "^0.0.0" diff --git a/packages/@aws-cdk/cli-lib-alpha/.projen/deps.json b/packages/@aws-cdk/cli-lib-alpha/.projen/deps.json index fbdcec31d..b03440335 100644 --- a/packages/@aws-cdk/cli-lib-alpha/.projen/deps.json +++ b/packages/@aws-cdk/cli-lib-alpha/.projen/deps.json @@ -99,12 +99,12 @@ }, { "name": "jsii-rosetta", - "version": "5.6", + "version": "5.8", "type": "build" }, { "name": "jsii", - "version": "5.6", + "version": "5.8", "type": "build" }, { @@ -122,7 +122,7 @@ }, { "name": "typescript", - "version": "5.6", + "version": "5.8", "type": "build" } ], diff --git a/packages/@aws-cdk/cli-lib-alpha/THIRD_PARTY_LICENSES b/packages/@aws-cdk/cli-lib-alpha/THIRD_PARTY_LICENSES index cc5af0bd6..b63a4d55b 100644 --- a/packages/@aws-cdk/cli-lib-alpha/THIRD_PARTY_LICENSES +++ b/packages/@aws-cdk/cli-lib-alpha/THIRD_PARTY_LICENSES @@ -618,7 +618,7 @@ The @aws-cdk/cli-lib-alpha package includes the following third-party software/l ---------------- -** @aws-sdk/client-appsync@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-appsync/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-appsync@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-appsync/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -824,7 +824,7 @@ The @aws-cdk/cli-lib-alpha package includes the following third-party software/l ---------------- -** @aws-sdk/client-cloudcontrol@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-cloudcontrol/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-cloudcontrol@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-cloudcontrol/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -1030,7 +1030,7 @@ The @aws-cdk/cli-lib-alpha package includes the following third-party software/l ---------------- -** @aws-sdk/client-cloudformation@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-cloudformation/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-cloudformation@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-cloudformation/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -1236,7 +1236,7 @@ The @aws-cdk/cli-lib-alpha package includes the following third-party software/l ---------------- -** @aws-sdk/client-cloudwatch-logs@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-cloudwatch-logs/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-cloudwatch-logs@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-cloudwatch-logs/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -1442,7 +1442,7 @@ The @aws-cdk/cli-lib-alpha package includes the following third-party software/l ---------------- -** @aws-sdk/client-codebuild@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-codebuild/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-codebuild@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-codebuild/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -1648,7 +1648,7 @@ The @aws-cdk/cli-lib-alpha package includes the following third-party software/l ---------------- -** @aws-sdk/client-cognito-identity@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-cognito-identity/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-cognito-identity@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-cognito-identity/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -1854,7 +1854,7 @@ The @aws-cdk/cli-lib-alpha package includes the following third-party software/l ---------------- -** @aws-sdk/client-ec2@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-ec2/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-ec2@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-ec2/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -2060,7 +2060,7 @@ The @aws-cdk/cli-lib-alpha package includes the following third-party software/l ---------------- -** @aws-sdk/client-ecr@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-ecr/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-ecr@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-ecr/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -2266,7 +2266,7 @@ The @aws-cdk/cli-lib-alpha package includes the following third-party software/l ---------------- -** @aws-sdk/client-ecs@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-ecs/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-ecs@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-ecs/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -2472,7 +2472,7 @@ The @aws-cdk/cli-lib-alpha package includes the following third-party software/l ---------------- -** @aws-sdk/client-elastic-load-balancing-v2@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-elastic-load-balancing-v2/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-elastic-load-balancing-v2@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-elastic-load-balancing-v2/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -2678,7 +2678,7 @@ The @aws-cdk/cli-lib-alpha package includes the following third-party software/l ---------------- -** @aws-sdk/client-iam@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-iam/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-iam@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-iam/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -2884,7 +2884,7 @@ The @aws-cdk/cli-lib-alpha package includes the following third-party software/l ---------------- -** @aws-sdk/client-kms@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-kms/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-kms@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-kms/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -3090,7 +3090,7 @@ The @aws-cdk/cli-lib-alpha package includes the following third-party software/l ---------------- -** @aws-sdk/client-lambda@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-lambda/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-lambda@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-lambda/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -3296,7 +3296,7 @@ The @aws-cdk/cli-lib-alpha package includes the following third-party software/l ---------------- -** @aws-sdk/client-route-53@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-route-53/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-route-53@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-route-53/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -3502,7 +3502,7 @@ The @aws-cdk/cli-lib-alpha package includes the following third-party software/l ---------------- -** @aws-sdk/client-s3@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-s3/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-s3@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-s3/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -3708,7 +3708,7 @@ The @aws-cdk/cli-lib-alpha package includes the following third-party software/l ---------------- -** @aws-sdk/client-secrets-manager@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-secrets-manager/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-secrets-manager@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-secrets-manager/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -3914,7 +3914,7 @@ The @aws-cdk/cli-lib-alpha package includes the following third-party software/l ---------------- -** @aws-sdk/client-sfn@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-sfn/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-sfn@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-sfn/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -4120,7 +4120,7 @@ The @aws-cdk/cli-lib-alpha package includes the following third-party software/l ---------------- -** @aws-sdk/client-ssm@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-ssm/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-ssm@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-ssm/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -4326,7 +4326,7 @@ The @aws-cdk/cli-lib-alpha package includes the following third-party software/l ---------------- -** @aws-sdk/client-sso@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-sso/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-sso@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-sso/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -4532,7 +4532,7 @@ The @aws-cdk/cli-lib-alpha package includes the following third-party software/l ---------------- -** @aws-sdk/client-sts@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-sts/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-sts@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-sts/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -4738,11 +4738,11 @@ The @aws-cdk/cli-lib-alpha package includes the following third-party software/l ---------------- -** @aws-sdk/core@3.839.0 - https://www.npmjs.com/package/@aws-sdk/core/v/3.839.0 | Apache-2.0 +** @aws-sdk/core@3.846.0 - https://www.npmjs.com/package/@aws-sdk/core/v/3.846.0 | Apache-2.0 ---------------- -** @aws-sdk/credential-provider-cognito-identity@3.839.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-cognito-identity/v/3.839.0 | Apache-2.0 +** @aws-sdk/credential-provider-cognito-identity@3.846.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-cognito-identity/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -4948,7 +4948,7 @@ The @aws-cdk/cli-lib-alpha package includes the following third-party software/l ---------------- -** @aws-sdk/credential-provider-env@3.839.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-env/v/3.839.0 | Apache-2.0 +** @aws-sdk/credential-provider-env@3.846.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-env/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -5153,11 +5153,11 @@ Apache License ---------------- -** @aws-sdk/credential-provider-http@3.839.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-http/v/3.839.0 | Apache-2.0 +** @aws-sdk/credential-provider-http@3.846.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-http/v/3.846.0 | Apache-2.0 ---------------- -** @aws-sdk/credential-provider-ini@3.839.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-ini/v/3.839.0 | Apache-2.0 +** @aws-sdk/credential-provider-ini@3.846.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-ini/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -5362,7 +5362,7 @@ Apache License ---------------- -** @aws-sdk/credential-provider-node@3.839.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-node/v/3.839.0 | Apache-2.0 +** @aws-sdk/credential-provider-node@3.846.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-node/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -5567,7 +5567,7 @@ Apache License ---------------- -** @aws-sdk/credential-provider-process@3.839.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-process/v/3.839.0 | Apache-2.0 +** @aws-sdk/credential-provider-process@3.846.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-process/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -5772,7 +5772,7 @@ Apache License ---------------- -** @aws-sdk/credential-provider-sso@3.839.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-sso/v/3.839.0 | Apache-2.0 +** @aws-sdk/credential-provider-sso@3.846.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-sso/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -5977,7 +5977,7 @@ Apache License ---------------- -** @aws-sdk/credential-provider-web-identity@3.839.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-web-identity/v/3.839.0 | Apache-2.0 +** @aws-sdk/credential-provider-web-identity@3.846.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-web-identity/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -6182,7 +6182,7 @@ Apache License ---------------- -** @aws-sdk/credential-providers@3.839.0 - https://www.npmjs.com/package/@aws-sdk/credential-providers/v/3.839.0 | Apache-2.0 +** @aws-sdk/credential-providers@3.846.0 - https://www.npmjs.com/package/@aws-sdk/credential-providers/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -6387,7 +6387,7 @@ Apache License ---------------- -** @aws-sdk/ec2-metadata-service@3.839.0 - https://www.npmjs.com/package/@aws-sdk/ec2-metadata-service/v/3.839.0 | Apache-2.0 +** @aws-sdk/ec2-metadata-service@3.846.0 - https://www.npmjs.com/package/@aws-sdk/ec2-metadata-service/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -6592,7 +6592,7 @@ Apache License ---------------- -** @aws-sdk/lib-storage@3.839.0 - https://www.npmjs.com/package/@aws-sdk/lib-storage/v/3.839.0 | Apache-2.0 +** @aws-sdk/lib-storage@3.846.0 - https://www.npmjs.com/package/@aws-sdk/lib-storage/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -6797,7 +6797,7 @@ Apache License ---------------- -** @aws-sdk/middleware-bucket-endpoint@3.830.0 - https://www.npmjs.com/package/@aws-sdk/middleware-bucket-endpoint/v/3.830.0 | Apache-2.0 +** @aws-sdk/middleware-bucket-endpoint@3.840.0 - https://www.npmjs.com/package/@aws-sdk/middleware-bucket-endpoint/v/3.840.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -7003,7 +7003,7 @@ Apache License ---------------- -** @aws-sdk/middleware-expect-continue@3.821.0 - https://www.npmjs.com/package/@aws-sdk/middleware-expect-continue/v/3.821.0 | Apache-2.0 +** @aws-sdk/middleware-expect-continue@3.840.0 - https://www.npmjs.com/package/@aws-sdk/middleware-expect-continue/v/3.840.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -7209,7 +7209,7 @@ Apache License ---------------- -** @aws-sdk/middleware-flexible-checksums@3.839.0 - https://www.npmjs.com/package/@aws-sdk/middleware-flexible-checksums/v/3.839.0 | Apache-2.0 +** @aws-sdk/middleware-flexible-checksums@3.846.0 - https://www.npmjs.com/package/@aws-sdk/middleware-flexible-checksums/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -7415,7 +7415,7 @@ Apache License ---------------- -** @aws-sdk/middleware-host-header@3.821.0 - https://www.npmjs.com/package/@aws-sdk/middleware-host-header/v/3.821.0 | Apache-2.0 +** @aws-sdk/middleware-host-header@3.840.0 - https://www.npmjs.com/package/@aws-sdk/middleware-host-header/v/3.840.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -7621,7 +7621,7 @@ Apache License ---------------- -** @aws-sdk/middleware-location-constraint@3.821.0 - https://www.npmjs.com/package/@aws-sdk/middleware-location-constraint/v/3.821.0 | Apache-2.0 +** @aws-sdk/middleware-location-constraint@3.840.0 - https://www.npmjs.com/package/@aws-sdk/middleware-location-constraint/v/3.840.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -7827,7 +7827,7 @@ Apache License ---------------- -** @aws-sdk/middleware-logger@3.821.0 - https://www.npmjs.com/package/@aws-sdk/middleware-logger/v/3.821.0 | Apache-2.0 +** @aws-sdk/middleware-logger@3.840.0 - https://www.npmjs.com/package/@aws-sdk/middleware-logger/v/3.840.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -8032,7 +8032,7 @@ Apache License ---------------- -** @aws-sdk/middleware-recursion-detection@3.821.0 - https://www.npmjs.com/package/@aws-sdk/middleware-recursion-detection/v/3.821.0 | Apache-2.0 +** @aws-sdk/middleware-recursion-detection@3.840.0 - https://www.npmjs.com/package/@aws-sdk/middleware-recursion-detection/v/3.840.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -8238,7 +8238,7 @@ Apache License ---------------- -** @aws-sdk/middleware-sdk-ec2@3.839.0 - https://www.npmjs.com/package/@aws-sdk/middleware-sdk-ec2/v/3.839.0 | Apache-2.0 +** @aws-sdk/middleware-sdk-ec2@3.845.0 - https://www.npmjs.com/package/@aws-sdk/middleware-sdk-ec2/v/3.845.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -8443,7 +8443,7 @@ Apache License ---------------- -** @aws-sdk/middleware-sdk-route53@3.821.0 - https://www.npmjs.com/package/@aws-sdk/middleware-sdk-route53/v/3.821.0 | Apache-2.0 +** @aws-sdk/middleware-sdk-route53@3.840.0 - https://www.npmjs.com/package/@aws-sdk/middleware-sdk-route53/v/3.840.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -8649,7 +8649,7 @@ Apache License ---------------- -** @aws-sdk/middleware-sdk-s3@3.839.0 - https://www.npmjs.com/package/@aws-sdk/middleware-sdk-s3/v/3.839.0 | Apache-2.0 +** @aws-sdk/middleware-sdk-s3@3.846.0 - https://www.npmjs.com/package/@aws-sdk/middleware-sdk-s3/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -8855,7 +8855,7 @@ Apache License ---------------- -** @aws-sdk/middleware-ssec@3.821.0 - https://www.npmjs.com/package/@aws-sdk/middleware-ssec/v/3.821.0 | Apache-2.0 +** @aws-sdk/middleware-ssec@3.840.0 - https://www.npmjs.com/package/@aws-sdk/middleware-ssec/v/3.840.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -9061,7 +9061,7 @@ Apache License ---------------- -** @aws-sdk/middleware-user-agent@3.839.0 - https://www.npmjs.com/package/@aws-sdk/middleware-user-agent/v/3.839.0 | Apache-2.0 +** @aws-sdk/middleware-user-agent@3.846.0 - https://www.npmjs.com/package/@aws-sdk/middleware-user-agent/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -9267,11 +9267,11 @@ Apache License ---------------- -** @aws-sdk/nested-clients@3.839.0 - https://www.npmjs.com/package/@aws-sdk/nested-clients/v/3.839.0 | Apache-2.0 +** @aws-sdk/nested-clients@3.846.0 - https://www.npmjs.com/package/@aws-sdk/nested-clients/v/3.846.0 | Apache-2.0 ---------------- -** @aws-sdk/region-config-resolver@3.821.0 - https://www.npmjs.com/package/@aws-sdk/region-config-resolver/v/3.821.0 | Apache-2.0 +** @aws-sdk/region-config-resolver@3.840.0 - https://www.npmjs.com/package/@aws-sdk/region-config-resolver/v/3.840.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -9476,7 +9476,7 @@ Apache License ---------------- -** @aws-sdk/signature-v4-multi-region@3.839.0 - https://www.npmjs.com/package/@aws-sdk/signature-v4-multi-region/v/3.839.0 | Apache-2.0 +** @aws-sdk/signature-v4-multi-region@3.846.0 - https://www.npmjs.com/package/@aws-sdk/signature-v4-multi-region/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -9682,7 +9682,7 @@ Apache License ---------------- -** @aws-sdk/token-providers@3.839.0 - https://www.npmjs.com/package/@aws-sdk/token-providers/v/3.839.0 | Apache-2.0 +** @aws-sdk/token-providers@3.846.0 - https://www.npmjs.com/package/@aws-sdk/token-providers/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -10092,7 +10092,7 @@ Apache License ---------------- -** @aws-sdk/util-endpoints@3.828.0 - https://www.npmjs.com/package/@aws-sdk/util-endpoints/v/3.828.0 | Apache-2.0 +** @aws-sdk/util-endpoints@3.845.0 - https://www.npmjs.com/package/@aws-sdk/util-endpoints/v/3.845.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -10297,7 +10297,7 @@ Apache License ---------------- -** @aws-sdk/util-format-url@3.821.0 - https://www.npmjs.com/package/@aws-sdk/util-format-url/v/3.821.0 | Apache-2.0 +** @aws-sdk/util-format-url@3.840.0 - https://www.npmjs.com/package/@aws-sdk/util-format-url/v/3.840.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -10502,7 +10502,7 @@ Apache License ---------------- -** @aws-sdk/util-user-agent-node@3.839.0 - https://www.npmjs.com/package/@aws-sdk/util-user-agent-node/v/3.839.0 | Apache-2.0 +** @aws-sdk/util-user-agent-node@3.846.0 - https://www.npmjs.com/package/@aws-sdk/util-user-agent-node/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -11530,7 +11530,7 @@ Apache License ---------------- -** @smithy/core@3.6.0 - https://www.npmjs.com/package/@smithy/core/v/3.6.0 | Apache-2.0 +** @smithy/core@3.7.0 - https://www.npmjs.com/package/@smithy/core/v/3.7.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -12765,7 +12765,7 @@ Apache License ---------------- -** @smithy/fetch-http-handler@5.0.4 - https://www.npmjs.com/package/@smithy/fetch-http-handler/v/5.0.4 | Apache-2.0 +** @smithy/fetch-http-handler@5.1.0 - https://www.npmjs.com/package/@smithy/fetch-http-handler/v/5.1.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -13995,7 +13995,7 @@ Apache License ---------------- -** @smithy/middleware-endpoint@4.1.13 - https://www.npmjs.com/package/@smithy/middleware-endpoint/v/4.1.13 | Apache-2.0 +** @smithy/middleware-endpoint@4.1.15 - https://www.npmjs.com/package/@smithy/middleware-endpoint/v/4.1.15 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -14200,7 +14200,7 @@ Apache License ---------------- -** @smithy/middleware-retry@4.1.14 - https://www.npmjs.com/package/@smithy/middleware-retry/v/4.1.14 | Apache-2.0 +** @smithy/middleware-retry@4.1.16 - https://www.npmjs.com/package/@smithy/middleware-retry/v/4.1.16 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -15022,7 +15022,7 @@ Apache License ---------------- -** @smithy/node-http-handler@4.0.6 - https://www.npmjs.com/package/@smithy/node-http-handler/v/4.0.6 | Apache-2.0 +** @smithy/node-http-handler@4.1.0 - https://www.npmjs.com/package/@smithy/node-http-handler/v/4.1.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -16666,7 +16666,7 @@ Apache License ---------------- -** @smithy/smithy-client@4.4.5 - https://www.npmjs.com/package/@smithy/smithy-client/v/4.4.5 | Apache-2.0 +** @smithy/smithy-client@4.4.7 - https://www.npmjs.com/package/@smithy/smithy-client/v/4.4.7 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -18514,7 +18514,7 @@ Apache License ---------------- -** @smithy/util-defaults-mode-node@4.0.21 - https://www.npmjs.com/package/@smithy/util-defaults-mode-node/v/4.0.21 | Apache-2.0 +** @smithy/util-defaults-mode-node@4.0.23 - https://www.npmjs.com/package/@smithy/util-defaults-mode-node/v/4.0.23 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -19540,7 +19540,7 @@ Apache License ---------------- -** @smithy/util-stream@4.2.2 - https://www.npmjs.com/package/@smithy/util-stream/v/4.2.2 | Apache-2.0 +** @smithy/util-stream@4.2.3 - https://www.npmjs.com/package/@smithy/util-stream/v/4.2.3 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -20617,7 +20617,7 @@ SOFTWARE. ---------------- -** agent-base@7.1.3 - https://www.npmjs.com/package/agent-base/v/7.1.3 | MIT +** agent-base@7.1.4 - https://www.npmjs.com/package/agent-base/v/7.1.4 | MIT (The MIT License) Copyright (c) 2013 Nathan Rajlich @@ -21196,7 +21196,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI ---------------- -** cdk-from-cfn@0.226.0 - https://www.npmjs.com/package/cdk-from-cfn/v/0.226.0 | MIT OR Apache-2.0 +** cdk-from-cfn@0.230.0 - https://www.npmjs.com/package/cdk-from-cfn/v/0.230.0 | MIT OR Apache-2.0 ---------------- @@ -21912,7 +21912,7 @@ THE SOFTWARE. ---------------- -** fast-xml-parser@4.4.1 - https://www.npmjs.com/package/fast-xml-parser/v/4.4.1 | MIT +** fast-xml-parser@5.2.5 - https://www.npmjs.com/package/fast-xml-parser/v/5.2.5 | MIT MIT License Copyright (c) 2017 Amit Kumar Gupta @@ -22002,7 +22002,7 @@ OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHE ---------------- -** get-uri@6.0.4 - https://www.npmjs.com/package/get-uri/v/6.0.4 | MIT +** get-uri@6.0.5 - https://www.npmjs.com/package/get-uri/v/6.0.5 | MIT (The MIT License) Copyright (c) 2014 Nathan Rajlich @@ -23476,7 +23476,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ---------------- -** socks@2.8.5 - https://www.npmjs.com/package/socks/v/2.8.5 | MIT +** socks@2.8.6 - https://www.npmjs.com/package/socks/v/2.8.6 | MIT The MIT License (MIT) Copyright (c) 2013 Josh Glazebrook @@ -23741,7 +23741,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI ---------------- -** strnum@1.1.2 - https://www.npmjs.com/package/strnum/v/1.1.2 | MIT +** strnum@2.1.1 - https://www.npmjs.com/package/strnum/v/2.1.1 | MIT MIT License Copyright (c) 2021 Natural Intelligence diff --git a/packages/@aws-cdk/cli-lib-alpha/lib/aws-cdk.ts b/packages/@aws-cdk/cli-lib-alpha/lib/aws-cdk.ts index 50c89f2ae..bca850d8e 100644 --- a/packages/@aws-cdk/cli-lib-alpha/lib/aws-cdk.ts +++ b/packages/@aws-cdk/cli-lib-alpha/lib/aws-cdk.ts @@ -3,5 +3,5 @@ export { contextFromSettings, prepareDefaultEnvironment } from '../../../aws-cdk/lib/api/cloud-assembly'; export { createAssembly } from '../../../aws-cdk/lib/cxapp/exec'; export { exec } from '../../../aws-cdk'; -export { debug } from '../../../aws-cdk/lib/logging'; +export { debug } from '../../../aws-cdk/lib/legacy'; export { synthParametersFromSettings, writeContextToEnv } from '../../../aws-cdk/lib/api/cloud-assembly'; diff --git a/packages/@aws-cdk/cli-lib-alpha/package.json b/packages/@aws-cdk/cli-lib-alpha/package.json index 4ada45988..68c5c7b57 100644 --- a/packages/@aws-cdk/cli-lib-alpha/package.json +++ b/packages/@aws-cdk/cli-lib-alpha/package.json @@ -47,7 +47,7 @@ "@typescript-eslint/eslint-plugin": "^8", "@typescript-eslint/parser": "^8", "aws-cdk": "^0.0.0", - "aws-cdk-lib": "^2.202.0", + "aws-cdk-lib": "2.205.0", "commit-and-tag-version": "^12", "constructs": "^10.0.0", "eslint": "^9", @@ -59,15 +59,15 @@ "eslint-plugin-prettier": "^5.5.1", "jest": "^29.7.0", "jest-junit": "^16", - "jsii": "5.6", + "jsii": "5.8", "jsii-diff": "^1.112.0", "jsii-docgen": "^10.5.0", "jsii-pacmak": "^1.112.0", - "jsii-rosetta": "5.6", + "jsii-rosetta": "5.8", "license-checker": "^25.0.1", "prettier": "^2.8", "ts-jest": "^29.4.0", - "typescript": "5.6" + "typescript": "5.8" }, "keywords": [ "aws", diff --git a/packages/@aws-cdk/cli-plugin-contract/.projen/deps.json b/packages/@aws-cdk/cli-plugin-contract/.projen/deps.json index f8c70454e..85e94aed4 100644 --- a/packages/@aws-cdk/cli-plugin-contract/.projen/deps.json +++ b/packages/@aws-cdk/cli-plugin-contract/.projen/deps.json @@ -91,7 +91,7 @@ }, { "name": "typescript", - "version": "5.6", + "version": "5.8", "type": "build" } ], diff --git a/packages/@aws-cdk/cli-plugin-contract/package.json b/packages/@aws-cdk/cli-plugin-contract/package.json index fa0fe7381..eeff40401 100644 --- a/packages/@aws-cdk/cli-plugin-contract/package.json +++ b/packages/@aws-cdk/cli-plugin-contract/package.json @@ -51,7 +51,7 @@ "license-checker": "^25.0.1", "prettier": "^2.8", "ts-jest": "^29.4.0", - "typescript": "5.6" + "typescript": "5.8" }, "keywords": [ "aws", diff --git a/packages/@aws-cdk/cloud-assembly-schema/.projen/deps.json b/packages/@aws-cdk/cloud-assembly-schema/.projen/deps.json index 7fb4138f0..7f1bfe872 100644 --- a/packages/@aws-cdk/cloud-assembly-schema/.projen/deps.json +++ b/packages/@aws-cdk/cloud-assembly-schema/.projen/deps.json @@ -90,12 +90,12 @@ }, { "name": "jsii-rosetta", - "version": "5.6", + "version": "5.8", "type": "build" }, { "name": "jsii", - "version": "5.6", + "version": "5.8", "type": "build" }, { @@ -125,7 +125,7 @@ }, { "name": "typescript", - "version": "5.6", + "version": "5.8", "type": "build" }, { diff --git a/packages/@aws-cdk/cloud-assembly-schema/lib/integ-tests/schema.ts b/packages/@aws-cdk/cloud-assembly-schema/lib/integ-tests/schema.ts index 03ef588c0..5752a2d71 100644 --- a/packages/@aws-cdk/cloud-assembly-schema/lib/integ-tests/schema.ts +++ b/packages/@aws-cdk/cloud-assembly-schema/lib/integ-tests/schema.ts @@ -11,7 +11,7 @@ export interface IntegManifest { /** * Enable lookups for this test. If lookups are enabled * then `stackUpdateWorkflow` must be set to false. - * Lookups should only be enabled when you are explicitely testing + * Lookups should only be enabled when you are explicitly testing * lookups. * * @default false diff --git a/packages/@aws-cdk/cloud-assembly-schema/package.json b/packages/@aws-cdk/cloud-assembly-schema/package.json index 868e251c8..447c697dc 100644 --- a/packages/@aws-cdk/cloud-assembly-schema/package.json +++ b/packages/@aws-cdk/cloud-assembly-schema/package.json @@ -57,16 +57,16 @@ "eslint-plugin-prettier": "^5.5.1", "jest": "^29.7.0", "jest-junit": "^16", - "jsii": "5.6", + "jsii": "5.8", "jsii-diff": "^1.112.0", "jsii-pacmak": "^1.112.0", - "jsii-rosetta": "5.6", + "jsii-rosetta": "5.8", "license-checker": "^25.0.1", "mock-fs": "^5.5.0", "prettier": "^2.8", "ts-jest": "^29.4.0", "tsx": "^4.20.3", - "typescript": "5.6", + "typescript": "5.8", "typescript-json-schema": "^0.65.1" }, "dependencies": { diff --git a/packages/@aws-cdk/cloud-assembly-schema/projenrc/versioning.ts b/packages/@aws-cdk/cloud-assembly-schema/projenrc/versioning.ts index d39d50d1d..16a4a3d84 100644 --- a/packages/@aws-cdk/cloud-assembly-schema/projenrc/versioning.ts +++ b/packages/@aws-cdk/cloud-assembly-schema/projenrc/versioning.ts @@ -4,6 +4,7 @@ import * as path from 'path'; import { SCHEMA_DIR } from './schema-definition'; export function maybeBumpVersion(schemas: Record) { + const $comment = "Do not hold back the version on additions: jsonschema validation of the manifest by the consumer will trigger errors on unexpected fields."; const serializedSchema = JSON.stringify(sortJson(schemas), null, 2); const versionFile = path.join(SCHEMA_DIR, 'version.json'); @@ -11,7 +12,7 @@ export function maybeBumpVersion(schemas: Record) { const schemaHash = sha256(serializedSchema); if (current.schemaHash !== schemaHash) { - current = { schemaHash, revision: current.revision + 1 }; + current = { schemaHash, $comment, revision: current.revision + 1 }; console.log(`Schemas changed, bumping version to ${current.revision}`); } @@ -26,6 +27,7 @@ function sha256(x: string) { interface SchemaVersionFile { revision: number; + $comment?: string; schemaHash: string; } diff --git a/packages/@aws-cdk/cloud-assembly-schema/schema/integ.schema.json b/packages/@aws-cdk/cloud-assembly-schema/schema/integ.schema.json index 5bd06f916..afc1326b6 100644 --- a/packages/@aws-cdk/cloud-assembly-schema/schema/integ.schema.json +++ b/packages/@aws-cdk/cloud-assembly-schema/schema/integ.schema.json @@ -10,7 +10,7 @@ "type": "string" }, "enableLookups": { - "description": "Enable lookups for this test. If lookups are enabled\nthen `stackUpdateWorkflow` must be set to false.\nLookups should only be enabled when you are explicitely testing\nlookups.", + "description": "Enable lookups for this test. If lookups are enabled\nthen `stackUpdateWorkflow` must be set to false.\nLookups should only be enabled when you are explicitly testing\nlookups.", "default": false, "type": "boolean" }, diff --git a/packages/@aws-cdk/cloud-assembly-schema/schema/version.json b/packages/@aws-cdk/cloud-assembly-schema/schema/version.json index 3da7936c4..4fea20043 100644 --- a/packages/@aws-cdk/cloud-assembly-schema/schema/version.json +++ b/packages/@aws-cdk/cloud-assembly-schema/schema/version.json @@ -1,4 +1,5 @@ { - "schemaHash": "4709e40bc5dd6ad7d2bb6c6bd0315c622b7f4aa07ee3af66ff07f9bc77fdf783", - "revision": 45 + "schemaHash": "0807b42f8220bdafddeb4dad246a696721ed86e99ac6b13aa83359bab834d60d", + "$comment": "Do not hold back the version on additions: jsonschema validation of the manifest by the consumer will trigger errors on unexpected fields.", + "revision": 48 } \ No newline at end of file diff --git a/packages/@aws-cdk/cloudformation-diff/.projen/deps.json b/packages/@aws-cdk/cloudformation-diff/.projen/deps.json index 6371e74d4..b5386fcd5 100644 --- a/packages/@aws-cdk/cloudformation-diff/.projen/deps.json +++ b/packages/@aws-cdk/cloudformation-diff/.projen/deps.json @@ -95,7 +95,7 @@ }, { "name": "typescript", - "version": "5.6", + "version": "5.8", "type": "build" }, { diff --git a/packages/@aws-cdk/cloudformation-diff/lib/diff/types.ts b/packages/@aws-cdk/cloudformation-diff/lib/diff/types.ts index 52df47ff9..baa9dc062 100644 --- a/packages/@aws-cdk/cloudformation-diff/lib/diff/types.ts +++ b/packages/@aws-cdk/cloudformation-diff/lib/diff/types.ts @@ -547,6 +547,12 @@ export interface Resource { [key: string]: any; } +export interface Move { + readonly direction: 'from' | 'to'; + readonly stackName: string; + readonly resourceLogicalId: string; +} + /** * Change to a single resource between two CloudFormation templates * @@ -568,6 +574,8 @@ export class ResourceDifference implements IDifference { */ public isImport?: boolean; + public move?: Move; + /** Property-level changes on the resource */ private readonly propertyDiffs: { [key: string]: PropertyDifference }; diff --git a/packages/@aws-cdk/cloudformation-diff/lib/format.ts b/packages/@aws-cdk/cloudformation-diff/lib/format.ts index dd76f92ca..4686debee 100644 --- a/packages/@aws-cdk/cloudformation-diff/lib/format.ts +++ b/packages/@aws-cdk/cloudformation-diff/lib/format.ts @@ -1,6 +1,6 @@ import { format } from 'util'; import * as chalk from 'chalk'; -import type { DifferenceCollection, TemplateDiff } from './diff/types'; +import type { DifferenceCollection, Move, TemplateDiff } from './diff/types'; import { deepEqual } from './diff/util'; import type { Difference, ResourceDifference } from './diff-template'; import { isPropertyDifference, ResourceImpact } from './diff-template'; @@ -166,8 +166,15 @@ export class Formatter { const resourceType = diff.isRemoval ? diff.oldResourceType : diff.newResourceType; - // eslint-disable-next-line @stylistic/max-len - this.print(`${this.formatResourcePrefix(diff)} ${this.formatValue(resourceType, chalk.cyan)} ${this.formatLogicalId(logicalId)} ${this.formatImpact(diff.changeImpact)}`.trimEnd()); + const message = [ + this.formatResourcePrefix(diff), + this.formatValue(resourceType, chalk.cyan), + this.formatLogicalId(logicalId), + this.formatImpact(diff.changeImpact), + this.formatMove(diff.move), + ].filter(Boolean).join(' '); + + this.print(message); if (diff.isUpdate) { const differenceCount = diff.differenceCount; @@ -239,6 +246,10 @@ export class Formatter { } } + private formatMove(move?: Move): string { + return !move ? '' : chalk.yellow('(OR', chalk.italic(chalk.bold('move')), `${move.direction} ${move.stackName}.${move.resourceLogicalId} via refactoring)`); + } + /** * Renders a tree of differences under a particular name. * @param name - the name of the root of the tree. diff --git a/packages/@aws-cdk/cloudformation-diff/lib/mappings.ts b/packages/@aws-cdk/cloudformation-diff/lib/mappings.ts index feda7f371..498590fc3 100644 --- a/packages/@aws-cdk/cloudformation-diff/lib/mappings.ts +++ b/packages/@aws-cdk/cloudformation-diff/lib/mappings.ts @@ -8,41 +8,33 @@ export interface TypedMapping { readonly destinationPath: string; } -export function formatMappingsHeader(stream: NodeJS.WritableStream) { +export function formatEnvironmentSectionHeader(stream: NodeJS.WritableStream, env: string) { const formatter = new Formatter(stream, {}); - formatter.printSectionHeader('The following resources were moved or renamed:\n'); + formatter.printSectionHeader(`${env}\n`); } -export function formatTypedMappings(stream: NodeJS.WritableStream, mappings: TypedMapping[], env: string) { - const header = [['Resource Type', 'Old Construct Path', 'New Construct Path']]; - const rows = mappings.map((m) => [m.type, m.sourcePath, m.destinationPath]); - - const formatter = new Formatter(stream, {}); - formatter.print(`${env}:`); +export function formatTypedMappings(stream: NodeJS.WritableStream, mappings: TypedMapping[]) { if (mappings.length > 0) { + const header = [['Resource Type', 'Old Construct Path', 'New Construct Path']]; + const rows = mappings.map((m) => [m.type, m.sourcePath, m.destinationPath]); + const formatter = new Formatter(stream, {}); + + formatter.print('The following resources were moved or renamed:'); formatter.print(chalk.green(formatTable(header.concat(rows), undefined))); - } else { - formatter.print('Nothing to refactor.'); + formatter.print(' '); } - formatter.print(' '); -} - -export function formatAmbiguitySectionHeader(stream: NodeJS.WritableStream) { - const formatter = new Formatter(stream, {}); - formatter.printSectionHeader('Ambiguous Resource Name Changes:\n'); } export function formatAmbiguousMappings( stream: NodeJS.WritableStream, pairs: [string[], string[]][], - env: string, ) { const tables = pairs.map(renderTable); const formatter = new Formatter(stream, {}); - formatter.print(`${env}:`); + formatter.print('Detected ambiguities:'); formatter.print(tables.join('\n\n')); - formatter.printSectionFooter(); + formatter.print(' '); function renderTable([removed, added]: [string[], string[]]) { return formatTable([['', 'Resource'], renderRemoval(removed), renderAddition(added)], undefined); diff --git a/packages/@aws-cdk/cloudformation-diff/package.json b/packages/@aws-cdk/cloudformation-diff/package.json index e35d0fbcf..5a6e05a34 100644 --- a/packages/@aws-cdk/cloudformation-diff/package.json +++ b/packages/@aws-cdk/cloudformation-diff/package.json @@ -53,14 +53,14 @@ "license-checker": "^25.0.1", "prettier": "^2.8", "ts-jest": "^29.4.0", - "typescript": "5.6" + "typescript": "5.8" }, "peerDependencies": { "@aws-sdk/client-cloudformation": "^3" }, "dependencies": { - "@aws-cdk/aws-service-spec": "^0.1.84", - "@aws-cdk/service-spec-types": "^0.0.150", + "@aws-cdk/aws-service-spec": "^0.1.86", + "@aws-cdk/service-spec-types": "^0.0.152", "chalk": "^4", "diff": "^7.0.0", "fast-deep-equal": "^3.1.3", diff --git a/packages/@aws-cdk/integ-runner/.projen/deps.json b/packages/@aws-cdk/integ-runner/.projen/deps.json index 129eea2c4..db56528a4 100644 --- a/packages/@aws-cdk/integ-runner/.projen/deps.json +++ b/packages/@aws-cdk/integ-runner/.projen/deps.json @@ -127,7 +127,7 @@ }, { "name": "typescript", - "version": "5.6", + "version": "5.8", "type": "build" }, { diff --git a/packages/@aws-cdk/integ-runner/THIRD_PARTY_LICENSES b/packages/@aws-cdk/integ-runner/THIRD_PARTY_LICENSES index a6b61cd29..0da0a3327 100644 --- a/packages/@aws-cdk/integ-runner/THIRD_PARTY_LICENSES +++ b/packages/@aws-cdk/integ-runner/THIRD_PARTY_LICENSES @@ -618,7 +618,7 @@ The @aws-cdk/integ-runner package includes the following third-party software/li ---------------- -** @aws-sdk/client-appsync@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-appsync/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-appsync@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-appsync/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -824,7 +824,7 @@ The @aws-cdk/integ-runner package includes the following third-party software/li ---------------- -** @aws-sdk/client-cloudcontrol@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-cloudcontrol/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-cloudcontrol@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-cloudcontrol/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -1030,7 +1030,7 @@ The @aws-cdk/integ-runner package includes the following third-party software/li ---------------- -** @aws-sdk/client-cloudformation@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-cloudformation/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-cloudformation@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-cloudformation/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -1236,7 +1236,7 @@ The @aws-cdk/integ-runner package includes the following third-party software/li ---------------- -** @aws-sdk/client-cloudwatch-logs@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-cloudwatch-logs/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-cloudwatch-logs@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-cloudwatch-logs/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -1442,7 +1442,7 @@ The @aws-cdk/integ-runner package includes the following third-party software/li ---------------- -** @aws-sdk/client-codebuild@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-codebuild/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-codebuild@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-codebuild/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -1648,7 +1648,7 @@ The @aws-cdk/integ-runner package includes the following third-party software/li ---------------- -** @aws-sdk/client-cognito-identity@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-cognito-identity/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-cognito-identity@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-cognito-identity/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -1854,7 +1854,7 @@ The @aws-cdk/integ-runner package includes the following third-party software/li ---------------- -** @aws-sdk/client-ec2@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-ec2/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-ec2@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-ec2/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -2060,7 +2060,7 @@ The @aws-cdk/integ-runner package includes the following third-party software/li ---------------- -** @aws-sdk/client-ecr@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-ecr/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-ecr@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-ecr/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -2266,7 +2266,7 @@ The @aws-cdk/integ-runner package includes the following third-party software/li ---------------- -** @aws-sdk/client-ecs@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-ecs/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-ecs@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-ecs/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -2472,7 +2472,7 @@ The @aws-cdk/integ-runner package includes the following third-party software/li ---------------- -** @aws-sdk/client-elastic-load-balancing-v2@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-elastic-load-balancing-v2/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-elastic-load-balancing-v2@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-elastic-load-balancing-v2/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -2678,7 +2678,7 @@ The @aws-cdk/integ-runner package includes the following third-party software/li ---------------- -** @aws-sdk/client-iam@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-iam/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-iam@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-iam/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -2884,7 +2884,7 @@ The @aws-cdk/integ-runner package includes the following third-party software/li ---------------- -** @aws-sdk/client-kms@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-kms/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-kms@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-kms/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -3090,7 +3090,7 @@ The @aws-cdk/integ-runner package includes the following third-party software/li ---------------- -** @aws-sdk/client-lambda@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-lambda/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-lambda@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-lambda/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -3296,7 +3296,7 @@ The @aws-cdk/integ-runner package includes the following third-party software/li ---------------- -** @aws-sdk/client-route-53@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-route-53/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-route-53@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-route-53/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -3502,7 +3502,7 @@ The @aws-cdk/integ-runner package includes the following third-party software/li ---------------- -** @aws-sdk/client-s3@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-s3/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-s3@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-s3/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -3708,7 +3708,7 @@ The @aws-cdk/integ-runner package includes the following third-party software/li ---------------- -** @aws-sdk/client-secrets-manager@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-secrets-manager/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-secrets-manager@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-secrets-manager/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -3914,7 +3914,7 @@ The @aws-cdk/integ-runner package includes the following third-party software/li ---------------- -** @aws-sdk/client-sfn@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-sfn/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-sfn@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-sfn/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -4120,7 +4120,7 @@ The @aws-cdk/integ-runner package includes the following third-party software/li ---------------- -** @aws-sdk/client-ssm@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-ssm/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-ssm@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-ssm/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -4326,7 +4326,7 @@ The @aws-cdk/integ-runner package includes the following third-party software/li ---------------- -** @aws-sdk/client-sso@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-sso/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-sso@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-sso/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -4532,7 +4532,7 @@ The @aws-cdk/integ-runner package includes the following third-party software/li ---------------- -** @aws-sdk/client-sts@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-sts/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-sts@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-sts/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -4738,11 +4738,11 @@ The @aws-cdk/integ-runner package includes the following third-party software/li ---------------- -** @aws-sdk/core@3.839.0 - https://www.npmjs.com/package/@aws-sdk/core/v/3.839.0 | Apache-2.0 +** @aws-sdk/core@3.846.0 - https://www.npmjs.com/package/@aws-sdk/core/v/3.846.0 | Apache-2.0 ---------------- -** @aws-sdk/credential-provider-cognito-identity@3.839.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-cognito-identity/v/3.839.0 | Apache-2.0 +** @aws-sdk/credential-provider-cognito-identity@3.846.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-cognito-identity/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -4948,7 +4948,7 @@ The @aws-cdk/integ-runner package includes the following third-party software/li ---------------- -** @aws-sdk/credential-provider-env@3.839.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-env/v/3.839.0 | Apache-2.0 +** @aws-sdk/credential-provider-env@3.846.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-env/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -5153,11 +5153,11 @@ Apache License ---------------- -** @aws-sdk/credential-provider-http@3.839.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-http/v/3.839.0 | Apache-2.0 +** @aws-sdk/credential-provider-http@3.846.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-http/v/3.846.0 | Apache-2.0 ---------------- -** @aws-sdk/credential-provider-ini@3.839.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-ini/v/3.839.0 | Apache-2.0 +** @aws-sdk/credential-provider-ini@3.846.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-ini/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -5362,7 +5362,7 @@ Apache License ---------------- -** @aws-sdk/credential-provider-node@3.839.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-node/v/3.839.0 | Apache-2.0 +** @aws-sdk/credential-provider-node@3.846.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-node/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -5567,7 +5567,7 @@ Apache License ---------------- -** @aws-sdk/credential-provider-process@3.839.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-process/v/3.839.0 | Apache-2.0 +** @aws-sdk/credential-provider-process@3.846.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-process/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -5772,7 +5772,7 @@ Apache License ---------------- -** @aws-sdk/credential-provider-sso@3.839.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-sso/v/3.839.0 | Apache-2.0 +** @aws-sdk/credential-provider-sso@3.846.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-sso/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -5977,7 +5977,7 @@ Apache License ---------------- -** @aws-sdk/credential-provider-web-identity@3.839.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-web-identity/v/3.839.0 | Apache-2.0 +** @aws-sdk/credential-provider-web-identity@3.846.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-web-identity/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -6182,7 +6182,7 @@ Apache License ---------------- -** @aws-sdk/credential-providers@3.839.0 - https://www.npmjs.com/package/@aws-sdk/credential-providers/v/3.839.0 | Apache-2.0 +** @aws-sdk/credential-providers@3.846.0 - https://www.npmjs.com/package/@aws-sdk/credential-providers/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -6387,7 +6387,7 @@ Apache License ---------------- -** @aws-sdk/ec2-metadata-service@3.839.0 - https://www.npmjs.com/package/@aws-sdk/ec2-metadata-service/v/3.839.0 | Apache-2.0 +** @aws-sdk/ec2-metadata-service@3.846.0 - https://www.npmjs.com/package/@aws-sdk/ec2-metadata-service/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -6592,7 +6592,7 @@ Apache License ---------------- -** @aws-sdk/lib-storage@3.839.0 - https://www.npmjs.com/package/@aws-sdk/lib-storage/v/3.839.0 | Apache-2.0 +** @aws-sdk/lib-storage@3.846.0 - https://www.npmjs.com/package/@aws-sdk/lib-storage/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -6797,7 +6797,7 @@ Apache License ---------------- -** @aws-sdk/middleware-bucket-endpoint@3.830.0 - https://www.npmjs.com/package/@aws-sdk/middleware-bucket-endpoint/v/3.830.0 | Apache-2.0 +** @aws-sdk/middleware-bucket-endpoint@3.840.0 - https://www.npmjs.com/package/@aws-sdk/middleware-bucket-endpoint/v/3.840.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -7003,7 +7003,7 @@ Apache License ---------------- -** @aws-sdk/middleware-expect-continue@3.821.0 - https://www.npmjs.com/package/@aws-sdk/middleware-expect-continue/v/3.821.0 | Apache-2.0 +** @aws-sdk/middleware-expect-continue@3.840.0 - https://www.npmjs.com/package/@aws-sdk/middleware-expect-continue/v/3.840.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -7209,7 +7209,7 @@ Apache License ---------------- -** @aws-sdk/middleware-flexible-checksums@3.839.0 - https://www.npmjs.com/package/@aws-sdk/middleware-flexible-checksums/v/3.839.0 | Apache-2.0 +** @aws-sdk/middleware-flexible-checksums@3.846.0 - https://www.npmjs.com/package/@aws-sdk/middleware-flexible-checksums/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -7415,7 +7415,7 @@ Apache License ---------------- -** @aws-sdk/middleware-host-header@3.821.0 - https://www.npmjs.com/package/@aws-sdk/middleware-host-header/v/3.821.0 | Apache-2.0 +** @aws-sdk/middleware-host-header@3.840.0 - https://www.npmjs.com/package/@aws-sdk/middleware-host-header/v/3.840.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -7621,7 +7621,7 @@ Apache License ---------------- -** @aws-sdk/middleware-location-constraint@3.821.0 - https://www.npmjs.com/package/@aws-sdk/middleware-location-constraint/v/3.821.0 | Apache-2.0 +** @aws-sdk/middleware-location-constraint@3.840.0 - https://www.npmjs.com/package/@aws-sdk/middleware-location-constraint/v/3.840.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -7827,7 +7827,7 @@ Apache License ---------------- -** @aws-sdk/middleware-logger@3.821.0 - https://www.npmjs.com/package/@aws-sdk/middleware-logger/v/3.821.0 | Apache-2.0 +** @aws-sdk/middleware-logger@3.840.0 - https://www.npmjs.com/package/@aws-sdk/middleware-logger/v/3.840.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -8032,7 +8032,7 @@ Apache License ---------------- -** @aws-sdk/middleware-recursion-detection@3.821.0 - https://www.npmjs.com/package/@aws-sdk/middleware-recursion-detection/v/3.821.0 | Apache-2.0 +** @aws-sdk/middleware-recursion-detection@3.840.0 - https://www.npmjs.com/package/@aws-sdk/middleware-recursion-detection/v/3.840.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -8238,7 +8238,7 @@ Apache License ---------------- -** @aws-sdk/middleware-sdk-ec2@3.839.0 - https://www.npmjs.com/package/@aws-sdk/middleware-sdk-ec2/v/3.839.0 | Apache-2.0 +** @aws-sdk/middleware-sdk-ec2@3.845.0 - https://www.npmjs.com/package/@aws-sdk/middleware-sdk-ec2/v/3.845.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -8443,7 +8443,7 @@ Apache License ---------------- -** @aws-sdk/middleware-sdk-route53@3.821.0 - https://www.npmjs.com/package/@aws-sdk/middleware-sdk-route53/v/3.821.0 | Apache-2.0 +** @aws-sdk/middleware-sdk-route53@3.840.0 - https://www.npmjs.com/package/@aws-sdk/middleware-sdk-route53/v/3.840.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -8649,7 +8649,7 @@ Apache License ---------------- -** @aws-sdk/middleware-sdk-s3@3.839.0 - https://www.npmjs.com/package/@aws-sdk/middleware-sdk-s3/v/3.839.0 | Apache-2.0 +** @aws-sdk/middleware-sdk-s3@3.846.0 - https://www.npmjs.com/package/@aws-sdk/middleware-sdk-s3/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -8855,7 +8855,7 @@ Apache License ---------------- -** @aws-sdk/middleware-ssec@3.821.0 - https://www.npmjs.com/package/@aws-sdk/middleware-ssec/v/3.821.0 | Apache-2.0 +** @aws-sdk/middleware-ssec@3.840.0 - https://www.npmjs.com/package/@aws-sdk/middleware-ssec/v/3.840.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -9061,7 +9061,7 @@ Apache License ---------------- -** @aws-sdk/middleware-user-agent@3.839.0 - https://www.npmjs.com/package/@aws-sdk/middleware-user-agent/v/3.839.0 | Apache-2.0 +** @aws-sdk/middleware-user-agent@3.846.0 - https://www.npmjs.com/package/@aws-sdk/middleware-user-agent/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -9267,11 +9267,11 @@ Apache License ---------------- -** @aws-sdk/nested-clients@3.839.0 - https://www.npmjs.com/package/@aws-sdk/nested-clients/v/3.839.0 | Apache-2.0 +** @aws-sdk/nested-clients@3.846.0 - https://www.npmjs.com/package/@aws-sdk/nested-clients/v/3.846.0 | Apache-2.0 ---------------- -** @aws-sdk/region-config-resolver@3.821.0 - https://www.npmjs.com/package/@aws-sdk/region-config-resolver/v/3.821.0 | Apache-2.0 +** @aws-sdk/region-config-resolver@3.840.0 - https://www.npmjs.com/package/@aws-sdk/region-config-resolver/v/3.840.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -9476,7 +9476,7 @@ Apache License ---------------- -** @aws-sdk/signature-v4-multi-region@3.839.0 - https://www.npmjs.com/package/@aws-sdk/signature-v4-multi-region/v/3.839.0 | Apache-2.0 +** @aws-sdk/signature-v4-multi-region@3.846.0 - https://www.npmjs.com/package/@aws-sdk/signature-v4-multi-region/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -9682,7 +9682,7 @@ Apache License ---------------- -** @aws-sdk/token-providers@3.839.0 - https://www.npmjs.com/package/@aws-sdk/token-providers/v/3.839.0 | Apache-2.0 +** @aws-sdk/token-providers@3.846.0 - https://www.npmjs.com/package/@aws-sdk/token-providers/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -10092,7 +10092,7 @@ Apache License ---------------- -** @aws-sdk/util-endpoints@3.828.0 - https://www.npmjs.com/package/@aws-sdk/util-endpoints/v/3.828.0 | Apache-2.0 +** @aws-sdk/util-endpoints@3.845.0 - https://www.npmjs.com/package/@aws-sdk/util-endpoints/v/3.845.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -10297,7 +10297,7 @@ Apache License ---------------- -** @aws-sdk/util-format-url@3.821.0 - https://www.npmjs.com/package/@aws-sdk/util-format-url/v/3.821.0 | Apache-2.0 +** @aws-sdk/util-format-url@3.840.0 - https://www.npmjs.com/package/@aws-sdk/util-format-url/v/3.840.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -10502,7 +10502,7 @@ Apache License ---------------- -** @aws-sdk/util-user-agent-node@3.839.0 - https://www.npmjs.com/package/@aws-sdk/util-user-agent-node/v/3.839.0 | Apache-2.0 +** @aws-sdk/util-user-agent-node@3.846.0 - https://www.npmjs.com/package/@aws-sdk/util-user-agent-node/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -11323,7 +11323,7 @@ Apache License ---------------- -** @smithy/core@3.6.0 - https://www.npmjs.com/package/@smithy/core/v/3.6.0 | Apache-2.0 +** @smithy/core@3.7.0 - https://www.npmjs.com/package/@smithy/core/v/3.7.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -12558,7 +12558,7 @@ Apache License ---------------- -** @smithy/fetch-http-handler@5.0.4 - https://www.npmjs.com/package/@smithy/fetch-http-handler/v/5.0.4 | Apache-2.0 +** @smithy/fetch-http-handler@5.1.0 - https://www.npmjs.com/package/@smithy/fetch-http-handler/v/5.1.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -13788,7 +13788,7 @@ Apache License ---------------- -** @smithy/middleware-endpoint@4.1.13 - https://www.npmjs.com/package/@smithy/middleware-endpoint/v/4.1.13 | Apache-2.0 +** @smithy/middleware-endpoint@4.1.15 - https://www.npmjs.com/package/@smithy/middleware-endpoint/v/4.1.15 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -13993,7 +13993,7 @@ Apache License ---------------- -** @smithy/middleware-retry@4.1.14 - https://www.npmjs.com/package/@smithy/middleware-retry/v/4.1.14 | Apache-2.0 +** @smithy/middleware-retry@4.1.16 - https://www.npmjs.com/package/@smithy/middleware-retry/v/4.1.16 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -14815,7 +14815,7 @@ Apache License ---------------- -** @smithy/node-http-handler@4.0.6 - https://www.npmjs.com/package/@smithy/node-http-handler/v/4.0.6 | Apache-2.0 +** @smithy/node-http-handler@4.1.0 - https://www.npmjs.com/package/@smithy/node-http-handler/v/4.1.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -16459,7 +16459,7 @@ Apache License ---------------- -** @smithy/smithy-client@4.4.5 - https://www.npmjs.com/package/@smithy/smithy-client/v/4.4.5 | Apache-2.0 +** @smithy/smithy-client@4.4.7 - https://www.npmjs.com/package/@smithy/smithy-client/v/4.4.7 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -18307,7 +18307,7 @@ Apache License ---------------- -** @smithy/util-defaults-mode-node@4.0.21 - https://www.npmjs.com/package/@smithy/util-defaults-mode-node/v/4.0.21 | Apache-2.0 +** @smithy/util-defaults-mode-node@4.0.23 - https://www.npmjs.com/package/@smithy/util-defaults-mode-node/v/4.0.23 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -19333,7 +19333,7 @@ Apache License ---------------- -** @smithy/util-stream@4.2.2 - https://www.npmjs.com/package/@smithy/util-stream/v/4.2.2 | Apache-2.0 +** @smithy/util-stream@4.2.3 - https://www.npmjs.com/package/@smithy/util-stream/v/4.2.3 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -21392,7 +21392,7 @@ THE SOFTWARE. ---------------- -** fast-xml-parser@4.4.1 - https://www.npmjs.com/package/fast-xml-parser/v/4.4.1 | MIT +** fast-xml-parser@5.2.5 - https://www.npmjs.com/package/fast-xml-parser/v/5.2.5 | MIT MIT License Copyright (c) 2017 Amit Kumar Gupta @@ -22615,7 +22615,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI ---------------- -** strnum@1.1.2 - https://www.npmjs.com/package/strnum/v/1.1.2 | MIT +** strnum@2.1.1 - https://www.npmjs.com/package/strnum/v/2.1.1 | MIT MIT License Copyright (c) 2021 Natural Intelligence diff --git a/packages/@aws-cdk/integ-runner/lib/engines/toolkit-lib.ts b/packages/@aws-cdk/integ-runner/lib/engines/toolkit-lib.ts index 16479b956..960ca6d38 100644 --- a/packages/@aws-cdk/integ-runner/lib/engines/toolkit-lib.ts +++ b/packages/@aws-cdk/integ-runner/lib/engines/toolkit-lib.ts @@ -4,6 +4,7 @@ import type { DefaultCdkOptions, DestroyOptions } from '@aws-cdk/cloud-assembly- import type { DeploymentMethod, ICloudAssemblySource, IIoHost, IoMessage, IoRequest, NonInteractiveIoHostProps, StackSelector } from '@aws-cdk/toolkit-lib'; import { ExpandStackSelection, MemoryContext, NonInteractiveIoHost, StackSelectionStrategy, Toolkit } from '@aws-cdk/toolkit-lib'; import * as chalk from 'chalk'; +import * as fs from 'fs-extra'; export interface ToolkitLibEngineOptions { /** @@ -84,6 +85,7 @@ export class ToolkitLibRunnerEngine implements ICdk { outdir: options.output ? path.join(this.options.workingDirectory, options.output) : undefined, contextStore: new MemoryContext(options.context), lookups: false, + resolveDefaultEnvironment: false, env: { ...this.options.env, ...options.env, @@ -200,6 +202,12 @@ export class ToolkitLibRunnerEngine implements ICdk { throw new Error('No app provided'); } + // check if the app is a path to existing snapshot and then use it as an assembly directory + const potentialCxPath = path.join(this.options.workingDirectory, options.app); + if (fs.pathExistsSync(potentialCxPath) && fs.statSync(potentialCxPath).isDirectory()) { + return this.toolkit.fromAssemblyDirectory(potentialCxPath); + } + let outdir; if (options.output) { outdir = path.join(this.options.workingDirectory, options.output); @@ -209,6 +217,7 @@ export class ToolkitLibRunnerEngine implements ICdk { workingDirectory: this.options.workingDirectory, outdir, lookups: options.lookups, + resolveDefaultEnvironment: false, // not part of the integ-runner contract contextStore: new MemoryContext(options.context), env: this.options.env, synthOptions: { diff --git a/packages/@aws-cdk/integ-runner/lib/logger.ts b/packages/@aws-cdk/integ-runner/lib/logger.ts index b656feed3..75e7a7b29 100644 --- a/packages/@aws-cdk/integ-runner/lib/logger.ts +++ b/packages/@aws-cdk/integ-runner/lib/logger.ts @@ -18,3 +18,4 @@ export const error = logger(stderr, [chalk.red]); export const warning = logger(stderr, [chalk.yellow]); export const success = logger(stderr, [chalk.green]); export const highlight = logger(stderr, [chalk.bold]); +export const trace = logger(stderr, [chalk.gray]); diff --git a/packages/@aws-cdk/integ-runner/lib/runner/integ-test-runner.ts b/packages/@aws-cdk/integ-runner/lib/runner/integ-test-runner.ts index 07714a541..5035f9e07 100644 --- a/packages/@aws-cdk/integ-runner/lib/runner/integ-test-runner.ts +++ b/packages/@aws-cdk/integ-runner/lib/runner/integ-test-runner.ts @@ -454,7 +454,7 @@ export class IntegTestRunner extends IntegRunner { }); } // if the update workflow is not disabled, first - // perform a deployment with the exising snapshot + // perform a deployment with the existing snapshot // then perform a deployment (which will be a stack update) // with the current integration test // We also only want to run the update workflow if there is an existing diff --git a/packages/@aws-cdk/integ-runner/lib/runner/private/integ-manifest.ts b/packages/@aws-cdk/integ-runner/lib/runner/private/integ-manifest.ts index bb6deff82..6ce8626b6 100644 --- a/packages/@aws-cdk/integ-runner/lib/runner/private/integ-manifest.ts +++ b/packages/@aws-cdk/integ-runner/lib/runner/private/integ-manifest.ts @@ -3,6 +3,44 @@ import type { IntegManifest, TestCase } from '@aws-cdk/cloud-assembly-schema'; import { Manifest } from '@aws-cdk/cloud-assembly-schema'; import * as fs from 'fs-extra'; +/** + * An error indicating that the manifest file does not exists. + * + * This can signal to treat the integ test case as a legacy test. + */ +export class NoManifestError extends Error { + public readonly manifestPath: string; + public readonly cause: Error; + + constructor(manifestPath: string, cause: Error) { + super(`Cannot read integ manifest '${manifestPath}': ${cause.message}`); + this.name = 'NoManifestError'; + this.manifestPath = manifestPath; + this.cause = cause; + + Object.setPrototypeOf(this, NoManifestError.prototype); + } +} + +/** + * An error indicating that the manifest failed to load. + * + * The error implies the the manifest file exists, but is invalid. + */ +export class ManifestLoadError extends Error { + public readonly manifestPath: string; + public readonly cause: Error; + + constructor(manifestPath: string, cause: Error) { + super(`Failed to load integ manifest '${manifestPath}': ${cause.message}`); + this.name = 'ManifestLoadingError'; + this.manifestPath = manifestPath; + this.cause = cause; + + Object.setPrototypeOf(this, ManifestLoadError.prototype); + } +} + /** * Test case configuration read from the integ manifest */ @@ -39,11 +77,17 @@ export class IntegManifestReader { * Reads an integration test manifest from the specified file */ public static fromFile(fileName: string): IntegManifestReader { + try { + fs.statSync(fileName); + } catch (e: any) { + throw new NoManifestError(fileName, e); + } + try { const obj = Manifest.loadIntegManifest(fileName); return new IntegManifestReader(path.dirname(fileName), obj); - } catch (e: any) { - throw new Error(`Cannot read integ manifest '${fileName}': ${e.message}`); + } catch (loadErr: any) { + throw new ManifestLoadError(fileName, loadErr); } } @@ -57,7 +101,7 @@ export class IntegManifestReader { try { st = fs.statSync(filePath); } catch (e: any) { - throw new Error(`Cannot read integ manifest at '${filePath}': ${e.message}`); + throw new NoManifestError(filePath, e); } if (st.isDirectory()) { return IntegManifestReader.fromFile(path.join(filePath, IntegManifestReader.DEFAULT_FILENAME)); diff --git a/packages/@aws-cdk/integ-runner/lib/runner/runner-base.ts b/packages/@aws-cdk/integ-runner/lib/runner/runner-base.ts index 25a106d36..11113104b 100644 --- a/packages/@aws-cdk/integ-runner/lib/runner/runner-base.ts +++ b/packages/@aws-cdk/integ-runner/lib/runner/runner-base.ts @@ -9,9 +9,11 @@ import type { IntegTest } from './integration-tests'; import * as recommendedFlagsFile from '../recommended-feature-flags.json'; import { flatten } from '../utils'; import { makeEngine, type EngineOptions } from './engine'; +import * as logger from '../logger'; import type { ManifestTrace } from './private/cloud-assembly'; import { AssemblyManifestReader } from './private/cloud-assembly'; import type { DestructiveChange } from '../workers/common'; +import { NoManifestError } from './private/integ-manifest'; const DESTRUCTIVE_CHANGES = '!!DESTRUCTIVE_CHANGES:'; @@ -128,6 +130,11 @@ export abstract class IntegRunner { */ protected readonly profile?: string; + /** + * Show output from the integ test run. + */ + protected readonly showOutput: boolean; + protected _destructiveChanges?: DestructiveChange[]; private legacyContext?: Record; private _expectedTestSuite?: IntegTestSuite | LegacyIntegTestSuite; @@ -139,14 +146,14 @@ export abstract class IntegRunner { this.testName = this.test.testName; this.snapshotDir = this.test.snapshotDir; this.cdkContextPath = path.join(this.directory, 'cdk.context.json'); + this.profile = options.profile; + this.showOutput = options.showOutput ?? false; this.cdk = options.cdk ?? makeEngine(options); this.cdkOutDir = options.integOutDir ?? this.test.temporaryOutputDir; const testRunCommand = this.test.appCommand; this.cdkApp = testRunCommand.replace('{filePath}', path.relative(this.directory, this.test.fileName)); - - this.profile = options.profile; } /** @@ -219,10 +226,25 @@ export abstract class IntegRunner { * "legacy mode" and create a manifest from pragma */ protected async loadManifest(dir?: string): Promise { + const manifest = dir ?? this.snapshotDir; try { - const testSuite = IntegTestSuite.fromPath(dir ?? this.snapshotDir); + const testSuite = IntegTestSuite.fromPath(manifest); return testSuite; - } catch { + } catch (modernError: any) { + // Only attempt legacy test case if the integ test manifest was not found + // For any other errors, e.g. when parsing the manifest fails, we abort. + if (!(modernError instanceof NoManifestError)) { + throw modernError; + } + + if (this.showOutput) { + logger.trace( + "Failed to load integ test manifest for '%s'. Attempting as deprecated legacy test instead. Error was: %s", + manifest, + modernError.message ?? String(modernError), + ); + } + const testCases = await LegacyIntegTestSuite.fromLegacy({ cdk: this.cdk, testName: this.test.normalizedTestName, diff --git a/packages/@aws-cdk/integ-runner/lib/workers/common.ts b/packages/@aws-cdk/integ-runner/lib/workers/common.ts index 85e8658e7..c8a09397b 100644 --- a/packages/@aws-cdk/integ-runner/lib/workers/common.ts +++ b/packages/@aws-cdk/integ-runner/lib/workers/common.ts @@ -286,23 +286,23 @@ export function printResults(diagnostic: Diagnostic): void { logger.success(' UNCHANGED %s %s', diagnostic.testName, chalk.gray(`${diagnostic.duration}s`)); break; case DiagnosticReason.TEST_SUCCESS: - logger.success(' SUCCESS %s %s\n ', diagnostic.testName, chalk.gray(`${diagnostic.duration}s`), diagnostic.message); + logger.success(' SUCCESS %s %s\n ', diagnostic.testName, chalk.gray(`${diagnostic.duration}s`)); break; case DiagnosticReason.NO_SNAPSHOT: logger.error(' NEW %s %s', diagnostic.testName, chalk.gray(`${diagnostic.duration}s`)); break; case DiagnosticReason.SNAPSHOT_FAILED: - logger.error(' CHANGED %s %s\n %s', diagnostic.testName, chalk.gray(`${diagnostic.duration}s`), diagnostic.message); + logger.error(' CHANGED %s %s\n%s', diagnostic.testName, chalk.gray(`${diagnostic.duration}s`), indentLines(diagnostic.message, 6)); break; case DiagnosticReason.SNAPSHOT_ERROR: case DiagnosticReason.TEST_ERROR: - logger.error(' ERROR %s %s\n %s', diagnostic.testName, chalk.gray(`${diagnostic.duration}s`), diagnostic.message); + logger.error(' ERROR %s %s\n%s', diagnostic.testName, chalk.gray(`${diagnostic.duration}s`), indentLines(diagnostic.message, 6)); break; case DiagnosticReason.TEST_FAILED: - logger.error(' FAILED %s %s\n %s', diagnostic.testName, chalk.gray(`${diagnostic.duration}s`), diagnostic.message); + logger.error(' FAILED %s %s\n%s', diagnostic.testName, chalk.gray(`${diagnostic.duration}s`), indentLines(diagnostic.message, 6)); break; case DiagnosticReason.ASSERTION_FAILED: - logger.error(' ASSERT %s %s\n %s', diagnostic.testName, chalk.gray(`${diagnostic.duration}s`), diagnostic.message); + logger.error(' ASSERT %s %s\n%s', diagnostic.testName, chalk.gray(`${diagnostic.duration}s`), indentLines(diagnostic.message, 6)); break; } for (const addl of diagnostic.additionalMessages ?? []) { @@ -310,6 +310,13 @@ export function printResults(diagnostic: Diagnostic): void { } } +/** + * Takes a multiline string and indents every line with the same number of spaces. + */ +function indentLines(message: string, count = 2): string { + return message.split('\n').map(line => ' '.repeat(count) + line).join('\n'); +} + export function printLaggards(testNames: Set) { const parts = [ ' ', @@ -319,3 +326,14 @@ export function printLaggards(testNames: Set) { logger.print(chalk.grey(parts.filter(x => x).join(' '))); } + +export function formatError(error: any): string { + const name = error.name || 'Error'; + const message = error.message || String(error); + + if (error.cause) { + return `${name}: ${message}\n${chalk.gray('Cause: ' + formatError(error.cause))}`; + } + + return `${name}: ${message}`; +} diff --git a/packages/@aws-cdk/integ-runner/lib/workers/extract/extract_worker.ts b/packages/@aws-cdk/integ-runner/lib/workers/extract/extract_worker.ts index 21bc75518..63d4059a9 100644 --- a/packages/@aws-cdk/integ-runner/lib/workers/extract/extract_worker.ts +++ b/packages/@aws-cdk/integ-runner/lib/workers/extract/extract_worker.ts @@ -3,7 +3,7 @@ import { IntegSnapshotRunner, IntegTestRunner } from '../../runner'; import type { IntegTestInfo } from '../../runner/integration-tests'; import { IntegTest } from '../../runner/integration-tests'; import type { IntegTestWorkerConfig, SnapshotVerificationOptions, Diagnostic } from '../common'; -import { DiagnosticReason, formatAssertionResults } from '../common'; +import { DiagnosticReason, formatAssertionResults, formatError } from '../common'; import type { IntegTestBatchRequest } from '../integ-test-worker'; import type { IntegWatchOptions } from '../integ-watch-worker'; @@ -73,7 +73,7 @@ export async function integTestWorker(request: IntegTestBatchRequest): Promise; +const mockedFs = fs as jest.Mocked; + +describe('ToolkitLibRunnerEngine - Snapshot Path Handling', () => { + let mockToolkit: jest.Mocked; + let engine: ToolkitLibRunnerEngine; + + beforeEach(() => { + jest.clearAllMocks(); + mockToolkit = { + fromCdkApp: jest.fn(), + fromAssemblyDirectory: jest.fn(), + synth: jest.fn(), + } as any; + MockedToolkit.mockImplementation(() => mockToolkit); + + engine = new ToolkitLibRunnerEngine({ + workingDirectory: '/test/dir', + }); + }); + + it('should use fromAssemblyDirectory when app is a path to existing snapshot directory', async () => { + const snapshotPath = 'test.snapshot'; + const fullSnapshotPath = path.join('/test/dir', snapshotPath); + const mockCx = { produce: jest.fn() }; + const mockLock = { dispose: jest.fn() }; + + // Mock fs to indicate the snapshot directory exists + mockedFs.pathExistsSync.mockReturnValue(true); + mockedFs.statSync.mockReturnValue({ isDirectory: () => true } as any); + + mockToolkit.fromAssemblyDirectory.mockResolvedValue(mockCx as any); + mockToolkit.synth.mockResolvedValue(mockLock as any); + + await engine.synth({ + app: snapshotPath, + stacks: ['stack1'], + }); + + expect(mockedFs.pathExistsSync).toHaveBeenCalledWith(fullSnapshotPath); + expect(mockedFs.statSync).toHaveBeenCalledWith(fullSnapshotPath); + expect(mockToolkit.fromAssemblyDirectory).toHaveBeenCalledWith(fullSnapshotPath); + expect(mockToolkit.fromCdkApp).not.toHaveBeenCalled(); + }); + + it('should use fromCdkApp when app is not a path to existing directory', async () => { + const appCommand = 'node bin/app.js'; + const mockCx = { produce: jest.fn() }; + const mockLock = { dispose: jest.fn() }; + + // Mock fs to indicate the path doesn't exist + mockedFs.pathExistsSync.mockReturnValue(false); + + mockToolkit.fromCdkApp.mockResolvedValue(mockCx as any); + mockToolkit.synth.mockResolvedValue(mockLock as any); + + await engine.synth({ + app: appCommand, + stacks: ['stack1'], + }); + + expect(mockToolkit.fromCdkApp).toHaveBeenCalledWith(appCommand, expect.any(Object)); + expect(mockToolkit.fromAssemblyDirectory).not.toHaveBeenCalled(); + }); + + it('should use fromCdkApp when app path exists but is not a directory', async () => { + const appPath = 'app.js'; + const fullAppPath = path.join('/test/dir', appPath); + const mockCx = { produce: jest.fn() }; + const mockLock = { dispose: jest.fn() }; + + // Mock fs to indicate the path exists but is not a directory + mockedFs.pathExistsSync.mockReturnValue(true); + mockedFs.statSync.mockReturnValue({ isDirectory: () => false } as any); + + mockToolkit.fromCdkApp.mockResolvedValue(mockCx as any); + mockToolkit.synth.mockResolvedValue(mockLock as any); + + await engine.synth({ + app: appPath, + stacks: ['stack1'], + }); + + expect(mockedFs.pathExistsSync).toHaveBeenCalledWith(fullAppPath); + expect(mockedFs.statSync).toHaveBeenCalledWith(fullAppPath); + expect(mockToolkit.fromCdkApp).toHaveBeenCalledWith(appPath, expect.any(Object)); + expect(mockToolkit.fromAssemblyDirectory).not.toHaveBeenCalled(); + }); +}); diff --git a/packages/@aws-cdk/integ-runner/test/engines/toolkit-lib.test.ts b/packages/@aws-cdk/integ-runner/test/engines/toolkit-lib.test.ts index f77ee4f60..2dc440d41 100644 --- a/packages/@aws-cdk/integ-runner/test/engines/toolkit-lib.test.ts +++ b/packages/@aws-cdk/integ-runner/test/engines/toolkit-lib.test.ts @@ -73,6 +73,7 @@ describe('ToolkitLibRunnerEngine', () => { contextStore: expect.any(Object), lookups: false, env: { TEST: 'true' }, + resolveDefaultEnvironment: false, synthOptions: { versionReporting: false, pathMetadata: false, diff --git a/packages/@aws-cdk/integ-runner/test/helpers.ts b/packages/@aws-cdk/integ-runner/test/helpers.ts index 869a5c514..dda1059d5 100644 --- a/packages/@aws-cdk/integ-runner/test/helpers.ts +++ b/packages/@aws-cdk/integ-runner/test/helpers.ts @@ -1,5 +1,4 @@ -import type { ChildProcess } from 'child_process'; -import { Readable, Writable } from 'stream'; +import * as path from 'path'; import type { CdkCliWrapperOptions, DeployOptions, ICdk, ListOptions, SynthFastOptions, SynthOptions } from '@aws-cdk/cdk-cli-wrapper'; import type { DestroyOptions } from '@aws-cdk/cloud-assembly-schema/lib/integ-tests'; import { IntegSnapshotRunner, IntegTest } from '../lib/runner'; @@ -106,3 +105,10 @@ export class MockCdkProvider { return results; } } + +/** + * Get the absolute path to a data located the test-data directory + */ +export function testDataPath(...location: string[]): string { + return path.join(__dirname, 'test-data', ...location); +} diff --git a/packages/@aws-cdk/integ-runner/test/runner/private/invalid-manifest.test.ts b/packages/@aws-cdk/integ-runner/test/runner/private/invalid-manifest.test.ts new file mode 100644 index 000000000..2f0b29bf9 --- /dev/null +++ b/packages/@aws-cdk/integ-runner/test/runner/private/invalid-manifest.test.ts @@ -0,0 +1,21 @@ +import { IntegTestSuite } from '../../../lib/runner/integ-test-suite'; +import { IntegManifestReader, ManifestLoadError } from '../../../lib/runner/private/integ-manifest'; +import { testDataPath } from '../../helpers'; + +describe('Invalid Manifest Handling', () => { + test('throws ManifestLoadError when loading an invalid JSON manifest', () => { + // GIVEN + const invalidManifestPath = testDataPath('invalid-integ-manifest', 'integ.json'); + + // WHEN / THEN + expect(() => IntegManifestReader.fromFile(invalidManifestPath)).toThrow(ManifestLoadError); + }); + + test('IntegTestSuite.fromPath propagates ManifestLoadError', () => { + // GIVEN + const invalidManifestDir = testDataPath('invalid-integ-manifest'); + + // WHEN / THEN + expect(() => IntegTestSuite.fromPath(invalidManifestDir)).toThrow(ManifestLoadError); + }); +}); diff --git a/packages/@aws-cdk/integ-runner/test/runner/runner-base-manifest-errors.test.ts b/packages/@aws-cdk/integ-runner/test/runner/runner-base-manifest-errors.test.ts new file mode 100644 index 000000000..87a84543e --- /dev/null +++ b/packages/@aws-cdk/integ-runner/test/runner/runner-base-manifest-errors.test.ts @@ -0,0 +1,84 @@ +import * as path from 'path'; +import { LegacyIntegTestSuite } from '../../lib/runner'; +import { IntegTest } from '../../lib/runner/integration-tests'; +import { ManifestLoadError } from '../../lib/runner/private/integ-manifest'; +import { IntegRunner } from '../../lib/runner/runner-base'; +import { testDataPath } from '../helpers'; + +// Create a concrete implementation of IntegRunner for testing +class TestIntegRunner extends IntegRunner { + public async runIntegTestCase(): Promise { + // No-op for testing + } + + // Expose protected method for testing + public async testLoadManifest(dir?: string) { + return this.loadManifest(dir); + } +} + +describe('IntegRunner manifest error handling', () => { + let mockCdk: any; + + beforeEach(() => { + mockCdk = { + synthesize: jest.fn(), + deploy: jest.fn(), + destroy: jest.fn(), + }; + + // fakeTest = new IntegTest({ + // fileName: 'test/test-data/xxxxx.test-with-snapshot.js', + // discoveryRoot: 'test/test-data', + // }); + + // { + // fileName: 'test/integ.test.js', + // testName: 'test', + // normalizedTestName: 'test', + // snapshotDir: 'test.snapshot', + // temporaryOutputDir: 'test.output', + // appCommand: 'node {filePath}', + // discoveryRelativeFileName: 1, + // absoluteFileName: 1, + // directory: 'test', + // info: 1, + // matches: '', + // }; + }); + + test('loadManifest throws ManifestLoadError when manifest is invalid', async () => { + // GIVEN + const invalidManifestDir = testDataPath('invalid-integ-manifest'); + const runner = new TestIntegRunner({ + cdk: mockCdk, + test: new IntegTest({ + fileName: 'test/test-data/xxxxx.test-with-snapshot.js', + discoveryRoot: 'test/test-data', + }), + showOutput: true, + }); + + // WHEN / THEN + await expect(runner.testLoadManifest(invalidManifestDir)).rejects.toThrow(ManifestLoadError); + }); + + test('loadManifest falls back to legacy mode when manifest does not exist', async () => { + // GIVEN + const nonExistentDir = testDataPath('non-existent-dir'); + const runner = new TestIntegRunner({ + cdk: mockCdk, + test: new IntegTest({ + fileName: 'test/test-data/xxxxx.test-with-snapshot.js', + discoveryRoot: 'test/test-data', + }), + showOutput: true, + }); + + // WHEN + const result = await runner.testLoadManifest(nonExistentDir); + + // THEN + expect(result instanceof LegacyIntegTestSuite).toBe(true); + }); +}); diff --git a/packages/@aws-cdk/integ-runner/test/runner/snapshot-test-runner.test.ts b/packages/@aws-cdk/integ-runner/test/runner/snapshot-test-runner.test.ts index 8617f02f4..a32c1beaf 100644 --- a/packages/@aws-cdk/integ-runner/test/runner/snapshot-test-runner.test.ts +++ b/packages/@aws-cdk/integ-runner/test/runner/snapshot-test-runner.test.ts @@ -155,7 +155,7 @@ describe('IntegTest runSnapshotTests', () => { describe('Legacy parameter based assets ', () => { test('diff asset hashes', async () => { // WHEN - const results = await cdkMock.snapshotTest('xxxxx.test-with-snapshot-assets.js', 'xxxxx.test-with-snapshot-assets-diff.js.snapshot'); + const results = await cdkMock.snapshotTest('xxxxx.test-with-snapshot-assets.js', 'xxxxx.legacy-with-snapshot-assets-diff.js.snapshot'); // THEN expect(results.diagnostics).toEqual(expect.arrayContaining([expect.objectContaining({ diff --git a/packages/@aws-cdk/integ-runner/test/test-data/invalid-integ-manifest/integ.json b/packages/@aws-cdk/integ-runner/test/test-data/invalid-integ-manifest/integ.json new file mode 100644 index 000000000..e3374c471 --- /dev/null +++ b/packages/@aws-cdk/integ-runner/test/test-data/invalid-integ-manifest/integ.json @@ -0,0 +1,11 @@ +{ + "version": "v1.0.0", + "testCases": { + "invalid-test": { + "stacks": ["test-stack"], + "diffAssets": false, + // This is an invalid JSON comment that will cause parsing to fail + "regions": ["us-east-1"] + } + } +} diff --git a/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.legacy-with-snapshot-assets-diff.js.snapshot/asset.fec1c56a3f23d9d27f58815e0c34c810cc02f431ac63a078f9b5d2aa44cc3509/index.js b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.legacy-with-snapshot-assets-diff.js.snapshot/asset.fec1c56a3f23d9d27f58815e0c34c810cc02f431ac63a078f9b5d2aa44cc3509/index.js new file mode 100644 index 000000000..e69de29bb diff --git a/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.legacy-with-snapshot-assets-diff.js.snapshot/cdk.out b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.legacy-with-snapshot-assets-diff.js.snapshot/cdk.out new file mode 100644 index 000000000..2efc89439 --- /dev/null +++ b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.legacy-with-snapshot-assets-diff.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"18.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.legacy-with-snapshot-assets-diff.js.snapshot/manifest.json b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.legacy-with-snapshot-assets-diff.js.snapshot/manifest.json new file mode 100644 index 000000000..0d7e598bc --- /dev/null +++ b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.legacy-with-snapshot-assets-diff.js.snapshot/manifest.json @@ -0,0 +1,49 @@ +{ + "version": "21.0.0", + "artifacts": { + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + }, + "metadata": {} + }, + "test-stack": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "test-stack.template.json", + "validateOnSynth": false + }, + "metadata": { + "/test-stack": [ + { + "type": "aws:cdk:asset", + "data": { + "path": "asset.fec1c56a3f23d9d27f58815e0c34c810cc02f431ac63a078f9b5d2aa44cc3509", + "id": "fec1c56a3f23d9d27f58815e0c34c810cc02f431ac63a078f9b5d2aa44cc3509", + "packaging": "zip", + "sourceHash": "fec1c56a3f23d9d27f58815e0c34c810cc02f431ac63a078f9b5d2aa44cc3509", + "s3BucketParameter": "AssetParametersfec1c56a3f23d9d27f58815e0c34c810cc02f431ac63a078f9b5d2aa44cc3509S3BucketBF50F97C", + "s3KeyParameter": "AssetParametersfec1c56a3f23d9d27f58815e0c34c810cc02f431ac63a078f9b5d2aa44cc3509S3VersionKeyF21AC8C1", + "artifactHashParameter": "AssetParametersfec1c56a3f23d9d27f58815e0c34c810cc02f431ac63a078f9b5d2aa44cc3509ArtifactHash5D8C129B" + } + } + ], + "/test-stack/MyFunction1/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyFunction1ServiceRole9852B06B" + } + ], + "/test-stack/MyFunction1/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyFunction12A744C2E" + } + ] + }, + "displayName": "test-stack" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.legacy-with-snapshot-assets-diff.js.snapshot/test-stack.template.json b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.legacy-with-snapshot-assets-diff.js.snapshot/test-stack.template.json new file mode 100644 index 000000000..969780cdf --- /dev/null +++ b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.legacy-with-snapshot-assets-diff.js.snapshot/test-stack.template.json @@ -0,0 +1,68 @@ +{ + "Resources": { + "MyFunction1ServiceRole9852B06B": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "MyFunction12A744C2E": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "foo" + }, + "Role": { + "Fn::GetAtt": [ + "MyFunction1ServiceRole9852B06B", + "Arn" + ] + }, + "Handler": "index.handler", + "Runtime": "nodejs14.x" + }, + "DependsOn": [ + "MyFunction1ServiceRole9852B06B" + ] + } + }, + "Parameters": { + "AssetParametersDec1c56a3f23d9d27f58815e0c34c810cc02f431ac63a078f9b5d2aa44cc3509S3BucketBF50F97C": { + "Type": "String", + "Description": "S3 bucket for asset \"Dec1c56a3f23d9d27f58815e0c34c810cc02f431ac63a078f9b5d2aa44cc3509\"" + }, + "AssetParametersDec1c56a3f23d9d27f58815e0c34c810cc02f431ac63a078f9b5d2aa44cc3509S3VersionKeyF21AC8C1": { + "Type": "String", + "Description": "S3 key for asset version \"Dec1c56a3f23d9d27f58815e0c34c810cc02f431ac63a078f9b5d2aa44cc3509\"" + }, + "AssetParametersDec1c56a3f23d9d27f58815e0c34c810cc02f431ac63a078f9b5d2aa44cc3509ArtifactHash5D8C129B": { + "Type": "String", + "Description": "Artifact hash for asset \"Dec1c56a3f23d9d27f58815e0c34c810cc02f431ac63a078f9b5d2aa44cc3509\"" + } + } +} diff --git a/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.legacy-with-snapshot-assets-diff.js.snapshot/tree.json b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.legacy-with-snapshot-assets-diff.js.snapshot/tree.json new file mode 100644 index 000000000..b664bec74 --- /dev/null +++ b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.legacy-with-snapshot-assets-diff.js.snapshot/tree.json @@ -0,0 +1,114 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "@aws-cdk/core.Construct", + "version": "0.0.0" + } + }, + "test-stack": { + "id": "test-stack", + "path": "test-stack", + "children": { + "MyFunction1": { + "id": "MyFunction1", + "path": "test-stack/MyFunction1", + "children": { + "ServiceRole": { + "id": "ServiceRole", + "path": "test-stack/MyFunction1/ServiceRole", + "children": { + "Resource": { + "id": "Resource", + "path": "test-stack/MyFunction1/ServiceRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "managedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnRole", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Role", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "test-stack/MyFunction1/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::Function", + "aws:cdk:cloudformation:props": { + "code": { + "zipFile": "foo" + }, + "role": { + "Fn::GetAtt": [ + "MyFunction1ServiceRole9852B06B", + "Arn" + ] + }, + "handler": "index.handler", + "runtime": "nodejs14.x" + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.CfnFunction", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.Function", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.legacy-with-snapshot-assets.js.snapshot/asset.be270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824/index.js b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.legacy-with-snapshot-assets.js.snapshot/asset.be270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824/index.js new file mode 100644 index 000000000..e69de29bb diff --git a/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.legacy-with-snapshot-assets.js.snapshot/cdk.out b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.legacy-with-snapshot-assets.js.snapshot/cdk.out new file mode 100644 index 000000000..2efc89439 --- /dev/null +++ b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.legacy-with-snapshot-assets.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"18.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.legacy-with-snapshot-assets.js.snapshot/manifest.json b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.legacy-with-snapshot-assets.js.snapshot/manifest.json new file mode 100644 index 000000000..606c37571 --- /dev/null +++ b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.legacy-with-snapshot-assets.js.snapshot/manifest.json @@ -0,0 +1,43 @@ +{ + "version": "21.0.0", + "artifacts": { + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + }, + "metadata": {} + }, + "test-stack.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "test-stack.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "test-stack": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "test-stack.template.json", + "validateOnSynth": false + }, + "metadata": { + "/test-stack/MyFunction1/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyFunction1ServiceRole9852B06B" + } + ], + "/test-stack/MyFunction1/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyFunction12A744C2E" + } + ] + }, + "displayName": "test-stack" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.legacy-with-snapshot-assets.js.snapshot/test-stack.assets.json b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.legacy-with-snapshot-assets.js.snapshot/test-stack.assets.json new file mode 100644 index 000000000..9fce39f0c --- /dev/null +++ b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.legacy-with-snapshot-assets.js.snapshot/test-stack.assets.json @@ -0,0 +1,32 @@ +{ + "version": "17.0.0", + "files": { + "be270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824": { + "source": { + "path": "asset.be270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824", + "packaging": "zip" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "be270bbdebe0851c887569796e3997437cca54ce86893ed94788500448e92824.zip", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "cb05f22f001734dbadeb4f07d875c6ab8180f703346a8d66fca572a0e94c54a9": { + "source": { + "path": "test-stack.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "cb05f22f001734dbadeb4f07d875c6ab8180f703346a8d66fca572a0e94c54a9.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} diff --git a/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.legacy-with-snapshot-assets.js.snapshot/test-stack.template.json b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.legacy-with-snapshot-assets.js.snapshot/test-stack.template.json new file mode 100644 index 000000000..ed2a09b94 --- /dev/null +++ b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.legacy-with-snapshot-assets.js.snapshot/test-stack.template.json @@ -0,0 +1,68 @@ +{ + "Resources": { + "MyFunction1ServiceRole9852B06B": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "MyFunction12A744C2E": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "foo" + }, + "Role": { + "Fn::GetAtt": [ + "MyFunction1ServiceRole9852B06B", + "Arn" + ] + }, + "Handler": "index.handler", + "Runtime": "nodejs14.x" + }, + "DependsOn": [ + "MyFunction1ServiceRole9852B06B" + ] + } + }, + "Parameters": { + "AssetParametersfec1c56a3f23d9d27f58815e0c34c810cc02f431ac63a078f9b5d2aa44cc3509S3BucketBF50F97C": { + "Type": "String", + "Description": "S3 bucket for asset \"fec1c56a3f23d9d27f58815e0c34c810cc02f431ac63a078f9b5d2aa44cc3509\"" + }, + "AssetParametersfec1c56a3f23d9d27f58815e0c34c810cc02f431ac63a078f9b5d2aa44cc3509S3VersionKeyF21AC8C1": { + "Type": "String", + "Description": "S3 key for asset version \"fec1c56a3f23d9d27f58815e0c34c810cc02f431ac63a078f9b5d2aa44cc3509\"" + }, + "AssetParametersfec1c56a3f23d9d27f58815e0c34c810cc02f431ac63a078f9b5d2aa44cc3509ArtifactHash5D8C129B": { + "Type": "String", + "Description": "Artifact hash for asset \"fec1c56a3f23d9d27f58815e0c34c810cc02f431ac63a078f9b5d2aa44cc3509\"" + } + } +} diff --git a/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.legacy-with-snapshot-assets.js.snapshot/tree.json b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.legacy-with-snapshot-assets.js.snapshot/tree.json new file mode 100644 index 000000000..b664bec74 --- /dev/null +++ b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.legacy-with-snapshot-assets.js.snapshot/tree.json @@ -0,0 +1,114 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "@aws-cdk/core.Construct", + "version": "0.0.0" + } + }, + "test-stack": { + "id": "test-stack", + "path": "test-stack", + "children": { + "MyFunction1": { + "id": "MyFunction1", + "path": "test-stack/MyFunction1", + "children": { + "ServiceRole": { + "id": "ServiceRole", + "path": "test-stack/MyFunction1/ServiceRole", + "children": { + "Resource": { + "id": "Resource", + "path": "test-stack/MyFunction1/ServiceRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "managedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnRole", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Role", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "test-stack/MyFunction1/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::Function", + "aws:cdk:cloudformation:props": { + "code": { + "zipFile": "foo" + }, + "role": { + "Fn::GetAtt": [ + "MyFunction1ServiceRole9852B06B", + "Arn" + ] + }, + "handler": "index.handler", + "runtime": "nodejs14.x" + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.CfnFunction", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.Function", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-snapshot-assets-diff.js.snapshot/integ.json b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-snapshot-assets-diff.js.snapshot/integ.json index c602dbd38..a407da109 100644 --- a/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-snapshot-assets-diff.js.snapshot/integ.json +++ b/packages/@aws-cdk/integ-runner/test/test-data/xxxxx.test-with-snapshot-assets-diff.js.snapshot/integ.json @@ -1,7 +1,7 @@ { "version": "v1.0.0", + "enableLookups": true, "testCases": { - "enableLookups": true, "xxxxx.test-with-snapshot-assets-diff": { "stacks": ["test-stack"], "diffAssets": false, diff --git a/packages/@aws-cdk/toolkit-lib/.projen/deps.json b/packages/@aws-cdk/toolkit-lib/.projen/deps.json index 8525a9819..5367aebc6 100644 --- a/packages/@aws-cdk/toolkit-lib/.projen/deps.json +++ b/packages/@aws-cdk/toolkit-lib/.projen/deps.json @@ -66,6 +66,7 @@ }, { "name": "aws-cdk-lib", + "version": "2.203.0", "type": "build" }, { @@ -156,7 +157,7 @@ }, { "name": "typescript", - "version": "5.6", + "version": "5.8", "type": "build" }, { diff --git a/packages/@aws-cdk/toolkit-lib/.projen/tasks.json b/packages/@aws-cdk/toolkit-lib/.projen/tasks.json index 06febfc3d..e38716958 100644 --- a/packages/@aws-cdk/toolkit-lib/.projen/tasks.json +++ b/packages/@aws-cdk/toolkit-lib/.projen/tasks.json @@ -53,7 +53,7 @@ }, "steps": [ { - "exec": "npx npm-check-updates@16 --upgrade --target=minor --peer --no-deprecated --dep=dev,peer,prod,optional --filter=@aws-cdk/aws-service-spec,@cdklabs/eslint-plugin,@jest/environment,@jest/globals,@jest/types,@microsoft/api-extractor,@smithy/util-stream,@types/fs-extra,@types/jest,@types/jest-when,@types/split2,aws-cdk-lib,aws-sdk-client-mock,aws-sdk-client-mock-jest,eslint-config-prettier,eslint-import-resolver-typescript,eslint-plugin-import,eslint-plugin-jest,eslint-plugin-jsdoc,eslint-plugin-prettier,fast-check,jest,jest-environment-node,jest-when,license-checker,ts-jest,xml-js,archiver,cdk-from-cfn,glob,minimatch,semver,split2,uuid" + "exec": "npx npm-check-updates@16 --upgrade --target=minor --peer --no-deprecated --dep=dev,peer,prod,optional --filter=@aws-cdk/aws-service-spec,@cdklabs/eslint-plugin,@jest/environment,@jest/globals,@jest/types,@microsoft/api-extractor,@smithy/util-stream,@types/fs-extra,@types/jest,@types/jest-when,@types/split2,aws-sdk-client-mock,aws-sdk-client-mock-jest,eslint-config-prettier,eslint-import-resolver-typescript,eslint-plugin-import,eslint-plugin-jest,eslint-plugin-jsdoc,eslint-plugin-prettier,fast-check,jest,jest-environment-node,jest-when,license-checker,ts-jest,xml-js,archiver,cdk-from-cfn,glob,minimatch,semver,split2,uuid" } ] }, @@ -92,7 +92,7 @@ "name": "docs", "steps": [ { - "exec": "api-extractor run || true && mkdir -p dist/api-extractor-docs/cdk/api/toolkit-lib && if [ -f dist/toolkit-lib.api.json ]; then cp dist/toolkit-lib.api.json dist/api-extractor-docs/cdk/api/toolkit-lib/; else echo \"Warning: API JSON file not found\"; fi && (cat dist/version.txt 2>/dev/null || echo \"latest\") > dist/api-extractor-docs/cdk/api/toolkit-lib/VERSION && if [ -f README.md ]; then cp README.md dist/api-extractor-docs/cdk/api/toolkit-lib/; fi && if [ -d docs ]; then mkdir -p dist/api-extractor-docs/cdk/api/toolkit-lib/docs && cp -r docs/* dist/api-extractor-docs/cdk/api/toolkit-lib/docs/; fi && if [ -d assets ]; then mkdir -p dist/api-extractor-docs/cdk/api/toolkit-lib/assets && cp -r assets/* dist/api-extractor-docs/cdk/api/toolkit-lib/assets/; fi && cd dist/api-extractor-docs && zip -r -q ../api-extractor-docs.zip cdk" + "exec": "api-extractor run && mkdir -p dist/api-extractor-docs/cdk/api/toolkit-lib && if [ -f dist/toolkit-lib.api.json ]; then cp dist/toolkit-lib.api.json dist/api-extractor-docs/cdk/api/toolkit-lib/; else echo \"Warning: API JSON file not found\"; fi && (cat dist/version.txt 2>/dev/null || echo \"latest\") > dist/api-extractor-docs/cdk/api/toolkit-lib/VERSION && if [ -f README.md ]; then cp README.md dist/api-extractor-docs/cdk/api/toolkit-lib/; fi && if [ -d docs ]; then mkdir -p dist/api-extractor-docs/cdk/api/toolkit-lib/docs && cp -r docs/* dist/api-extractor-docs/cdk/api/toolkit-lib/docs/; fi && if [ -d assets ]; then mkdir -p dist/api-extractor-docs/cdk/api/toolkit-lib/assets && cp -r assets/* dist/api-extractor-docs/cdk/api/toolkit-lib/assets/; fi && cd dist/api-extractor-docs && zip -r -q ../api-extractor-docs.zip cdk" } ] }, diff --git a/packages/@aws-cdk/toolkit-lib/docs/message-registry.md b/packages/@aws-cdk/toolkit-lib/docs/message-registry.md index 66f342305..faf35634d 100644 --- a/packages/@aws-cdk/toolkit-lib/docs/message-registry.md +++ b/packages/@aws-cdk/toolkit-lib/docs/message-registry.md @@ -125,6 +125,7 @@ Please let us know by [opening an issue](https://github.com/aws/aws-cdk-cli/issu | `CDK_TOOLKIT_I7900` | Stack deletion succeeded | `result` | [cxapi.CloudFormationStackArtifact](https://docs.aws.amazon.com/cdk/api/v2/docs/@aws-cdk_cx-api.CloudFormationStackArtifact.html) | | `CDK_TOOLKIT_E7010` | Action was aborted due to negative confirmation of request | `error` | n/a | | `CDK_TOOLKIT_E7900` | Stack deletion failed | `error` | {@link ErrorPayload} | +| `CDK_TOOLKIT_E8900` | Stack refactor failed | `error` | {@link ErrorPayload} | | `CDK_TOOLKIT_I8900` | Refactor result | `result` | {@link RefactorResult} | | `CDK_TOOLKIT_W8010` | Refactor execution not yet supported | `warn` | n/a | | `CDK_TOOLKIT_I9000` | Provides bootstrap times | `info` | {@link Duration} | diff --git a/packages/@aws-cdk/toolkit-lib/lib/actions/diff/index.ts b/packages/@aws-cdk/toolkit-lib/lib/actions/diff/index.ts index 439c5ab9e..9e200d645 100644 --- a/packages/@aws-cdk/toolkit-lib/lib/actions/diff/index.ts +++ b/packages/@aws-cdk/toolkit-lib/lib/actions/diff/index.ts @@ -129,4 +129,12 @@ export interface DiffOptions { * @default 3 */ readonly contextLines?: number; + + /** + * Whether to include resource moves in the diff. These are the same moves that are detected + * by the `refactor` command. + * + * @default false + */ + readonly includeMoves?: boolean; } diff --git a/packages/@aws-cdk/toolkit-lib/lib/actions/diff/private/helpers.ts b/packages/@aws-cdk/toolkit-lib/lib/actions/diff/private/helpers.ts index e790a61d5..1bab05680 100644 --- a/packages/@aws-cdk/toolkit-lib/lib/actions/diff/private/helpers.ts +++ b/packages/@aws-cdk/toolkit-lib/lib/actions/diff/private/helpers.ts @@ -13,6 +13,7 @@ import type { ResourcesToImport } from '../../../api/resource-import'; import { removeNonImportResources, ResourceMigrator } from '../../../api/resource-import'; import { ToolkitError } from '../../../toolkit/toolkit-error'; import { deserializeStructure, formatErrorMessage } from '../../../util'; +import { mappingsByEnvironment } from '../../refactor/private/mapping-helpers'; export function prepareDiff( ioHelper: IoHelper, @@ -67,6 +68,10 @@ async function cfnDiff( const templateInfos = []; const methodOptions = (options.method?.options ?? {}) as ChangeSetDiffOptions; + const allMappings = options.includeMoves + ? await mappingsByEnvironment(stacks.stackArtifacts, sdkProvider, true) + : []; + // Compare N stacks against deployed templates for (const stack of stacks.stackArtifacts) { const templateWithNestedStacks = await deployments.readCurrentTemplateWithNestedStacks( @@ -93,12 +98,17 @@ async function cfnDiff( methodOptions.importExistingResources, ) : undefined; + const mappings = allMappings.find(m => + m.environment.region === stack.environment.region && m.environment.account === stack.environment.account, + )?.mappings ?? {}; + templateInfos.push({ oldTemplate: currentTemplate, newTemplate: stack, isImport: !!resourcesToImport, nestedStacks, changeSet, + mappings, }); } diff --git a/packages/@aws-cdk/toolkit-lib/lib/actions/refactor/index.ts b/packages/@aws-cdk/toolkit-lib/lib/actions/refactor/index.ts index 743ed0618..93ded1a07 100644 --- a/packages/@aws-cdk/toolkit-lib/lib/actions/refactor/index.ts +++ b/packages/@aws-cdk/toolkit-lib/lib/actions/refactor/index.ts @@ -1,66 +1,4 @@ -import type { StackSelector } from '../../api/cloud-assembly'; -import type { ExcludeList } from '../../api/refactoring'; -import { InMemoryExcludeList, NeverExclude } from '../../api/refactoring'; - -type MappingType = 'auto' | 'explicit'; - -/** - * The source of the resource mappings to be used for refactoring. - */ -export class MappingSource { - /** - * The mapping will be automatically generated based on a comparison of - * the deployed stacks and the local stacks. - * - * @param exclude - A list of resource locations to exclude from the mapping. - */ - public static auto(exclude: string[] = []): MappingSource { - const excludeList = new InMemoryExcludeList(exclude); - return new MappingSource('auto', [], excludeList); - } - - /** - * An explicitly provided list of mappings, which will be used for refactoring. - */ - public static explicit(groups: MappingGroup[]): MappingSource { - return new MappingSource('explicit', groups, new NeverExclude()); - } - - /** - * An explicitly provided list of mappings, which will be used for refactoring, - * but in reverse, that is, the source locations will become the destination - * locations and vice versa. - */ - public static reverse(groups: MappingGroup[]): MappingSource { - const reverseGroups = groups.map((group) => ({ - ...group, - resources: Object.fromEntries(Object.entries(group.resources).map(([src, dst]) => [dst, src])), - })); - - return MappingSource.explicit(reverseGroups); - } - - /** - * @internal - */ - public readonly source: MappingType; - - /** - * @internal - */ - public readonly groups: MappingGroup[]; - - /** - * @internal - */ - public readonly exclude: ExcludeList; - - private constructor(source: MappingType, groups: MappingGroup[], exclude: ExcludeList) { - this.source = source; - this.groups = groups; - this.exclude = exclude; - } -} +import type { StackSelector } from '../../api'; export interface RefactorOptions { /** @@ -71,28 +9,33 @@ export interface RefactorOptions { readonly dryRun?: boolean; /** - * Criteria for selecting stacks to deploy - * - * @default - All stacks + * List of overrides to be applied to resolve possible ambiguities in the + * computed list of mappings. + */ + readonly overrides?: MappingGroup[]; + + /** + * Criteria for selecting stacks to compare with the deployed stacks in the + * target environment. */ - stacks?: StackSelector; + readonly stacks?: StackSelector; /** - * How the toolkit should obtain the mappings + * A list of names of additional deployed stacks to be included in the comparison. */ - mappingSource?: MappingSource; + readonly additionalStackNames?: string[]; } export interface MappingGroup { /** * The account ID of the environment in which the mapping is valid. */ - account: string; + readonly account: string; /** * The region of the environment in which the mapping is valid. */ - region: string; + readonly region: string; /** * A collection of resource mappings, where each key is the source location @@ -102,7 +45,7 @@ export interface MappingGroup { * location that is not already occupied by any resource. * */ - resources: { - [key: string]: string; + readonly resources: { + readonly [key: string]: string; }; } diff --git a/packages/@aws-cdk/toolkit-lib/lib/actions/refactor/private/mapping-helpers.ts b/packages/@aws-cdk/toolkit-lib/lib/actions/refactor/private/mapping-helpers.ts new file mode 100644 index 000000000..d1c802a0d --- /dev/null +++ b/packages/@aws-cdk/toolkit-lib/lib/actions/refactor/private/mapping-helpers.ts @@ -0,0 +1,61 @@ +import type * as cxapi from '@aws-cdk/cx-api'; +import type { MappingGroup } from '..'; +import type { SdkProvider } from '../../../api/aws-auth/sdk-provider'; +import { groupStacks, RefactoringContext } from '../../../api/refactoring'; +import { ToolkitError } from '../../../toolkit/toolkit-error'; + +export function parseMappingGroups(s: string) { + const mappingGroups = doParse(); + + // Validate that there are no duplicate destinations. + // By construction, there are no duplicate sources, already. + for (let group of mappingGroups) { + const destinations = new Set(); + + for (const destination of Object.values(group.resources)) { + if (destinations.has(destination)) { + throw new ToolkitError( + `Duplicate destination resource '${destination}' in environment ${group.account}/${group.region}`, + ); + } + destinations.add(destination); + } + } + + return mappingGroups; + + function doParse(): MappingGroup[] { + const content = JSON.parse(s); + if (content.environments || !Array.isArray(content.environments)) { + return content.environments; + } else { + throw new ToolkitError("Expected an 'environments' array"); + } + } +} + +interface EnvironmentSpecificMappings { + readonly environment: cxapi.Environment; + readonly mappings: Record; +} + +export async function mappingsByEnvironment( + stackArtifacts: cxapi.CloudFormationStackArtifact[], + sdkProvider: SdkProvider, + ignoreModifications?: boolean, +): Promise { + const groups = await groupStacks(sdkProvider, stackArtifacts, []); + return groups.map((group) => { + const context = new RefactoringContext({ + ...group, + ignoreModifications, + }); + return { + environment: context.environment, + mappings: Object.fromEntries( + context.mappings.map((m) => [m.source.toLocationString(), m.destination.toLocationString()]), + ), + }; + }); +} + diff --git a/packages/@aws-cdk/toolkit-lib/lib/api/cloud-assembly/private/context-aware-source.ts b/packages/@aws-cdk/toolkit-lib/lib/api/cloud-assembly/private/context-aware-source.ts index fb2e859ae..5195cfb4c 100644 --- a/packages/@aws-cdk/toolkit-lib/lib/api/cloud-assembly/private/context-aware-source.ts +++ b/packages/@aws-cdk/toolkit-lib/lib/api/cloud-assembly/private/context-aware-source.ts @@ -6,6 +6,7 @@ import { IO } from '../../io/private'; import type { IContextStore } from '../context-store'; import type { ICloudAssemblySource, IReadableCloudAssembly } from '../types'; import { missingContextKeys } from './helpers'; +import { equalSets } from '../../../util/sets'; export interface ContextAwareCloudAssemblyProps { /** @@ -114,18 +115,3 @@ export class ContextAwareCloudAssemblySource implements ICloudAssemblySource { } } } - -/** - * Are two sets equal to each other - */ -function equalSets(a: Set, b: Set) { - if (a.size !== b.size) { - return false; - } - for (const x of a) { - if (!b.has(x)) { - return false; - } - } - return true; -} diff --git a/packages/@aws-cdk/toolkit-lib/lib/api/cloud-assembly/private/exec.ts b/packages/@aws-cdk/toolkit-lib/lib/api/cloud-assembly/private/exec.ts index b54b8e925..691689cff 100644 --- a/packages/@aws-cdk/toolkit-lib/lib/api/cloud-assembly/private/exec.ts +++ b/packages/@aws-cdk/toolkit-lib/lib/api/cloud-assembly/private/exec.ts @@ -1,7 +1,7 @@ import * as child_process from 'node:child_process'; // eslint-disable-next-line @typescript-eslint/no-require-imports import split = require('split2'); -import { ToolkitError } from '../../../toolkit/toolkit-error'; +import { AssemblyError } from '../../../toolkit/toolkit-error'; type EventPublisher = (event: 'open' | 'data_stdout' | 'data_stderr' | 'close', line: string) => void; @@ -45,8 +45,14 @@ export async function execInChildProcess(commandAndArgs: string, options: ExecOp return; } }); + + const stderr = new Array(); + proc.stdout.pipe(split()).on('data', (line) => eventPublisher('data_stdout', line)); - proc.stderr.pipe(split()).on('data', (line) => eventPublisher('data_stderr', line)); + proc.stderr.pipe(split()).on('data', (line) => { + stderr.push(line); + return eventPublisher('data_stderr', line); + }); proc.on('error', fail); @@ -54,7 +60,12 @@ export async function execInChildProcess(commandAndArgs: string, options: ExecOp if (code === 0) { return ok(); } else { - return fail(new ToolkitError(`${commandAndArgs}: Subprocess exited with error ${code}`)); + let cause: Error | undefined; + if (stderr.length) { + cause = new Error(stderr.join('\n')); + cause.name = 'ExecutionError'; + } + return fail(AssemblyError.withCause(`${commandAndArgs}: Subprocess exited with error ${code}`, cause)); } }); }); diff --git a/packages/@aws-cdk/toolkit-lib/lib/api/cloud-assembly/private/prepare-source.ts b/packages/@aws-cdk/toolkit-lib/lib/api/cloud-assembly/private/prepare-source.ts index 657ad2da2..9c8c2d178 100644 --- a/packages/@aws-cdk/toolkit-lib/lib/api/cloud-assembly/private/prepare-source.ts +++ b/packages/@aws-cdk/toolkit-lib/lib/api/cloud-assembly/private/prepare-source.ts @@ -15,11 +15,28 @@ import { IO } from '../../io/private'; import type { IReadLock, IWriteLock } from '../../rwlock'; import { RWLock } from '../../rwlock'; import { Settings } from '../../settings'; +import type { ConstructTreeNode } from '../../tree'; import { loadTree, some } from '../../tree'; import type { Context, Env } from '../environment'; import { prepareDefaultEnvironment, spaceAvailableForContext, guessExecutable, synthParametersFromSettings } from '../environment'; import type { AppSynthOptions, LoadAssemblyOptions } from '../source-builder'; +export interface ExecutionEnvironmentOptions { + /** + * The directory the cloud assembly will be written to. + * + * @default - use a temporary directory as output directory, this will be cleaned up when this object is disposed + */ + readonly outdir?: string; + + /** + * Resolve and add environment variables for the app's default environment. + * + * This will make a call to STS, which is not always desirable e.g. if the env is explicitly specified. + */ + readonly resolveDefaultAppEnv: boolean; +} + export class ExecutionEnvironment implements AsyncDisposable { /** * Create an ExecutionEnvironment @@ -33,18 +50,39 @@ export class ExecutionEnvironment implements AsyncDisposable { * If `markSuccessful()` is called, the writer lock is converted to a reader lock * and temporary directories will not be cleaned up anymore. */ - public static async create(services: ToolkitServices, props: { outdir?: string } = {}) { - let tempDir = false; - let dir = props.outdir; + public static async create(services: ToolkitServices, options: ExecutionEnvironmentOptions) { + let outDirIsTemporary = false; + let dir = options.outdir; if (!dir) { - tempDir = true; + outDirIsTemporary = true; dir = fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), 'cdk.out')); } - const lock = await new RWLock(dir).acquireWrite(); - return new ExecutionEnvironment(services, dir, tempDir, lock); + + const opts = { + outdir: dir, + resolveDefaultAppEnv: options.resolveDefaultAppEnv, + }; + + return new ExecutionEnvironment(services, opts, { + lock, + outDirIsTemporary, + }); } + /** + * Should the outdir be disposed of. + */ + public get shouldDisposeOutDir(): boolean { + return this.shouldClean; + } + + /** + * The directory the cloud assembly will be written to. + */ + public readonly outdir: string; + + private readonly options: Required; private readonly ioHelper: IoHelper; private readonly sdkProvider: SdkProvider; private readonly debugFn: (msg: string) => Promise; @@ -53,21 +91,25 @@ export class ExecutionEnvironment implements AsyncDisposable { private constructor( services: ToolkitServices, - public readonly outdir: string, - public readonly outDirIsTemporary: boolean, - lock: IWriteLock, + options: Required, + { lock, outDirIsTemporary }: { + readonly outDirIsTemporary: boolean; + readonly lock: IWriteLock; + }, ) { this.ioHelper = services.ioHelper; this.sdkProvider = services.sdkProvider; this.debugFn = (msg: string) => this.ioHelper.defaults.debug(msg); this.lock = lock; this.shouldClean = outDirIsTemporary; + this.outdir = options.outdir; + this.options = options; } public async [Symbol.asyncDispose]() { await this.lock?.release(); - if (this.shouldClean) { + if (this.shouldDisposeOutDir) { await fs.rm(this.outdir, { recursive: true, force: true }); } } @@ -136,7 +178,7 @@ export class ExecutionEnvironment implements AsyncDisposable { */ public async defaultEnvVars(): Promise { const debugFn = (msg: string) => this.ioHelper.notify(IO.CDK_ASSEMBLY_I0010.msg(msg)); - const env = await prepareDefaultEnvironment(this.sdkProvider, debugFn); + const env = this.options.resolveDefaultAppEnv ? await prepareDefaultEnvironment(this.sdkProvider, debugFn) : {}; env[cxapi.OUTDIR_ENV] = this.outdir; await debugFn(format('outdir:', this.outdir)); @@ -221,20 +263,30 @@ export function writeContextToEnv(env: Env, context: Context, completeness: 'add async function checkContextOverflowSupport(assembly: cxapi.CloudAssembly, ioHelper: IoHelper): Promise { const traceFn = (msg: string) => ioHelper.defaults.trace(msg); const tree = await loadTree(assembly, traceFn); - const frameworkDoesNotSupportContextOverflow = some(tree, node => { - const fqn = node.constructInfo?.fqn; - const version = node.constructInfo?.version; - return (fqn === 'aws-cdk-lib.App' && version != null && lte(version, '2.38.0')) // v2 - || fqn === '@aws-cdk/core.App'; // v1 - }); // We're dealing with an old version of the framework here. It is unaware of the temporary // file, which means that it will ignore the context overflow. - if (frameworkDoesNotSupportContextOverflow) { + if (!frameworkSupportsContextOverflow(tree)) { await ioHelper.notify(IO.CDK_ASSEMBLY_W0010.msg('Part of the context could not be sent to the application. Please update the AWS CDK library to the latest version.')); } } +/** + * Checks if the framework supports context overflow + */ +export function frameworkSupportsContextOverflow(tree: ConstructTreeNode | undefined): boolean { + return !some(tree, node => { + const fqn = node.constructInfo?.fqn; + const version = node.constructInfo?.version; + return ( + fqn === 'aws-cdk-lib.App' // v2 app + && version !== '0.0.0' // ignore developer builds + && version != null && lte(version, '2.38.0') // last version not supporting large context + ) // v2 + || fqn === '@aws-cdk/core.App'; // v1 app => not supported + }); +} + /** * Safely create an assembly from a cloud assembly directory */ diff --git a/packages/@aws-cdk/toolkit-lib/lib/api/cloud-assembly/source-builder.ts b/packages/@aws-cdk/toolkit-lib/lib/api/cloud-assembly/source-builder.ts index 161409b47..eb8a5735d 100644 --- a/packages/@aws-cdk/toolkit-lib/lib/api/cloud-assembly/source-builder.ts +++ b/packages/@aws-cdk/toolkit-lib/lib/api/cloud-assembly/source-builder.ts @@ -118,6 +118,18 @@ export interface AssemblySourceProps { * @default - `true` if `outdir` is not given, `false` otherwise */ readonly disposeOutdir?: boolean; + + /** + * Resolve the current default environment an provide as environment variables to the app. + * + * This will make a (cached) call to STS to resolve the current account using + * base credentials. The behavior is not always desirable and can add + * unnecessary delays, e.g. when an app specifies an environment explicitly + * or when local actions are be performed without internet access. + * + * @default true + */ + readonly resolveDefaultEnvironment?: boolean; } /** @@ -324,7 +336,10 @@ export abstract class CloudAssemblySourceBuilder { return new ContextAwareCloudAssemblySource( { produce: async () => { - await using execution = await ExecutionEnvironment.create(services, { outdir }); + await using execution = await ExecutionEnvironment.create(services, { + outdir, + resolveDefaultAppEnv: props.resolveDefaultEnvironment ?? true, + }); const synthParams = parametersFromSynthOptions(props.synthOptions); @@ -368,7 +383,7 @@ export abstract class CloudAssemblySourceBuilder { : await assemblyFromDirectory(assembly.directory, services.ioHelper, props.loadAssemblyOptions); const success = await execution.markSuccessful(); - const deleteOnDispose = props.disposeOutdir ?? execution.outDirIsTemporary; + const deleteOnDispose = props.disposeOutdir ?? execution.shouldDisposeOutDir; return new ReadableCloudAssembly(asm, success.readLock, { deleteOnDispose }); }, }, @@ -462,19 +477,16 @@ export abstract class CloudAssemblySourceBuilder { return new ContextAwareCloudAssemblySource( { produce: async () => { - // @todo build - // const build = this.props.configuration.settings.get(['build']); - // if (build) { - // await execInChildProcess(build, { cwd: props.workingDirectory }); - // } - try { fs.mkdirpSync(outdir); } catch (e: any) { throw new ToolkitError(`Could not create output directory at '${outdir}' (${e.message}).`); } - await using execution = await ExecutionEnvironment.create(services, { outdir }); + await using execution = await ExecutionEnvironment.create(services, { + outdir, + resolveDefaultAppEnv: props.resolveDefaultEnvironment ?? true, + }); const commandLine = await execution.guessExecutable(app); @@ -521,7 +533,7 @@ export abstract class CloudAssemblySourceBuilder { const asm = await assemblyFromDirectory(outdir, services.ioHelper, props.loadAssemblyOptions); const success = await execution.markSuccessful(); - const deleteOnDispose = props.disposeOutdir ?? execution.outDirIsTemporary; + const deleteOnDispose = props.disposeOutdir ?? execution.shouldDisposeOutDir; return new ReadableCloudAssembly(asm, success.readLock, { deleteOnDispose }); }, }, diff --git a/packages/@aws-cdk/toolkit-lib/lib/api/cloud-assembly/stack-collection.ts b/packages/@aws-cdk/toolkit-lib/lib/api/cloud-assembly/stack-collection.ts index d3d3e58e2..7b383e84a 100644 --- a/packages/@aws-cdk/toolkit-lib/lib/api/cloud-assembly/stack-collection.ts +++ b/packages/@aws-cdk/toolkit-lib/lib/api/cloud-assembly/stack-collection.ts @@ -42,6 +42,7 @@ export class StackCollection { id: stack.displayName ?? stack.id, name: stack.stackName, environment: stack.environment, + metadata: stack.manifest.metadata, dependencies: [], }; diff --git a/packages/@aws-cdk/toolkit-lib/lib/api/diff/diff-formatter.ts b/packages/@aws-cdk/toolkit-lib/lib/api/diff/diff-formatter.ts index efc777ffa..6adc19273 100644 --- a/packages/@aws-cdk/toolkit-lib/lib/api/diff/diff-formatter.ts +++ b/packages/@aws-cdk/toolkit-lib/lib/api/diff/diff-formatter.ts @@ -5,6 +5,7 @@ import { formatSecurityChanges, fullDiff, mangleLikeCloudFormation, + type ResourceDifference, type TemplateDiff, } from '@aws-cdk/cloudformation-diff'; import type * as cxapi from '@aws-cdk/cx-api'; @@ -122,6 +123,14 @@ export interface TemplateInfo { readonly nestedStacks?: { [nestedStackLogicalId: string]: NestedStackTemplates; }; + + /** + * Mappings of old locations to new locations. If these are provided, + * for all resources that were moved, their corresponding addition + * and removal lines will be augmented with the location they were + * moved fom and to, respectively. + */ + readonly mappings?: Record; } /** @@ -134,6 +143,7 @@ export class DiffFormatter { private readonly changeSet?: any; private readonly nestedStacks: { [nestedStackLogicalId: string]: NestedStackTemplates } | undefined; private readonly isImport: boolean; + private readonly mappings: Record; /** * Stores the TemplateDiffs that get calculated in this DiffFormatter, @@ -148,6 +158,7 @@ export class DiffFormatter { this.changeSet = props.templateInfo.changeSet; this.nestedStacks = props.templateInfo.nestedStacks; this.isImport = props.templateInfo.isImport ?? false; + this.mappings = props.templateInfo.mappings ?? {}; } public get diffs() { @@ -159,16 +170,38 @@ export class DiffFormatter { * If it creates the diff, it stores the result in a map for * easier retrieval later. */ - private diff(stackName?: string, oldTemplate?: any) { + private diff(stackName?: string, oldTemplate?: any, mappings: Record = {}) { const realStackName = stackName ?? this.stackName; if (!this._diffs[realStackName]) { - this._diffs[realStackName] = fullDiff( + const templateDiff = fullDiff( oldTemplate ?? this.oldTemplate, this.newTemplate.template, this.changeSet, this.isImport, ); + + const setMove = (change: ResourceDifference, direction: 'from' | 'to', location?: string)=> { + if (location != null) { + const [sourceStackName, sourceLogicalId] = location.split('.'); + change.move = { + direction, + stackName: sourceStackName, + resourceLogicalId: sourceLogicalId, + }; + } + }; + + templateDiff.resources.forEachDifference((id, change) => { + const location = `${realStackName}.${id}`; + if (change.isAddition && Object.values(mappings).includes(location)) { + setMove(change, 'from', Object.keys(mappings).find(k => mappings[k] === location)); + } else if (change.isRemoval && Object.keys(mappings).includes(location)) { + setMove(change, 'to', mappings[location]); + } + }); + + this._diffs[realStackName] = templateDiff; } return this._diffs[realStackName]; } @@ -199,6 +232,7 @@ export class DiffFormatter { this.stackName, this.nestedStacks, options, + this.mappings, ); } @@ -207,8 +241,9 @@ export class DiffFormatter { stackName: string, nestedStackTemplates: { [nestedStackLogicalId: string]: NestedStackTemplates } | undefined, options: ReusableStackDiffOptions, + mappings: Record = {}, ) { - let diff = this.diff(stackName, oldTemplate); + let diff = this.diff(stackName, oldTemplate, mappings); // The stack diff is formatted via `Formatter`, which takes in a stream // and sends its output directly to that stream. To facilitate use of the @@ -279,6 +314,7 @@ export class DiffFormatter { nestedStack.physicalName ?? nestedStackLogicalId, nestedStack.nestedStackTemplates, options, + this.mappings, ); numStacksWithChanges += nextDiff.numStacksWithChanges; formattedDiff += nextDiff.formattedDiff; diff --git a/packages/@aws-cdk/toolkit-lib/lib/api/io/private/messages.ts b/packages/@aws-cdk/toolkit-lib/lib/api/io/private/messages.ts index 105620e1f..9314e8530 100644 --- a/packages/@aws-cdk/toolkit-lib/lib/api/io/private/messages.ts +++ b/packages/@aws-cdk/toolkit-lib/lib/api/io/private/messages.ts @@ -369,6 +369,12 @@ export const IO = { }), // 8. Refactor (8xxx) + CDK_TOOLKIT_E8900: make.error({ + code: 'CDK_TOOLKIT_E8900', + description: 'Stack refactor failed', + interface: 'ErrorPayload', + }), + CDK_TOOLKIT_I8900: make.result({ code: 'CDK_TOOLKIT_I8900', description: 'Refactor result', diff --git a/packages/@aws-cdk/toolkit-lib/lib/api/io/toolkit-action.ts b/packages/@aws-cdk/toolkit-lib/lib/api/io/toolkit-action.ts index 6ad88707f..a5abd05b2 100644 --- a/packages/@aws-cdk/toolkit-lib/lib/api/io/toolkit-action.ts +++ b/packages/@aws-cdk/toolkit-lib/lib/api/io/toolkit-action.ts @@ -18,4 +18,5 @@ export type ToolkitAction = | 'metadata' | 'init' | 'migrate' -| 'refactor'; +| 'refactor' +| 'flags'; diff --git a/packages/@aws-cdk/toolkit-lib/lib/api/refactoring/cloudformation.ts b/packages/@aws-cdk/toolkit-lib/lib/api/refactoring/cloudformation.ts index 5f2c51461..2c06e4e8d 100644 --- a/packages/@aws-cdk/toolkit-lib/lib/api/refactoring/cloudformation.ts +++ b/packages/@aws-cdk/toolkit-lib/lib/api/refactoring/cloudformation.ts @@ -31,8 +31,7 @@ export class ResourceLocation { } public toPath(): string { - const stack = this.stack; - const resource = stack.template.Resources?.[this.logicalResourceId]; + const resource = this.stack.template.Resources?.[this.logicalResourceId]; const result = resource?.Metadata?.['aws:cdk:path']; if (result != null) { @@ -40,7 +39,11 @@ export class ResourceLocation { } // If the path is not available, we can use stack name and logical ID - return `${stack.stackName}.${this.logicalResourceId}`; + return this.toLocationString(); + } + + public toLocationString() { + return `${this.stack.stackName}.${this.logicalResourceId}`; } public getType(): string { diff --git a/packages/@aws-cdk/toolkit-lib/lib/api/refactoring/context.ts b/packages/@aws-cdk/toolkit-lib/lib/api/refactoring/context.ts index 963df434b..5ad66625b 100644 --- a/packages/@aws-cdk/toolkit-lib/lib/api/refactoring/context.ts +++ b/packages/@aws-cdk/toolkit-lib/lib/api/refactoring/context.ts @@ -1,8 +1,10 @@ import type { Environment } from '@aws-cdk/cx-api'; import type { CloudFormationStack } from './cloudformation'; import { ResourceLocation, ResourceMapping } from './cloudformation'; +import type { GraphDirection } from './digest'; import { computeResourceDigests } from './digest'; import { ToolkitError } from '../../toolkit/toolkit-error'; +import { equalSets } from '../../util/sets'; /** * Represents a set of possible moves of a resource from one location @@ -11,12 +13,12 @@ import { ToolkitError } from '../../toolkit/toolkit-error'; */ type ResourceMove = [ResourceLocation[], ResourceLocation[]]; -export interface RefactorManagerOptions { +export interface RefactoringContextOptions { environment: Environment; localStacks: CloudFormationStack[]; deployedStacks: CloudFormationStack[]; - mappings?: ResourceMapping[]; - filteredStacks?: CloudFormationStack[]; + overrides?: ResourceMapping[]; + ignoreModifications?: boolean; } /** @@ -27,22 +29,15 @@ export class RefactoringContext { private readonly ambiguousMoves: ResourceMove[] = []; public readonly environment: Environment; - constructor(props: RefactorManagerOptions) { + constructor(props: RefactoringContextOptions) { this.environment = props.environment; - if (props.mappings != null) { - this._mappings = props.mappings; - } else { - const moves = resourceMoves(props.deployedStacks, props.localStacks); - this.ambiguousMoves = ambiguousMoves(moves); + const moves = resourceMoves(props.deployedStacks, props.localStacks, 'direct', props.ignoreModifications); + const additionalOverrides = structuralOverrides(props.deployedStacks, props.localStacks); + const overrides = (props.overrides ?? []).concat(additionalOverrides); + const [nonAmbiguousMoves, ambiguousMoves] = partitionByAmbiguity(overrides, moves); + this.ambiguousMoves = ambiguousMoves; - if (!this.isAmbiguous) { - this._mappings = resourceMappings(resourceMoves(props.deployedStacks, props.localStacks), props.filteredStacks); - } - } - } - - public get isAmbiguous(): boolean { - return this.ambiguousMoves.length > 0; + this._mappings = resourceMappings(nonAmbiguousMoves); } public get ambiguousPaths(): [string[], string[]][] { @@ -54,24 +49,72 @@ export class RefactoringContext { } public get mappings(): ResourceMapping[] { - if (this.isAmbiguous) { - throw new ToolkitError( - 'Cannot access mappings when there are ambiguous resource moves. Please resolve the ambiguity first.', - ); - } return this._mappings; } } -function resourceMoves(before: CloudFormationStack[], after: CloudFormationStack[]): ResourceMove[] { - return Object.values( - removeUnmovedResources(zip(groupByKey(resourceDigests(before)), groupByKey(resourceDigests(after)))), - ); +/** + * Generates an automatic list of overrides that can be deduced from the structure of the opposite resource graph. + * Suppose we have the following resource graph: + * + * A --> B + * C --> D + * + * such that B and D are identical, but A is different from C. Then digest(B) = digest(D). If both resources are moved, + * we have an ambiguity. But if we reverse the arrows: + * + * A <-- B + * C <-- D + * + * then digest(B) ≠ digest(D), because they now have different dependencies. If we compute the mappings from this + * opposite graph, we can use them as a set of overrides to disambiguate the original moves. + * + */ +function structuralOverrides(deployedStacks: CloudFormationStack[], localStacks: CloudFormationStack[]): ResourceMapping[] { + const moves = resourceMoves(deployedStacks, localStacks, 'opposite', true); + const [nonAmbiguousMoves] = partitionByAmbiguity([], moves); + return resourceMappings(nonAmbiguousMoves); } -function removeUnmovedResources(m: Record): Record { +function resourceMoves( + before: CloudFormationStack[], + after: CloudFormationStack[], + direction: GraphDirection = 'direct', + ignoreModifications: boolean = false): ResourceMove[] { + const digestsBefore = resourceDigests(before, direction); + const digestsAfter = resourceDigests(after, direction); + + const stackNames = (stacks: CloudFormationStack[]) => + stacks + .map((s) => s.stackName) + .sort() + .join(', '); + if (!(ignoreModifications || isomorphic(digestsBefore, digestsAfter))) { + const message = [ + 'A refactor operation cannot add, remove or update resources. Only resource moves and renames are allowed. ', + "Run 'cdk diff' to compare the local templates to the deployed stacks.\n", + `Deployed stacks: ${stackNames(before)}`, + `Local stacks: ${stackNames(after)}`, + ]; + + throw new ToolkitError(message.join('\n')); + } + + return Object.values(removeUnmovedResources(zip(digestsBefore, digestsAfter))); +} + +/** + * Whether two sets of resources have the same elements (uniquely identified by the digest), and + * each element is in the same number of locations. The locations themselves may be different. + */ +function isomorphic(a: Record, b: Record): boolean { + const sameKeys = equalSets(new Set(Object.keys(a)), new Set(Object.keys(b))); + return sameKeys && Object.entries(a).every(([digest, locations]) => locations.length === b[digest].length); +} + +function removeUnmovedResources(moves: Record): Record { const result: Record = {}; - for (const [hash, [before, after]] of Object.entries(m)) { + for (const [hash, [before, after]] of Object.entries(moves)) { const common = before.filter((b) => after.some((a) => a.equalTo(b))); result[hash] = [ before.filter((b) => !common.some((c) => b.equalTo(c))), @@ -109,61 +152,99 @@ function zip( return result; } -function groupByKey(entries: [string, A][]): Record { - const result: Record = {}; - - for (const [hash, location] of entries) { - if (hash in result) { - result[hash].push(location); - } else { - result[hash] = [location]; - } - } - - return result; -} - /** * Computes a list of pairs [digest, location] for each resource in the stack. */ -function resourceDigests(stacks: CloudFormationStack[]): [string, ResourceLocation][] { +function resourceDigests(stacks: CloudFormationStack[], direction: GraphDirection): Record { // index stacks by name const stacksByName = new Map(); for (const stack of stacks) { stacksByName.set(stack.stackName, stack); } - const digests = computeResourceDigests(stacks); + const digests = computeResourceDigests(stacks, direction); - return Object.entries(digests).map(([loc, digest]) => { - const [stackName, logicalId] = loc.split('.'); - const location: ResourceLocation = new ResourceLocation(stacksByName.get(stackName)!, logicalId); - return [digest, location]; - }); + return groupByKey( + Object.entries(digests).map(([loc, digest]) => { + const [stackName, logicalId] = loc.split('.'); + const location: ResourceLocation = new ResourceLocation(stacksByName.get(stackName)!, logicalId); + return [digest, location]; + }), + ); + + function groupByKey(entries: [string, A][]): Record { + const result: Record = {}; + + for (const [key, value] of entries) { + if (key in result) { + result[key].push(value); + } else { + result[key] = [value]; + } + } + + return result; + } } -function ambiguousMoves(movements: ResourceMove[]) { +function isAmbiguousMove(move: ResourceMove): boolean { + const [pre, post] = move; + // A move is considered ambiguous if two conditions are met: // 1. Both sides have at least one element (otherwise, it's just addition or deletion) // 2. At least one side has more than one element - return movements - .filter(([pre, post]) => pre.length > 0 && post.length > 0) - .filter(([pre, post]) => pre.length > 1 || post.length > 1); + return pre.length > 0 && post.length > 0 && (pre.length > 1 || post.length > 1); } -function resourceMappings(movements: ResourceMove[], stacks?: CloudFormationStack[]): ResourceMapping[] { - const stacksPredicate = - stacks == null - ? () => true - : (m: ResourceMapping) => { - // Any movement that involves one of the selected stacks (either moving from or to) - // is considered a candidate for refactoring. - const stackNames = [m.source.stack.stackName, m.destination.stack.stackName]; - return stacks.some((stack) => stackNames.includes(stack.stackName)); - }; - +function resourceMappings(movements: ResourceMove[]): ResourceMapping[] { return movements .filter(([pre, post]) => pre.length === 1 && post.length === 1 && !pre[0].equalTo(post[0])) - .map(([pre, post]) => new ResourceMapping(pre[0], post[0])) - .filter(stacksPredicate); + .map(([pre, post]) => new ResourceMapping(pre[0], post[0])); +} + +/** + * Partitions a list of moves into non-ambiguous and ambiguous moves. + * @param overrides - The list of overrides to disambiguate moves + * @param moves - a pair of lists of moves. First: non-ambiguous, second: ambiguous + */ +function partitionByAmbiguity(overrides: ResourceMapping[], moves: ResourceMove[]): [ResourceMove[], ResourceMove[]] { + const ambiguous: ResourceMove[] = []; + const nonAmbiguous: ResourceMove[] = []; + + for (let move of moves) { + if (!isAmbiguousMove(move)) { + nonAmbiguous.push(move); + } else { + for (const override of overrides) { + const resolvedMove = resolve(override, move); + if (resolvedMove != null) { + nonAmbiguous.push(resolvedMove); + move = remove(override, move); + } + } + // One last chance to be non-ambiguous + if (!isAmbiguousMove(move)) { + nonAmbiguous.push(move); + } else { + ambiguous.push(move); + } + } + } + + function resolve(override: ResourceMapping, move: ResourceMove): ResourceMove | undefined { + const [pre, post] = move; + const source = pre.find((loc) => loc.equalTo(override.source)); + const destination = post.find((loc) => loc.equalTo(override.destination)); + return (source && destination) ? [[source], [destination]] : undefined; + } + + function remove(override: ResourceMapping, move: ResourceMove): ResourceMove { + const [pre, post] = move; + return [ + pre.filter(loc => !loc.equalTo(override.source)), + post.filter(loc => !loc.equalTo(override.destination)), + ]; + } + + return [nonAmbiguous, ambiguous]; } diff --git a/packages/@aws-cdk/toolkit-lib/lib/api/refactoring/digest.ts b/packages/@aws-cdk/toolkit-lib/lib/api/refactoring/digest.ts index fe8072561..cf1d0e4de 100644 --- a/packages/@aws-cdk/toolkit-lib/lib/api/refactoring/digest.ts +++ b/packages/@aws-cdk/toolkit-lib/lib/api/refactoring/digest.ts @@ -1,76 +1,66 @@ import * as crypto from 'node:crypto'; -import { loadResourceModel } from '@aws-cdk/cloudformation-diff/lib/diff/util'; import type { CloudFormationResource, CloudFormationStack } from './cloudformation'; import { ResourceGraph } from './graph'; +export type GraphDirection = + 'direct' // Edge A -> B mean that A depends on B + | 'opposite'; // Edge A -> B mean that B depends on A + /** * Computes the digest for each resource in the template. * * Conceptually, the digest is computed as: * - * d(resource) = hash(type + physicalId) , if physicalId is defined - * = hash(type + properties + dependencies.map(d)) , otherwise - * - * where `hash` is a cryptographic hash function. In other words, if a resource has - * a physical ID, we use the physical ID plus its type to uniquely identify - * that resource. In this case, the digest can be computed from these two fields - * alone. A corollary is that such resources can be renamed and have their - * properties updated at the same time, and still be considered equivalent. + * digest(resource) = hash(type + properties + dependencies.map(d)) * - * Otherwise, the digest is computed from its type, its own properties (that is, - * excluding properties that refer to other resources), and the digests of each of - * its dependencies. + * where `hash` is a cryptographic hash function. In other words, the digest of a + * resource is computed from its type, its own properties (that is, excluding + * properties that refer to other resources), and the digests of each of its + * dependencies. * * The digest of a resource, defined recursively this way, remains stable even if * one or more of its dependencies gets renamed. Since the resources in a * CloudFormation template form a directed acyclic graph, this function is * well-defined. */ -export function computeResourceDigests(stacks: CloudFormationStack[]): Record { +export function computeResourceDigests(stacks: CloudFormationStack[], direction: GraphDirection = 'direct'): Record { const exports: { [p: string]: { stackName: string; value: any } } = Object.fromEntries( stacks.flatMap((s) => Object.values(s.template.Outputs ?? {}) .filter((o) => o.Export != null && typeof o.Export.Name === 'string') - .map((o) => [o.Export.Name, { stackName: s.stackName, value: o.Value }] as [string, { stackName: string; value: any }]), + .map( + (o) => + [o.Export.Name, { stackName: s.stackName, value: o.Value }] as [string, { stackName: string; value: any }], + ), ), ); const resources = Object.fromEntries( - stacks.flatMap((s) => - Object.entries(s.template.Resources ?? {}).map( - ([id, res]) => [`${s.stackName}.${id}`, res] as [string, CloudFormationResource], - ), - ), + stacks.flatMap((s) => { + return Object.entries(s.template.Resources ?? {}) + .filter(([_, res]) => res.Type !== 'AWS::CDK::Metadata') + .map(([id, res]) => [`${s.stackName}.${id}`, res] as [string, CloudFormationResource]); + }), ); - const graph = new ResourceGraph(stacks); - const nodes = graph.sortedNodes; - // 4. Compute digests in sorted order + const graph = direction == 'direct' + ? ResourceGraph.fromStacks(stacks) + : ResourceGraph.fromStacks(stacks).opposite(); + + return computeDigestsInTopologicalOrder(graph, resources, exports); +} + +function computeDigestsInTopologicalOrder( + graph: ResourceGraph, + resources: Record, + exports: Record): Record { + const nodes = graph.sortedNodes.filter(n => resources[n] != null); const result: Record = {}; for (const id of nodes) { const resource = resources[id]; - const resourceProperties = resource.Properties ?? {}; - const model = loadResourceModel(resource.Type); - const identifier = intersection(Object.keys(resourceProperties), model?.primaryIdentifier ?? []); - let toHash: string; - - if (identifier.length === model?.primaryIdentifier?.length) { - // The resource has a physical ID defined, so we can - // use the ID and the type as the identity of the resource. - toHash = - resource.Type + - identifier - .sort() - .map((attr) => JSON.stringify(resourceProperties[attr])) - .join(''); - } else { - // The resource does not have a physical ID defined, so we need to - // compute the digest based on its properties and dependencies. - const depDigests = Array.from(graph.outNeighbors(id)).map((d) => result[d]); - const propertiesHash = hashObject(stripReferences(stripConstructPath(resource), exports)); - toHash = resource.Type + propertiesHash + depDigests.join(''); - } - + const depDigests = Array.from(graph.outNeighbors(id)).map((d) => result[d]); + const propertiesHash = hashObject(stripReferences(stripConstructPath(resource), exports)); + const toHash = resource.Type + propertiesHash + depDigests.join(''); result[id] = crypto.createHash('sha256').update(toHash).digest('hex'); } @@ -146,7 +136,3 @@ function stripConstructPath(resource: any): any { delete copy.Metadata['aws:cdk:path']; return copy; } - -function intersection(a: T[], b: T[]): T[] { - return a.filter((value) => b.includes(value)); -} diff --git a/packages/@aws-cdk/toolkit-lib/lib/api/refactoring/graph.ts b/packages/@aws-cdk/toolkit-lib/lib/api/refactoring/graph.ts index 049699f19..ea18cf8c7 100644 --- a/packages/@aws-cdk/toolkit-lib/lib/api/refactoring/graph.ts +++ b/packages/@aws-cdk/toolkit-lib/lib/api/refactoring/graph.ts @@ -5,10 +5,7 @@ import { ToolkitError } from '../../toolkit/toolkit-error'; * An immutable directed graph of resources from multiple CloudFormation stacks. */ export class ResourceGraph { - private readonly edges: Record> = {}; - private readonly reverseEdges: Record> = {}; - - constructor(stacks: Omit[]) { + public static fromStacks(stacks: Omit[]): ResourceGraph { const exports: { [p: string]: { stackName: string; value: any } } = Object.fromEntries( stacks.flatMap((s) => Object.values(s.template.Outputs ?? {}) @@ -35,9 +32,11 @@ export class ResourceGraph { ); // 1. Build adjacency lists + const edges: Record> = {}; + const reverseEdges: Record> = {}; for (const id of Object.keys(resources)) { - this.edges[id] = new Set(); - this.reverseEdges[id] = new Set(); + edges[id] = new Set(); + reverseEdges[id] = new Set(); } // 2. Detect dependencies by searching for Ref/Fn::GetAtt @@ -84,11 +83,21 @@ export class ResourceGraph { const deps = findDependencies(stackName, res || {}); for (const dep of deps) { if (dep in resources && dep !== id) { - this.edges[id].add(dep); - this.reverseEdges[dep].add(id); + edges[id].add(dep); + reverseEdges[dep].add(id); } } } + + return new ResourceGraph(edges, reverseEdges); + } + + private readonly edges: Record> = {}; + private readonly reverseEdges: Record> = {}; + + private constructor(edges: Record>, reverseEdges: Record>) { + this.edges = edges; + this.reverseEdges = reverseEdges; } /** @@ -129,4 +138,11 @@ export class ResourceGraph { } return Array.from(this.edges[node] || []); } + + /** + * Returns another graph with the same nodes, but with the edges inverted + */ + public opposite(): ResourceGraph { + return new ResourceGraph(this.reverseEdges, this.edges); + } } diff --git a/packages/@aws-cdk/toolkit-lib/lib/api/refactoring/index.ts b/packages/@aws-cdk/toolkit-lib/lib/api/refactoring/index.ts index 179eb8aed..5ed26b49a 100644 --- a/packages/@aws-cdk/toolkit-lib/lib/api/refactoring/index.ts +++ b/packages/@aws-cdk/toolkit-lib/lib/api/refactoring/index.ts @@ -1,32 +1,39 @@ import type { TypedMapping } from '@aws-cdk/cloudformation-diff'; import { formatAmbiguousMappings as fmtAmbiguousMappings, - formatMappingsHeader as fmtMappingsHeader, + formatEnvironmentSectionHeader as fmtEnvironmentSectionHeader, formatTypedMappings as fmtTypedMappings, - formatAmbiguitySectionHeader as fmtAmbiguitySectionHeader, } from '@aws-cdk/cloudformation-diff'; import type * as cxapi from '@aws-cdk/cx-api'; import type { StackSummary } from '@aws-sdk/client-cloudformation'; -import { deserializeStructure } from '../../util'; +import { deserializeStructure, indexBy } from '../../util'; import type { SdkProvider } from '../aws-auth/private'; import { Mode } from '../plugin'; import { StringWriteStream } from '../streams'; import type { CloudFormationStack } from './cloudformation'; import { ResourceLocation, ResourceMapping } from './cloudformation'; +import { hashObject } from './digest'; import type { MappingGroup } from '../../actions'; import { ToolkitError } from '../../toolkit/toolkit-error'; export * from './exclude'; +export * from './context'; + +interface StackGroup { + environment: cxapi.Environment; + localStacks: CloudFormationStack[]; + deployedStacks: CloudFormationStack[]; +} export async function usePrescribedMappings( mappingGroups: MappingGroup[], sdkProvider: SdkProvider, ): Promise { - interface StackGroup extends MappingGroup { + interface MappingGroupWithStacks extends MappingGroup { stacks: CloudFormationStack[]; } - const stackGroups: StackGroup[] = []; + const stackGroups: MappingGroupWithStacks[] = []; for (const group of mappingGroups) { stackGroups.push({ ...group, @@ -135,26 +142,17 @@ export async function getDeployedStacks( return Promise.all(summaries.map(normalize)); } -export function formatMappingsHeader(): string { - return formatToStream(fmtMappingsHeader); +export function formatEnvironmentSectionHeader(environment: cxapi.Environment) { + const env = `aws://${environment.account}/${environment.region}`; + return formatToStream(stream => fmtEnvironmentSectionHeader(stream, env)); } -export function formatTypedMappings(environment: cxapi.Environment, mappings: TypedMapping[]): string { - return formatToStream((stream) => { - const env = `aws://${environment.account}/${environment.region}`; - fmtTypedMappings(stream, mappings, env); - }); +export function formatTypedMappings(mappings: TypedMapping[]): string { + return formatToStream((stream) => fmtTypedMappings(stream, mappings)); } -export function formatAmbiguitySectionHeader(): string { - return formatToStream(fmtAmbiguitySectionHeader); -} - -export function formatAmbiguousMappings(environment: cxapi.Environment, paths: [string[], string[]][]): string { - return formatToStream((stream) => { - const env = `aws://${environment.account}/${environment.region}`; - fmtAmbiguousMappings(stream, paths, env); - }); +export function formatAmbiguousMappings(paths: [string[], string[]][]): string { + return formatToStream((stream) => fmtAmbiguousMappings(stream, paths)); } function formatToStream(cb: (stream: NodeJS.WritableStream) => void): string { @@ -162,3 +160,37 @@ function formatToStream(cb: (stream: NodeJS.WritableStream) => void): string { cb(stream); return stream.toString(); } + +/** + * Returns a list of stack groups, each containing the local stacks and the deployed stacks that match the given patterns. + */ +export async function groupStacks(sdkProvider: SdkProvider, localStacks: CloudFormationStack[], additionalStackNames: string[]) { + const environments: Map = new Map(); + + for (const stack of localStacks) { + const environment = await sdkProvider.resolveEnvironment(stack.environment); + const key = hashObject(environment); + environments.set(key, environment); + } + + const localByEnvironment = await indexBy(localStacks, + async (s) => hashObject(await sdkProvider.resolveEnvironment(s.environment)), + ); + + const groups: StackGroup[] = []; + for (let key of localByEnvironment.keys()) { + const environment = environments.get(key)!; + const allDeployedStacks = await getDeployedStacks(sdkProvider, environment); + const local = localByEnvironment.get(key)!; + const hasLocalCounterpart = (s: CloudFormationStack) => local.some((l) => l.stackName === s.stackName); + const wasExplicitlyProvided = (s: CloudFormationStack) => additionalStackNames.includes(s.stackName); + + groups.push({ + environment, + deployedStacks: allDeployedStacks.filter(s => hasLocalCounterpart(s) || wasExplicitlyProvided(s)), + localStacks: local, + }); + } + + return groups; +} diff --git a/packages/@aws-cdk/toolkit-lib/lib/api/tree.ts b/packages/@aws-cdk/toolkit-lib/lib/api/tree.ts index 14d0c6836..85fa27662 100644 --- a/packages/@aws-cdk/toolkit-lib/lib/api/tree.ts +++ b/packages/@aws-cdk/toolkit-lib/lib/api/tree.ts @@ -36,7 +36,7 @@ export function some(node: ConstructTreeNode | undefined, predicate: (n: Constru } } -export async function loadTree(assembly: CloudAssembly, trace: (msg: string) => Promise): Promise { +export async function loadTree(assembly: CloudAssembly, trace: (msg: string) => Promise): Promise { try { const outdir = assembly.directory; const fileName = assembly.tree()?.file; diff --git a/packages/@aws-cdk/toolkit-lib/lib/payloads/refactor.ts b/packages/@aws-cdk/toolkit-lib/lib/payloads/refactor.ts index 271cbdfec..0d342b302 100644 --- a/packages/@aws-cdk/toolkit-lib/lib/payloads/refactor.ts +++ b/packages/@aws-cdk/toolkit-lib/lib/payloads/refactor.ts @@ -12,5 +12,5 @@ export interface RefactorResult { /** * Ambiguous path correspondences, if any */ - readonly ambiguousPaths?: [string[], string[]][]; + ambiguousPaths?: [string[], string[]][]; } diff --git a/packages/@aws-cdk/toolkit-lib/lib/payloads/stack-details.ts b/packages/@aws-cdk/toolkit-lib/lib/payloads/stack-details.ts index 31d995755..267ce1641 100644 --- a/packages/@aws-cdk/toolkit-lib/lib/payloads/stack-details.ts +++ b/packages/@aws-cdk/toolkit-lib/lib/payloads/stack-details.ts @@ -1,3 +1,4 @@ +import type * as cxschema from '@aws-cdk/cloud-assembly-schema'; import type * as cxapi from '@aws-cdk/cx-api'; /** @@ -15,6 +16,7 @@ export interface StackDetails { id: string; name: string; environment: cxapi.Environment; + metadata?: { [path: string]: cxschema.MetadataEntry[] }; dependencies: StackDependency[]; } diff --git a/packages/@aws-cdk/toolkit-lib/lib/toolkit/toolkit.ts b/packages/@aws-cdk/toolkit-lib/lib/toolkit/toolkit.ts index 7ec6e770c..8d0e1df7b 100644 --- a/packages/@aws-cdk/toolkit-lib/lib/toolkit/toolkit.ts +++ b/packages/@aws-cdk/toolkit-lib/lib/toolkit/toolkit.ts @@ -1,5 +1,7 @@ import '../private/dispose-polyfill'; import * as path from 'node:path'; +import type { FeatureFlagReportProperties } from '@aws-cdk/cloud-assembly-schema'; +import { ArtifactType } from '@aws-cdk/cloud-assembly-schema'; import type { TemplateDiff } from '@aws-cdk/cloudformation-diff'; import * as cxapi from '@aws-cdk/cx-api'; import * as chalk from 'chalk'; @@ -9,7 +11,7 @@ import { NonInteractiveIoHost } from './non-interactive-io-host'; import type { ToolkitServices } from './private'; import { assemblyFromSource } from './private'; import { ToolkitError } from './toolkit-error'; -import type { DeployResult, DestroyResult, RollbackResult } from './types'; +import type { FeatureFlag, DeployResult, DestroyResult, RollbackResult } from './types'; import type { BootstrapEnvironments, BootstrapOptions, @@ -28,8 +30,7 @@ import type { DiffOptions } from '../actions/diff'; import { appendObject, prepareDiff } from '../actions/diff/private'; import type { DriftOptions, DriftResult } from '../actions/drift'; import { type ListOptions } from '../actions/list'; -import type { MappingGroup, RefactorOptions } from '../actions/refactor'; -import { MappingSource } from '../actions/refactor'; +import type { RefactorOptions } from '../actions/refactor'; import { type RollbackOptions } from '../actions/rollback'; import { type SynthOptions } from '../actions/synth'; import type { IWatcher, WatchOptions } from '../actions/watch'; @@ -59,23 +60,20 @@ import { asIoHelper, IO, SPAN, withoutColor, withoutEmojis, withTrimmedWhitespac import { CloudWatchLogEventMonitor, findCloudWatchLogGroups } from '../api/logs-monitor'; import { Mode, PluginHost } from '../api/plugin'; import { - formatAmbiguitySectionHeader, formatAmbiguousMappings, - formatMappingsHeader, + formatEnvironmentSectionHeader, formatTypedMappings, - getDeployedStacks, - ManifestExcludeList, - usePrescribedMappings, + groupStacks, } from '../api/refactoring'; -import type { CloudFormationStack, ResourceMapping } from '../api/refactoring/cloudformation'; +import type { CloudFormationStack } from '../api/refactoring/cloudformation'; +import { ResourceMapping, ResourceLocation } from '../api/refactoring/cloudformation'; import { RefactoringContext } from '../api/refactoring/context'; -import { hashObject } from '../api/refactoring/digest'; import { ResourceMigrator } from '../api/resource-import'; import { tagsForStack } from '../api/tags/private'; import { DEFAULT_TOOLKIT_STACK_NAME } from '../api/toolkit-info'; import type { AssetBuildNode, AssetPublishNode, Concurrency, StackNode } from '../api/work-graph'; import { WorkGraphBuilder } from '../api/work-graph'; -import type { AssemblyData, StackDetails, SuccessfulDeployStackResult } from '../payloads'; +import type { AssemblyData, RefactorResult, StackDetails, SuccessfulDeployStackResult } from '../payloads'; import { PermissionChangeType } from '../payloads'; import { formatErrorMessage, formatTime, obscureTemplate, serializeStructure, validateSnsTopicArn } from '../util'; import { pLimit } from '../util/concurrency'; @@ -142,17 +140,11 @@ export interface ToolkitOptions { readonly unstableFeatures?: Array; } -interface StackGroup { - environment: cxapi.Environment; - localStacks: CloudFormationStack[]; - deployedStacks: CloudFormationStack[]; -} - /** * Names of toolkit features that are still under development, and may change in * the future. */ -export type UnstableFeature = 'refactor'; +export type UnstableFeature = 'refactor' | 'flags'; /** * The AWS CDK Programmatic Toolkit @@ -1062,8 +1054,8 @@ export class Toolkit extends CloudAssemblySourceBuilder { this.requireUnstableFeature('refactor'); const ioHelper = asIoHelper(this.ioHost, 'refactor'); - const assembly = await assemblyFromSource(ioHelper, cx); - return this._refactor(assembly, ioHelper, options); + await using assembly = await assemblyFromSource(ioHelper, cx); + return await this._refactor(assembly, ioHelper, options); } private async _refactor(assembly: StackAssembly, ioHelper: IoHelper, options: RefactorOptions = {}): Promise { @@ -1072,82 +1064,82 @@ export class Toolkit extends CloudAssemblySourceBuilder { } const sdkProvider = await this.sdkProvider('refactor'); - const stacks = await assembly.selectStacksV2(ALL_STACKS); - const mappingSource = options.mappingSource ?? MappingSource.auto(); - const exclude = mappingSource.exclude.union(new ManifestExcludeList(assembly.cloudAssembly.manifest)); - const filteredStacks = await assembly.selectStacksV2(options.stacks ?? ALL_STACKS); - - const refactoringContexts: RefactoringContext[] = []; - for (let { environment, localStacks, deployedStacks } of await groupStacksByEnvironment()) { - refactoringContexts.push(new RefactoringContext({ - environment, - deployedStacks, - localStacks, - filteredStacks: filteredStacks.stackArtifacts, - mappings: await getUserProvidedMappings(environment), - })); - } + const selectedStacks = await assembly.selectStacksV2(options.stacks ?? ALL_STACKS); + const groups = await groupStacks(sdkProvider, selectedStacks.stackArtifacts, options.additionalStackNames ?? []); - const nonAmbiguousContexts = refactoringContexts.filter(c => !c.isAmbiguous); - if (nonAmbiguousContexts.length > 0) { - await ioHelper.notify(IO.CDK_TOOLKIT_I8900.msg(formatMappingsHeader(), {})); - } - for (const context of nonAmbiguousContexts) { - const mappings = context.mappings.filter((m) => !exclude.isExcluded(m.destination)); - const typedMappings = mappings.map(m => m.toTypedMapping()); - const environment = context.environment; - await ioHelper.notify(IO.CDK_TOOLKIT_I8900.msg(formatTypedMappings(environment, typedMappings), { - typedMappings, - })); - } + for (let { environment, localStacks, deployedStacks } of groups) { + await ioHelper.defaults.info(formatEnvironmentSectionHeader(environment)); - const ambiguousContexts = refactoringContexts.filter(c => c.isAmbiguous); - if (ambiguousContexts.length > 0) { - await ioHelper.notify(IO.CDK_TOOLKIT_I8900.msg(formatAmbiguitySectionHeader(), {})); - } - for (const context of ambiguousContexts) { - const paths = context.ambiguousPaths; - const environment = context.environment; - await ioHelper.notify(IO.CDK_TOOLKIT_I8900.msg(formatAmbiguousMappings(environment, paths), { - ambiguousPaths: paths, - })); - } + try { + const context = new RefactoringContext({ + environment, + deployedStacks, + localStacks, + overrides: getOverrides(environment, deployedStacks, localStacks), + }); - async function groupStacksByEnvironment(): Promise { - const stackGroups: Map = new Map(); - const environments: Map = new Map(); + const mappings = context.mappings; - for (const stack of stacks.stackArtifacts) { - const environment = await sdkProvider.resolveEnvironment(stack.environment); - const key = hashObject(environment); - environments.set(key, environment); - if (stackGroups.has(key)) { - stackGroups.get(key)![1].push(stack); - } else { - // The first time we see an environment, we need to fetch all stacks deployed to it. - const before = await getDeployedStacks(sdkProvider, environment); - stackGroups.set(key, [before, [stack]]); + if (mappings.length === 0 && context.ambiguousPaths.length === 0) { + await ioHelper.defaults.info('Nothing to refactor.'); + continue; } + + const typedMappings = mappings + .map(m => m.toTypedMapping()) + .filter(m => m.type !== 'AWS::CDK::Metadata'); + + let refactorMessage = formatTypedMappings(typedMappings); + const refactorResult: RefactorResult = { typedMappings }; + + if (context.ambiguousPaths.length > 0) { + const paths = context.ambiguousPaths; + refactorMessage += '\n' + formatAmbiguousMappings(paths); + refactorResult.ambiguousPaths = paths; + } + + await ioHelper.notify(IO.CDK_TOOLKIT_I8900.msg(refactorMessage, refactorResult)); + } catch (e: any) { + await ioHelper.notify(IO.CDK_TOOLKIT_E8900.msg(e.message, { error: e })); } + } - const result: StackGroup[] = []; - for (const [hash, [deployedStacks, localStacks]] of stackGroups) { - result.push({ - environment: environments.get(hash)!, - localStacks, - deployedStacks, + function getOverrides(environment: cxapi.Environment, deployedStacks: CloudFormationStack[], localStacks: CloudFormationStack[]) { + const mappingGroup = options.overrides + ?.find(g => g.region === environment.region && g.account === environment.account); + + let overrides: ResourceMapping[] = []; + if (mappingGroup != null) { + overrides = Object.entries(mappingGroup.resources ?? {}).map(([source, destination]) => { + const sourceStack = findStack(source, deployedStacks); + const sourceLogicalId = source.split('.')[1]; + + const destinationStack = findStack(destination, localStacks); + const destinationLogicalId = destination.split('.')[1]; + + return new ResourceMapping( + new ResourceLocation(sourceStack, sourceLogicalId), + new ResourceLocation(destinationStack, destinationLogicalId), + ); }); } - return result; - } - async function getUserProvidedMappings(environment: cxapi.Environment): Promise { - return mappingSource.source == 'explicit' - ? usePrescribedMappings(mappingSource.groups.filter(matchesEnvironment), sdkProvider) - : undefined; + return overrides; + + function findStack(location: string, stacks: CloudFormationStack[]): CloudFormationStack { + const result = stacks.find(stack => { + const [stackName, logicalId] = location.split('.'); + if (stackName == null || logicalId == null) { + throw new ToolkitError(`Invalid location '${location}'`); + } + return stack.stackName === stackName && stack.template.Resources?.[logicalId] != null; + }); + + if (result == null) { + throw new ToolkitError(`Cannot find resource in location ${location}`); + } - function matchesEnvironment(g: MappingGroup): boolean { - return g.account === environment.account && g.region === environment.region; + return result; } } } @@ -1281,6 +1273,33 @@ export class Toolkit extends CloudAssemblySourceBuilder { } } + /** + * Retrieve feature flag information from the cloud assembly + */ + + public async flags(cx: ICloudAssemblySource): Promise { + this.requireUnstableFeature('flags'); + + const ioHelper = asIoHelper(this.ioHost, 'flags'); + await using assembly = await assemblyFromSource(ioHelper, cx); + const artifacts = assembly.cloudAssembly.manifest.artifacts; + + return Object.values(artifacts!) + .filter(a => a.type === ArtifactType.FEATURE_FLAG_REPORT) + .flatMap(report => { + const properties = report.properties as FeatureFlagReportProperties; + const moduleName = properties.module; + + return Object.entries(properties.flags).map(([flagName, flagInfo]) => ({ + module: moduleName, + name: flagName, + recommendedValue: flagInfo.recommendedValue, + userValue: flagInfo.userValue ?? undefined, + explanation: flagInfo.explanation ?? '', + })); + }); + } + private requireUnstableFeature(requestedFeature: UnstableFeature) { if (!this.unstableFeatures.includes(requestedFeature)) { throw new ToolkitError(`Unstable feature '${requestedFeature}' is not enabled. Please enable it under 'unstableFeatures'`); diff --git a/packages/@aws-cdk/toolkit-lib/lib/toolkit/types.ts b/packages/@aws-cdk/toolkit-lib/lib/toolkit/types.ts index afd698367..3c354c807 100644 --- a/packages/@aws-cdk/toolkit-lib/lib/toolkit/types.ts +++ b/packages/@aws-cdk/toolkit-lib/lib/toolkit/types.ts @@ -116,3 +116,11 @@ export interface RolledBackStack extends PhysicalStack { } export type StackRollbackResult = 'rolled-back' | 'already-stable'; + +export interface FeatureFlag { + readonly module: string; + readonly name: string; + readonly recommendedValue: unknown; + readonly userValue?: unknown; + readonly explanation?: string; +} diff --git a/packages/@aws-cdk/toolkit-lib/lib/util/arrays.ts b/packages/@aws-cdk/toolkit-lib/lib/util/arrays.ts index 516466cd1..8a55995ca 100644 --- a/packages/@aws-cdk/toolkit-lib/lib/util/arrays.ts +++ b/packages/@aws-cdk/toolkit-lib/lib/util/arrays.ts @@ -29,3 +29,18 @@ export function partition(collection: T[], pred: (x: T) => boolean): T[] { } return ret; } + +export async function indexBy(xs: A[], fn: (a: A) => Promise): Promise> { + const ret = new Map(); + for (const x of xs) { + const key = await fn(x); + const group = ret.get(key); + if (group) { + group.push(x); + } else { + ret.set(key, [x]); + } + } + return ret; +} + diff --git a/packages/@aws-cdk/toolkit-lib/lib/util/sets.ts b/packages/@aws-cdk/toolkit-lib/lib/util/sets.ts new file mode 100644 index 000000000..73c773ca9 --- /dev/null +++ b/packages/@aws-cdk/toolkit-lib/lib/util/sets.ts @@ -0,0 +1,14 @@ +/** + * Are two sets equal to each other + */ +export function equalSets(a: Set, b: Set) { + if (a.size !== b.size) { + return false; + } + for (const x of a) { + if (!b.has(x)) { + return false; + } + } + return true; +} diff --git a/packages/@aws-cdk/toolkit-lib/package.json b/packages/@aws-cdk/toolkit-lib/package.json index f4fe81445..abd45fe7e 100644 --- a/packages/@aws-cdk/toolkit-lib/package.json +++ b/packages/@aws-cdk/toolkit-lib/package.json @@ -34,14 +34,14 @@ "organization": true }, "devDependencies": { - "@aws-cdk/aws-service-spec": "^0.1.84", + "@aws-cdk/aws-service-spec": "^0.1.86", "@aws-cdk/cli-plugin-contract": "^0.0.0", "@cdklabs/eslint-plugin": "^1.3.2", "@jest/environment": "^29.7.0", "@jest/globals": "^29.7.0", "@jest/types": "^29.6.3", "@microsoft/api-extractor": "^7.52.8", - "@smithy/util-stream": "^4.2.2", + "@smithy/util-stream": "^4.2.3", "@stylistic/eslint-plugin": "^3", "@types/fs-extra": "^11.0.4", "@types/jest": "^29.5.14", @@ -50,7 +50,7 @@ "@types/split2": "^4.2.3", "@typescript-eslint/eslint-plugin": "^8", "@typescript-eslint/parser": "^8", - "aws-cdk-lib": "^2.202.0", + "aws-cdk-lib": "2.203.0", "aws-sdk-client-mock": "^4.1.0", "aws-sdk-client-mock-jest": "^4.1.0", "commit-and-tag-version": "^12", @@ -62,7 +62,7 @@ "eslint-plugin-jest": "^28.14.0", "eslint-plugin-jsdoc": "^50.8.0", "eslint-plugin-prettier": "^5.5.1", - "fast-check": "^4.1.1", + "fast-check": "^4.2.0", "jest": "^29.7.0", "jest-environment-node": "^29.7.0", "jest-junit": "^16", @@ -71,7 +71,7 @@ "nock": "13", "prettier": "^2.8", "ts-jest": "^29.4.0", - "typescript": "5.6", + "typescript": "5.8", "xml-js": "^1.6.11" }, "peerDependencies": { @@ -109,7 +109,7 @@ "@smithy/util-retry": "^4", "@smithy/util-waiter": "^4", "archiver": "^7.0.1", - "cdk-from-cfn": "^0.226.0", + "cdk-from-cfn": "^0.230.0", "chalk": "^4", "chokidar": "^3", "fs-extra": "^9", diff --git a/packages/@aws-cdk/toolkit-lib/test/_fixtures/stack-with-two-buckets/index.ts b/packages/@aws-cdk/toolkit-lib/test/_fixtures/stack-with-two-buckets/index.ts new file mode 100644 index 000000000..ca75970c9 --- /dev/null +++ b/packages/@aws-cdk/toolkit-lib/test/_fixtures/stack-with-two-buckets/index.ts @@ -0,0 +1,14 @@ +import * as s3 from 'aws-cdk-lib/aws-s3'; +import * as core from 'aws-cdk-lib/core'; + +export default async () => { + const app = new core.App({ autoSynth: false }); + const stack = new core.Stack(app, 'Stack1', { + env: { + account: '123456789012', region: 'us-east-1', + }, + }); + new s3.Bucket(stack, 'MyBucket1'); + new s3.Bucket(stack, 'MyBucket2'); + return app.synth(); +}; diff --git a/packages/@aws-cdk/toolkit-lib/test/_helpers/jest-custom-matchers.ts b/packages/@aws-cdk/toolkit-lib/test/_helpers/jest-custom-matchers.ts index af17871ff..38c52e2ee 100644 --- a/packages/@aws-cdk/toolkit-lib/test/_helpers/jest-custom-matchers.ts +++ b/packages/@aws-cdk/toolkit-lib/test/_helpers/jest-custom-matchers.ts @@ -1,4 +1,4 @@ -import * as assert from 'assert'; +import { strict as assert } from 'node:assert'; type TestableError = string | RegExp | Error; diff --git a/packages/@aws-cdk/toolkit-lib/test/actions/diff.test.ts b/packages/@aws-cdk/toolkit-lib/test/actions/diff.test.ts index 4634fa2fc..1662b5812 100644 --- a/packages/@aws-cdk/toolkit-lib/test/actions/diff.test.ts +++ b/packages/@aws-cdk/toolkit-lib/test/actions/diff.test.ts @@ -1,4 +1,5 @@ import * as path from 'path'; +import { GetTemplateCommand, ListStacksCommand } from '@aws-sdk/client-cloudformation'; import * as chalk from 'chalk'; import { DiffMethod } from '../../lib/actions/diff'; import * as awsauth from '../../lib/api/aws-auth/private'; @@ -7,7 +8,7 @@ import * as deployments from '../../lib/api/deployments'; import * as cfnApi from '../../lib/api/deployments/cfn-api'; import { Toolkit } from '../../lib/toolkit'; import { builderFixture, disposableCloudAssemblySource, TestIoHost } from '../_helpers'; -import { MockSdk, restoreSdkMocksToDefault, setDefaultSTSMocks } from '../_helpers/mock-sdk'; +import { mockCloudFormationClient, MockSdk, restoreSdkMocksToDefault, setDefaultSTSMocks } from '../_helpers/mock-sdk'; let ioHost: TestIoHost; let toolkit: Toolkit; @@ -87,6 +88,78 @@ describe('diff', () => { })); }); + const resources = { + OldLogicalID: { + Type: 'AWS::S3::Bucket', + UpdateReplacePolicy: 'Retain', + DeletionPolicy: 'Retain', + Metadata: { 'aws:cdk:path': 'Stack1/OldLogicalID/Resource' }, + }, + }; + + test('returns diff augmented with moves', async () => { + // GIVEN + mockCloudFormationClient.on(ListStacksCommand).resolves({ + StackSummaries: [ + { + StackName: 'Stack1', + StackId: 'arn:aws:cloudformation:us-east-1:999999999999:stack/Stack1', + StackStatus: 'CREATE_COMPLETE', + CreationTime: new Date(), + }, + ], + }); + + jest.spyOn(deployments.Deployments.prototype, 'readCurrentTemplateWithNestedStacks').mockResolvedValue({ + deployedRootTemplate: { + Parameters: {}, + resources, + }, + nestedStacks: [] as any, + }); + + mockCloudFormationClient + .on(GetTemplateCommand, { + StackName: 'Stack1', + }) + .resolves({ + TemplateBody: JSON.stringify({ + Resources: resources, + }), + }); + + // WHEN + const cx = await builderFixture(toolkit, 'stack-with-bucket'); + const result = await toolkit.diff(cx, { + stacks: { strategy: StackSelectionStrategy.ALL_STACKS }, + includeMoves: true, + }); + + // THEN + expect(result.Stack1).toMatchObject(expect.objectContaining({ + resources: { + diffs: expect.objectContaining({ + MyBucketF68F3FF0: expect.objectContaining({ + isAddition: true, + isRemoval: false, + oldValue: undefined, + move: { + direction: 'from', + resourceLogicalId: 'OldLogicalID', + stackName: 'Stack1', + }, + newValue: { + Type: 'AWS::S3::Bucket', + UpdateReplacePolicy: 'Retain', + DeletionPolicy: 'Retain', + Metadata: { 'aws:cdk:path': 'Stack1/MyBucket/Resource' }, + }, + }), + }), + }, + })); + }); + test('returns multiple template diffs', async () => { // WHEN const cx = await builderFixture(toolkit, 'two-different-stacks'); diff --git a/packages/@aws-cdk/toolkit-lib/test/actions/list.test.ts b/packages/@aws-cdk/toolkit-lib/test/actions/list.test.ts index 06d80b495..cd8855d9c 100644 --- a/packages/@aws-cdk/toolkit-lib/test/actions/list.test.ts +++ b/packages/@aws-cdk/toolkit-lib/test/actions/list.test.ts @@ -95,6 +95,7 @@ describe('list', () => { region: 'bermuda-triangle-1', name: 'aws://123456789012/bermuda-triangle-1', }, + metadata: MOCK_STACK_A.metadata, dependencies: [], }, { @@ -105,6 +106,7 @@ describe('list', () => { region: 'bermuda-triangle-1', name: 'aws://123456789012/bermuda-triangle-1', }, + metadata: MOCK_STACK_B.metadata, dependencies: [], }]; expect(ioHost.notifySpy).toHaveBeenCalledWith(expect.objectContaining({ @@ -141,6 +143,7 @@ describe('list', () => { region: 'bermuda-triangle-1', name: 'aws://123456789012/bermuda-triangle-1', }, + metadata: MOCK_STACK_A.metadata, dependencies: [], }, { @@ -151,6 +154,7 @@ describe('list', () => { region: 'bermuda-triangle-1', name: 'aws://123456789012/bermuda-triangle-1', }, + metadata: MOCK_STACK_B.metadata, dependencies: [{ id: 'Test-Stack-A', dependencies: [], @@ -193,6 +197,7 @@ describe('list', () => { region: 'bermuda-triangle-1', name: 'aws://123456789012/bermuda-triangle-1', }, + metadata: MOCK_STACK_A.metadata, dependencies: [], }, { @@ -203,6 +208,7 @@ describe('list', () => { region: 'bermuda-triangle-1', name: 'aws://123456789012/bermuda-triangle-1', }, + metadata: MOCK_STACK_B.metadata, dependencies: [{ id: 'Test-Stack-A', dependencies: [], @@ -251,6 +257,7 @@ describe('list', () => { region: 'bermuda-triangle-1', name: 'aws://123456789012/bermuda-triangle-1', }, + metadata: MOCK_STACK_A.metadata, dependencies: [], }, { @@ -261,6 +268,7 @@ describe('list', () => { region: 'bermuda-triangle-1', name: 'aws://123456789012/bermuda-triangle-1', }, + metadata: MOCK_STACK_B.metadata, dependencies: [{ id: 'Test-Stack-A', dependencies: [], @@ -274,6 +282,7 @@ describe('list', () => { region: 'bermuda-triangle-1', name: 'aws://123456789012/bermuda-triangle-1', }, + metadata: MOCK_STACK_C.metadata, dependencies: [{ id: 'Test-Stack-A/Test-Stack-B', dependencies: [{ @@ -324,6 +333,7 @@ describe('list', () => { region: 'bermuda-triangle-1', name: 'aws://123456789012/bermuda-triangle-1', }, + metadata: MOCK_STACK_A.metadata, dependencies: [], }, { @@ -334,6 +344,7 @@ describe('list', () => { region: 'bermuda-triangle-1', name: 'aws://123456789012/bermuda-triangle-1', }, + metadata: MOCK_STACK_B.metadata, dependencies: [{ id: 'Test-Stack-A', dependencies: [], @@ -347,6 +358,7 @@ describe('list', () => { region: 'bermuda-triangle-1', name: 'aws://123456789012/bermuda-triangle-1', }, + metadata: MOCK_STACK_C.metadata, dependencies: [{ id: 'Test-Stack-B', dependencies: [{ @@ -411,6 +423,7 @@ describe('list', () => { region: 'bermuda-triangle-1', name: 'aws://123456789012/bermuda-triangle-1', }, + metadata: MOCK_STACK_C.metadata, dependencies: [], }, { @@ -421,6 +434,7 @@ describe('list', () => { region: 'bermuda-triangle-1', name: 'aws://123456789012/bermuda-triangle-1', }, + metadata: MOCK_STACK_A.metadata, dependencies: [{ id: 'Test-Stack-C', dependencies: [], diff --git a/packages/@aws-cdk/toolkit-lib/test/actions/refactor.test.ts b/packages/@aws-cdk/toolkit-lib/test/actions/refactor.test.ts index 50a0b54cd..01b99a1ce 100644 --- a/packages/@aws-cdk/toolkit-lib/test/actions/refactor.test.ts +++ b/packages/@aws-cdk/toolkit-lib/test/actions/refactor.test.ts @@ -1,5 +1,5 @@ import { GetTemplateCommand, ListStacksCommand } from '@aws-sdk/client-cloudformation'; -import { MappingSource, StackSelectionStrategy, Toolkit } from '../../lib'; +import { type RefactorOptions, StackSelectionStrategy, Toolkit } from '../../lib'; import { SdkProvider } from '../../lib/api/aws-auth/private'; import { builderFixture, TestIoHost } from '../_helpers'; import { mockCloudFormationClient, MockSdk } from '../_helpers/mock-sdk'; @@ -86,8 +86,10 @@ test('detects the same resource in different locations', async () => { ); }); -test('detects ambiguous mappings', async () => { +test('includes additional stacks in the comparison if provided', async () => { // GIVEN + // Deployed: Stack1, Stack2, CDKToolkit + // Local: Stack1 mockCloudFormationClient.on(ListStacksCommand).resolves({ StackSummaries: [ { @@ -96,6 +98,18 @@ test('detects ambiguous mappings', async () => { StackStatus: 'CREATE_COMPLETE', CreationTime: new Date(), }, + { + StackName: 'Stack2', + StackId: 'arn:aws:cloudformation:us-east-1:999999999999:stack/Stack2', + StackStatus: 'CREATE_COMPLETE', + CreationTime: new Date(), + }, + { + StackName: 'CDKToolkit', + StackId: 'arn:aws:cloudformation:us-east-1:999999999999:stack/CDKToolkit', + StackStatus: 'CREATE_COMPLETE', + CreationTime: new Date(), + }, ], }); @@ -106,68 +120,96 @@ test('detects ambiguous mappings', async () => { .resolves({ TemplateBody: JSON.stringify({ Resources: { - CatPhotos: { + OldLogicalID: { Type: 'AWS::S3::Bucket', UpdateReplacePolicy: 'Retain', DeletionPolicy: 'Retain', Metadata: { - 'aws:cdk:path': 'Stack1/CatPhotos/Resource', + 'aws:cdk:path': 'Stack1/OldLogicalID/Resource', }, }, - DogPhotos: { - Type: 'AWS::S3::Bucket', - UpdateReplacePolicy: 'Retain', - DeletionPolicy: 'Retain', + }, + }), + }); + + mockCloudFormationClient + .on(GetTemplateCommand, { + StackName: 'Stack2', + }) + .resolves({ + TemplateBody: JSON.stringify({ + Resources: { + Queue: { + Type: 'AWS::SQS::Queue', + UpdateReplacePolicy: 'Delete', + DeletionPolicy: 'Delete', Metadata: { - 'aws:cdk:path': 'Stack1/DogPhotos/Resource', + 'aws:cdk:path': 'Stack2/Queue/Resource', }, }, }, }), }); - // WHEN - const cx = await builderFixture(toolkit, 'stack-with-bucket'); - await toolkit.refactor(cx, { - dryRun: true, - }); + mockCloudFormationClient + .on(GetTemplateCommand, { + StackName: 'CDKToolkit', + }) + .resolves({ + TemplateBody: JSON.stringify({ + Resources: { + CdkBootstrapVersion: { + Type: 'AWS::SSM::Parameter', + Properties: { + Type: 'String', + Name: { + 'Fn::Sub': '/cdk-bootstrap/${Qualifier}/version', + }, + Value: '1', + }, + }, + }, + }), + }); - // THEN - expect(ioHost.notifySpy).toHaveBeenCalledWith( - expect.objectContaining({ + await expectRefactorBehavior('stack-with-bucket', + { + dryRun: true, + // We are not passing any filter, which means that only deployed Stack1 will be + // compared to local Stack1. + }, + { action: 'refactor', level: 'result', code: 'CDK_TOOLKIT_I8900', - /* - ┌───┬───────────────────────────┐ - │ │ Resource │ - ├───┼───────────────────────────┤ - │ - │ Stack1/CatPhotos/Resource │ - │ │ Stack1/DogPhotos/Resource │ - ├───┼───────────────────────────┤ - │ + │ Stack1/Bucket/Resource │ - └───┴───────────────────────────┘ - */ - message: expect.stringMatching( - /-.*Stack1\/CatPhotos\/Resource.*\s+.*Stack1\/DogPhotos\/Resource.*\s+.*\s+.*\+.*Stack1\/MyBucket\/Resource/gm, - ), - data: { - ambiguousPaths: [[['Stack1/CatPhotos/Resource', 'Stack1/DogPhotos/Resource'], ['Stack1/MyBucket/Resource']]], - }, - }), + data: expect.objectContaining({ + typedMappings: [ + { + sourcePath: 'Stack1/OldLogicalID/Resource', + destinationPath: 'Stack1/MyBucket/Resource', + type: 'AWS::S3::Bucket', + }, + ], + }), + }, ); -}); -test('fails when dry-run is false', async () => { - const cx = await builderFixture(toolkit, 'stack-with-bucket'); - await expect( - toolkit.refactor(cx, { - dryRun: false, - }), - ).rejects.toThrow('Refactor is not available yet. Too see the proposed changes, use the --dry-run flag.'); + await expectRefactorBehavior('stack-with-bucket', + { + dryRun: true, + // If we include Stack2, the two resource graphs will now be different, and we'll get an error + additionalStackNames: ['Stack2'], + }, + { + action: 'refactor', + level: 'error', + code: 'CDK_TOOLKIT_E8900', + message: expect.stringMatching(/A refactor operation cannot add, remove or update resources/), + }, + ); }); -test('filters stacks when stack selector is passed', async () => { +test('detects ambiguous mappings', async () => { // GIVEN mockCloudFormationClient.on(ListStacksCommand).resolves({ StackSummaries: [ @@ -177,12 +219,6 @@ test('filters stacks when stack selector is passed', async () => { StackStatus: 'CREATE_COMPLETE', CreationTime: new Date(), }, - { - StackName: 'Stack2', - StackId: 'arn:aws:cloudformation:us-east-1:999999999999:stack/Stack2', - StackStatus: 'CREATE_COMPLETE', - CreationTime: new Date(), - }, ], }); @@ -193,29 +229,21 @@ test('filters stacks when stack selector is passed', async () => { .resolves({ TemplateBody: JSON.stringify({ Resources: { - OldBucketName: { + // These two buckets were replaced with two other buckets + CatPhotos: { Type: 'AWS::S3::Bucket', UpdateReplacePolicy: 'Retain', DeletionPolicy: 'Retain', Metadata: { - 'aws:cdk:path': 'Stack1/OldBucketName/Resource', + 'aws:cdk:path': 'Stack1/CatPhotos/Resource', }, }, - }, - }), - }) - .on(GetTemplateCommand, { - StackName: 'Stack2', - }) - .resolves({ - TemplateBody: JSON.stringify({ - Resources: { - OldQueueName: { - Type: 'AWS::SQS::Queue', - UpdateReplacePolicy: 'Delete', - DeletionPolicy: 'Delete', + DogPhotos: { + Type: 'AWS::S3::Bucket', + UpdateReplacePolicy: 'Retain', + DeletionPolicy: 'Retain', Metadata: { - 'aws:cdk:path': 'Stack2/OldQueueName/Resource', + 'aws:cdk:path': 'Stack1/DogPhotos/Resource', }, }, }, @@ -223,43 +251,45 @@ test('filters stacks when stack selector is passed', async () => { }); // WHEN - const cx = await builderFixture(toolkit, 'two-different-stacks'); + const cx = await builderFixture(toolkit, 'stack-with-two-buckets'); await toolkit.refactor(cx, { dryRun: true, - stacks: { - strategy: StackSelectionStrategy.PATTERN_MATCH, - patterns: ['Stack1'], - }, }); - // Resources were renamed in both stacks, but we are only including Stack1. - // So expect to see only changes for Stack1. + // THEN expect(ioHost.notifySpy).toHaveBeenCalledWith( expect.objectContaining({ action: 'refactor', level: 'result', code: 'CDK_TOOLKIT_I8900', - message: expect.stringMatching(/AWS::S3::Bucket.*Stack1\/OldBucketName\/Resource.*Stack1\/MyBucket\/Resource/), - data: expect.objectContaining({ - typedMappings: [ - { - sourcePath: 'Stack1/OldBucketName/Resource', - destinationPath: 'Stack1/MyBucket/Resource', - type: 'AWS::S3::Bucket', - }, + /* + ┌───┬───────────────────────────┐ + │ │ Resource │ + ├───┼───────────────────────────┤ + │ - │ Stack1/CatPhotos/Resource │ + │ │ Stack1/DogPhotos/Resource │ + ├───┼───────────────────────────┤ + │ + │ Stack1/MyBucket1/Resource │ + │ │ Stack1/MyBucket2/Resource │ + └───┴───────────────────────────┘ + */ + message: expect.stringMatching( + /-.*Stack1\/CatPhotos\/Resource.*\s+.*Stack1\/DogPhotos\/Resource.*\s+.*\s+.*\+.*Stack1\/MyBucket1\/Resource.*\s+.*Stack1\/MyBucket2\/Resource/gm, + ), + data: { + ambiguousPaths: [ + [ + ['Stack1/CatPhotos/Resource', 'Stack1/DogPhotos/Resource'], + ['Stack1/MyBucket1/Resource', 'Stack1/MyBucket2/Resource'], + ], ], - }), - }), - ); - - expect(ioHost.notifySpy).toHaveBeenCalledWith( - expect.objectContaining({ - message: expect.not.stringMatching(/OldQueueName/), + typedMappings: [], + }, }), ); }); -test('resource is marked to be excluded for refactoring in the cloud assembly', async () => { +test('detects modifications to the infrastructure', async () => { // GIVEN mockCloudFormationClient.on(ListStacksCommand).resolves({ StackSummaries: [ @@ -279,14 +309,22 @@ test('resource is marked to be excluded for refactoring in the cloud assembly', .resolves({ TemplateBody: JSON.stringify({ Resources: { - // This would have caused a refactor to be detected, - // but the resource is marked to be excluded... - OldLogicalID: { + // This resource would be refactored + OldName: { Type: 'AWS::S3::Bucket', UpdateReplacePolicy: 'Retain', DeletionPolicy: 'Retain', Metadata: { - 'aws:cdk:path': 'Stack1/OldLogicalID/Resource', + 'aws:cdk:path': 'Stack1/OldName/Resource', + }, + }, + // But there is an additional resource that will prevent it + Queue: { + Type: 'AWS::S3::Queue', + UpdateReplacePolicy: 'Retain', + DeletionPolicy: 'Retain', + Metadata: { + 'aws:cdk:path': 'Stack1/Queue/Resource', }, }, }, @@ -294,7 +332,7 @@ test('resource is marked to be excluded for refactoring in the cloud assembly', }); // WHEN - const cx = await builderFixture(toolkit, 'exclude-refactor'); + const cx = await builderFixture(toolkit, 'stack-with-bucket'); await toolkit.refactor(cx, { dryRun: true, }); @@ -303,21 +341,29 @@ test('resource is marked to be excluded for refactoring in the cloud assembly', expect(ioHost.notifySpy).toHaveBeenCalledWith( expect.objectContaining({ action: 'refactor', - level: 'result', - code: 'CDK_TOOLKIT_I8900', - // ...so we don't see it in the output - message: expect.stringMatching(/Nothing to refactor/), + level: 'error', + code: 'CDK_TOOLKIT_E8900', + message: expect.stringMatching(/A refactor operation cannot add, remove or update resources/), }), ); }); -test('uses the explicit mapping when provided, instead of computing it on-the-fly', async () => { +test('fails when dry-run is false', async () => { + const cx = await builderFixture(toolkit, 'stack-with-bucket'); + await expect( + toolkit.refactor(cx, { + dryRun: false, + }), + ).rejects.toThrow('Refactor is not available yet. Too see the proposed changes, use the --dry-run flag.'); +}); + +test('overrides can be used to resolve ambiguities', async () => { // GIVEN mockCloudFormationClient.on(ListStacksCommand).resolves({ StackSummaries: [ { StackName: 'Stack1', - StackId: 'arn:aws:cloudformation:us-east-1:123456789012:stack/Stack1', + StackId: 'arn:aws:cloudformation:us-east-1:999999999999:stack/Stack1', StackStatus: 'CREATE_COMPLETE', CreationTime: new Date(), }, @@ -331,12 +377,21 @@ test('uses the explicit mapping when provided, instead of computing it on-the-fl .resolves({ TemplateBody: JSON.stringify({ Resources: { - OldLogicalID: { + // These two buckets were replaced with two other buckets + CatPhotos: { Type: 'AWS::S3::Bucket', UpdateReplacePolicy: 'Retain', DeletionPolicy: 'Retain', Metadata: { - 'aws:cdk:path': 'Stack1/OldLogicalID/Resource', + 'aws:cdk:path': 'Stack1/CatPhotos/Resource', + }, + }, + DogPhotos: { + Type: 'AWS::S3::Bucket', + UpdateReplacePolicy: 'Retain', + DeletionPolicy: 'Retain', + Metadata: { + 'aws:cdk:path': 'Stack1/DogPhotos/Resource', }, }, }, @@ -344,18 +399,23 @@ test('uses the explicit mapping when provided, instead of computing it on-the-fl }); // WHEN - const cx = await builderFixture(toolkit, 'stack-with-bucket'); + const cx = await builderFixture(toolkit, 'stack-with-two-buckets'); await toolkit.refactor(cx, { dryRun: true, - mappingSource: MappingSource.explicit([ + overrides: [ { account: '123456789012', region: 'us-east-1', resources: { - 'Stack1.OldLogicalID': 'Stack1.NewLogicalID', + // Only one override is enough in this case + 'Stack1.CatPhotos': 'Stack1.MyBucket1553EAA46', }, }, - ]), + ], + stacks: { + patterns: ['Stack1'], + strategy: StackSelectionStrategy.PATTERN_MATCH, + }, }); // THEN @@ -364,27 +424,37 @@ test('uses the explicit mapping when provided, instead of computing it on-the-fl action: 'refactor', level: 'result', code: 'CDK_TOOLKIT_I8900', - message: expect.stringMatching(/AWS::S3::Bucket.*Stack1\/OldLogicalID\/Resource.*Stack1\.NewLogicalID/), - data: expect.objectContaining({ + data: { typedMappings: [ { - sourcePath: 'Stack1/OldLogicalID/Resource', - destinationPath: 'Stack1.NewLogicalID', + destinationPath: 'Stack1/MyBucket1/Resource', + sourcePath: 'Stack1/CatPhotos/Resource', + type: 'AWS::S3::Bucket', + }, + { + destinationPath: 'Stack1/MyBucket2/Resource', + sourcePath: 'Stack1/DogPhotos/Resource', type: 'AWS::S3::Bucket', }, ], - }), + }, }), ); }); -test('uses the reverse of an explicit mapping when provided', async () => { +test('filters stacks when stack selector is passed', async () => { // GIVEN mockCloudFormationClient.on(ListStacksCommand).resolves({ StackSummaries: [ { StackName: 'Stack1', - StackId: 'arn:aws:cloudformation:us-east-1:123456789012:stack/Stack1', + StackId: 'arn:aws:cloudformation:us-east-1:999999999999:stack/Stack1', + StackStatus: 'CREATE_COMPLETE', + CreationTime: new Date(), + }, + { + StackName: 'Stack2', + StackId: 'arn:aws:cloudformation:us-east-1:999999999999:stack/Stack2', StackStatus: 'CREATE_COMPLETE', CreationTime: new Date(), }, @@ -398,13 +468,29 @@ test('uses the reverse of an explicit mapping when provided', async () => { .resolves({ TemplateBody: JSON.stringify({ Resources: { - // Suppose we had already mapped OldLogicalID -> NewLogicalID... - NewLogicalID: { + OldBucketName: { Type: 'AWS::S3::Bucket', UpdateReplacePolicy: 'Retain', DeletionPolicy: 'Retain', Metadata: { - 'aws:cdk:path': 'Stack1/NewLogicalID/Resource', + 'aws:cdk:path': 'Stack1/OldBucketName/Resource', + }, + }, + }, + }), + }) + .on(GetTemplateCommand, { + StackName: 'Stack2', + }) + .resolves({ + TemplateBody: JSON.stringify({ + Resources: { + OldQueueName: { + Type: 'AWS::SQS::Queue', + UpdateReplacePolicy: 'Delete', + DeletionPolicy: 'Delete', + Metadata: { + 'aws:cdk:path': 'Stack2/OldQueueName/Resource', }, }, }, @@ -412,37 +498,40 @@ test('uses the reverse of an explicit mapping when provided', async () => { }); // WHEN - const cx = await builderFixture(toolkit, 'stack-with-bucket'); + const cx = await builderFixture(toolkit, 'two-different-stacks'); await toolkit.refactor(cx, { dryRun: true, - // ... this is the mapping we used, and now we want to revert it - mappingSource: MappingSource.reverse([{ - account: '123456789012', - region: 'us-east-1', - resources: { - 'Stack1.OldLogicalID': 'Stack1.NewLogicalID', - }, - }]), + stacks: { + patterns: ['Stack1'], + strategy: StackSelectionStrategy.PATTERN_MATCH, + }, }); - // THEN + // Resources were renamed in both stacks, but we are only including Stack1. + // So expect to see only changes for Stack1. expect(ioHost.notifySpy).toHaveBeenCalledWith( expect.objectContaining({ action: 'refactor', level: 'result', code: 'CDK_TOOLKIT_I8900', - message: expect.stringMatching(/AWS::S3::Bucket.*Stack1\/NewLogicalID\/Resource.*Stack1\.OldLogicalID/), + message: expect.stringMatching(/AWS::S3::Bucket.*Stack1\/OldBucketName\/Resource.*Stack1\/MyBucket\/Resource/), data: expect.objectContaining({ typedMappings: [ { - sourcePath: 'Stack1/NewLogicalID/Resource', - destinationPath: 'Stack1.OldLogicalID', + sourcePath: 'Stack1/OldBucketName/Resource', + destinationPath: 'Stack1/MyBucket/Resource', type: 'AWS::S3::Bucket', }, ], }), }), ); + + expect(ioHost.notifySpy).toHaveBeenCalledWith( + expect.objectContaining({ + message: expect.not.stringMatching(/OldQueueName/), + }), + ); }); test('computes one set of mappings per environment', async () => { @@ -519,18 +608,24 @@ test('computes one set of mappings per environment', async () => { }); // THEN - expect(ioHost.notifySpy).toHaveBeenCalledTimes(3); + expect(ioHost.notifySpy).toHaveBeenCalledTimes(4); - expect(ioHost.notifySpy).toHaveBeenNthCalledWith(2, expect.objectContaining({ - message: expect.stringMatching('aws://123456789012/us-east-1'), - })); + expect(ioHost.notifySpy).toHaveBeenNthCalledWith( + 1, + expect.objectContaining({ + message: expect.stringMatching('aws://123456789012/us-east-1'), + }), + ); - expect(ioHost.notifySpy).toHaveBeenNthCalledWith(2, + expect(ioHost.notifySpy).toHaveBeenNthCalledWith( + 2, expect.objectContaining({ action: 'refactor', level: 'result', code: 'CDK_TOOLKIT_I8900', - message: expect.stringMatching(/AWS::S3::Bucket.*Stack1\/OldBucketName\/Resource.*Stack1\/NewBucketNameInStack1\/Resource/), + message: expect.stringMatching( + /AWS::S3::Bucket.*Stack1\/OldBucketName\/Resource.*Stack1\/NewBucketNameInStack1\/Resource/, + ), data: expect.objectContaining({ typedMappings: [ { @@ -543,16 +638,22 @@ test('computes one set of mappings per environment', async () => { }), ); - expect(ioHost.notifySpy).toHaveBeenNthCalledWith(3, expect.objectContaining({ - message: expect.stringMatching('aws://123456789012/us-east-2'), - })); + expect(ioHost.notifySpy).toHaveBeenNthCalledWith( + 3, + expect.objectContaining({ + message: expect.stringMatching('aws://123456789012/us-east-2'), + }), + ); - expect(ioHost.notifySpy).toHaveBeenNthCalledWith(3, + expect(ioHost.notifySpy).toHaveBeenNthCalledWith( + 4, expect.objectContaining({ action: 'refactor', level: 'result', code: 'CDK_TOOLKIT_I8900', - message: expect.stringMatching(/AWS::S3::Bucket.*Stack2\/OldBucketName\/Resource.*Stack2\/NewBucketNameInStack2\/Resource/), + message: expect.stringMatching( + /AWS::S3::Bucket.*Stack2\/OldBucketName\/Resource.*Stack2\/NewBucketNameInStack2\/Resource/, + ), data: expect.objectContaining({ typedMappings: [ { @@ -565,3 +666,11 @@ test('computes one set of mappings per environment', async () => { }), ); }); + +async function expectRefactorBehavior(fixtureName: string, input: RefactorOptions, output: E) { + const host = new TestIoHost(); + const tk = new Toolkit({ ioHost: host, unstableFeatures: ['refactor'] }); + await tk.refactor(await builderFixture(tk, fixtureName), input); + expect(host.notifySpy).toHaveBeenCalledWith(expect.objectContaining(output)); +} + diff --git a/packages/@aws-cdk/toolkit-lib/test/api/cloud-assembly/prepare-source.test.ts b/packages/@aws-cdk/toolkit-lib/test/api/cloud-assembly/prepare-source.test.ts new file mode 100644 index 000000000..0a5cf2e1c --- /dev/null +++ b/packages/@aws-cdk/toolkit-lib/test/api/cloud-assembly/prepare-source.test.ts @@ -0,0 +1,198 @@ +import { frameworkSupportsContextOverflow } from '../../../lib/api/cloud-assembly/private/prepare-source'; +import type { ConstructTreeNode } from '../../../lib/api/tree'; + +describe('frameworkSupportsContextOverflow', () => { + test('returns true for undefined tree', () => { + expect(frameworkSupportsContextOverflow(undefined)).toBe(true); + }); + + test('returns true for empty tree', () => { + expect(frameworkSupportsContextOverflow({} as any)).toBe(true); + }); + + test('returns true for tree with non-App constructs', () => { + const tree: ConstructTreeNode = { + id: 'root', + path: '', + children: { + stack1: { + id: 'stack1', + path: 'stack1', + constructInfo: { + fqn: 'aws-cdk-lib.Stack', + version: '2.50.0', + }, + }, + }, + }; + expect(frameworkSupportsContextOverflow(tree)).toBe(true); + }); + + test('returns false for v1 App', () => { + const tree: ConstructTreeNode = { + id: 'root', + path: '', + children: { + app: { + id: 'app', + path: 'app', + constructInfo: { + fqn: '@aws-cdk/core.App', + version: '1.180.0', + }, + }, + }, + }; + expect(frameworkSupportsContextOverflow(tree)).toBe(false); + }); + + test('returns false for v2 App with version <= 2.38.0', () => { + const tree: ConstructTreeNode = { + id: 'root', + path: '', + children: { + app: { + id: 'app', + path: 'app', + constructInfo: { + fqn: 'aws-cdk-lib.App', + version: '2.38.0', + }, + }, + }, + }; + expect(frameworkSupportsContextOverflow(tree)).toBe(false); + }); + + test('returns true for v2 App with version > 2.38.0', () => { + const tree: ConstructTreeNode = { + id: 'root', + path: '', + children: { + app: { + id: 'app', + path: 'app', + constructInfo: { + fqn: 'aws-cdk-lib.App', + version: '2.38.1', + }, + }, + }, + }; + expect(frameworkSupportsContextOverflow(tree)).toBe(true); + }); + + test('returns true for v2 App with developer version (0.0.0)', () => { + const tree: ConstructTreeNode = { + id: 'root', + path: '', + children: { + app: { + id: 'app', + path: 'app', + constructInfo: { + fqn: 'aws-cdk-lib.App', + version: '0.0.0', + }, + }, + }, + }; + expect(frameworkSupportsContextOverflow(tree)).toBe(true); + }); + + test('returns false if any node in the tree is a v1 App', () => { + const tree: ConstructTreeNode = { + id: 'root', + path: '', + children: { + stack1: { + id: 'stack1', + path: 'stack1', + constructInfo: { + fqn: 'aws-cdk-lib.Stack', + version: '2.50.0', + }, + }, + nested: { + id: 'nested', + path: 'nested', + children: { + app: { + id: 'app', + path: 'nested/app', + constructInfo: { + fqn: '@aws-cdk/core.App', + version: '1.180.0', + }, + }, + }, + }, + }, + }; + expect(frameworkSupportsContextOverflow(tree)).toBe(false); + }); + + test('returns false if any node in the tree is a v2 App with version <= 2.38.0', () => { + const tree: ConstructTreeNode = { + id: 'root', + path: '', + children: { + stack1: { + id: 'stack1', + path: 'stack1', + constructInfo: { + fqn: 'aws-cdk-lib.Stack', + version: '2.50.0', + }, + }, + nested: { + id: 'nested', + path: 'nested', + children: { + app: { + id: 'app', + path: 'nested/app', + constructInfo: { + fqn: 'aws-cdk-lib.App', + version: '2.38.0', + }, + }, + }, + }, + }, + }; + expect(frameworkSupportsContextOverflow(tree)).toBe(false); + }); + + test('returns true if all v2 Apps in the tree have version > 2.38.0', () => { + const tree: ConstructTreeNode = { + id: 'root', + path: '', + children: { + app1: { + id: 'app1', + path: 'app1', + constructInfo: { + fqn: 'aws-cdk-lib.App', + version: '2.38.1', + }, + }, + nested: { + id: 'nested', + path: 'nested', + children: { + app2: { + id: 'app2', + path: 'nested/app2', + constructInfo: { + fqn: 'aws-cdk-lib.App', + version: '2.50.0', + }, + }, + }, + }, + }, + }; + expect(frameworkSupportsContextOverflow(tree)).toBe(true); + }); +}); diff --git a/packages/@aws-cdk/toolkit-lib/test/api/cloud-assembly/source-builder.test.ts b/packages/@aws-cdk/toolkit-lib/test/api/cloud-assembly/source-builder.test.ts index 010b2a52e..498a21646 100644 --- a/packages/@aws-cdk/toolkit-lib/test/api/cloud-assembly/source-builder.test.ts +++ b/packages/@aws-cdk/toolkit-lib/test/api/cloud-assembly/source-builder.test.ts @@ -2,6 +2,7 @@ import * as path from 'path'; import { App } from 'aws-cdk-lib/core'; import * as fs from 'fs-extra'; import { MemoryContext } from '../../../lib'; +import * as environment from '../../../lib/api/cloud-assembly/environment'; import { RWLock } from '../../../lib/api/rwlock'; import * as contextproviders from '../../../lib/context-providers'; import { Toolkit } from '../../../lib/toolkit/toolkit'; @@ -157,6 +158,39 @@ describe('fromAssemblyBuilder', () => { expect(await (lock! as any)._currentWriter()).toBeUndefined(); expect(await (lock! as any)._currentReaders()).toEqual([]); }); + + describe('resolveDefaultEnvironment', () => { + let prepareDefaultEnvironmentSpy: jest.SpyInstance; + beforeEach(() => { + // Mock the prepareDefaultEnvironment function to avoid actual STS calls + prepareDefaultEnvironmentSpy = jest.spyOn(environment, 'prepareDefaultEnvironment') + .mockImplementation(async () => { + return { + CDK_DEFAULT_ACCOUNT: '123456789012', + CDK_DEFAULT_REGION: 'us-east-1', + }; + }); + }); + + afterEach(() => { + prepareDefaultEnvironmentSpy.mockRestore(); + }); + + test.each([[true, 1], [false, 0], [undefined, 1]])('respects resolveDefaultEnvironment=%s', async (resolveDefaultEnvironment, callCount) => { + // WHEN + const cx = await toolkit.fromAssemblyBuilder(async () => { + const app = new App(); + return app.synth(); + }, { + resolveDefaultEnvironment, + }); + + await using _ = await cx.produce(); + + // THEN + expect(prepareDefaultEnvironmentSpy).toHaveBeenCalledTimes(callCount); + }); + }); }); describe('fromCdkApp', () => { @@ -290,6 +324,45 @@ describe('fromCdkApp', () => { expect(await (lock! as any)._currentWriter()).toBeUndefined(); expect(await (lock! as any)._currentReaders()).toEqual([]); }); + + describe('resolveDefaultEnvironment', () => { + let prepareDefaultEnvironmentSpy: jest.SpyInstance; + beforeEach(() => { + // Mock the prepareDefaultEnvironment function to avoid actual STS calls + prepareDefaultEnvironmentSpy = jest.spyOn(environment, 'prepareDefaultEnvironment') + .mockImplementation(async () => { + return { + CDK_DEFAULT_ACCOUNT: '123456789012', + CDK_DEFAULT_REGION: 'us-east-1', + }; + }); + }); + + afterEach(() => { + prepareDefaultEnvironmentSpy.mockRestore(); + }); + + test.each([[true, 1], [false, 0], [undefined, 1]])('respects resolveDefaultEnvironment=%s', async (resolveDefaultEnvironment, callCount) => { + // GIVEN + await using synthDir = autoCleanOutDir(); + + // WHEN + const cx = await toolkit.fromCdkApp('node -e "console.log(JSON.stringify(process.env))"', { + workingDirectory: process.cwd(), + outdir: synthDir.dir, + resolveDefaultEnvironment, + }); + + try { + await using _ = await cx.produce(); + } catch { + // we expect this app to throw + } + + // THEN + expect(prepareDefaultEnvironmentSpy).toHaveBeenCalledTimes(callCount); + }); + }); }); describe('fromAssemblyDirectory', () => { diff --git a/packages/@aws-cdk/toolkit-lib/test/api/diff/diff.test.ts b/packages/@aws-cdk/toolkit-lib/test/api/diff/diff.test.ts index 9580ca7c2..8214e7493 100644 --- a/packages/@aws-cdk/toolkit-lib/test/api/diff/diff.test.ts +++ b/packages/@aws-cdk/toolkit-lib/test/api/diff/diff.test.ts @@ -92,6 +92,29 @@ describe('formatStackDiff', () => { ); }); + test('formats differences showing resource moves', () => { + // WHEN + const formatter = new DiffFormatter({ + templateInfo: { + oldTemplate: {}, + newTemplate: mockNewTemplate, + mappings: { + 'test-stack.OldName': 'test-stack.Func', + }, + }, + }); + const result = formatter.formatStackDiff(); + + // THEN + expect(result.formattedDiff).toBeDefined(); + const sanitizedDiff = result.formattedDiff!.replace(/\x1B\[[0-?]*[ -/]*[@-~]/g, '').trim(); + expect(sanitizedDiff).toBe( + 'Stack test-stack\n' + + 'Resources\n' + + '[+] AWS::Lambda::Function Func (OR move from test-stack.OldName via refactoring)', + ); + }); + test('handles nested stack templates', () => { // GIVEN const nestedStacks = { diff --git a/packages/@aws-cdk/toolkit-lib/test/api/refactoring/context.test.ts b/packages/@aws-cdk/toolkit-lib/test/api/refactoring/context.test.ts index e7c895a5e..9a14ff51a 100644 --- a/packages/@aws-cdk/toolkit-lib/test/api/refactoring/context.test.ts +++ b/packages/@aws-cdk/toolkit-lib/test/api/refactoring/context.test.ts @@ -50,7 +50,7 @@ describe('typed mappings', () => { expect(context.mappings).toEqual([]); }); - test('returns empty mappings when there are only removals', () => { + test('resource removal is not allowed', () => { const stack1 = { environment, stackName: 'Foo', @@ -73,15 +73,14 @@ describe('typed mappings', () => { }, }; - const context = new RefactoringContext({ + expect(() => new RefactoringContext({ environment, deployedStacks: [stack1], localStacks: [stack2], - }); - expect(context.mappings).toEqual([]); + })).toThrow(/A refactor operation cannot add, remove or update resources/); }); - test('returns empty mappings when there are only additions', () => { + test('resource addition is not allowed', () => { const stack1 = { environment, stackName: 'Foo', @@ -104,15 +103,14 @@ describe('typed mappings', () => { }, }; - const context = new RefactoringContext({ + expect(() => new RefactoringContext({ environment, deployedStacks: [stack1], localStacks: [stack2], - }); - expect(context.mappings).toEqual([]); + })).toThrow(/A refactor operation cannot add, remove or update resources/); }); - test('normal updates are not mappings', () => { + test('resource update is not allowed', () => { const stack1 = { environment, stackName: 'Foo', @@ -136,17 +134,17 @@ describe('typed mappings', () => { Bucket1: { Type: 'AWS::S3::Bucket', // Updated property - Properties: { Prop: 'old value' }, + Properties: { Prop: 'new value' }, }, }, }, }; - const context = new RefactoringContext({ + + expect(() => new RefactoringContext({ environment, deployedStacks: [stack1], localStacks: [stack2], - }); - expect(context.mappings).toEqual([]); + })).toThrow(/A refactor operation cannot add, remove or update resources/); }); test('moving resources across stacks', () => { @@ -299,16 +297,14 @@ describe('typed mappings', () => { }, }; - const context = new RefactoringContext({ - environment, - deployedStacks: [stack1], - localStacks: [stack2], - }); - // We don't consider that a resource was moved from Foo.OldName to Bar.NewName, // even though they have the same properties. Since they have different types, // they are considered different resources. - expect(context.mappings).toEqual([]); + expect(() => new RefactoringContext({ + environment, + deployedStacks: [stack1], + localStacks: [stack2], + })).toThrow(/A refactor operation cannot add, remove or update resources/); }); test('ambiguous resources from multiple stacks', () => { @@ -351,12 +347,11 @@ describe('typed mappings', () => { }, }; - const context = new RefactoringContext({ + expect(() => new RefactoringContext({ environment, deployedStacks: [stack1, stack2], localStacks: [stack3], - }); - expect(context.ambiguousPaths).toEqual([[['Stack1.Bucket1', 'Stack2.Bucket2'], ['Stack3.Bucket3']]]); + })).toThrow(/A refactor operation cannot add, remove or update resources/); }); test('ambiguous pairs', () => { @@ -407,23 +402,31 @@ describe('typed mappings', () => { ]); }); - test('combines addition, deletion, update, and rename', () => { + test('ambiguous pairs that can be disambiguated by the structure', () => { const stack1 = { environment, stackName: 'Foo', template: { Resources: { - OldName: { + Bucket1: { Type: 'AWS::S3::Bucket', - Properties: { Prop: 'OldBucket' }, + Properties: {}, }, - ToBeDeleted: { + Bucket2: { Type: 'AWS::S3::Bucket', - Properties: { Prop: 'DeleteMe' }, + Properties: {}, }, - ToBeUpdated: { - Type: 'AWS::S3::Bucket', - Properties: { Prop: 'UpdateMe' }, + Depender1: { + Type: 'AWS::Foo::Foo', + Properties: { + SomeProp: { Ref: 'Bucket1' }, + }, + }, + Depender2: { + Type: 'AWS::Bar::Bar', + Properties: { + SomeProp: { Ref: 'Bucket2' }, + }, }, }, }, @@ -431,20 +434,28 @@ describe('typed mappings', () => { const stack2 = { environment, - stackName: 'Foo', + stackName: 'Bar', template: { Resources: { - NewName: { + Bucket3: { Type: 'AWS::S3::Bucket', - Properties: { Prop: 'OldBucket' }, + Properties: {}, }, - ToBeAdded: { + Bucket4: { Type: 'AWS::S3::Bucket', - Properties: { Prop: 'NewBucket' }, + Properties: {}, }, - ToBeUpdated: { - Type: 'AWS::S3::Bucket', - Properties: { Prop: 'UpdatedBucket' }, + Depender1: { + Type: 'AWS::Foo::Foo', + Properties: { + SomeProp: { Ref: 'Bucket3' }, + }, + }, + Depender2: { + Type: 'AWS::Bar::Bar', + Properties: { + SomeProp: { Ref: 'Bucket4' }, + }, }, }, }, @@ -455,91 +466,13 @@ describe('typed mappings', () => { deployedStacks: [stack1], localStacks: [stack2], }); + expect(context.ambiguousPaths.length).toEqual(0); expect(context.mappings.map(toCfnMapping)).toEqual([ - { - Source: { LogicalResourceId: 'OldName', StackName: 'Foo' }, - Destination: { LogicalResourceId: 'NewName', StackName: 'Foo' }, - }, - ]); - }); - - test('stack filtering', () => { - // eslint-disable-next-line @typescript-eslint/no-shadow - const environment = { - name: 'prod', - account: '123456789012', - region: 'us-east-1', - }; - - // Scenario: - // Foo.Bucket1 -> Bar.Bucket1 - // Zee.OldName -> Zee.NewName - - const stack1 = { - environment, - stackName: 'Foo', - template: { - Resources: { - Bucket1: { - Type: 'AWS::S3::Bucket', - Properties: { Prop: 'XXXXXXXXX' }, - }, - }, - }, - }; - - const stack2 = { - environment, - stackName: 'Bar', - template: { - Resources: { - Bucket1: { - Type: 'AWS::S3::Bucket', - Properties: { Prop: 'XXXXXXXXX' }, - }, - }, - }, - }; - - const stack3 = { - environment, - stackName: 'Zee', - template: { - Resources: { - OldName: { - Type: 'AWS::SQS::Queue', - Properties: { Prop: 'YYYYYYYYY' }, - }, - }, - }, - }; - - const stack4 = { - environment, - stackName: 'Zee', - template: { - Resources: { - NewName: { - Type: 'AWS::SQS::Queue', - Properties: { Prop: 'YYYYYYYYY' }, - }, - }, - }, - }; - - // Testing different filters: - - // Only Foo. Should include Foo and Bar - let context = new RefactoringContext({ - environment, - deployedStacks: [stack1, stack3], - localStacks: [stack2, stack4], - filteredStacks: [stack1], - }); - expect(context.mappings.map(toCfnMapping)).toEqual([ + // Despite Bucket1 and Bucket2 being identical, we could still disambiguate + // them based on the resources that depend on them. { Destination: { - LogicalResourceId: 'Bucket1', + LogicalResourceId: 'Bucket3', StackName: 'Bar', }, Source: { @@ -547,77 +480,87 @@ describe('typed mappings', () => { StackName: 'Foo', }, }, - ]); - - // Only Bar. Should include Foo and Bar - context = new RefactoringContext({ - environment, - deployedStacks: [stack1, stack3], - localStacks: [stack2, stack4], - filteredStacks: [stack2], - }); - expect(context.mappings.map(toCfnMapping)).toEqual([ { Destination: { - LogicalResourceId: 'Bucket1', + LogicalResourceId: 'Bucket4', StackName: 'Bar', }, Source: { - LogicalResourceId: 'Bucket1', + LogicalResourceId: 'Bucket2', StackName: 'Foo', }, }, - ]); - - // Only Zee. Should include Zee - context = new RefactoringContext({ - environment, - deployedStacks: [stack1, stack3], - localStacks: [stack2, stack4], - filteredStacks: [stack3], - }); - expect(context.mappings.map(toCfnMapping)).toEqual([ { Destination: { - LogicalResourceId: 'NewName', - StackName: 'Zee', + LogicalResourceId: 'Depender1', + StackName: 'Bar', }, Source: { - LogicalResourceId: 'OldName', - StackName: 'Zee', + LogicalResourceId: 'Depender1', + StackName: 'Foo', }, }, - ]); - - // Foo and Zee. Should include all - context = new RefactoringContext({ - environment, - deployedStacks: [stack1, stack3], - localStacks: [stack2, stack4], - filteredStacks: [stack1, stack3], - }); - expect(context.mappings.map(toCfnMapping)).toEqual([ { Destination: { - LogicalResourceId: 'Bucket1', + LogicalResourceId: 'Depender2', StackName: 'Bar', }, Source: { - LogicalResourceId: 'Bucket1', + LogicalResourceId: 'Depender2', StackName: 'Foo', }, }, - { - Destination: { - LogicalResourceId: 'NewName', - StackName: 'Zee', + ]); + }); + + test('combines addition, deletion, update, and rename', () => { + const stack1 = { + environment, + stackName: 'Foo', + template: { + Resources: { + OldName: { + Type: 'AWS::S3::Bucket', + Properties: { Prop: 'OldBucket' }, + }, + ToBeDeleted: { + Type: 'AWS::S3::Bucket', + Properties: { Prop: 'DeleteMe' }, + }, + ToBeUpdated: { + Type: 'AWS::S3::Bucket', + Properties: { Prop: 'UpdateMe' }, + }, }, - Source: { - LogicalResourceId: 'OldName', - StackName: 'Zee', + }, + }; + + const stack2 = { + environment, + stackName: 'Foo', + template: { + Resources: { + NewName: { + Type: 'AWS::S3::Bucket', + Properties: { Prop: 'OldBucket' }, + }, + ToBeAdded: { + Type: 'AWS::S3::Bucket', + Properties: { Prop: 'NewBucket' }, + }, + ToBeUpdated: { + Type: 'AWS::S3::Bucket', + Properties: { Prop: 'UpdatedBucket' }, + }, }, }, - ]); + }; + + expect(() => new RefactoringContext({ + environment, + deployedStacks: [stack1], + localStacks: [stack2], + })).toThrow(/A refactor operation cannot add, remove or update resources/); }); }); diff --git a/packages/@aws-cdk/toolkit-lib/test/api/refactoring/refactoring.test.ts b/packages/@aws-cdk/toolkit-lib/test/api/refactoring/refactoring.test.ts index 113f1a2c8..367f2f593 100644 --- a/packages/@aws-cdk/toolkit-lib/test/api/refactoring/refactoring.test.ts +++ b/packages/@aws-cdk/toolkit-lib/test/api/refactoring/refactoring.test.ts @@ -334,74 +334,6 @@ describe(computeResourceDigests, () => { expect(result['Stack1.Q1']).toBe(result['Stack1.Q2']); }); - test('uses physical ID if present', () => { - mockLoadResourceModel.mockReturnValue({ - primaryIdentifier: ['FooName'], - }); - - const template = { - Resources: { - Foo1: { - Type: 'AWS::S3::Foo', - Properties: { - FooName: 'XXXXXXXXX', - ShouldBeIgnored: true, - }, - }, - Foo2: { - Type: 'AWS::S3::Foo', - Properties: { - FooName: 'XXXXXXXXX', - ShouldAlsoBeIgnored: true, - }, - }, - }, - }; - - const result = computeResourceDigests(makeStacks([template])); - expect(result['Stack1.Foo1']).toBeDefined(); - expect(result['Stack1.Foo2']).toBeDefined(); - expect(result['Stack1.Foo1']).toEqual(result['Stack1.Foo2']); - }); - - test('uses physical ID if present - with dependencies', () => { - mockLoadResourceModel.mockReturnValue({ - primaryIdentifier: ['FooName'], - }); - - const template = { - Resources: { - Foo1: { - Type: 'AWS::S3::Foo', - Properties: { - FooName: 'XXXXXXXXX', - ShouldBeIgnored: true, - }, - }, - Foo2: { - Type: 'AWS::S3::Foo', - Properties: { - FooName: 'XXXXXXXXX', - ShouldAlsoBeIgnored: true, - }, - }, - Bucket1: { - Type: 'AWS::S3::Bucket', - Properties: { Dep: { Ref: 'Foo1' } }, - }, - Bucket2: { - Type: 'AWS::S3::Bucket', - Properties: { Dep: { Ref: 'Foo2' } }, - }, - }, - }; - - const result = computeResourceDigests(makeStacks([template])); - expect(result['Stack1.Bucket1']).toBeDefined(); - expect(result['Stack1.Bucket2']).toBeDefined(); - expect(result['Stack1.Bucket1']).toEqual(result['Stack1.Bucket2']); - }); - test('different physical IDs lead to different digests', () => { mockLoadResourceModel.mockReturnValue({ primaryIdentifier: ['FooName'], @@ -464,68 +396,6 @@ describe(computeResourceDigests, () => { expect(result['Stack1.Foo1']).not.toEqual(result['Stack1.Foo2']); }); - test('primaryIdentifier is a composite field - same value', () => { - mockLoadResourceModel.mockReturnValue({ - primaryIdentifier: ['FooName', 'BarName'], - }); - - const template = { - Resources: { - Foo1: { - Type: 'AWS::S3::Foo', - Properties: { - FooName: 'XXXXXXXXX', - BarName: 'YYYYYYYYY', - ShouldBeIgnored: true, - }, - }, - Foo2: { - Type: 'AWS::S3::Foo', - Properties: { - FooName: 'XXXXXXXXX', - BarName: 'YYYYYYYYY', - ShouldAlsoBeIgnored: true, - }, - }, - }, - }; - - const result = computeResourceDigests(makeStacks([template])); - expect(result['Stack1.Foo1']).toBeDefined(); - expect(result['Stack1.Foo2']).toBeDefined(); - expect(result['Stack1.Foo1']).toEqual(result['Stack1.Foo2']); - }); - - test('primaryIdentifier is a composite field but not all of them are set in the resource', () => { - mockLoadResourceModel.mockReturnValue({ - primaryIdentifier: ['FooName', 'BarName'], - }); - - const template = { - Resources: { - Foo1: { - Type: 'AWS::S3::Foo', - Properties: { - FooName: 'XXXXXXXXX', - ShouldBeIgnored: true, - }, - }, - Foo2: { - Type: 'AWS::S3::Foo', - Properties: { - FooName: 'XXXXXXXXX', - ShouldAlsoBeIgnored: true, - }, - }, - }, - }; - - const result = computeResourceDigests(makeStacks([template])); - expect(result['Stack1.Foo1']).toBeDefined(); - expect(result['Stack1.Foo2']).toBeDefined(); - expect(result['Stack1.Foo1']).not.toEqual(result['Stack1.Foo2']); - }); - test('resource properties does not contain primaryIdentifier - different values', () => { mockLoadResourceModel.mockReturnValue({ primaryIdentifier: ['FooName'], diff --git a/packages/@aws-cdk/toolkit-lib/test/toolkit-flags.test.ts b/packages/@aws-cdk/toolkit-lib/test/toolkit-flags.test.ts new file mode 100644 index 000000000..416c5e153 --- /dev/null +++ b/packages/@aws-cdk/toolkit-lib/test/toolkit-flags.test.ts @@ -0,0 +1,183 @@ +import { ArtifactType } from '@aws-cdk/cloud-assembly-schema'; +import type { CloudAssembly } from '@aws-cdk/cx-api'; +import { appFixture, TestIoHost, builderFixture } from './_helpers'; +import { Toolkit } from '../lib/toolkit/toolkit'; + +let ioHost: TestIoHost; +beforeEach(() => { + jest.restoreAllMocks(); + ioHost = new TestIoHost(); +}); + +const toolkit = new Toolkit({ + ioHost: new TestIoHost(), unstableFeatures: ['flags'], +}); + +function createMockCloudAssemblySource(artifacts: any) { + return { + async produce() { + const mockCloudAssembly = { + manifest: { + artifacts: artifacts, + }, + } as CloudAssembly; + + return { + cloudAssembly: mockCloudAssembly, + dispose: jest.fn(), + [Symbol.asyncDispose]: jest.fn(), + _unlock: jest.fn(), + }; + }, + }; +} + +describe('Toolkit.flags() method', () => { + test('requires acknowledgment that the feature is unstable', async () => { + const tk = new Toolkit({ ioHost }); + const cx = await builderFixture(tk, 'stack-with-bucket'); + + await expect( + tk.flags(cx), + ).rejects.toThrow("Unstable feature 'flags' is not enabled. Please enable it under 'unstableFeatures'"); + }); + + test('should retrieve feature flags in correct structure', async () => { + const tk = new Toolkit({ ioHost, unstableFeatures: ['flags'] }); + const cx = await appFixture(toolkit, 'two-empty-stacks'); + const flags = await tk.flags(cx); + + expect(flags.length).toBeGreaterThan(0); + expect(Array.isArray(flags)).toBe(true); + + flags.forEach((flag) => { + expect(flag).toHaveProperty('module'); + expect(flag).toHaveProperty('recommendedValue'); + expect(flag).toHaveProperty('userValue'); + expect(flag).toHaveProperty('explanation'); + expect(flag).toHaveProperty('name'); + }); + }); + + test('processes feature flag correctly when mocked cloud assembly is used', async () => { + const mockCloudAssemblySource = createMockCloudAssemblySource({ + 'aws-cdk-lib/feature-flag-report': { + type: 'cdk:feature-flag-report', + properties: { + module: 'aws-cdk-lib', + flags: { + '@aws-cdk/core:enableStackNameDuplicates': { + recommendedValue: true, + explanation: 'Allow multiple stacks with the same name', + }, + }, + }, + }, + }); + + const mockFlags = await toolkit.flags(mockCloudAssemblySource as any); + + expect(mockFlags.length).toBe(1); + expect(mockFlags[0].module).toEqual('aws-cdk-lib'); + expect(mockFlags[0].name).toEqual('@aws-cdk/core:enableStackNameDuplicates'); + expect(mockFlags[0].userValue).toBeUndefined(); + expect(mockFlags[0].recommendedValue).toEqual(true); + expect(mockFlags[0].explanation).toEqual('Allow multiple stacks with the same name'); + }); + + test('handles multiple feature flag modules', async () => { + const mockCloudAssemblySource = createMockCloudAssemblySource({ + 'module1-flags': { + type: ArtifactType.FEATURE_FLAG_REPORT, + properties: { + module: 'module1', + flags: { + flag1: { + userValue: true, + recommendedValue: false, + explanation: 'Module 1 flag', + }, + }, + }, + }, + 'module2-flags': { + type: ArtifactType.FEATURE_FLAG_REPORT, + properties: { + module: 'module2', + flags: { + flag2: { + userValue: 'value', + recommendedValue: 'recommended', + explanation: 'Module 2 flag', + }, + }, + }, + }, + }); + + const mockFlags = await toolkit.flags(mockCloudAssemblySource as any); + + expect(mockFlags.length).toBe(2); + expect(mockFlags[0].module).toBe('module1'); + expect(mockFlags[0].explanation).toEqual('Module 1 flag'); + expect(mockFlags[0].name).toEqual('flag1'); + expect(mockFlags[0].userValue).toEqual(true); + expect(mockFlags[0].recommendedValue).toEqual(false); + expect(mockFlags[1].module).toBe('module2'); + expect(mockFlags[1].explanation).toEqual('Module 2 flag'); + expect(mockFlags[1].name).toEqual('flag2'); + expect(mockFlags[1].userValue).toEqual('value'); + expect(mockFlags[1].recommendedValue).toEqual('recommended'); + }); + + test('handles various data types for flag values', async () => { + const mockCloudAssemblySource = createMockCloudAssemblySource({ + 'feature-flag-report': { + type: ArtifactType.FEATURE_FLAG_REPORT, + properties: { + module: 'testModule', + flags: { + stringFlag: { + userValue: 'string-value', + recommendedValue: 'recommended-string', + explanation: 'String flag', + }, + numberFlag: { + userValue: 123, + recommendedValue: 456, + explanation: 'Number flag', + }, + booleanFlag: { + userValue: true, + recommendedValue: false, + explanation: 'Boolean flag', + }, + arrayFlag: { + userValue: ['a', 'b'], + recommendedValue: ['x', 'y'], + explanation: 'Array flag', + }, + objectFlag: { + userValue: { key: 'value' }, + recommendedValue: { key: 'recommended' }, + explanation: 'Object flag', + }, + }, + }, + }, + }); + + const mockFlags = await toolkit.flags(mockCloudAssemblySource as any); + + expect(mockFlags[0].userValue).toBe('string-value'); + expect(mockFlags[0].recommendedValue).toBe('recommended-string'); + expect(mockFlags[1].userValue).toBe(123); + expect(mockFlags[1].recommendedValue).toBe(456); + expect(mockFlags[2].userValue).toBe(true); + expect(mockFlags[2].recommendedValue).toBe(false); + expect(mockFlags[3].userValue).toEqual(['a', 'b']); + expect(mockFlags[3].recommendedValue).toEqual(['x', 'y']); + expect(mockFlags[4].userValue).toEqual({ key: 'value' }); + expect(mockFlags[4].recommendedValue).toEqual({ key: 'recommended' }); + }); +}); diff --git a/packages/@aws-cdk/user-input-gen/.projen/deps.json b/packages/@aws-cdk/user-input-gen/.projen/deps.json index a8ac6b1b9..f0a30be4d 100644 --- a/packages/@aws-cdk/user-input-gen/.projen/deps.json +++ b/packages/@aws-cdk/user-input-gen/.projen/deps.json @@ -99,7 +99,7 @@ }, { "name": "typescript", - "version": "5.6", + "version": "5.8", "type": "build" }, { diff --git a/packages/@aws-cdk/user-input-gen/package.json b/packages/@aws-cdk/user-input-gen/package.json index e160ea839..f95cd71f3 100644 --- a/packages/@aws-cdk/user-input-gen/package.json +++ b/packages/@aws-cdk/user-input-gen/package.json @@ -52,7 +52,7 @@ "jest-junit": "^16", "prettier": "^2.8", "ts-jest": "^29.4.0", - "typescript": "5.6" + "typescript": "5.8" }, "dependencies": { "@cdklabs/typewriter": "^0.0.5", diff --git a/packages/@aws-cdk/yarn-cling/.projen/deps.json b/packages/@aws-cdk/yarn-cling/.projen/deps.json index 882ab613b..2e6499866 100644 --- a/packages/@aws-cdk/yarn-cling/.projen/deps.json +++ b/packages/@aws-cdk/yarn-cling/.projen/deps.json @@ -94,7 +94,7 @@ }, { "name": "typescript", - "version": "5.6", + "version": "5.8", "type": "build" }, { diff --git a/packages/@aws-cdk/yarn-cling/lib/hoisting.ts b/packages/@aws-cdk/yarn-cling/lib/hoisting.ts index 2ac8960b9..9ede3eaa2 100644 --- a/packages/@aws-cdk/yarn-cling/lib/hoisting.ts +++ b/packages/@aws-cdk/yarn-cling/lib/hoisting.ts @@ -23,6 +23,7 @@ import { iterDeps, isPackage, type PackageLockFile, type PackageLockTree } from */ export function hoistDependencies(packageTree: PackageLockFile): PackageLockFile { let tree = packageTree; + tree = _addTombstones(tree); tree = _pushDepsToParent(tree); tree = _removeDupesWithParent(tree); tree = _removeTombstones(tree); @@ -60,6 +61,28 @@ export function renderTree(tree: PackageLockTree): string[] { } } +export function _addTombstones(root: A): A { + let tree = structuredClone(root); + recurse(tree); + return tree; + + function recurse(node: PackageLockTree) { + // For every node, all the packages they 'requires' should be in 'dependencies'. + // If it's not in 'dependencies', that must mean its at a higher level already, so we put + // the 'moved' tombstone in to make sure we don't accidentally replace this package with a different version. + for (const name of Object.keys(node.requires ?? {})) { + if (!node.dependencies?.[name]) { + node.dependencies = node.dependencies ?? {}; + node.dependencies[name] = 'moved'; + } + } + + for (const [_, dep] of iterDeps(node)) { + recurse(dep); + } + } +} + export function _pushDepsToParent(root: A): A { let tree = structuredClone(root); while (recurse(tree)) { diff --git a/packages/@aws-cdk/yarn-cling/package.json b/packages/@aws-cdk/yarn-cling/package.json index b09a2d438..3b88a281b 100644 --- a/packages/@aws-cdk/yarn-cling/package.json +++ b/packages/@aws-cdk/yarn-cling/package.json @@ -49,12 +49,12 @@ "eslint-plugin-jest": "^28.14.0", "eslint-plugin-jsdoc": "^50.8.0", "eslint-plugin-prettier": "^5.5.1", - "fast-check": "^4.1.1", + "fast-check": "^4.2.0", "jest": "^29.7.0", "jest-junit": "^16", "prettier": "^2.8", "ts-jest": "^29.4.0", - "typescript": "5.6" + "typescript": "5.8" }, "dependencies": { "@yarnpkg/lockfile": "^1.1.0", diff --git a/packages/aws-cdk/.projen/deps.json b/packages/aws-cdk/.projen/deps.json index ee158e588..df472b32a 100644 --- a/packages/aws-cdk/.projen/deps.json +++ b/packages/aws-cdk/.projen/deps.json @@ -178,7 +178,7 @@ }, { "name": "typescript", - "version": "5.6", + "version": "5.8", "type": "build" }, { diff --git a/packages/aws-cdk/README.md b/packages/aws-cdk/README.md index b1dcf95b3..ba02d61ef 100644 --- a/packages/aws-cdk/README.md +++ b/packages/aws-cdk/README.md @@ -1101,8 +1101,12 @@ when using this command. Compares the infrastructure specified in the current state of the CDK app with the currently deployed application, to determine if any resource was moved -(to a different stack or to a different logical ID, or both). The CLI will -show the correspondence between the old and new locations in a table: +(to a different stack or to a different logical ID, or both). In keeping with +the CloudFormation API, you are not allowed to modify the set of resources +as part of a refactor. In other words, adding, deleting or updating resources +is considered an error. + +The CLI will show the correspondence between the old and new locations in a table: ``` $ cdk refactor --unstable=refactor --dry-run @@ -1125,41 +1129,45 @@ show this table and exit. Eventually, the CLI will also be able to automatically apply the refactor on your CloudFormation stacks. But for now, only the dry-run mode is supported. -If you want to exclude some resources from the refactor, you can pass an -exclude file, containing a list of destination locations to exclude. A -location can be either the stack name + logical ID, or the construct path. For -example, if you don't want to include the bucket and the distribution from -the table above in the refactor, you can create a file called -`exclude.txt` with the following content (destination locations separated by -newlines): +If your application has more than one stack, and you want the `refactor` +command to consider only a subset of them, you can pass a list of stack +patterns as a parameter: +```shell +$ cdk refactor Web* --unstable=refactor --dry-run ``` -Web/Website/Origin/Resource -Web/Website/Distribution/Resource -``` -and pass it to the CLI via the `--exclude-file` flag: +The pattern language is the same as the one used in the `cdk deploy` command. +However, unlike `cdk deploy`, in the absence of this parameter, all stacks are +considered. + +The CLI's default behavior is to include in the comparison only the deployed +stacks that have a counterpart (stack with the same name) locally. If you want +to include additional deployed stacks in the comparison, pass their names using +the `--additional-stack-name` option: ```shell -$ cdk refactor --exclude-file exclude.txt --unstable=refactor --dry-run +$ cdk refactor --unstable=refactor --dry-run --additional-stack-name=Foo --additional-stack-name=Bar ``` -If your application has more than one stack, and you want the refactor -command to consider only a subset of them, you can pass a list of stack -patterns as a parameter: +In case of ambiguities, the CLI will display a table like this: -```shell -$ cdk refactor Web* --unstable=refactor --dry-run +``` +Detected ambiguities: +┌───┬──────────────────────┐ +│ │ Resource │ +├───┼──────────────────────┤ +│ - │ Stack2/DLQ/Resource │ +│ │ Stack2/DLQ2/Resource │ +├───┼──────────────────────┤ +│ + │ Stack1/DLQ/Resource │ +│ │ Stack1/DLQ2/Resource │ +└───┴──────────────────────┘ ``` -The pattern language is the same as the one used in the `cdk deploy` command. -However, unlike `cdk deploy`, in the absence of this parameter, all stacks are -considered. - -If, instead of letting the CLI decide which resources to move, you want to -provide your own mapping of old to new locations, you can do so by passing a -mapping file to the CLI via the `--mapping-file` flag. This file should -contain a JSON object with the following format: +You can resolve this ambiguity manually, by passing an override file via the +`--override-file=` CLI option. This file should contain a JSON object +with the following structure: ```json { @@ -1168,22 +1176,19 @@ contain a JSON object with the following format: "account": "123456789012", "region": "us-east-1", "resources": { - "Foo.OldName": "Bar.NewName" + "Stack2.OldName": "Stack2.NewName" } } ] } ``` -where `resources` is a mapping of resources from source to destination -locations for a given environment. Resource locations are in the format -`StackName.LogicalId`.The source must refer to a location where there is a -resource currently deployed, while the destination must refer to a location +where `resources` is a mapping of resources from source to destination +locations for a given environment. Resource locations are in the format +`StackName.LogicalId`.The source must refer to a location where there is a +resource currently deployed, while the destination must refer to a location that is not already occupied by any resource. -If you want to undo a refactor, you can use the `--revert` option in -conjunction with the `--mapping-file` option. It will apply the mapping in -reverse order (source becomes destination and vice versa). ### `cdk drift` diff --git a/packages/aws-cdk/THIRD_PARTY_LICENSES b/packages/aws-cdk/THIRD_PARTY_LICENSES index 9c905189f..52bcd0dc3 100644 --- a/packages/aws-cdk/THIRD_PARTY_LICENSES +++ b/packages/aws-cdk/THIRD_PARTY_LICENSES @@ -618,7 +618,7 @@ The aws-cdk package includes the following third-party software/licensing: ---------------- -** @aws-sdk/client-appsync@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-appsync/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-appsync@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-appsync/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -824,7 +824,7 @@ The aws-cdk package includes the following third-party software/licensing: ---------------- -** @aws-sdk/client-cloudcontrol@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-cloudcontrol/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-cloudcontrol@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-cloudcontrol/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -1030,7 +1030,7 @@ The aws-cdk package includes the following third-party software/licensing: ---------------- -** @aws-sdk/client-cloudformation@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-cloudformation/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-cloudformation@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-cloudformation/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -1236,7 +1236,7 @@ The aws-cdk package includes the following third-party software/licensing: ---------------- -** @aws-sdk/client-cloudwatch-logs@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-cloudwatch-logs/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-cloudwatch-logs@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-cloudwatch-logs/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -1442,7 +1442,7 @@ The aws-cdk package includes the following third-party software/licensing: ---------------- -** @aws-sdk/client-codebuild@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-codebuild/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-codebuild@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-codebuild/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -1648,7 +1648,7 @@ The aws-cdk package includes the following third-party software/licensing: ---------------- -** @aws-sdk/client-cognito-identity@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-cognito-identity/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-cognito-identity@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-cognito-identity/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -1854,7 +1854,7 @@ The aws-cdk package includes the following third-party software/licensing: ---------------- -** @aws-sdk/client-ec2@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-ec2/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-ec2@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-ec2/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -2060,7 +2060,7 @@ The aws-cdk package includes the following third-party software/licensing: ---------------- -** @aws-sdk/client-ecr@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-ecr/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-ecr@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-ecr/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -2266,7 +2266,7 @@ The aws-cdk package includes the following third-party software/licensing: ---------------- -** @aws-sdk/client-ecs@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-ecs/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-ecs@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-ecs/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -2472,7 +2472,7 @@ The aws-cdk package includes the following third-party software/licensing: ---------------- -** @aws-sdk/client-elastic-load-balancing-v2@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-elastic-load-balancing-v2/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-elastic-load-balancing-v2@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-elastic-load-balancing-v2/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -2678,7 +2678,7 @@ The aws-cdk package includes the following third-party software/licensing: ---------------- -** @aws-sdk/client-iam@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-iam/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-iam@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-iam/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -2884,7 +2884,7 @@ The aws-cdk package includes the following third-party software/licensing: ---------------- -** @aws-sdk/client-kms@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-kms/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-kms@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-kms/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -3090,7 +3090,7 @@ The aws-cdk package includes the following third-party software/licensing: ---------------- -** @aws-sdk/client-lambda@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-lambda/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-lambda@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-lambda/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -3296,7 +3296,7 @@ The aws-cdk package includes the following third-party software/licensing: ---------------- -** @aws-sdk/client-route-53@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-route-53/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-route-53@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-route-53/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -3502,7 +3502,7 @@ The aws-cdk package includes the following third-party software/licensing: ---------------- -** @aws-sdk/client-s3@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-s3/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-s3@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-s3/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -3708,7 +3708,7 @@ The aws-cdk package includes the following third-party software/licensing: ---------------- -** @aws-sdk/client-secrets-manager@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-secrets-manager/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-secrets-manager@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-secrets-manager/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -3914,7 +3914,7 @@ The aws-cdk package includes the following third-party software/licensing: ---------------- -** @aws-sdk/client-sfn@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-sfn/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-sfn@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-sfn/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -4120,7 +4120,7 @@ The aws-cdk package includes the following third-party software/licensing: ---------------- -** @aws-sdk/client-ssm@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-ssm/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-ssm@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-ssm/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -4326,7 +4326,7 @@ The aws-cdk package includes the following third-party software/licensing: ---------------- -** @aws-sdk/client-sso@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-sso/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-sso@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-sso/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -4532,7 +4532,7 @@ The aws-cdk package includes the following third-party software/licensing: ---------------- -** @aws-sdk/client-sts@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-sts/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-sts@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-sts/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -4738,11 +4738,11 @@ The aws-cdk package includes the following third-party software/licensing: ---------------- -** @aws-sdk/core@3.839.0 - https://www.npmjs.com/package/@aws-sdk/core/v/3.839.0 | Apache-2.0 +** @aws-sdk/core@3.846.0 - https://www.npmjs.com/package/@aws-sdk/core/v/3.846.0 | Apache-2.0 ---------------- -** @aws-sdk/credential-provider-cognito-identity@3.839.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-cognito-identity/v/3.839.0 | Apache-2.0 +** @aws-sdk/credential-provider-cognito-identity@3.846.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-cognito-identity/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -4948,7 +4948,7 @@ The aws-cdk package includes the following third-party software/licensing: ---------------- -** @aws-sdk/credential-provider-env@3.839.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-env/v/3.839.0 | Apache-2.0 +** @aws-sdk/credential-provider-env@3.846.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-env/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -5153,11 +5153,11 @@ Apache License ---------------- -** @aws-sdk/credential-provider-http@3.839.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-http/v/3.839.0 | Apache-2.0 +** @aws-sdk/credential-provider-http@3.846.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-http/v/3.846.0 | Apache-2.0 ---------------- -** @aws-sdk/credential-provider-ini@3.839.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-ini/v/3.839.0 | Apache-2.0 +** @aws-sdk/credential-provider-ini@3.846.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-ini/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -5362,7 +5362,7 @@ Apache License ---------------- -** @aws-sdk/credential-provider-node@3.839.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-node/v/3.839.0 | Apache-2.0 +** @aws-sdk/credential-provider-node@3.846.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-node/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -5567,7 +5567,7 @@ Apache License ---------------- -** @aws-sdk/credential-provider-process@3.839.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-process/v/3.839.0 | Apache-2.0 +** @aws-sdk/credential-provider-process@3.846.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-process/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -5772,7 +5772,7 @@ Apache License ---------------- -** @aws-sdk/credential-provider-sso@3.839.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-sso/v/3.839.0 | Apache-2.0 +** @aws-sdk/credential-provider-sso@3.846.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-sso/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -5977,7 +5977,7 @@ Apache License ---------------- -** @aws-sdk/credential-provider-web-identity@3.839.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-web-identity/v/3.839.0 | Apache-2.0 +** @aws-sdk/credential-provider-web-identity@3.846.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-web-identity/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -6182,7 +6182,7 @@ Apache License ---------------- -** @aws-sdk/credential-providers@3.839.0 - https://www.npmjs.com/package/@aws-sdk/credential-providers/v/3.839.0 | Apache-2.0 +** @aws-sdk/credential-providers@3.846.0 - https://www.npmjs.com/package/@aws-sdk/credential-providers/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -6387,7 +6387,7 @@ Apache License ---------------- -** @aws-sdk/ec2-metadata-service@3.839.0 - https://www.npmjs.com/package/@aws-sdk/ec2-metadata-service/v/3.839.0 | Apache-2.0 +** @aws-sdk/ec2-metadata-service@3.846.0 - https://www.npmjs.com/package/@aws-sdk/ec2-metadata-service/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -6592,7 +6592,7 @@ Apache License ---------------- -** @aws-sdk/lib-storage@3.839.0 - https://www.npmjs.com/package/@aws-sdk/lib-storage/v/3.839.0 | Apache-2.0 +** @aws-sdk/lib-storage@3.846.0 - https://www.npmjs.com/package/@aws-sdk/lib-storage/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -6797,7 +6797,7 @@ Apache License ---------------- -** @aws-sdk/middleware-bucket-endpoint@3.830.0 - https://www.npmjs.com/package/@aws-sdk/middleware-bucket-endpoint/v/3.830.0 | Apache-2.0 +** @aws-sdk/middleware-bucket-endpoint@3.840.0 - https://www.npmjs.com/package/@aws-sdk/middleware-bucket-endpoint/v/3.840.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -7003,7 +7003,7 @@ Apache License ---------------- -** @aws-sdk/middleware-expect-continue@3.821.0 - https://www.npmjs.com/package/@aws-sdk/middleware-expect-continue/v/3.821.0 | Apache-2.0 +** @aws-sdk/middleware-expect-continue@3.840.0 - https://www.npmjs.com/package/@aws-sdk/middleware-expect-continue/v/3.840.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -7209,7 +7209,7 @@ Apache License ---------------- -** @aws-sdk/middleware-flexible-checksums@3.839.0 - https://www.npmjs.com/package/@aws-sdk/middleware-flexible-checksums/v/3.839.0 | Apache-2.0 +** @aws-sdk/middleware-flexible-checksums@3.846.0 - https://www.npmjs.com/package/@aws-sdk/middleware-flexible-checksums/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -7415,7 +7415,7 @@ Apache License ---------------- -** @aws-sdk/middleware-host-header@3.821.0 - https://www.npmjs.com/package/@aws-sdk/middleware-host-header/v/3.821.0 | Apache-2.0 +** @aws-sdk/middleware-host-header@3.840.0 - https://www.npmjs.com/package/@aws-sdk/middleware-host-header/v/3.840.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -7621,7 +7621,7 @@ Apache License ---------------- -** @aws-sdk/middleware-location-constraint@3.821.0 - https://www.npmjs.com/package/@aws-sdk/middleware-location-constraint/v/3.821.0 | Apache-2.0 +** @aws-sdk/middleware-location-constraint@3.840.0 - https://www.npmjs.com/package/@aws-sdk/middleware-location-constraint/v/3.840.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -7827,7 +7827,7 @@ Apache License ---------------- -** @aws-sdk/middleware-logger@3.821.0 - https://www.npmjs.com/package/@aws-sdk/middleware-logger/v/3.821.0 | Apache-2.0 +** @aws-sdk/middleware-logger@3.840.0 - https://www.npmjs.com/package/@aws-sdk/middleware-logger/v/3.840.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -8032,7 +8032,7 @@ Apache License ---------------- -** @aws-sdk/middleware-recursion-detection@3.821.0 - https://www.npmjs.com/package/@aws-sdk/middleware-recursion-detection/v/3.821.0 | Apache-2.0 +** @aws-sdk/middleware-recursion-detection@3.840.0 - https://www.npmjs.com/package/@aws-sdk/middleware-recursion-detection/v/3.840.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -8238,7 +8238,7 @@ Apache License ---------------- -** @aws-sdk/middleware-sdk-ec2@3.839.0 - https://www.npmjs.com/package/@aws-sdk/middleware-sdk-ec2/v/3.839.0 | Apache-2.0 +** @aws-sdk/middleware-sdk-ec2@3.845.0 - https://www.npmjs.com/package/@aws-sdk/middleware-sdk-ec2/v/3.845.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -8443,7 +8443,7 @@ Apache License ---------------- -** @aws-sdk/middleware-sdk-route53@3.821.0 - https://www.npmjs.com/package/@aws-sdk/middleware-sdk-route53/v/3.821.0 | Apache-2.0 +** @aws-sdk/middleware-sdk-route53@3.840.0 - https://www.npmjs.com/package/@aws-sdk/middleware-sdk-route53/v/3.840.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -8649,7 +8649,7 @@ Apache License ---------------- -** @aws-sdk/middleware-sdk-s3@3.839.0 - https://www.npmjs.com/package/@aws-sdk/middleware-sdk-s3/v/3.839.0 | Apache-2.0 +** @aws-sdk/middleware-sdk-s3@3.846.0 - https://www.npmjs.com/package/@aws-sdk/middleware-sdk-s3/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -8855,7 +8855,7 @@ Apache License ---------------- -** @aws-sdk/middleware-ssec@3.821.0 - https://www.npmjs.com/package/@aws-sdk/middleware-ssec/v/3.821.0 | Apache-2.0 +** @aws-sdk/middleware-ssec@3.840.0 - https://www.npmjs.com/package/@aws-sdk/middleware-ssec/v/3.840.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -9061,7 +9061,7 @@ Apache License ---------------- -** @aws-sdk/middleware-user-agent@3.839.0 - https://www.npmjs.com/package/@aws-sdk/middleware-user-agent/v/3.839.0 | Apache-2.0 +** @aws-sdk/middleware-user-agent@3.846.0 - https://www.npmjs.com/package/@aws-sdk/middleware-user-agent/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -9267,11 +9267,11 @@ Apache License ---------------- -** @aws-sdk/nested-clients@3.839.0 - https://www.npmjs.com/package/@aws-sdk/nested-clients/v/3.839.0 | Apache-2.0 +** @aws-sdk/nested-clients@3.846.0 - https://www.npmjs.com/package/@aws-sdk/nested-clients/v/3.846.0 | Apache-2.0 ---------------- -** @aws-sdk/region-config-resolver@3.821.0 - https://www.npmjs.com/package/@aws-sdk/region-config-resolver/v/3.821.0 | Apache-2.0 +** @aws-sdk/region-config-resolver@3.840.0 - https://www.npmjs.com/package/@aws-sdk/region-config-resolver/v/3.840.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -9476,7 +9476,7 @@ Apache License ---------------- -** @aws-sdk/signature-v4-multi-region@3.839.0 - https://www.npmjs.com/package/@aws-sdk/signature-v4-multi-region/v/3.839.0 | Apache-2.0 +** @aws-sdk/signature-v4-multi-region@3.846.0 - https://www.npmjs.com/package/@aws-sdk/signature-v4-multi-region/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -9682,7 +9682,7 @@ Apache License ---------------- -** @aws-sdk/token-providers@3.839.0 - https://www.npmjs.com/package/@aws-sdk/token-providers/v/3.839.0 | Apache-2.0 +** @aws-sdk/token-providers@3.846.0 - https://www.npmjs.com/package/@aws-sdk/token-providers/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -10092,7 +10092,7 @@ Apache License ---------------- -** @aws-sdk/util-endpoints@3.828.0 - https://www.npmjs.com/package/@aws-sdk/util-endpoints/v/3.828.0 | Apache-2.0 +** @aws-sdk/util-endpoints@3.845.0 - https://www.npmjs.com/package/@aws-sdk/util-endpoints/v/3.845.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -10297,7 +10297,7 @@ Apache License ---------------- -** @aws-sdk/util-format-url@3.821.0 - https://www.npmjs.com/package/@aws-sdk/util-format-url/v/3.821.0 | Apache-2.0 +** @aws-sdk/util-format-url@3.840.0 - https://www.npmjs.com/package/@aws-sdk/util-format-url/v/3.840.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -10502,7 +10502,7 @@ Apache License ---------------- -** @aws-sdk/util-user-agent-node@3.839.0 - https://www.npmjs.com/package/@aws-sdk/util-user-agent-node/v/3.839.0 | Apache-2.0 +** @aws-sdk/util-user-agent-node@3.846.0 - https://www.npmjs.com/package/@aws-sdk/util-user-agent-node/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -11323,7 +11323,7 @@ Apache License ---------------- -** @smithy/core@3.6.0 - https://www.npmjs.com/package/@smithy/core/v/3.6.0 | Apache-2.0 +** @smithy/core@3.7.0 - https://www.npmjs.com/package/@smithy/core/v/3.7.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -12558,7 +12558,7 @@ Apache License ---------------- -** @smithy/fetch-http-handler@5.0.4 - https://www.npmjs.com/package/@smithy/fetch-http-handler/v/5.0.4 | Apache-2.0 +** @smithy/fetch-http-handler@5.1.0 - https://www.npmjs.com/package/@smithy/fetch-http-handler/v/5.1.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -13788,7 +13788,7 @@ Apache License ---------------- -** @smithy/middleware-endpoint@4.1.13 - https://www.npmjs.com/package/@smithy/middleware-endpoint/v/4.1.13 | Apache-2.0 +** @smithy/middleware-endpoint@4.1.15 - https://www.npmjs.com/package/@smithy/middleware-endpoint/v/4.1.15 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -13993,7 +13993,7 @@ Apache License ---------------- -** @smithy/middleware-retry@4.1.14 - https://www.npmjs.com/package/@smithy/middleware-retry/v/4.1.14 | Apache-2.0 +** @smithy/middleware-retry@4.1.16 - https://www.npmjs.com/package/@smithy/middleware-retry/v/4.1.16 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -14815,7 +14815,7 @@ Apache License ---------------- -** @smithy/node-http-handler@4.0.6 - https://www.npmjs.com/package/@smithy/node-http-handler/v/4.0.6 | Apache-2.0 +** @smithy/node-http-handler@4.1.0 - https://www.npmjs.com/package/@smithy/node-http-handler/v/4.1.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -16459,7 +16459,7 @@ Apache License ---------------- -** @smithy/smithy-client@4.4.5 - https://www.npmjs.com/package/@smithy/smithy-client/v/4.4.5 | Apache-2.0 +** @smithy/smithy-client@4.4.7 - https://www.npmjs.com/package/@smithy/smithy-client/v/4.4.7 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -18307,7 +18307,7 @@ Apache License ---------------- -** @smithy/util-defaults-mode-node@4.0.21 - https://www.npmjs.com/package/@smithy/util-defaults-mode-node/v/4.0.21 | Apache-2.0 +** @smithy/util-defaults-mode-node@4.0.23 - https://www.npmjs.com/package/@smithy/util-defaults-mode-node/v/4.0.23 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -19333,7 +19333,7 @@ Apache License ---------------- -** @smithy/util-stream@4.2.2 - https://www.npmjs.com/package/@smithy/util-stream/v/4.2.2 | Apache-2.0 +** @smithy/util-stream@4.2.3 - https://www.npmjs.com/package/@smithy/util-stream/v/4.2.3 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -20410,7 +20410,7 @@ SOFTWARE. ---------------- -** agent-base@7.1.3 - https://www.npmjs.com/package/agent-base/v/7.1.3 | MIT +** agent-base@7.1.4 - https://www.npmjs.com/package/agent-base/v/7.1.4 | MIT (The MIT License) Copyright (c) 2013 Nathan Rajlich @@ -20989,7 +20989,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI ---------------- -** cdk-from-cfn@0.226.0 - https://www.npmjs.com/package/cdk-from-cfn/v/0.226.0 | MIT OR Apache-2.0 +** cdk-from-cfn@0.230.0 - https://www.npmjs.com/package/cdk-from-cfn/v/0.230.0 | MIT OR Apache-2.0 ---------------- @@ -21705,7 +21705,7 @@ THE SOFTWARE. ---------------- -** fast-xml-parser@4.4.1 - https://www.npmjs.com/package/fast-xml-parser/v/4.4.1 | MIT +** fast-xml-parser@5.2.5 - https://www.npmjs.com/package/fast-xml-parser/v/5.2.5 | MIT MIT License Copyright (c) 2017 Amit Kumar Gupta @@ -21795,7 +21795,7 @@ OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHE ---------------- -** get-uri@6.0.4 - https://www.npmjs.com/package/get-uri/v/6.0.4 | MIT +** get-uri@6.0.5 - https://www.npmjs.com/package/get-uri/v/6.0.5 | MIT (The MIT License) Copyright (c) 2014 Nathan Rajlich @@ -23269,7 +23269,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ---------------- -** socks@2.8.5 - https://www.npmjs.com/package/socks/v/2.8.5 | MIT +** socks@2.8.6 - https://www.npmjs.com/package/socks/v/2.8.6 | MIT The MIT License (MIT) Copyright (c) 2013 Josh Glazebrook @@ -23534,7 +23534,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI ---------------- -** strnum@1.1.2 - https://www.npmjs.com/package/strnum/v/1.1.2 | MIT +** strnum@2.1.1 - https://www.npmjs.com/package/strnum/v/2.1.1 | MIT MIT License Copyright (c) 2021 Natural Intelligence diff --git a/packages/aws-cdk/lib/api/refactor.ts b/packages/aws-cdk/lib/api/refactor.ts new file mode 100644 index 000000000..7c6a9861e --- /dev/null +++ b/packages/aws-cdk/lib/api/refactor.ts @@ -0,0 +1,2 @@ +/* eslint-disable import/no-relative-packages */ +export { mappingsByEnvironment, parseMappingGroups } from '../../../@aws-cdk/toolkit-lib/lib/actions/refactor/private/mapping-helpers'; diff --git a/packages/aws-cdk/lib/cli/cdk-toolkit.ts b/packages/aws-cdk/lib/cli/cdk-toolkit.ts index 4b900b1df..4e023d7b7 100644 --- a/packages/aws-cdk/lib/cli/cdk-toolkit.ts +++ b/packages/aws-cdk/lib/cli/cdk-toolkit.ts @@ -3,7 +3,7 @@ import { format } from 'util'; import { RequireApproval } from '@aws-cdk/cloud-assembly-schema'; import * as cxapi from '@aws-cdk/cx-api'; import type { DeploymentMethod, ToolkitAction, ToolkitOptions } from '@aws-cdk/toolkit-lib'; -import { StackSelectionStrategy, ToolkitError, PermissionChangeType, Toolkit, MappingSource } from '@aws-cdk/toolkit-lib'; +import { PermissionChangeType, Toolkit, ToolkitError } from '@aws-cdk/toolkit-lib'; import * as chalk from 'chalk'; import * as chokidar from 'chokidar'; import * as fs from 'fs-extra'; @@ -12,14 +12,27 @@ import * as uuid from 'uuid'; import { CliIoHost } from './io-host'; import type { Configuration } from './user-configuration'; import { PROJECT_CONFIG } from './user-configuration'; +import type { IoHelper } from '../../lib/api-private'; import { asIoHelper, cfnApi, tagsForStack } from '../../lib/api-private'; import type { AssetBuildNode, AssetPublishNode, Concurrency, StackNode, WorkGraph } from '../api'; -import { DEFAULT_TOOLKIT_STACK_NAME, DiffFormatter, WorkGraphBuilder, removeNonImportResources, ResourceImporter, ResourceMigrator, GarbageCollector, CloudWatchLogEventMonitor, findCloudWatchLogGroups } from '../api'; +import { + CloudWatchLogEventMonitor, + DEFAULT_TOOLKIT_STACK_NAME, + DiffFormatter, + findCloudWatchLogGroups, + GarbageCollector, + removeNonImportResources, + ResourceImporter, + ResourceMigrator, + StackSelectionStrategy, + WorkGraphBuilder, +} from '../api'; import type { SdkProvider } from '../api/aws-auth'; import type { BootstrapEnvironmentOptions } from '../api/bootstrap'; import { Bootstrapper } from '../api/bootstrap'; import { ExtendedStackSelection, StackCollection } from '../api/cloud-assembly'; import type { Deployments, SuccessfulDeployStackResult } from '../api/deployments'; +import { mappingsByEnvironment, parseMappingGroups } from '../api/refactor'; import { type Tag } from '../api/tags'; import { StackActivityProgress } from '../commands/deploy'; import { listStacks } from '../commands/list-stacks'; @@ -27,7 +40,7 @@ import type { FromScan, GenerateTemplateOutput } from '../commands/migrate'; import { appendWarningsToReadme, buildCfnClient, - buildGenertedTemplateOutput, + buildGeneratedTemplateOutput, CfnTemplateGeneratorProvider, generateCdkApp, generateStack, @@ -42,7 +55,6 @@ import { } from '../commands/migrate'; import type { CloudAssembly, CloudExecutable, StackSelector } from '../cxapp'; import { DefaultSelection, environmentsFromDescriptors, globEnvironmentsFromStacks, looksLikeGlob } from '../cxapp'; -import { debug, error, highlight, info, result as logResult, success, warning } from '../logging'; import { deserializeStructure, formatErrorMessage, @@ -185,7 +197,7 @@ export class CdkToolkit { public async metadata(stackName: string, json: boolean) { const stacks = await this.selectSingleStackByName(stackName); - printSerializedObject(stacks.firstStack.manifest.metadata ?? {}, json); + await printSerializedObject(this.ioHost.asIoHelper(), stacks.firstStack.manifest.metadata ?? {}, json); } public async acknowledge(noticeId: string) { @@ -198,7 +210,7 @@ export class CdkToolkit { public async cliTelemetry(enable: boolean) { this.props.configuration.context.set('cli-telemetry', enable); await this.props.configuration.saveContext(); - info(`Telemetry ${enable ? 'enabled' : 'disabled'}`); + await this.ioHost.asIoHelper().defaults.info(`Telemetry ${enable ? 'enabled' : 'disabled'}`); } public async diff(options: DiffOptions): Promise { @@ -241,8 +253,8 @@ export class CdkToolkit { const securityDiff = formatter.formatSecurityDiff(); // Warn, count, and display the diff only if the reported changes are broadening permissions if (securityDiff.permissionChangeType === PermissionChangeType.BROADENING) { - warning('This deployment will make potentially sensitive changes according to your current security approval level.\nPlease confirm you intend to make the following modifications:\n'); - info(securityDiff.formattedDiff); + await this.ioHost.asIoHelper().defaults.warn('This deployment will make potentially sensitive changes according to your current security approval level.\nPlease confirm you intend to make the following modifications:\n'); + await this.ioHost.asIoHelper().defaults.info(securityDiff.formattedDiff); diffs += 1; } } else { @@ -252,9 +264,13 @@ export class CdkToolkit { quiet, }); diffs = diff.numStacksWithChanges; - info(diff.formattedDiff); + await this.ioHost.asIoHelper().defaults.info(diff.formattedDiff); } } else { + const allMappings = options.includeMoves + ? await mappingsByEnvironment(stacks.stackArtifacts, this.props.sdkProvider, true) + : []; + // Compare N stacks against deployed templates for (const stack of stacks.stackArtifacts) { const templateWithNestedStacks = await this.props.deployments.readCurrentTemplateWithNestedStacks( @@ -284,9 +300,9 @@ export class CdkToolkit { tryLookupRole: true, }); } catch (e: any) { - debug(formatErrorMessage(e)); + await this.ioHost.asIoHelper().defaults.debug(formatErrorMessage(e)); if (!quiet) { - info( + await this.ioHost.asIoHelper().defaults.info( `Checking if the stack ${stack.stackName} exists before creating the changeset has failed, will base the diff on template differences (run again with -v to see the reason)\n`, ); } @@ -305,12 +321,16 @@ export class CdkToolkit { importExistingResources: options.importExistingResources, }); } else { - debug( + await this.ioHost.asIoHelper().defaults.debug( `the stack '${stack.stackName}' has not been deployed to CloudFormation or describeStacks call failed, skipping changeset creation.`, ); } } + const mappings = allMappings.find(m => + m.environment.region === stack.environment.region && m.environment.account === stack.environment.account, + )?.mappings ?? {}; + const formatter = new DiffFormatter({ templateInfo: { oldTemplate: currentTemplate, @@ -318,6 +338,7 @@ export class CdkToolkit { changeSet, isImport: !!resourcesToImport, nestedStacks, + mappings, }, }); @@ -325,8 +346,8 @@ export class CdkToolkit { const securityDiff = formatter.formatSecurityDiff(); // Warn, count, and display the diff only if the reported changes are broadening permissions if (securityDiff.permissionChangeType === PermissionChangeType.BROADENING) { - warning('This deployment will make potentially sensitive changes according to your current security approval level.\nPlease confirm you intend to make the following modifications:\n'); - info(securityDiff.formattedDiff); + await this.ioHost.asIoHelper().defaults.warn('This deployment will make potentially sensitive changes according to your current security approval level.\nPlease confirm you intend to make the following modifications:\n'); + await this.ioHost.asIoHelper().defaults.info(securityDiff.formattedDiff); diffs += 1; } } else { @@ -335,13 +356,13 @@ export class CdkToolkit { contextLines, quiet, }); - info(diff.formattedDiff); + await this.ioHost.asIoHelper().defaults.info(diff.formattedDiff); diffs += diff.numStacksWithChanges; } } } - info(format('\n✨ Number of stacks with differences: %s\n', diffs)); + await this.ioHost.asIoHelper().defaults.info(format('\n✨ Number of stacks with differences: %s\n', diffs)); return diffs && options.fail ? 1 : 0; } @@ -364,10 +385,10 @@ export class CdkToolkit { options.ignoreNoStacks, ); const elapsedSynthTime = new Date().getTime() - startSynthTime; - info(`\n✨ Synthesis time: ${formatTime(elapsedSynthTime)}s\n`); + await this.ioHost.asIoHelper().defaults.info(`\n✨ Synthesis time: ${formatTime(elapsedSynthTime)}s\n`); if (stackCollection.stackCount === 0) { - error('This app contains no stacks'); + await this.ioHost.asIoHelper().defaults.error('This app contains no stacks'); return; } @@ -385,10 +406,10 @@ export class CdkToolkit { const parameterMap = buildParameterMap(options.parameters); if (options.deploymentMethod?.method === 'hotswap') { - warning( + await this.ioHost.asIoHelper().defaults.warn( '⚠️ The --hotswap and --hotswap-fallback flags deliberately introduce CloudFormation drift to speed up deployments', ); - warning('⚠️ They should only be used for development - never use them for your production Stacks!\n'); + await this.ioHost.asIoHelper().defaults.warn('⚠️ They should only be used for development - never use them for your production Stacks!\n'); } const stacks = stackCollection.stackArtifacts; @@ -421,7 +442,7 @@ export class CdkToolkit { const deployStack = async (stackNode: StackNode) => { const stack = stackNode.stack; if (stackCollection.stackCount !== 1) { - highlight(stack.displayName); + await this.ioHost.asIoHelper().defaults.info(chalk.bold(stack.displayName)); } if (!stack.environment) { @@ -434,9 +455,9 @@ export class CdkToolkit { if (Object.keys(stack.template.Resources || {}).length === 0) { // The generated stack has no resources if (!(await this.props.deployments.stackExists({ stack }))) { - warning('%s: stack has no resources, skipping deployment.', chalk.bold(stack.displayName)); + await this.ioHost.asIoHelper().defaults.warn('%s: stack has no resources, skipping deployment.', chalk.bold(stack.displayName)); } else { - warning('%s: stack has no resources, deleting existing stack.', chalk.bold(stack.displayName)); + await this.ioHost.asIoHelper().defaults.warn('%s: stack has no resources, deleting existing stack.', chalk.bold(stack.displayName)); await this.destroy({ selector: { patterns: [stack.hierarchicalId] }, exclusively: true, @@ -458,7 +479,7 @@ export class CdkToolkit { }); const securityDiff = formatter.formatSecurityDiff(); if (requiresApproval(requireApproval, securityDiff.permissionChangeType)) { - info(securityDiff.formattedDiff); + await this.ioHost.asIoHelper().defaults.info(securityDiff.formattedDiff); await askUserConfirmation( this.ioHost, concurrency, @@ -484,7 +505,7 @@ export class CdkToolkit { } const stackIndex = stacks.indexOf(stack) + 1; - info(`${chalk.bold(stack.displayName)}: deploying... [${stackIndex}/${stackCollection.stackCount}]`); + await this.ioHost.asIoHelper().defaults.info(`${chalk.bold(stack.displayName)}: deploying... [${stackIndex}/${stackCollection.stackCount}]`); const startDeployTime = new Date().getTime(); let tags = options.tags; @@ -534,7 +555,7 @@ export class CdkToolkit { : `Stack is in a paused fail state (${r.status}) and command line arguments do not include "--no-rollback"`; if (options.force) { - warning(`${motivation}. Rolling back first (--force).`); + await this.ioHost.asIoHelper().defaults.warn(`${motivation}. Rolling back first (--force).`); } else { await askUserConfirmation( this.ioHost, @@ -560,7 +581,7 @@ export class CdkToolkit { const motivation = 'Change includes a replacement which cannot be deployed with "--no-rollback"'; if (options.force) { - warning(`${motivation}. Proceeding with regular deployment (--force).`); + await this.ioHost.asIoHelper().defaults.warn(`${motivation}. Proceeding with regular deployment (--force).`); } else { await askUserConfirmation( this.ioHost, @@ -584,24 +605,24 @@ export class CdkToolkit { ? ' ✅ %s (no changes)' : ' ✅ %s'; - success('\n' + message, stack.displayName); + await this.ioHost.asIoHelper().defaults.info(chalk.green('\n' + message), stack.displayName); elapsedDeployTime = new Date().getTime() - startDeployTime; - info(`\n✨ Deployment time: ${formatTime(elapsedDeployTime)}s\n`); + await this.ioHost.asIoHelper().defaults.info(`\n✨ Deployment time: ${formatTime(elapsedDeployTime)}s\n`); if (Object.keys(deployResult.outputs).length > 0) { - info('Outputs:'); + await this.ioHost.asIoHelper().defaults.info('Outputs:'); stackOutputs[stack.stackName] = deployResult.outputs; } for (const name of Object.keys(deployResult.outputs).sort()) { const value = deployResult.outputs[name]; - info(`${chalk.cyan(stack.id)}.${chalk.cyan(name)} = ${chalk.underline(chalk.cyan(value))}`); + await this.ioHost.asIoHelper().defaults.info(`${chalk.cyan(stack.id)}.${chalk.cyan(name)} = ${chalk.underline(chalk.cyan(value))}`); } - info('Stack ARN:'); + await this.ioHost.asIoHelper().defaults.info('Stack ARN:'); - logResult(deployResult.stackArn); + await this.ioHost.asIoHelper().defaults.result(deployResult.stackArn); } catch (e: any) { // It has to be exactly this string because an integration test tests for // "bold(stackname) failed: ResourceNotReady: " @@ -628,7 +649,7 @@ export class CdkToolkit { }); } } - info(`\n✨ Total time: ${formatTime(elapsedSynthTime + elapsedDeployTime)}s\n`); + await this.ioHost.asIoHelper().defaults.info(`\n✨ Total time: ${formatTime(elapsedSynthTime + elapsedDeployTime)}s\n`); }; const assetBuildTime = options.assetBuildTime ?? AssetBuildTime.ALL_BEFORE_DEPLOY; @@ -640,7 +661,7 @@ export class CdkToolkit { // ...but only warn if the user explicitly requested "bar" progress if (options.progress && options.progress != StackActivityProgress.EVENTS) { - warning('⚠️ The --concurrency flag only supports --progress "events". Switching to "events".'); + await this.ioHost.asIoHelper().defaults.warn('⚠️ The --concurrency flag only supports --progress "events". Switching to "events".'); } } @@ -693,17 +714,17 @@ export class CdkToolkit { const startSynthTime = new Date().getTime(); const stackCollection = await this.selectStacksForDeploy(options.selector, true); const elapsedSynthTime = new Date().getTime() - startSynthTime; - info(`\n✨ Synthesis time: ${formatTime(elapsedSynthTime)}s\n`); + await this.ioHost.asIoHelper().defaults.info(`\n✨ Synthesis time: ${formatTime(elapsedSynthTime)}s\n`); if (stackCollection.stackCount === 0) { - error('No stacks selected'); + await this.ioHost.asIoHelper().defaults.error('No stacks selected'); return; } let anyRollbackable = false; for (const stack of stackCollection.stackArtifacts) { - info('Rolling back %s', chalk.bold(stack.displayName)); + await this.ioHost.asIoHelper().defaults.info('Rolling back %s', chalk.bold(stack.displayName)); const startRollbackTime = new Date().getTime(); try { const result = await this.props.deployments.rollbackStack({ @@ -718,9 +739,9 @@ export class CdkToolkit { anyRollbackable = true; } const elapsedRollbackTime = new Date().getTime() - startRollbackTime; - info(`\n✨ Rollback time: ${formatTime(elapsedRollbackTime).toString()}s\n`); + await this.ioHost.asIoHelper().defaults.info(`\n✨ Rollback time: ${formatTime(elapsedRollbackTime).toString()}s\n`); } catch (e: any) { - error('\n ❌ %s failed: %s', chalk.bold(stack.displayName), formatErrorMessage(e)); + await this.ioHost.asIoHelper().defaults.error('\n ❌ %s failed: %s', chalk.bold(stack.displayName), formatErrorMessage(e)); throw new ToolkitError('Rollback failed (use --force to orphan failing resources)'); } } @@ -732,14 +753,14 @@ export class CdkToolkit { public async watch(options: WatchOptions) { const rootDir = path.dirname(path.resolve(PROJECT_CONFIG)); const ioHelper = asIoHelper(this.ioHost, 'watch'); - debug("root directory used for 'watch' is: %s", rootDir); + await this.ioHost.asIoHelper().defaults.debug("root directory used for 'watch' is: %s", rootDir); const watchSettings: { include?: string | string[]; exclude: string | string[] } | undefined = this.props.configuration.settings.get(['watch']); if (!watchSettings) { throw new ToolkitError( "Cannot use the 'watch' command without specifying at least one directory to monitor. " + - 'Make sure to add a "watch" key to your cdk.json', + 'Make sure to add a "watch" key to your cdk.json', ); } @@ -752,7 +773,7 @@ export class CdkToolkit { rootDir, returnRootDirIfEmpty: true, }); - debug("'include' patterns for 'watch': %s", watchIncludes); + await this.ioHost.asIoHelper().defaults.debug("'include' patterns for 'watch': %s", watchIncludes); // For the "exclude" subkey under the "watch" key, // the behavior is to add some default excludes in addition to the ones specified by the user: @@ -765,7 +786,7 @@ export class CdkToolkit { rootDir, returnRootDirIfEmpty: false, }).concat(`${outputDir}/**`, '**/.*', '**/.*/**', '**/node_modules/**'); - debug("'exclude' patterns for 'watch': %s", watchExcludes); + await this.ioHost.asIoHelper().defaults.debug("'exclude' patterns for 'watch': %s", watchExcludes); // Since 'cdk deploy' is a relatively slow operation for a 'watch' process, // introduce a concurrency latch that tracks the state. @@ -795,7 +816,7 @@ export class CdkToolkit { // TypeScript doesn't realize latch can change between 'awaits', // and thinks the above 'while' condition is always 'false' without the cast latch = 'deploying'; - info("Detected file changes during deployment. Invoking 'cdk deploy' again"); + await this.ioHost.asIoHelper().defaults.info("Detected file changes during deployment. Invoking 'cdk deploy' again"); await this.invokeDeployFromWatch(options, cloudWatchLogMonitor); } latch = 'open'; @@ -809,22 +830,22 @@ export class CdkToolkit { }) .on('ready', async () => { latch = 'open'; - debug("'watch' received the 'ready' event. From now on, all file changes will trigger a deployment"); - info("Triggering initial 'cdk deploy'"); + await this.ioHost.asIoHelper().defaults.debug("'watch' received the 'ready' event. From now on, all file changes will trigger a deployment"); + await this.ioHost.asIoHelper().defaults.info("Triggering initial 'cdk deploy'"); await deployAndWatch(); }) .on('all', async (event: 'add' | 'addDir' | 'change' | 'unlink' | 'unlinkDir', filePath?: string) => { if (latch === 'pre-ready') { - info(`'watch' is observing ${event === 'addDir' ? 'directory' : 'the file'} '%s' for changes`, filePath); + await this.ioHost.asIoHelper().defaults.info(`'watch' is observing ${event === 'addDir' ? 'directory' : 'the file'} '%s' for changes`, filePath); } else if (latch === 'open') { - info("Detected change to '%s' (type: %s). Triggering 'cdk deploy'", filePath, event); + await this.ioHost.asIoHelper().defaults.info("Detected change to '%s' (type: %s). Triggering 'cdk deploy'", filePath, event); await deployAndWatch(); } else { // this means latch is either 'deploying' or 'queued' latch = 'queued'; - info( + await this.ioHost.asIoHelper().defaults.info( "Detected change to '%s' (type: %s) while 'cdk deploy' is still running. " + - 'Will queue for another deployment after this one finishes', + 'Will queue for another deployment after this one finishes', filePath, event, ); @@ -852,7 +873,7 @@ export class CdkToolkit { const stack = stacks.stackArtifacts[0]; - highlight(stack.displayName); + await this.ioHost.asIoHelper().defaults.info(chalk.bold(stack.displayName)); const resourceImporter = new ResourceImporter(stack, { deployments: this.props.deployments, @@ -860,7 +881,7 @@ export class CdkToolkit { }); const { additions, hasNonAdditions } = await resourceImporter.discoverImportableResources(options.force); if (additions.length === 0) { - warning( + await this.ioHost.asIoHelper().defaults.warn( '%s: no new resources compared to the currently deployed stack, skipping import.', chalk.bold(stack.displayName), ); @@ -873,7 +894,7 @@ export class CdkToolkit { : await resourceImporter.loadResourceIdentifiers(additions, options.resourceMappingFile); if (actualImport.importResources.length === 0) { - warning('No resources selected for import.'); + await this.ioHost.asIoHelper().defaults.warn('No resources selected for import.'); return; } @@ -885,12 +906,12 @@ export class CdkToolkit { spaces: 2, encoding: 'utf8', }); - info('%s: mapping file written.', outputFile); + await this.ioHost.asIoHelper().defaults.info('%s: mapping file written.', outputFile); return; } // Import the resources according to the given mapping - info('%s: importing resources into stack...', chalk.bold(stack.displayName)); + await this.ioHost.asIoHelper().defaults.info('%s: importing resources into stack...', chalk.bold(stack.displayName)); const tags = tagsForStack(stack); await resourceImporter.importResourcesFromMap(actualImport, { roleArn: options.roleArn, @@ -901,21 +922,21 @@ export class CdkToolkit { }); // Notify user of next steps - info( + await this.ioHost.asIoHelper().defaults.info( `Import operation complete. We recommend you run a ${chalk.blueBright('drift detection')} operation ` + - 'to confirm your CDK app resource definitions are up-to-date. Read more here: ' + - chalk.underline.blueBright( - 'https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/detect-drift-stack.html', - ), + 'to confirm your CDK app resource definitions are up-to-date. Read more here: ' + + chalk.underline.blueBright( + 'https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/detect-drift-stack.html', + ), ); if (actualImport.importResources.length < additions.length) { - info(''); - warning( + await this.ioHost.asIoHelper().defaults.info(''); + await this.ioHost.asIoHelper().defaults.warn( `Some resources were skipped. Run another ${chalk.blueBright('cdk import')} or a ${chalk.blueBright('cdk deploy')} to bring the stack up-to-date with your CDK app definition.`, ); } else if (hasNonAdditions) { - info(''); - warning( + await this.ioHost.asIoHelper().defaults.info(''); + await this.ioHost.asIoHelper().defaults.warn( `Your app has pending updates or deletes excluded from this import operation. Run a ${chalk.blueBright('cdk deploy')} to bring the stack up-to-date with your CDK app definition.`, ); } @@ -939,16 +960,16 @@ export class CdkToolkit { const action = options.fromDeploy ? 'deploy' : 'destroy'; for (const [index, stack] of stacks.stackArtifacts.entries()) { - success('%s: destroying... [%s/%s]', chalk.blue(stack.displayName), index + 1, stacks.stackCount); + await this.ioHost.asIoHelper().defaults.info(chalk.green('%s: destroying... [%s/%s]'), chalk.blue(stack.displayName), index + 1, stacks.stackCount); try { await this.props.deployments.destroyStack({ stack, deployName: stack.stackName, roleArn: options.roleArn, }); - success(`\n ✅ %s: ${action}ed`, chalk.blue(stack.displayName)); + await this.ioHost.asIoHelper().defaults.info(chalk.green(`\n ✅ %s: ${action}ed`), chalk.blue(stack.displayName)); } catch (e) { - error(`\n ❌ %s: ${action} failed`, chalk.blue(stack.displayName), e); + await this.ioHost.asIoHelper().defaults.error(`\n ❌ %s: ${action} failed`, chalk.blue(stack.displayName), e); throw e; } } @@ -963,43 +984,33 @@ export class CdkToolkit { }); if (options.long && options.showDeps) { - printSerializedObject(stacks, options.json ?? false); + await printSerializedObject(this.ioHost.asIoHelper(), stacks, options.json ?? false); return 0; } if (options.showDeps) { - const stackDeps = []; - - for (const stack of stacks) { - stackDeps.push({ - id: stack.id, - dependencies: stack.dependencies, - }); - } - - printSerializedObject(stackDeps, options.json ?? false); + const stackDeps = stacks.map(stack => ({ + id: stack.id, + dependencies: stack.dependencies, + })); + await printSerializedObject(this.ioHost.asIoHelper(), stackDeps, options.json ?? false); return 0; } if (options.long) { - const long = []; - - for (const stack of stacks) { - long.push({ - id: stack.id, - name: stack.name, - environment: stack.environment, - }); - } - printSerializedObject(long, options.json ?? false); + const long = stacks.map(stack => ({ + id: stack.id, + name: stack.name, + environment: stack.environment, + })); + await printSerializedObject(this.ioHost.asIoHelper(), long, options.json ?? false); return 0; } // just print stack IDs for (const stack of stacks) { - logResult(stack.id); + await this.ioHost.asIoHelper().defaults.result(stack.id); } - return 0; // exit-code } @@ -1024,14 +1035,14 @@ export class CdkToolkit { // if we have a single stack, print it to STDOUT if (stacks.stackCount === 1) { if (!quiet) { - printSerializedObject(obscureTemplate(stacks.firstStack.template), json ?? false); + await printSerializedObject(this.ioHost.asIoHelper(), obscureTemplate(stacks.firstStack.template), json ?? false); } return undefined; } // not outputting template to stdout, let's explain things to the user a little bit... - success(`Successfully synthesized to ${chalk.blue(path.resolve(stacks.assembly.directory))}`); - info( + await this.ioHost.asIoHelper().defaults.info(chalk.green(`Successfully synthesized to ${chalk.blue(path.resolve(stacks.assembly.directory))}`)); + await this.ioHost.asIoHelper().defaults.info( `Supply a stack id (${stacks.stackArtifacts.map((s) => chalk.green(s.hierarchicalId)).join(', ')}) to display its template.`, ); @@ -1059,15 +1070,15 @@ export class CdkToolkit { // eslint-disable-next-line @cdklabs/promiseall-no-unbounded-parallelism await Promise.all(environments.map((environment) => limit(async () => { - success(' ⏳ Bootstrapping environment %s...', chalk.blue(environment.name)); + await this.ioHost.asIoHelper().defaults.info(chalk.green(' ⏳ Bootstrapping environment %s...'), chalk.blue(environment.name)); try { const result = await bootstrapper.bootstrapEnvironment(environment, this.props.sdkProvider, options); const message = result.noOp ? ' ✅ Environment %s bootstrapped (no changes).' : ' ✅ Environment %s bootstrapped.'; - success(message, chalk.blue(environment.name)); + await this.ioHost.asIoHelper().defaults.info(chalk.green(message), chalk.blue(environment.name)); } catch (e) { - error(' ❌ Environment %s failed bootstrapping: %s', chalk.blue(environment.name), e); + await this.ioHost.asIoHelper().defaults.error(' ❌ Environment %s failed bootstrapping: %s', chalk.blue(environment.name), e); throw e; } }))); @@ -1081,7 +1092,7 @@ export class CdkToolkit { const environments = await this.defineEnvironments(userEnvironmentSpecs); for (const environment of environments) { - success(' ⏳ Garbage Collecting environment %s...', chalk.blue(environment.name)); + await this.ioHost.asIoHelper().defaults.info(chalk.green(' ⏳ Garbage Collecting environment %s...'), chalk.blue(environment.name)); const gc = new GarbageCollector({ sdkProvider: this.props.sdkProvider, ioHelper: asIoHelper(this.ioHost, 'gc'), @@ -1134,7 +1145,7 @@ export class CdkToolkit { * @param options - Options for CDK app creation */ public async migrate(options: MigrateOptions): Promise { - warning('This command is an experimental feature.'); + await this.ioHost.asIoHelper().defaults.warn('This command is an experimental feature.'); const language = options.language?.toLowerCase() ?? 'typescript'; const environment = setEnvironment(options.account, options.region); let generateTemplateOutput: GenerateTemplateOutput | undefined; @@ -1151,6 +1162,7 @@ export class CdkToolkit { fromScan: options.fromScan, sdkProvider: this.props.sdkProvider, environment: environment, + ioHelper: this.ioHost.asIoHelper(), }); templateToDelete = generateTemplateOutput.templateId; } else if (scanType == TemplateSourceOptions.PATH) { @@ -1161,9 +1173,9 @@ export class CdkToolkit { if (templateId) { // if we have a template id, we can call describe generated template to get the resource identifiers // resource metadata, and template source to generate the template - cfn = new CfnTemplateGeneratorProvider(await buildCfnClient(this.props.sdkProvider, environment)); + cfn = new CfnTemplateGeneratorProvider(await buildCfnClient(this.props.sdkProvider, environment), this.ioHost.asIoHelper()); const generatedTemplateSummary = await cfn.describeGeneratedTemplate(templateId); - generateTemplateOutput = buildGenertedTemplateOutput( + generateTemplateOutput = buildGeneratedTemplateOutput( generatedTemplateSummary, templateBody, generatedTemplateSummary.GeneratedTemplateId!, @@ -1192,13 +1204,13 @@ export class CdkToolkit { throw new ToolkitError(`Invalid source option provided: ${scanType}`); } const stack = generateStack(generateTemplateOutput.migrateJson.templateBody, options.stackName, language); - success(' ⏳ Generating CDK app for %s...', chalk.blue(options.stackName)); - await generateCdkApp(options.stackName, stack!, language, options.outputPath, options.compress); + await this.ioHost.asIoHelper().defaults.info(chalk.green(' ⏳ Generating CDK app for %s...'), chalk.blue(options.stackName)); + await generateCdkApp(this.ioHost.asIoHelper(), options.stackName, stack!, language, options.outputPath, options.compress); if (generateTemplateOutput) { writeMigrateJsonFile(options.outputPath, options.stackName, generateTemplateOutput.migrateJson); } if (isThereAWarning(generateTemplateOutput)) { - warning( + await this.ioHost.asIoHelper().defaults.warn( ' ⚠️ Some resources could not be migrated completely. Please review the README.md file for more information.', ); appendWarningsToReadme( @@ -1207,12 +1219,12 @@ export class CdkToolkit { ); } } catch (e) { - error(' ❌ Migrate failed for `%s`: %s', options.stackName, (e as Error).message); + await this.ioHost.asIoHelper().defaults.error(' ❌ Migrate failed for `%s`: %s', options.stackName, (e as Error).message); throw e; } finally { if (templateToDelete) { if (!cfn) { - cfn = new CfnTemplateGeneratorProvider(await buildCfnClient(this.props.sdkProvider, environment)); + cfn = new CfnTemplateGeneratorProvider(await buildCfnClient(this.props.sdkProvider, environment), this.ioHost.asIoHelper()); } if (!process.env.MIGRATE_INTEG_TEST) { await cfn.deleteGeneratedTemplate(templateToDelete); @@ -1222,63 +1234,43 @@ export class CdkToolkit { } public async refactor(options: RefactorOptions): Promise { - if (options.mappingFile && options.excludeFile) { - throw new ToolkitError('Cannot use both --exclude-file and mapping-file.'); - } - - if (options.revert && !options.mappingFile) { - throw new ToolkitError('The --revert option can only be used with the --mapping-file option.'); + if (options.revert && !options.overrideFile) { + throw new ToolkitError('The --revert option can only be used with the --override-file option.'); } try { + const patterns = options.stacks?.patterns ?? []; await this.toolkit.refactor(this.props.cloudExecutable, { dryRun: options.dryRun, stacks: { - patterns: options.selector.patterns, - strategy: options.selector.patterns.length > 0 ? StackSelectionStrategy.PATTERN_MATCH : StackSelectionStrategy.ALL_STACKS, + patterns: patterns, + strategy: patterns.length > 0 ? StackSelectionStrategy.PATTERN_MATCH : StackSelectionStrategy.ALL_STACKS, }, - mappingSource: await mappingSource(), + additionalStackNames: options.additionalStackNames, + overrides: readOverrides(options.overrideFile, options.revert), }); } catch (e) { - error((e as Error).message); + await this.ioHost.asIoHelper().defaults.error((e as Error).message); return 1; } return 0; - async function readMappingFile(filePath: string | undefined) { + function readOverrides(filePath: string | undefined, revert: boolean = false) { if (filePath == null) { - return undefined; + return []; } - if (!(await fs.pathExists(filePath))) { + if (!fs.pathExistsSync(filePath)) { throw new ToolkitError(`The mapping file ${filePath} does not exist`); } - const content = JSON.parse(fs.readFileSync(filePath).toString('utf-8')); - if (content.environments) { - return content.environments; - } else { - throw new ToolkitError(`The mapping file ${filePath} does not contain an \`environments\` array`); - } - } - - async function readExcludeFile(filePath: string | undefined) { - if (filePath != null) { - if (!(await fs.pathExists(filePath))) { - throw new ToolkitError(`The exclude file '${filePath}' does not exist`); - } - return fs.readFileSync(filePath).toString('utf-8').split('\n'); - } - return undefined; - } - - async function mappingSource(): Promise { - if (options.mappingFile != null) { - return MappingSource.explicit(await readMappingFile(options.mappingFile)); - } - if (options.revert) { - return MappingSource.reverse(await readMappingFile(options.mappingFile)); - } - return MappingSource.auto((await readExcludeFile(options.excludeFile)) ?? []); + const groups = parseMappingGroups(fs.readFileSync(filePath).toString('utf-8')); + + return revert + ? groups.map((group) => ({ + ...group, + resources: Object.fromEntries(Object.entries(group.resources ?? {}).map(([src, dst]) => [dst, src])), + })) + : groups; } } @@ -1353,7 +1345,7 @@ export class CdkToolkit { */ private async validateStacks(stacks: StackCollection) { const failAt = this.validateMetadataFailAt(); - await stacks.validateMetadata(failAt, stackMetadataLogger(this.props.verbose)); + await stacks.validateMetadata(failAt, stackMetadataLogger(this.ioHost.asIoHelper(), this.props.verbose)); } private validateMetadataFailAt(): 'warn' | 'error' | 'none' { @@ -1450,8 +1442,8 @@ export class CdkToolkit { /** * Print a serialized object (YAML or JSON) to stdout. */ -function printSerializedObject(obj: any, json: boolean) { - logResult(serializeStructure(obj, json)); +async function printSerializedObject(ioHelper: IoHelper, obj: any, json: boolean) { + await ioHelper.defaults.result(serializeStructure(obj, json)); } /** @@ -1546,6 +1538,13 @@ export interface DiffOptions { * @default false */ readonly importExistingResources?: boolean; + + /** + * Whether to include resource moves in the diff + * + * @default false + */ + readonly includeMoves?: boolean; } interface CfnDeployOptions { @@ -1967,28 +1966,8 @@ export interface RefactorOptions { readonly dryRun: boolean; /** - * Criteria for selecting stacks to deploy - */ - selector: StackSelector; - - /** - * The absolute path to a file that contains a list of resources that - * should be excluded during the refactor. This file should contain a - * newline separated list of _destination_ locations to exclude, i.e., - * the location to which a resource would be moved if the refactor - * were to happen. - * - * The format of the locations in the file can be either: - * - * - Stack name and logical ID (e.g. `Stack1.MyQueue`) - * - A construct path (e.g. `Stack1/Foo/Bar/Resource`). - */ - excludeFile?: string; - - /** - * The absolute path to a file that contains an explicit mapping to - * be used by the toolkit (as opposed to letting the toolkit itself - * compute the mapping). This file should contain a JSON object with + * The absolute path to a file that contains overrides to the mappings + * computed by the CLI. This file should contain a JSON object with * the following format: * * { @@ -2010,7 +1989,7 @@ export interface RefactorOptions { * deployed, while the destination must refer to a location that is not already * occupied by any resource. */ - mappingFile?: string; + overrideFile?: string; /** * Modifies the behavior of the `mappingFile` option by swapping source and @@ -2018,6 +1997,17 @@ export interface RefactorOptions { * that was previously applied. */ revert?: boolean; + + /** + * Criteria for selecting stacks to compare with the deployed stacks in the + * target environment. + */ + stacks?: StackSelector; + + /** + * A list of names of additional deployed stacks to be included in the comparison. + */ + additionalStackNames?: string[]; } /** @@ -2039,10 +2029,10 @@ export interface DriftOptions { function buildParameterMap( parameters: - | { - [name: string]: string | undefined; - } - | undefined, + | { + [name: string]: string | undefined; + } + | undefined, ): { [name: string]: { [name: string]: string | undefined } } { const parameterMap: { [name: string]: { [name: string]: string | undefined }; @@ -2097,21 +2087,21 @@ async function askUserConfirmation( /** * Logger for processing stack metadata */ -function stackMetadataLogger(verbose?: boolean): (level: 'info' | 'error' | 'warn', msg: cxapi.SynthesisMessage) => Promise { +function stackMetadataLogger(ioHelper: IoHelper, verbose?: boolean): (level: 'info' | 'error' | 'warn', msg: cxapi.SynthesisMessage) => Promise { const makeLogger = (level: string): [logger: (m: string) => void, prefix: string] => { switch (level) { case 'error': - return [error, 'Error']; + return [(m) => ioHelper.defaults.error(m), 'Error']; case 'warn': - return [warning, 'Warning']; + return [(m) => ioHelper.defaults.warn(m), 'Warning']; default: - return [info, 'Info']; + return [(m) => ioHelper.defaults.info(m), 'Info']; } }; return async (level, msg) => { const [logFn, prefix] = makeLogger(level); - logFn(`[${prefix} at ${msg.id}] ${msg.entry.data}`); + await logFn(`[${prefix} at ${msg.id}] ${msg.entry.data}`); if (verbose && msg.entry.trace) { logFn(` ${msg.entry.trace.join('\n ')}`); @@ -2126,5 +2116,5 @@ function stackMetadataLogger(verbose?: boolean): (level: 'info' | 'error' | 'war */ function requiresApproval(requireApproval: RequireApproval, permissionChangeType: PermissionChangeType) { return requireApproval === RequireApproval.ANYCHANGE || - requireApproval === RequireApproval.BROADENING && permissionChangeType === PermissionChangeType.BROADENING; + requireApproval === RequireApproval.BROADENING && permissionChangeType === PermissionChangeType.BROADENING; } diff --git a/packages/aws-cdk/lib/cli/cli-config.ts b/packages/aws-cdk/lib/cli/cli-config.ts index 9c48126b0..ef49b1588 100644 --- a/packages/aws-cdk/lib/cli/cli-config.ts +++ b/packages/aws-cdk/lib/cli/cli-config.ts @@ -112,6 +112,9 @@ export async function makeConfig(): Promise { 'bootstrap-stack-name': { type: 'string', desc: 'The name of the CDK toolkit stack, if different from the default "CDKToolkit"', requiresArg: true }, }, }, + 'flags': { + description: 'View and toggle feature flags.', + }, 'deploy': { description: 'Deploys the stack(s) named STACKS into your AWS account', options: { @@ -337,6 +340,7 @@ export async function makeConfig(): Promise { 'quiet': { type: 'boolean', alias: 'q', desc: 'Do not print stack name and default message when there is no diff to stdout', default: false }, 'change-set': { type: 'boolean', alias: 'changeset', desc: 'Whether to create a changeset to analyze resource replacements. In this mode, diff will use the deploy role instead of the lookup role.', default: true }, 'import-existing-resources': { type: 'boolean', desc: 'Whether or not the change set imports resources that already exist', default: false }, + 'include-moves': { type: 'boolean', desc: 'Whether to include moves in the diff', default: false }, }, }, 'drift': { @@ -436,25 +440,21 @@ export async function makeConfig(): Promise { }, 'refactor': { description: 'Moves resources between stacks or within the same stack', - arg: { - name: 'STACKS', - variadic: true, - }, options: { + 'additional-stack-name': { + type: 'array', + requiresArg: true, + desc: 'Names of deployed stacks to be considered for resource comparison.', + }, 'dry-run': { type: 'boolean', desc: 'Do not perform any changes, just show what would be done', default: false, }, - 'exclude-file': { - type: 'string', - requiresArg: true, - desc: 'If specified, CDK will use the given file to exclude resources from the refactor', - }, - 'mapping-file': { + 'override-file': { type: 'string', requiresArg: true, - desc: 'A file that declares an explicit mapping to be applied. If provided, the command will use it instead of computing the mapping.', + desc: 'A file that declares overrides to be applied to the list of mappings computed by the CLI.', }, 'revert': { type: 'boolean', diff --git a/packages/aws-cdk/lib/cli/cli-type-registry.json b/packages/aws-cdk/lib/cli/cli-type-registry.json index 8d397ac86..0065a9f41 100644 --- a/packages/aws-cdk/lib/cli/cli-type-registry.json +++ b/packages/aws-cdk/lib/cli/cli-type-registry.json @@ -324,6 +324,9 @@ } } }, + "flags": { + "description": "View and toggle feature flags." + }, "deploy": { "description": "Deploys the stack(s) named STACKS into your AWS account", "options": { @@ -719,6 +722,11 @@ "type": "boolean", "desc": "Whether or not the change set imports resources that already exist", "default": false + }, + "include-moves": { + "type": "boolean", + "desc": "Whether to include moves in the diff", + "default": false } } }, @@ -896,25 +904,21 @@ }, "refactor": { "description": "Moves resources between stacks or within the same stack", - "arg": { - "name": "STACKS", - "variadic": true - }, "options": { + "additional-stack-name": { + "type": "array", + "requiresArg": true, + "desc": "Names of deployed stacks to be considered for resource comparison." + }, "dry-run": { "type": "boolean", "desc": "Do not perform any changes, just show what would be done", "default": false }, - "exclude-file": { - "type": "string", - "requiresArg": true, - "desc": "If specified, CDK will use the given file to exclude resources from the refactor" - }, - "mapping-file": { + "override-file": { "type": "string", "requiresArg": true, - "desc": "A file that declares an explicit mapping to be applied. If provided, the command will use it instead of computing the mapping." + "desc": "A file that declares overrides to be applied to the list of mappings computed by the CLI." }, "revert": { "type": "boolean", diff --git a/packages/aws-cdk/lib/cli/cli.ts b/packages/aws-cdk/lib/cli/cli.ts index e5648b94d..9612fc59b 100644 --- a/packages/aws-cdk/lib/cli/cli.ts +++ b/packages/aws-cdk/lib/cli/cli.ts @@ -1,9 +1,10 @@ /* eslint-disable @typescript-eslint/no-shadow */ // yargs import * as cxapi from '@aws-cdk/cx-api'; import type { ChangeSetDeployment, DeploymentMethod, DirectDeployment } from '@aws-cdk/toolkit-lib'; -import { ToolkitError } from '@aws-cdk/toolkit-lib'; +import { ToolkitError, Toolkit } from '@aws-cdk/toolkit-lib'; import * as chalk from 'chalk'; import { CdkToolkit, AssetBuildTime } from './cdk-toolkit'; +import { displayVersionMessage } from './display-version'; import type { IoMessageLevel } from './io-host'; import { CliIoHost } from './io-host'; import { parseCommandLineArguments } from './parse-command-line-arguments'; @@ -12,7 +13,6 @@ import { prettyPrintError } from './pretty-print-error'; import { GLOBAL_PLUGIN_HOST } from './singleton-plugin-host'; import type { Command } from './user-configuration'; import { Configuration } from './user-configuration'; -import * as version from './version'; import { asIoHelper } from '../../lib/api-private'; import type { IReadLock } from '../api'; import { ToolkitInfo, Notices } from '../api'; @@ -25,11 +25,13 @@ import type { Settings } from '../api/settings'; import { contextHandler as context } from '../commands/context'; import { docs } from '../commands/docs'; import { doctor } from '../commands/doctor'; +import { displayFlags } from '../commands/flags'; import { cliInit, printAvailableTemplates } from '../commands/init'; import { getMigrateScanType } from '../commands/migrate'; import { execProgram, CloudExecutable } from '../cxapp'; import type { StackSelector, Synthesizer } from '../cxapp'; import { ProxyAgentProvider } from './proxy-agent'; +import { isDeveloperBuildVersion, versionWithBuild, versionNumber } from './version'; if (!process.stdout.isTTY) { // Disable chalk color highlighting @@ -62,6 +64,7 @@ export async function exec(args: string[], synthesizer?: Synthesizer): Promise 2) { @@ -72,23 +75,21 @@ export async function exec(args: string[], synthesizer?: Synthesizer): Promise { // the cdk notices command has it's own refresh @@ -165,7 +166,7 @@ export async function exec(args: string[], synthesizer?: Synthesizer): Promise { // Log the stack trace if we're on a developer workstation. Otherwise this will be into a minified // file and the printed code line and stack trace are huge and useless. - prettyPrintError(err, version.isDeveloperBuild()); + prettyPrintError(err, isDeveloperBuildVersion()); process.exitCode = 1; }); } diff --git a/packages/aws-cdk/lib/cli/convert-to-user-input.ts b/packages/aws-cdk/lib/cli/convert-to-user-input.ts index f8d429a3c..cd0beb4fd 100644 --- a/packages/aws-cdk/lib/cli/convert-to-user-input.ts +++ b/packages/aws-cdk/lib/cli/convert-to-user-input.ts @@ -93,6 +93,10 @@ export function convertYargsToUserInput(args: any): UserInput { }; break; + case 'flags': + commandOptions = {}; + break; + case 'deploy': commandOptions = { all: args.all, @@ -192,6 +196,7 @@ export function convertYargsToUserInput(args: any): UserInput { quiet: args.quiet, changeSet: args.changeSet, importExistingResources: args.importExistingResources, + includeMoves: args.includeMoves, STACKS: args.STACKS, }; break; @@ -268,11 +273,10 @@ export function convertYargsToUserInput(args: any): UserInput { case 'refactor': commandOptions = { + additionalStackName: args.additionalStackName, dryRun: args.dryRun, - excludeFile: args.excludeFile, - mappingFile: args.mappingFile, + overrideFile: args.overrideFile, revert: args.revert, - STACKS: args.STACKS, }; break; @@ -359,6 +363,7 @@ export function convertConfigToUserInput(config: any): UserInput { confirm: config.gc?.confirm, bootstrapStackName: config.gc?.bootstrapStackName, }; + const flagsOptions = {}; const deployOptions = { all: config.deploy?.all, buildExclude: config.deploy?.buildExclude, @@ -437,6 +442,7 @@ export function convertConfigToUserInput(config: any): UserInput { quiet: config.diff?.quiet, changeSet: config.diff?.changeSet, importExistingResources: config.diff?.importExistingResources, + includeMoves: config.diff?.includeMoves, }; const driftOptions = { fail: config.drift?.fail, @@ -474,9 +480,9 @@ export function convertConfigToUserInput(config: any): UserInput { }; const doctorOptions = {}; const refactorOptions = { + additionalStackName: config.refactor?.additionalStackName, dryRun: config.refactor?.dryRun, - excludeFile: config.refactor?.excludeFile, - mappingFile: config.refactor?.mappingFile, + overrideFile: config.refactor?.overrideFile, revert: config.refactor?.revert, }; const cliTelemetryOptions = { @@ -489,6 +495,7 @@ export function convertConfigToUserInput(config: any): UserInput { synth: synthOptions, bootstrap: bootstrapOptions, gc: gcOptions, + flags: flagsOptions, deploy: deployOptions, rollback: rollbackOptions, import: importOptions, diff --git a/packages/aws-cdk/lib/cli/display-version.ts b/packages/aws-cdk/lib/cli/display-version.ts new file mode 100644 index 000000000..8db5f97de --- /dev/null +++ b/packages/aws-cdk/lib/cli/display-version.ts @@ -0,0 +1,115 @@ +import * as path from 'path'; +import { ToolkitError } from '@aws-cdk/toolkit-lib'; +import * as chalk from 'chalk'; +import * as fs from 'fs-extra'; +import * as semver from 'semver'; +import type { IoHelper } from '../api-private'; +import { cdkCacheDir, versionNumber } from '../util'; +import { formatAsBanner } from './util/console-formatters'; +import { execNpmView } from './util/npm'; + +const ONE_DAY_IN_SECONDS = 1 * 24 * 60 * 60; + +const UPGRADE_DOCUMENTATION_LINKS: Record = { + 1: 'https://docs.aws.amazon.com/cdk/v2/guide/migrating-v2.html', +}; + +export class VersionCheckTTL { + public static timestampFilePath(): string { + // Using the same path from account-cache.ts + return path.join(cdkCacheDir(), 'repo-version-ttl'); + } + + private readonly file: string; + + // File modify times are accurate only to the second + private readonly ttlSecs: number; + + constructor(file?: string, ttlSecs?: number) { + this.file = file || VersionCheckTTL.timestampFilePath(); + try { + fs.mkdirsSync(path.dirname(this.file)); + fs.accessSync(path.dirname(this.file), fs.constants.W_OK); + } catch { + throw new ToolkitError(`Directory (${path.dirname(this.file)}) is not writable.`); + } + this.ttlSecs = ttlSecs || ONE_DAY_IN_SECONDS; + } + + public async hasExpired(): Promise { + try { + const lastCheckTime = (await fs.stat(this.file)).mtimeMs; + const today = new Date().getTime(); + + if ((today - lastCheckTime) / 1000 > this.ttlSecs) { // convert ms to sec + return true; + } + return false; + } catch (err: any) { + if (err.code === 'ENOENT') { + return true; + } else { + throw err; + } + } + } + + public async update(latestVersion?: string): Promise { + if (!latestVersion) { + latestVersion = ''; + } + await fs.writeFile(this.file, latestVersion); + } +} + +// Export for unit testing only. +// Don't use directly, use displayVersionMessage() instead. +export async function getVersionMessages(currentVersion: string, cacheFile: VersionCheckTTL): Promise { + if (!(await cacheFile.hasExpired())) { + return []; + } + + const packageInfo = await execNpmView(currentVersion); + const latestVersion = packageInfo.latestVersion; + await cacheFile.update(JSON.stringify(packageInfo)); + + // If the latest version is the same as the current version, there is no need to display a message + if (semver.eq(latestVersion, currentVersion)) { + return []; + } + + const versionMessage = [ + packageInfo.deprecated ? `${chalk.red(packageInfo.deprecated as string)}` : undefined, + `Newer version of CDK is available [${chalk.green(latestVersion as string)}]`, + getMajorVersionUpgradeMessage(currentVersion), + 'Upgrade recommended (npm install -g aws-cdk)', + ].filter(Boolean) as string[]; + + return versionMessage; +} + +function getMajorVersionUpgradeMessage(currentVersion: string): string | void { + const currentMajorVersion = semver.major(currentVersion); + if (UPGRADE_DOCUMENTATION_LINKS[currentMajorVersion]) { + return `Information about upgrading from version ${currentMajorVersion}.x to version ${currentMajorVersion + 1}.x is available here: ${UPGRADE_DOCUMENTATION_LINKS[currentMajorVersion]}`; + } +} + +export async function displayVersionMessage( + ioHelper: IoHelper, + currentVersion = versionNumber(), + versionCheckCache?: VersionCheckTTL, +): Promise { + if (!process.stdout.isTTY || process.env.CDK_DISABLE_VERSION_CHECK) { + return; + } + + try { + const versionMessages = await getVersionMessages(currentVersion, versionCheckCache ?? new VersionCheckTTL()); + for (const e of formatAsBanner(versionMessages)) { + await ioHelper.defaults.info(e); + } + } catch (err: any) { + await ioHelper.defaults.debug(`Could not run version check - ${err.message}`); + } +} diff --git a/packages/aws-cdk/lib/cli/io-host/cli-io-host.ts b/packages/aws-cdk/lib/cli/io-host/cli-io-host.ts index 6e09a3ae3..32ec3811b 100644 --- a/packages/aws-cdk/lib/cli/io-host/cli-io-host.ts +++ b/packages/aws-cdk/lib/cli/io-host/cli-io-host.ts @@ -17,6 +17,7 @@ type CliAction = | ToolkitAction | 'context' | 'docs' +| 'flags' | 'notices' | 'version' | 'cli-telemetry' @@ -135,7 +136,6 @@ export class CliIoHost implements IIoHost { */ public noticesDestination: TargetStream = 'stderr'; - private _internalIoHost?: IIoHost; private _progress: StackActivityProgress = StackActivityProgress.BAR; // Stack Activity Printer @@ -155,15 +155,6 @@ export class CliIoHost implements IIoHost { this.stackProgress = props.stackProgress ?? StackActivityProgress.BAR; } - /** - * Returns the singleton instance - */ - public registerIoHost(ioHost: IIoHost) { - if (ioHost !== this) { - this._internalIoHost = ioHost; - } - } - /** * Update the stackProgress preference. */ @@ -245,10 +236,6 @@ export class CliIoHost implements IIoHost { * The caller waits until the notification completes. */ public async notify(msg: IoMessage): Promise { - if (this._internalIoHost) { - return this._internalIoHost.notify(msg); - } - if (this.isStackActivity(msg)) { if (!this.activityPrinter) { this.activityPrinter = this.makeActivityPrinter(); @@ -344,11 +331,6 @@ export class CliIoHost implements IIoHost { * default response from the input message will be used. */ public async requestResponse(msg: IoRequest): Promise { - // First call out to a registered instance if we have one - if (this._internalIoHost) { - return this._internalIoHost.requestResponse(msg); - } - // If the request cannot be prompted for by the CliIoHost, we just accept the default if (!isPromptableRequest(msg)) { await this.notify(msg); diff --git a/packages/aws-cdk/lib/cli/parse-command-line-arguments.ts b/packages/aws-cdk/lib/cli/parse-command-line-arguments.ts index ef7085895..7fb9de482 100644 --- a/packages/aws-cdk/lib/cli/parse-command-line-arguments.ts +++ b/packages/aws-cdk/lib/cli/parse-command-line-arguments.ts @@ -346,6 +346,7 @@ export function parseCommandLineArguments(args: Array): any { requiresArg: true, }), ) + .command('flags', 'View and toggle feature flags.') .command('deploy [STACKS..]', 'Deploys the stack(s) named STACKS into your AWS account', (yargs: Argv) => yargs .option('all', { @@ -749,6 +750,11 @@ export function parseCommandLineArguments(args: Array): any { default: false, type: 'boolean', desc: 'Whether or not the change set imports resources that already exist', + }) + .option('include-moves', { + default: false, + type: 'boolean', + desc: 'Whether to include moves in the diff', }), ) .command('drift [STACKS..]', 'Detect drifts in the given CloudFormation stack(s)', (yargs: Argv) => @@ -882,24 +888,24 @@ export function parseCommandLineArguments(args: Array): any { }), ) .command('doctor', 'Check your set-up for potential problems') - .command('refactor [STACKS..]', 'Moves resources between stacks or within the same stack', (yargs: Argv) => + .command('refactor', 'Moves resources between stacks or within the same stack', (yargs: Argv) => yargs + .option('additional-stack-name', { + type: 'array', + requiresArg: true, + desc: 'Names of deployed stacks to be considered for resource comparison.', + nargs: 1, + }) .option('dry-run', { default: false, type: 'boolean', desc: 'Do not perform any changes, just show what would be done', }) - .option('exclude-file', { - default: undefined, - type: 'string', - requiresArg: true, - desc: 'If specified, CDK will use the given file to exclude resources from the refactor', - }) - .option('mapping-file', { + .option('override-file', { default: undefined, type: 'string', requiresArg: true, - desc: 'A file that declares an explicit mapping to be applied. If provided, the command will use it instead of computing the mapping.', + desc: 'A file that declares overrides to be applied to the list of mappings computed by the CLI.', }) .option('revert', { default: false, diff --git a/packages/aws-cdk/lib/cli/platform-warnings.ts b/packages/aws-cdk/lib/cli/platform-warnings.ts index 8144cc9f0..b342a8f7b 100644 --- a/packages/aws-cdk/lib/cli/platform-warnings.ts +++ b/packages/aws-cdk/lib/cli/platform-warnings.ts @@ -1,10 +1,10 @@ import * as os from 'os'; import * as fs from 'fs-extra'; -import * as logging from '../logging'; +import type { IoHelper } from '../api-private'; -export async function checkForPlatformWarnings() { +export async function checkForPlatformWarnings(ioHelper: IoHelper) { if (await hasDockerCopyBug()) { - logging.warning('`cdk synth` may hang in Docker on Linux 5.6-5.10. See https://github.com/aws/aws-cdk/issues/21379 for workarounds.'); + await ioHelper.defaults.warn('`cdk synth` may hang in Docker on Linux 5.6-5.10. See https://github.com/aws/aws-cdk/issues/21379 for workarounds.'); } } diff --git a/packages/aws-cdk/lib/cli/telemetry/endpoint-sink.ts b/packages/aws-cdk/lib/cli/telemetry/endpoint-sink.ts index 7593b85c6..18feb1f63 100644 --- a/packages/aws-cdk/lib/cli/telemetry/endpoint-sink.ts +++ b/packages/aws-cdk/lib/cli/telemetry/endpoint-sink.ts @@ -1,7 +1,7 @@ import type { IncomingMessage } from 'http'; import type { Agent } from 'https'; import { request } from 'https'; -import type { UrlWithStringQuery } from 'url'; +import { parse, type UrlWithStringQuery } from 'url'; import { ToolkitError } from '@aws-cdk/toolkit-lib'; import { IoHelper } from '../../api-private'; import type { IIoHost } from '../io-host'; @@ -17,7 +17,7 @@ export interface EndpointTelemetrySinkProps { /** * The external endpoint to hit */ - readonly endpoint: UrlWithStringQuery; + readonly endpoint: string; /** * Where messages are going to be sent @@ -44,7 +44,7 @@ export class EndpointTelemetrySink implements ITelemetrySink { private agent?: Agent; public constructor(props: EndpointTelemetrySinkProps) { - this.endpoint = props.endpoint; + this.endpoint = parse(props.endpoint); this.ioHelper = IoHelper.fromActionAwareIoHost(props.ioHost); this.agent = props.agent; @@ -70,7 +70,7 @@ export class EndpointTelemetrySink implements ITelemetrySink { return; } - const res = await this.https(this.endpoint, this.events); + const res = await this.https(this.endpoint, { events: this.events }); // Clear the events array after successful output if (res) { @@ -87,7 +87,7 @@ export class EndpointTelemetrySink implements ITelemetrySink { */ private async https( url: UrlWithStringQuery, - body: TelemetrySchema[], + body: { events: TelemetrySchema[] }, ): Promise { try { const res = await doRequest(url, body, this.agent); @@ -112,7 +112,7 @@ export class EndpointTelemetrySink implements ITelemetrySink { */ function doRequest( url: UrlWithStringQuery, - data: TelemetrySchema[], + data: { events: TelemetrySchema[] }, agent?: Agent, ) { return new Promise((ok, ko) => { diff --git a/packages/aws-cdk/lib/cli/telemetry/file-sink.ts b/packages/aws-cdk/lib/cli/telemetry/file-sink.ts index 5dfadc500..04d167ce7 100644 --- a/packages/aws-cdk/lib/cli/telemetry/file-sink.ts +++ b/packages/aws-cdk/lib/cli/telemetry/file-sink.ts @@ -1,6 +1,5 @@ -import * as fs from 'fs'; -import * as path from 'path'; import { ToolkitError, type IIoHost } from '@aws-cdk/toolkit-lib'; +import * as fs from 'fs-extra'; import type { TelemetrySchema } from './schema'; import type { ITelemetrySink } from './sink-interface'; import { IoHelper } from '../../api-private'; @@ -38,11 +37,9 @@ export class FileTelemetrySink implements ITelemetrySink { throw new ToolkitError(`Telemetry file already exists at ${this.logFilePath}`); } - // Create the file if necessary - const directory = path.dirname(this.logFilePath); - if (!fs.existsSync(directory)) { - fs.mkdirSync(directory, { recursive: true }); - } + // Create the file + fs.ensureFileSync(this.logFilePath); + fs.writeJsonSync(this.logFilePath, []); } /** @@ -50,11 +47,9 @@ export class FileTelemetrySink implements ITelemetrySink { */ public async emit(event: TelemetrySchema): Promise { try { - // Format the events as a JSON string with pretty printing - const output = JSON.stringify(event, null, 2) + '\n'; - - // Write to file - fs.appendFileSync(this.logFilePath, output); + const json = fs.readJsonSync(this.logFilePath); + json.push(event); + fs.writeJSONSync(this.logFilePath, json, { spaces: 2 }); } catch (e: any) { // Never throw errors, just log them via ioHost await this.ioHelper.defaults.trace(`Failed to add telemetry event: ${e.message}`); diff --git a/packages/aws-cdk/lib/cli/user-configuration.ts b/packages/aws-cdk/lib/cli/user-configuration.ts index 9ffb57750..733f56a83 100644 --- a/packages/aws-cdk/lib/cli/user-configuration.ts +++ b/packages/aws-cdk/lib/cli/user-configuration.ts @@ -5,7 +5,7 @@ import * as fs from 'fs-extra'; import { Context, PROJECT_CONTEXT } from '../api/context'; import { Settings } from '../api/settings'; import type { Tag } from '../api/tags'; -import { debug, warning } from '../logging'; +import type { IoHelper } from '../api-private'; export const PROJECT_CONFIG = 'cdk.json'; export { PROJECT_CONTEXT } from '../api/context'; @@ -26,6 +26,7 @@ export enum Command { VERSION = 'version', WATCH = 'watch', GC = 'gc', + FLAGS = 'flags', ROLLBACK = 'rollback', IMPORT = 'import', ACKNOWLEDGE = 'acknowledge', @@ -78,6 +79,25 @@ export interface ConfigurationProps { * All sources of settings combined */ export class Configuration { + /** + * Creates user configuration from commandLineArguments + */ + public static async fromArgs(ioHelper: IoHelper, args?: Arguments) { + const commandLineArguments = args + ? await commandLineArgumentsToSettings(ioHelper, args) + : new Settings(); + + return new Configuration(ioHelper, commandLineArguments); + } + + /** + * Creates user configuration from commandLineArguments and loads + */ + public static async fromArgsAndFiles(ioHelper: IoHelper, props: ConfigurationProps = {}) { + const configuration = await Configuration.fromArgs(ioHelper, props.commandLineArguments); + return configuration.loadConfigFiles(props.readUserContext ?? true); + } + public settings = new Settings(); public context = new Context(); @@ -94,10 +114,11 @@ export class Configuration { private _projectContext?: Settings; private loaded = false; - constructor(private readonly props: ConfigurationProps = {}) { - this.commandLineArguments = props.commandLineArguments - ? commandLineArgumentsToSettings(props.commandLineArguments) - : new Settings(); + private ioHelper: IoHelper; + + private constructor(ioHelper: IoHelper, commandLineArguments: Settings) { + this.ioHelper = ioHelper; + this.commandLineArguments = commandLineArguments; this.commandLineContext = this.commandLineArguments .subSettings([CONTEXT_KEY]) .makeReadOnly(); @@ -120,13 +141,10 @@ export class Configuration { /** * Load all config */ - public async load(): Promise { - const userConfig = await loadAndLog(USER_DEFAULTS); - this._projectConfig = await loadAndLog(PROJECT_CONFIG); - this._projectContext = await loadAndLog(PROJECT_CONTEXT); - - // @todo cannot currently be disabled by cli users - const readUserContext = this.props.readUserContext ?? true; + private async loadConfigFiles(readUserContext: boolean): Promise { + const userConfig = await loadAndLog(this.ioHelper, USER_DEFAULTS); + this._projectConfig = await loadAndLog(this.ioHelper, PROJECT_CONFIG); + this._projectContext = await loadAndLog(this.ioHelper, PROJECT_CONTEXT); if (userConfig.get(['build'])) { throw new ToolkitError( @@ -158,7 +176,7 @@ export class Configuration { .merge(this.commandLineArguments) .makeReadOnly(); - debug('merged settings:', this.settings.all); + await this.ioHelper.defaults.debug('merged settings:', this.settings.all); this.loaded = true; @@ -179,15 +197,15 @@ export class Configuration { } } -async function loadAndLog(fileName: string): Promise { - const ret = await settingsFromFile(fileName); +async function loadAndLog(ioHelper: IoHelper, fileName: string): Promise { + const ret = await settingsFromFile(ioHelper, fileName); if (!ret.empty) { - debug(fileName + ':', JSON.stringify(ret.all, undefined, 2)); + await ioHelper.defaults.debug(fileName + ':', JSON.stringify(ret.all, undefined, 2)); } return ret; } -async function settingsFromFile(fileName: string): Promise { +async function settingsFromFile(ioHelper: IoHelper, fileName: string): Promise { let settings; const expanded = expandHomeDir(fileName); if (await fs.pathExists(expanded)) { @@ -199,7 +217,7 @@ async function settingsFromFile(fileName: string): Promise { // See https://github.com/aws/aws-cdk/issues/59 prohibitContextKeys(settings, ['default-account', 'default-region'], fileName); - warnAboutContextKey(settings, 'aws:', fileName); + await warnAboutContextKey(ioHelper, settings, 'aws:', fileName); return settings; } @@ -221,7 +239,7 @@ function prohibitContextKeys(settings: Settings, keys: string[], fileName: strin } } -function warnAboutContextKey(settings: Settings, prefix: string, fileName: string) { +async function warnAboutContextKey(ioHelper: IoHelper, settings: Settings, prefix: string, fileName: string) { const context = settings.get(['context']); if (!context || typeof context !== 'object') { return; @@ -229,7 +247,7 @@ function warnAboutContextKey(settings: Settings, prefix: string, fileName: strin for (const contextKey of Object.keys(context)) { if (contextKey.startsWith(prefix)) { - warning( + await ioHelper.defaults.warning( `A reserved context key ('context.${prefix}') key was found in ${fs_path.resolve( fileName, )}, it might cause surprising behavior and should be removed.`, @@ -258,9 +276,9 @@ function expandHomeDir(x: string) { * @param argv - the received CLI arguments. * @returns a new Settings object. */ -export function commandLineArgumentsToSettings(argv: Arguments): Settings { - const context = parseStringContextListToObject(argv); - const tags = parseStringTagsListToObject(expectStringList(argv.tags)); +export async function commandLineArgumentsToSettings(ioHelper: IoHelper, argv: Arguments): Promise { + const context = await parseStringContextListToObject(ioHelper, argv); + const tags = await parseStringTagsListToObject(ioHelper, expectStringList(argv.tags)); // Determine bundling stacks let bundlingStacks: string[]; @@ -330,13 +348,13 @@ function expectStringList(x: unknown): string[] | undefined { return x; } -function parseStringContextListToObject(argv: Arguments): any { +async function parseStringContextListToObject(ioHelper: IoHelper, argv: Arguments): Promise { const context: any = {}; for (const assignment of (argv as any).context || []) { const parts = assignment.split(/=(.*)/, 2); if (parts.length === 2) { - debug('CLI argument context: %s=%s', parts[0], parts[1]); + await ioHelper.defaults.debug('CLI argument context: %s=%s', parts[0], parts[1]); if (parts[0].match(/^aws:.+/)) { throw new ToolkitError( `User-provided context cannot use keys prefixed with 'aws:', but ${parts[0]} was provided.`, @@ -344,7 +362,7 @@ function parseStringContextListToObject(argv: Arguments): any { } context[parts[0]] = parts[1]; } else { - warning( + await ioHelper.defaults.warn( 'Context argument is not an assignment (key=value): %s', assignment, ); @@ -359,9 +377,10 @@ function parseStringContextListToObject(argv: Arguments): any { * Return undefined if no tags were provided, return an empty array if only empty * strings were provided */ -function parseStringTagsListToObject( +async function parseStringTagsListToObject( + ioHelper: IoHelper, argTags: string[] | undefined, -): Tag[] | undefined { +): Promise { if (argTags === undefined) { return undefined; } @@ -378,13 +397,13 @@ function parseStringTagsListToObject( for (const assignment of nonEmptyTags) { const parts = assignment.split(/=(.*)/, 2); if (parts.length === 2) { - debug('CLI argument tags: %s=%s', parts[0], parts[1]); + await ioHelper.defaults.debug('CLI argument tags: %s=%s', parts[0], parts[1]); tags.push({ Key: parts[0], Value: parts[1], }); } else { - warning('Tags argument is not an assignment (key=value): %s', assignment); + await ioHelper.defaults.warn('Tags argument is not an assignment (key=value): %s', assignment); } } return tags.length > 0 ? tags : undefined; diff --git a/packages/aws-cdk/lib/cli/user-input.ts b/packages/aws-cdk/lib/cli/user-input.ts index 068bc6c4b..646f7082f 100644 --- a/packages/aws-cdk/lib/cli/user-input.ts +++ b/packages/aws-cdk/lib/cli/user-input.ts @@ -45,6 +45,11 @@ export interface UserInput { */ readonly gc?: GcOptions; + /** + * View and toggle feature flags. + */ + readonly flags?: {}; + /** * Deploys the stack(s) named STACKS into your AWS account */ @@ -1169,6 +1174,13 @@ export interface DiffOptions { */ readonly importExistingResources?: boolean; + /** + * Whether to include moves in the diff + * + * @default - false + */ + readonly includeMoves?: boolean; + /** * Positional argument for diff */ @@ -1425,25 +1437,25 @@ export interface DocsOptions { */ export interface RefactorOptions { /** - * Do not perform any changes, just show what would be done + * Names of deployed stacks to be considered for resource comparison. * - * @default - false + * @default - undefined */ - readonly dryRun?: boolean; + readonly additionalStackName?: Array; /** - * If specified, CDK will use the given file to exclude resources from the refactor + * Do not perform any changes, just show what would be done * - * @default - undefined + * @default - false */ - readonly excludeFile?: string; + readonly dryRun?: boolean; /** - * A file that declares an explicit mapping to be applied. If provided, the command will use it instead of computing the mapping. + * A file that declares overrides to be applied to the list of mappings computed by the CLI. * * @default - undefined */ - readonly mappingFile?: string; + readonly overrideFile?: string; /** * If specified, the command will revert the refactor operation. This is only valid if a mapping file was provided. @@ -1451,11 +1463,6 @@ export interface RefactorOptions { * @default - false */ readonly revert?: boolean; - - /** - * Positional argument for refactor - */ - readonly STACKS?: Array; } /** diff --git a/packages/aws-cdk/lib/cli/util/yargs-helpers.ts b/packages/aws-cdk/lib/cli/util/yargs-helpers.ts index 6da555cbc..fa94e215c 100644 --- a/packages/aws-cdk/lib/cli/util/yargs-helpers.ts +++ b/packages/aws-cdk/lib/cli/util/yargs-helpers.ts @@ -1,6 +1,6 @@ import { ciSystemIsStdErrSafe } from '../ci-systems'; import { isCI } from '../io-host'; -import * as version from '../version'; +import { versionWithBuild } from '../version'; export { isCI } from '../io-host'; @@ -31,7 +31,7 @@ export function yargsNegativeAlias = { - 1: 'https://docs.aws.amazon.com/cdk/v2/guide/migrating-v2.html', -}; - -export function displayVersion() { +export function versionWithBuild() { return `${versionNumber()} (build ${commit()})`; } -export function isDeveloperBuild(): boolean { +export function isDeveloperBuildVersion(): boolean { return versionNumber() === '0.0.0'; } @@ -33,98 +19,3 @@ function commit(): string { // eslint-disable-next-line @typescript-eslint/no-require-imports return require(path.join(cliRootDir(), 'build-info.json')).commit; } - -export class VersionCheckTTL { - public static timestampFilePath(): string { - // Using the same path from account-cache.ts - return path.join(cdkCacheDir(), 'repo-version-ttl'); - } - - private readonly file: string; - - // File modify times are accurate only to the second - private readonly ttlSecs: number; - - constructor(file?: string, ttlSecs?: number) { - this.file = file || VersionCheckTTL.timestampFilePath(); - try { - fs.mkdirsSync(path.dirname(this.file)); - fs.accessSync(path.dirname(this.file), fs.constants.W_OK); - } catch { - throw new ToolkitError(`Directory (${path.dirname(this.file)}) is not writable.`); - } - this.ttlSecs = ttlSecs || ONE_DAY_IN_SECONDS; - } - - public async hasExpired(): Promise { - try { - const lastCheckTime = (await fs.stat(this.file)).mtimeMs; - const today = new Date().getTime(); - - if ((today - lastCheckTime) / 1000 > this.ttlSecs) { // convert ms to sec - return true; - } - return false; - } catch (err: any) { - if (err.code === 'ENOENT') { - return true; - } else { - throw err; - } - } - } - - public async update(latestVersion?: string): Promise { - if (!latestVersion) { - latestVersion = ''; - } - await fs.writeFile(this.file, latestVersion); - } -} - -// Export for unit testing only. -// Don't use directly, use displayVersionMessage() instead. -export async function getVersionMessages(currentVersion: string, cacheFile: VersionCheckTTL): Promise { - if (!(await cacheFile.hasExpired())) { - return []; - } - - const packageInfo = await execNpmView(currentVersion); - const latestVersion = packageInfo.latestVersion; - await cacheFile.update(JSON.stringify(packageInfo)); - - // If the latest version is the same as the current version, there is no need to display a message - if (semver.eq(latestVersion, currentVersion)) { - return []; - } - - const versionMessage = [ - packageInfo.deprecated ? `${chalk.red(packageInfo.deprecated as string)}` : undefined, - `Newer version of CDK is available [${chalk.green(latestVersion as string)}]`, - getMajorVersionUpgradeMessage(currentVersion), - 'Upgrade recommended (npm install -g aws-cdk)', - ].filter(Boolean) as string[]; - - return versionMessage; -} - -function getMajorVersionUpgradeMessage(currentVersion: string): string | void { - const currentMajorVersion = semver.major(currentVersion); - if (UPGRADE_DOCUMENTATION_LINKS[currentMajorVersion]) { - return `Information about upgrading from version ${currentMajorVersion}.x to version ${currentMajorVersion + 1}.x is available here: ${UPGRADE_DOCUMENTATION_LINKS[currentMajorVersion]}`; - } -} - -export async function displayVersionMessage(currentVersion = versionNumber(), versionCheckCache?: VersionCheckTTL): Promise { - if (!process.stdout.isTTY || process.env.CDK_DISABLE_VERSION_CHECK) { - return; - } - - try { - const versionMessages = await getVersionMessages(currentVersion, versionCheckCache ?? new VersionCheckTTL()); - formatAsBanner(versionMessages).forEach(e => info(e)); - } catch (err: any) { - debug(`Could not run version check - ${err.message}`); - } -} -/* c8 ignore stop */ diff --git a/packages/aws-cdk/lib/commands/context.ts b/packages/aws-cdk/lib/commands/context.ts index e16e02911..49216e403 100644 --- a/packages/aws-cdk/lib/commands/context.ts +++ b/packages/aws-cdk/lib/commands/context.ts @@ -2,10 +2,10 @@ import { ToolkitError } from '@aws-cdk/toolkit-lib'; import * as chalk from 'chalk'; import { minimatch } from 'minimatch'; import type { Context } from '../api/context'; +import type { IoHelper } from '../api-private'; +import { displayVersionMessage } from '../cli/display-version'; import { renderTable } from '../cli/tables'; import { PROJECT_CONFIG, PROJECT_CONTEXT, USER_DEFAULTS } from '../cli/user-configuration'; -import * as version from '../cli/version'; -import { error, warning, info, result } from '../logging'; /** * Options for the context command @@ -14,70 +14,77 @@ export interface ContextOptions { /** * The context object sourced from all context locations */ - context: Context; + readonly context: Context; /** * The context key (or its index) to reset * * @default undefined */ - reset?: string; + readonly reset?: string; /** * Ignore missing key error * * @default false */ - force?: boolean; + readonly force?: boolean; /** * Clear all context * * @default false */ - clear?: boolean; + readonly clear?: boolean; /** * Use JSON output instead of YAML when templates are printed to STDOUT * * @default false */ - json?: boolean; + readonly json?: boolean; + + /** + * IoHelper for messaging. + */ + readonly ioHelper: IoHelper; } export async function contextHandler(options: ContextOptions): Promise { + const ioHelper = options.ioHelper; + if (options.clear) { options.context.clear(); await options.context.save(PROJECT_CONTEXT); - info('All context values cleared.'); + await ioHelper.defaults.info('All context values cleared.'); } else if (options.reset) { - invalidateContext(options.context, options.reset, options.force ?? false); + await invalidateContext(ioHelper, options.context, options.reset, options.force ?? false); await options.context.save(PROJECT_CONTEXT); } else { // List -- support '--json' flag if (options.json) { /* c8 ignore start */ const contextValues = options.context.all; - result(JSON.stringify(contextValues, undefined, 2)); + await ioHelper.defaults.result(JSON.stringify(contextValues, undefined, 2)); /* c8 ignore stop */ } else { - listContext(options.context); + await listContext(ioHelper, options.context); } } - await version.displayVersionMessage(); + await displayVersionMessage(ioHelper); return 0; } -function listContext(context: Context) { +async function listContext(ioHelper: IoHelper, context: Context) { const keys = contextKeys(context); if (keys.length === 0) { - info('This CDK application does not have any saved context values yet.'); - info(''); - info('Context will automatically be saved when you synthesize CDK apps'); - info('that use environment context information like AZ information, VPCs,'); - info('SSM parameters, and so on.'); + await ioHelper.defaults.info('This CDK application does not have any saved context values yet.'); + await ioHelper.defaults.info(''); + await ioHelper.defaults.info('Context will automatically be saved when you synthesize CDK apps'); + await ioHelper.defaults.info('that use environment context information like AZ information, VPCs,'); + await ioHelper.defaults.info('SSM parameters, and so on.'); return; } @@ -88,15 +95,15 @@ function listContext(context: Context) { const jsonWithoutNewlines = JSON.stringify(context.all[key], undefined, 2).replace(/\s+/g, ' '); data_out.push([i, key, jsonWithoutNewlines]); } - info('Context found in %s:', chalk.blue(PROJECT_CONFIG)); - info(''); - info(renderTable(data_out, process.stdout.columns)); + await ioHelper.defaults.info('Context found in %s:', chalk.blue(PROJECT_CONFIG)); + await ioHelper.defaults.info(''); + await ioHelper.defaults.info(renderTable(data_out, process.stdout.columns)); // eslint-disable-next-line @stylistic/max-len - info(`Run ${chalk.blue('cdk context --reset KEY_OR_NUMBER')} to remove a context key. It will be refreshed on the next CDK synthesis run.`); + await ioHelper.defaults.info(`Run ${chalk.blue('cdk context --reset KEY_OR_NUMBER')} to remove a context key. It will be refreshed on the next CDK synthesis run.`); } -function invalidateContext(context: Context, key: string, force: boolean) { +async function invalidateContext(ioHelper: IoHelper, context: Context, key: string, force: boolean) { const i = parseInt(key, 10); if (`${i}` === key) { // was a number and we fully parsed it. @@ -107,12 +114,12 @@ function invalidateContext(context: Context, key: string, force: boolean) { context.unset(key); // check if the value was actually unset. if (!context.has(key)) { - info('Context value %s reset. It will be refreshed on next synthesis', chalk.blue(key)); + await ioHelper.defaults.info('Context value %s reset. It will be refreshed on next synthesis', chalk.blue(key)); return; } // Value must be in readonly bag - error('Only context values specified in %s can be reset through the CLI', chalk.blue(PROJECT_CONTEXT)); + await ioHelper.defaults.error('Only context values specified in %s can be reset through the CLI', chalk.blue(PROJECT_CONTEXT)); if (!force) { throw new ToolkitError(`Cannot reset readonly context value with key: ${key}`); } @@ -129,10 +136,10 @@ function invalidateContext(context: Context, key: string, force: boolean) { const { unset, readonly } = getUnsetAndReadonly(context, matches); // output the reset values - printUnset(unset); + await printUnset(ioHelper, unset); // warn about values not reset - printReadonly(readonly); + await printReadonly(ioHelper, readonly); // throw when none of the matches were reset if (!force && unset.length === 0) { @@ -145,22 +152,22 @@ function invalidateContext(context: Context, key: string, force: boolean) { } } -function printUnset(unset: string[]) { +async function printUnset(ioHelper: IoHelper, unset: string[]) { if (unset.length === 0) return; - info('The following matched context values reset. They will be refreshed on next synthesis'); - unset.forEach((match) => { - info(' %s', match); - }); + await ioHelper.defaults.info('The following matched context values reset. They will be refreshed on next synthesis'); + for (const match of unset) { + await ioHelper.defaults.info(' %s', match); + } } -function printReadonly(readonly: string[]) { +async function printReadonly(ioHelper: IoHelper, readonly: string[]) { if (readonly.length === 0) return; - warning('The following matched context values could not be reset through the CLI'); - readonly.forEach((match) => { - info(' %s', match); - }); - info(''); - info('This usually means they are configured in %s or %s', chalk.blue(PROJECT_CONFIG), chalk.blue(USER_DEFAULTS)); + await ioHelper.defaults.warn('The following matched context values could not be reset through the CLI'); + for (const match of readonly) { + await ioHelper.defaults.info(' %s', match); + } + await ioHelper.defaults.info(''); + await ioHelper.defaults.info('This usually means they are configured in %s or %s', chalk.blue(PROJECT_CONFIG), chalk.blue(USER_DEFAULTS)); } function keysByExpression(context: Context, expression: string) { diff --git a/packages/aws-cdk/lib/commands/docs.ts b/packages/aws-cdk/lib/commands/docs.ts index fdec35978..7aa64d4c2 100644 --- a/packages/aws-cdk/lib/commands/docs.ts +++ b/packages/aws-cdk/lib/commands/docs.ts @@ -1,6 +1,7 @@ import * as childProcess from 'child_process'; +import { promisify } from 'node:util'; import * as chalk from 'chalk'; -import { debug, info, warning } from '../../lib/logging'; +import type { IoHelper } from '../api-private'; export const command = 'docs'; export const describe = 'Opens the reference documentation in a browser'; @@ -13,27 +14,35 @@ export interface DocsOptions { /** * The command to use to open the browser */ - browser: string; + readonly browser: string; + + /** + * IoHelper for messaging + */ + readonly ioHelper: IoHelper; } export async function docs(options: DocsOptions): Promise { + const ioHelper = options.ioHelper; const url = 'https://docs.aws.amazon.com/cdk/api/v2/'; - info(chalk.green(url)); + await ioHelper.defaults.info(chalk.green(url)); const browserCommand = (options.browser).replace(/%u/g, url); - debug(`Opening documentation ${chalk.green(browserCommand)}`); - return new Promise((resolve, _reject) => { - childProcess.exec(browserCommand, (err, stdout, stderr) => { - if (err) { - debug(`An error occurred when trying to open a browser: ${err.stack || err.message}`); - return resolve(0); - } - if (stdout) { - debug(stdout); - } - if (stderr) { - warning(stderr); - } - resolve(0); - }); - }); + await ioHelper.defaults.debug(`Opening documentation ${chalk.green(browserCommand)}`); + + const exec = promisify(childProcess.exec); + + try { + const { stdout, stderr } = await exec(browserCommand); + if (stdout) { + await ioHelper.defaults.debug(stdout); + } + if (stderr) { + await ioHelper.defaults.warn(stderr); + } + } catch (err: unknown) { + const e = err as childProcess.ExecException; + await ioHelper.defaults.debug(`An error occurred when trying to open a browser: ${e.stack || e.message}`); + } + + return 0; } diff --git a/packages/aws-cdk/lib/commands/doctor.ts b/packages/aws-cdk/lib/commands/doctor.ts index 425c91a59..34939e8fe 100644 --- a/packages/aws-cdk/lib/commands/doctor.ts +++ b/packages/aws-cdk/lib/commands/doctor.ts @@ -1,21 +1,22 @@ import * as process from 'process'; import * as cxapi from '@aws-cdk/cx-api'; import * as chalk from 'chalk'; -import { info } from '../../lib/logging'; -import * as version from '../cli/version'; +import type { IoHelper } from '../api-private'; +import { displayVersionMessage } from '../cli/display-version'; +import { versionWithBuild } from '../cli/version'; -export async function doctor(): Promise { +export async function doctor({ ioHelper }: { ioHelper: IoHelper }): Promise { let exitStatus: number = 0; for (const verification of verifications) { - if (!await verification()) { + if (!await verification(ioHelper)) { exitStatus = -1; } } - await version.displayVersionMessage(); + await displayVersionMessage(ioHelper); return exitStatus; } -const verifications: Array<() => boolean | Promise> = [ +const verifications: Array<(ioHelper: IoHelper) => boolean | Promise> = [ displayVersionInformation, displayAwsEnvironmentVariables, displayCdkEnvironmentVariables, @@ -23,38 +24,38 @@ const verifications: Array<() => boolean | Promise> = [ // ### Verifications ### -function displayVersionInformation() { - info(`ℹ️ CDK Version: ${chalk.green(version.displayVersion())}`); +async function displayVersionInformation(ioHelper: IoHelper) { + await ioHelper.defaults.info(`ℹ️ CDK Version: ${chalk.green(versionWithBuild())}`); return true; } -function displayAwsEnvironmentVariables() { +async function displayAwsEnvironmentVariables(ioHelper: IoHelper) { const keys = Object.keys(process.env).filter(s => s.startsWith('AWS_')); if (keys.length === 0) { - info('ℹ️ No AWS environment variables'); + await ioHelper.defaults.info('ℹ️ No AWS environment variables'); return true; } - info('ℹ️ AWS environment variables:'); + await ioHelper.defaults.info('ℹ️ AWS environment variables:'); for (const key of keys) { - info(` - ${chalk.blue(key)} = ${chalk.green(anonymizeAwsVariable(key, process.env[key]!))}`); + await ioHelper.defaults.info(` - ${chalk.blue(key)} = ${chalk.green(anonymizeAwsVariable(key, process.env[key]!))}`); } return true; } -function displayCdkEnvironmentVariables() { +async function displayCdkEnvironmentVariables(ioHelper: IoHelper) { const keys = Object.keys(process.env).filter(s => s.startsWith('CDK_')); if (keys.length === 0) { - info('ℹ️ No CDK environment variables'); + await ioHelper.defaults.info('ℹ️ No CDK environment variables'); return true; } - info('ℹ️ CDK environment variables:'); + await ioHelper.defaults.info('ℹ️ CDK environment variables:'); let healthy = true; for (const key of keys.sort()) { if (key === cxapi.CONTEXT_ENV || key === cxapi.CONTEXT_OVERFLOW_LOCATION_ENV || key === cxapi.OUTDIR_ENV) { - info(` - ${chalk.red(key)} = ${chalk.green(process.env[key]!)} (⚠️ reserved for use by the CDK toolkit)`); + await ioHelper.defaults.info(` - ${chalk.red(key)} = ${chalk.green(process.env[key]!)} (⚠️ reserved for use by the CDK toolkit)`); healthy = false; } else { - info(` - ${chalk.blue(key)} = ${chalk.green(process.env[key]!)}`); + await ioHelper.defaults.info(` - ${chalk.blue(key)} = ${chalk.green(process.env[key]!)}`); } } return healthy; diff --git a/packages/aws-cdk/lib/commands/flags.ts b/packages/aws-cdk/lib/commands/flags.ts new file mode 100644 index 000000000..85bd7f26c --- /dev/null +++ b/packages/aws-cdk/lib/commands/flags.ts @@ -0,0 +1,53 @@ +import type { FeatureFlag } from '@aws-cdk/toolkit-lib'; +import * as chalk from 'chalk'; +import type { IoHelper } from '../api-private'; + +function formatTable(headers: string[], rows: string[][]): string { + const columnWidths = [ + Math.max(headers[0].length, ...rows.map(row => row[0].length)), + Math.max(headers[1].length, ...rows.map(row => row[1].length)), + Math.max(headers[2].length, ...rows.map(row => row[2].length)), + ]; + + const createSeparator = () => { + return '+' + columnWidths.map(width => '-'.repeat(width + 2)).join('+') + '+'; + }; + + const formatRow = (values: string[]) => { + return '|' + values.map((value, i) => ` ${value.padEnd(columnWidths[i])} `).join('|') + '|'; + }; + + const separator = createSeparator(); + let table = separator + '\n'; + table += formatRow(headers) + '\n'; + table += separator + '\n'; + + rows.forEach(row => { + table += formatRow(row) + '\n'; + }); + + table += separator; + return table; +} + +export async function displayFlags(flagsData: FeatureFlag[], ioHelper: IoHelper): Promise { + const headers = ['Feature Flag Name', 'Recommended Value', 'User Value']; + + const rows: string[][] = []; + + flagsData.forEach((flag, index) => { + if (index === 0 || flagsData[index].module !== flagsData[index - 1].module) { + rows.push([chalk.bold(`Module: ${flag.module}`), '', '']); + } + + rows.push([ + flag.name, + String(flag.recommendedValue), + flag.userValue === undefined ? '' : String(flag.userValue), + ]); + }); + + const formattedTable = formatTable(headers, rows); + + await ioHelper.defaults.info(formattedTable); +} diff --git a/packages/aws-cdk/lib/commands/init/init-hooks.ts b/packages/aws-cdk/lib/commands/init/init-hooks.ts index 01a9eff62..2708a05ff 100644 --- a/packages/aws-cdk/lib/commands/init/init-hooks.ts +++ b/packages/aws-cdk/lib/commands/init/init-hooks.ts @@ -1,6 +1,7 @@ import * as path from 'path'; import { ToolkitError } from '@aws-cdk/toolkit-lib'; import { shell } from './os'; +import type { IoHelper } from '../../api-private'; import { formatErrorMessage } from '../../util'; export type SubstitutePlaceholders = (...fileNames: string[]) => Promise; @@ -47,17 +48,17 @@ export interface HookTarget { * Bundle hooks as built-ins into the CLI, so they get bundled and can take advantage * of all shared code. */ -export async function invokeBuiltinHooks(target: HookTarget, context: HookContext) { +export async function invokeBuiltinHooks(ioHelper: IoHelper, target: HookTarget, context: HookContext) { switch (target.language) { case 'csharp': if (['app', 'sample-app'].includes(target.templateName)) { - return dotnetAddProject(target.targetDirectory, context); + return dotnetAddProject(ioHelper, target.targetDirectory, context); } break; case 'fsharp': if (['app', 'sample-app'].includes(target.templateName)) { - return dotnetAddProject(target.targetDirectory, context, 'fsproj'); + return dotnetAddProject(ioHelper, target.targetDirectory, context, 'fsproj'); } break; @@ -79,7 +80,7 @@ export async function invokeBuiltinHooks(target: HookTarget, context: HookContex } } -async function dotnetAddProject(targetDirectory: string, context: HookContext, ext = 'csproj') { +async function dotnetAddProject(ioHelper: IoHelper, targetDirectory: string, context: HookContext, ext = 'csproj') { const pname = context.placeholder('name.PascalCased'); const slnPath = path.join(targetDirectory, 'src', `${pname}.sln`); const csprojPath = path.join(targetDirectory, 'src', pname, `${pname}.${ext}`); @@ -101,7 +102,7 @@ async function dotnetAddProject(targetDirectory: string, context: HookContext, e const MAX_ATTEMPTS = 3; for (let attempt = 1; ; attempt++) { try { - await shell(['dotnet', 'sln', slnPath, 'add', csprojPath]); + await shell(ioHelper, ['dotnet', 'sln', slnPath, 'add', csprojPath]); return; } catch (e: any) { if (attempt === MAX_ATTEMPTS) { diff --git a/packages/aws-cdk/lib/commands/init/init.ts b/packages/aws-cdk/lib/commands/init/init.ts index 8265dc849..c01761c7c 100644 --- a/packages/aws-cdk/lib/commands/init/init.ts +++ b/packages/aws-cdk/lib/commands/init/init.ts @@ -4,9 +4,9 @@ import { ToolkitError } from '@aws-cdk/toolkit-lib'; import * as chalk from 'chalk'; import * as fs from 'fs-extra'; import { invokeBuiltinHooks } from './init-hooks'; +import type { IoHelper } from '../../api-private'; import { cliRootDir } from '../../cli/root-dir'; import { versionNumber } from '../../cli/version'; -import { error, info, warning } from '../../logging'; import { cdkHomeDir, formatErrorMessage, rangeFromSemver } from '../../util'; /* eslint-disable @typescript-eslint/no-var-requires */ // Packages don't have @types module @@ -28,17 +28,20 @@ export interface CliInitOptions { * Override the built-in CDK version */ readonly libVersion?: string; + + readonly ioHelper: IoHelper; } /** * Initialize a CDK package in the current directory */ export async function cliInit(options: CliInitOptions) { + const ioHelper = options.ioHelper; const canUseNetwork = options.canUseNetwork ?? true; const generateOnly = options.generateOnly ?? false; const workDir = options.workDir ?? process.cwd(); if (!options.type && !options.language) { - await printAvailableTemplates(); + await printAvailableTemplates(ioHelper); return; } @@ -46,21 +49,22 @@ export async function cliInit(options: CliInitOptions) { const template = (await availableInitTemplates()).find((t) => t.hasName(type!)); if (!template) { - await printAvailableTemplates(options.language); + await printAvailableTemplates(ioHelper, options.language); throw new ToolkitError(`Unknown init template: ${type}`); } if (!options.language && template.languages.length === 1) { const language = template.languages[0]; - warning( + await ioHelper.defaults.warn( `No --language was provided, but '${type}' supports only '${language}', so defaulting to --language=${language}`, ); } if (!options.language) { - info(`Available languages for ${chalk.green(type)}: ${template.languages.map((l) => chalk.blue(l)).join(', ')}`); + await ioHelper.defaults.info(`Available languages for ${chalk.green(type)}: ${template.languages.map((l) => chalk.blue(l)).join(', ')}`); throw new ToolkitError('No language was selected'); } await initializeProject( + ioHelper, template, options.language, canUseNetwork, @@ -121,9 +125,9 @@ export class InitTemplate { * @param language - the language to instantiate this template with * @param targetDirectory - the directory where the template is to be instantiated into */ - public async install(language: string, targetDirectory: string, stackName?: string, libVersion?: string) { + public async install(ioHelper: IoHelper, language: string, targetDirectory: string, stackName?: string, libVersion?: string) { if (this.languages.indexOf(language) === -1) { - error( + await ioHelper.defaults.error( `The ${chalk.blue(language)} language is not supported for ${chalk.green(this.name)} ` + `(it supports: ${this.languages.map((l) => chalk.blue(l)).join(', ')})`, ); @@ -145,6 +149,7 @@ export class InitTemplate { await this.installFiles(sourceDirectory, targetDirectory, language, projectInfo); await this.applyFutureFlags(targetDirectory); await invokeBuiltinHooks( + ioHelper, { targetDirectory, language, templateName: this.name }, { substitutePlaceholdersIn: async (...fileNames: string[]) => { @@ -308,23 +313,24 @@ async function listDirectory(dirPath: string) { ); } -export async function printAvailableTemplates(language?: string) { - info('Available templates:'); +export async function printAvailableTemplates(ioHelper: IoHelper, language?: string) { + await ioHelper.defaults.info('Available templates:'); for (const template of await availableInitTemplates()) { if (language && template.languages.indexOf(language) === -1) { continue; } - info(`* ${chalk.green(template.name)}: ${template.description}`); + await ioHelper.defaults.info(`* ${chalk.green(template.name)}: ${template.description}`); const languageArg = language ? chalk.bold(language) : template.languages.length > 1 ? `[${template.languages.map((t) => chalk.bold(t)).join('|')}]` : chalk.bold(template.languages[0]); - info(` └─ ${chalk.blue(`cdk init ${chalk.bold(template.name)} --language=${languageArg}`)}`); + await ioHelper.defaults.info(` └─ ${chalk.blue(`cdk init ${chalk.bold(template.name)} --language=${languageArg}`)}`); } } async function initializeProject( + ioHelper: IoHelper, template: InitTemplate, language: string, canUseNetwork: boolean, @@ -335,22 +341,22 @@ async function initializeProject( cdkVersion?: string, ) { await assertIsEmptyDirectory(workDir); - info(`Applying project template ${chalk.green(template.name)} for ${chalk.blue(language)}`); - await template.install(language, workDir, stackName, cdkVersion); + await ioHelper.defaults.info(`Applying project template ${chalk.green(template.name)} for ${chalk.blue(language)}`); + await template.install(ioHelper, language, workDir, stackName, cdkVersion); if (migrate) { await template.addMigrateContext(workDir); } if (await fs.pathExists(`${workDir}/README.md`)) { const readme = await fs.readFile(`${workDir}/README.md`, { encoding: 'utf-8' }); - info(chalk.green(readme)); + await ioHelper.defaults.info(chalk.green(readme)); } if (!generateOnly) { - await initializeGitRepository(workDir); - await postInstall(language, canUseNetwork, workDir); + await initializeGitRepository(ioHelper, workDir); + await postInstall(ioHelper, language, canUseNetwork, workDir); } - info('✅ All done!'); + await ioHelper.defaults.info('✅ All done!'); } async function assertIsEmptyDirectory(workDir: string) { @@ -360,78 +366,78 @@ async function assertIsEmptyDirectory(workDir: string) { } } -async function initializeGitRepository(workDir: string) { +async function initializeGitRepository(ioHelper: IoHelper, workDir: string) { if (await isInGitRepository(workDir)) { return; } - info('Initializing a new git repository...'); + await ioHelper.defaults.info('Initializing a new git repository...'); try { - await execute('git', ['init'], { cwd: workDir }); - await execute('git', ['add', '.'], { cwd: workDir }); - await execute('git', ['commit', '--message="Initial commit"', '--no-gpg-sign'], { cwd: workDir }); + await execute(ioHelper, 'git', ['init'], { cwd: workDir }); + await execute(ioHelper, 'git', ['add', '.'], { cwd: workDir }); + await execute(ioHelper, 'git', ['commit', '--message="Initial commit"', '--no-gpg-sign'], { cwd: workDir }); } catch { - warning('Unable to initialize git repository for your project.'); + await ioHelper.defaults.warn('Unable to initialize git repository for your project.'); } } -async function postInstall(language: string, canUseNetwork: boolean, workDir: string) { +async function postInstall(ioHelper: IoHelper, language: string, canUseNetwork: boolean, workDir: string) { switch (language) { case 'javascript': - return postInstallJavascript(canUseNetwork, workDir); + return postInstallJavascript(ioHelper, canUseNetwork, workDir); case 'typescript': - return postInstallTypescript(canUseNetwork, workDir); + return postInstallTypescript(ioHelper, canUseNetwork, workDir); case 'java': - return postInstallJava(canUseNetwork, workDir); + return postInstallJava(ioHelper, canUseNetwork, workDir); case 'python': - return postInstallPython(workDir); + return postInstallPython(ioHelper, workDir); } } -async function postInstallJavascript(canUseNetwork: boolean, cwd: string) { - return postInstallTypescript(canUseNetwork, cwd); +async function postInstallJavascript(ioHelper: IoHelper, canUseNetwork: boolean, cwd: string) { + return postInstallTypescript(ioHelper, canUseNetwork, cwd); } -async function postInstallTypescript(canUseNetwork: boolean, cwd: string) { +async function postInstallTypescript(ioHelper: IoHelper, canUseNetwork: boolean, cwd: string) { const command = 'npm'; if (!canUseNetwork) { - warning(`Please run '${command} install'!`); + await ioHelper.defaults.warn(`Please run '${command} install'!`); return; } - info(`Executing ${chalk.green(`${command} install`)}...`); + await ioHelper.defaults.info(`Executing ${chalk.green(`${command} install`)}...`); try { - await execute(command, ['install'], { cwd }); + await execute(ioHelper, command, ['install'], { cwd }); } catch (e: any) { - warning(`${command} install failed: ` + formatErrorMessage(e)); + await ioHelper.defaults.warn(`${command} install failed: ` + formatErrorMessage(e)); } } -async function postInstallJava(canUseNetwork: boolean, cwd: string) { +async function postInstallJava(ioHelper: IoHelper, canUseNetwork: boolean, cwd: string) { const mvnPackageWarning = "Please run 'mvn package'!"; if (!canUseNetwork) { - warning(mvnPackageWarning); + await ioHelper.defaults.warn(mvnPackageWarning); return; } - info("Executing 'mvn package'"); + await ioHelper.defaults.info("Executing 'mvn package'"); try { - await execute('mvn', ['package'], { cwd }); + await execute(ioHelper, 'mvn', ['package'], { cwd }); } catch { - warning('Unable to package compiled code as JAR'); - warning(mvnPackageWarning); + await ioHelper.defaults.warn('Unable to package compiled code as JAR'); + await ioHelper.defaults.warn(mvnPackageWarning); } } -async function postInstallPython(cwd: string) { +async function postInstallPython(ioHelper: IoHelper, cwd: string) { const python = pythonExecutable(); - warning(`Please run '${python} -m venv .venv'!`); - info(`Executing ${chalk.green('Creating virtualenv...')}`); + await ioHelper.defaults.warn(`Please run '${python} -m venv .venv'!`); + await ioHelper.defaults.info(`Executing ${chalk.green('Creating virtualenv...')}`); try { - await execute(python, ['-m venv', '.venv'], { cwd }); + await execute(ioHelper, python, ['-m venv', '.venv'], { cwd }); } catch { - warning('Unable to create virtualenv automatically'); - warning(`Please run '${python} -m venv .venv'!`); + await ioHelper.defaults.warn('Unable to create virtualenv automatically'); + await ioHelper.defaults.warn(`Please run '${python} -m venv .venv'!`); } } @@ -462,12 +468,12 @@ function isRoot(dir: string) { /** * Executes `command`. STDERR is emitted in real-time. * - * If command exits with non-zero exit code, an exceprion is thrown and includes + * If command exits with non-zero exit code, an exception is thrown and includes * the contents of STDOUT. * * @returns STDOUT (if successful). */ -async function execute(cmd: string, args: string[], { cwd }: { cwd: string }) { +async function execute(ioHelper: IoHelper, cmd: string, args: string[], { cwd }: { cwd: string }) { const child = childProcess.spawn(cmd, args, { cwd, shell: true, @@ -481,10 +487,12 @@ async function execute(cmd: string, args: string[], { cwd }: { cwd: string }) { if (status === 0) { return ok(stdout); } else { - error(stdout); return fail(new ToolkitError(`${cmd} exited with status ${status}`)); } }); + }).catch(async (err) => { + await ioHelper.defaults.error(stdout); + throw err; }); } diff --git a/packages/aws-cdk/lib/commands/init/os.ts b/packages/aws-cdk/lib/commands/init/os.ts index cbcef01c0..781bb4c46 100644 --- a/packages/aws-cdk/lib/commands/init/os.ts +++ b/packages/aws-cdk/lib/commands/init/os.ts @@ -1,7 +1,7 @@ import * as child_process from 'child_process'; import { ToolkitError } from '@aws-cdk/toolkit-lib'; import * as chalk from 'chalk'; -import { debug } from '../../logging'; +import type { IoHelper } from '../../api-private'; /** * OS helpers @@ -9,9 +9,9 @@ import { debug } from '../../logging'; * Shell function which both prints to stdout and collects the output into a * string. */ -export async function shell(command: string[]): Promise { +export async function shell(ioHelper: IoHelper, command: string[]): Promise { const commandLine = renderCommandLine(command); - debug(`Executing ${chalk.blue(commandLine)}`); + await ioHelper.defaults.debug(`Executing ${chalk.blue(commandLine)}`); const child = child_process.spawn(command[0], renderArguments(command.slice(1)), { // Need this for Windows where we want .cmd and .bat to be found as well. shell: true, diff --git a/packages/aws-cdk/lib/commands/list-stacks.ts b/packages/aws-cdk/lib/commands/list-stacks.ts index 452d5edbc..493e3471b 100644 --- a/packages/aws-cdk/lib/commands/list-stacks.ts +++ b/packages/aws-cdk/lib/commands/list-stacks.ts @@ -31,5 +31,11 @@ export async function listStacks(toolkit: CdkToolkit, options: ListStacksOptions defaultBehavior: DefaultSelection.AllStacks, }); - return stacks.withDependencies(); + // we only want to print a subset of information in `cdk list --json` + return stacks.withDependencies().map(stack => ({ + id: stack.id, + name: stack.name, + environment: stack.environment, + dependencies: stack.dependencies, + })); } diff --git a/packages/aws-cdk/lib/commands/migrate.ts b/packages/aws-cdk/lib/commands/migrate.ts index e84537249..b967f9e15 100644 --- a/packages/aws-cdk/lib/commands/migrate.ts +++ b/packages/aws-cdk/lib/commands/migrate.ts @@ -20,10 +20,10 @@ import type { import * as cdk_from_cfn from 'cdk-from-cfn'; import * as chalk from 'chalk'; import { cliInit } from './init'; -import { info } from '../../lib/logging'; import type { ICloudFormationClient, SdkProvider } from '../api/aws-auth'; import { CloudFormationStack } from '../api/cloudformation'; import { Mode } from '../api/plugin'; +import type { IoHelper } from '../api-private'; import { zipDirectory } from '../util'; const camelCase = require('camelcase'); const decamelize = require('decamelize'); @@ -39,6 +39,7 @@ const MIGRATE_SUPPORTED_LANGUAGES: readonly string[] = cdk_from_cfn.supported_la * @param outputPath - The path at which to generate the CDK app */ export async function generateCdkApp( + ioHelper: IoHelper, stackName: string, stack: string, language: string, @@ -53,6 +54,7 @@ export async function generateCdkApp( fs.mkdirSync(resolvedOutputPath, { recursive: true }); const generateOnly = compress; await cliInit({ + ioHelper, type: 'app', language, canUseNetwork: true, @@ -163,39 +165,39 @@ export async function readFromStack( * @returns a generated cloudformation template */ export async function generateTemplate(options: GenerateTemplateOptions): Promise { - const cfn = new CfnTemplateGeneratorProvider(await buildCfnClient(options.sdkProvider, options.environment)); + const cfn = new CfnTemplateGeneratorProvider(await buildCfnClient(options.sdkProvider, options.environment), options.ioHelper); + const ioHelper = options.ioHelper; const scanId = await findLastSuccessfulScan(cfn, options); // if a customer accidentally ctrl-c's out of the command and runs it again, this will continue the progress bar where it left off const curScan = await cfn.describeResourceScan(scanId); if (curScan.Status == ScanStatus.IN_PROGRESS) { - info('Resource scan in progress. Please wait, this can take 10 minutes or longer.'); - await scanProgressBar(scanId, cfn); + await ioHelper.defaults.info('Resource scan in progress. Please wait, this can take 10 minutes or longer.'); + await scanProgressBar(ioHelper, scanId, cfn); } - displayTimeDiff(new Date(), new Date(curScan.StartTime!)); + await displayTimeDiff(ioHelper, new Date(), new Date(curScan.StartTime!)); let resources: ScannedResource[] = await cfn.listResourceScanResources(scanId!, options.filters); - info('finding related resources.'); + await ioHelper.defaults.info('finding related resources.'); let relatedResources = await cfn.getResourceScanRelatedResources(scanId!, resources); - info(`Found ${relatedResources.length} resources.`); + await ioHelper.defaults.info(`Found ${relatedResources.length} resources.`); - info('Generating CFN template from scanned resources.'); + await ioHelper.defaults.info('Generating CFN template from scanned resources.'); const templateArn = (await cfn.createGeneratedTemplate(options.stackName, relatedResources)).GeneratedTemplateId!; let generatedTemplate = await cfn.describeGeneratedTemplate(templateArn); - info('Please wait, template creation in progress. This may take a couple minutes.'); + await ioHelper.defaults.info('Please wait, template creation in progress. This may take a couple minutes.'); while (generatedTemplate.Status !== ScanStatus.COMPLETE && generatedTemplate.Status !== ScanStatus.FAILED) { await printDots(`[${generatedTemplate.Status}] Template Creation in Progress`, 400); generatedTemplate = await cfn.describeGeneratedTemplate(templateArn); } - info(''); - info('Template successfully generated!'); - return buildGenertedTemplateOutput( + await ioHelper.defaults.info('\nTemplate successfully generated!'); + return buildGeneratedTemplateOutput( generatedTemplate, (await cfn.getGeneratedTemplate(templateArn)).TemplateBody!, templateArn, @@ -206,10 +208,11 @@ async function findLastSuccessfulScan( cfn: CfnTemplateGeneratorProvider, options: GenerateTemplateOptions, ): Promise { + const ioHelper = options.ioHelper; let resourceScanSummaries: ResourceScanSummary[] | undefined = []; const clientRequestToken = `cdk-migrate-${options.environment.account}-${options.environment.region}`; if (options.fromScan === FromScan.NEW) { - info(`Starting new scan for account ${options.environment.account} in region ${options.environment.region}`); + await ioHelper.defaults.info(`Starting new scan for account ${options.environment.account} in region ${options.environment.region}`); try { await cfn.startResourceScan(clientRequestToken); resourceScanSummaries = (await cfn.listResourceScans()).ResourceScanSummaries; @@ -217,7 +220,7 @@ async function findLastSuccessfulScan( // continuing here because if the scan fails on a new-scan it is very likely because there is either already a scan in progress // or the customer hit a rate limit. In either case we want to continue with the most recent scan. // If this happens to fail for a credential error then that will be caught immediately after anyway. - info(`Scan failed to start due to error '${(e as Error).message}', defaulting to latest scan.`); + await ioHelper.defaults.info(`Scan failed to start due to error '${(e as Error).message}', defaulting to latest scan.`); } } else { resourceScanSummaries = (await cfn.listResourceScans()).ResourceScanSummaries; @@ -412,7 +415,7 @@ function resourceIdentifiers(resourceList: ScannedResource[]): ScannedResourceId * @param scanId - A string representing the scan id * @param cloudFormation - The CloudFormation sdk client to use */ -export async function scanProgressBar(scanId: string, cfn: CfnTemplateGeneratorProvider) { +async function scanProgressBar(ioHelper: IoHelper, scanId: string, cfn: CfnTemplateGeneratorProvider) { let curProgress = 0.5; // we know it's in progress initially since we wouldn't have gotten here if it wasn't let curScan: DescribeResourceScanCommandOutput = { @@ -425,8 +428,7 @@ export async function scanProgressBar(scanId: string, cfn: CfnTemplateGeneratorP printBar(30, curProgress); await new Promise((resolve) => setTimeout(resolve, 2000)); } - info(''); - info('✅ Scan Complete!'); + await ioHelper.defaults.info('\n✅ Scan Complete!'); } /** @@ -496,14 +498,14 @@ export function rewriteLine(message: string) { * @param time1 - The first date to compare * @param time2 - The second date to compare */ -export function displayTimeDiff(time1: Date, time2: Date): void { +async function displayTimeDiff(ioHelper: IoHelper, time1: Date, time2: Date): Promise { const diff = Math.abs(time1.getTime() - time2.getTime()); const days = Math.floor(diff / (1000 * 60 * 60 * 24)); const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)); const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60)); - info(`Using the latest successful scan which is ${days} days, ${hours} hours, and ${minutes} minutes old.`); + await ioHelper.defaults.info(`Using the latest successful scan which is ${days} days, ${hours} hours, and ${minutes} minutes old.`); } /** @@ -574,7 +576,7 @@ export function isThereAWarning(generatedTemplateOutput: GenerateTemplateOutput) * @param templateBody - The body of the generated template * @returns A GenerateTemplateOutput object */ -export function buildGenertedTemplateOutput( +export function buildGeneratedTemplateOutput( generatedTemplateSummary: DescribeGeneratedTemplateCommandOutput, templateBody: string, source: string, @@ -670,8 +672,10 @@ function deduplicateResources(resources: ResourceDetail[]) { */ export class CfnTemplateGeneratorProvider { private cfn: ICloudFormationClient; - constructor(cfn: ICloudFormationClient) { + private ioHelper: IoHelper; + constructor(cfn: ICloudFormationClient, ioHelper: IoHelper) { this.cfn = cfn; + this.ioHelper = ioHelper; } async checkForResourceScan( @@ -685,7 +689,7 @@ export class CfnTemplateGeneratorProvider { 'No scans found. Please either start a new scan with the `--from-scan` new or do not specify a `--from-scan` option.', ); } else { - info('No scans found. Initiating a new resource scan.'); + await this.ioHelper.defaults.info('No scans found. Initiating a new resource scan.'); await this.startResourceScan(clientRequestToken); } } @@ -774,7 +778,7 @@ export class CfnTemplateGeneratorProvider { let resourceScanInputs: ListResourceScanResourcesCommandInput; if (filters.length > 0) { - info('Applying filters to resource scan.'); + await this.ioHelper.defaults.info('Applying filters to resource scan.'); for (const filter of filters) { const filterList = parseFilters(filter); resourceScanInputs = { @@ -797,7 +801,7 @@ export class CfnTemplateGeneratorProvider { } } } else { - info('No filters provided. Retrieving all resources from scan.'); + await this.ioHelper.defaults.info('No filters provided. Retrieving all resources from scan.'); resourceScanInputs = { ResourceScanId: scanId, }; @@ -933,6 +937,7 @@ export interface GenerateTemplateOptions { fromScan?: FromScan; sdkProvider: SdkProvider; environment: Environment; + ioHelper: IoHelper; } /** diff --git a/packages/aws-cdk/lib/cxapp/cloud-assembly.ts b/packages/aws-cdk/lib/cxapp/cloud-assembly.ts index a08d0a05b..824cd6aaf 100644 --- a/packages/aws-cdk/lib/cxapp/cloud-assembly.ts +++ b/packages/aws-cdk/lib/cxapp/cloud-assembly.ts @@ -131,7 +131,6 @@ export class CloudAssembly extends BaseStackAssembly { ): Promise { const matchingPattern = (pattern: string) => (stack: cxapi.CloudFormationStackArtifact) => minimatch(stack.hierarchicalId, pattern); const matchedStacks = flatten(patterns.map(pattern => stacks.filter(matchingPattern(pattern)))); - return this.extendStacks(matchedStacks, stacks, extend); } diff --git a/packages/aws-cdk/lib/index.ts b/packages/aws-cdk/lib/index.ts index 2e4a1c183..62a5d29d4 100644 --- a/packages/aws-cdk/lib/index.ts +++ b/packages/aws-cdk/lib/index.ts @@ -3,4 +3,4 @@ export { cli, exec } from './cli/cli'; // Re-export the legacy exports under a name // We import and re-export them from the index.ts file to generate a single bundle of all code and dependencies -export * as legacy from './legacy-exports-source'; +export * as legacy from './legacy'; diff --git a/packages/aws-cdk/lib/init-templates/.init-version.json b/packages/aws-cdk/lib/init-templates/.init-version.json index cf188c0bb..7b1257dec 100644 --- a/packages/aws-cdk/lib/init-templates/.init-version.json +++ b/packages/aws-cdk/lib/init-templates/.init-version.json @@ -1 +1 @@ -{"aws-cdk-lib": "2.202.0", "constructs": "^10.0.0"} +{"aws-cdk-lib": "2.205.0", "constructs": "^10.0.0"} diff --git a/packages/aws-cdk/lib/init-templates/.recommended-feature-flags.json b/packages/aws-cdk/lib/init-templates/.recommended-feature-flags.json index 41900a9c3..aa804dd0f 100644 --- a/packages/aws-cdk/lib/init-templates/.recommended-feature-flags.json +++ b/packages/aws-cdk/lib/init-templates/.recommended-feature-flags.json @@ -51,6 +51,7 @@ "@aws-cdk/aws-ecs:removeDefaultDeploymentAlarm": true, "@aws-cdk/custom-resources:logApiResponseDataPropertyTrueDefault": false, "@aws-cdk/aws-s3:keepNotificationInImportedBucket": false, + "@aws-cdk/core:explicitStackTags": true, "@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature": false, "@aws-cdk/aws-ecs:disableEcsImdsBlocking": true, "@aws-cdk/aws-ecs:reduceEc2FargateCloudWatchPermissions": true, diff --git a/packages/aws-cdk/lib/legacy-exports-source.ts b/packages/aws-cdk/lib/legacy-exports-source.ts deleted file mode 100644 index e3483339b..000000000 --- a/packages/aws-cdk/lib/legacy-exports-source.ts +++ /dev/null @@ -1,32 +0,0 @@ -// This is a barrel export file, of all known symbols that are imported by users from the `aws-cdk` package. -// Importing these symbols was never officially supported, but here we are. -// In order to preserver backwards-compatibly for these users, we re-export and preserve them as explicit subpath exports. -// See https://github.com/aws/aws-cdk/pull/33021 for more information. - -// API -export { CfnEvaluationException } from './api/cloudformation'; -export { Deployments } from './api/deployments'; -export { deployStack } from './api-private'; -export { PluginHost } from './api/plugin'; -export { Settings } from './api/settings'; -export { Bootstrapper } from './api/bootstrap'; - -// Note: All type exports are in `legacy-exports.ts` -export * from './legacy-logging-source'; -export * from './legacy-aws-auth'; - -// CLI -export { CloudExecutable, execProgram } from './cxapp'; -export { cli, exec } from './cli/cli'; -export { cliRootDir as rootDir } from './cli/root-dir'; -export { Command, Configuration, PROJECT_CONTEXT } from './cli/user-configuration'; -export { formatAsBanner } from './cli/util/console-formatters'; -export { versionNumber } from './cli/version'; - -// Commands -export { RequireApproval } from '@aws-cdk/cloud-assembly-schema'; -export { availableInitTemplates } from './commands/init'; -export { aliases, command, describe } from './commands/docs'; - -// util -export { deepClone, flatten, ifDefined, isArray, isEmpty, numberFromBool, partition, padLeft as leftPad, contentHash, deepMerge, lowerCaseFirstCharacter } from './util'; diff --git a/packages/aws-cdk/lib/legacy-exports.ts b/packages/aws-cdk/lib/legacy-exports.ts index b4c6ab4b1..bf68451b4 100644 --- a/packages/aws-cdk/lib/legacy-exports.ts +++ b/packages/aws-cdk/lib/legacy-exports.ts @@ -25,13 +25,14 @@ import { legacy } from './index'; export type { BootstrapEnvironmentOptions, BootstrapSource } from './api/bootstrap'; export type { DeployStackResult } from './api/deployments'; -// Legacy copies -export type * from './legacy-types'; -export type { Account, ContextProviderPlugin } from './legacy-aws-auth'; -export type { LoggerFunction } from './legacy-logging-source'; +// Legacy type copies +export type * from './legacy'; // Re-export all symbols via index.js // We do this, because index.js is the file that will end up with all dependencies bundled +/** + * @deprecated + */ export const { deepClone, flatten, diff --git a/packages/aws-cdk/lib/legacy-aws-auth.ts b/packages/aws-cdk/lib/legacy/aws-auth.ts similarity index 93% rename from packages/aws-cdk/lib/legacy-aws-auth.ts rename to packages/aws-cdk/lib/legacy/aws-auth.ts index 2ebae47c6..06dd383d0 100644 --- a/packages/aws-cdk/lib/legacy-aws-auth.ts +++ b/packages/aws-cdk/lib/legacy/aws-auth.ts @@ -7,9 +7,9 @@ // and can be used by the users that are ready to migrate // The old code will be removed in a future version of aws-cdk import type { AwsCredentialIdentityProvider, Logger, NodeHttpHandlerOptions } from '@smithy/types'; -import { SdkProvider as SdkProviderCurrentVersion } from './api/aws-auth'; -import { CliIoHost } from './cli/io-host'; -import { GLOBAL_PLUGIN_HOST } from './cli/singleton-plugin-host'; +import { SdkProvider as SdkProviderCurrentVersion } from '../api/aws-auth'; +import { CliIoHost } from '../cli/io-host'; +import { GLOBAL_PLUGIN_HOST } from '../cli/singleton-plugin-host'; /** * @deprecated diff --git a/packages/aws-cdk/lib/legacy/configuration.ts b/packages/aws-cdk/lib/legacy/configuration.ts new file mode 100644 index 000000000..95f31a2ed --- /dev/null +++ b/packages/aws-cdk/lib/legacy/configuration.ts @@ -0,0 +1,395 @@ +import * as os from 'os'; +import * as fs_path from 'path'; +import { ToolkitError } from '@aws-cdk/toolkit-lib'; +import * as fs from 'fs-extra'; +import { debug, warning } from './logging'; +import { Context } from '../api/context'; +import { Settings } from '../api/settings'; +import type { Tag } from '../api/tags'; + +export const PROJECT_CONTEXT = 'cdk.context.json'; +const PROJECT_CONFIG = 'cdk.json'; +const USER_DEFAULTS = '~/.cdk.json'; +const CONTEXT_KEY = 'context'; + +/** + * @deprecated + */ +export enum Command { + LS = 'ls', + LIST = 'list', + DIFF = 'diff', + BOOTSTRAP = 'bootstrap', + DEPLOY = 'deploy', + DESTROY = 'destroy', + SYNTHESIZE = 'synthesize', + SYNTH = 'synth', + METADATA = 'metadata', + INIT = 'init', + VERSION = 'version', + WATCH = 'watch', + GC = 'gc', + ROLLBACK = 'rollback', + IMPORT = 'import', + ACKNOWLEDGE = 'acknowledge', + ACK = 'ack', + NOTICES = 'notices', + MIGRATE = 'migrate', + CONTEXT = 'context', + DOCS = 'docs', + DOC = 'doc', + DOCTOR = 'doctor', + REFACTOR = 'refactor', + DRIFT = 'drift', + CLI_TELEMETRY = 'cli-telemetry', +} + +const BUNDLING_COMMANDS = [ + Command.DEPLOY, + Command.DIFF, + Command.SYNTH, + Command.SYNTHESIZE, + Command.WATCH, + Command.IMPORT, +]; + +type Arguments = { + readonly _: [Command, ...string[]]; + readonly exclusively?: boolean; + readonly STACKS?: string[]; + readonly lookups?: boolean; + readonly [name: string]: unknown; +}; + +interface ConfigurationProps { + /** + * Configuration passed via command line arguments + * + * @default - Nothing passed + */ + readonly commandLineArguments?: Arguments; + + /** + * Whether or not to use context from `.cdk.json` in user home directory + * + * @default true + */ + readonly readUserContext?: boolean; +} + +/** + * All sources of settings combined + * @deprecated + */ +export class Configuration { + public settings = new Settings(); + public context = new Context(); + + public readonly defaultConfig = new Settings({ + versionReporting: true, + assetMetadata: true, + pathMetadata: true, + output: 'cdk.out', + }); + + private readonly commandLineArguments: Settings; + private readonly commandLineContext: Settings; + private _projectConfig?: Settings; + private _projectContext?: Settings; + private loaded = false; + + constructor(private readonly props: ConfigurationProps = {}) { + this.commandLineArguments = props.commandLineArguments + ? commandLineArgumentsToSettings(props.commandLineArguments) + : new Settings(); + this.commandLineContext = this.commandLineArguments + .subSettings([CONTEXT_KEY]) + .makeReadOnly(); + } + + private get projectConfig() { + if (!this._projectConfig) { + throw new ToolkitError('#load has not been called yet!'); + } + return this._projectConfig; + } + + public get projectContext() { + if (!this._projectContext) { + throw new ToolkitError('#load has not been called yet!'); + } + return this._projectContext; + } + + /** + * Load all config + */ + public async load(): Promise { + const userConfig = await loadAndLog(USER_DEFAULTS); + this._projectConfig = await loadAndLog(PROJECT_CONFIG); + this._projectContext = await loadAndLog(PROJECT_CONTEXT); + + // @todo cannot currently be disabled by cli users + const readUserContext = this.props.readUserContext ?? true; + + if (userConfig.get(['build'])) { + throw new ToolkitError( + 'The `build` key cannot be specified in the user config (~/.cdk.json), specify it in the project config (cdk.json) instead', + ); + } + + const contextSources = [ + { bag: this.commandLineContext }, + { + fileName: PROJECT_CONFIG, + bag: this.projectConfig.subSettings([CONTEXT_KEY]).makeReadOnly(), + }, + { fileName: PROJECT_CONTEXT, bag: this.projectContext }, + ]; + if (readUserContext) { + contextSources.push({ + fileName: USER_DEFAULTS, + bag: userConfig.subSettings([CONTEXT_KEY]).makeReadOnly(), + }); + } + + this.context = new Context(...contextSources); + + // Build settings from what's left + this.settings = this.defaultConfig + .merge(userConfig) + .merge(this.projectConfig) + .merge(this.commandLineArguments) + .makeReadOnly(); + + debug('merged settings:', this.settings.all); + + this.loaded = true; + + return this; + } + + /** + * Save the project context + */ + public async saveContext(): Promise { + if (!this.loaded) { + return this; + } // Avoid overwriting files with nothing + + await this.projectContext.save(PROJECT_CONTEXT); + + return this; + } +} + +async function loadAndLog(fileName: string): Promise { + const ret = await settingsFromFile(fileName); + if (!ret.empty) { + debug(fileName + ':', JSON.stringify(ret.all, undefined, 2)); + } + return ret; +} + +async function settingsFromFile(fileName: string): Promise { + let settings; + const expanded = expandHomeDir(fileName); + if (await fs.pathExists(expanded)) { + const data = await fs.readJson(expanded); + settings = new Settings(data); + } else { + settings = new Settings(); + } + + // See https://github.com/aws/aws-cdk/issues/59 + prohibitContextKeys(settings, ['default-account', 'default-region'], fileName); + warnAboutContextKey(settings, 'aws:', fileName); + + return settings; +} + +function prohibitContextKeys(settings: Settings, keys: string[], fileName: string) { + const context = settings.get(['context']); + if (!context || typeof context !== 'object') { + return; + } + + for (const key of keys) { + if (key in context) { + throw new ToolkitError( + `The 'context.${key}' key was found in ${fs_path.resolve( + fileName, + )}, but it is no longer supported. Please remove it.`, + ); + } + } +} + +function warnAboutContextKey(settings: Settings, prefix: string, fileName: string) { + const context = settings.get(['context']); + if (!context || typeof context !== 'object') { + return; + } + + for (const contextKey of Object.keys(context)) { + if (contextKey.startsWith(prefix)) { + warning( + `A reserved context key ('context.${prefix}') key was found in ${fs_path.resolve( + fileName, + )}, it might cause surprising behavior and should be removed.`, + ); + } + } +} + +function expandHomeDir(x: string) { + if (x.startsWith('~')) { + return fs_path.join(os.homedir(), x.slice(1)); + } + return x; +} + +/** + * Parse CLI arguments into Settings + * + * CLI arguments in must be accessed in the CLI code via + * `configuration.settings.get(['argName'])` instead of via `args.argName`. + * + * The advantage is that they can be configured via `cdk.json` and + * `$HOME/.cdk.json`. Arguments not listed below and accessed via this object + * can only be specified on the command line. + * + * @param argv - the received CLI arguments. + * @returns a new Settings object. + */ +function commandLineArgumentsToSettings(argv: Arguments): Settings { + const context = parseStringContextListToObject(argv); + const tags = parseStringTagsListToObject(expectStringList(argv.tags)); + + // Determine bundling stacks + let bundlingStacks: string[]; + if (BUNDLING_COMMANDS.includes(argv._[0])) { + // If we deploy, diff, synth or watch a list of stacks exclusively we skip + // bundling for all other stacks. + bundlingStacks = argv.exclusively ? argv.STACKS ?? ['**'] : ['**']; + } else { + // Skip bundling for all stacks + bundlingStacks = []; + } + + return new Settings({ + app: argv.app, + browser: argv.browser, + build: argv.build, + caBundlePath: argv.caBundlePath, + context, + debug: argv.debug, + tags, + language: argv.language, + pathMetadata: argv.pathMetadata, + assetMetadata: argv.assetMetadata, + profile: argv.profile, + plugin: argv.plugin, + requireApproval: argv.requireApproval, + toolkitStackName: argv.toolkitStackName, + toolkitBucket: { + bucketName: argv.bootstrapBucketName, + kmsKeyId: argv.bootstrapKmsKeyId, + }, + versionReporting: argv.versionReporting, + staging: argv.staging, + output: argv.output, + outputsFile: argv.outputsFile, + progress: argv.progress, + proxy: argv.proxy, + bundlingStacks, + lookups: argv.lookups, + rollback: argv.rollback, + notices: argv.notices, + assetParallelism: argv['asset-parallelism'], + assetPrebuild: argv['asset-prebuild'], + ignoreNoStacks: argv['ignore-no-stacks'], + hotswap: { + ecs: { + minimumHealthyPercent: argv.hotswapEcsMinimumHealthyPercent, + maximumHealthyPercent: argv.hotswapEcsMaximumHealthyPercent, + stabilizationTimeoutSeconds: argv.hotswapEcsStabilizationTimeoutSeconds, + }, + }, + unstable: argv.unstable, + }); +} + +function expectStringList(x: unknown): string[] | undefined { + if (x === undefined) { + return undefined; + } + if (!Array.isArray(x)) { + throw new ToolkitError(`Expected array, got '${x}'`); + } + const nonStrings = x.filter((e) => typeof e !== 'string'); + if (nonStrings.length > 0) { + throw new ToolkitError(`Expected list of strings, found ${nonStrings}`); + } + return x; +} + +function parseStringContextListToObject(argv: Arguments): any { + const context: any = {}; + + for (const assignment of (argv as any).context || []) { + const parts = assignment.split(/=(.*)/, 2); + if (parts.length === 2) { + debug('CLI argument context: %s=%s', parts[0], parts[1]); + if (parts[0].match(/^aws:.+/)) { + throw new ToolkitError( + `User-provided context cannot use keys prefixed with 'aws:', but ${parts[0]} was provided.`, + ); + } + context[parts[0]] = parts[1]; + } else { + warning( + 'Context argument is not an assignment (key=value): %s', + assignment, + ); + } + } + return context; +} + +/** + * Parse tags out of arguments + * + * Return undefined if no tags were provided, return an empty array if only empty + * strings were provided + */ +function parseStringTagsListToObject( + argTags: string[] | undefined, +): Tag[] | undefined { + if (argTags === undefined) { + return undefined; + } + if (argTags.length === 0) { + return undefined; + } + const nonEmptyTags = argTags.filter((t) => t !== ''); + if (nonEmptyTags.length === 0) { + return []; + } + + const tags: Tag[] = []; + + for (const assignment of nonEmptyTags) { + const parts = assignment.split(/=(.*)/, 2); + if (parts.length === 2) { + debug('CLI argument tags: %s=%s', parts[0], parts[1]); + tags.push({ + Key: parts[0], + Value: parts[1], + }); + } else { + warning('Tags argument is not an assignment (key=value): %s', assignment); + } + } + return tags.length > 0 ? tags : undefined; +} diff --git a/packages/aws-cdk/lib/legacy/index.ts b/packages/aws-cdk/lib/legacy/index.ts new file mode 100644 index 000000000..95a3b9138 --- /dev/null +++ b/packages/aws-cdk/lib/legacy/index.ts @@ -0,0 +1,35 @@ +// This is a barrel export file, of all known symbols that are imported by users from the `aws-cdk` package. +// Importing these symbols was never officially supported, but here we are. +// In order to preserver backwards-compatibly for these users, we re-export and preserve them as explicit subpath exports. +// See https://github.com/aws/aws-cdk/pull/33021 for more information. + +// Legacy Type Copies +export type * from './types'; + +// Legacy Code Copies +export * from './logging'; +export * from './aws-auth'; +export { Command, Configuration, PROJECT_CONTEXT } from './configuration'; + +// API +export { CfnEvaluationException } from '../api/cloudformation'; +export { Deployments } from '../api/deployments'; +export { deployStack } from '../api-private'; +export { PluginHost } from '../api/plugin'; +export { Settings } from '../api/settings'; +export { Bootstrapper } from '../api/bootstrap'; + +// CLI +export { CloudExecutable, execProgram } from '../cxapp'; +export { cli, exec } from '../cli/cli'; +export { cliRootDir as rootDir } from '../cli/root-dir'; +export { formatAsBanner } from '../cli/util/console-formatters'; +export { versionNumber } from '../cli/version'; + +// Commands +export { RequireApproval } from '@aws-cdk/cloud-assembly-schema'; +export { availableInitTemplates } from '../commands/init'; +export { aliases, command, describe } from '../commands/docs'; + +// util +export { deepClone, flatten, ifDefined, isArray, isEmpty, numberFromBool, partition, padLeft as leftPad, contentHash, deepMerge, lowerCaseFirstCharacter } from '../util'; diff --git a/packages/aws-cdk/lib/legacy-logging-source.ts b/packages/aws-cdk/lib/legacy/logging.ts similarity index 90% rename from packages/aws-cdk/lib/legacy-logging-source.ts rename to packages/aws-cdk/lib/legacy/logging.ts index 2e4bb1dd8..71ea56c80 100644 --- a/packages/aws-cdk/lib/legacy-logging-source.ts +++ b/packages/aws-cdk/lib/legacy/logging.ts @@ -14,6 +14,9 @@ const { stdout, stderr } = process; type WritableFactory = () => Writable; +/** + * @deprecated + */ export async function withCorkedLogging(block: () => Promise): Promise { corkLogging(); try { @@ -71,6 +74,9 @@ function formatTime(d: Date) { } } +/** + * @deprecated + */ export enum LogLevel { /** Not verbose at all */ DEFAULT = 0, @@ -80,17 +86,32 @@ export enum LogLevel { TRACE = 2, } +/** + * @deprecated + */ export let logLevel = LogLevel.DEFAULT; +/** + * @deprecated + */ export let CI = false; +/** + * @deprecated + */ export function setLogLevel(newLogLevel: LogLevel) { logLevel = newLogLevel; } +/** + * @deprecated + */ export function setCI(newCI: boolean) { CI = newCI; } +/** + * @deprecated + */ export function increaseVerbosity() { logLevel += 1; } @@ -98,20 +119,49 @@ export function increaseVerbosity() { const stream = () => CI ? stdout : stderr; const _debug = logger(stream, [chalk.gray], true); +/** + * @deprecated + */ export const trace = (fmt: string, ...args: unknown[]) => logLevel >= LogLevel.TRACE && _debug(fmt, ...args); +/** + * @deprecated + */ export const debug = (fmt: string, ...args: unknown[]) => logLevel >= LogLevel.DEBUG && _debug(fmt, ...args); +/** + * @deprecated + */ export const error = logger(stderr, [chalk.red]); +/** + * @deprecated + */ export const warning = logger(stream, [chalk.yellow]); +/** + * @deprecated + */ export const success = logger(stream, [chalk.green]); +/** + * @deprecated + */ export const highlight = logger(stream, [chalk.bold]); +/** + * @deprecated + */ export const print = logger(stream); +/** + * @deprecated + */ export const data = logger(stdout); +/** + * @deprecated + */ export type LoggerFunction = (fmt: string, ...args: unknown[]) => void; /** * Create a logger output that features a constant prefix string. * + * @deprecated + * * @param prefixString - the prefix string to be appended before any log entry. * @param fn - the logger function to be used (typically one of the other functions in this module) * diff --git a/packages/aws-cdk/lib/legacy-types.ts b/packages/aws-cdk/lib/legacy/types.ts similarity index 100% rename from packages/aws-cdk/lib/legacy-types.ts rename to packages/aws-cdk/lib/legacy/types.ts diff --git a/packages/aws-cdk/lib/logging.ts b/packages/aws-cdk/lib/logging.ts deleted file mode 100644 index 2253d7cf2..000000000 --- a/packages/aws-cdk/lib/logging.ts +++ /dev/null @@ -1,170 +0,0 @@ -import * as chalk from 'chalk'; -import { asIoHelper } from '../lib/api-private'; -import type { IoMessageLevel } from './cli/io-host/cli-io-host'; -import { CliIoHost } from './cli/io-host/cli-io-host'; - -type IoMessageCodeCategory = 'TOOLKIT' | 'SDK' | 'ASSETS'; -type IoCodeLevel = 'E' | 'W' | 'I'; -type IoMessageSpecificCode = `CDK_${IoMessageCodeCategory}_${L}${number}${number}${number}${number}`; - -/** - * Logs messages to the global CliIoHost - * - * Internal helper that processes log inputs into a consistent format. - * Handles string interpolation, format strings, and object parameter styles. - * Applies optional styling and sends the message to the IoHost. - */ -function formatMessageAndLog( - level: IoMessageLevel, - input: LogInput, - ...args: unknown[] -): void { - const singletonHost = CliIoHost.instance(); - // ALARM: forcing a CliAction into a ToolkitAction. - const helper = asIoHelper(singletonHost, singletonHost.currentAction as any); - - if (typeof input === 'string') { - void singletonHost.defaults[level](input, ...args); - } else { - void helper.notify({ - data: undefined, - time: new Date(), - level, - ...input, - }); - } -} - -// Type for the object parameter style -interface LogParams { - /** - * Message code - */ - readonly code: IoMessageSpecificCode; - /** - * Message - */ - readonly message: string; -} - -// Type for the exported log function arguments -type LogInput = string | LogParams; - -// Exported logging functions. If any additional logging functionality is required, it should be added as -// a new logging function here. - -/** - * Logs an error level message. - * - * Can be used in multiple ways: - * ```ts - * error(`operation failed: ${e}`) // infers default error code `CDK_TOOLKIT_E000` - * error('operation failed: %s', e) // infers default error code `CDK_TOOLKIT_E000` - * error({ message: 'operation failed', code: 'CDK_SDK_E001' }) // specifies error code `CDK_SDK_E001` - * error({ message: 'operation failed: %s', code: 'CDK_SDK_E001' }, e) // specifies error code `CDK_SDK_E001` - * ``` - */ -export const error = (input: LogInput<'E'>, ...args: unknown[]) => { - return formatMessageAndLog('error', input, ...args); -}; - -/** - * Logs an warning level message. - * - * Can be used in multiple ways: - * ```ts - * warning(`deprected feature: ${message}`) // infers default warning code `CDK_TOOLKIT_W000` - * warning('deprected feature: %s', message) // infers default warning code `CDK_TOOLKIT_W000` - * warning({ message: 'deprected feature', code: 'CDK_SDK_W001' }) // specifies warning code `CDK_SDK_W001` - * warning({ message: 'deprected feature: %s', code: 'CDK_SDK_W001' }, message) // specifies warning code `CDK_SDK_W001` - * ``` - */ -export const warning = (input: LogInput<'W'>, ...args: unknown[]) => { - return formatMessageAndLog('warn', input, ...args); -}; - -/** - * Logs an info level message. - * - * Can be used in multiple ways: - * ```ts - * info(`processing: ${message}`) // infers default info code `CDK_TOOLKIT_I000` - * info('processing: %s', message) // infers default info code `CDK_TOOLKIT_I000` - * info({ message: 'processing', code: 'CDK_TOOLKIT_I001' }) // specifies info code `CDK_TOOLKIT_I001` - * info({ message: 'processing: %s', code: 'CDK_TOOLKIT_I001' }, message) // specifies info code `CDK_TOOLKIT_I001` - * ``` - */ -export const info = (input: LogInput<'I'>, ...args: unknown[]) => { - return formatMessageAndLog('info', input, ...args); -}; - -/** - * Logs an result. In the CLI, this always goes to stdout. - * - * Can be used in multiple ways: - * ```ts - * result(`${JSON.stringify(stats)}`) // infers default info code `CDK_TOOLKIT_I000` - * result('{"count": %d}', count) // infers default info code `CDK_TOOLKIT_I000` - * result({ message: 'stats: %j', code: 'CDK_DATA_I001' }) // specifies info code `CDK_DATA_I001` - * result({ message: 'stats: %j', code: 'CDK_DATA_I001' }, stats) // specifies info code `CDK_DATA_I001` - * ``` - */ -export const result = (input: LogInput<'I'>, ...args: unknown[]) => { - return formatMessageAndLog('result', input, ...args); -}; - -/** - * Logs a debug level message. - * - * Can be used in multiple ways: - * ```ts - * debug(`state: ${JSON.stringify(state)}`) // infers default info code `CDK_TOOLKIT_I000` - * debug('cache hit ratio: %d%%', ratio) // infers default info code `CDK_TOOLKIT_I000` - * debug({ message: 'state update', code: 'CDK_TOOLKIT_I001' }) // specifies info code `CDK_TOOLKIT_I001` - * debug({ message: 'ratio: %d%%', code: 'CDK_TOOLKIT_I001' }, ratio) // specifies info code `CDK_TOOLKIT_I001` - * ``` - */ -export const debug = (input: LogInput<'I'>, ...args: unknown[]) => { - return formatMessageAndLog('debug', input, ...args); -}; - -/** - * Logs an info level success message in green text. - * - * Can be used in multiple ways: - * ```ts - * success(`deployment completed: ${name}`) // infers default info code `CDK_TOOLKIT_I000` - * success('processed %d items', count) // infers default info code `CDK_TOOLKIT_I000` - * success({ message: 'completed', code: 'CDK_TOOLKIT_I001' }) // specifies info code `CDK_TOOLKIT_I001` - * success({ message: 'items: %d', code: 'CDK_TOOLKIT_I001' }, count) // specifies info code `CDK_TOOLKIT_I001` - * ``` - */ -export const success = (input: LogInput<'I'>, ...args: unknown[]) => { - return formatMessageAndLog('info', chalkInput(input, chalk.green), ...args); -}; - -/** - * Logs an info level message in bold text. - * - * Can be used in multiple ways: - * ```ts - * highlight(`important: ${msg}`) // infers default info code `CDK_TOOLKIT_I000` - * highlight('attention required: %s', reason) // infers default info code `CDK_TOOLKIT_I000` - * highlight({ message: 'notice', code: 'CDK_TOOLKIT_I001' }) // specifies info code `CDK_TOOLKIT_I001` - * highlight({ message: 'notice: %s', code: 'CDK_TOOLKIT_I001' }, msg) // specifies info code `CDK_TOOLKIT_I001` - * ``` - */ -export const highlight = (input: LogInput<'I'>, ...args: unknown[]) => { - return formatMessageAndLog('info', chalkInput(input, chalk.bold), ...args); -}; - -function chalkInput>(i: A, style: (str: string) => string): A { - if (typeof i === 'string') { - return style(i) as A; - } - - return { - ...i as any, - message: style(i.message), - }; -} diff --git a/packages/aws-cdk/package.json b/packages/aws-cdk/package.json index 7b3b038a0..21b8e2a0c 100644 --- a/packages/aws-cdk/package.json +++ b/packages/aws-cdk/package.json @@ -49,7 +49,7 @@ "@types/yargs": "^15", "@typescript-eslint/eslint-plugin": "^8", "@typescript-eslint/parser": "^8", - "aws-cdk-lib": "^2.202.0", + "aws-cdk-lib": "2.205.0", "aws-sdk-client-mock": "^4.1.0", "aws-sdk-client-mock-jest": "^4.1.0", "axios": "^1.10.0", @@ -70,19 +70,19 @@ "license-checker": "^25.0.1", "madge": "^8.0.0", "nock": "13", - "node-backpack": "^1.0.0", + "node-backpack": "^1.1.0", "prettier": "^2.8", "sinon": "^19.0.5", "ts-jest": "^29.4.0", "ts-mock-imports": "^1.3.17", - "typescript": "5.6", + "typescript": "5.8", "xml-js": "^1.6.11" }, "dependencies": { "@aws-cdk/cdk-assets-lib": "^0.0.0", "@aws-cdk/cloud-assembly-schema": "^0.0.0", "@aws-cdk/cloudformation-diff": "^0.0.0", - "@aws-cdk/cx-api": "^2.202.0", + "@aws-cdk/cx-api": "^2.205.0", "@aws-cdk/toolkit-lib": "^0.0.0", "@aws-sdk/client-appsync": "^3", "@aws-sdk/client-cloudcontrol": "^3", @@ -108,7 +108,7 @@ "@aws-sdk/middleware-endpoint": "^3.374.0", "@aws-sdk/util-retry": "^3.374.0", "@aws-sdk/util-waiter": "^3.374.0", - "@smithy/middleware-endpoint": "^4.1.13", + "@smithy/middleware-endpoint": "^4.1.15", "@smithy/property-provider": "^4.0.4", "@smithy/shared-ini-file-loader": "^4.0.4", "@smithy/types": "^4.3.1", @@ -116,7 +116,7 @@ "@smithy/util-waiter": "^4.0.6", "archiver": "^7.0.1", "camelcase": "^6", - "cdk-from-cfn": "^0.226.0", + "cdk-from-cfn": "^0.230.0", "chalk": "^4", "chokidar": "^3", "decamelize": "^5", diff --git a/packages/aws-cdk/test/_helpers/assembly.ts b/packages/aws-cdk/test/_helpers/assembly.ts index b9c47bbe5..1327ae32c 100644 --- a/packages/aws-cdk/test/_helpers/assembly.ts +++ b/packages/aws-cdk/test/_helpers/assembly.ts @@ -40,19 +40,23 @@ export interface TestAssembly { } export class MockCloudExecutable extends CloudExecutable { + public static async create(assembly: TestAssembly, sdkProviderArg?: MockSdkProvider, ioHost?: IIoHost) { + const mockIoHost = ioHost ?? new TestIoHost(); + const configuration = await Configuration.fromArgs(asIoHelper(mockIoHost, 'deploy')); + const sdkProvider = sdkProviderArg ?? new MockSdkProvider(); + + return new MockCloudExecutable(assembly, configuration, sdkProvider, mockIoHost); + } + public readonly configuration: Configuration; public readonly sdkProvider: MockSdkProvider; - constructor(assembly: TestAssembly, sdkProviderArg?: MockSdkProvider, ioHost?: IIoHost) { - const configuration = new Configuration(); - const sdkProvider = sdkProviderArg ?? new MockSdkProvider(); - const mockIoHost = ioHost ?? new TestIoHost(); - + private constructor(assembly: TestAssembly, configuration: Configuration, sdkProvider: MockSdkProvider, ioHost: IIoHost) { super({ configuration, sdkProvider, synthesizer: () => Promise.resolve(testAssembly(assembly)), - ioHelper: asIoHelper(mockIoHost, 'deploy'), + ioHelper: asIoHelper(ioHost, 'deploy'), }); this.configuration = configuration; diff --git a/packages/aws-cdk/test/_helpers/io-host.ts b/packages/aws-cdk/test/_helpers/io-host.ts index 2a96d1b46..c03a38184 100644 --- a/packages/aws-cdk/test/_helpers/io-host.ts +++ b/packages/aws-cdk/test/_helpers/io-host.ts @@ -39,3 +39,10 @@ export class TestIoHost implements IIoHost { return msg.defaultResponse; } } + +export function expectIoMsg(message: any, level?: IoMessageLevel) { + return expect.objectContaining({ + message, + level: level ?? expect.any(String), + }); +} diff --git a/packages/aws-cdk/test/_helpers/promises.ts b/packages/aws-cdk/test/_helpers/promises.ts new file mode 100644 index 000000000..58a62713a --- /dev/null +++ b/packages/aws-cdk/test/_helpers/promises.ts @@ -0,0 +1,19 @@ +/** + * A backport of Promiser.withResolvers + * + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/withResolvers + */ +export function promiseWithResolvers(): PromiseAndResolvers { + let resolve: PromiseAndResolvers['resolve'], reject: PromiseAndResolvers['reject']; + const promise = new Promise((res, rej) => { + resolve = res; + reject = rej; + }); + return { promise, resolve: resolve!, reject: reject! }; +} + +interface PromiseAndResolvers { + promise: Promise; + resolve: (value: A) => void; + reject: (reason: any) => void; +} diff --git a/packages/aws-cdk/test/cli/cdk-toolkit.test.ts b/packages/aws-cdk/test/cli/cdk-toolkit.test.ts index f9bab081d..51d872a4d 100644 --- a/packages/aws-cdk/test/cli/cdk-toolkit.test.ts +++ b/packages/aws-cdk/test/cli/cdk-toolkit.test.ts @@ -50,11 +50,6 @@ const fakeChokidarWatch = { }, }; -const mockResult = jest.fn(); -jest.mock('../../lib/logging', () => ({ - ...jest.requireActual('../../lib/logging'), - result: mockResult, -})); jest.setTimeout(30_000); import 'aws-sdk-client-mock'; @@ -94,6 +89,7 @@ import { flatten } from '../../lib/util'; import { instanceMockFrom } from '../_helpers/as-mock'; import type { TestStackArtifact } from '../_helpers/assembly'; import { MockCloudExecutable } from '../_helpers/assembly'; +import { expectIoMsg } from '../_helpers/io-host'; import { mockCloudFormationClient, MockSdk, @@ -101,16 +97,18 @@ import { mockSSMClient, restoreSdkMocksToDefault, } from '../_helpers/mock-sdk'; +import { promiseWithResolvers } from '../_helpers/promises'; markTesting(); const defaultBootstrapSource: BootstrapSource = { source: 'default' }; const bootstrapEnvironmentMock = jest.spyOn(Bootstrapper.prototype, 'bootstrapEnvironment'); let cloudExecutable: MockCloudExecutable; -let stderrMock: jest.SpyInstance; -let ioHelper = asIoHelper(CliIoHost.instance(), 'deploy'); +let ioHost = CliIoHost.instance(); +let ioHelper = asIoHelper(ioHost, 'deploy'); +let notifySpy = jest.spyOn(ioHost, 'notify'); -beforeEach(() => { +beforeEach(async () => { jest.resetAllMocks(); restoreSdkMocksToDefault(); @@ -125,7 +123,7 @@ beforeEach(() => { stackArn: 'fake-arn', }); - cloudExecutable = new MockCloudExecutable({ + cloudExecutable = await MockCloudExecutable.create({ stacks: [MockStack.MOCK_STACK_A, MockStack.MOCK_STACK_B], nestedAssemblies: [ { @@ -134,14 +132,15 @@ beforeEach(() => { ], }); - CliIoHost.instance().isCI = false; - stderrMock = jest.spyOn(process.stderr, 'write').mockImplementation(() => { - return true; - }); + ioHost = CliIoHost.instance(); + ioHelper = asIoHelper(ioHost, 'deploy'); + ioHost.isCI = false; + notifySpy = jest.spyOn(ioHost, 'notify'); }); function defaultToolkitSetup() { return new CdkToolkit({ + ioHost, cloudExecutable, configuration: cloudExecutable.configuration, sdkProvider: cloudExecutable.sdkProvider, @@ -159,7 +158,7 @@ describe('bootstrap', () => { test('accepts qualifier from context', async () => { // GIVEN const toolkit = defaultToolkitSetup(); - const configuration = new Configuration(); + const configuration = await Configuration.fromArgs(ioHelper); configuration.context.set('@aws-cdk/core:bootstrapQualifier', 'abcde'); // WHEN @@ -190,9 +189,9 @@ describe('list', () => { // THEN expect(result).toEqual(0); // Exit code - expect(mockResult).toHaveBeenCalledWith('Test-Stack-A-Display-Name'); - expect(mockResult).toHaveBeenCalledWith('Test-Stack-B'); - expect(mockResult).toHaveBeenCalledWith('Test-Stack-A/Test-Stack-C'); + expect(notifySpy).toHaveBeenCalledWith(expectIoMsg('Test-Stack-A-Display-Name', 'result')); + expect(notifySpy).toHaveBeenCalledWith(expectIoMsg('Test-Stack-B', 'result')); + expect(notifySpy).toHaveBeenCalledWith(expectIoMsg('Test-Stack-A/Test-Stack-C', 'result')); }); }); @@ -224,6 +223,7 @@ describe('deploy', () => { }), ); const cdkToolkit = new CdkToolkit({ + ioHost, cloudExecutable, configuration: cloudExecutable.configuration, sdkProvider: cloudExecutable.sdkProvider, @@ -288,19 +288,16 @@ describe('deploy', () => { test('uses display names to reference assets', async () => { // GIVEN - cloudExecutable = new MockCloudExecutable({ + cloudExecutable = await MockCloudExecutable.create({ stacks: [MockStack.MOCK_STACK_WITH_ASSET], }); const toolkit = new CdkToolkit({ + ioHost, cloudExecutable, configuration: cloudExecutable.configuration, sdkProvider: cloudExecutable.sdkProvider, deployments: new FakeCloudFormation({}), }); - stderrMock.mockImplementation((...x) => { - // eslint-disable-next-line no-console - console.error(...x); - }); // WHEN await toolkit.deploy({ @@ -309,16 +306,17 @@ describe('deploy', () => { }); // THEN - expect(stderrMock).toHaveBeenCalledWith(expect.stringContaining('Building Asset Display Name')); - expect(stderrMock).toHaveBeenCalledWith(expect.stringContaining('Publishing Asset Display Name (desto)')); + expect(notifySpy).toHaveBeenCalledWith(expect.objectContaining({ message: expect.stringContaining('Building Asset Display Name') })); + expect(notifySpy).toHaveBeenCalledWith(expect.objectContaining({ message: expect.stringContaining('Publishing Asset Display Name (desto)') })); }); test('force flag is passed to asset publishing', async () => { // GIVEN - cloudExecutable = new MockCloudExecutable({ + cloudExecutable = await MockCloudExecutable.create({ stacks: [MockStack.MOCK_STACK_WITH_ASSET], }); const toolkit = new CdkToolkit({ + ioHost, cloudExecutable, configuration: cloudExecutable.configuration, sdkProvider: cloudExecutable.sdkProvider, @@ -354,8 +352,8 @@ describe('deploy', () => { }); describe('sns notification arns', () => { - beforeEach(() => { - cloudExecutable = new MockCloudExecutable({ + beforeEach(async () => { + cloudExecutable = await MockCloudExecutable.create({ stacks: [ MockStack.MOCK_STACK_A, MockStack.MOCK_STACK_B, @@ -372,6 +370,7 @@ describe('deploy', () => { 'arn:aws:sns:eu-west-1:111155556666:my-great-topic', ]; const toolkit = new CdkToolkit({ + ioHost, cloudExecutable, configuration: cloudExecutable.configuration, sdkProvider: cloudExecutable.sdkProvider, @@ -396,6 +395,7 @@ describe('deploy', () => { // GIVEN const notificationArns = ['arn:::cfn-my-cool-topic']; const toolkit = new CdkToolkit({ + ioHost, cloudExecutable, configuration: cloudExecutable.configuration, sdkProvider: cloudExecutable.sdkProvider, @@ -422,6 +422,7 @@ describe('deploy', () => { // GIVEN const expectedNotificationArns = ['arn:aws:sns:bermuda-triangle-1337:123456789012:MyTopic']; const toolkit = new CdkToolkit({ + ioHost, cloudExecutable, configuration: cloudExecutable.configuration, sdkProvider: cloudExecutable.sdkProvider, @@ -443,6 +444,7 @@ describe('deploy', () => { test('fail with incorrect sns notification arns in the executable', async () => { // GIVEN const toolkit = new CdkToolkit({ + ioHost, cloudExecutable, configuration: cloudExecutable.configuration, sdkProvider: cloudExecutable.sdkProvider, @@ -471,6 +473,7 @@ describe('deploy', () => { 'arn:aws:sns:bermuda-triangle-1337:123456789012:MyTopic', ]); const toolkit = new CdkToolkit({ + ioHost, cloudExecutable, configuration: cloudExecutable.configuration, sdkProvider: cloudExecutable.sdkProvider, @@ -494,6 +497,7 @@ describe('deploy', () => { // GIVEN const notificationArns = ['arn:::cfn-my-cool-topic']; const toolkit = new CdkToolkit({ + ioHost, cloudExecutable, configuration: cloudExecutable.configuration, sdkProvider: cloudExecutable.sdkProvider, @@ -519,6 +523,7 @@ describe('deploy', () => { // GIVEN const notificationArns = ['arn:aws:sns:bermuda-triangle-1337:123456789012:MyTopic']; const toolkit = new CdkToolkit({ + ioHost, cloudExecutable, configuration: cloudExecutable.configuration, sdkProvider: cloudExecutable.sdkProvider, @@ -544,6 +549,7 @@ describe('deploy', () => { // GIVEN const notificationArns = ['arn:::cfn-my-cool-topic']; const toolkit = new CdkToolkit({ + ioHost, cloudExecutable, configuration: cloudExecutable.configuration, sdkProvider: cloudExecutable.sdkProvider, @@ -646,7 +652,7 @@ describe('deploy', () => { let mockCloudExecutable: MockCloudExecutable; let sdkProvider: SdkProvider; let mockForEnvironment: any; - beforeEach(() => { + beforeEach(async () => { jest.resetAllMocks(); template = { Resources: { @@ -658,7 +664,7 @@ describe('deploy', () => { }, }, }; - mockCloudExecutable = new MockCloudExecutable({ + mockCloudExecutable = await MockCloudExecutable.create({ stacks: [ { stackName: 'Test-Stack-C', @@ -712,6 +718,7 @@ describe('deploy', () => { mockSSMClient.on(GetParameterCommand).resolves({ Parameter: { Value: '6' } }); const cdkToolkit = new CdkToolkit({ + ioHost, cloudExecutable: mockCloudExecutable, configuration: mockCloudExecutable.configuration, sdkProvider: mockCloudExecutable.sdkProvider, @@ -752,6 +759,7 @@ describe('deploy', () => { mockSSMClient.on(GetParameterCommand).resolves({ Parameter: { Value: '1' } }); const cdkToolkit = new CdkToolkit({ + ioHost, cloudExecutable: mockCloudExecutable, configuration: mockCloudExecutable.configuration, sdkProvider: mockCloudExecutable.sdkProvider, @@ -768,11 +776,10 @@ describe('deploy', () => { }); // THEN - expect(flatten(stderrMock.mock.calls)).toEqual( + expect(flatten(notifySpy.mock.calls)).toEqual( expect.arrayContaining([ - - expect.stringContaining( - "Bootstrap stack version '5' is required, found version '1'. To get rid of this error, please upgrade to bootstrap version >= 5", + expectIoMsg( + expect.stringContaining("Bootstrap stack version '5' is required, found version '1'. To get rid of this error, please upgrade to bootstrap version >= 5"), ), ]), ); @@ -817,6 +824,7 @@ describe('deploy', () => { }); const cdkToolkit = new CdkToolkit({ + ioHost, cloudExecutable: mockCloudExecutable, configuration: mockCloudExecutable.configuration, sdkProvider: mockCloudExecutable.sdkProvider, @@ -833,8 +841,8 @@ describe('deploy', () => { }); // THEN - expect(flatten(stderrMock.mock.calls)).toEqual( - expect.arrayContaining([expect.stringMatching(/SSM parameter.*not found./)]), + expect(flatten(notifySpy.mock.calls)).toEqual( + expect.arrayContaining([expectIoMsg(expect.stringMatching(/SSM parameter.*not found./))]), ); expect(mockForEnvironment).toHaveBeenCalledTimes(3); expect(mockForEnvironment).toHaveBeenNthCalledWith( @@ -873,6 +881,7 @@ describe('deploy', () => { }); const cdkToolkit = new CdkToolkit({ + ioHost, cloudExecutable: mockCloudExecutable, configuration: mockCloudExecutable.configuration, sdkProvider: mockCloudExecutable.sdkProvider, @@ -890,8 +899,8 @@ describe('deploy', () => { // THEN expect(mockSSMClient).not.toHaveReceivedAnyCommand(); - expect(flatten(stderrMock.mock.calls)).toEqual( - expect.arrayContaining([expect.stringMatching(/TheErrorThatGetsThrown/)]), + expect(flatten(notifySpy.mock.calls)).toEqual( + expect.arrayContaining([expectIoMsg(expect.stringMatching(/TheErrorThatGetsThrown/))]), ); expect(mockForEnvironment).toHaveBeenCalledTimes(3); expect(mockForEnvironment).toHaveBeenNthCalledWith( @@ -929,6 +938,7 @@ describe('deploy', () => { }); mockCloudExecutable.sdkProvider.forEnvironment = mockForEnvironment; const cdkToolkit = new CdkToolkit({ + ioHost, cloudExecutable: mockCloudExecutable, configuration: mockCloudExecutable.configuration, sdkProvider: mockCloudExecutable.sdkProvider, @@ -945,9 +955,9 @@ describe('deploy', () => { }); // THEN - expect(flatten(stderrMock.mock.calls)).toEqual( + expect(flatten(notifySpy.mock.calls)).toEqual( expect.arrayContaining([ - expect.stringMatching(/Lookup role.*was not assumed. Proceeding with default credentials./), + expectIoMsg(expect.stringMatching(/Lookup role.*was not assumed. Proceeding with default credentials./)), ]), ); expect(mockSSMClient).not.toHaveReceivedAnyCommand(); @@ -982,6 +992,7 @@ describe('deploy', () => { test('do not print warnings if lookup role not provided in stack artifact', async () => { // GIVEN const cdkToolkit = new CdkToolkit({ + ioHost, cloudExecutable: mockCloudExecutable, configuration: mockCloudExecutable.configuration, sdkProvider: mockCloudExecutable.sdkProvider, @@ -998,7 +1009,7 @@ describe('deploy', () => { }); // THEN - expect(flatten(stderrMock.mock.calls)).not.toEqual( + expect(flatten(notifySpy.mock.calls)).not.toEqual( expect.arrayContaining([ expect.stringMatching(/Could not assume/), expect.stringMatching(/please upgrade to bootstrap version/), @@ -1036,8 +1047,6 @@ describe('deploy', () => { }); test('can set progress via options', async () => { - const ioHost = CliIoHost.instance(); - // Ensure environment allows StackActivityProgress.BAR ioHost.stackProgress = StackActivityProgress.BAR; ioHost.isTTY = true; @@ -1306,13 +1315,16 @@ describe('watch', () => { }); test("an initial 'deploy' is triggered, without any file changes", async () => { - expect(cdkDeployMock).toHaveBeenCalledTimes(1); + expect(cdkDeployMock).toHaveBeenCalledTimes(1); // from ready event }); test("does trigger a 'deploy' for a file change", async () => { await fakeChokidarWatcherOn.fileEventCallback('add', 'my-file'); - expect(cdkDeployMock).toHaveBeenCalledTimes(2); + expect(cdkDeployMock).toHaveBeenCalledTimes( + 1 // from ready event + + 1, // from file event + ); }); test("triggers a 'deploy' twice for two file changes", async () => { @@ -1322,19 +1334,52 @@ describe('watch', () => { fakeChokidarWatcherOn.fileEventCallback('change', 'my-file2'), ]); - expect(cdkDeployMock).toHaveBeenCalledTimes(3); + expect(cdkDeployMock).toHaveBeenCalledTimes( + 1 // from ready event + + 2, // from file events + ); }); test("batches file changes that happen during 'deploy'", async () => { - // eslint-disable-next-line @cdklabs/promiseall-no-unbounded-parallelism - await Promise.all([ - fakeChokidarWatcherOn.fileEventCallback('add', 'my-file1'), + // The next time a deployment is triggered, we want to simulate the deployment + // taking some time, so we can queue up additional file changes. + const deployment = promiseWithResolvers(); + cdkDeployMock.mockImplementationOnce(() => { + return deployment.promise; + }); + + // Send the initial file event, this will start the deployment. + // We don't await this here, since we will finish the deployment after + // other events have been queued up. + const firstEvent = fakeChokidarWatcherOn.fileEventCallback('add', 'my-file1'); + + // We need to wait a few event loop cycles here, before additional events + // are send. If we don't, the callback for these events will be executed + // before we even have started the deployment. And that means the latch is still + // open. In reality, file events will come with a delay anyway. + await new Promise(r => setTimeout(r, 10)); + + // Next we simulate more file events. + // Because the deployment is still ongoing they will be queued. + const otherEvents = [ fakeChokidarWatcherOn.fileEventCallback('change', 'my-file2'), fakeChokidarWatcherOn.fileEventCallback('unlink', 'my-file3'), fakeChokidarWatcherOn.fileEventCallback('add', 'my-file4'), - ]); + ]; + + // Now complete the initial deployment. + // Because we are in the queued state, this will kick-off an other deployment. + deployment.resolve(); - expect(cdkDeployMock).toHaveBeenCalledTimes(3); + // Then wait for all events to complete so we can assert how often deploy was called + // eslint-disable-next-line @cdklabs/promiseall-no-unbounded-parallelism + await Promise.all([firstEvent, ...otherEvents]); + + expect(cdkDeployMock).toHaveBeenCalledTimes( + 1 // from ready event + + 1 // from first add event + + 1, // from the queued events + ); }); }); }); @@ -1346,8 +1391,8 @@ describe('synth', () => { await toolkit.synth([], false, false); // Separate tests as colorizing hampers detection - expect(stderrMock.mock.calls[1][0]).toMatch('Test-Stack-A-Display-Name'); - expect(stderrMock.mock.calls[1][0]).toMatch('Test-Stack-B'); + expect(notifySpy.mock.calls[1][0].message).toMatch('Test-Stack-A-Display-Name'); + expect(notifySpy.mock.calls[1][0].message).toMatch('Test-Stack-B'); }); test('with no stdout option', async () => { @@ -1356,12 +1401,12 @@ describe('synth', () => { // THEN await toolkit.synth(['Test-Stack-A-Display-Name'], false, true); - expect(mockResult.mock.calls.length).toEqual(0); + expect(notifySpy.mock.calls.length).toEqual(0); }); describe('stack with error and flagged for validation', () => { - beforeEach(() => { - cloudExecutable = new MockCloudExecutable({ + beforeEach(async () => { + cloudExecutable = await MockCloudExecutable.create({ stacks: [MockStack.MOCK_STACK_A, MockStack.MOCK_STACK_B], nestedAssemblies: [ { @@ -1386,12 +1431,12 @@ describe('synth', () => { const toolkit = defaultToolkitSetup(); const autoValidate = false; await toolkit.synth([], false, true, autoValidate); - expect(mockResult.mock.calls.length).toEqual(0); + expect(notifySpy.mock.calls.filter(([msg]) => msg.level === 'result').length).toBe(0); }); }); test('stack has error and was explicitly selected', async () => { - cloudExecutable = new MockCloudExecutable({ + cloudExecutable = await MockCloudExecutable.create({ stacks: [MockStack.MOCK_STACK_A, MockStack.MOCK_STACK_B], nestedAssemblies: [ { @@ -1411,7 +1456,7 @@ describe('synth', () => { }); test('stack has error, is not flagged for validation and was not explicitly selected', async () => { - cloudExecutable = new MockCloudExecutable({ + cloudExecutable = await MockCloudExecutable.create({ stacks: [MockStack.MOCK_STACK_A, MockStack.MOCK_STACK_B], nestedAssemblies: [ { @@ -1431,7 +1476,7 @@ describe('synth', () => { }); test('stack has dependency and was explicitly selected', async () => { - cloudExecutable = new MockCloudExecutable({ + cloudExecutable = await MockCloudExecutable.create({ stacks: [MockStack.MOCK_STACK_C, MockStack.MOCK_STACK_D], }); @@ -1439,8 +1484,8 @@ describe('synth', () => { await toolkit.synth([MockStack.MOCK_STACK_D.stackName], true, false); - expect(mockResult.mock.calls.length).toEqual(1); - expect(mockResult.mock.calls[0][0]).toBeDefined(); + expect(notifySpy.mock.calls.length).toEqual(1); + expect(notifySpy.mock.calls[0][0]).toBeDefined(); }); }); @@ -1460,7 +1505,7 @@ describe('migrate', () => { fromStack: true, }), ).rejects.toThrow('Only one of `--from-path` or `--from-stack` may be provided.'); - expect(stderrMock.mock.calls[1][0]).toContain( + expect(notifySpy.mock.calls[1][0].message).toContain( ' ❌ Migrate failed for `no-source`: Only one of `--from-path` or `--from-stack` may be provided.', ); }); @@ -1473,7 +1518,7 @@ describe('migrate', () => { fromPath: './here/template.yml', }), ).rejects.toThrow("'./here/template.yml' is not a valid path."); - expect(stderrMock.mock.calls[1][0]).toContain( + expect(notifySpy.mock.calls[1][0].message).toContain( " ❌ Migrate failed for `bad-local-source`: './here/template.yml' is not a valid path.", ); }); @@ -1482,11 +1527,12 @@ describe('migrate', () => { const mockSdkProvider = new MockSdkProvider(); mockCloudFormationClient.on(DescribeStacksCommand).rejects(new Error('Stack does not exist in this environment')); - const mockCloudExecutable = new MockCloudExecutable({ + const mockCloudExecutable = await MockCloudExecutable.create({ stacks: [], }); const cdkToolkit = new CdkToolkit({ + ioHost, cloudExecutable: mockCloudExecutable, deployments: new Deployments({ sdkProvider: mockSdkProvider, @@ -1502,7 +1548,7 @@ describe('migrate', () => { fromStack: true, }), ).rejects.toThrow('Stack does not exist in this environment'); - expect(stderrMock.mock.calls[1][0]).toContain( + expect(notifySpy.mock.calls[1][0].message).toContain( ' ❌ Migrate failed for `bad-cloudformation-source`: Stack does not exist in this environment', ); }); @@ -1518,7 +1564,7 @@ describe('migrate', () => { ).rejects.toThrow( 'CannotGenerateTemplateStack could not be generated because rust is not a supported language', ); - expect(stderrMock.mock.calls[1][0]).toContain( + expect(notifySpy.mock.calls[1][0].message).toContain( ' ❌ Migrate failed for `cannot-generate-template`: CannotGenerateTemplateStack could not be generated because rust is not a supported language', ); }); @@ -1595,7 +1641,7 @@ describe('migrate', () => { describe('rollback', () => { test('rollback uses deployment role', async () => { - cloudExecutable = new MockCloudExecutable({ + cloudExecutable = await MockCloudExecutable.create({ stacks: [MockStack.MOCK_STACK_C], }); @@ -1605,6 +1651,7 @@ describe('rollback', () => { }); const toolkit = new CdkToolkit({ + ioHost, cloudExecutable, configuration: cloudExecutable.configuration, sdkProvider: cloudExecutable.sdkProvider, @@ -1629,7 +1676,7 @@ describe('rollback', () => { [{ type: 'replacement-requires-rollback' }, false], [{ type: 'replacement-requires-rollback' }, true], ] satisfies Array<[DeployStackResult, boolean]>)('no-rollback deployment that cant proceed will be called with rollback on retry: %p (using force: %p)', async (firstResult, useForce) => { - cloudExecutable = new MockCloudExecutable({ + cloudExecutable = await MockCloudExecutable.create({ stacks: [ MockStack.MOCK_STACK_C, ], @@ -1656,6 +1703,7 @@ describe('rollback', () => { const mockedConfirm = jest.spyOn(promptly, 'confirm').mockResolvedValue(true); const toolkit = new CdkToolkit({ + ioHost, cloudExecutable, configuration: cloudExecutable.configuration, sdkProvider: cloudExecutable.sdkProvider, diff --git a/packages/aws-cdk/test/cli/cli-arguments.test.ts b/packages/aws-cdk/test/cli/cli-arguments.test.ts index e09d48325..cdf2b809a 100644 --- a/packages/aws-cdk/test/cli/cli-arguments.test.ts +++ b/packages/aws-cdk/test/cli/cli-arguments.test.ts @@ -137,6 +137,7 @@ describe('config', () => { notices: expect.anything(), import: expect.anything(), gc: expect.anything(), + flags: expect.anything(), doctor: expect.anything(), docs: expect.anything(), refactor: expect.anything(), diff --git a/packages/aws-cdk/test/cli/cli-commands.test.ts b/packages/aws-cdk/test/cli/cli-commands.test.ts index 9107343d2..3545f3a2f 100644 --- a/packages/aws-cdk/test/cli/cli-commands.test.ts +++ b/packages/aws-cdk/test/cli/cli-commands.test.ts @@ -1,14 +1,7 @@ import { exec } from '../../lib/cli/cli'; -import * as logging from '../../lib/logging'; +import { CliIoHost } from '../../lib/cli/io-host'; -// Mock the dependencies -jest.mock('../../lib/logging', () => ({ - info: jest.fn(), - debug: jest.fn(), - error: jest.fn(), - print: jest.fn(), - result: jest.fn(), -})); +const notifySpy = jest.spyOn(CliIoHost.prototype, 'notify'); jest.mock('@aws-cdk/cx-api'); jest.mock('../../lib/cli/platform-warnings', () => ({ @@ -27,21 +20,21 @@ jest.mock('../../lib/api/notices', () => ({ describe('doctor', () => { test('prints CDK version', async () => { await exec(['doctor']); - expect(logging.info).toHaveBeenCalledWith(expect.stringContaining('CDK Version:')); + expect(notifySpy).toHaveBeenCalledWith(expect.objectContaining({ level: 'info', message: expect.stringContaining('CDK Version:') })); }); }); describe('docs', () => { test('prints docs url version', async () => { await exec(['docs', '-b "echo %u"']); - expect(logging.info).toHaveBeenCalledWith(expect.stringContaining('https://docs.aws.amazon.com/cdk/api/v2/')); + expect(notifySpy).toHaveBeenCalledWith(expect.objectContaining({ level: 'info', message: expect.stringContaining('https://docs.aws.amazon.com/cdk/api/v2/') })); }); }); describe('context', () => { test('prints note about empty context', async () => { await exec(['context']); - expect(logging.info).toHaveBeenCalledWith(expect.stringContaining('This CDK application does not have any saved context values yet.')); + expect(notifySpy).toHaveBeenCalledWith(expect.objectContaining({ level: 'info', message: expect.stringContaining('This CDK application does not have any saved context values yet.') })); }); }); diff --git a/packages/aws-cdk/test/cli/cli.test.ts b/packages/aws-cdk/test/cli/cli.test.ts index 3bb03c9b2..53073a947 100644 --- a/packages/aws-cdk/test/cli/cli.test.ts +++ b/packages/aws-cdk/test/cli/cli.test.ts @@ -1,16 +1,13 @@ import { exec } from '../../lib/cli/cli'; import { CliIoHost } from '../../lib/cli/io-host'; +import { Configuration } from '../../lib/cli/user-configuration'; +import { TestIoHost } from '../_helpers/io-host'; // Store original version module exports so we don't conflict with other tests const originalVersion = jest.requireActual('../../lib/cli/version'); -// Mock the dependencies -jest.mock('../../lib/logging', () => ({ - debug: jest.fn(), - error: jest.fn(), - print: jest.fn(), - result: jest.fn(), -})); +const ioHost = new TestIoHost(); +const ioHelper = ioHost.asHelper(); jest.mock('@aws-cdk/cx-api'); jest.mock('../../lib/cli/platform-warnings', () => ({ @@ -19,7 +16,7 @@ jest.mock('../../lib/cli/platform-warnings', () => ({ jest.mock('../../lib/cli/user-configuration', () => ({ Configuration: jest.fn().mockImplementation(() => ({ - load: jest.fn().mockResolvedValue(undefined), + loadConfigFiles: jest.fn().mockResolvedValue(undefined), settings: { get: jest.fn().mockReturnValue(undefined), }, @@ -29,6 +26,10 @@ jest.mock('../../lib/cli/user-configuration', () => ({ })), })); +const actualUserConfig = jest.requireActual('../../lib/cli/user-configuration'); +Configuration.fromArgs = jest.fn().mockImplementation(() => actualUserConfig.Configuration.fromArgs(ioHelper)); +Configuration.fromArgsAndFiles = jest.fn().mockImplementation(() => actualUserConfig.Configuration.fromArgs(ioHelper)); + jest.mock('../../lib/api/notices', () => ({ Notices: { create: jest.fn().mockReturnValue({ diff --git a/packages/aws-cdk/test/cli/configuration.test.ts b/packages/aws-cdk/test/cli/configuration.test.ts index 3e8c0b361..7ccb0db31 100644 --- a/packages/aws-cdk/test/cli/configuration.test.ts +++ b/packages/aws-cdk/test/cli/configuration.test.ts @@ -1,49 +1,52 @@ import type { Tag } from '../../lib/api/tags'; import { Command, commandLineArgumentsToSettings } from '../../lib/cli/user-configuration'; +import { TestIoHost } from '../_helpers/io-host'; -test('can parse string context from command line arguments', () => { +const ioHelper = new TestIoHost().asHelper(); + +test('can parse string context from command line arguments', async () => { // GIVEN - const settings1 = commandLineArgumentsToSettings({ context: ['foo=bar'], _: [Command.DEPLOY] }); - const settings2 = commandLineArgumentsToSettings({ context: ['foo='], _: [Command.DEPLOY] }); + const settings1 = await commandLineArgumentsToSettings(ioHelper, { context: ['foo=bar'], _: [Command.DEPLOY] }); + const settings2 = await commandLineArgumentsToSettings(ioHelper, { context: ['foo='], _: [Command.DEPLOY] }); // THEN expect(settings1.get(['context']).foo).toEqual( 'bar'); expect(settings2.get(['context']).foo).toEqual( ''); }); -test('can parse string context from command line arguments with equals sign in value', () => { +test('can parse string context from command line arguments with equals sign in value', async () => { // GIVEN - const settings1 = commandLineArgumentsToSettings({ context: ['foo==bar='], _: [Command.DEPLOY] }); - const settings2 = commandLineArgumentsToSettings({ context: ['foo=bar='], _: [Command.DEPLOY] }); + const settings1 = await commandLineArgumentsToSettings(ioHelper, { context: ['foo==bar='], _: [Command.DEPLOY] }); + const settings2 = await commandLineArgumentsToSettings(ioHelper, { context: ['foo=bar='], _: [Command.DEPLOY] }); // THEN expect(settings1.get(['context']).foo).toEqual( '=bar='); expect(settings2.get(['context']).foo).toEqual( 'bar='); }); -test('can parse tag values from command line arguments', () => { +test('can parse tag values from command line arguments', async () => { // GIVEN - const settings1 = commandLineArgumentsToSettings({ tags: ['foo=bar'], _: [Command.DEPLOY] }); - const settings2 = commandLineArgumentsToSettings({ tags: ['foo='], _: [Command.DEPLOY] }); + const settings1 = await commandLineArgumentsToSettings(ioHelper, { tags: ['foo=bar'], _: [Command.DEPLOY] }); + const settings2 = await commandLineArgumentsToSettings(ioHelper, { tags: ['foo='], _: [Command.DEPLOY] }); // THEN expect(settings1.get(['tags']).find((tag: Tag) => tag.Key === 'foo').Value).toEqual('bar'); expect(settings2.get(['tags']).find((tag: Tag) => tag.Key === 'foo').Value).toEqual(''); }); -test('can parse tag values from command line arguments with equals sign in value', () => { +test('can parse tag values from command line arguments with equals sign in value', async () => { // GIVEN - const settings1 = commandLineArgumentsToSettings({ tags: ['foo==bar='], _: [Command.DEPLOY] }); - const settings2 = commandLineArgumentsToSettings({ tags: ['foo=bar='], _: [Command.DEPLOY] }); + const settings1 = await commandLineArgumentsToSettings(ioHelper, { tags: ['foo==bar='], _: [Command.DEPLOY] }); + const settings2 = await commandLineArgumentsToSettings(ioHelper, { tags: ['foo=bar='], _: [Command.DEPLOY] }); // THEN expect(settings1.get(['tags']).find((tag: Tag) => tag.Key === 'foo').Value).toEqual('=bar='); expect(settings2.get(['tags']).find((tag: Tag) => tag.Key === 'foo').Value).toEqual('bar='); }); -test('bundling stacks defaults to an empty list', () => { +test('bundling stacks defaults to an empty list', async () => { // GIVEN - const settings = commandLineArgumentsToSettings({ + const settings = await commandLineArgumentsToSettings(ioHelper, { _: [Command.LIST], }); @@ -51,9 +54,9 @@ test('bundling stacks defaults to an empty list', () => { expect(settings.get(['bundlingStacks'])).toEqual([]); }); -test('bundling stacks defaults to ** for deploy', () => { +test('bundling stacks defaults to ** for deploy', async () => { // GIVEN - const settings = commandLineArgumentsToSettings({ + const settings = await commandLineArgumentsToSettings(ioHelper, { _: [Command.DEPLOY], }); @@ -61,9 +64,9 @@ test('bundling stacks defaults to ** for deploy', () => { expect(settings.get(['bundlingStacks'])).toEqual(['**']); }); -test('bundling stacks defaults to ** for watch', () => { +test('bundling stacks defaults to ** for watch', async () => { // GIVEN - const settings = commandLineArgumentsToSettings({ + const settings = await commandLineArgumentsToSettings(ioHelper, { _: [Command.WATCH], }); @@ -71,9 +74,9 @@ test('bundling stacks defaults to ** for watch', () => { expect(settings.get(['bundlingStacks'])).toEqual(['**']); }); -test('bundling stacks with deploy exclusively', () => { +test('bundling stacks with deploy exclusively', async () => { // GIVEN - const settings = commandLineArgumentsToSettings({ + const settings = await commandLineArgumentsToSettings(ioHelper, { _: [Command.DEPLOY], exclusively: true, STACKS: ['cool-stack'], @@ -83,9 +86,9 @@ test('bundling stacks with deploy exclusively', () => { expect(settings.get(['bundlingStacks'])).toEqual(['cool-stack']); }); -test('bundling stacks with watch exclusively', () => { +test('bundling stacks with watch exclusively', async () => { // GIVEN - const settings = commandLineArgumentsToSettings({ + const settings = await commandLineArgumentsToSettings(ioHelper, { _: [Command.WATCH], exclusively: true, STACKS: ['cool-stack'], @@ -95,9 +98,9 @@ test('bundling stacks with watch exclusively', () => { expect(settings.get(['bundlingStacks'])).toEqual(['cool-stack']); }); -test('should include outputs-file in settings', () => { +test('should include outputs-file in settings', async () => { // GIVEN - const settings = commandLineArgumentsToSettings({ + const settings = await commandLineArgumentsToSettings(ioHelper, { _: [Command.DEPLOY], outputsFile: 'my-outputs-file.json', }); @@ -106,9 +109,9 @@ test('should include outputs-file in settings', () => { expect(settings.get(['outputsFile'])).toEqual('my-outputs-file.json'); }); -test('providing a build arg', () => { +test('providing a build arg', async () => { // GIVEN - const settings = commandLineArgumentsToSettings({ + const settings = await commandLineArgumentsToSettings(ioHelper, { _: [Command.SYNTH], build: 'mvn package', }); diff --git a/packages/aws-cdk/test/cli/io-host/cli-io-host-corked.test.ts b/packages/aws-cdk/test/cli/io-host/cli-io-host-corked.test.ts index e48d9df63..71f1bb913 100644 --- a/packages/aws-cdk/test/cli/io-host/cli-io-host-corked.test.ts +++ b/packages/aws-cdk/test/cli/io-host/cli-io-host-corked.test.ts @@ -1,5 +1,4 @@ import { CliIoHost } from '../../../lib/cli/io-host'; -import { debug, error, info, success, warning } from '../../../lib/logging'; const ioHost = CliIoHost.instance({}, true); let mockStderr: jest.Mock; @@ -27,8 +26,8 @@ afterEach(() => { describe('corked logging', () => { test('buffers messages when corked', async () => { await ioHost.withCorkedLogging(async () => { - info('message 1'); - info('message 2'); + await ioHost.asIoHelper().defaults.info('message 1'); + await ioHost.asIoHelper().defaults.info('message 2'); expect(mockStderr).not.toHaveBeenCalled(); }); @@ -38,11 +37,11 @@ describe('corked logging', () => { test('handles nested corking correctly', async () => { await ioHost.withCorkedLogging(async () => { - info('outer 1'); + await ioHost.asIoHelper().defaults.info('outer 1'); await ioHost.withCorkedLogging(async () => { - info('inner'); + await ioHost.asIoHelper().defaults.info('inner'); }); - info('outer 2'); + await ioHost.asIoHelper().defaults.info('outer 2'); expect(mockStderr).not.toHaveBeenCalled(); }); @@ -54,7 +53,7 @@ describe('corked logging', () => { test('handles errors in corked block while preserving buffer', async () => { await expect(ioHost.withCorkedLogging(async () => { - info('message 1'); + await ioHost.asIoHelper().defaults.info('message 1'); throw new Error('test error'); })).rejects.toThrow('test error'); @@ -67,17 +66,15 @@ describe('corked logging', () => { ioHost.logLevel = 'debug'; await ioHost.withCorkedLogging(async () => { - error('error message'); - warning('warning message'); - success('success message'); - debug('debug message'); + await ioHost.asIoHelper().defaults.error('error message'); + await ioHost.asIoHelper().defaults.warning('warning message'); + await ioHost.asIoHelper().defaults.debug('debug message'); }); const calls = mockStderr.mock.calls.map(call => call[0]); expect(calls).toEqual([ 'error message\n', 'warning message\n', - 'success message\n', expect.stringMatching(/^\[\d{2}:\d{2}:\d{2}\] debug message\n$/), ]); }); diff --git a/packages/aws-cdk/test/cli/telemetry/endpoint-sink.test.ts b/packages/aws-cdk/test/cli/telemetry/endpoint-sink.test.ts index 375d29df0..6af5d4f52 100644 --- a/packages/aws-cdk/test/cli/telemetry/endpoint-sink.test.ts +++ b/packages/aws-cdk/test/cli/telemetry/endpoint-sink.test.ts @@ -1,5 +1,4 @@ import * as https from 'https'; -import { parse } from 'url'; import { IoHelper } from '../../../lib/api-private'; import { CliIoHost } from '../../../lib/cli/io-host'; import { EndpointTelemetrySink } from '../../../lib/cli/telemetry/endpoint-sink'; @@ -88,16 +87,15 @@ describe('EndpointTelemetrySink', () => { test('makes a POST request to the specified endpoint', async () => { // GIVEN const mockRequest = setupMockRequest(); - const endpoint = parse('https://example.com/telemetry'); const testEvent = createTestEvent('test', { foo: 'bar' }); - const client = new EndpointTelemetrySink({ endpoint, ioHost }); + const client = new EndpointTelemetrySink({ endpoint: 'https://example.com/telemetry', ioHost }); // WHEN await client.emit(testEvent); await client.flush(); // THEN - const expectedPayload = JSON.stringify([testEvent]); + const expectedPayload = JSON.stringify({ events: [testEvent] }); expect(https.request).toHaveBeenCalledWith({ hostname: 'example.com', port: null, @@ -117,9 +115,8 @@ describe('EndpointTelemetrySink', () => { test('silently catches request errors', async () => { // GIVEN const mockRequest = setupMockRequest(); - const endpoint = parse('https://example.com/telemetry'); const testEvent = createTestEvent('test'); - const client = new EndpointTelemetrySink({ endpoint, ioHost }); + const client = new EndpointTelemetrySink({ endpoint: 'https://example.com/telemetry', ioHost }); mockRequest.on.mockImplementation((event, callback) => { if (event === 'error') { @@ -137,10 +134,9 @@ describe('EndpointTelemetrySink', () => { test('multiple events sent as one', async () => { // GIVEN const mockRequest = setupMockRequest(); - const endpoint = parse('https://example.com/telemetry'); const testEvent1 = createTestEvent('test1', { foo: 'bar' }); const testEvent2 = createTestEvent('test2', { foo: 'bazoo' }); - const client = new EndpointTelemetrySink({ endpoint, ioHost }); + const client = new EndpointTelemetrySink({ endpoint: 'https://example.com/telemetry', ioHost }); // WHEN await client.emit(testEvent1); @@ -148,7 +144,7 @@ describe('EndpointTelemetrySink', () => { await client.flush(); // THEN - const expectedPayload = JSON.stringify([testEvent1, testEvent2]); + const expectedPayload = JSON.stringify({ events: [testEvent1, testEvent2] }); expect(https.request).toHaveBeenCalledTimes(1); expect(https.request).toHaveBeenCalledWith({ hostname: 'example.com', @@ -169,10 +165,9 @@ describe('EndpointTelemetrySink', () => { test('successful flush clears events cache', async () => { // GIVEN setupMockRequest(); - const endpoint = parse('https://example.com/telemetry'); const testEvent1 = createTestEvent('test1', { foo: 'bar' }); const testEvent2 = createTestEvent('test2', { foo: 'bazoo' }); - const client = new EndpointTelemetrySink({ endpoint, ioHost }); + const client = new EndpointTelemetrySink({ endpoint: 'https://example.com/telemetry', ioHost }); // WHEN await client.emit(testEvent1); @@ -181,7 +176,7 @@ describe('EndpointTelemetrySink', () => { await client.flush(); // THEN - const expectedPayload1 = JSON.stringify([testEvent1]); + const expectedPayload1 = JSON.stringify({ events: [testEvent1] }); expect(https.request).toHaveBeenCalledTimes(2); expect(https.request).toHaveBeenCalledWith({ hostname: 'example.com', @@ -196,7 +191,7 @@ describe('EndpointTelemetrySink', () => { timeout: 500, }, expect.anything()); - const expectedPayload2 = JSON.stringify([testEvent2]); + const expectedPayload2 = JSON.stringify({ events: [testEvent2] }); expect(https.request).toHaveBeenCalledWith({ hostname: 'example.com', port: null, @@ -238,10 +233,9 @@ describe('EndpointTelemetrySink', () => { return mockRequest; }); - const endpoint = parse('https://example.com/telemetry'); const testEvent1 = createTestEvent('test1', { foo: 'bar' }); const testEvent2 = createTestEvent('test2', { foo: 'bazoo' }); - const client = new EndpointTelemetrySink({ endpoint, ioHost }); + const client = new EndpointTelemetrySink({ endpoint: 'https://example.com/telemetry', ioHost }); // WHEN await client.emit(testEvent1); @@ -255,7 +249,7 @@ describe('EndpointTelemetrySink', () => { await client.flush(); // THEN - const expectedPayload1 = JSON.stringify([testEvent1]); + const expectedPayload1 = JSON.stringify({ events: [testEvent1] }); expect(https.request).toHaveBeenCalledTimes(2); expect(https.request).toHaveBeenCalledWith({ hostname: 'example.com', @@ -270,7 +264,7 @@ describe('EndpointTelemetrySink', () => { timeout: 500, }, expect.anything()); - const expectedPayload2 = JSON.stringify([testEvent2]); + const expectedPayload2 = JSON.stringify({ events: [testEvent1, testEvent2] }); expect(https.request).toHaveBeenCalledWith({ hostname: 'example.com', port: null, @@ -278,7 +272,7 @@ describe('EndpointTelemetrySink', () => { method: 'POST', headers: { 'content-type': 'application/json', - 'content-length': expectedPayload1.length + expectedPayload2.length - 1, + 'content-length': expectedPayload2.length, }, agent: undefined, timeout: 500, @@ -289,13 +283,12 @@ describe('EndpointTelemetrySink', () => { // GIVEN jest.useFakeTimers(); setupMockRequest(); // Setup the mock request but we don't need the return value - const endpoint = parse('https://example.com/telemetry'); // Create a spy on setInterval const setIntervalSpy = jest.spyOn(global, 'setInterval'); // Create the client - const client = new EndpointTelemetrySink({ endpoint, ioHost }); + const client = new EndpointTelemetrySink({ endpoint: 'https://example.com/telemetry', ioHost }); // Create a spy on the flush method const flushSpy = jest.spyOn(client, 'flush'); @@ -337,8 +330,7 @@ describe('EndpointTelemetrySink', () => { // Mock IoHelper.fromActionAwareIoHost to return our mock jest.spyOn(IoHelper, 'fromActionAwareIoHost').mockReturnValue(mockIoHelper as any); - const endpoint = parse('https://example.com/telemetry'); - const client = new EndpointTelemetrySink({ endpoint, ioHost }); + const client = new EndpointTelemetrySink({ endpoint: 'https://example.com/telemetry', ioHost }); // Mock https.request to throw an error (https.request as jest.Mock).mockImplementation(() => { diff --git a/packages/aws-cdk/test/cli/telemetry/file-sink.test.ts b/packages/aws-cdk/test/cli/telemetry/file-sink.test.ts index e9982603a..f411aee71 100644 --- a/packages/aws-cdk/test/cli/telemetry/file-sink.test.ts +++ b/packages/aws-cdk/test/cli/telemetry/file-sink.test.ts @@ -1,6 +1,6 @@ -import * as fs from 'fs'; import * as os from 'os'; import * as path from 'path'; +import * as fs from 'fs-extra'; import { IoHelper } from '../../../lib/api-private'; import { CliIoHost } from '../../../lib/cli/io-host'; import { FileTelemetrySink } from '../../../lib/cli/telemetry/file-sink'; @@ -69,10 +69,8 @@ describe('FileTelemetrySink', () => { await client.emit(testEvent); // THEN - expect(fs.existsSync(logFilePath)).toBe(true); - const fileContent = fs.readFileSync(logFilePath, 'utf8'); - const parsedContent = JSON.parse(fileContent); - expect(parsedContent).toEqual(testEvent); + const fileJson = fs.readJSONSync(logFilePath, 'utf8'); + expect(fileJson).toEqual([testEvent]); }); test('appends data to a file', async () => { @@ -116,11 +114,17 @@ describe('FileTelemetrySink', () => { // THEN expect(fs.existsSync(logFilePath)).toBe(true); - const fileContent = fs.readFileSync(logFilePath, 'utf8'); + const fileJson = fs.readJSONSync(logFilePath, 'utf8'); + const expectedJson = [testEvent, testEvent]; + expect(fileJson).toEqual(expectedJson); + }); - // The file should contain two JSON objects, each pretty-printed with a newline - const expectedSingleEvent = JSON.stringify(testEvent, null, 2) + '\n'; - expect(fileContent).toBe(expectedSingleEvent + expectedSingleEvent); + test('constructor throws if file already exists', async () => { + // GIVEN + fs.writeFileSync(logFilePath, 'exists'); + + // WHEN & THEN + expect(() => new FileTelemetrySink({ logFilePath, ioHost })).toThrow(/Telemetry file already exists/); }); test('handles errors gracefully and logs to trace without throwing', async () => { @@ -170,8 +174,8 @@ describe('FileTelemetrySink', () => { const client = new FileTelemetrySink({ logFilePath, ioHost }); - // Mock fs.appendFileSync to throw an error - jest.spyOn(fs, 'appendFileSync').mockImplementation(() => { + // Mock fs.writeJSONSync to throw an error + jest.spyOn(fs, 'writeJSONSync').mockImplementation(() => { throw new Error('File write error'); }); diff --git a/packages/aws-cdk/test/cli/user-config.test.ts b/packages/aws-cdk/test/cli/user-config.test.ts index de367d5b1..7c838a2b9 100644 --- a/packages/aws-cdk/test/cli/user-config.test.ts +++ b/packages/aws-cdk/test/cli/user-config.test.ts @@ -2,9 +2,10 @@ import * as os from 'os'; import * as fs_path from 'path'; import * as fs from 'fs-extra'; -import type { Command } from '../../lib/cli/user-configuration'; +import type { Arguments, Command } from '../../lib/cli/user-configuration'; import { Configuration, PROJECT_CONFIG, PROJECT_CONTEXT } from '../../lib/cli/user-configuration'; import { parseCommandLineArguments } from '../../lib/cli/parse-command-line-arguments'; +import { TestIoHost } from '../_helpers/io-host'; // mock fs deeply jest.mock('fs-extra'); @@ -12,6 +13,9 @@ const mockedFs = jest.mocked(fs, { shallow: true }); const USER_CONFIG = fs_path.join(os.homedir(), '.cdk.json'); +const ioHost = new TestIoHost(); +const ioHelper = ioHost.asHelper(); + test('correctly parses hotswap overrides', async () => { const GIVEN_CONFIG: Map = new Map([ [PROJECT_CONFIG, { @@ -31,14 +35,14 @@ test('correctly parses hotswap overrides', async () => { return GIVEN_CONFIG.get(path); }); - const config = await new Configuration({ + const config = await Configuration.fromArgsAndFiles(ioHelper, { commandLineArguments: { _: ['deploy'] as unknown as [Command, ...string[]], hotswapEcsMinimumHealthyPercent: 50, hotswapEcsMaximumHealthyPercent: 250, hotswapEcsStabilizationTimeoutSeconds: 20, }, - }).load(); + }); expect(config.settings.get(['hotswap', 'ecs', 'minimumHealthyPercent'])).toEqual(50); expect(config.settings.get(['hotswap', 'ecs', 'maximumHealthyPercent'])).toEqual(250); expect(config.settings.get(['hotswap', 'ecs', 'stabilizationTimeoutSeconds'])).toEqual(20); @@ -64,7 +68,7 @@ test('load settings from both files if available', async () => { return GIVEN_CONFIG.get(path); }); - const config = await new Configuration().load(); + const config = await Configuration.fromArgsAndFiles(ioHelper); // THEN expect(config.settings.get(['project'])).toBe('foobar'); @@ -97,7 +101,7 @@ test('load context from all 3 files if available', async () => { return GIVEN_CONFIG.get(path); }); - const config = await new Configuration().load(); + const config = await Configuration.fromArgsAndFiles(ioHelper); // THEN expect(config.context.get('project')).toBe('foobar'); @@ -122,7 +126,7 @@ test('throws an error if the `build` key is specified in the user config', async }); // THEN - await expect(new Configuration().load()).rejects.toEqual(new Error('The `build` key cannot be specified in the user config (~/.cdk.json), specify it in the project config (cdk.json) instead')); + await expect(Configuration.fromArgsAndFiles(ioHelper)).rejects.toEqual(new Error('The `build` key cannot be specified in the user config (~/.cdk.json), specify it in the project config (cdk.json) instead')); }); test('Can specify the `quiet` key in the user config', async () => { @@ -142,7 +146,7 @@ test('Can specify the `quiet` key in the user config', async () => { }); // THEN - const config = await new Configuration().load(); + const config = await Configuration.fromArgsAndFiles(ioHelper); expect(config.settings.get(['quiet'])).toBe(true); }); @@ -154,8 +158,8 @@ test('array settings are not overridden by yarg defaults', async () => { plugin: ['dummy'], }], ]); - const argsWithPlugin = await parseCommandLineArguments(['ls', '--plugin', '[]']); - const argsWithoutPlugin = await parseCommandLineArguments(['ls']); + const argsWithPlugin: Arguments = await parseCommandLineArguments(['ls', '--plugin', '[]']); + const argsWithoutPlugin: Arguments= await parseCommandLineArguments(['ls']); // WHEN mockedFs.pathExists.mockImplementation(path => { @@ -165,12 +169,8 @@ test('array settings are not overridden by yarg defaults', async () => { return GIVEN_CONFIG.get(path); }); - const configWithPlugin = await new Configuration({ - commandLineArguments: argsWithPlugin, - }).load(); - const configWithoutPlugin = await new Configuration({ - commandLineArguments: argsWithoutPlugin, - }).load(); + const configWithPlugin = await Configuration.fromArgsAndFiles(ioHelper, { commandLineArguments: argsWithPlugin }); + const configWithoutPlugin = await Configuration.fromArgsAndFiles(ioHelper, { commandLineArguments: argsWithoutPlugin }); // THEN expect(configWithPlugin.settings.get(['plugin'])).toEqual(['[]']); diff --git a/packages/aws-cdk/test/cli/user-context.test.ts b/packages/aws-cdk/test/cli/user-context.test.ts index 4bf8d0067..b0ff2ff1c 100644 --- a/packages/aws-cdk/test/cli/user-context.test.ts +++ b/packages/aws-cdk/test/cli/user-context.test.ts @@ -5,12 +5,16 @@ import * as fs from 'fs-extra'; import { Configuration, PROJECT_CONFIG, PROJECT_CONTEXT } from '../../lib/cli/user-configuration'; import { Context, TRANSIENT_CONTEXT_KEY } from '../../lib/api/context'; import { Settings } from '../../lib/api/settings'; +import { TestIoHost } from '../_helpers/io-host'; const state: { previousWorkingDir?: string; tempDir?: string; } = {}; +const ioHost = new TestIoHost(); +const ioHelper = ioHost.asHelper(); + beforeEach(async () => { state.previousWorkingDir = process.cwd(); state.tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'aws-cdk-test')); @@ -32,7 +36,7 @@ test('load context from both files if available', async () => { await fs.writeJSON(PROJECT_CONFIG, { context: { boo: 'far' } }); // WHEN - const config = await new Configuration({ readUserContext: false }).load(); + const config = await Configuration.fromArgsAndFiles(ioHelper, { readUserContext: false }); // THEN expect(config.context.get('foo')).toBe('bar'); @@ -43,7 +47,7 @@ test('deleted context disappears from new file', async () => { // GIVEN await fs.writeJSON(PROJECT_CONTEXT, { foo: 'bar' }); await fs.writeJSON(PROJECT_CONFIG, { context: { foo: 'bar' } }); - const config = await new Configuration({ readUserContext: false }).load(); + const config = await Configuration.fromArgsAndFiles(ioHelper, { readUserContext: false }); // WHEN config.context.unset('foo'); @@ -58,7 +62,7 @@ test('clear deletes from new file', async () => { // GIVEN await fs.writeJSON(PROJECT_CONTEXT, { foo: 'bar' }); await fs.writeJSON(PROJECT_CONFIG, { context: { boo: 'far' } }); - const config = await new Configuration({ readUserContext: false }).load(); + const config = await Configuration.fromArgsAndFiles(ioHelper, { readUserContext: false }); // WHEN config.context.clear(); @@ -72,7 +76,7 @@ test('clear deletes from new file', async () => { test('context is preserved in the location from which it is read', async () => { // GIVEN await fs.writeJSON(PROJECT_CONFIG, { context: { 'boo:boo': 'far' } }); - const config = await new Configuration({ readUserContext: false }).load(); + const config = await Configuration.fromArgsAndFiles(ioHelper, { readUserContext: false }); // WHEN expect(config.context.all).toEqual({ 'boo:boo': 'far' }); @@ -87,7 +91,7 @@ test('save no context in old file', async () => { // GIVEN await fs.writeJSON(PROJECT_CONFIG, {}); await fs.writeJSON(PROJECT_CONTEXT, { boo: 'far' }); - const config = await new Configuration({ readUserContext: false }).load(); + const config = await Configuration.fromArgsAndFiles(ioHelper, { readUserContext: false }); // WHEN expect(config.context.all).toEqual({ boo: 'far' }); @@ -100,13 +104,13 @@ test('save no context in old file', async () => { test('command line context is merged with stored context', async () => { // GIVEN await fs.writeJSON(PROJECT_CONTEXT, { boo: 'far' }); - const config = await new Configuration({ + const config = await Configuration.fromArgsAndFiles(ioHelper, { readUserContext: false, commandLineArguments: { context: ['foo=bar'], _: ['command'], } as any, - }).load(); + }); // WHEN expect(config.context.all).toEqual({ foo: 'bar', boo: 'far' }); @@ -114,13 +118,13 @@ test('command line context is merged with stored context', async () => { test('can save and load', async () => { // GIVEN - const config1 = await new Configuration({ readUserContext: false }).load(); + const config1 = await Configuration.fromArgsAndFiles(ioHelper, { readUserContext: false }); config1.context.set('some_key', 'some_value'); await config1.context.save(PROJECT_CONTEXT); expect(config1.context.get('some_key')).toEqual('some_value'); // WHEN - const config2 = await new Configuration({ readUserContext: false }).load(); + const config2 = await Configuration.fromArgsAndFiles(ioHelper, { readUserContext: false }); // THEN expect(config2.context.get('some_key')).toEqual('some_value'); @@ -128,13 +132,13 @@ test('can save and load', async () => { test('transient values arent saved to disk', async () => { // GIVEN - const config1 = await new Configuration({ readUserContext: false }).load(); + const config1 = await Configuration.fromArgsAndFiles(ioHelper, { readUserContext: false }); config1.context.set('some_key', { [TRANSIENT_CONTEXT_KEY]: true, value: 'some_value' }); await config1.context.save(PROJECT_CONTEXT); expect(config1.context.get('some_key').value).toEqual('some_value'); // WHEN - const config2 = await new Configuration({ readUserContext: false }).load(); + const config2 = await Configuration.fromArgsAndFiles(ioHelper, { readUserContext: false }); // THEN expect(config2.context.get('some_key')).toEqual(undefined); diff --git a/packages/aws-cdk/test/cli/version.test.ts b/packages/aws-cdk/test/cli/version.test.ts index 56708b6bb..2057de1d8 100644 --- a/packages/aws-cdk/test/cli/version.test.ts +++ b/packages/aws-cdk/test/cli/version.test.ts @@ -6,8 +6,9 @@ import * as sinon from 'sinon'; import { setTimeout as _setTimeout } from 'timers'; import { promisify } from 'util'; import * as npm from '../../lib/cli/util/npm'; -import { displayVersionMessage, getVersionMessages, isDeveloperBuild, VersionCheckTTL } from '../../lib/cli/version'; -import * as logging from '../../lib/logging'; +import { isDeveloperBuildVersion } from '../../lib/cli/version'; +import { TestIoHost } from '../_helpers/io-host'; +import { displayVersionMessage, getVersionMessages, VersionCheckTTL } from '../../lib/cli/display-version'; jest.setTimeout(10_000); @@ -17,6 +18,9 @@ function tmpfile(): string { return `/tmp/version-${Math.floor(Math.random() * 10000)}`; } +const ioHost = new TestIoHost(); +const ioHelper = ioHost.asHelper(); + beforeEach(() => { process.chdir(os.tmpdir()); // Need a chdir because in the workspace 'npm view' will take a long time }); @@ -70,9 +74,8 @@ test('No Version specified for storage in the TTL file', async () => { test('Skip version check if environment variable is set', async () => { sinon.stub(process, 'stdout').value({ ...process.stdout, isTTY: true }); sinon.stub(process, 'env').value({ ...process.env, CDK_DISABLE_VERSION_CHECK: '1' }); - const printStub = sinon.stub(logging, 'info'); - await displayVersionMessage(); - expect(printStub.called).toEqual(false); + await displayVersionMessage(ioHelper); + expect(ioHost.notifySpy).not.toHaveBeenCalled(); }); describe('version message', () => { @@ -148,7 +151,7 @@ test('isDeveloperBuild call does not throw an error', () => { // that the value is `true` when running tests, because I won't want to make too // many assumptions for no good reason. - isDeveloperBuild(); + isDeveloperBuildVersion(); // THEN: should not explode }); diff --git a/packages/aws-cdk/test/commands/cdk-docs.test.ts b/packages/aws-cdk/test/commands/cdk-docs.test.ts index 7a24b1dd0..6224a1264 100644 --- a/packages/aws-cdk/test/commands/cdk-docs.test.ts +++ b/packages/aws-cdk/test/commands/cdk-docs.test.ts @@ -1,9 +1,11 @@ import * as child_process from 'child_process'; import { mocked } from 'jest-mock'; import { docs } from '../../lib/commands/docs'; +import { TestIoHost } from '../_helpers/io-host'; + +const ioHost = new TestIoHost(); +const ioHelper = ioHost.asHelper('docs'); -// eslint-disable-next-line no-console -console.log = jest.fn(); jest.mock('child_process'); describe('`cdk docs`', () => { @@ -11,7 +13,10 @@ describe('`cdk docs`', () => { const mockChildProcessExec: any = (_: string, cb: (err?: Error, stdout?: string, stderr?: string) => void) => cb(); mocked(child_process.exec).mockImplementation(mockChildProcessExec); - const result = await docs({ browser: 'echo %u' }); + const result = await docs({ + ioHelper, + browser: 'echo %u', + }); expect(result).toBe(0); }); @@ -19,7 +24,10 @@ describe('`cdk docs`', () => { const mockChildProcessExec: any = (_: string, cb: (err: Error, stdout?: string, stderr?: string) => void) => cb(new Error('TEST')); mocked(child_process.exec).mockImplementation(mockChildProcessExec); - const result = await docs({ browser: 'echo %u' }); + const result = await docs({ + ioHelper, + browser: 'echo %u', + }); expect(result).toBe(0); }); }); diff --git a/packages/aws-cdk/test/commands/cdk-doctor.test.ts b/packages/aws-cdk/test/commands/cdk-doctor.test.ts index 728e65613..d7b505e4f 100644 --- a/packages/aws-cdk/test/commands/cdk-doctor.test.ts +++ b/packages/aws-cdk/test/commands/cdk-doctor.test.ts @@ -1,11 +1,12 @@ import { doctor } from '../../lib/commands/doctor'; +import { TestIoHost } from '../_helpers/io-host'; -// eslint-disable-next-line no-console -console.log = jest.fn(); +const ioHost = new TestIoHost(); +const ioHelper = ioHost.asHelper('doctor'); describe('`cdk doctor`', () => { test('exits with 0 when everything is OK', async () => { - const result = await doctor(); + const result = await doctor({ ioHelper }); expect(result).toBe(0); }); }); diff --git a/packages/aws-cdk/test/commands/context-command.test.ts b/packages/aws-cdk/test/commands/context-command.test.ts index 45e29b6a1..6cab50cb7 100644 --- a/packages/aws-cdk/test/commands/context-command.test.ts +++ b/packages/aws-cdk/test/commands/context-command.test.ts @@ -3,11 +3,15 @@ import { contextHandler } from '../../lib/commands/context'; import { Settings } from '../../lib/api/settings'; import { Context } from '../../lib/api/context'; import { Configuration } from '../../lib/cli/user-configuration'; +import { TestIoHost } from '../_helpers/io-host'; + +const ioHost = new TestIoHost(); +const ioHelper = ioHost.asHelper('context'); describe('context --list', () => { - test('runs', async() => { + test('runs', async () => { // GIVEN - const configuration = new Configuration(); + const configuration = await Configuration.fromArgs(ioHelper); configuration.context.set('foo', 'bar'); expect(configuration.context.all).toEqual({ @@ -16,6 +20,7 @@ describe('context --list', () => { // WHEN await contextHandler({ + ioHelper, context: configuration.context, }); }); @@ -24,7 +29,7 @@ describe('context --list', () => { describe('context --reset', () => { test('can remove a context key', async () => { // GIVEN - const configuration = new Configuration(); + const configuration = await Configuration.fromArgs(ioHelper); configuration.context.set('foo', 'bar'); configuration.context.set('baz', 'quux'); @@ -35,6 +40,7 @@ describe('context --reset', () => { // WHEN await contextHandler({ + ioHelper, context: configuration.context, reset: 'foo', }); @@ -47,7 +53,7 @@ describe('context --reset', () => { test('can remove a context key using number', async () => { // GIVEN - const configuration = new Configuration(); + const configuration = await Configuration.fromArgs(ioHelper); configuration.context.set('foo', 'bar'); configuration.context.set('baz', 'quux'); @@ -58,6 +64,7 @@ describe('context --reset', () => { // WHEN await contextHandler({ + ioHelper, context: configuration.context, reset: '1', }); @@ -70,7 +77,7 @@ describe('context --reset', () => { test('can reset matched pattern', async () => { // GIVEN - const configuration = new Configuration(); + const configuration = await Configuration.fromArgs(ioHelper); configuration.context.set('foo', 'bar'); configuration.context.set('match-a', 'baz'); configuration.context.set('match-b', 'qux'); @@ -83,6 +90,7 @@ describe('context --reset', () => { // WHEN await contextHandler({ + ioHelper, context: configuration.context, reset: 'match-*', }); @@ -95,7 +103,7 @@ describe('context --reset', () => { test('prefers an exact match', async () => { // GIVEN - const configuration = new Configuration(); + const configuration = await Configuration.fromArgs(ioHelper); configuration.context.set('foo', 'bar'); configuration.context.set('fo*', 'baz'); @@ -106,6 +114,7 @@ describe('context --reset', () => { // WHEN await contextHandler({ + ioHelper, context: configuration.context, reset: 'fo*', }); @@ -118,7 +127,7 @@ describe('context --reset', () => { test('doesn\'t throw when at least one match is reset', async () => { // GIVEN - const configuration = new Configuration(); + const configuration = await Configuration.fromArgs(ioHelper); const readOnlySettings = new Settings({ 'foo': 'bar', 'match-a': 'baz', @@ -128,6 +137,7 @@ describe('context --reset', () => { // When await expect(contextHandler({ + ioHelper, context: configuration.context, reset: 'match-*', })); @@ -141,7 +151,7 @@ describe('context --reset', () => { test('throws when key not found', async () => { // GIVEN - const configuration = new Configuration(); + const configuration = await Configuration.fromArgs(ioHelper); configuration.context.set('foo', 'bar'); expect(configuration.context.all).toEqual({ @@ -150,6 +160,7 @@ describe('context --reset', () => { // THEN await expect(contextHandler({ + ioHelper, context: configuration.context, reset: 'baz', })).rejects.toThrow(/No context value matching key/); @@ -157,7 +168,7 @@ describe('context --reset', () => { test('Doesn\'t throw when key not found and --force is set', async () => { // GIVEN - const configuration = new Configuration(); + const configuration = await Configuration.fromArgs(ioHelper); configuration.context.set('foo', 'bar'); expect(configuration.context.all).toEqual({ @@ -166,6 +177,7 @@ describe('context --reset', () => { // THEN await expect(contextHandler({ + ioHelper, context: configuration.context, reset: 'baz', force: true, @@ -174,7 +186,7 @@ describe('context --reset', () => { test('throws when no key of index found', async () => { // GIVEN - const configuration = new Configuration(); + const configuration = await Configuration.fromArgs(ioHelper); configuration.context.set('foo', 'bar'); expect(configuration.context.all).toEqual({ @@ -183,6 +195,7 @@ describe('context --reset', () => { // THEN await expect(contextHandler({ + ioHelper, context: configuration.context, reset: '2', })).rejects.toThrow(/No context key with number/); @@ -190,7 +203,7 @@ describe('context --reset', () => { test('throws when resetting read-only values', async () => { // GIVEN - const configuration = new Configuration(); + const configuration = await Configuration.fromArgs(ioHelper); const readOnlySettings = new Settings({ foo: 'bar', }, true); @@ -202,6 +215,7 @@ describe('context --reset', () => { // THEN await expect(contextHandler({ + ioHelper, context: configuration.context, reset: 'foo', })).rejects.toThrow(/Cannot reset readonly context value with key/); @@ -209,7 +223,7 @@ describe('context --reset', () => { test('throws when no matches could be reset', async () => { // GIVEN - const configuration = new Configuration(); + const configuration = await Configuration.fromArgs(ioHelper); const readOnlySettings = new Settings({ 'foo': 'bar', 'match-a': 'baz', @@ -225,6 +239,7 @@ describe('context --reset', () => { // THEN await expect(contextHandler({ + ioHelper, context: configuration.context, reset: 'match-*', })).rejects.toThrow(/None of the matched context values could be reset/); @@ -234,7 +249,7 @@ describe('context --reset', () => { describe('context --clear', () => { test('can clear all context keys', async () => { // GIVEN - const configuration = new Configuration(); + const configuration = await Configuration.fromArgs(ioHelper); configuration.context.set('foo', 'bar'); configuration.context.set('baz', 'quux'); @@ -245,6 +260,7 @@ describe('context --clear', () => { // WHEN await contextHandler({ + ioHelper, context: configuration.context, clear: true, }); diff --git a/packages/aws-cdk/test/commands/diff.test.ts b/packages/aws-cdk/test/commands/diff.test.ts index b4713c48a..930f54f37 100644 --- a/packages/aws-cdk/test/commands/diff.test.ts +++ b/packages/aws-cdk/test/commands/diff.test.ts @@ -49,7 +49,7 @@ afterEach(() => { describe('fixed template', () => { const templatePath = 'oldTemplate.json'; - beforeEach(() => { + beforeEach(async () => { const oldTemplate = { Resources: { SomeResource: { @@ -61,7 +61,7 @@ describe('fixed template', () => { }, }; - cloudExecutable = new MockCloudExecutable({ + cloudExecutable = await MockCloudExecutable.create({ stacks: [ { stackName: 'A', @@ -122,7 +122,7 @@ describe('import existing resources', () => { any >; - beforeEach(() => { + beforeEach(async () => { // Default implementations cloudFormation = instanceMockFrom(Deployments); cloudFormation.readCurrentTemplateWithNestedStacks.mockImplementation( @@ -144,7 +144,7 @@ describe('import existing resources', () => { }, ); cloudFormation.stackExists = jest.fn().mockReturnValue(Promise.resolve(true)); - cloudExecutable = new MockCloudExecutable({ + cloudExecutable = await MockCloudExecutable.create({ stacks: [ { stackName: 'A', @@ -316,7 +316,7 @@ describe('imports', () => { any >; - beforeEach(() => { + beforeEach(async () => { const outputToJson = { '//': 'This file is generated by cdk migrate. It will be automatically deleted after the first successful deployment of this app to the environment of the original resources.', 'Source': 'localfile', @@ -348,7 +348,7 @@ describe('imports', () => { ], }; }); - cloudExecutable = new MockCloudExecutable({ + cloudExecutable = await MockCloudExecutable.create({ stacks: [ { stackName: 'A', @@ -455,8 +455,8 @@ Resources }); describe('non-nested stacks', () => { - beforeEach(() => { - cloudExecutable = new MockCloudExecutable({ + beforeEach(async () => { + cloudExecutable = await MockCloudExecutable.create({ stacks: [ { stackName: 'A', @@ -541,7 +541,7 @@ describe('non-nested stacks', () => { test('diff number of stack diffs, not resource diffs', async () => { // GIVEN - cloudExecutable = new MockCloudExecutable({ + cloudExecutable = await MockCloudExecutable.create({ stacks: [ { stackName: 'A', @@ -661,10 +661,10 @@ describe('non-nested stacks', () => { }); describe('stack exists checks', () => { - beforeEach(() => { + beforeEach(async () => { jest.resetAllMocks(); - cloudExecutable = new MockCloudExecutable({ + cloudExecutable = await MockCloudExecutable.create({ stacks: [ { stackName: 'A', @@ -788,8 +788,8 @@ describe('stack exists checks', () => { }); describe('nested stacks', () => { - beforeEach(() => { - cloudExecutable = new MockCloudExecutable({ + beforeEach(async () => { + cloudExecutable = await MockCloudExecutable.create({ stacks: [ { stackName: 'Parent', @@ -1256,7 +1256,7 @@ Resources describe('--strict', () => { const templatePath = 'oldTemplate.json'; - beforeEach(() => { + beforeEach(async () => { const oldTemplate = {}; cloudFormation = instanceMockFrom(Deployments); @@ -1267,7 +1267,7 @@ describe('--strict', () => { }); }); - cloudExecutable = new MockCloudExecutable({ + cloudExecutable = await MockCloudExecutable.create({ stacks: [ { stackName: 'A', @@ -1348,7 +1348,7 @@ Resources }); describe('stack display names', () => { - beforeEach(() => { + beforeEach(async () => { cloudFormation = instanceMockFrom(Deployments); cloudFormation.readCurrentTemplateWithNestedStacks.mockImplementation((_stackArtifact: CloudFormationStackArtifact) => { return Promise.resolve({ @@ -1356,7 +1356,7 @@ describe('stack display names', () => { nestedStacks: {}, }); }); - cloudExecutable = new MockCloudExecutable({ + cloudExecutable = await MockCloudExecutable.create({ stacks: [ { stackName: 'MyParent', @@ -1403,7 +1403,7 @@ describe('stack display names', () => { test('diff should fall back to logical ID if display name is not available', async () => { // Create a new cloud executable with stacks that don't have display names - cloudExecutable = new MockCloudExecutable({ + cloudExecutable = await MockCloudExecutable.create({ stacks: [ { stackName: 'NoDisplayNameStack', diff --git a/packages/aws-cdk/test/commands/drift.test.ts b/packages/aws-cdk/test/commands/drift.test.ts index 5c881f9a1..b6ac8b045 100644 --- a/packages/aws-cdk/test/commands/drift.test.ts +++ b/packages/aws-cdk/test/commands/drift.test.ts @@ -22,11 +22,11 @@ Modified Resources }; const stack2Output: FormattedDrift = {}; - beforeEach(() => { + beforeEach(async () => { notifySpy = jest.spyOn(ioHost, 'notify'); notifySpy.mockClear(); - cloudExecutable = new MockCloudExecutable({ + cloudExecutable = await MockCloudExecutable.create({ stacks: [ { stackName: 'Stack1', diff --git a/packages/aws-cdk/test/commands/flags.test.ts b/packages/aws-cdk/test/commands/flags.test.ts new file mode 100644 index 000000000..b4a65a1a2 --- /dev/null +++ b/packages/aws-cdk/test/commands/flags.test.ts @@ -0,0 +1,117 @@ +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; +import type { FeatureFlag } from '@aws-cdk/toolkit-lib'; +import { asIoHelper } from '../../lib/api-private'; +import { CliIoHost } from '../../lib/cli/io-host'; +import { displayFlags } from '../../lib/commands/flags'; + +let oldDir: string; +let tmpDir: string; +let ioHost = CliIoHost.instance(); +let notifySpy: jest.SpyInstance>; +let ioHelper = asIoHelper(ioHost, 'flags'); + +beforeAll(() => { + oldDir = process.cwd(); + tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'aws-cdk-test')); + process.chdir(tmpDir); +}); + +afterAll(() => { + process.chdir(oldDir); + fs.rmSync(tmpDir, { recursive: true, force: true }); +}); + +beforeEach(() => { + notifySpy = jest.spyOn(ioHost, 'notify'); + notifySpy.mockClear(); +}); + +afterEach(() => { + jest.restoreAllMocks(); +}); + +function output() { + return notifySpy.mock.calls.map(x => x[0].message).join('\n').replace(/\x1B\[[0-?]*[ -/]*[@-~]/g, ''); +} + +describe('displayFlags', () => { + test('displays multiple feature flags', async () => { + const flagsData: FeatureFlag[] = + [{ + module: 'aws-cdk-lib', + name: '@aws-cdk/core:enableStackNameDuplicates', + recommendedValue: 'false', + userValue: 'true', + explanation: 'Enable stack name duplicates', + + }, { + module: 'aws-cdk-lib', + name: '@aws-cdk/aws-s3:createDefaultLoggingPolicy', + recommendedValue: 'true', + userValue: 'false', + explanation: 'Create default logging policy for S3 buckets', + }]; + + await displayFlags(flagsData, ioHelper); + + const plainTextOutput = output(); + expect(plainTextOutput).toContain('Feature Flag Name'); + expect(plainTextOutput).toContain('Recommended Value'); + expect(plainTextOutput).toContain('User Value'); + expect(plainTextOutput).toContain('@aws-cdk/core:enableStackNameDuplicates'); + expect(plainTextOutput).toContain('@aws-cdk/aws-s3:createDefaultLoggingPolicy'); + }); + + test('handles null user values correctly', async () => { + const flagsData: FeatureFlag[] = + [{ + module: 'aws-cdk-lib', + name: '@aws-cdk/aws-s3:createDefaultLoggingPolicy', + recommendedValue: 'true', + userValue: undefined, + explanation: 'Create default logging policy for S3 buckets', + }]; + + await displayFlags(flagsData, ioHelper); + + const plainTextOutput = output(); + expect(plainTextOutput).toContain('true'); + expect(plainTextOutput).toContain(''); + }); + + test('handles mixed data types in flag values', async () => { + const flagsData: FeatureFlag[] = + [{ + module: 'aws-cdk-lib', + name: '@aws-cdk/core:stringFlag', + recommendedValue: 'recommended-string', + userValue: 'string-value', + explanation: 'String flag', + + }, { + module: 'aws-cdk-lib', + name: '@aws-cdk/core:numberFlag', + recommendedValue: 456, + userValue: 123, + explanation: 'Number flag', + } + , { + module: 'aws-cdk-lib', + name: '@aws-cdk/core:booleanFlag', + recommendedValue: false, + userValue: true, + explanation: 'Boolean flag', + }]; + + await displayFlags(flagsData, ioHelper); + + const plainTextOutput = output(); expect(plainTextOutput).toContain('string-value'); + expect(plainTextOutput).toContain('recommended-string'); + expect(plainTextOutput).toContain('123'); + expect(plainTextOutput).toContain('456'); + expect(plainTextOutput).toContain('true'); + expect(plainTextOutput).toContain('false'); + }); +}); diff --git a/packages/aws-cdk/test/commands/init.test.ts b/packages/aws-cdk/test/commands/init.test.ts index 1eff6ffe9..5c766cf57 100644 --- a/packages/aws-cdk/test/commands/init.test.ts +++ b/packages/aws-cdk/test/commands/init.test.ts @@ -3,10 +3,15 @@ import * as path from 'path'; import * as cxapi from '@aws-cdk/cx-api'; import * as fs from 'fs-extra'; import { availableInitLanguages, availableInitTemplates, cliInit, currentlyRecommendedAwsCdkLibFlags, expandPlaceholders, printAvailableTemplates } from '../../lib/commands/init'; +import { TestIoHost } from '../_helpers/io-host'; + +const ioHost = new TestIoHost(); +const ioHelper = ioHost.asHelper('init'); describe('constructs version', () => { cliTest('create a TypeScript library project', async (workDir) => { await cliInit({ + ioHelper, type: 'lib', language: 'typescript', workDir, @@ -19,6 +24,7 @@ describe('constructs version', () => { cliTest('can override requested version with environment variable', async (workDir) => { await cliInit({ + ioHelper, type: 'lib', language: 'typescript', workDir, @@ -32,6 +38,7 @@ describe('constructs version', () => { cliTest('asking for a nonexistent template fails', async (workDir) => { await expect(cliInit({ + ioHelper, type: 'banana', language: 'typescript', workDir, @@ -40,6 +47,7 @@ describe('constructs version', () => { cliTest('asking for a template but no language prints and throws', async (workDir) => { await expect(cliInit({ + ioHelper, type: 'app', workDir, })).rejects.toThrow(/No language/); @@ -47,6 +55,7 @@ describe('constructs version', () => { cliTest('create a TypeScript app project', async (workDir) => { await cliInit({ + ioHelper, type: 'app', language: 'typescript', workDir, @@ -59,6 +68,7 @@ describe('constructs version', () => { cliTest('create a JavaScript app project', async (workDir) => { await cliInit({ + ioHelper, type: 'app', language: 'javascript', workDir, @@ -72,6 +82,7 @@ describe('constructs version', () => { cliTest('create a Java app project', async (workDir) => { await cliInit({ + ioHelper, type: 'app', language: 'java', canUseNetwork: false, @@ -94,6 +105,7 @@ describe('constructs version', () => { cliTest('create a .NET app project in csharp', async (workDir) => { await cliInit({ + ioHelper, type: 'app', language: 'csharp', canUseNetwork: false, @@ -116,6 +128,7 @@ describe('constructs version', () => { cliTest('create a .NET app project in fsharp', async (workDir) => { await cliInit({ + ioHelper, type: 'app', language: 'fsharp', canUseNetwork: false, @@ -138,6 +151,7 @@ describe('constructs version', () => { cliTestWithDirSpaces('csharp app with spaces', async (workDir) => { await cliInit({ + ioHelper, type: 'app', language: 'csharp', canUseNetwork: false, @@ -156,6 +170,7 @@ describe('constructs version', () => { cliTestWithDirSpaces('fsharp app with spaces', async (workDir) => { await cliInit({ + ioHelper, type: 'app', language: 'fsharp', canUseNetwork: false, @@ -174,6 +189,7 @@ describe('constructs version', () => { cliTest('create a Python app project', async (workDir) => { await cliInit({ + ioHelper, type: 'app', language: 'python', canUseNetwork: false, @@ -196,6 +212,7 @@ describe('constructs version', () => { cliTest('--generate-only should skip git init', async (workDir) => { await cliInit({ + ioHelper, type: 'app', language: 'javascript', canUseNetwork: false, @@ -213,6 +230,7 @@ describe('constructs version', () => { fs.mkdirSync(path.join(workDir, '.git')); await cliInit({ + ioHelper, type: 'app', language: 'typescript', canUseNetwork: false, @@ -227,6 +245,7 @@ describe('constructs version', () => { cliTest('CLI uses recommended feature flags from data file to initialize context', async (workDir) => { const recommendedFlagsFile = path.join(__dirname, '..', '..', 'lib', 'init-templates', '.recommended-feature-flags.json'); await withReplacedFile(recommendedFlagsFile, JSON.stringify({ banana: 'yellow' }), () => cliInit({ + ioHelper, type: 'app', language: 'typescript', canUseNetwork: false, @@ -241,6 +260,7 @@ describe('constructs version', () => { cliTest('CLI uses init versions file to initialize template', async (workDir) => { const recommendedFlagsFile = path.join(__dirname, '..', '..', 'lib', 'init-templates', '.init-version.json'); await withReplacedFile(recommendedFlagsFile, JSON.stringify({ 'aws-cdk-lib': '100.1.1', 'constructs': '^200.2.2' }), () => cliInit({ + ioHelper, type: 'app', language: 'typescript', canUseNetwork: false, @@ -258,6 +278,7 @@ describe('constructs version', () => { for (const lang of templ.languages) { await withTempDir(async tmpDir => { await cliInit({ + ioHelper, type: templ.name, language: lang, canUseNetwork: false, @@ -301,7 +322,7 @@ test('check available init languages', async () => { }); test('exercise printing available templates', async () => { - await printAvailableTemplates(); + await printAvailableTemplates(ioHelper); }); describe('expandPlaceholders', () => { diff --git a/packages/aws-cdk/test/commands/list-stacks.test.ts b/packages/aws-cdk/test/commands/list-stacks.test.ts index a1643c45f..e653f6bb4 100644 --- a/packages/aws-cdk/test/commands/list-stacks.test.ts +++ b/packages/aws-cdk/test/commands/list-stacks.test.ts @@ -1,6 +1,6 @@ import * as cxschema from '@aws-cdk/cloud-assembly-schema'; import { Bootstrapper } from '../../lib/api/bootstrap'; -import type { Deployments } from '../../lib/api/deployments'; +import { Deployments } from '../../lib/api/deployments'; import { CdkToolkit } from '../../lib/cli/cdk-toolkit'; import { listStacks } from '../../lib/commands/list-stacks'; import { instanceMockFrom, MockCloudExecutable } from '../_helpers'; @@ -13,12 +13,14 @@ describe('list', () => { beforeEach(() => { jest.resetAllMocks(); + cloudFormation = instanceMockFrom(Deployments); + bootstrapper = instanceMockFrom(Bootstrapper); bootstrapper.bootstrapEnvironment.mockResolvedValue({ noOp: false, outputs: {} } as any); }); test('stacks with no dependencies', async () => { - let cloudExecutable = new MockCloudExecutable({ + let cloudExecutable = await MockCloudExecutable.create({ stacks: [ MockStack.MOCK_STACK_A, { @@ -70,7 +72,7 @@ describe('list', () => { }); test('stacks with dependent stacks', async () => { - let cloudExecutable = new MockCloudExecutable({ + let cloudExecutable = await MockCloudExecutable.create({ stacks: [ MockStack.MOCK_STACK_A, { @@ -129,7 +131,7 @@ describe('list', () => { // In the context where we have a display name set to hieraricalId/stackName // we would need to pass in the displayName to list the stacks. test('stacks with dependent stacks and have display name set to hieraricalId/stackName', async () => { - let cloudExecutable = new MockCloudExecutable({ + let cloudExecutable = await MockCloudExecutable.create({ stacks: [ MockStack.MOCK_STACK_A, { @@ -187,7 +189,7 @@ describe('list', () => { }); test('stacks with display names and have nested dependencies', async () => { - let cloudExecutable = new MockCloudExecutable({ + let cloudExecutable = await MockCloudExecutable.create({ stacks: [ MockStack.MOCK_STACK_A, { @@ -275,7 +277,7 @@ describe('list', () => { }); test('stacks with nested dependencies', async () => { - let cloudExecutable = new MockCloudExecutable({ + let cloudExecutable = await MockCloudExecutable.create({ stacks: [ MockStack.MOCK_STACK_A, { @@ -366,7 +368,7 @@ describe('list', () => { // This involves handling the establishment of cross-references between stacks or nested stacks // and generating assets for nested stack templates as necessary. test('stacks with cross stack referencing', async () => { - let cloudExecutable = new MockCloudExecutable({ + let cloudExecutable = await MockCloudExecutable.create({ stacks: [ { stackName: 'Test-Stack-A', @@ -435,7 +437,7 @@ describe('list', () => { }); test('stacks with circular dependencies should error out', async () => { - let cloudExecutable = new MockCloudExecutable({ + let cloudExecutable = await MockCloudExecutable.create({ stacks: [ { stackName: 'Test-Stack-A', diff --git a/packages/aws-cdk/test/commands/migrate.test.ts b/packages/aws-cdk/test/commands/migrate.test.ts index bf2c85fb0..1016d831e 100644 --- a/packages/aws-cdk/test/commands/migrate.test.ts +++ b/packages/aws-cdk/test/commands/migrate.test.ts @@ -29,12 +29,15 @@ import { TemplateSourceOptions, FromScan, } from '../../lib/commands/migrate'; +import { TestIoHost } from '../_helpers/io-host'; import { MockSdkProvider, mockCloudFormationClient, restoreSdkMocksToDefault } from '../_helpers/mock-sdk'; jest.setTimeout(120_000); const exec = promisify(_exec); +const ioHelper = new TestIoHost().asHelper('migrate'); + describe('Migrate Function Tests', () => { let sdkProvider: MockSdkProvider; @@ -205,7 +208,7 @@ describe('Migrate Function Tests', () => { cliTest('generateCdkApp generates the expected cdk app when called for typescript', async (workDir) => { const stack = generateStack(validTemplate, 'GoodTypeScript', 'typescript'); - await generateCdkApp('GoodTypeScript', stack, 'typescript', workDir); + await generateCdkApp(ioHelper, 'GoodTypeScript', stack, 'typescript', workDir); // Packages exist in the correct spot expect(fs.pathExistsSync(path.join(workDir, 'GoodTypeScript', 'package.json'))).toBeTruthy(); @@ -234,7 +237,7 @@ describe('Migrate Function Tests', () => { cliTest('generateCdkApp adds cdk-migrate key in context', async (workDir) => { const stack = generateStack(validTemplate, 'GoodTypeScript', 'typescript'); - await generateCdkApp('GoodTypeScript', stack, 'typescript', workDir); + await generateCdkApp(ioHelper, 'GoodTypeScript', stack, 'typescript', workDir); // cdk.json exist in the correct spot expect(fs.pathExistsSync(path.join(workDir, 'GoodTypeScript', 'cdk.json'))).toBeTruthy(); @@ -246,7 +249,7 @@ describe('Migrate Function Tests', () => { cliTest('generateCdkApp generates the expected cdk app when called for python', async (workDir) => { const stack = generateStack(validTemplate, 'GoodPython', 'python'); - await generateCdkApp('GoodPython', stack, 'python', workDir); + await generateCdkApp(ioHelper, 'GoodPython', stack, 'python', workDir); // Packages exist in the correct spot expect(fs.pathExistsSync(path.join(workDir, 'GoodPython', 'requirements.txt'))).toBeTruthy(); @@ -273,7 +276,7 @@ describe('Migrate Function Tests', () => { cliTest('generateCdkApp generates the expected cdk app when called for java', async (workDir) => { const stack = generateStack(validTemplate, 'GoodJava', 'java'); - await generateCdkApp('GoodJava', stack, 'java', workDir); + await generateCdkApp(ioHelper, 'GoodJava', stack, 'java', workDir); // Packages exist in the correct spot expect(fs.pathExistsSync(path.join(workDir, 'GoodJava', 'pom.xml'))).toBeTruthy(); @@ -305,7 +308,7 @@ describe('Migrate Function Tests', () => { cliTest('generateCdkApp generates the expected cdk app when called for csharp', async (workDir) => { const stack = generateStack(validTemplate, 'GoodCSharp', 'csharp'); - await generateCdkApp('GoodCSharp', stack, 'csharp', workDir); + await generateCdkApp(ioHelper, 'GoodCSharp', stack, 'csharp', workDir); // Packages exist in the correct spot expect(fs.pathExistsSync(path.join(workDir, 'GoodCSharp', 'src', 'GoodCSharp.sln'))).toBeTruthy(); @@ -333,7 +336,7 @@ describe('Migrate Function Tests', () => { cliTest('generatedCdkApp generates the expected cdk app when called for go', async (workDir) => { const stack = generateStack(validTemplate, 'GoodGo', 'go'); - await generateCdkApp('GoodGo', stack, 'go', workDir); + await generateCdkApp(ioHelper, 'GoodGo', stack, 'go', workDir); expect(fs.pathExists(path.join(workDir, 's3.go'))).toBeTruthy(); const app = fs.readFileSync(path.join(workDir, 'GoodGo', 'good_go.go'), 'utf8').split('\n'); @@ -351,7 +354,7 @@ describe('Migrate Function Tests', () => { cliTest('generatedCdkApp generates a zip file when --compress is used', async (workDir) => { const stack = generateStack(validTemplate, 'GoodTypeScript', 'typescript'); - await generateCdkApp('GoodTypeScript', stack, 'typescript', workDir, true); + await generateCdkApp(ioHelper, 'GoodTypeScript', stack, 'typescript', workDir, true); // Packages not in outDir expect(fs.pathExistsSync(path.join(workDir, 'GoodTypeScript', 'package.json'))).toBeFalsy(); @@ -487,6 +490,7 @@ describe('generateTemplate', () => { test('generateTemplate successfully generates template with a new scan', async () => { const opts: GenerateTemplateOptions = { + ioHelper, stackName: stackName, filters: [], fromScan: FromScan.NEW, @@ -511,6 +515,7 @@ describe('generateTemplate', () => { }); const opts = { + ioHelper, stackName: stackName, filters: [], newScan: true, @@ -528,6 +533,7 @@ describe('generateTemplate', () => { }); const opts: GenerateTemplateOptions = { + ioHelper, stackName: stackName, filters: [], fromScan: FromScan.MOST_RECENT, @@ -541,6 +547,7 @@ describe('generateTemplate', () => { test('generateTemplate throws an error when an invalid key is passed in the filters', async () => { const opts: GenerateTemplateOptions = { + ioHelper, stackName: stackName, filters: ['invalid-key=invalid-value'], fromScan: FromScan.MOST_RECENT, @@ -560,6 +567,7 @@ describe('generateTemplate', () => { }); const opts: GenerateTemplateOptions = { + ioHelper, stackName: stackName, sdkProvider: sdkProvider, environment: environment, @@ -571,6 +579,7 @@ describe('generateTemplate', () => { test('generateTemplate successfully generates templates with valid filter options', async () => { const opts: GenerateTemplateOptions = { + ioHelper, stackName: stackName, filters: ['type=AWS::S3::Bucket,identifier={"my-key":"my-bucket"}', 'type=AWS::EC2::Instance'], sdkProvider: sdkProvider, diff --git a/packages/aws-cdk/test/commands/telemetry.test.ts b/packages/aws-cdk/test/commands/telemetry.test.ts index 722f4f63d..6281c830d 100644 --- a/packages/aws-cdk/test/commands/telemetry.test.ts +++ b/packages/aws-cdk/test/commands/telemetry.test.ts @@ -1,18 +1,19 @@ import { CdkToolkit } from '../../lib/cli/cdk-toolkit'; +import { CliIoHost } from '../../lib/cli/io-host'; import { Configuration } from '../../lib/cli/user-configuration'; -import { info } from '../../lib/logging'; -jest.mock('../../lib/logging', () => ({ - info: jest.fn(), -})); +const ioHost = CliIoHost.instance({}, true); +const ioHelper = ioHost.asIoHelper(); +const notifySpy = jest.spyOn(ioHost, 'notify'); describe('telemetry command', () => { let configuration: Configuration; let toolkit: CdkToolkit; - beforeEach(() => { - configuration = new Configuration(); + beforeEach(async () => { + configuration = await Configuration.fromArgs(ioHelper); toolkit = new CdkToolkit({ + ioHost, configuration, sdkProvider: {} as any, cloudExecutable: {} as any, @@ -27,7 +28,7 @@ describe('telemetry command', () => { // THEN expect(configuration.context.get('cli-telemetry')).toBe(true); - expect(info).toHaveBeenCalledWith('Telemetry enabled'); + expect(notifySpy).toHaveBeenCalledWith(expect.objectContaining({ level: 'info', message: 'Telemetry enabled' })); }); test('disable telemetry saves setting and displays message', async () => { @@ -36,6 +37,6 @@ describe('telemetry command', () => { // THEN expect(configuration.context.get('cli-telemetry')).toBe(false); - expect(info).toHaveBeenCalledWith('Telemetry disabled'); + expect(notifySpy).toHaveBeenCalledWith(expect.objectContaining({ level: 'info', message: 'Telemetry disabled' })); }); }); diff --git a/packages/aws-cdk/test/cxapp/cloud-assembly.test.ts b/packages/aws-cdk/test/cxapp/cloud-assembly.test.ts index 3aa912c54..60cb8da5f 100644 --- a/packages/aws-cdk/test/cxapp/cloud-assembly.test.ts +++ b/packages/aws-cdk/test/cxapp/cloud-assembly.test.ts @@ -249,7 +249,7 @@ describe('StackCollection', () => { }); async function testCloudAssembly({ env }: { env?: string; versionReporting?: boolean } = {}) { - const cloudExec = new MockCloudExecutable({ + const cloudExec = await MockCloudExecutable.create({ stacks: [{ stackName: 'withouterrors', displayName: 'withouterrorsNODEPATH', @@ -288,7 +288,7 @@ async function testCloudAssembly({ env }: { env?: string; versionReporting?: boo } async function testCloudAssemblyNoStacks() { - const cloudExec = new MockCloudExecutable({ + const cloudExec = await MockCloudExecutable.create({ stacks: [], }); @@ -296,7 +296,7 @@ async function testCloudAssemblyNoStacks() { } async function testNestedCloudAssembly({ env }: { env?: string; versionReporting?: boolean } = {}) { - const cloudExec = new MockCloudExecutable({ + const cloudExec = await MockCloudExecutable.create({ stacks: [{ stackName: 'withouterrors', env, diff --git a/packages/aws-cdk/test/cxapp/cloud-executable.test.ts b/packages/aws-cdk/test/cxapp/cloud-executable.test.ts index ea3171546..ff1323065 100644 --- a/packages/aws-cdk/test/cxapp/cloud-executable.test.ts +++ b/packages/aws-cdk/test/cxapp/cloud-executable.test.ts @@ -26,7 +26,7 @@ test('stop executing if context providers are not making progress', async () => }, }); - const cloudExecutable = new MockCloudExecutable({ + const cloudExecutable = await MockCloudExecutable.create({ stacks: [{ stackName: 'thestack', template: { resource: 'noerrorresource' }, @@ -46,7 +46,7 @@ test('stop executing if context providers are not making progress', async () => test('fails if lookups are disabled and missing context is synthesized', async () => { // GIVEN - const cloudExecutable = new MockCloudExecutable({ + const cloudExecutable = await MockCloudExecutable.create({ stacks: [{ stackName: 'thestack', template: { resource: 'noerrorresource' }, @@ -66,7 +66,7 @@ async function testCloudExecutable( { env, versionReporting = true, schemaVersion }: { env?: string; versionReporting?: boolean; schemaVersion?: string } = {}, ) { - const cloudExec = new MockCloudExecutable({ + const cloudExec = await MockCloudExecutable.create({ stacks: [{ stackName: 'withouterrors', env, diff --git a/packages/aws-cdk/test/cxapp/exec.test.ts b/packages/aws-cdk/test/cxapp/exec.test.ts index 527833420..0d9b6619f 100644 --- a/packages/aws-cdk/test/cxapp/exec.test.ts +++ b/packages/aws-cdk/test/cxapp/exec.test.ts @@ -20,12 +20,12 @@ let config: Configuration; const ioHost = new TestIoHost(); const ioHelper = ioHost.asHelper('synth'); -beforeEach(() => { +beforeEach(async () => { ioHost.notifySpy.mockClear(); ioHost.requestSpy.mockClear(); sdkProvider = new MockSdkProvider(); - config = new Configuration(); + config = await Configuration.fromArgs(ioHelper); config.settings.set(['output'], 'cdk.out'); diff --git a/packages/aws-cdk/test/logging.test.ts b/packages/aws-cdk/test/logging.test.ts deleted file mode 100644 index 5803bcbf1..000000000 --- a/packages/aws-cdk/test/logging.test.ts +++ /dev/null @@ -1,203 +0,0 @@ -import { CliIoHost } from '../lib/cli/io-host'; -import { result, success, highlight, error, warning, info, debug } from '../lib/logging'; - -describe('logging', () => { - const ioHost = CliIoHost.instance({}, true); - let mockStdout: jest.Mock; - let mockStderr: jest.Mock; - - const stripAnsi = (str: string): string => { - const ansiRegex = /\u001b\[[0-9;]*[a-zA-Z]/g; - return str.replace(ansiRegex, ''); - }; - - beforeEach(() => { - ioHost.logLevel = 'info'; - ioHost.isCI = false; - - mockStdout = jest.fn(); - mockStderr = jest.fn(); - - jest.spyOn(process.stdout, 'write').mockImplementation((chunk: any) => { - mockStdout(stripAnsi(chunk.toString())); - return true; - }); - - jest.spyOn(process.stderr, 'write').mockImplementation((chunk: any) => { - mockStderr(stripAnsi(chunk.toString())); - return true; - }); - }); - - afterEach(() => { - jest.restoreAllMocks(); - }); - - describe('stream selection', () => { - test('result() always writes to stdout with both styles', () => { - // String style - result('test message'); - expect(mockStdout).toHaveBeenCalledWith('test message\n'); - - expect(mockStderr).not.toHaveBeenCalled(); - }); - - test('error() always writes to stderr with both styles', () => { - // String style - error('test error'); - expect(mockStderr).toHaveBeenCalledWith('test error\n'); - - expect(mockStdout).not.toHaveBeenCalled(); - }); - - test('info() writes to stderr by default with both styles', () => { - // String style - info('test print'); - expect(mockStderr).toHaveBeenCalledWith('test print\n'); - - expect(mockStdout).not.toHaveBeenCalled(); - }); - - test('info() writes to stdout in CI mode with both styles', () => { - ioHost.isCI = true; - // String style - info('test print'); - expect(mockStdout).toHaveBeenCalledWith('test print\n'); - - expect(mockStderr).not.toHaveBeenCalled(); - }); - }); - - describe('log levels', () => { - test('respects log level settings with both styles', () => { - ioHost.logLevel = 'error'; - - // String style - error('error message'); - warning('warning message'); - info('print message'); - - expect(mockStderr).toHaveBeenCalledWith('error message\n'); - expect(mockStderr).not.toHaveBeenCalledWith('warning message\n'); - expect(mockStderr).not.toHaveBeenCalledWith('print message\n'); - }); - - test('debug messages only show at debug level with both styles', () => { - ioHost.logLevel = 'info'; - debug('debug message'); - expect(mockStderr).not.toHaveBeenCalled(); - - ioHost.logLevel = 'debug'; - debug('debug message'); - expect(mockStderr).toHaveBeenCalledWith( - expect.stringMatching(/^\[\d{2}:\d{2}:\d{2}\] debug message\n$/), - ); - }); - }); - - describe('formatted messages', () => { - test('handles format strings correctly with both styles', () => { - // String style - info('Hello %s, you have %d messages', 'User', 5); - expect(mockStderr).toHaveBeenCalledWith('Hello User, you have 5 messages\n'); - }); - - test('handles objects in format strings with both styles', () => { - const obj = { name: 'test' }; - // String style - info('Object: %j', obj); - expect(mockStderr).toHaveBeenCalledWith('Object: {"name":"test"}\n'); - }); - - test('handles multiple style changes in single call', () => { - const obj = { id: 123 }; - success('Processing %s: %j at %d%%', 'task', obj, 50); - expect(mockStderr).toHaveBeenCalledWith( - 'Processing task: {"id":123} at 50%\n', - ); - }); - }); - - describe('styled output', () => { - test('success() adds green color to output with both styles', () => { - // String style - success('operation completed'); - expect(mockStderr).toHaveBeenCalledWith('operation completed\n'); - }); - - test('highlight() adds bold formatting to output with both styles', () => { - // String style - highlight('important message'); - expect(mockStderr).toHaveBeenCalledWith('important message\n'); - }); - - test('success handles format strings with styling', () => { - success('completed task %d of %d', 1, 3); - expect(mockStderr).toHaveBeenCalledWith('completed task 1 of 3\n'); - - // Remove the code from the test since it's an implementation detail - success('completed task %d of %d', 2, 3); - expect(mockStderr).toHaveBeenCalledWith('completed task 2 of 3\n'); - }); - - test('highlight handles complex objects with styling', () => { - const complexObj = { status: 'active', count: 42 }; - highlight('Status: %j', complexObj); - expect(mockStderr).toHaveBeenCalledWith('Status: {"status":"active","count":42}\n'); - }); - }); - - describe('edge cases', () => { - test('handles null and undefined arguments with both styles', () => { - // String style - info('Values: %s, %s', null, undefined); - expect(mockStderr).toHaveBeenCalledWith('Values: null, undefined\n'); - }); - - test('handles circular references in objects with both styles', () => { - const obj: any = { name: 'test' }; - obj.self = obj; - - // String style - info('Object: %j', obj); - expect(mockStderr).toHaveBeenCalledWith(expect.stringContaining('[Circular')); - }); - }); - - describe('message codes', () => { - test('validates message codes correctly', () => { - // Valid codes - expect(() => error({ message: 'test', code: 'CDK_TOOLKIT_E0001' })).not.toThrow(); - expect(() => warning({ message: 'test', code: 'CDK_ASSETS_W4999' })).not.toThrow(); - expect(() => info({ message: 'test', code: 'CDK_SDK_I0000' })).not.toThrow(); - }); - - test('uses default codes when none provided', () => { - error('test error'); - expect(mockStderr).toHaveBeenCalledWith(expect.stringContaining('test error')); - // Would need to modify the code to expose the actual message code for verification - }); - }); - - describe('CI mode behavior', () => { - test('correctly switches between stdout and stderr based on CI mode', () => { - ioHost.isCI = true; - warning('warning in CI'); - success('success in CI'); - error('error in CI'); - - expect(mockStdout).toHaveBeenCalledWith('warning in CI\n'); - expect(mockStdout).toHaveBeenCalledWith('success in CI\n'); - expect(mockStderr).toHaveBeenCalledWith('error in CI\n'); - - ioHost.isCI = false; - warning('warning not in CI'); - success('success not in CI'); - error('error not in CI'); - - expect(mockStderr).toHaveBeenCalledWith('warning not in CI\n'); - expect(mockStderr).toHaveBeenCalledWith('success not in CI\n'); - expect(mockStderr).toHaveBeenCalledWith('error not in CI\n'); - }); - }); -}); diff --git a/packages/cdk-assets/.projen/deps.json b/packages/cdk-assets/.projen/deps.json index d1bfba957..6c080efdf 100644 --- a/packages/cdk-assets/.projen/deps.json +++ b/packages/cdk-assets/.projen/deps.json @@ -111,7 +111,7 @@ }, { "name": "typescript", - "version": "5.6", + "version": "5.8", "type": "build" }, { diff --git a/packages/cdk-assets/.projen/tasks.json b/packages/cdk-assets/.projen/tasks.json index 8872722c1..51ee57414 100644 --- a/packages/cdk-assets/.projen/tasks.json +++ b/packages/cdk-assets/.projen/tasks.json @@ -33,7 +33,7 @@ "VERSIONRCOPTIONS": "{\"path\":\".\"}", "BUMP_PACKAGE": "commit-and-tag-version@^12", "NEXT_VERSION_COMMAND": "tsx ../../projenrc/next-version.ts maybeRc", - "RELEASABLE_COMMITS": "git log --no-merges --oneline $LATEST_TAG..HEAD -E --grep \"^(feat|fix){1}(\\([^()[:space:]]+\\))?(!)?:[[:blank:]]+.+\" -- .", + "RELEASABLE_COMMITS": "git log --no-merges --oneline $LATEST_TAG..HEAD -E --grep \"^(feat|fix){1}(\\([^()[:space:]]+\\))?(!)?:[[:blank:]]+.+\" -- . ../@aws-cdk/cdk-assets-lib ../@aws-cdk/cloud-assembly-schema", "MAJOR": "4" }, "steps": [ @@ -198,7 +198,7 @@ "VERSIONRCOPTIONS": "{\"path\":\".\"}", "BUMP_PACKAGE": "commit-and-tag-version@^12", "NEXT_VERSION_COMMAND": "tsx ../../projenrc/next-version.ts maybeRc", - "RELEASABLE_COMMITS": "git log --no-merges --oneline $LATEST_TAG..HEAD -E --grep \"^(feat|fix){1}(\\([^()[:space:]]+\\))?(!)?:[[:blank:]]+.+\" -- ." + "RELEASABLE_COMMITS": "git log --no-merges --oneline $LATEST_TAG..HEAD -E --grep \"^(feat|fix){1}(\\([^()[:space:]]+\\))?(!)?:[[:blank:]]+.+\" -- . ../@aws-cdk/cdk-assets-lib ../@aws-cdk/cloud-assembly-schema" }, "steps": [ { diff --git a/packages/cdk-assets/THIRD_PARTY_LICENSES b/packages/cdk-assets/THIRD_PARTY_LICENSES index 341dad711..e065cec53 100644 --- a/packages/cdk-assets/THIRD_PARTY_LICENSES +++ b/packages/cdk-assets/THIRD_PARTY_LICENSES @@ -618,7 +618,7 @@ The cdk-assets package includes the following third-party software/licensing: ---------------- -** @aws-sdk/client-cognito-identity@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-cognito-identity/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-cognito-identity@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-cognito-identity/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -824,7 +824,7 @@ The cdk-assets package includes the following third-party software/licensing: ---------------- -** @aws-sdk/client-ecr@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-ecr/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-ecr@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-ecr/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -1030,7 +1030,7 @@ The cdk-assets package includes the following third-party software/licensing: ---------------- -** @aws-sdk/client-s3@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-s3/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-s3@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-s3/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -1236,7 +1236,7 @@ The cdk-assets package includes the following third-party software/licensing: ---------------- -** @aws-sdk/client-secrets-manager@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-secrets-manager/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-secrets-manager@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-secrets-manager/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -1442,7 +1442,7 @@ The cdk-assets package includes the following third-party software/licensing: ---------------- -** @aws-sdk/client-sso@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-sso/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-sso@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-sso/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -1648,7 +1648,7 @@ The cdk-assets package includes the following third-party software/licensing: ---------------- -** @aws-sdk/client-sts@3.839.0 - https://www.npmjs.com/package/@aws-sdk/client-sts/v/3.839.0 | Apache-2.0 +** @aws-sdk/client-sts@3.846.0 - https://www.npmjs.com/package/@aws-sdk/client-sts/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -1854,11 +1854,11 @@ The cdk-assets package includes the following third-party software/licensing: ---------------- -** @aws-sdk/core@3.839.0 - https://www.npmjs.com/package/@aws-sdk/core/v/3.839.0 | Apache-2.0 +** @aws-sdk/core@3.846.0 - https://www.npmjs.com/package/@aws-sdk/core/v/3.846.0 | Apache-2.0 ---------------- -** @aws-sdk/credential-provider-cognito-identity@3.839.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-cognito-identity/v/3.839.0 | Apache-2.0 +** @aws-sdk/credential-provider-cognito-identity@3.846.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-cognito-identity/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -2064,7 +2064,7 @@ The cdk-assets package includes the following third-party software/licensing: ---------------- -** @aws-sdk/credential-provider-env@3.839.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-env/v/3.839.0 | Apache-2.0 +** @aws-sdk/credential-provider-env@3.846.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-env/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -2269,11 +2269,11 @@ Apache License ---------------- -** @aws-sdk/credential-provider-http@3.839.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-http/v/3.839.0 | Apache-2.0 +** @aws-sdk/credential-provider-http@3.846.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-http/v/3.846.0 | Apache-2.0 ---------------- -** @aws-sdk/credential-provider-ini@3.839.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-ini/v/3.839.0 | Apache-2.0 +** @aws-sdk/credential-provider-ini@3.846.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-ini/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -2478,7 +2478,7 @@ Apache License ---------------- -** @aws-sdk/credential-provider-node@3.839.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-node/v/3.839.0 | Apache-2.0 +** @aws-sdk/credential-provider-node@3.846.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-node/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -2683,7 +2683,7 @@ Apache License ---------------- -** @aws-sdk/credential-provider-process@3.839.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-process/v/3.839.0 | Apache-2.0 +** @aws-sdk/credential-provider-process@3.846.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-process/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -2888,7 +2888,7 @@ Apache License ---------------- -** @aws-sdk/credential-provider-sso@3.839.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-sso/v/3.839.0 | Apache-2.0 +** @aws-sdk/credential-provider-sso@3.846.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-sso/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -3093,7 +3093,7 @@ Apache License ---------------- -** @aws-sdk/credential-provider-web-identity@3.839.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-web-identity/v/3.839.0 | Apache-2.0 +** @aws-sdk/credential-provider-web-identity@3.846.0 - https://www.npmjs.com/package/@aws-sdk/credential-provider-web-identity/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -3298,7 +3298,7 @@ Apache License ---------------- -** @aws-sdk/credential-providers@3.839.0 - https://www.npmjs.com/package/@aws-sdk/credential-providers/v/3.839.0 | Apache-2.0 +** @aws-sdk/credential-providers@3.846.0 - https://www.npmjs.com/package/@aws-sdk/credential-providers/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -3503,7 +3503,7 @@ Apache License ---------------- -** @aws-sdk/lib-storage@3.839.0 - https://www.npmjs.com/package/@aws-sdk/lib-storage/v/3.839.0 | Apache-2.0 +** @aws-sdk/lib-storage@3.846.0 - https://www.npmjs.com/package/@aws-sdk/lib-storage/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -3708,7 +3708,7 @@ Apache License ---------------- -** @aws-sdk/middleware-bucket-endpoint@3.830.0 - https://www.npmjs.com/package/@aws-sdk/middleware-bucket-endpoint/v/3.830.0 | Apache-2.0 +** @aws-sdk/middleware-bucket-endpoint@3.840.0 - https://www.npmjs.com/package/@aws-sdk/middleware-bucket-endpoint/v/3.840.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -3914,7 +3914,7 @@ Apache License ---------------- -** @aws-sdk/middleware-expect-continue@3.821.0 - https://www.npmjs.com/package/@aws-sdk/middleware-expect-continue/v/3.821.0 | Apache-2.0 +** @aws-sdk/middleware-expect-continue@3.840.0 - https://www.npmjs.com/package/@aws-sdk/middleware-expect-continue/v/3.840.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -4120,7 +4120,7 @@ Apache License ---------------- -** @aws-sdk/middleware-flexible-checksums@3.839.0 - https://www.npmjs.com/package/@aws-sdk/middleware-flexible-checksums/v/3.839.0 | Apache-2.0 +** @aws-sdk/middleware-flexible-checksums@3.846.0 - https://www.npmjs.com/package/@aws-sdk/middleware-flexible-checksums/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -4326,7 +4326,7 @@ Apache License ---------------- -** @aws-sdk/middleware-host-header@3.821.0 - https://www.npmjs.com/package/@aws-sdk/middleware-host-header/v/3.821.0 | Apache-2.0 +** @aws-sdk/middleware-host-header@3.840.0 - https://www.npmjs.com/package/@aws-sdk/middleware-host-header/v/3.840.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -4532,7 +4532,7 @@ Apache License ---------------- -** @aws-sdk/middleware-location-constraint@3.821.0 - https://www.npmjs.com/package/@aws-sdk/middleware-location-constraint/v/3.821.0 | Apache-2.0 +** @aws-sdk/middleware-location-constraint@3.840.0 - https://www.npmjs.com/package/@aws-sdk/middleware-location-constraint/v/3.840.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -4738,7 +4738,7 @@ Apache License ---------------- -** @aws-sdk/middleware-logger@3.821.0 - https://www.npmjs.com/package/@aws-sdk/middleware-logger/v/3.821.0 | Apache-2.0 +** @aws-sdk/middleware-logger@3.840.0 - https://www.npmjs.com/package/@aws-sdk/middleware-logger/v/3.840.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -4943,7 +4943,7 @@ Apache License ---------------- -** @aws-sdk/middleware-recursion-detection@3.821.0 - https://www.npmjs.com/package/@aws-sdk/middleware-recursion-detection/v/3.821.0 | Apache-2.0 +** @aws-sdk/middleware-recursion-detection@3.840.0 - https://www.npmjs.com/package/@aws-sdk/middleware-recursion-detection/v/3.840.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -5149,7 +5149,7 @@ Apache License ---------------- -** @aws-sdk/middleware-sdk-s3@3.839.0 - https://www.npmjs.com/package/@aws-sdk/middleware-sdk-s3/v/3.839.0 | Apache-2.0 +** @aws-sdk/middleware-sdk-s3@3.846.0 - https://www.npmjs.com/package/@aws-sdk/middleware-sdk-s3/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -5355,7 +5355,7 @@ Apache License ---------------- -** @aws-sdk/middleware-ssec@3.821.0 - https://www.npmjs.com/package/@aws-sdk/middleware-ssec/v/3.821.0 | Apache-2.0 +** @aws-sdk/middleware-ssec@3.840.0 - https://www.npmjs.com/package/@aws-sdk/middleware-ssec/v/3.840.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -5561,7 +5561,7 @@ Apache License ---------------- -** @aws-sdk/middleware-user-agent@3.839.0 - https://www.npmjs.com/package/@aws-sdk/middleware-user-agent/v/3.839.0 | Apache-2.0 +** @aws-sdk/middleware-user-agent@3.846.0 - https://www.npmjs.com/package/@aws-sdk/middleware-user-agent/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -5767,11 +5767,11 @@ Apache License ---------------- -** @aws-sdk/nested-clients@3.839.0 - https://www.npmjs.com/package/@aws-sdk/nested-clients/v/3.839.0 | Apache-2.0 +** @aws-sdk/nested-clients@3.846.0 - https://www.npmjs.com/package/@aws-sdk/nested-clients/v/3.846.0 | Apache-2.0 ---------------- -** @aws-sdk/region-config-resolver@3.821.0 - https://www.npmjs.com/package/@aws-sdk/region-config-resolver/v/3.821.0 | Apache-2.0 +** @aws-sdk/region-config-resolver@3.840.0 - https://www.npmjs.com/package/@aws-sdk/region-config-resolver/v/3.840.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -5976,7 +5976,7 @@ Apache License ---------------- -** @aws-sdk/signature-v4-multi-region@3.839.0 - https://www.npmjs.com/package/@aws-sdk/signature-v4-multi-region/v/3.839.0 | Apache-2.0 +** @aws-sdk/signature-v4-multi-region@3.846.0 - https://www.npmjs.com/package/@aws-sdk/signature-v4-multi-region/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -6182,7 +6182,7 @@ Apache License ---------------- -** @aws-sdk/token-providers@3.839.0 - https://www.npmjs.com/package/@aws-sdk/token-providers/v/3.839.0 | Apache-2.0 +** @aws-sdk/token-providers@3.846.0 - https://www.npmjs.com/package/@aws-sdk/token-providers/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -6592,7 +6592,7 @@ Apache License ---------------- -** @aws-sdk/util-endpoints@3.828.0 - https://www.npmjs.com/package/@aws-sdk/util-endpoints/v/3.828.0 | Apache-2.0 +** @aws-sdk/util-endpoints@3.845.0 - https://www.npmjs.com/package/@aws-sdk/util-endpoints/v/3.845.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -6797,7 +6797,7 @@ Apache License ---------------- -** @aws-sdk/util-user-agent-node@3.839.0 - https://www.npmjs.com/package/@aws-sdk/util-user-agent-node/v/3.839.0 | Apache-2.0 +** @aws-sdk/util-user-agent-node@3.846.0 - https://www.npmjs.com/package/@aws-sdk/util-user-agent-node/v/3.846.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -7618,7 +7618,7 @@ Apache License ---------------- -** @smithy/core@3.6.0 - https://www.npmjs.com/package/@smithy/core/v/3.6.0 | Apache-2.0 +** @smithy/core@3.7.0 - https://www.npmjs.com/package/@smithy/core/v/3.7.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -8853,7 +8853,7 @@ Apache License ---------------- -** @smithy/fetch-http-handler@5.0.4 - https://www.npmjs.com/package/@smithy/fetch-http-handler/v/5.0.4 | Apache-2.0 +** @smithy/fetch-http-handler@5.1.0 - https://www.npmjs.com/package/@smithy/fetch-http-handler/v/5.1.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -10083,7 +10083,7 @@ Apache License ---------------- -** @smithy/middleware-endpoint@4.1.13 - https://www.npmjs.com/package/@smithy/middleware-endpoint/v/4.1.13 | Apache-2.0 +** @smithy/middleware-endpoint@4.1.15 - https://www.npmjs.com/package/@smithy/middleware-endpoint/v/4.1.15 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -10288,7 +10288,7 @@ Apache License ---------------- -** @smithy/middleware-retry@4.1.14 - https://www.npmjs.com/package/@smithy/middleware-retry/v/4.1.14 | Apache-2.0 +** @smithy/middleware-retry@4.1.16 - https://www.npmjs.com/package/@smithy/middleware-retry/v/4.1.16 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -11110,7 +11110,7 @@ Apache License ---------------- -** @smithy/node-http-handler@4.0.6 - https://www.npmjs.com/package/@smithy/node-http-handler/v/4.0.6 | Apache-2.0 +** @smithy/node-http-handler@4.1.0 - https://www.npmjs.com/package/@smithy/node-http-handler/v/4.1.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -12754,7 +12754,7 @@ Apache License ---------------- -** @smithy/smithy-client@4.4.5 - https://www.npmjs.com/package/@smithy/smithy-client/v/4.4.5 | Apache-2.0 +** @smithy/smithy-client@4.4.7 - https://www.npmjs.com/package/@smithy/smithy-client/v/4.4.7 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -14602,7 +14602,7 @@ Apache License ---------------- -** @smithy/util-defaults-mode-node@4.0.21 - https://www.npmjs.com/package/@smithy/util-defaults-mode-node/v/4.0.21 | Apache-2.0 +** @smithy/util-defaults-mode-node@4.0.23 - https://www.npmjs.com/package/@smithy/util-defaults-mode-node/v/4.0.23 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -15628,7 +15628,7 @@ Apache License ---------------- -** @smithy/util-stream@4.2.2 - https://www.npmjs.com/package/@smithy/util-stream/v/4.2.2 | Apache-2.0 +** @smithy/util-stream@4.2.3 - https://www.npmjs.com/package/@smithy/util-stream/v/4.2.3 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -17474,7 +17474,7 @@ THE SOFTWARE. ---------------- -** fast-xml-parser@4.4.1 - https://www.npmjs.com/package/fast-xml-parser/v/4.4.1 | MIT +** fast-xml-parser@5.2.5 - https://www.npmjs.com/package/fast-xml-parser/v/5.2.5 | MIT MIT License Copyright (c) 2017 Amit Kumar Gupta @@ -18354,7 +18354,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI ---------------- -** strnum@1.1.2 - https://www.npmjs.com/package/strnum/v/1.1.2 | MIT +** strnum@2.1.1 - https://www.npmjs.com/package/strnum/v/2.1.1 | MIT MIT License Copyright (c) 2021 Natural Intelligence diff --git a/packages/cdk-assets/bin/docker-credential-cdk-assets.ts b/packages/cdk-assets/bin/docker-credential-cdk-assets.ts index a53aa8002..caf9e6c0d 100644 --- a/packages/cdk-assets/bin/docker-credential-cdk-assets.ts +++ b/packages/cdk-assets/bin/docker-credential-cdk-assets.ts @@ -15,13 +15,14 @@ import * as fs from 'fs'; import { DefaultAwsClient } from '@aws-cdk/cdk-assets-lib'; // During bundling, esbuild enforces that every module accessed -// via the top level package name is also exported. Since 'docker-credentials' -// is a private module, we prefer to not export it. Luckily, we can use relative +// via the top level package name is also exported. Since 'docker-credentials' +// is a private module, we prefer to not export it. Luckily, we can use relative // local paths instead. import { cdkCredentialsConfig, cdkCredentialsConfigFile, fetchDockerLoginCredentials, +// eslint-disable-next-line import/no-relative-packages } from '../../@aws-cdk/cdk-assets-lib/lib/private/docker-credentials'; async function main() { diff --git a/packages/cdk-assets/package.json b/packages/cdk-assets/package.json index a60f59ec9..998809e30 100644 --- a/packages/cdk-assets/package.json +++ b/packages/cdk-assets/package.json @@ -36,7 +36,7 @@ }, "devDependencies": { "@aws-cdk/cloud-assembly-schema": "^0.0.0", - "@aws-sdk/client-s3": "^3.839.0", + "@aws-sdk/client-s3": "^3.846.0", "@cdklabs/eslint-plugin": "^1.3.2", "@stylistic/eslint-plugin": "^3", "@types/jest": "^29.5.14", @@ -57,10 +57,10 @@ "jest": "^29.7.0", "jest-junit": "^16", "license-checker": "^25.0.1", - "node-backpack": "^1.0.0", + "node-backpack": "^1.1.0", "prettier": "^2.8", "ts-jest": "^29.4.0", - "typescript": "5.6" + "typescript": "5.8" }, "dependencies": { "@aws-cdk/cdk-assets-lib": "^0.0.0", diff --git a/packages/cdk/.projen/deps.json b/packages/cdk/.projen/deps.json index 716162c7f..0820e8f23 100644 --- a/packages/cdk/.projen/deps.json +++ b/packages/cdk/.projen/deps.json @@ -91,7 +91,7 @@ }, { "name": "typescript", - "version": "5.6", + "version": "5.8", "type": "build" }, { diff --git a/packages/cdk/package.json b/packages/cdk/package.json index d17f1eb40..dcbd26a38 100644 --- a/packages/cdk/package.json +++ b/packages/cdk/package.json @@ -54,7 +54,7 @@ "license-checker": "^25.0.1", "prettier": "^2.8", "ts-jest": "^29.4.0", - "typescript": "5.6" + "typescript": "5.8" }, "dependencies": { "aws-cdk": "^0.0.0" diff --git a/yarn.lock b/yarn.lock index 092289be9..f4b361535 100644 --- a/yarn.lock +++ b/yarn.lock @@ -21,36 +21,44 @@ "@csstools/css-tokenizer" "^3.0.3" lru-cache "^10.4.3" -"@aws-cdk/asset-awscli-v1@2.2.240": - version "2.2.240" - resolved "https://registry.yarnpkg.com/@aws-cdk/asset-awscli-v1/-/asset-awscli-v1-2.2.240.tgz#1dae84e4772778b461aaf14dec5ed7922d8c4385" - integrity sha512-Ry5yvGVf8s7j1Gf1aBFs0mBnWzRkkRtgSVpRGkDWXvZoPbRODAH33S1mAxkETNb+dNnTPGE2Gvws0XbhpJ6RzA== +"@aws-cdk/asset-awscli-v1@2.2.242": + version "2.2.242" + resolved "https://registry.yarnpkg.com/@aws-cdk/asset-awscli-v1/-/asset-awscli-v1-2.2.242.tgz#235cb25b6d1ad26975b0095c0d6ee84309adae5c" + integrity sha512-4c1bAy2ISzcdKXYS1k4HYZsNrgiwbiDzj36ybwFVxEWZXVAP0dimQTCaB9fxu7sWzEjw3d+eaw6Fon+QTfTIpQ== "@aws-cdk/asset-node-proxy-agent-v6@^2.1.0": version "2.1.0" resolved "https://registry.yarnpkg.com/@aws-cdk/asset-node-proxy-agent-v6/-/asset-node-proxy-agent-v6-2.1.0.tgz#6d3c7860354d4856a7e75375f2f0ecab313b4989" integrity sha512-7bY3J8GCVxLupn/kNmpPc5VJz8grx+4RKfnnJiO1LG+uxkZfANZG3RMHhE+qQxxwkyQ9/MfPtTpf748UhR425A== -"@aws-cdk/aws-service-spec@^0.1.84": - version "0.1.84" - resolved "https://registry.yarnpkg.com/@aws-cdk/aws-service-spec/-/aws-service-spec-0.1.84.tgz#520b4d69365bed901813fac1821750d899f6cc7e" - integrity sha512-anurRdTvmebg3VhHeXDE7c039jJqVZNBtDvnxmbmjENDLch+jmu7uxIx0DXRLT7201raR7BKA28/nQh2srCzNA== +"@aws-cdk/aws-service-spec@^0.1.86": + version "0.1.86" + resolved "https://registry.yarnpkg.com/@aws-cdk/aws-service-spec/-/aws-service-spec-0.1.86.tgz#ef9a74a3a9ff6a2901e5489bab465ed5ee6163ab" + integrity sha512-/el9RfmBfwVnz1D7/Y3pKImLUnEpm+qTwaLSbWEg0iS7owYOvU/Ab5WivLN3EOVCZpE9XHkMhbaHiJ9WUGXdcg== dependencies: - "@aws-cdk/service-spec-types" "^0.0.150" + "@aws-cdk/service-spec-types" "^0.0.152" "@cdklabs/tskb" "^0.0.3" -"@aws-cdk/cloud-assembly-schema@^44.2.0": - version "44.8.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/cloud-assembly-schema/-/cloud-assembly-schema-44.8.0.tgz#52da129bd718cc354c2970a6922c2346459f3945" - integrity sha512-Bxyj0VH8phE1uHJ6LiG3/UC/HYK91EBZnXSOzwtLsMJ0ZPuaQCYDRVAAfjDCSsEOwAk56/Waks8b5pXHpgz/xw== +"@aws-cdk/cloud-assembly-schema@^44.8.0": + version "44.9.0" + resolved "https://registry.yarnpkg.com/@aws-cdk/cloud-assembly-schema/-/cloud-assembly-schema-44.9.0.tgz#1b8673cd7d83d749566b5acc1d510397f1dc60cb" + integrity sha512-zQ/CwW/CZ3Zcf2vdukBCHbZi8wwYuoVIRU7w6dWS7Y7wPuq7iWTWwQyujvH5YlDVMyH4mrgYa3f1lV2etTZLVQ== dependencies: jsonschema "~1.4.1" semver "^7.7.2" -"@aws-cdk/cx-api@^2", "@aws-cdk/cx-api@^2.202.0": - version "2.202.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/cx-api/-/cx-api-2.202.0.tgz#3c4e4acbc8c5717f4acc284204d3b47eb60a7c17" - integrity sha512-VhG77DeB4hStbV8EEbO3sHUjFRG3vSlT4KzU0bwa7XeCql8nWhQt7YtMWY3bFzDIHkKWDeiffN8d0wwuR8imGA== +"@aws-cdk/cloud-assembly-schema@^45.0.0": + version "45.2.0" + resolved "https://registry.yarnpkg.com/@aws-cdk/cloud-assembly-schema/-/cloud-assembly-schema-45.2.0.tgz#bd4bf1e16189a2d424b9ab503db48ca9732325b1" + integrity sha512-5TTUkGHQ+nfuUGwKA8/Yraxb+JdNUh4np24qk/VHXmrCMq+M6HfmGWfhcg/QlHA2S5P3YIamfYHdQAB4uSNLAg== + dependencies: + jsonschema "~1.4.1" + semver "^7.7.2" + +"@aws-cdk/cx-api@^2", "@aws-cdk/cx-api@^2.205.0": + version "2.205.0" + resolved "https://registry.yarnpkg.com/@aws-cdk/cx-api/-/cx-api-2.205.0.tgz#6858ef7f67cf7279269e2d0fcfaf98f17047343b" + integrity sha512-IaLz5mDEC60AuTAug981liWNSu1mz0VGN8qyKhXd7s7ma+pw/HVtzA30+T3TPKEgTEchjmmroCooMbyyoVxQQA== dependencies: semver "^7.7.2" @@ -59,10 +67,10 @@ resolved "https://registry.yarnpkg.com/@aws-cdk/integ-tests-alpha/-/integ-tests-alpha-2.184.1-alpha.0.tgz#0719db2d294eac42de58f320238b3cd9a0e5b8fc" integrity sha512-9ca8uxcP41USi2Y/ulGFR9iCLEAofq6h8VcSMpJHRvJb3mQtBJ+WYwXIn+uyMtDBIWX4pOyMk/6XZDuZVpwOsg== -"@aws-cdk/service-spec-types@^0.0.150": - version "0.0.150" - resolved "https://registry.yarnpkg.com/@aws-cdk/service-spec-types/-/service-spec-types-0.0.150.tgz#3a42559d9f81663f089b7ac518116c33a726c5ff" - integrity sha512-s/hDl+Q+ste5xtriLBxKFreH3GfG9YFBsxpvz+oYEjMtc9ILrtVPcUqcU3SonprRdgDNkuB8Kghecp5iRBTgpA== +"@aws-cdk/service-spec-types@^0.0.152": + version "0.0.152" + resolved "https://registry.yarnpkg.com/@aws-cdk/service-spec-types/-/service-spec-types-0.0.152.tgz#09370362ef9fd26604f79075d9e7759cdfdd658c" + integrity sha512-zTEzp4EwUXrwqts48xV11GknGnQuEw3/l4tBZ1mePJXRZzBHcP5q4h/Q4AGJ9jrBtCqSks9EAoX2kTlgjkU4fg== dependencies: "@cdklabs/tskb" "^0.0.3" @@ -187,90 +195,90 @@ tslib "^1.8.0" "@aws-sdk/client-appsync@^3": - version "3.839.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-appsync/-/client-appsync-3.839.0.tgz#5cae16967f0633d783ec1b82d6e8e11008339ce1" - integrity sha512-TcJN9Gk7w9hhXUlCOTLc/hghzPJLRXCdM9/a0zdzOz3kd7N7b6rPuTL3qgXuPn4eO90oHjOucioQmlgJUnEYDg== + version "3.846.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-appsync/-/client-appsync-3.846.0.tgz#8a5555e62777e420c16de33de9d49b2e3ee758bd" + integrity sha512-pZPQ7VMXZ04rkipLk2OFyfq13hnW90r4gIzsqpXCG3dYxLaIyTmyyGG02F2xAQvOjK5My2J+09W+6Ll/HkeiBg== dependencies: "@aws-crypto/sha256-browser" "5.2.0" "@aws-crypto/sha256-js" "5.2.0" - "@aws-sdk/core" "3.839.0" - "@aws-sdk/credential-provider-node" "3.839.0" - "@aws-sdk/middleware-host-header" "3.821.0" - "@aws-sdk/middleware-logger" "3.821.0" - "@aws-sdk/middleware-recursion-detection" "3.821.0" - "@aws-sdk/middleware-user-agent" "3.839.0" - "@aws-sdk/region-config-resolver" "3.821.0" - "@aws-sdk/types" "3.821.0" - "@aws-sdk/util-endpoints" "3.828.0" - "@aws-sdk/util-user-agent-browser" "3.821.0" - "@aws-sdk/util-user-agent-node" "3.839.0" + "@aws-sdk/core" "3.846.0" + "@aws-sdk/credential-provider-node" "3.846.0" + "@aws-sdk/middleware-host-header" "3.840.0" + "@aws-sdk/middleware-logger" "3.840.0" + "@aws-sdk/middleware-recursion-detection" "3.840.0" + "@aws-sdk/middleware-user-agent" "3.846.0" + "@aws-sdk/region-config-resolver" "3.840.0" + "@aws-sdk/types" "3.840.0" + "@aws-sdk/util-endpoints" "3.845.0" + "@aws-sdk/util-user-agent-browser" "3.840.0" + "@aws-sdk/util-user-agent-node" "3.846.0" "@smithy/config-resolver" "^4.1.4" - "@smithy/core" "^3.6.0" - "@smithy/fetch-http-handler" "^5.0.4" + "@smithy/core" "^3.7.0" + "@smithy/fetch-http-handler" "^5.1.0" "@smithy/hash-node" "^4.0.4" "@smithy/invalid-dependency" "^4.0.4" "@smithy/middleware-content-length" "^4.0.4" - "@smithy/middleware-endpoint" "^4.1.13" - "@smithy/middleware-retry" "^4.1.14" + "@smithy/middleware-endpoint" "^4.1.15" + "@smithy/middleware-retry" "^4.1.16" "@smithy/middleware-serde" "^4.0.8" "@smithy/middleware-stack" "^4.0.4" "@smithy/node-config-provider" "^4.1.3" - "@smithy/node-http-handler" "^4.0.6" + "@smithy/node-http-handler" "^4.1.0" "@smithy/protocol-http" "^5.1.2" - "@smithy/smithy-client" "^4.4.5" + "@smithy/smithy-client" "^4.4.7" "@smithy/types" "^4.3.1" "@smithy/url-parser" "^4.0.4" "@smithy/util-base64" "^4.0.0" "@smithy/util-body-length-browser" "^4.0.0" "@smithy/util-body-length-node" "^4.0.0" - "@smithy/util-defaults-mode-browser" "^4.0.21" - "@smithy/util-defaults-mode-node" "^4.0.21" + "@smithy/util-defaults-mode-browser" "^4.0.23" + "@smithy/util-defaults-mode-node" "^4.0.23" "@smithy/util-endpoints" "^3.0.6" "@smithy/util-middleware" "^4.0.4" "@smithy/util-retry" "^4.0.6" - "@smithy/util-stream" "^4.2.2" + "@smithy/util-stream" "^4.2.3" "@smithy/util-utf8" "^4.0.0" tslib "^2.6.2" "@aws-sdk/client-cloudcontrol@^3": - version "3.839.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-cloudcontrol/-/client-cloudcontrol-3.839.0.tgz#4da4f891b647eda06a8b46c3e51d419f636a1fe1" - integrity sha512-EZxZnlKJ258t9Mefzex3LTNZlSvwFYFsqSx5Qo/UXCz/EqFcNbMtTA9yclfpRtisfUR1+QAdAEx4a1/I5LYCUw== + version "3.846.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-cloudcontrol/-/client-cloudcontrol-3.846.0.tgz#6878aab1ed5994caa4cc50118659f19bda30cec7" + integrity sha512-VmRKhgCYbQ4FKoAb11PbSYWorrq0n5n06B32clJjO021MuUJouuiFprh7TjR39MpOWcf1DW5PqseKXHN5wafVw== dependencies: "@aws-crypto/sha256-browser" "5.2.0" "@aws-crypto/sha256-js" "5.2.0" - "@aws-sdk/core" "3.839.0" - "@aws-sdk/credential-provider-node" "3.839.0" - "@aws-sdk/middleware-host-header" "3.821.0" - "@aws-sdk/middleware-logger" "3.821.0" - "@aws-sdk/middleware-recursion-detection" "3.821.0" - "@aws-sdk/middleware-user-agent" "3.839.0" - "@aws-sdk/region-config-resolver" "3.821.0" - "@aws-sdk/types" "3.821.0" - "@aws-sdk/util-endpoints" "3.828.0" - "@aws-sdk/util-user-agent-browser" "3.821.0" - "@aws-sdk/util-user-agent-node" "3.839.0" + "@aws-sdk/core" "3.846.0" + "@aws-sdk/credential-provider-node" "3.846.0" + "@aws-sdk/middleware-host-header" "3.840.0" + "@aws-sdk/middleware-logger" "3.840.0" + "@aws-sdk/middleware-recursion-detection" "3.840.0" + "@aws-sdk/middleware-user-agent" "3.846.0" + "@aws-sdk/region-config-resolver" "3.840.0" + "@aws-sdk/types" "3.840.0" + "@aws-sdk/util-endpoints" "3.845.0" + "@aws-sdk/util-user-agent-browser" "3.840.0" + "@aws-sdk/util-user-agent-node" "3.846.0" "@smithy/config-resolver" "^4.1.4" - "@smithy/core" "^3.6.0" - "@smithy/fetch-http-handler" "^5.0.4" + "@smithy/core" "^3.7.0" + "@smithy/fetch-http-handler" "^5.1.0" "@smithy/hash-node" "^4.0.4" "@smithy/invalid-dependency" "^4.0.4" "@smithy/middleware-content-length" "^4.0.4" - "@smithy/middleware-endpoint" "^4.1.13" - "@smithy/middleware-retry" "^4.1.14" + "@smithy/middleware-endpoint" "^4.1.15" + "@smithy/middleware-retry" "^4.1.16" "@smithy/middleware-serde" "^4.0.8" "@smithy/middleware-stack" "^4.0.4" "@smithy/node-config-provider" "^4.1.3" - "@smithy/node-http-handler" "^4.0.6" + "@smithy/node-http-handler" "^4.1.0" "@smithy/protocol-http" "^5.1.2" - "@smithy/smithy-client" "^4.4.5" + "@smithy/smithy-client" "^4.4.7" "@smithy/types" "^4.3.1" "@smithy/url-parser" "^4.0.4" "@smithy/util-base64" "^4.0.0" "@smithy/util-body-length-browser" "^4.0.0" "@smithy/util-body-length-node" "^4.0.0" - "@smithy/util-defaults-mode-browser" "^4.0.21" - "@smithy/util-defaults-mode-node" "^4.0.21" + "@smithy/util-defaults-mode-browser" "^4.0.23" + "@smithy/util-defaults-mode-node" "^4.0.23" "@smithy/util-endpoints" "^3.0.6" "@smithy/util-middleware" "^4.0.4" "@smithy/util-retry" "^4.0.6" @@ -319,45 +327,45 @@ tslib "^2.0.0" uuid "^3.0.0" -"@aws-sdk/client-cloudformation@3.839.0", "@aws-sdk/client-cloudformation@^3": - version "3.839.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-cloudformation/-/client-cloudformation-3.839.0.tgz#d60d83420e56cb4765639659f79472c472eb49b5" - integrity sha512-c6kF7aiR98nf3uo6FQ5v2PSZTbESlViwMFQTKlZzQR+GexxrR5aKdaJWHpf0TsgjM0LjcrXdaJU6ccIwT6+XZg== +"@aws-sdk/client-cloudformation@^3", "@aws-sdk/client-cloudformation@^3.846.0": + version "3.846.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-cloudformation/-/client-cloudformation-3.846.0.tgz#78313d10613e8d9a55111bd57ecf9ec8a2588980" + integrity sha512-czKaX5JBkiG4zjfIM8EDNVwb6NaAtdv3BJF5EIw0/sdImPnY3Twvx8ylmpQO+kmRwN3/TsKUfF2+SYZMjRFrTg== dependencies: "@aws-crypto/sha256-browser" "5.2.0" "@aws-crypto/sha256-js" "5.2.0" - "@aws-sdk/core" "3.839.0" - "@aws-sdk/credential-provider-node" "3.839.0" - "@aws-sdk/middleware-host-header" "3.821.0" - "@aws-sdk/middleware-logger" "3.821.0" - "@aws-sdk/middleware-recursion-detection" "3.821.0" - "@aws-sdk/middleware-user-agent" "3.839.0" - "@aws-sdk/region-config-resolver" "3.821.0" - "@aws-sdk/types" "3.821.0" - "@aws-sdk/util-endpoints" "3.828.0" - "@aws-sdk/util-user-agent-browser" "3.821.0" - "@aws-sdk/util-user-agent-node" "3.839.0" + "@aws-sdk/core" "3.846.0" + "@aws-sdk/credential-provider-node" "3.846.0" + "@aws-sdk/middleware-host-header" "3.840.0" + "@aws-sdk/middleware-logger" "3.840.0" + "@aws-sdk/middleware-recursion-detection" "3.840.0" + "@aws-sdk/middleware-user-agent" "3.846.0" + "@aws-sdk/region-config-resolver" "3.840.0" + "@aws-sdk/types" "3.840.0" + "@aws-sdk/util-endpoints" "3.845.0" + "@aws-sdk/util-user-agent-browser" "3.840.0" + "@aws-sdk/util-user-agent-node" "3.846.0" "@smithy/config-resolver" "^4.1.4" - "@smithy/core" "^3.6.0" - "@smithy/fetch-http-handler" "^5.0.4" + "@smithy/core" "^3.7.0" + "@smithy/fetch-http-handler" "^5.1.0" "@smithy/hash-node" "^4.0.4" "@smithy/invalid-dependency" "^4.0.4" "@smithy/middleware-content-length" "^4.0.4" - "@smithy/middleware-endpoint" "^4.1.13" - "@smithy/middleware-retry" "^4.1.14" + "@smithy/middleware-endpoint" "^4.1.15" + "@smithy/middleware-retry" "^4.1.16" "@smithy/middleware-serde" "^4.0.8" "@smithy/middleware-stack" "^4.0.4" "@smithy/node-config-provider" "^4.1.3" - "@smithy/node-http-handler" "^4.0.6" + "@smithy/node-http-handler" "^4.1.0" "@smithy/protocol-http" "^5.1.2" - "@smithy/smithy-client" "^4.4.5" + "@smithy/smithy-client" "^4.4.7" "@smithy/types" "^4.3.1" "@smithy/url-parser" "^4.0.4" "@smithy/util-base64" "^4.0.0" "@smithy/util-body-length-browser" "^4.0.0" "@smithy/util-body-length-node" "^4.0.0" - "@smithy/util-defaults-mode-browser" "^4.0.21" - "@smithy/util-defaults-mode-node" "^4.0.21" + "@smithy/util-defaults-mode-browser" "^4.0.23" + "@smithy/util-defaults-mode-node" "^4.0.23" "@smithy/util-endpoints" "^3.0.6" "@smithy/util-middleware" "^4.0.4" "@smithy/util-retry" "^4.0.6" @@ -368,47 +376,47 @@ uuid "^9.0.1" "@aws-sdk/client-cloudwatch-logs@^3": - version "3.839.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-cloudwatch-logs/-/client-cloudwatch-logs-3.839.0.tgz#7f2720c611193bbceb8098dcdf5482f97809cef7" - integrity sha512-VHcCFMqcWeElldZKuJNU0ZM50QVraw9ZyeOlc74JU3F9xQG6aRGdpAzX+dvFemVipnnoaIU8f70DnlZ2/FB62g== + version "3.846.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-cloudwatch-logs/-/client-cloudwatch-logs-3.846.0.tgz#ac1de573c3877e04a97c4669ee02e01d2f8b9003" + integrity sha512-tBylQcQnf1+Z3ERiuqW4V1p/Dq6L70azVGhwEfsh3XVrRVLK2So1qjtJP3zLXetaGw1Nbcud2T6IDHZLDJmBDA== dependencies: "@aws-crypto/sha256-browser" "5.2.0" "@aws-crypto/sha256-js" "5.2.0" - "@aws-sdk/core" "3.839.0" - "@aws-sdk/credential-provider-node" "3.839.0" - "@aws-sdk/middleware-host-header" "3.821.0" - "@aws-sdk/middleware-logger" "3.821.0" - "@aws-sdk/middleware-recursion-detection" "3.821.0" - "@aws-sdk/middleware-user-agent" "3.839.0" - "@aws-sdk/region-config-resolver" "3.821.0" - "@aws-sdk/types" "3.821.0" - "@aws-sdk/util-endpoints" "3.828.0" - "@aws-sdk/util-user-agent-browser" "3.821.0" - "@aws-sdk/util-user-agent-node" "3.839.0" + "@aws-sdk/core" "3.846.0" + "@aws-sdk/credential-provider-node" "3.846.0" + "@aws-sdk/middleware-host-header" "3.840.0" + "@aws-sdk/middleware-logger" "3.840.0" + "@aws-sdk/middleware-recursion-detection" "3.840.0" + "@aws-sdk/middleware-user-agent" "3.846.0" + "@aws-sdk/region-config-resolver" "3.840.0" + "@aws-sdk/types" "3.840.0" + "@aws-sdk/util-endpoints" "3.845.0" + "@aws-sdk/util-user-agent-browser" "3.840.0" + "@aws-sdk/util-user-agent-node" "3.846.0" "@smithy/config-resolver" "^4.1.4" - "@smithy/core" "^3.6.0" + "@smithy/core" "^3.7.0" "@smithy/eventstream-serde-browser" "^4.0.4" "@smithy/eventstream-serde-config-resolver" "^4.1.2" "@smithy/eventstream-serde-node" "^4.0.4" - "@smithy/fetch-http-handler" "^5.0.4" + "@smithy/fetch-http-handler" "^5.1.0" "@smithy/hash-node" "^4.0.4" "@smithy/invalid-dependency" "^4.0.4" "@smithy/middleware-content-length" "^4.0.4" - "@smithy/middleware-endpoint" "^4.1.13" - "@smithy/middleware-retry" "^4.1.14" + "@smithy/middleware-endpoint" "^4.1.15" + "@smithy/middleware-retry" "^4.1.16" "@smithy/middleware-serde" "^4.0.8" "@smithy/middleware-stack" "^4.0.4" "@smithy/node-config-provider" "^4.1.3" - "@smithy/node-http-handler" "^4.0.6" + "@smithy/node-http-handler" "^4.1.0" "@smithy/protocol-http" "^5.1.2" - "@smithy/smithy-client" "^4.4.5" + "@smithy/smithy-client" "^4.4.7" "@smithy/types" "^4.3.1" "@smithy/url-parser" "^4.0.4" "@smithy/util-base64" "^4.0.0" "@smithy/util-body-length-browser" "^4.0.0" "@smithy/util-body-length-node" "^4.0.0" - "@smithy/util-defaults-mode-browser" "^4.0.21" - "@smithy/util-defaults-mode-node" "^4.0.21" + "@smithy/util-defaults-mode-browser" "^4.0.23" + "@smithy/util-defaults-mode-node" "^4.0.23" "@smithy/util-endpoints" "^3.0.6" "@smithy/util-middleware" "^4.0.4" "@smithy/util-retry" "^4.0.6" @@ -417,136 +425,136 @@ tslib "^2.6.2" uuid "^9.0.1" -"@aws-sdk/client-codeartifact@3.839.0": - version "3.839.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-codeartifact/-/client-codeartifact-3.839.0.tgz#62a57a443cafe19d482111eac996745bc292e1f7" - integrity sha512-6FB4bOPe3yJNjK5JoEuKj2HuAHMBdf9RS97TgsKsYcjXywHI1i0trKDWqwRnK9HaKezKP+jN0d+0ezijX0bQuQ== +"@aws-sdk/client-codeartifact@^3.846.0": + version "3.846.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-codeartifact/-/client-codeartifact-3.846.0.tgz#89a08ddb056a91ca4a118276a6ba0c8428da5ce3" + integrity sha512-iB5RsAjWaZT/SOxN+nCWsm9Rr4k94TqowUtQyut7Wv2Ds0fOPhGJc/mzq2siY7uilP8ppgW7Re6VN8D8GQ4g7Q== dependencies: "@aws-crypto/sha256-browser" "5.2.0" "@aws-crypto/sha256-js" "5.2.0" - "@aws-sdk/core" "3.839.0" - "@aws-sdk/credential-provider-node" "3.839.0" - "@aws-sdk/middleware-host-header" "3.821.0" - "@aws-sdk/middleware-logger" "3.821.0" - "@aws-sdk/middleware-recursion-detection" "3.821.0" - "@aws-sdk/middleware-user-agent" "3.839.0" - "@aws-sdk/region-config-resolver" "3.821.0" - "@aws-sdk/types" "3.821.0" - "@aws-sdk/util-endpoints" "3.828.0" - "@aws-sdk/util-user-agent-browser" "3.821.0" - "@aws-sdk/util-user-agent-node" "3.839.0" + "@aws-sdk/core" "3.846.0" + "@aws-sdk/credential-provider-node" "3.846.0" + "@aws-sdk/middleware-host-header" "3.840.0" + "@aws-sdk/middleware-logger" "3.840.0" + "@aws-sdk/middleware-recursion-detection" "3.840.0" + "@aws-sdk/middleware-user-agent" "3.846.0" + "@aws-sdk/region-config-resolver" "3.840.0" + "@aws-sdk/types" "3.840.0" + "@aws-sdk/util-endpoints" "3.845.0" + "@aws-sdk/util-user-agent-browser" "3.840.0" + "@aws-sdk/util-user-agent-node" "3.846.0" "@smithy/config-resolver" "^4.1.4" - "@smithy/core" "^3.6.0" - "@smithy/fetch-http-handler" "^5.0.4" + "@smithy/core" "^3.7.0" + "@smithy/fetch-http-handler" "^5.1.0" "@smithy/hash-node" "^4.0.4" "@smithy/invalid-dependency" "^4.0.4" "@smithy/middleware-content-length" "^4.0.4" - "@smithy/middleware-endpoint" "^4.1.13" - "@smithy/middleware-retry" "^4.1.14" + "@smithy/middleware-endpoint" "^4.1.15" + "@smithy/middleware-retry" "^4.1.16" "@smithy/middleware-serde" "^4.0.8" "@smithy/middleware-stack" "^4.0.4" "@smithy/node-config-provider" "^4.1.3" - "@smithy/node-http-handler" "^4.0.6" + "@smithy/node-http-handler" "^4.1.0" "@smithy/protocol-http" "^5.1.2" - "@smithy/smithy-client" "^4.4.5" + "@smithy/smithy-client" "^4.4.7" "@smithy/types" "^4.3.1" "@smithy/url-parser" "^4.0.4" "@smithy/util-base64" "^4.0.0" "@smithy/util-body-length-browser" "^4.0.0" "@smithy/util-body-length-node" "^4.0.0" - "@smithy/util-defaults-mode-browser" "^4.0.21" - "@smithy/util-defaults-mode-node" "^4.0.21" + "@smithy/util-defaults-mode-browser" "^4.0.23" + "@smithy/util-defaults-mode-node" "^4.0.23" "@smithy/util-endpoints" "^3.0.6" "@smithy/util-middleware" "^4.0.4" "@smithy/util-retry" "^4.0.6" - "@smithy/util-stream" "^4.2.2" + "@smithy/util-stream" "^4.2.3" "@smithy/util-utf8" "^4.0.0" tslib "^2.6.2" "@aws-sdk/client-codebuild@^3": - version "3.839.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-codebuild/-/client-codebuild-3.839.0.tgz#da814302d9f8a0d8de7307b748d04f34a5264cfc" - integrity sha512-TVFZ21x88bycKxrLZhVq1OToUUCbg93XqtRQ/z7zZeA4hKG0oYLQJGNuur3PWdex0dLBImnecg3vb7Lwpq+fJQ== + version "3.846.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-codebuild/-/client-codebuild-3.846.0.tgz#90db4a1be7d0a259beb01b38f43fe06604fad7ac" + integrity sha512-WKItCZIH86UzzW/ndQsl4Xw4wYrSph2+Txx9WJPF2A2/N3ltTg3kSgIob8CauKJhUU/6LrFgdL1FTAhr9bciVg== dependencies: "@aws-crypto/sha256-browser" "5.2.0" "@aws-crypto/sha256-js" "5.2.0" - "@aws-sdk/core" "3.839.0" - "@aws-sdk/credential-provider-node" "3.839.0" - "@aws-sdk/middleware-host-header" "3.821.0" - "@aws-sdk/middleware-logger" "3.821.0" - "@aws-sdk/middleware-recursion-detection" "3.821.0" - "@aws-sdk/middleware-user-agent" "3.839.0" - "@aws-sdk/region-config-resolver" "3.821.0" - "@aws-sdk/types" "3.821.0" - "@aws-sdk/util-endpoints" "3.828.0" - "@aws-sdk/util-user-agent-browser" "3.821.0" - "@aws-sdk/util-user-agent-node" "3.839.0" + "@aws-sdk/core" "3.846.0" + "@aws-sdk/credential-provider-node" "3.846.0" + "@aws-sdk/middleware-host-header" "3.840.0" + "@aws-sdk/middleware-logger" "3.840.0" + "@aws-sdk/middleware-recursion-detection" "3.840.0" + "@aws-sdk/middleware-user-agent" "3.846.0" + "@aws-sdk/region-config-resolver" "3.840.0" + "@aws-sdk/types" "3.840.0" + "@aws-sdk/util-endpoints" "3.845.0" + "@aws-sdk/util-user-agent-browser" "3.840.0" + "@aws-sdk/util-user-agent-node" "3.846.0" "@smithy/config-resolver" "^4.1.4" - "@smithy/core" "^3.6.0" - "@smithy/fetch-http-handler" "^5.0.4" + "@smithy/core" "^3.7.0" + "@smithy/fetch-http-handler" "^5.1.0" "@smithy/hash-node" "^4.0.4" "@smithy/invalid-dependency" "^4.0.4" "@smithy/middleware-content-length" "^4.0.4" - "@smithy/middleware-endpoint" "^4.1.13" - "@smithy/middleware-retry" "^4.1.14" + "@smithy/middleware-endpoint" "^4.1.15" + "@smithy/middleware-retry" "^4.1.16" "@smithy/middleware-serde" "^4.0.8" "@smithy/middleware-stack" "^4.0.4" "@smithy/node-config-provider" "^4.1.3" - "@smithy/node-http-handler" "^4.0.6" + "@smithy/node-http-handler" "^4.1.0" "@smithy/protocol-http" "^5.1.2" - "@smithy/smithy-client" "^4.4.5" + "@smithy/smithy-client" "^4.4.7" "@smithy/types" "^4.3.1" "@smithy/url-parser" "^4.0.4" "@smithy/util-base64" "^4.0.0" "@smithy/util-body-length-browser" "^4.0.0" "@smithy/util-body-length-node" "^4.0.0" - "@smithy/util-defaults-mode-browser" "^4.0.21" - "@smithy/util-defaults-mode-node" "^4.0.21" + "@smithy/util-defaults-mode-browser" "^4.0.23" + "@smithy/util-defaults-mode-node" "^4.0.23" "@smithy/util-endpoints" "^3.0.6" "@smithy/util-middleware" "^4.0.4" "@smithy/util-retry" "^4.0.6" "@smithy/util-utf8" "^4.0.0" tslib "^2.6.2" -"@aws-sdk/client-cognito-identity@3.839.0": - version "3.839.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.839.0.tgz#ccbeaba2e673ff70c95b42f32d2621206045098d" - integrity sha512-Pq/A5W46Z0JrRTIl4eVvguQjXWwVHiiBC3WyrLxlIH0hMS6bILgC7H+z+JiCm4mXR/oF2ZobQ8Wei/Sga1Uxkw== +"@aws-sdk/client-cognito-identity@3.846.0": + version "3.846.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.846.0.tgz#f7bfecb0c731df961058b4f63029f7556cb7eda6" + integrity sha512-vlzQVq1TOOYHPppmON/+oNhCxprCPPqxlqAuUddf885JcT6Q9r7FeV7S2yHli/1XC6vBa7sAninNvOjzwDbwYw== dependencies: "@aws-crypto/sha256-browser" "5.2.0" "@aws-crypto/sha256-js" "5.2.0" - "@aws-sdk/core" "3.839.0" - "@aws-sdk/credential-provider-node" "3.839.0" - "@aws-sdk/middleware-host-header" "3.821.0" - "@aws-sdk/middleware-logger" "3.821.0" - "@aws-sdk/middleware-recursion-detection" "3.821.0" - "@aws-sdk/middleware-user-agent" "3.839.0" - "@aws-sdk/region-config-resolver" "3.821.0" - "@aws-sdk/types" "3.821.0" - "@aws-sdk/util-endpoints" "3.828.0" - "@aws-sdk/util-user-agent-browser" "3.821.0" - "@aws-sdk/util-user-agent-node" "3.839.0" + "@aws-sdk/core" "3.846.0" + "@aws-sdk/credential-provider-node" "3.846.0" + "@aws-sdk/middleware-host-header" "3.840.0" + "@aws-sdk/middleware-logger" "3.840.0" + "@aws-sdk/middleware-recursion-detection" "3.840.0" + "@aws-sdk/middleware-user-agent" "3.846.0" + "@aws-sdk/region-config-resolver" "3.840.0" + "@aws-sdk/types" "3.840.0" + "@aws-sdk/util-endpoints" "3.845.0" + "@aws-sdk/util-user-agent-browser" "3.840.0" + "@aws-sdk/util-user-agent-node" "3.846.0" "@smithy/config-resolver" "^4.1.4" - "@smithy/core" "^3.6.0" - "@smithy/fetch-http-handler" "^5.0.4" + "@smithy/core" "^3.7.0" + "@smithy/fetch-http-handler" "^5.1.0" "@smithy/hash-node" "^4.0.4" "@smithy/invalid-dependency" "^4.0.4" "@smithy/middleware-content-length" "^4.0.4" - "@smithy/middleware-endpoint" "^4.1.13" - "@smithy/middleware-retry" "^4.1.14" + "@smithy/middleware-endpoint" "^4.1.15" + "@smithy/middleware-retry" "^4.1.16" "@smithy/middleware-serde" "^4.0.8" "@smithy/middleware-stack" "^4.0.4" "@smithy/node-config-provider" "^4.1.3" - "@smithy/node-http-handler" "^4.0.6" + "@smithy/node-http-handler" "^4.1.0" "@smithy/protocol-http" "^5.1.2" - "@smithy/smithy-client" "^4.4.5" + "@smithy/smithy-client" "^4.4.7" "@smithy/types" "^4.3.1" "@smithy/url-parser" "^4.0.4" "@smithy/util-base64" "^4.0.0" "@smithy/util-body-length-browser" "^4.0.0" "@smithy/util-body-length-node" "^4.0.0" - "@smithy/util-defaults-mode-browser" "^4.0.21" - "@smithy/util-defaults-mode-node" "^4.0.21" + "@smithy/util-defaults-mode-browser" "^4.0.23" + "@smithy/util-defaults-mode-node" "^4.0.23" "@smithy/util-endpoints" "^3.0.6" "@smithy/util-middleware" "^4.0.4" "@smithy/util-retry" "^4.0.6" @@ -554,45 +562,45 @@ tslib "^2.6.2" "@aws-sdk/client-ec2@^3": - version "3.839.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-ec2/-/client-ec2-3.839.0.tgz#cc8712d1a40cecfbfb3e3f81b4c3b6ccf1a1ae77" - integrity sha512-ObZbGopmMKUWGR7UIz1ATCb5CrgWWdgsFtWxu9BOExjJEdmQURaKAuepx8HjyQvuWufK/iN65dyqHaaDKfzaRg== + version "3.846.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-ec2/-/client-ec2-3.846.0.tgz#564e636751aabbafc4aabd779392e2ec04961dad" + integrity sha512-FIZxrT6Daykq9RYmppo/jI9hNQVHrPzooBwZjVhoD7tkAxDUGZn4h/t2BM+OPs0ecUaw37H2sIKvBSLbhEgldQ== dependencies: "@aws-crypto/sha256-browser" "5.2.0" "@aws-crypto/sha256-js" "5.2.0" - "@aws-sdk/core" "3.839.0" - "@aws-sdk/credential-provider-node" "3.839.0" - "@aws-sdk/middleware-host-header" "3.821.0" - "@aws-sdk/middleware-logger" "3.821.0" - "@aws-sdk/middleware-recursion-detection" "3.821.0" - "@aws-sdk/middleware-sdk-ec2" "3.839.0" - "@aws-sdk/middleware-user-agent" "3.839.0" - "@aws-sdk/region-config-resolver" "3.821.0" - "@aws-sdk/types" "3.821.0" - "@aws-sdk/util-endpoints" "3.828.0" - "@aws-sdk/util-user-agent-browser" "3.821.0" - "@aws-sdk/util-user-agent-node" "3.839.0" + "@aws-sdk/core" "3.846.0" + "@aws-sdk/credential-provider-node" "3.846.0" + "@aws-sdk/middleware-host-header" "3.840.0" + "@aws-sdk/middleware-logger" "3.840.0" + "@aws-sdk/middleware-recursion-detection" "3.840.0" + "@aws-sdk/middleware-sdk-ec2" "3.845.0" + "@aws-sdk/middleware-user-agent" "3.846.0" + "@aws-sdk/region-config-resolver" "3.840.0" + "@aws-sdk/types" "3.840.0" + "@aws-sdk/util-endpoints" "3.845.0" + "@aws-sdk/util-user-agent-browser" "3.840.0" + "@aws-sdk/util-user-agent-node" "3.846.0" "@smithy/config-resolver" "^4.1.4" - "@smithy/core" "^3.6.0" - "@smithy/fetch-http-handler" "^5.0.4" + "@smithy/core" "^3.7.0" + "@smithy/fetch-http-handler" "^5.1.0" "@smithy/hash-node" "^4.0.4" "@smithy/invalid-dependency" "^4.0.4" "@smithy/middleware-content-length" "^4.0.4" - "@smithy/middleware-endpoint" "^4.1.13" - "@smithy/middleware-retry" "^4.1.14" + "@smithy/middleware-endpoint" "^4.1.15" + "@smithy/middleware-retry" "^4.1.16" "@smithy/middleware-serde" "^4.0.8" "@smithy/middleware-stack" "^4.0.4" "@smithy/node-config-provider" "^4.1.3" - "@smithy/node-http-handler" "^4.0.6" + "@smithy/node-http-handler" "^4.1.0" "@smithy/protocol-http" "^5.1.2" - "@smithy/smithy-client" "^4.4.5" + "@smithy/smithy-client" "^4.4.7" "@smithy/types" "^4.3.1" "@smithy/url-parser" "^4.0.4" "@smithy/util-base64" "^4.0.0" "@smithy/util-body-length-browser" "^4.0.0" "@smithy/util-body-length-node" "^4.0.0" - "@smithy/util-defaults-mode-browser" "^4.0.21" - "@smithy/util-defaults-mode-node" "^4.0.21" + "@smithy/util-defaults-mode-browser" "^4.0.23" + "@smithy/util-defaults-mode-node" "^4.0.23" "@smithy/util-endpoints" "^3.0.6" "@smithy/util-middleware" "^4.0.4" "@smithy/util-retry" "^4.0.6" @@ -602,90 +610,90 @@ tslib "^2.6.2" uuid "^9.0.1" -"@aws-sdk/client-ecr-public@3.839.0": - version "3.839.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-ecr-public/-/client-ecr-public-3.839.0.tgz#4776ef876b6cd09b7e9aecc25b4b3405f7fabd03" - integrity sha512-U21ymxYvcHcSJJEPeF+O3RZLXYkmNa3MZS0EcmCPB0ggWZYHrjXnZJfveZck4UTvNEwZ6y5ohdLyOBhSPMtgPg== +"@aws-sdk/client-ecr-public@^3.846.0": + version "3.846.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-ecr-public/-/client-ecr-public-3.846.0.tgz#d5081e55a21c04e0fc8949d21f23b6497ada0439" + integrity sha512-7UiaBB127p221pQmmceZPYY/fWexXmYn7oegHWkQJr2TejxbSchMLIWiZeSIglPWKQ5l4PhHZpVIcBJjRWf6Uw== dependencies: "@aws-crypto/sha256-browser" "5.2.0" "@aws-crypto/sha256-js" "5.2.0" - "@aws-sdk/core" "3.839.0" - "@aws-sdk/credential-provider-node" "3.839.0" - "@aws-sdk/middleware-host-header" "3.821.0" - "@aws-sdk/middleware-logger" "3.821.0" - "@aws-sdk/middleware-recursion-detection" "3.821.0" - "@aws-sdk/middleware-user-agent" "3.839.0" - "@aws-sdk/region-config-resolver" "3.821.0" - "@aws-sdk/types" "3.821.0" - "@aws-sdk/util-endpoints" "3.828.0" - "@aws-sdk/util-user-agent-browser" "3.821.0" - "@aws-sdk/util-user-agent-node" "3.839.0" + "@aws-sdk/core" "3.846.0" + "@aws-sdk/credential-provider-node" "3.846.0" + "@aws-sdk/middleware-host-header" "3.840.0" + "@aws-sdk/middleware-logger" "3.840.0" + "@aws-sdk/middleware-recursion-detection" "3.840.0" + "@aws-sdk/middleware-user-agent" "3.846.0" + "@aws-sdk/region-config-resolver" "3.840.0" + "@aws-sdk/types" "3.840.0" + "@aws-sdk/util-endpoints" "3.845.0" + "@aws-sdk/util-user-agent-browser" "3.840.0" + "@aws-sdk/util-user-agent-node" "3.846.0" "@smithy/config-resolver" "^4.1.4" - "@smithy/core" "^3.6.0" - "@smithy/fetch-http-handler" "^5.0.4" + "@smithy/core" "^3.7.0" + "@smithy/fetch-http-handler" "^5.1.0" "@smithy/hash-node" "^4.0.4" "@smithy/invalid-dependency" "^4.0.4" "@smithy/middleware-content-length" "^4.0.4" - "@smithy/middleware-endpoint" "^4.1.13" - "@smithy/middleware-retry" "^4.1.14" + "@smithy/middleware-endpoint" "^4.1.15" + "@smithy/middleware-retry" "^4.1.16" "@smithy/middleware-serde" "^4.0.8" "@smithy/middleware-stack" "^4.0.4" "@smithy/node-config-provider" "^4.1.3" - "@smithy/node-http-handler" "^4.0.6" + "@smithy/node-http-handler" "^4.1.0" "@smithy/protocol-http" "^5.1.2" - "@smithy/smithy-client" "^4.4.5" + "@smithy/smithy-client" "^4.4.7" "@smithy/types" "^4.3.1" "@smithy/url-parser" "^4.0.4" "@smithy/util-base64" "^4.0.0" "@smithy/util-body-length-browser" "^4.0.0" "@smithy/util-body-length-node" "^4.0.0" - "@smithy/util-defaults-mode-browser" "^4.0.21" - "@smithy/util-defaults-mode-node" "^4.0.21" + "@smithy/util-defaults-mode-browser" "^4.0.23" + "@smithy/util-defaults-mode-node" "^4.0.23" "@smithy/util-endpoints" "^3.0.6" "@smithy/util-middleware" "^4.0.4" "@smithy/util-retry" "^4.0.6" "@smithy/util-utf8" "^4.0.0" tslib "^2.6.2" -"@aws-sdk/client-ecr@3.839.0", "@aws-sdk/client-ecr@^3": - version "3.839.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-ecr/-/client-ecr-3.839.0.tgz#5e03b871124b015b303513929eac64fad8d8ca6f" - integrity sha512-aaSPaqfWvz9OAGfcl97Ps/bQHulRLt8tg8tB8zc4gyGo4OTn6gnKMd+FEhPBszRKP7xeb4pzjjqcXvHsFt7HEQ== +"@aws-sdk/client-ecr@^3", "@aws-sdk/client-ecr@^3.846.0": + version "3.846.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-ecr/-/client-ecr-3.846.0.tgz#567bdfadc5f20872c282b82fe25c6b42ffb2bbd1" + integrity sha512-MzPUMgtvJuhXjJPjQEncs0nCY9uE0423IG+hecSqqo5sIi1c0x74THcYpSbSVgmnbaj/FqcKGRE3pYdDYiSfEA== dependencies: "@aws-crypto/sha256-browser" "5.2.0" "@aws-crypto/sha256-js" "5.2.0" - "@aws-sdk/core" "3.839.0" - "@aws-sdk/credential-provider-node" "3.839.0" - "@aws-sdk/middleware-host-header" "3.821.0" - "@aws-sdk/middleware-logger" "3.821.0" - "@aws-sdk/middleware-recursion-detection" "3.821.0" - "@aws-sdk/middleware-user-agent" "3.839.0" - "@aws-sdk/region-config-resolver" "3.821.0" - "@aws-sdk/types" "3.821.0" - "@aws-sdk/util-endpoints" "3.828.0" - "@aws-sdk/util-user-agent-browser" "3.821.0" - "@aws-sdk/util-user-agent-node" "3.839.0" + "@aws-sdk/core" "3.846.0" + "@aws-sdk/credential-provider-node" "3.846.0" + "@aws-sdk/middleware-host-header" "3.840.0" + "@aws-sdk/middleware-logger" "3.840.0" + "@aws-sdk/middleware-recursion-detection" "3.840.0" + "@aws-sdk/middleware-user-agent" "3.846.0" + "@aws-sdk/region-config-resolver" "3.840.0" + "@aws-sdk/types" "3.840.0" + "@aws-sdk/util-endpoints" "3.845.0" + "@aws-sdk/util-user-agent-browser" "3.840.0" + "@aws-sdk/util-user-agent-node" "3.846.0" "@smithy/config-resolver" "^4.1.4" - "@smithy/core" "^3.6.0" - "@smithy/fetch-http-handler" "^5.0.4" + "@smithy/core" "^3.7.0" + "@smithy/fetch-http-handler" "^5.1.0" "@smithy/hash-node" "^4.0.4" "@smithy/invalid-dependency" "^4.0.4" "@smithy/middleware-content-length" "^4.0.4" - "@smithy/middleware-endpoint" "^4.1.13" - "@smithy/middleware-retry" "^4.1.14" + "@smithy/middleware-endpoint" "^4.1.15" + "@smithy/middleware-retry" "^4.1.16" "@smithy/middleware-serde" "^4.0.8" "@smithy/middleware-stack" "^4.0.4" "@smithy/node-config-provider" "^4.1.3" - "@smithy/node-http-handler" "^4.0.6" + "@smithy/node-http-handler" "^4.1.0" "@smithy/protocol-http" "^5.1.2" - "@smithy/smithy-client" "^4.4.5" + "@smithy/smithy-client" "^4.4.7" "@smithy/types" "^4.3.1" "@smithy/url-parser" "^4.0.4" "@smithy/util-base64" "^4.0.0" "@smithy/util-body-length-browser" "^4.0.0" "@smithy/util-body-length-node" "^4.0.0" - "@smithy/util-defaults-mode-browser" "^4.0.21" - "@smithy/util-defaults-mode-node" "^4.0.21" + "@smithy/util-defaults-mode-browser" "^4.0.23" + "@smithy/util-defaults-mode-node" "^4.0.23" "@smithy/util-endpoints" "^3.0.6" "@smithy/util-middleware" "^4.0.4" "@smithy/util-retry" "^4.0.6" @@ -693,45 +701,45 @@ "@smithy/util-waiter" "^4.0.6" tslib "^2.6.2" -"@aws-sdk/client-ecs@3.839.0", "@aws-sdk/client-ecs@^3": - version "3.839.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-ecs/-/client-ecs-3.839.0.tgz#78ae65e0b48531510f559421df2c4aa8947c7eb3" - integrity sha512-mIfXE7XD7fFZb9D/yr5XqhPla7HCTP0WOLqJtocm18WFAK3zseSQzx8kuOH7mL65rmenTbZGY5nhG1sKZPmV8w== +"@aws-sdk/client-ecs@^3", "@aws-sdk/client-ecs@^3.846.0": + version "3.846.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-ecs/-/client-ecs-3.846.0.tgz#4965065516036f53868da9b9ae6fba38a80ace89" + integrity sha512-abNPxnsHGWQhYKBJBf7ql/weJflSKMAUKEPJ38GEyyKu8D3rnOt/wNQPHw0n9az1EKD+yKTFvgaZwIvLSrjP3w== dependencies: "@aws-crypto/sha256-browser" "5.2.0" "@aws-crypto/sha256-js" "5.2.0" - "@aws-sdk/core" "3.839.0" - "@aws-sdk/credential-provider-node" "3.839.0" - "@aws-sdk/middleware-host-header" "3.821.0" - "@aws-sdk/middleware-logger" "3.821.0" - "@aws-sdk/middleware-recursion-detection" "3.821.0" - "@aws-sdk/middleware-user-agent" "3.839.0" - "@aws-sdk/region-config-resolver" "3.821.0" - "@aws-sdk/types" "3.821.0" - "@aws-sdk/util-endpoints" "3.828.0" - "@aws-sdk/util-user-agent-browser" "3.821.0" - "@aws-sdk/util-user-agent-node" "3.839.0" + "@aws-sdk/core" "3.846.0" + "@aws-sdk/credential-provider-node" "3.846.0" + "@aws-sdk/middleware-host-header" "3.840.0" + "@aws-sdk/middleware-logger" "3.840.0" + "@aws-sdk/middleware-recursion-detection" "3.840.0" + "@aws-sdk/middleware-user-agent" "3.846.0" + "@aws-sdk/region-config-resolver" "3.840.0" + "@aws-sdk/types" "3.840.0" + "@aws-sdk/util-endpoints" "3.845.0" + "@aws-sdk/util-user-agent-browser" "3.840.0" + "@aws-sdk/util-user-agent-node" "3.846.0" "@smithy/config-resolver" "^4.1.4" - "@smithy/core" "^3.6.0" - "@smithy/fetch-http-handler" "^5.0.4" + "@smithy/core" "^3.7.0" + "@smithy/fetch-http-handler" "^5.1.0" "@smithy/hash-node" "^4.0.4" "@smithy/invalid-dependency" "^4.0.4" "@smithy/middleware-content-length" "^4.0.4" - "@smithy/middleware-endpoint" "^4.1.13" - "@smithy/middleware-retry" "^4.1.14" + "@smithy/middleware-endpoint" "^4.1.15" + "@smithy/middleware-retry" "^4.1.16" "@smithy/middleware-serde" "^4.0.8" "@smithy/middleware-stack" "^4.0.4" "@smithy/node-config-provider" "^4.1.3" - "@smithy/node-http-handler" "^4.0.6" + "@smithy/node-http-handler" "^4.1.0" "@smithy/protocol-http" "^5.1.2" - "@smithy/smithy-client" "^4.4.5" + "@smithy/smithy-client" "^4.4.7" "@smithy/types" "^4.3.1" "@smithy/url-parser" "^4.0.4" "@smithy/util-base64" "^4.0.0" "@smithy/util-body-length-browser" "^4.0.0" "@smithy/util-body-length-node" "^4.0.0" - "@smithy/util-defaults-mode-browser" "^4.0.21" - "@smithy/util-defaults-mode-node" "^4.0.21" + "@smithy/util-defaults-mode-browser" "^4.0.23" + "@smithy/util-defaults-mode-node" "^4.0.23" "@smithy/util-endpoints" "^3.0.6" "@smithy/util-middleware" "^4.0.4" "@smithy/util-retry" "^4.0.6" @@ -742,44 +750,44 @@ uuid "^9.0.1" "@aws-sdk/client-elastic-load-balancing-v2@^3": - version "3.839.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-elastic-load-balancing-v2/-/client-elastic-load-balancing-v2-3.839.0.tgz#797cef93c09b8633063e126cfa552c3706a53bb4" - integrity sha512-ps3yLiXzZ605vhp/GnkU/I2Da3MWh2CNJxE/Bc1Dhgixft2swPYmJWF9wyzungisE2i4SzEQ7K4rfsMORQE+9Q== + version "3.846.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-elastic-load-balancing-v2/-/client-elastic-load-balancing-v2-3.846.0.tgz#0efff969a6e81d7a7870bf40b3bb330fc88c3e29" + integrity sha512-39srdO1zlEm2MKhEF93CrwG73sytQpc0c/iQ26XssLqN2b9+WS5jEwLKV28XhYh8F8BYNtzgI8LFM6QJGY1JpA== dependencies: "@aws-crypto/sha256-browser" "5.2.0" "@aws-crypto/sha256-js" "5.2.0" - "@aws-sdk/core" "3.839.0" - "@aws-sdk/credential-provider-node" "3.839.0" - "@aws-sdk/middleware-host-header" "3.821.0" - "@aws-sdk/middleware-logger" "3.821.0" - "@aws-sdk/middleware-recursion-detection" "3.821.0" - "@aws-sdk/middleware-user-agent" "3.839.0" - "@aws-sdk/region-config-resolver" "3.821.0" - "@aws-sdk/types" "3.821.0" - "@aws-sdk/util-endpoints" "3.828.0" - "@aws-sdk/util-user-agent-browser" "3.821.0" - "@aws-sdk/util-user-agent-node" "3.839.0" + "@aws-sdk/core" "3.846.0" + "@aws-sdk/credential-provider-node" "3.846.0" + "@aws-sdk/middleware-host-header" "3.840.0" + "@aws-sdk/middleware-logger" "3.840.0" + "@aws-sdk/middleware-recursion-detection" "3.840.0" + "@aws-sdk/middleware-user-agent" "3.846.0" + "@aws-sdk/region-config-resolver" "3.840.0" + "@aws-sdk/types" "3.840.0" + "@aws-sdk/util-endpoints" "3.845.0" + "@aws-sdk/util-user-agent-browser" "3.840.0" + "@aws-sdk/util-user-agent-node" "3.846.0" "@smithy/config-resolver" "^4.1.4" - "@smithy/core" "^3.6.0" - "@smithy/fetch-http-handler" "^5.0.4" + "@smithy/core" "^3.7.0" + "@smithy/fetch-http-handler" "^5.1.0" "@smithy/hash-node" "^4.0.4" "@smithy/invalid-dependency" "^4.0.4" "@smithy/middleware-content-length" "^4.0.4" - "@smithy/middleware-endpoint" "^4.1.13" - "@smithy/middleware-retry" "^4.1.14" + "@smithy/middleware-endpoint" "^4.1.15" + "@smithy/middleware-retry" "^4.1.16" "@smithy/middleware-serde" "^4.0.8" "@smithy/middleware-stack" "^4.0.4" "@smithy/node-config-provider" "^4.1.3" - "@smithy/node-http-handler" "^4.0.6" + "@smithy/node-http-handler" "^4.1.0" "@smithy/protocol-http" "^5.1.2" - "@smithy/smithy-client" "^4.4.5" + "@smithy/smithy-client" "^4.4.7" "@smithy/types" "^4.3.1" "@smithy/url-parser" "^4.0.4" "@smithy/util-base64" "^4.0.0" "@smithy/util-body-length-browser" "^4.0.0" "@smithy/util-body-length-node" "^4.0.0" - "@smithy/util-defaults-mode-browser" "^4.0.21" - "@smithy/util-defaults-mode-node" "^4.0.21" + "@smithy/util-defaults-mode-browser" "^4.0.23" + "@smithy/util-defaults-mode-node" "^4.0.23" "@smithy/util-endpoints" "^3.0.6" "@smithy/util-middleware" "^4.0.4" "@smithy/util-retry" "^4.0.6" @@ -787,45 +795,45 @@ "@smithy/util-waiter" "^4.0.6" tslib "^2.6.2" -"@aws-sdk/client-iam@3.839.0", "@aws-sdk/client-iam@^3": - version "3.839.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-iam/-/client-iam-3.839.0.tgz#8432b8cb4368f30bf971b922f7468e11c75e4916" - integrity sha512-Y8P4p5xkkEtnizUqJvBplRp4Ehl/kQRaKAmZCX2j1neOeOCofyqKK4zkovMhU8/Yu2zo3p4/ztyOSaMNYZpQZQ== +"@aws-sdk/client-iam@^3", "@aws-sdk/client-iam@^3.846.0": + version "3.846.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-iam/-/client-iam-3.846.0.tgz#43e77f080138f23caab5c9571eaf7255225153e2" + integrity sha512-P7ActDcZepqObChRq8L1gR2E64EsZV/sY1r1er8gkOHMk72LaNfhGcgyNeIrvDTp1BiQ5sPNt82z1dSDoJnooA== dependencies: "@aws-crypto/sha256-browser" "5.2.0" "@aws-crypto/sha256-js" "5.2.0" - "@aws-sdk/core" "3.839.0" - "@aws-sdk/credential-provider-node" "3.839.0" - "@aws-sdk/middleware-host-header" "3.821.0" - "@aws-sdk/middleware-logger" "3.821.0" - "@aws-sdk/middleware-recursion-detection" "3.821.0" - "@aws-sdk/middleware-user-agent" "3.839.0" - "@aws-sdk/region-config-resolver" "3.821.0" - "@aws-sdk/types" "3.821.0" - "@aws-sdk/util-endpoints" "3.828.0" - "@aws-sdk/util-user-agent-browser" "3.821.0" - "@aws-sdk/util-user-agent-node" "3.839.0" + "@aws-sdk/core" "3.846.0" + "@aws-sdk/credential-provider-node" "3.846.0" + "@aws-sdk/middleware-host-header" "3.840.0" + "@aws-sdk/middleware-logger" "3.840.0" + "@aws-sdk/middleware-recursion-detection" "3.840.0" + "@aws-sdk/middleware-user-agent" "3.846.0" + "@aws-sdk/region-config-resolver" "3.840.0" + "@aws-sdk/types" "3.840.0" + "@aws-sdk/util-endpoints" "3.845.0" + "@aws-sdk/util-user-agent-browser" "3.840.0" + "@aws-sdk/util-user-agent-node" "3.846.0" "@smithy/config-resolver" "^4.1.4" - "@smithy/core" "^3.6.0" - "@smithy/fetch-http-handler" "^5.0.4" + "@smithy/core" "^3.7.0" + "@smithy/fetch-http-handler" "^5.1.0" "@smithy/hash-node" "^4.0.4" "@smithy/invalid-dependency" "^4.0.4" "@smithy/middleware-content-length" "^4.0.4" - "@smithy/middleware-endpoint" "^4.1.13" - "@smithy/middleware-retry" "^4.1.14" + "@smithy/middleware-endpoint" "^4.1.15" + "@smithy/middleware-retry" "^4.1.16" "@smithy/middleware-serde" "^4.0.8" "@smithy/middleware-stack" "^4.0.4" "@smithy/node-config-provider" "^4.1.3" - "@smithy/node-http-handler" "^4.0.6" + "@smithy/node-http-handler" "^4.1.0" "@smithy/protocol-http" "^5.1.2" - "@smithy/smithy-client" "^4.4.5" + "@smithy/smithy-client" "^4.4.7" "@smithy/types" "^4.3.1" "@smithy/url-parser" "^4.0.4" "@smithy/util-base64" "^4.0.0" "@smithy/util-body-length-browser" "^4.0.0" "@smithy/util-body-length-node" "^4.0.0" - "@smithy/util-defaults-mode-browser" "^4.0.21" - "@smithy/util-defaults-mode-node" "^4.0.21" + "@smithy/util-defaults-mode-browser" "^4.0.23" + "@smithy/util-defaults-mode-node" "^4.0.23" "@smithy/util-endpoints" "^3.0.6" "@smithy/util-middleware" "^4.0.4" "@smithy/util-retry" "^4.0.6" @@ -834,141 +842,141 @@ tslib "^2.6.2" "@aws-sdk/client-kms@^3": - version "3.839.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-kms/-/client-kms-3.839.0.tgz#0826645b7c834358bc5a0ec4181d192e39fb3c7f" - integrity sha512-izh6+CRMa1iJdBiawbQCqvIY+vdna+8/cdKrbNA5st1xzrUQZ6fp0QNXxZ/DqSBMeDJSdlOR6zBZoiI7wMwz0w== + version "3.846.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-kms/-/client-kms-3.846.0.tgz#7ccd4411ae1774fe8ab95e85f40870d56fdc2994" + integrity sha512-5BJhvLsuY+lb/B3AIPu9UmUdMrSC28stJmiWKxz9IHuwjf/3HNP5c4pop08VnMbKavWsvcTujObP6Oq7W9I18A== dependencies: "@aws-crypto/sha256-browser" "5.2.0" "@aws-crypto/sha256-js" "5.2.0" - "@aws-sdk/core" "3.839.0" - "@aws-sdk/credential-provider-node" "3.839.0" - "@aws-sdk/middleware-host-header" "3.821.0" - "@aws-sdk/middleware-logger" "3.821.0" - "@aws-sdk/middleware-recursion-detection" "3.821.0" - "@aws-sdk/middleware-user-agent" "3.839.0" - "@aws-sdk/region-config-resolver" "3.821.0" - "@aws-sdk/types" "3.821.0" - "@aws-sdk/util-endpoints" "3.828.0" - "@aws-sdk/util-user-agent-browser" "3.821.0" - "@aws-sdk/util-user-agent-node" "3.839.0" + "@aws-sdk/core" "3.846.0" + "@aws-sdk/credential-provider-node" "3.846.0" + "@aws-sdk/middleware-host-header" "3.840.0" + "@aws-sdk/middleware-logger" "3.840.0" + "@aws-sdk/middleware-recursion-detection" "3.840.0" + "@aws-sdk/middleware-user-agent" "3.846.0" + "@aws-sdk/region-config-resolver" "3.840.0" + "@aws-sdk/types" "3.840.0" + "@aws-sdk/util-endpoints" "3.845.0" + "@aws-sdk/util-user-agent-browser" "3.840.0" + "@aws-sdk/util-user-agent-node" "3.846.0" "@smithy/config-resolver" "^4.1.4" - "@smithy/core" "^3.6.0" - "@smithy/fetch-http-handler" "^5.0.4" + "@smithy/core" "^3.7.0" + "@smithy/fetch-http-handler" "^5.1.0" "@smithy/hash-node" "^4.0.4" "@smithy/invalid-dependency" "^4.0.4" "@smithy/middleware-content-length" "^4.0.4" - "@smithy/middleware-endpoint" "^4.1.13" - "@smithy/middleware-retry" "^4.1.14" + "@smithy/middleware-endpoint" "^4.1.15" + "@smithy/middleware-retry" "^4.1.16" "@smithy/middleware-serde" "^4.0.8" "@smithy/middleware-stack" "^4.0.4" "@smithy/node-config-provider" "^4.1.3" - "@smithy/node-http-handler" "^4.0.6" + "@smithy/node-http-handler" "^4.1.0" "@smithy/protocol-http" "^5.1.2" - "@smithy/smithy-client" "^4.4.5" + "@smithy/smithy-client" "^4.4.7" "@smithy/types" "^4.3.1" "@smithy/url-parser" "^4.0.4" "@smithy/util-base64" "^4.0.0" "@smithy/util-body-length-browser" "^4.0.0" "@smithy/util-body-length-node" "^4.0.0" - "@smithy/util-defaults-mode-browser" "^4.0.21" - "@smithy/util-defaults-mode-node" "^4.0.21" + "@smithy/util-defaults-mode-browser" "^4.0.23" + "@smithy/util-defaults-mode-node" "^4.0.23" "@smithy/util-endpoints" "^3.0.6" "@smithy/util-middleware" "^4.0.4" "@smithy/util-retry" "^4.0.6" "@smithy/util-utf8" "^4.0.0" tslib "^2.6.2" -"@aws-sdk/client-lambda@3.839.0", "@aws-sdk/client-lambda@^3": - version "3.839.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-lambda/-/client-lambda-3.839.0.tgz#81d10bcffc775807194d5735b72668b5e9d5eecb" - integrity sha512-i3umPgrz8WqGEzRXDIvbS+aANDSfNtDh1N6G5ESFmws2I2bFT9C748fJK91ALs35q7v+KcPRYVGObGekoZMV1A== +"@aws-sdk/client-lambda@^3", "@aws-sdk/client-lambda@^3.846.0": + version "3.846.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-lambda/-/client-lambda-3.846.0.tgz#b20f51e790a21136748f75c2961223756a2e1cdc" + integrity sha512-kMOr1XjKXZyazfXhEyYFz8t2Tx/fT/93GVb2arHAd1KZvFaydUmN618SnHlmFnvFEZYc4WQrSi9Eh+3YBOLbhw== dependencies: "@aws-crypto/sha256-browser" "5.2.0" "@aws-crypto/sha256-js" "5.2.0" - "@aws-sdk/core" "3.839.0" - "@aws-sdk/credential-provider-node" "3.839.0" - "@aws-sdk/middleware-host-header" "3.821.0" - "@aws-sdk/middleware-logger" "3.821.0" - "@aws-sdk/middleware-recursion-detection" "3.821.0" - "@aws-sdk/middleware-user-agent" "3.839.0" - "@aws-sdk/region-config-resolver" "3.821.0" - "@aws-sdk/types" "3.821.0" - "@aws-sdk/util-endpoints" "3.828.0" - "@aws-sdk/util-user-agent-browser" "3.821.0" - "@aws-sdk/util-user-agent-node" "3.839.0" + "@aws-sdk/core" "3.846.0" + "@aws-sdk/credential-provider-node" "3.846.0" + "@aws-sdk/middleware-host-header" "3.840.0" + "@aws-sdk/middleware-logger" "3.840.0" + "@aws-sdk/middleware-recursion-detection" "3.840.0" + "@aws-sdk/middleware-user-agent" "3.846.0" + "@aws-sdk/region-config-resolver" "3.840.0" + "@aws-sdk/types" "3.840.0" + "@aws-sdk/util-endpoints" "3.845.0" + "@aws-sdk/util-user-agent-browser" "3.840.0" + "@aws-sdk/util-user-agent-node" "3.846.0" "@smithy/config-resolver" "^4.1.4" - "@smithy/core" "^3.6.0" + "@smithy/core" "^3.7.0" "@smithy/eventstream-serde-browser" "^4.0.4" "@smithy/eventstream-serde-config-resolver" "^4.1.2" "@smithy/eventstream-serde-node" "^4.0.4" - "@smithy/fetch-http-handler" "^5.0.4" + "@smithy/fetch-http-handler" "^5.1.0" "@smithy/hash-node" "^4.0.4" "@smithy/invalid-dependency" "^4.0.4" "@smithy/middleware-content-length" "^4.0.4" - "@smithy/middleware-endpoint" "^4.1.13" - "@smithy/middleware-retry" "^4.1.14" + "@smithy/middleware-endpoint" "^4.1.15" + "@smithy/middleware-retry" "^4.1.16" "@smithy/middleware-serde" "^4.0.8" "@smithy/middleware-stack" "^4.0.4" "@smithy/node-config-provider" "^4.1.3" - "@smithy/node-http-handler" "^4.0.6" + "@smithy/node-http-handler" "^4.1.0" "@smithy/protocol-http" "^5.1.2" - "@smithy/smithy-client" "^4.4.5" + "@smithy/smithy-client" "^4.4.7" "@smithy/types" "^4.3.1" "@smithy/url-parser" "^4.0.4" "@smithy/util-base64" "^4.0.0" "@smithy/util-body-length-browser" "^4.0.0" "@smithy/util-body-length-node" "^4.0.0" - "@smithy/util-defaults-mode-browser" "^4.0.21" - "@smithy/util-defaults-mode-node" "^4.0.21" + "@smithy/util-defaults-mode-browser" "^4.0.23" + "@smithy/util-defaults-mode-node" "^4.0.23" "@smithy/util-endpoints" "^3.0.6" "@smithy/util-middleware" "^4.0.4" "@smithy/util-retry" "^4.0.6" - "@smithy/util-stream" "^4.2.2" + "@smithy/util-stream" "^4.2.3" "@smithy/util-utf8" "^4.0.0" "@smithy/util-waiter" "^4.0.6" tslib "^2.6.2" "@aws-sdk/client-route-53@^3": - version "3.839.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-route-53/-/client-route-53-3.839.0.tgz#f311c659b80004587152d007699bc095cb7c5ac2" - integrity sha512-P2Qwa207QvE8HjDnVTfKT8iPftpEptbKJH8jnQtDtgqKe/bZ25M9xmf6RYfJPO6/XGZmT/UR7m1dqUKFbElG+A== + version "3.846.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-route-53/-/client-route-53-3.846.0.tgz#fa2a5ec22fc3f57277fa9ef7d0011679ba5b6da5" + integrity sha512-8SH+NHkOytY0fL25iPNt2ITZ5mORRbSGvCnoGbb5NgtpTjK2lQE9kPYfeAPqrFN38jso7bru2bMBOtIIASsSPg== dependencies: "@aws-crypto/sha256-browser" "5.2.0" "@aws-crypto/sha256-js" "5.2.0" - "@aws-sdk/core" "3.839.0" - "@aws-sdk/credential-provider-node" "3.839.0" - "@aws-sdk/middleware-host-header" "3.821.0" - "@aws-sdk/middleware-logger" "3.821.0" - "@aws-sdk/middleware-recursion-detection" "3.821.0" - "@aws-sdk/middleware-sdk-route53" "3.821.0" - "@aws-sdk/middleware-user-agent" "3.839.0" - "@aws-sdk/region-config-resolver" "3.821.0" - "@aws-sdk/types" "3.821.0" - "@aws-sdk/util-endpoints" "3.828.0" - "@aws-sdk/util-user-agent-browser" "3.821.0" - "@aws-sdk/util-user-agent-node" "3.839.0" + "@aws-sdk/core" "3.846.0" + "@aws-sdk/credential-provider-node" "3.846.0" + "@aws-sdk/middleware-host-header" "3.840.0" + "@aws-sdk/middleware-logger" "3.840.0" + "@aws-sdk/middleware-recursion-detection" "3.840.0" + "@aws-sdk/middleware-sdk-route53" "3.840.0" + "@aws-sdk/middleware-user-agent" "3.846.0" + "@aws-sdk/region-config-resolver" "3.840.0" + "@aws-sdk/types" "3.840.0" + "@aws-sdk/util-endpoints" "3.845.0" + "@aws-sdk/util-user-agent-browser" "3.840.0" + "@aws-sdk/util-user-agent-node" "3.846.0" "@aws-sdk/xml-builder" "3.821.0" "@smithy/config-resolver" "^4.1.4" - "@smithy/core" "^3.6.0" - "@smithy/fetch-http-handler" "^5.0.4" + "@smithy/core" "^3.7.0" + "@smithy/fetch-http-handler" "^5.1.0" "@smithy/hash-node" "^4.0.4" "@smithy/invalid-dependency" "^4.0.4" "@smithy/middleware-content-length" "^4.0.4" - "@smithy/middleware-endpoint" "^4.1.13" - "@smithy/middleware-retry" "^4.1.14" + "@smithy/middleware-endpoint" "^4.1.15" + "@smithy/middleware-retry" "^4.1.16" "@smithy/middleware-serde" "^4.0.8" "@smithy/middleware-stack" "^4.0.4" "@smithy/node-config-provider" "^4.1.3" - "@smithy/node-http-handler" "^4.0.6" + "@smithy/node-http-handler" "^4.1.0" "@smithy/protocol-http" "^5.1.2" - "@smithy/smithy-client" "^4.4.5" + "@smithy/smithy-client" "^4.4.7" "@smithy/types" "^4.3.1" "@smithy/url-parser" "^4.0.4" "@smithy/util-base64" "^4.0.0" "@smithy/util-body-length-browser" "^4.0.0" "@smithy/util-body-length-node" "^4.0.0" - "@smithy/util-defaults-mode-browser" "^4.0.21" - "@smithy/util-defaults-mode-node" "^4.0.21" + "@smithy/util-defaults-mode-browser" "^4.0.23" + "@smithy/util-defaults-mode-node" "^4.0.23" "@smithy/util-endpoints" "^3.0.6" "@smithy/util-middleware" "^4.0.4" "@smithy/util-retry" "^4.0.6" @@ -976,109 +984,109 @@ "@smithy/util-waiter" "^4.0.6" tslib "^2.6.2" -"@aws-sdk/client-s3@3.839.0", "@aws-sdk/client-s3@^3", "@aws-sdk/client-s3@^3.839.0": - version "3.839.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-s3/-/client-s3-3.839.0.tgz#91499477dd3ca1ef87cfe430cae3e2d74492aabf" - integrity sha512-7zDInY+qltKxeG+9d/97nbs+FWINcAi5bChBrleUQkuQ/dA9pSP1URo/6JlVzD2Ejvksm+hVK6z3VUWZaIAVOw== +"@aws-sdk/client-s3@^3", "@aws-sdk/client-s3@^3.846.0": + version "3.846.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-s3/-/client-s3-3.846.0.tgz#16dd96b4398cf15e0199245100667508ce5bf6eb" + integrity sha512-+C9qRJ7SFN+Bi2DJqfJ73Aj4ORpic9Jk5boosiOZj+TZi6qYHW6TCUqxheiC6JT/0xtE5C7VFIhW/UP/CAh0Tw== dependencies: "@aws-crypto/sha1-browser" "5.2.0" "@aws-crypto/sha256-browser" "5.2.0" "@aws-crypto/sha256-js" "5.2.0" - "@aws-sdk/core" "3.839.0" - "@aws-sdk/credential-provider-node" "3.839.0" - "@aws-sdk/middleware-bucket-endpoint" "3.830.0" - "@aws-sdk/middleware-expect-continue" "3.821.0" - "@aws-sdk/middleware-flexible-checksums" "3.839.0" - "@aws-sdk/middleware-host-header" "3.821.0" - "@aws-sdk/middleware-location-constraint" "3.821.0" - "@aws-sdk/middleware-logger" "3.821.0" - "@aws-sdk/middleware-recursion-detection" "3.821.0" - "@aws-sdk/middleware-sdk-s3" "3.839.0" - "@aws-sdk/middleware-ssec" "3.821.0" - "@aws-sdk/middleware-user-agent" "3.839.0" - "@aws-sdk/region-config-resolver" "3.821.0" - "@aws-sdk/signature-v4-multi-region" "3.839.0" - "@aws-sdk/types" "3.821.0" - "@aws-sdk/util-endpoints" "3.828.0" - "@aws-sdk/util-user-agent-browser" "3.821.0" - "@aws-sdk/util-user-agent-node" "3.839.0" + "@aws-sdk/core" "3.846.0" + "@aws-sdk/credential-provider-node" "3.846.0" + "@aws-sdk/middleware-bucket-endpoint" "3.840.0" + "@aws-sdk/middleware-expect-continue" "3.840.0" + "@aws-sdk/middleware-flexible-checksums" "3.846.0" + "@aws-sdk/middleware-host-header" "3.840.0" + "@aws-sdk/middleware-location-constraint" "3.840.0" + "@aws-sdk/middleware-logger" "3.840.0" + "@aws-sdk/middleware-recursion-detection" "3.840.0" + "@aws-sdk/middleware-sdk-s3" "3.846.0" + "@aws-sdk/middleware-ssec" "3.840.0" + "@aws-sdk/middleware-user-agent" "3.846.0" + "@aws-sdk/region-config-resolver" "3.840.0" + "@aws-sdk/signature-v4-multi-region" "3.846.0" + "@aws-sdk/types" "3.840.0" + "@aws-sdk/util-endpoints" "3.845.0" + "@aws-sdk/util-user-agent-browser" "3.840.0" + "@aws-sdk/util-user-agent-node" "3.846.0" "@aws-sdk/xml-builder" "3.821.0" "@smithy/config-resolver" "^4.1.4" - "@smithy/core" "^3.6.0" + "@smithy/core" "^3.7.0" "@smithy/eventstream-serde-browser" "^4.0.4" "@smithy/eventstream-serde-config-resolver" "^4.1.2" "@smithy/eventstream-serde-node" "^4.0.4" - "@smithy/fetch-http-handler" "^5.0.4" + "@smithy/fetch-http-handler" "^5.1.0" "@smithy/hash-blob-browser" "^4.0.4" "@smithy/hash-node" "^4.0.4" "@smithy/hash-stream-node" "^4.0.4" "@smithy/invalid-dependency" "^4.0.4" "@smithy/md5-js" "^4.0.4" "@smithy/middleware-content-length" "^4.0.4" - "@smithy/middleware-endpoint" "^4.1.13" - "@smithy/middleware-retry" "^4.1.14" + "@smithy/middleware-endpoint" "^4.1.15" + "@smithy/middleware-retry" "^4.1.16" "@smithy/middleware-serde" "^4.0.8" "@smithy/middleware-stack" "^4.0.4" "@smithy/node-config-provider" "^4.1.3" - "@smithy/node-http-handler" "^4.0.6" + "@smithy/node-http-handler" "^4.1.0" "@smithy/protocol-http" "^5.1.2" - "@smithy/smithy-client" "^4.4.5" + "@smithy/smithy-client" "^4.4.7" "@smithy/types" "^4.3.1" "@smithy/url-parser" "^4.0.4" "@smithy/util-base64" "^4.0.0" "@smithy/util-body-length-browser" "^4.0.0" "@smithy/util-body-length-node" "^4.0.0" - "@smithy/util-defaults-mode-browser" "^4.0.21" - "@smithy/util-defaults-mode-node" "^4.0.21" + "@smithy/util-defaults-mode-browser" "^4.0.23" + "@smithy/util-defaults-mode-node" "^4.0.23" "@smithy/util-endpoints" "^3.0.6" "@smithy/util-middleware" "^4.0.4" "@smithy/util-retry" "^4.0.6" - "@smithy/util-stream" "^4.2.2" + "@smithy/util-stream" "^4.2.3" "@smithy/util-utf8" "^4.0.0" "@smithy/util-waiter" "^4.0.6" "@types/uuid" "^9.0.1" tslib "^2.6.2" uuid "^9.0.1" -"@aws-sdk/client-secrets-manager@^3": - version "3.839.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.839.0.tgz#f8c89fc6df9ad6886b9be033f1662a86cdd09d19" - integrity sha512-zBlukvzSX9MLrjUGjlGG5d4TRdmAnsfaNPIQzU0K/F3r7hgdKm848nK81UJgc86pNjud7CQSuk5uMVMyd0HMhg== +"@aws-sdk/client-secrets-manager@^3", "@aws-sdk/client-secrets-manager@^3.846.0": + version "3.846.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.846.0.tgz#d91345d9e5e15b6ff50b95b1390a993c9d09dc84" + integrity sha512-3q4etq0DfxgyHoJacKfLbbWiXVB417SGztTtGmTFZQ2FJuopbdKcMpGuC/IDnUMqViGt8wCMHiIzB2dz2pYsWA== dependencies: "@aws-crypto/sha256-browser" "5.2.0" "@aws-crypto/sha256-js" "5.2.0" - "@aws-sdk/core" "3.839.0" - "@aws-sdk/credential-provider-node" "3.839.0" - "@aws-sdk/middleware-host-header" "3.821.0" - "@aws-sdk/middleware-logger" "3.821.0" - "@aws-sdk/middleware-recursion-detection" "3.821.0" - "@aws-sdk/middleware-user-agent" "3.839.0" - "@aws-sdk/region-config-resolver" "3.821.0" - "@aws-sdk/types" "3.821.0" - "@aws-sdk/util-endpoints" "3.828.0" - "@aws-sdk/util-user-agent-browser" "3.821.0" - "@aws-sdk/util-user-agent-node" "3.839.0" + "@aws-sdk/core" "3.846.0" + "@aws-sdk/credential-provider-node" "3.846.0" + "@aws-sdk/middleware-host-header" "3.840.0" + "@aws-sdk/middleware-logger" "3.840.0" + "@aws-sdk/middleware-recursion-detection" "3.840.0" + "@aws-sdk/middleware-user-agent" "3.846.0" + "@aws-sdk/region-config-resolver" "3.840.0" + "@aws-sdk/types" "3.840.0" + "@aws-sdk/util-endpoints" "3.845.0" + "@aws-sdk/util-user-agent-browser" "3.840.0" + "@aws-sdk/util-user-agent-node" "3.846.0" "@smithy/config-resolver" "^4.1.4" - "@smithy/core" "^3.6.0" - "@smithy/fetch-http-handler" "^5.0.4" + "@smithy/core" "^3.7.0" + "@smithy/fetch-http-handler" "^5.1.0" "@smithy/hash-node" "^4.0.4" "@smithy/invalid-dependency" "^4.0.4" "@smithy/middleware-content-length" "^4.0.4" - "@smithy/middleware-endpoint" "^4.1.13" - "@smithy/middleware-retry" "^4.1.14" + "@smithy/middleware-endpoint" "^4.1.15" + "@smithy/middleware-retry" "^4.1.16" "@smithy/middleware-serde" "^4.0.8" "@smithy/middleware-stack" "^4.0.4" "@smithy/node-config-provider" "^4.1.3" - "@smithy/node-http-handler" "^4.0.6" + "@smithy/node-http-handler" "^4.1.0" "@smithy/protocol-http" "^5.1.2" - "@smithy/smithy-client" "^4.4.5" + "@smithy/smithy-client" "^4.4.7" "@smithy/types" "^4.3.1" "@smithy/url-parser" "^4.0.4" "@smithy/util-base64" "^4.0.0" "@smithy/util-body-length-browser" "^4.0.0" "@smithy/util-body-length-node" "^4.0.0" - "@smithy/util-defaults-mode-browser" "^4.0.21" - "@smithy/util-defaults-mode-node" "^4.0.21" + "@smithy/util-defaults-mode-browser" "^4.0.23" + "@smithy/util-defaults-mode-node" "^4.0.23" "@smithy/util-endpoints" "^3.0.6" "@smithy/util-middleware" "^4.0.4" "@smithy/util-retry" "^4.0.6" @@ -1088,44 +1096,44 @@ uuid "^9.0.1" "@aws-sdk/client-sfn@^3": - version "3.839.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-sfn/-/client-sfn-3.839.0.tgz#5534879db5d47cbe07a36c6d2e101d0f9922a7fd" - integrity sha512-/z64mWj2U1Crx8CAIB9ahsqXOxq4R9WtrWX6ROZJmNun/tzHY8cRkpN1WogrfzMrhaaSzLdITLbs59fSpsjMAA== + version "3.846.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sfn/-/client-sfn-3.846.0.tgz#74cc803d5cbea20011ad45cccedb7e453c00aa95" + integrity sha512-1ttTXB00xZ8HJlj0uCjym8CIPG2fzR93baX07J7B0TBVUaiwBjdTMKWfqoXQqkxnUdQ6dQjLZsChbfYFw7+0iw== dependencies: "@aws-crypto/sha256-browser" "5.2.0" "@aws-crypto/sha256-js" "5.2.0" - "@aws-sdk/core" "3.839.0" - "@aws-sdk/credential-provider-node" "3.839.0" - "@aws-sdk/middleware-host-header" "3.821.0" - "@aws-sdk/middleware-logger" "3.821.0" - "@aws-sdk/middleware-recursion-detection" "3.821.0" - "@aws-sdk/middleware-user-agent" "3.839.0" - "@aws-sdk/region-config-resolver" "3.821.0" - "@aws-sdk/types" "3.821.0" - "@aws-sdk/util-endpoints" "3.828.0" - "@aws-sdk/util-user-agent-browser" "3.821.0" - "@aws-sdk/util-user-agent-node" "3.839.0" + "@aws-sdk/core" "3.846.0" + "@aws-sdk/credential-provider-node" "3.846.0" + "@aws-sdk/middleware-host-header" "3.840.0" + "@aws-sdk/middleware-logger" "3.840.0" + "@aws-sdk/middleware-recursion-detection" "3.840.0" + "@aws-sdk/middleware-user-agent" "3.846.0" + "@aws-sdk/region-config-resolver" "3.840.0" + "@aws-sdk/types" "3.840.0" + "@aws-sdk/util-endpoints" "3.845.0" + "@aws-sdk/util-user-agent-browser" "3.840.0" + "@aws-sdk/util-user-agent-node" "3.846.0" "@smithy/config-resolver" "^4.1.4" - "@smithy/core" "^3.6.0" - "@smithy/fetch-http-handler" "^5.0.4" + "@smithy/core" "^3.7.0" + "@smithy/fetch-http-handler" "^5.1.0" "@smithy/hash-node" "^4.0.4" "@smithy/invalid-dependency" "^4.0.4" "@smithy/middleware-content-length" "^4.0.4" - "@smithy/middleware-endpoint" "^4.1.13" - "@smithy/middleware-retry" "^4.1.14" + "@smithy/middleware-endpoint" "^4.1.15" + "@smithy/middleware-retry" "^4.1.16" "@smithy/middleware-serde" "^4.0.8" "@smithy/middleware-stack" "^4.0.4" "@smithy/node-config-provider" "^4.1.3" - "@smithy/node-http-handler" "^4.0.6" + "@smithy/node-http-handler" "^4.1.0" "@smithy/protocol-http" "^5.1.2" - "@smithy/smithy-client" "^4.4.5" + "@smithy/smithy-client" "^4.4.7" "@smithy/types" "^4.3.1" "@smithy/url-parser" "^4.0.4" "@smithy/util-base64" "^4.0.0" "@smithy/util-body-length-browser" "^4.0.0" "@smithy/util-body-length-node" "^4.0.0" - "@smithy/util-defaults-mode-browser" "^4.0.21" - "@smithy/util-defaults-mode-node" "^4.0.21" + "@smithy/util-defaults-mode-browser" "^4.0.23" + "@smithy/util-defaults-mode-node" "^4.0.23" "@smithy/util-endpoints" "^3.0.6" "@smithy/util-middleware" "^4.0.4" "@smithy/util-retry" "^4.0.6" @@ -1134,45 +1142,45 @@ tslib "^2.6.2" uuid "^9.0.1" -"@aws-sdk/client-sns@3.839.0": - version "3.839.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-sns/-/client-sns-3.839.0.tgz#3900c98a1a95aa43694ac21af905c46e0ccbee0d" - integrity sha512-TOYhuSGe0YOW0CZ9LMpAFKQy7IUrytX7Ge8SLHq0zhv/Eh7Am+r6v0xaeboFVPmMCDNKBhrAnMtC/AixIIDwsQ== +"@aws-sdk/client-sns@^3.846.0": + version "3.846.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sns/-/client-sns-3.846.0.tgz#7d0487abfc58b5408df045270bf1ab681e5b7b46" + integrity sha512-F7sv4Yhy4rel+D7v3AW864U0o8l65NdrdrkTyIqEQDjSkBQHq8uPlSuc2MYIia6RMvBYK59VL+bME4E11Zbklg== dependencies: "@aws-crypto/sha256-browser" "5.2.0" "@aws-crypto/sha256-js" "5.2.0" - "@aws-sdk/core" "3.839.0" - "@aws-sdk/credential-provider-node" "3.839.0" - "@aws-sdk/middleware-host-header" "3.821.0" - "@aws-sdk/middleware-logger" "3.821.0" - "@aws-sdk/middleware-recursion-detection" "3.821.0" - "@aws-sdk/middleware-user-agent" "3.839.0" - "@aws-sdk/region-config-resolver" "3.821.0" - "@aws-sdk/types" "3.821.0" - "@aws-sdk/util-endpoints" "3.828.0" - "@aws-sdk/util-user-agent-browser" "3.821.0" - "@aws-sdk/util-user-agent-node" "3.839.0" + "@aws-sdk/core" "3.846.0" + "@aws-sdk/credential-provider-node" "3.846.0" + "@aws-sdk/middleware-host-header" "3.840.0" + "@aws-sdk/middleware-logger" "3.840.0" + "@aws-sdk/middleware-recursion-detection" "3.840.0" + "@aws-sdk/middleware-user-agent" "3.846.0" + "@aws-sdk/region-config-resolver" "3.840.0" + "@aws-sdk/types" "3.840.0" + "@aws-sdk/util-endpoints" "3.845.0" + "@aws-sdk/util-user-agent-browser" "3.840.0" + "@aws-sdk/util-user-agent-node" "3.846.0" "@smithy/config-resolver" "^4.1.4" - "@smithy/core" "^3.6.0" - "@smithy/fetch-http-handler" "^5.0.4" + "@smithy/core" "^3.7.0" + "@smithy/fetch-http-handler" "^5.1.0" "@smithy/hash-node" "^4.0.4" "@smithy/invalid-dependency" "^4.0.4" "@smithy/middleware-content-length" "^4.0.4" - "@smithy/middleware-endpoint" "^4.1.13" - "@smithy/middleware-retry" "^4.1.14" + "@smithy/middleware-endpoint" "^4.1.15" + "@smithy/middleware-retry" "^4.1.16" "@smithy/middleware-serde" "^4.0.8" "@smithy/middleware-stack" "^4.0.4" "@smithy/node-config-provider" "^4.1.3" - "@smithy/node-http-handler" "^4.0.6" + "@smithy/node-http-handler" "^4.1.0" "@smithy/protocol-http" "^5.1.2" - "@smithy/smithy-client" "^4.4.5" + "@smithy/smithy-client" "^4.4.7" "@smithy/types" "^4.3.1" "@smithy/url-parser" "^4.0.4" "@smithy/util-base64" "^4.0.0" "@smithy/util-body-length-browser" "^4.0.0" "@smithy/util-body-length-node" "^4.0.0" - "@smithy/util-defaults-mode-browser" "^4.0.21" - "@smithy/util-defaults-mode-node" "^4.0.21" + "@smithy/util-defaults-mode-browser" "^4.0.23" + "@smithy/util-defaults-mode-node" "^4.0.23" "@smithy/util-endpoints" "^3.0.6" "@smithy/util-middleware" "^4.0.4" "@smithy/util-retry" "^4.0.6" @@ -1180,44 +1188,44 @@ tslib "^2.6.2" "@aws-sdk/client-ssm@^3": - version "3.839.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-ssm/-/client-ssm-3.839.0.tgz#2181ae7b69233e41dc448c98ccf7326a8a142cca" - integrity sha512-mqV4AL+Y2NxZCd0VPs23ylXNt5rI2yk2APBaWyRXaXREUbUwnZXHizNtrLtvAyOjXfhGiLtMpUdifLAOJxbgcw== + version "3.846.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-ssm/-/client-ssm-3.846.0.tgz#9b449dcf66c72d81fea7373ffaa9626aab817956" + integrity sha512-WKXqVsa7r5n1d9RWdbn49B9YOWytL+ohLPd8uHVClCo5igBC0HhUQM7JwLcFiW93RwO/KGy01fKg3veHigiS6g== dependencies: "@aws-crypto/sha256-browser" "5.2.0" "@aws-crypto/sha256-js" "5.2.0" - "@aws-sdk/core" "3.839.0" - "@aws-sdk/credential-provider-node" "3.839.0" - "@aws-sdk/middleware-host-header" "3.821.0" - "@aws-sdk/middleware-logger" "3.821.0" - "@aws-sdk/middleware-recursion-detection" "3.821.0" - "@aws-sdk/middleware-user-agent" "3.839.0" - "@aws-sdk/region-config-resolver" "3.821.0" - "@aws-sdk/types" "3.821.0" - "@aws-sdk/util-endpoints" "3.828.0" - "@aws-sdk/util-user-agent-browser" "3.821.0" - "@aws-sdk/util-user-agent-node" "3.839.0" + "@aws-sdk/core" "3.846.0" + "@aws-sdk/credential-provider-node" "3.846.0" + "@aws-sdk/middleware-host-header" "3.840.0" + "@aws-sdk/middleware-logger" "3.840.0" + "@aws-sdk/middleware-recursion-detection" "3.840.0" + "@aws-sdk/middleware-user-agent" "3.846.0" + "@aws-sdk/region-config-resolver" "3.840.0" + "@aws-sdk/types" "3.840.0" + "@aws-sdk/util-endpoints" "3.845.0" + "@aws-sdk/util-user-agent-browser" "3.840.0" + "@aws-sdk/util-user-agent-node" "3.846.0" "@smithy/config-resolver" "^4.1.4" - "@smithy/core" "^3.6.0" - "@smithy/fetch-http-handler" "^5.0.4" + "@smithy/core" "^3.7.0" + "@smithy/fetch-http-handler" "^5.1.0" "@smithy/hash-node" "^4.0.4" "@smithy/invalid-dependency" "^4.0.4" "@smithy/middleware-content-length" "^4.0.4" - "@smithy/middleware-endpoint" "^4.1.13" - "@smithy/middleware-retry" "^4.1.14" + "@smithy/middleware-endpoint" "^4.1.15" + "@smithy/middleware-retry" "^4.1.16" "@smithy/middleware-serde" "^4.0.8" "@smithy/middleware-stack" "^4.0.4" "@smithy/node-config-provider" "^4.1.3" - "@smithy/node-http-handler" "^4.0.6" + "@smithy/node-http-handler" "^4.1.0" "@smithy/protocol-http" "^5.1.2" - "@smithy/smithy-client" "^4.4.5" + "@smithy/smithy-client" "^4.4.7" "@smithy/types" "^4.3.1" "@smithy/url-parser" "^4.0.4" "@smithy/util-base64" "^4.0.0" "@smithy/util-body-length-browser" "^4.0.0" "@smithy/util-body-length-node" "^4.0.0" - "@smithy/util-defaults-mode-browser" "^4.0.21" - "@smithy/util-defaults-mode-node" "^4.0.21" + "@smithy/util-defaults-mode-browser" "^4.0.23" + "@smithy/util-defaults-mode-node" "^4.0.23" "@smithy/util-endpoints" "^3.0.6" "@smithy/util-middleware" "^4.0.4" "@smithy/util-retry" "^4.0.6" @@ -1227,89 +1235,89 @@ tslib "^2.6.2" uuid "^9.0.1" -"@aws-sdk/client-sso@3.839.0": - version "3.839.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso/-/client-sso-3.839.0.tgz#d8bf4628a210b0e326c0f3e41218c8ffb01564b1" - integrity sha512-AZABysUhbfcwXVlMo97/vwHgsfJNF81wypCAowpqAJkSjP2KrqsqHpb71/RoR2w8JGmEnBBXRD4wIxDhnmifWg== +"@aws-sdk/client-sso@3.846.0", "@aws-sdk/client-sso@^3.846.0": + version "3.846.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso/-/client-sso-3.846.0.tgz#9905ccf216e371c94ca63b1df19dba923d286307" + integrity sha512-7MgMl3nlwf2ixad5Xe8pFHtcwFchkx37MEvGuB00tn5jyBp3AQQ4dK3iHtj2HjhXcXD0G67zVPvH4/QNOL7/gw== dependencies: "@aws-crypto/sha256-browser" "5.2.0" "@aws-crypto/sha256-js" "5.2.0" - "@aws-sdk/core" "3.839.0" - "@aws-sdk/middleware-host-header" "3.821.0" - "@aws-sdk/middleware-logger" "3.821.0" - "@aws-sdk/middleware-recursion-detection" "3.821.0" - "@aws-sdk/middleware-user-agent" "3.839.0" - "@aws-sdk/region-config-resolver" "3.821.0" - "@aws-sdk/types" "3.821.0" - "@aws-sdk/util-endpoints" "3.828.0" - "@aws-sdk/util-user-agent-browser" "3.821.0" - "@aws-sdk/util-user-agent-node" "3.839.0" + "@aws-sdk/core" "3.846.0" + "@aws-sdk/middleware-host-header" "3.840.0" + "@aws-sdk/middleware-logger" "3.840.0" + "@aws-sdk/middleware-recursion-detection" "3.840.0" + "@aws-sdk/middleware-user-agent" "3.846.0" + "@aws-sdk/region-config-resolver" "3.840.0" + "@aws-sdk/types" "3.840.0" + "@aws-sdk/util-endpoints" "3.845.0" + "@aws-sdk/util-user-agent-browser" "3.840.0" + "@aws-sdk/util-user-agent-node" "3.846.0" "@smithy/config-resolver" "^4.1.4" - "@smithy/core" "^3.6.0" - "@smithy/fetch-http-handler" "^5.0.4" + "@smithy/core" "^3.7.0" + "@smithy/fetch-http-handler" "^5.1.0" "@smithy/hash-node" "^4.0.4" "@smithy/invalid-dependency" "^4.0.4" "@smithy/middleware-content-length" "^4.0.4" - "@smithy/middleware-endpoint" "^4.1.13" - "@smithy/middleware-retry" "^4.1.14" + "@smithy/middleware-endpoint" "^4.1.15" + "@smithy/middleware-retry" "^4.1.16" "@smithy/middleware-serde" "^4.0.8" "@smithy/middleware-stack" "^4.0.4" "@smithy/node-config-provider" "^4.1.3" - "@smithy/node-http-handler" "^4.0.6" + "@smithy/node-http-handler" "^4.1.0" "@smithy/protocol-http" "^5.1.2" - "@smithy/smithy-client" "^4.4.5" + "@smithy/smithy-client" "^4.4.7" "@smithy/types" "^4.3.1" "@smithy/url-parser" "^4.0.4" "@smithy/util-base64" "^4.0.0" "@smithy/util-body-length-browser" "^4.0.0" "@smithy/util-body-length-node" "^4.0.0" - "@smithy/util-defaults-mode-browser" "^4.0.21" - "@smithy/util-defaults-mode-node" "^4.0.21" + "@smithy/util-defaults-mode-browser" "^4.0.23" + "@smithy/util-defaults-mode-node" "^4.0.23" "@smithy/util-endpoints" "^3.0.6" "@smithy/util-middleware" "^4.0.4" "@smithy/util-retry" "^4.0.6" "@smithy/util-utf8" "^4.0.0" tslib "^2.6.2" -"@aws-sdk/client-sts@3.839.0", "@aws-sdk/client-sts@^3": - version "3.839.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-sts/-/client-sts-3.839.0.tgz#e86af1465209d37748c833d08fb5351d89e77557" - integrity sha512-R9Tg10Pdb1ue4IftYYw+pQegXUxQ5yYwthynvpBrByQHFiD8bKetVh/+J4zXduOD9usFJwWFYfh9zPmTIADG+A== +"@aws-sdk/client-sts@^3", "@aws-sdk/client-sts@^3.846.0": + version "3.846.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sts/-/client-sts-3.846.0.tgz#5278a19c56e7a289cfac5e27dc5635e0cc96ef89" + integrity sha512-DYvQvySC2kIK0llIedGXXIybrSTWEYg7KEoZQ1FrHxK9Q/xeLtj2AUvPrQ3GDiwif9DQcNZ1OgjDH+nJ7LqCZA== dependencies: "@aws-crypto/sha256-browser" "5.2.0" "@aws-crypto/sha256-js" "5.2.0" - "@aws-sdk/core" "3.839.0" - "@aws-sdk/credential-provider-node" "3.839.0" - "@aws-sdk/middleware-host-header" "3.821.0" - "@aws-sdk/middleware-logger" "3.821.0" - "@aws-sdk/middleware-recursion-detection" "3.821.0" - "@aws-sdk/middleware-user-agent" "3.839.0" - "@aws-sdk/region-config-resolver" "3.821.0" - "@aws-sdk/types" "3.821.0" - "@aws-sdk/util-endpoints" "3.828.0" - "@aws-sdk/util-user-agent-browser" "3.821.0" - "@aws-sdk/util-user-agent-node" "3.839.0" + "@aws-sdk/core" "3.846.0" + "@aws-sdk/credential-provider-node" "3.846.0" + "@aws-sdk/middleware-host-header" "3.840.0" + "@aws-sdk/middleware-logger" "3.840.0" + "@aws-sdk/middleware-recursion-detection" "3.840.0" + "@aws-sdk/middleware-user-agent" "3.846.0" + "@aws-sdk/region-config-resolver" "3.840.0" + "@aws-sdk/types" "3.840.0" + "@aws-sdk/util-endpoints" "3.845.0" + "@aws-sdk/util-user-agent-browser" "3.840.0" + "@aws-sdk/util-user-agent-node" "3.846.0" "@smithy/config-resolver" "^4.1.4" - "@smithy/core" "^3.6.0" - "@smithy/fetch-http-handler" "^5.0.4" + "@smithy/core" "^3.7.0" + "@smithy/fetch-http-handler" "^5.1.0" "@smithy/hash-node" "^4.0.4" "@smithy/invalid-dependency" "^4.0.4" "@smithy/middleware-content-length" "^4.0.4" - "@smithy/middleware-endpoint" "^4.1.13" - "@smithy/middleware-retry" "^4.1.14" + "@smithy/middleware-endpoint" "^4.1.15" + "@smithy/middleware-retry" "^4.1.16" "@smithy/middleware-serde" "^4.0.8" "@smithy/middleware-stack" "^4.0.4" "@smithy/node-config-provider" "^4.1.3" - "@smithy/node-http-handler" "^4.0.6" + "@smithy/node-http-handler" "^4.1.0" "@smithy/protocol-http" "^5.1.2" - "@smithy/smithy-client" "^4.4.5" + "@smithy/smithy-client" "^4.4.7" "@smithy/types" "^4.3.1" "@smithy/url-parser" "^4.0.4" "@smithy/util-base64" "^4.0.0" "@smithy/util-body-length-browser" "^4.0.0" "@smithy/util-body-length-node" "^4.0.0" - "@smithy/util-defaults-mode-browser" "^4.0.21" - "@smithy/util-defaults-mode-node" "^4.0.21" + "@smithy/util-defaults-mode-browser" "^4.0.23" + "@smithy/util-defaults-mode-node" "^4.0.23" "@smithy/util-endpoints" "^3.0.6" "@smithy/util-middleware" "^4.0.4" "@smithy/util-retry" "^4.0.6" @@ -1324,34 +1332,34 @@ "@aws-sdk/signature-v4" "3.0.0" tslib "^1.8.0" -"@aws-sdk/core@3.839.0": - version "3.839.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/core/-/core-3.839.0.tgz#dd841b3c331ca99c6c1d096184ea50b8f168fec4" - integrity sha512-KdwL5RaK7eUIlOpdOoZ5u+2t4X1rdX/MTZgz3IV/aBzjVUoGsp+uUnbyqXomLQSUitPHp72EE/NHDsvWW/IHvQ== +"@aws-sdk/core@3.846.0": + version "3.846.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/core/-/core-3.846.0.tgz#f226d7d4f9b25f31dfda260f7ef1f4de8e4314fa" + integrity sha512-7CX0pM906r4WSS68fCTNMTtBCSkTtf3Wggssmx13gD40gcWEZXsU00KzPp1bYheNRyPlAq3rE22xt4wLPXbuxA== dependencies: - "@aws-sdk/types" "3.821.0" + "@aws-sdk/types" "3.840.0" "@aws-sdk/xml-builder" "3.821.0" - "@smithy/core" "^3.6.0" + "@smithy/core" "^3.7.0" "@smithy/node-config-provider" "^4.1.3" "@smithy/property-provider" "^4.0.4" "@smithy/protocol-http" "^5.1.2" "@smithy/signature-v4" "^5.1.2" - "@smithy/smithy-client" "^4.4.5" + "@smithy/smithy-client" "^4.4.7" "@smithy/types" "^4.3.1" "@smithy/util-base64" "^4.0.0" "@smithy/util-body-length-browser" "^4.0.0" "@smithy/util-middleware" "^4.0.4" "@smithy/util-utf8" "^4.0.0" - fast-xml-parser "4.4.1" + fast-xml-parser "5.2.5" tslib "^2.6.2" -"@aws-sdk/credential-provider-cognito-identity@3.839.0": - version "3.839.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.839.0.tgz#71c06e0e329e7d42d6b7fef8994ab6a87e3d6b03" - integrity sha512-dXJsdSEVzG+8nIihqVnWzyW8Dc41kNKZEXYguHDb+VM/cIjRSVkaw9jXc+KAvbwcGkEB7BfAuW9VMjxpTR5eAA== +"@aws-sdk/credential-provider-cognito-identity@3.846.0": + version "3.846.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.846.0.tgz#61c09e6a3ccf325991f2e335378fd40d6018f44b" + integrity sha512-zfcNFUK0QC7czR/n3ATMp3ZWkMrGZzJ1mS/sTezjFg1IupFnogyF+8xKmnmqXiABJd1yE8FduYgw8yx0ZSWiCw== dependencies: - "@aws-sdk/client-cognito-identity" "3.839.0" - "@aws-sdk/types" "3.821.0" + "@aws-sdk/client-cognito-identity" "3.846.0" + "@aws-sdk/types" "3.840.0" "@smithy/property-provider" "^4.0.4" "@smithy/types" "^4.3.1" tslib "^2.6.2" @@ -1364,31 +1372,31 @@ "@aws-sdk/property-provider" "3.0.0" tslib "^1.8.0" -"@aws-sdk/credential-provider-env@3.839.0": - version "3.839.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.839.0.tgz#0102470388f1939206a80d8a7398047b380378bc" - integrity sha512-cWTadewPPz1OvObZJB+olrgh8VwcgIVcT293ZUT9V0CMF0UU7QaPwJP7uNXcNxltTh+sk1yhjH4UlcnJigZZbA== +"@aws-sdk/credential-provider-env@3.846.0": + version "3.846.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.846.0.tgz#b47637b123544971f4d1c7300ea77b70143a7141" + integrity sha512-QuCQZET9enja7AWVISY+mpFrEIeHzvkx/JEEbHYzHhUkxcnC2Kq2c0bB7hDihGD0AZd3Xsm653hk1O97qu69zg== dependencies: - "@aws-sdk/core" "3.839.0" - "@aws-sdk/types" "3.821.0" + "@aws-sdk/core" "3.846.0" + "@aws-sdk/types" "3.840.0" "@smithy/property-provider" "^4.0.4" "@smithy/types" "^4.3.1" tslib "^2.6.2" -"@aws-sdk/credential-provider-http@3.839.0": - version "3.839.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-http/-/credential-provider-http-3.839.0.tgz#fefd416af01bcb2429f7db7e47d5ceaf3c860673" - integrity sha512-fv0BZwrDhWDju4D1MCLT4I2aPjr0dVQ6P+MpqvcGNOA41Oa9UdRhYTV5iuy5NLXzIzoCmnS+XfSq5Kbsf6//xw== +"@aws-sdk/credential-provider-http@3.846.0": + version "3.846.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-http/-/credential-provider-http-3.846.0.tgz#fe8b36493070a3444d76082b5129450598563fe0" + integrity sha512-Jh1iKUuepdmtreMYozV2ePsPcOF5W9p3U4tWhi3v6nDvz0GsBjzjAROW+BW8XMz9vAD3I9R+8VC3/aq63p5nlw== dependencies: - "@aws-sdk/core" "3.839.0" - "@aws-sdk/types" "3.821.0" - "@smithy/fetch-http-handler" "^5.0.4" - "@smithy/node-http-handler" "^4.0.6" + "@aws-sdk/core" "3.846.0" + "@aws-sdk/types" "3.840.0" + "@smithy/fetch-http-handler" "^5.1.0" + "@smithy/node-http-handler" "^4.1.0" "@smithy/property-provider" "^4.0.4" "@smithy/protocol-http" "^5.1.2" - "@smithy/smithy-client" "^4.4.5" + "@smithy/smithy-client" "^4.4.7" "@smithy/types" "^4.3.1" - "@smithy/util-stream" "^4.2.2" + "@smithy/util-stream" "^4.2.3" tslib "^2.6.2" "@aws-sdk/credential-provider-imds@3.0.0": @@ -1408,19 +1416,19 @@ "@aws-sdk/shared-ini-file-loader" "3.0.0" tslib "^1.8.0" -"@aws-sdk/credential-provider-ini@3.839.0": - version "3.839.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.839.0.tgz#34535d13382dabad2de084f3c7a94e587ce9a832" - integrity sha512-GHm0hF4CiDxIDR7TauMaA6iI55uuSqRxMBcqTAHaTPm6+h1A+MS+ysQMxZ+Jvwtoy8WmfTIGrJVxSCw0sK2hvA== - dependencies: - "@aws-sdk/core" "3.839.0" - "@aws-sdk/credential-provider-env" "3.839.0" - "@aws-sdk/credential-provider-http" "3.839.0" - "@aws-sdk/credential-provider-process" "3.839.0" - "@aws-sdk/credential-provider-sso" "3.839.0" - "@aws-sdk/credential-provider-web-identity" "3.839.0" - "@aws-sdk/nested-clients" "3.839.0" - "@aws-sdk/types" "3.821.0" +"@aws-sdk/credential-provider-ini@3.846.0": + version "3.846.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.846.0.tgz#3d4df54131048d745a04ab3b4af95407f49f7514" + integrity sha512-GUxaBBKsYx1kOlRbcs77l6BVyG9K70zekJX+5hdwTEgJq7AoHl/XYoWiDxPf6zQ7J4euixPJoyRhpNbJjAXdFw== + dependencies: + "@aws-sdk/core" "3.846.0" + "@aws-sdk/credential-provider-env" "3.846.0" + "@aws-sdk/credential-provider-http" "3.846.0" + "@aws-sdk/credential-provider-process" "3.846.0" + "@aws-sdk/credential-provider-sso" "3.846.0" + "@aws-sdk/credential-provider-web-identity" "3.846.0" + "@aws-sdk/nested-clients" "3.846.0" + "@aws-sdk/types" "3.840.0" "@smithy/credential-provider-imds" "^4.0.6" "@smithy/property-provider" "^4.0.4" "@smithy/shared-ini-file-loader" "^4.0.4" @@ -1439,18 +1447,18 @@ "@aws-sdk/property-provider" "3.0.0" tslib "^1.8.0" -"@aws-sdk/credential-provider-node@3.839.0": - version "3.839.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.839.0.tgz#2e7cfa42caa76977c7734cfada0febca9f72570c" - integrity sha512-7bR+U2h+ft0V8chyeu9Bh/pvau4ZkQMeRt5f0dAULoepZQ77QQVRP4H04yJPTg9DCtqbVULQ3uf5YOp1/08vQw== - dependencies: - "@aws-sdk/credential-provider-env" "3.839.0" - "@aws-sdk/credential-provider-http" "3.839.0" - "@aws-sdk/credential-provider-ini" "3.839.0" - "@aws-sdk/credential-provider-process" "3.839.0" - "@aws-sdk/credential-provider-sso" "3.839.0" - "@aws-sdk/credential-provider-web-identity" "3.839.0" - "@aws-sdk/types" "3.821.0" +"@aws-sdk/credential-provider-node@3.846.0": + version "3.846.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.846.0.tgz#576d302e7d5af1abc7e5b95695dd97afa03ad2f8" + integrity sha512-du2DsXYRfQ8VIt/gXGThhT8KdUEt2j9W91W87Bl9IA5DINt4nSZv+gzh8LqHBYsTSqoUpKb+qIfP1RjZM/8r0A== + dependencies: + "@aws-sdk/credential-provider-env" "3.846.0" + "@aws-sdk/credential-provider-http" "3.846.0" + "@aws-sdk/credential-provider-ini" "3.846.0" + "@aws-sdk/credential-provider-process" "3.846.0" + "@aws-sdk/credential-provider-sso" "3.846.0" + "@aws-sdk/credential-provider-web-identity" "3.846.0" + "@aws-sdk/types" "3.840.0" "@smithy/credential-provider-imds" "^4.0.6" "@smithy/property-provider" "^4.0.4" "@smithy/shared-ini-file-loader" "^4.0.4" @@ -1467,63 +1475,63 @@ "@aws-sdk/shared-ini-file-loader" "3.0.0" tslib "^1.8.0" -"@aws-sdk/credential-provider-process@3.839.0": - version "3.839.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.839.0.tgz#13be5dae462dbd368ce907bd79a00eaf672fa57f" - integrity sha512-qShpekjociUZ+isyQNa0P7jo+0q3N2+0eJDg8SGyP6K6hHTcGfiqxTDps+IKl6NreCPhZCBzyI9mWkP0xSDR6g== +"@aws-sdk/credential-provider-process@3.846.0": + version "3.846.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.846.0.tgz#19d22592594ca554a83148313651d5167c181fc3" + integrity sha512-mEpwDYarJSH+CIXnnHN0QOe0MXI+HuPStD6gsv3z/7Q6ESl8KRWon3weFZCDnqpiJMUVavlDR0PPlAFg2MQoPg== dependencies: - "@aws-sdk/core" "3.839.0" - "@aws-sdk/types" "3.821.0" + "@aws-sdk/core" "3.846.0" + "@aws-sdk/types" "3.840.0" "@smithy/property-provider" "^4.0.4" "@smithy/shared-ini-file-loader" "^4.0.4" "@smithy/types" "^4.3.1" tslib "^2.6.2" -"@aws-sdk/credential-provider-sso@3.839.0": - version "3.839.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.839.0.tgz#d64941981ca3160f32db87d099b130c36af55a62" - integrity sha512-w10zBLHhU8SBQcdrSPMI02haLoRGZg+gP7mH/Er8VhIXfHefbr7o4NirmB0hwdw/YAH8MLlC9jj7c2SJlsNhYA== +"@aws-sdk/credential-provider-sso@3.846.0": + version "3.846.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.846.0.tgz#6c1040a3476e877a769075682c3f7c105f16460b" + integrity sha512-Dxz9dpdjfxUsSfW92SAldu9wy8wgEbskn4BNWBFHslQHTmqurmR0ci4P1SMxJJKd498AUEoIAzZOtjGOC38irQ== dependencies: - "@aws-sdk/client-sso" "3.839.0" - "@aws-sdk/core" "3.839.0" - "@aws-sdk/token-providers" "3.839.0" - "@aws-sdk/types" "3.821.0" + "@aws-sdk/client-sso" "3.846.0" + "@aws-sdk/core" "3.846.0" + "@aws-sdk/token-providers" "3.846.0" + "@aws-sdk/types" "3.840.0" "@smithy/property-provider" "^4.0.4" "@smithy/shared-ini-file-loader" "^4.0.4" "@smithy/types" "^4.3.1" tslib "^2.6.2" -"@aws-sdk/credential-provider-web-identity@3.839.0": - version "3.839.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.839.0.tgz#b135421b562c9577e3d12fbb39b7adbb48c9ca00" - integrity sha512-EvqTc7J1kgmiuxknpCp1S60hyMQvmKxsI5uXzQtcogl/N55rxiXEqnCLI5q6p33q91PJegrcMCM5Q17Afhm5qA== +"@aws-sdk/credential-provider-web-identity@3.846.0": + version "3.846.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.846.0.tgz#939629e1cf2b778168f350ea79aaf278b357317e" + integrity sha512-j6zOd+kynPQJzmVwSKSUTpsLXAf7vKkr7hCPbQyqC8ZqkIuExsRqu2vRQjX2iH/MKhwZ+qEWMxPMhfDoyv7Gag== dependencies: - "@aws-sdk/core" "3.839.0" - "@aws-sdk/nested-clients" "3.839.0" - "@aws-sdk/types" "3.821.0" + "@aws-sdk/core" "3.846.0" + "@aws-sdk/nested-clients" "3.846.0" + "@aws-sdk/types" "3.840.0" "@smithy/property-provider" "^4.0.4" "@smithy/types" "^4.3.1" tslib "^2.6.2" -"@aws-sdk/credential-providers@3.839.0", "@aws-sdk/credential-providers@^3", "@aws-sdk/credential-providers@^3.834.0": - version "3.839.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-providers/-/credential-providers-3.839.0.tgz#5c2320899f3c010b55b5355efba1b002f41c20d7" - integrity sha512-hiM7vY2qYAdNT87+Qd3vvfNA+bqhtecsPIduIxkhwispEs9NGcQYtOaG3KQRcHkJBb4kaMYpudVNMXeYUYi2Aw== - dependencies: - "@aws-sdk/client-cognito-identity" "3.839.0" - "@aws-sdk/core" "3.839.0" - "@aws-sdk/credential-provider-cognito-identity" "3.839.0" - "@aws-sdk/credential-provider-env" "3.839.0" - "@aws-sdk/credential-provider-http" "3.839.0" - "@aws-sdk/credential-provider-ini" "3.839.0" - "@aws-sdk/credential-provider-node" "3.839.0" - "@aws-sdk/credential-provider-process" "3.839.0" - "@aws-sdk/credential-provider-sso" "3.839.0" - "@aws-sdk/credential-provider-web-identity" "3.839.0" - "@aws-sdk/nested-clients" "3.839.0" - "@aws-sdk/types" "3.821.0" +"@aws-sdk/credential-providers@^3", "@aws-sdk/credential-providers@^3.840.0", "@aws-sdk/credential-providers@^3.846.0": + version "3.846.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-providers/-/credential-providers-3.846.0.tgz#98c348ec6551f7dc832bfc369fe221b2b71e4846" + integrity sha512-YpTJcV5PO0V+I1nRGAyNF/kCcOIgPgzihlAyOqicmq3vZ8UHZqUCOfzcS6qbEpPFeAB3domzBgsAJNsQXht4SA== + dependencies: + "@aws-sdk/client-cognito-identity" "3.846.0" + "@aws-sdk/core" "3.846.0" + "@aws-sdk/credential-provider-cognito-identity" "3.846.0" + "@aws-sdk/credential-provider-env" "3.846.0" + "@aws-sdk/credential-provider-http" "3.846.0" + "@aws-sdk/credential-provider-ini" "3.846.0" + "@aws-sdk/credential-provider-node" "3.846.0" + "@aws-sdk/credential-provider-process" "3.846.0" + "@aws-sdk/credential-provider-sso" "3.846.0" + "@aws-sdk/credential-provider-web-identity" "3.846.0" + "@aws-sdk/nested-clients" "3.846.0" + "@aws-sdk/types" "3.840.0" "@smithy/config-resolver" "^4.1.4" - "@smithy/core" "^3.6.0" + "@smithy/core" "^3.7.0" "@smithy/credential-provider-imds" "^4.0.6" "@smithy/node-config-provider" "^4.1.3" "@smithy/property-provider" "^4.0.4" @@ -1531,16 +1539,16 @@ tslib "^2.6.2" "@aws-sdk/ec2-metadata-service@^3": - version "3.839.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/ec2-metadata-service/-/ec2-metadata-service-3.839.0.tgz#64940578a19f7377e7e26829d8002b5377042d56" - integrity sha512-L4qZzOHKfw/CkV39Hf8X0fa/NYnXKCrXeXPqZvrb6F/23lef8pynOT3VSJLqx5NNossn3D2wkILKABjqlqT50Q== + version "3.846.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/ec2-metadata-service/-/ec2-metadata-service-3.846.0.tgz#1442f61b928742ee9e0cb4e38a221aa0afeff923" + integrity sha512-4NvE2RsB34Y/LkjyfZwLfEeaS36F/8k7hcUjeVf3rDXeEtnPpwuOPwtDXvvZVBcv0DPYuGj7FVItBwnvPLSCeQ== dependencies: - "@aws-sdk/types" "3.821.0" + "@aws-sdk/types" "3.840.0" "@smithy/node-config-provider" "^4.1.3" - "@smithy/node-http-handler" "^4.0.6" + "@smithy/node-http-handler" "^4.1.0" "@smithy/protocol-http" "^5.1.2" "@smithy/types" "^4.3.1" - "@smithy/util-stream" "^4.2.2" + "@smithy/util-stream" "^4.2.3" tslib "^2.6.2" "@aws-sdk/fetch-http-handler@3.0.0": @@ -1576,24 +1584,24 @@ tslib "^1.8.0" "@aws-sdk/lib-storage@^3": - version "3.839.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/lib-storage/-/lib-storage-3.839.0.tgz#2d8191a1c1079792d11db89ef33108e6db629e1d" - integrity sha512-cTracARTc9o1cqLKKb2k5r5lYiIAOZglJgHS2LVet5Xb0C6JDmSd4nRSj1N5rj9czRrxqf11RTrUdq4JgsV6tQ== + version "3.846.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/lib-storage/-/lib-storage-3.846.0.tgz#45abbdcfbdc1dd3054474d8ed8cf618586b8ef1f" + integrity sha512-Vd1BdkRDoDAAKgUcBAko1OezMHD90PjoP43iGi2HyMJaqak/rhoOXpPlejH4B1uGkrDEUVYbJz8UtKl8UdQp4g== dependencies: "@smithy/abort-controller" "^4.0.4" - "@smithy/middleware-endpoint" "^4.1.13" - "@smithy/smithy-client" "^4.4.5" + "@smithy/middleware-endpoint" "^4.1.15" + "@smithy/smithy-client" "^4.4.7" buffer "5.6.0" events "3.3.0" stream-browserify "3.0.0" tslib "^2.6.2" -"@aws-sdk/middleware-bucket-endpoint@3.830.0": - version "3.830.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.830.0.tgz#4ab8ebf3ab38b94021981e9cd069c73c9c2ae354" - integrity sha512-ElVeCReZSH5Ds+/pkL5ebneJjuo8f49e9JXV1cYizuH0OAOQfYaBU9+M+7+rn61pTttOFE8W//qKzrXBBJhfMg== +"@aws-sdk/middleware-bucket-endpoint@3.840.0": + version "3.840.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.840.0.tgz#ab414010b0230d9489c81dea38ab21feb1b18929" + integrity sha512-+gkQNtPwcSMmlwBHFd4saVVS11In6ID1HczNzpM3MXKXRBfSlbZJbCt6wN//AZ8HMklZEik4tcEOG0qa9UY8SQ== dependencies: - "@aws-sdk/types" "3.821.0" + "@aws-sdk/types" "3.840.0" "@aws-sdk/util-arn-parser" "3.804.0" "@smithy/node-config-provider" "^4.1.3" "@smithy/protocol-http" "^5.1.2" @@ -1617,32 +1625,32 @@ "@smithy/middleware-endpoint" "^1.0.2" tslib "^2.5.0" -"@aws-sdk/middleware-expect-continue@3.821.0": - version "3.821.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.821.0.tgz#de4e8f5ca3727dd2dd802685aa3342ceb4e662e3" - integrity sha512-zAOoSZKe1njOrtynvK6ZORU57YGv5I7KP4+rwOvUN3ZhJbQ7QPf8gKtFUCYAPRMegaXCKF/ADPtDZBAmM+zZ9g== +"@aws-sdk/middleware-expect-continue@3.840.0": + version "3.840.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.840.0.tgz#1d77857dd03a3cc47e949eadcd425bcb53ebdd60" + integrity sha512-iJg2r6FKsKKvdiU4oCOuCf7Ro/YE0Q2BT/QyEZN3/Rt8Nr4SAZiQOlcBXOCpGvuIKOEAhvDOUnW3aDHL01PdVw== dependencies: - "@aws-sdk/types" "3.821.0" + "@aws-sdk/types" "3.840.0" "@smithy/protocol-http" "^5.1.2" "@smithy/types" "^4.3.1" tslib "^2.6.2" -"@aws-sdk/middleware-flexible-checksums@3.839.0": - version "3.839.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.839.0.tgz#676fe98cdce22c75998446212009a5bbfc38f601" - integrity sha512-2LEuDUviV3wardiHoHCKx0WUvmiK1gBGmnw12aj5f/KKcWOaqnWI2h1K7nDQC/ZARQ1bbMZZ5kvOv5ueuMg1RA== +"@aws-sdk/middleware-flexible-checksums@3.846.0": + version "3.846.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.846.0.tgz#e697f2a32fafac39c6f7ba58554c148303cd7f82" + integrity sha512-CdkeVfkwt3+bDLhmOwBxvkUf6oY9iUhvosaUnqkoPsOqIiUEN54yTGOnO8A0wLz6mMsZ6aBlfFrQhFnxt3c+yw== dependencies: "@aws-crypto/crc32" "5.2.0" "@aws-crypto/crc32c" "5.2.0" "@aws-crypto/util" "5.2.0" - "@aws-sdk/core" "3.839.0" - "@aws-sdk/types" "3.821.0" + "@aws-sdk/core" "3.846.0" + "@aws-sdk/types" "3.840.0" "@smithy/is-array-buffer" "^4.0.0" "@smithy/node-config-provider" "^4.1.3" "@smithy/protocol-http" "^5.1.2" "@smithy/types" "^4.3.1" "@smithy/util-middleware" "^4.0.4" - "@smithy/util-stream" "^4.2.2" + "@smithy/util-stream" "^4.2.3" "@smithy/util-utf8" "^4.0.0" tslib "^2.6.2" @@ -1654,22 +1662,22 @@ "@aws-sdk/protocol-http" "3.0.0" tslib "^1.8.0" -"@aws-sdk/middleware-host-header@3.821.0": - version "3.821.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-host-header/-/middleware-host-header-3.821.0.tgz#1dfda8da4e0f9499648dab9a989d10706e289cc7" - integrity sha512-xSMR+sopSeWGx5/4pAGhhfMvGBHioVBbqGvDs6pG64xfNwM5vq5s5v6D04e2i+uSTj4qGa71dLUs5I0UzAK3sw== +"@aws-sdk/middleware-host-header@3.840.0": + version "3.840.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-host-header/-/middleware-host-header-3.840.0.tgz#7c8b163fb13d588b87523b53f7d98de73262e83f" + integrity sha512-ub+hXJAbAje94+Ya6c6eL7sYujoE8D4Bumu1NUI8TXjUhVVn0HzVWQjpRLshdLsUp1AW7XyeJaxyajRaJQ8+Xg== dependencies: - "@aws-sdk/types" "3.821.0" + "@aws-sdk/types" "3.840.0" "@smithy/protocol-http" "^5.1.2" "@smithy/types" "^4.3.1" tslib "^2.6.2" -"@aws-sdk/middleware-location-constraint@3.821.0": - version "3.821.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.821.0.tgz#9a5b52f8874f48274e89329aa3d45a55340d267e" - integrity sha512-sKrm80k0t3R0on8aA/WhWFoMaAl4yvdk+riotmMElLUpcMcRXAd1+600uFVrxJqZdbrKQ0mjX0PjT68DlkYXLg== +"@aws-sdk/middleware-location-constraint@3.840.0": + version "3.840.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.840.0.tgz#5796cb59ae4e19d04c66cf69de73c59f9cc64241" + integrity sha512-KVLD0u0YMF3aQkVF8bdyHAGWSUY6N1Du89htTLgqCcIhSxxAJ9qifrosVZ9jkAzqRW99hcufyt2LylcVU2yoKQ== dependencies: - "@aws-sdk/types" "3.821.0" + "@aws-sdk/types" "3.840.0" "@smithy/types" "^4.3.1" tslib "^2.6.2" @@ -1680,21 +1688,21 @@ dependencies: tslib "^1.8.0" -"@aws-sdk/middleware-logger@3.821.0": - version "3.821.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-logger/-/middleware-logger-3.821.0.tgz#87067907a25cdc6c155d3a35fe32e399c1ef87e6" - integrity sha512-0cvI0ipf2tGx7fXYEEN5fBeZDz2RnHyb9xftSgUsEq7NBxjV0yTZfLJw6Za5rjE6snC80dRN8+bTNR1tuG89zA== +"@aws-sdk/middleware-logger@3.840.0": + version "3.840.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-logger/-/middleware-logger-3.840.0.tgz#d92ade1817ac7dc78a3567c1239bb1a3f3b1b57a" + integrity sha512-lSV8FvjpdllpGaRspywss4CtXV8M7NNNH+2/j86vMH+YCOZ6fu2T/TyFd/tHwZ92vDfHctWkRbQxg0bagqwovA== dependencies: - "@aws-sdk/types" "3.821.0" + "@aws-sdk/types" "3.840.0" "@smithy/types" "^4.3.1" tslib "^2.6.2" -"@aws-sdk/middleware-recursion-detection@3.821.0": - version "3.821.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.821.0.tgz#bc34b08efc1e1af7b14a58023a79bfb75a0b64fa" - integrity sha512-efmaifbhBoqKG3bAoEfDdcM8hn1psF+4qa7ykWuYmfmah59JBeqHLfz5W9m9JoTwoKPkFcVLWZxnyZzAnVBOIg== +"@aws-sdk/middleware-recursion-detection@3.840.0": + version "3.840.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.840.0.tgz#8ea2c00af258db0b64ea394e044cedb6101b5ffd" + integrity sha512-Gu7lGDyfddyhIkj1Z1JtrY5NHb5+x/CRiB87GjaSrKxkDaydtX2CU977JIABtt69l9wLbcGDIQ+W0uJ5xPof7g== dependencies: - "@aws-sdk/types" "3.821.0" + "@aws-sdk/types" "3.840.0" "@smithy/protocol-http" "^5.1.2" "@smithy/types" "^4.3.1" tslib "^2.6.2" @@ -1710,46 +1718,46 @@ tslib "^1.8.0" uuid "^3.0.0" -"@aws-sdk/middleware-sdk-ec2@3.839.0": - version "3.839.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-ec2/-/middleware-sdk-ec2-3.839.0.tgz#6f1e1a56452d21b6cd2322c6ba08f003f66eb700" - integrity sha512-hFWKW75QDLmweuMI8KQOwoFHPxgNy37TpU0INpcdhiFZniTeMoXNuJJZ9Zj6+Ci3do7LuXBuZNyWUha5sX0OhQ== +"@aws-sdk/middleware-sdk-ec2@3.845.0": + version "3.845.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-ec2/-/middleware-sdk-ec2-3.845.0.tgz#076cc695f6dda5bfaba464336e19fa7f70d4df5f" + integrity sha512-AATrRHKPzvHdTHbDhOHKvVhOlkrdVmPY00gP/dSBRu2im2Hr694aCcnvf/RLJVlw9fdkJFIFH7TVgPeSO2AUOQ== dependencies: - "@aws-sdk/types" "3.821.0" - "@aws-sdk/util-format-url" "3.821.0" - "@smithy/middleware-endpoint" "^4.1.13" + "@aws-sdk/types" "3.840.0" + "@aws-sdk/util-format-url" "3.840.0" + "@smithy/middleware-endpoint" "^4.1.15" "@smithy/protocol-http" "^5.1.2" "@smithy/signature-v4" "^5.1.2" - "@smithy/smithy-client" "^4.4.5" + "@smithy/smithy-client" "^4.4.7" "@smithy/types" "^4.3.1" tslib "^2.6.2" -"@aws-sdk/middleware-sdk-route53@3.821.0": - version "3.821.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-route53/-/middleware-sdk-route53-3.821.0.tgz#e58bf018dfe436ae5395b38077150fd260766817" - integrity sha512-GhUXKekinxTYreYM2z0OOU7A1w17PzeutUVVT+CN3oWrwOgIpMZZEa+y7RoUkP5IQkPSzjMwS4c6hapNEFyQug== +"@aws-sdk/middleware-sdk-route53@3.840.0": + version "3.840.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-route53/-/middleware-sdk-route53-3.840.0.tgz#fed5a6eaeedef450625dbe9364c6a3e8192fac86" + integrity sha512-0xi4QU1oNddYDjnlvofMI/klOEMgLD53t0cmPqVEhdCGJGwte4fZaF+44GGy82vNyiqANPPrK9EcT3F9VR8xrQ== dependencies: - "@aws-sdk/types" "3.821.0" + "@aws-sdk/types" "3.840.0" "@smithy/types" "^4.3.1" tslib "^2.6.2" -"@aws-sdk/middleware-sdk-s3@3.839.0": - version "3.839.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.839.0.tgz#5218d7b3825bfa48c54f13aeb0739ea3d924792e" - integrity sha512-NwprpzJdkuUnUWxoZwKqAcL1/AsrM1YESVpLeL0pW747Vq6rIiUgkuoyQ1fASV9r5mUoWor7iMu8k5ZCisAh7A== +"@aws-sdk/middleware-sdk-s3@3.846.0": + version "3.846.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.846.0.tgz#802b728848b475cdbbf4b22135d65cf26063410e" + integrity sha512-jP9x+2Q87J5l8FOP+jlAd7vGLn0cC6G9QGmf386e5OslBPqxXKcl3RjqGLIOKKos2mVItY3ApP5xdXQx7jGTVA== dependencies: - "@aws-sdk/core" "3.839.0" - "@aws-sdk/types" "3.821.0" + "@aws-sdk/core" "3.846.0" + "@aws-sdk/types" "3.840.0" "@aws-sdk/util-arn-parser" "3.804.0" - "@smithy/core" "^3.6.0" + "@smithy/core" "^3.7.0" "@smithy/node-config-provider" "^4.1.3" "@smithy/protocol-http" "^5.1.2" "@smithy/signature-v4" "^5.1.2" - "@smithy/smithy-client" "^4.4.5" + "@smithy/smithy-client" "^4.4.7" "@smithy/types" "^4.3.1" "@smithy/util-config-provider" "^4.0.0" "@smithy/util-middleware" "^4.0.4" - "@smithy/util-stream" "^4.2.2" + "@smithy/util-stream" "^4.2.3" "@smithy/util-utf8" "^4.0.0" tslib "^2.6.2" @@ -1769,12 +1777,12 @@ "@aws-sdk/signature-v4" "3.0.0" tslib "^1.8.0" -"@aws-sdk/middleware-ssec@3.821.0": - version "3.821.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-ssec/-/middleware-ssec-3.821.0.tgz#4d4c2ba22e5bbf5ac618a1f679cbe256eaaf3d35" - integrity sha512-YYi1Hhr2AYiU/24cQc8HIB+SWbQo6FBkMYojVuz/zgrtkFmALxENGF/21OPg7f/QWd+eadZJRxCjmRwh5F2Cxg== +"@aws-sdk/middleware-ssec@3.840.0": + version "3.840.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-ssec/-/middleware-ssec-3.840.0.tgz#64252d11c21d99690abc51a6fabf1ea7144d40ac" + integrity sha512-CBZP9t1QbjDFGOrtnUEHL1oAvmnCUUm7p0aPNbIdSzNtH42TNKjPRN3TuEIJDGjkrqpL3MXyDSmNayDcw/XW7Q== dependencies: - "@aws-sdk/types" "3.821.0" + "@aws-sdk/types" "3.840.0" "@smithy/types" "^4.3.1" tslib "^2.6.2" @@ -1793,57 +1801,57 @@ "@aws-sdk/protocol-http" "3.0.0" tslib "^1.8.0" -"@aws-sdk/middleware-user-agent@3.839.0": - version "3.839.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.839.0.tgz#92c22d5a90bfcdbe8d757c4e388e53462d2d0883" - integrity sha512-2u74uRM1JWq6Sf7+3YpjejPM9YkomGt4kWhrmooIBEq1k5r2GTbkH7pNCxBQwBueXM21jAGVDxxeClpTx+5hig== +"@aws-sdk/middleware-user-agent@3.846.0": + version "3.846.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.846.0.tgz#e038f60b1b12b2c44a41c831925f52347ca27540" + integrity sha512-85/oUc2jMXqQWo+HHH7WwrdqqArzhMmTmBCpXZwklBHG+ZMzTS5Wug2B0HhGDVWo9aYRMeikSq4lsrpHFVd2MQ== dependencies: - "@aws-sdk/core" "3.839.0" - "@aws-sdk/types" "3.821.0" - "@aws-sdk/util-endpoints" "3.828.0" - "@smithy/core" "^3.6.0" + "@aws-sdk/core" "3.846.0" + "@aws-sdk/types" "3.840.0" + "@aws-sdk/util-endpoints" "3.845.0" + "@smithy/core" "^3.7.0" "@smithy/protocol-http" "^5.1.2" "@smithy/types" "^4.3.1" tslib "^2.6.2" -"@aws-sdk/nested-clients@3.839.0": - version "3.839.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/nested-clients/-/nested-clients-3.839.0.tgz#f25df2be30bbbdf13b29ec5e8575190599b9b375" - integrity sha512-Glic0pg2THYP3aRhJORwJJBe1JLtJoEdWV/MFZNyzCklfMwEzpWtZAyxy+tQyFmMeW50uBAnh2R0jhMMcf257w== +"@aws-sdk/nested-clients@3.846.0": + version "3.846.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/nested-clients/-/nested-clients-3.846.0.tgz#c0389df04f04e6f4d124a605cc17b2b3f9a82faa" + integrity sha512-LCXPVtNQnkTuE8inPCtpfWN2raE/ndFBKf5OIbuHnC/0XYGOUl5q7VsJz471zJuN9FX3WMfopaFwmNc7cQNMpQ== dependencies: "@aws-crypto/sha256-browser" "5.2.0" "@aws-crypto/sha256-js" "5.2.0" - "@aws-sdk/core" "3.839.0" - "@aws-sdk/middleware-host-header" "3.821.0" - "@aws-sdk/middleware-logger" "3.821.0" - "@aws-sdk/middleware-recursion-detection" "3.821.0" - "@aws-sdk/middleware-user-agent" "3.839.0" - "@aws-sdk/region-config-resolver" "3.821.0" - "@aws-sdk/types" "3.821.0" - "@aws-sdk/util-endpoints" "3.828.0" - "@aws-sdk/util-user-agent-browser" "3.821.0" - "@aws-sdk/util-user-agent-node" "3.839.0" + "@aws-sdk/core" "3.846.0" + "@aws-sdk/middleware-host-header" "3.840.0" + "@aws-sdk/middleware-logger" "3.840.0" + "@aws-sdk/middleware-recursion-detection" "3.840.0" + "@aws-sdk/middleware-user-agent" "3.846.0" + "@aws-sdk/region-config-resolver" "3.840.0" + "@aws-sdk/types" "3.840.0" + "@aws-sdk/util-endpoints" "3.845.0" + "@aws-sdk/util-user-agent-browser" "3.840.0" + "@aws-sdk/util-user-agent-node" "3.846.0" "@smithy/config-resolver" "^4.1.4" - "@smithy/core" "^3.6.0" - "@smithy/fetch-http-handler" "^5.0.4" + "@smithy/core" "^3.7.0" + "@smithy/fetch-http-handler" "^5.1.0" "@smithy/hash-node" "^4.0.4" "@smithy/invalid-dependency" "^4.0.4" "@smithy/middleware-content-length" "^4.0.4" - "@smithy/middleware-endpoint" "^4.1.13" - "@smithy/middleware-retry" "^4.1.14" + "@smithy/middleware-endpoint" "^4.1.15" + "@smithy/middleware-retry" "^4.1.16" "@smithy/middleware-serde" "^4.0.8" "@smithy/middleware-stack" "^4.0.4" "@smithy/node-config-provider" "^4.1.3" - "@smithy/node-http-handler" "^4.0.6" + "@smithy/node-http-handler" "^4.1.0" "@smithy/protocol-http" "^5.1.2" - "@smithy/smithy-client" "^4.4.5" + "@smithy/smithy-client" "^4.4.7" "@smithy/types" "^4.3.1" "@smithy/url-parser" "^4.0.4" "@smithy/util-base64" "^4.0.0" "@smithy/util-body-length-browser" "^4.0.0" "@smithy/util-body-length-node" "^4.0.0" - "@smithy/util-defaults-mode-browser" "^4.0.21" - "@smithy/util-defaults-mode-node" "^4.0.21" + "@smithy/util-defaults-mode-browser" "^4.0.23" + "@smithy/util-defaults-mode-node" "^4.0.23" "@smithy/util-endpoints" "^3.0.6" "@smithy/util-middleware" "^4.0.4" "@smithy/util-retry" "^4.0.6" @@ -1898,12 +1906,12 @@ dependencies: tslib "^1.8.0" -"@aws-sdk/region-config-resolver@3.821.0": - version "3.821.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/region-config-resolver/-/region-config-resolver-3.821.0.tgz#2f1cd54ca140cbdc821a604d8b20444f9b0b77cf" - integrity sha512-t8og+lRCIIy5nlId0bScNpCkif8sc0LhmtaKsbm0ZPm3sCa/WhCbSZibjbZ28FNjVCV+p0D9RYZx0VDDbtWyjw== +"@aws-sdk/region-config-resolver@3.840.0": + version "3.840.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/region-config-resolver/-/region-config-resolver-3.840.0.tgz#240690ead3131c4c47186b4929776439fe2f6729" + integrity sha512-Qjnxd/yDv9KpIMWr90ZDPtRj0v75AqGC92Lm9+oHXZ8p1MjG5JE2CW0HL8JRgK9iKzgKBL7pPQRXI8FkvEVfrA== dependencies: - "@aws-sdk/types" "3.821.0" + "@aws-sdk/types" "3.840.0" "@smithy/node-config-provider" "^4.1.3" "@smithy/types" "^4.3.1" "@smithy/util-config-provider" "^4.0.0" @@ -1922,13 +1930,13 @@ dependencies: tslib "^1.8.0" -"@aws-sdk/signature-v4-multi-region@3.839.0": - version "3.839.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.839.0.tgz#27085b7f787b5ac547c5158a7b03c21e41351c4f" - integrity sha512-/O+lh6qXKTMWPcip8ccGL7OgTceUTDmy3wBD22+tPHLeOUSMGUQTZcsmHeDB7vSHLpVY9H6GhOsdes7uQQMUwA== +"@aws-sdk/signature-v4-multi-region@3.846.0": + version "3.846.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.846.0.tgz#4c441134c8dc4cb329b2292ec78653ec4263b6e1" + integrity sha512-ZMfIMxUljqZzPJGOcraC6erwq/z1puNMU35cO1a/WdhB+LdYknMn1lr7SJuH754QwNzzIlZbEgg4hoHw50+DpQ== dependencies: - "@aws-sdk/middleware-sdk-s3" "3.839.0" - "@aws-sdk/types" "3.821.0" + "@aws-sdk/middleware-sdk-s3" "3.846.0" + "@aws-sdk/types" "3.840.0" "@smithy/protocol-http" "^5.1.2" "@smithy/signature-v4" "^5.1.2" "@smithy/types" "^4.3.1" @@ -1952,14 +1960,14 @@ "@aws-sdk/middleware-stack" "3.0.0" tslib "^1.8.0" -"@aws-sdk/token-providers@3.839.0": - version "3.839.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/token-providers/-/token-providers-3.839.0.tgz#55be3491195d09d8425e57cabd5bd042d67eef8a" - integrity sha512-2nlafqdSbet/2WtYIoZ7KEGFowFonPBDYlTjrUvwU2yooE10VhvzhLSCTB2aKIVzo2Z2wL5WGFQsqAY5QwK6Bw== +"@aws-sdk/token-providers@3.846.0": + version "3.846.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/token-providers/-/token-providers-3.846.0.tgz#36b499314c2ed754aa9372058a2a8c9e9054ad49" + integrity sha512-sGNk3xclK7xx+rIJZDJC4FNFqaSSqN0nSr+AdVdQ+/iKQKaUA6hixRbXaQ7I7M5mhqS6fMW1AsqVRywQq2BSMw== dependencies: - "@aws-sdk/core" "3.839.0" - "@aws-sdk/nested-clients" "3.839.0" - "@aws-sdk/types" "3.821.0" + "@aws-sdk/core" "3.846.0" + "@aws-sdk/nested-clients" "3.846.0" + "@aws-sdk/types" "3.840.0" "@smithy/property-provider" "^4.0.4" "@smithy/shared-ini-file-loader" "^4.0.4" "@smithy/types" "^4.3.1" @@ -1970,10 +1978,10 @@ resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.0.0.tgz#c84359dd0ba0040fc1089928d43c74683ed71066" integrity sha512-D2sSHRZRw0ixox5+Dx7xPvTfMLZQzxJ/nWDP26FAl+c/i/402d0Y9acfDtUxfxPxCbVogZ3XgZXhjDY/RmMAjQ== -"@aws-sdk/types@3.821.0", "@aws-sdk/types@^3.1.0", "@aws-sdk/types@^3.222.0": - version "3.821.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.821.0.tgz#edfd4595208e4e9f24f397fbc8cb82e3ec336649" - integrity sha512-Znroqdai1a90TlxGaJ+FK1lwC0fHpo97Xjsp5UKGR5JODYm7f9+/fF17ebO1KdoBr/Rm0UIFiF5VmI8ts9F1eA== +"@aws-sdk/types@3.840.0", "@aws-sdk/types@^3.1.0", "@aws-sdk/types@^3.222.0": + version "3.840.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.840.0.tgz#aadc6843d5c1f24b3d1d228059e702a355bf07c3" + integrity sha512-xliuHaUFZxEx1NSXeLLZ9Dyu6+EJVQKEoD+yM+zqUo3YDZ7medKJWY6fIOKiPX/N7XbLdBYwajb15Q7IL8KkeA== dependencies: "@smithy/types" "^4.3.1" tslib "^2.6.2" @@ -2039,22 +2047,23 @@ "@aws-sdk/is-array-buffer" "3.0.0" tslib "^1.8.0" -"@aws-sdk/util-endpoints@3.828.0": - version "3.828.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-endpoints/-/util-endpoints-3.828.0.tgz#a02f9c99d9749123fabad38d3b6cd51f4c8489db" - integrity sha512-RvKch111SblqdkPzg3oCIdlGxlQs+k+P7Etory9FmxPHyPDvsP1j1c74PmgYqtzzMWmoXTjd+c9naUHh9xG8xg== +"@aws-sdk/util-endpoints@3.845.0": + version "3.845.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-endpoints/-/util-endpoints-3.845.0.tgz#a4a303502b79a9868da2f6a17f81d24a34f10974" + integrity sha512-MBmOf0Pb4q6xs9V7jXT1+qciW2965yvaoZUlUUnxUEoX6zxWROeIu/gttASc4vSjOHr/+64hmFkxjeBUF37FJA== dependencies: - "@aws-sdk/types" "3.821.0" + "@aws-sdk/types" "3.840.0" "@smithy/types" "^4.3.1" + "@smithy/url-parser" "^4.0.4" "@smithy/util-endpoints" "^3.0.6" tslib "^2.6.2" -"@aws-sdk/util-format-url@3.821.0": - version "3.821.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-format-url/-/util-format-url-3.821.0.tgz#de0a61d6dc23478724c501b3894b0d13ae775c14" - integrity sha512-h+xqmPToxDrZ0a7rxE1a8Oh4zpWfZe9oiQUphGtfiGFA6j75UiURH5J3MmGHa/G4t15I3iLLbYtUXxvb1i7evg== +"@aws-sdk/util-format-url@3.840.0": + version "3.840.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-format-url/-/util-format-url-3.840.0.tgz#386f703f9048f0a297ec2f4e37a9bfbb84a0aa18" + integrity sha512-VB1PWyI1TQPiPvg4w7tgUGGQER1xxXPNUqfh3baxUSFi1Oh8wHrDnFywkxLm3NMmgDmnLnSZ5Q326qAoyqKLSg== dependencies: - "@aws-sdk/types" "3.821.0" + "@aws-sdk/types" "3.840.0" "@smithy/querystring-builder" "^4.0.4" "@smithy/types" "^4.3.1" tslib "^2.6.2" @@ -2095,12 +2104,12 @@ dependencies: tslib "^1.8.0" -"@aws-sdk/util-user-agent-browser@3.821.0": - version "3.821.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.821.0.tgz#32962fd3ae20986da128944b88a231508e017f5b" - integrity sha512-irWZHyM0Jr1xhC+38OuZ7JB6OXMLPZlj48thElpsO1ZSLRkLZx5+I7VV6k3sp2yZ7BYbKz/G2ojSv4wdm7XTLw== +"@aws-sdk/util-user-agent-browser@3.840.0": + version "3.840.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.840.0.tgz#6c2f55494352a86048c52852b0c357bb21905984" + integrity sha512-JdyZM3EhhL4PqwFpttZu1afDpPJCCc3eyZOLi+srpX11LsGj6sThf47TYQN75HT1CarZ7cCdQHGzP2uy3/xHfQ== dependencies: - "@aws-sdk/types" "3.821.0" + "@aws-sdk/types" "3.840.0" "@smithy/types" "^4.3.1" bowser "^2.11.0" tslib "^2.6.2" @@ -2112,13 +2121,13 @@ dependencies: tslib "^1.8.0" -"@aws-sdk/util-user-agent-node@3.839.0": - version "3.839.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.839.0.tgz#0c29e2d18e9d6ed1c6dffdf404adf8129f0f40e5" - integrity sha512-MuunkIG1bJVMtTH7MbjXOrhHleU5wjHz5eCAUc6vj7M9rwol71nqjj9b8RLnkO5gsJcKc29Qk8iV6xQuzKWNMw== +"@aws-sdk/util-user-agent-node@3.846.0": + version "3.846.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.846.0.tgz#05ab54d561bcbe3888d88b500ef62a7f41acac8c" + integrity sha512-MXYXCplw76xe8A9ejVaIru6Carum/2LQbVtNHsIa4h0TlafLdfulywsoMWL1F53Y9XxQSeOKyyqDKLNOgRVimw== dependencies: - "@aws-sdk/middleware-user-agent" "3.839.0" - "@aws-sdk/types" "3.821.0" + "@aws-sdk/middleware-user-agent" "3.846.0" + "@aws-sdk/types" "3.840.0" "@smithy/node-config-provider" "^4.1.3" "@smithy/types" "^4.3.1" tslib "^2.6.2" @@ -2180,40 +2189,40 @@ picocolors "^1.1.1" "@babel/compat-data@^7.27.2": - version "7.27.7" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.27.7.tgz#7fd698e531050cce432b073ab64857b99e0f3804" - integrity sha512-xgu/ySj2mTiUFmdE9yCMfBxLp4DHd5DwmbbD05YAuICfodYT3VvRxbrh81LGQ/8UpSdtMdfKMn3KouYDX59DGQ== + version "7.28.0" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.28.0.tgz#9fc6fd58c2a6a15243cd13983224968392070790" + integrity sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw== "@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.23.9", "@babel/core@^7.27.4": - version "7.27.7" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.27.7.tgz#0ddeab1e7b17317dad8c3c3a887716f66b5c4428" - integrity sha512-BU2f9tlKQ5CAthiMIgpzAh4eDTLWo1mqi9jqE2OxMG0E/OM199VJt2q8BztTxpnSW0i1ymdwLXRJnYzvDM5r2w== + version "7.28.0" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.28.0.tgz#55dad808d5bf3445a108eefc88ea3fdf034749a4" + integrity sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ== dependencies: "@ampproject/remapping" "^2.2.0" "@babel/code-frame" "^7.27.1" - "@babel/generator" "^7.27.5" + "@babel/generator" "^7.28.0" "@babel/helper-compilation-targets" "^7.27.2" "@babel/helper-module-transforms" "^7.27.3" "@babel/helpers" "^7.27.6" - "@babel/parser" "^7.27.7" + "@babel/parser" "^7.28.0" "@babel/template" "^7.27.2" - "@babel/traverse" "^7.27.7" - "@babel/types" "^7.27.7" + "@babel/traverse" "^7.28.0" + "@babel/types" "^7.28.0" convert-source-map "^2.0.0" debug "^4.1.0" gensync "^1.0.0-beta.2" json5 "^2.2.3" semver "^6.3.1" -"@babel/generator@^7.27.5", "@babel/generator@^7.7.2": - version "7.27.5" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.27.5.tgz#3eb01866b345ba261b04911020cbe22dd4be8c8c" - integrity sha512-ZGhA37l0e/g2s1Cnzdix0O3aLYm66eF8aufiVteOgnwxgnRP8GoyMj7VWsgWnQbVKXyge7hqrFh2K2TQM6t1Hw== +"@babel/generator@^7.27.5", "@babel/generator@^7.28.0", "@babel/generator@^7.7.2": + version "7.28.0" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.28.0.tgz#9cc2f7bd6eb054d77dc66c2664148a0c5118acd2" + integrity sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg== dependencies: - "@babel/parser" "^7.27.5" - "@babel/types" "^7.27.3" - "@jridgewell/gen-mapping" "^0.3.5" - "@jridgewell/trace-mapping" "^0.3.25" + "@babel/parser" "^7.28.0" + "@babel/types" "^7.28.0" + "@jridgewell/gen-mapping" "^0.3.12" + "@jridgewell/trace-mapping" "^0.3.28" jsesc "^3.0.2" "@babel/helper-compilation-targets@^7.27.2": @@ -2227,6 +2236,11 @@ lru-cache "^5.1.1" semver "^6.3.1" +"@babel/helper-globals@^7.28.0": + version "7.28.0" + resolved "https://registry.yarnpkg.com/@babel/helper-globals/-/helper-globals-7.28.0.tgz#b9430df2aa4e17bc28665eadeae8aa1d985e6674" + integrity sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw== + "@babel/helper-module-imports@^7.27.1": version "7.27.1" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz#7ef769a323e2655e126673bb6d2d6913bbead204" @@ -2272,12 +2286,12 @@ "@babel/template" "^7.27.2" "@babel/types" "^7.27.6" -"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.23.9", "@babel/parser@^7.26.7", "@babel/parser@^7.27.2", "@babel/parser@^7.27.5", "@babel/parser@^7.27.7": - version "7.27.7" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.27.7.tgz#1687f5294b45039c159730e3b9c1f1b242e425e9" - integrity sha512-qnzXzDXdr/po3bOTbTIQZ7+TxNKxpkN5IifVLXS+r7qwynkZfPyjZfE7hCXbo7IoO9TNcSyibgONsf2HauUd3Q== +"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.23.9", "@babel/parser@^7.26.7", "@babel/parser@^7.27.2", "@babel/parser@^7.27.5", "@babel/parser@^7.28.0": + version "7.28.0" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.28.0.tgz#979829fbab51a29e13901e5a80713dbcb840825e" + integrity sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g== dependencies: - "@babel/types" "^7.27.7" + "@babel/types" "^7.28.0" "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" @@ -2407,23 +2421,23 @@ "@babel/parser" "^7.27.2" "@babel/types" "^7.27.1" -"@babel/traverse@^7.27.1", "@babel/traverse@^7.27.3", "@babel/traverse@^7.27.7": - version "7.27.7" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.27.7.tgz#8355c39be6818362eace058cf7f3e25ac2ec3b55" - integrity sha512-X6ZlfR/O/s5EQ/SnUSLzr+6kGnkg8HXGMzpgsMsrJVcfDtH1vIp6ctCN4eZ1LS5c0+te5Cb6Y514fASjMRJ1nw== +"@babel/traverse@^7.27.1", "@babel/traverse@^7.27.3", "@babel/traverse@^7.28.0": + version "7.28.0" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.28.0.tgz#518aa113359b062042379e333db18380b537e34b" + integrity sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg== dependencies: "@babel/code-frame" "^7.27.1" - "@babel/generator" "^7.27.5" - "@babel/parser" "^7.27.7" + "@babel/generator" "^7.28.0" + "@babel/helper-globals" "^7.28.0" + "@babel/parser" "^7.28.0" "@babel/template" "^7.27.2" - "@babel/types" "^7.27.7" + "@babel/types" "^7.28.0" debug "^4.3.1" - globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.27.1", "@babel/types@^7.27.3", "@babel/types@^7.27.6", "@babel/types@^7.27.7", "@babel/types@^7.3.3": - version "7.27.7" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.27.7.tgz#40eabd562049b2ee1a205fa589e629f945dce20f" - integrity sha512-8OLQgDScAOHXnAz2cV+RfzzNMipuLVBz2biuAJFMV9bfkNf393je3VM8CLkjQodW5+iWsSJdSgSWT6rsZoXHPw== +"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.27.1", "@babel/types@^7.27.3", "@babel/types@^7.27.6", "@babel/types@^7.28.0", "@babel/types@^7.3.3": + version "7.28.1" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.28.1.tgz#2aaf3c10b31ba03a77ac84f52b3912a0edef4cf9" + integrity sha512-x0LvFTekgSX+83TI28Y9wYPUfzrnl2aT5+5QLnO6v7mSJYtEEevuDRN0F0uSHRk1G1IWZC43o00Y0xDDrpBGPQ== dependencies: "@babel/helper-string-parser" "^7.27.1" "@babel/helper-validator-identifier" "^7.27.1" @@ -2438,12 +2452,12 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@cdklabs/cdk-atmosphere-client@^0.0.56": - version "0.0.56" - resolved "https://registry.yarnpkg.com/@cdklabs/cdk-atmosphere-client/-/cdk-atmosphere-client-0.0.56.tgz#95f4134287627cd121362d849d82d054e42c8859" - integrity sha512-3SPfe6nBhxSIIDl34AnbT0WiP63AdtDr5u0/g/RL6XcsG6zzowCJjZyHec2GiXFqyxoHVC/P0u+vviz+H2nf1Q== +"@cdklabs/cdk-atmosphere-client@^0.0.58": + version "0.0.58" + resolved "https://registry.yarnpkg.com/@cdklabs/cdk-atmosphere-client/-/cdk-atmosphere-client-0.0.58.tgz#de99108e71b3864015ca81225d09b3c0de71338a" + integrity sha512-TYTX83D71B8H+yLUZBlTAZPwixyThqDeCxLBFB4xmxfG4FCtlqaxS5E++gj4SVb/YqP6ZMUK3yAAwzxNlfMDSg== dependencies: - "@aws-sdk/credential-providers" "^3.834.0" + "@aws-sdk/credential-providers" "^3.840.0" aws4fetch "^1.0.20" "@cdklabs/eslint-plugin@^1.3.2": @@ -2507,24 +2521,24 @@ node-source-walk "^7.0.1" "@emnapi/core@^1.1.0", "@emnapi/core@^1.4.3": - version "1.4.3" - resolved "https://registry.yarnpkg.com/@emnapi/core/-/core-1.4.3.tgz#9ac52d2d5aea958f67e52c40a065f51de59b77d6" - integrity sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g== + version "1.4.4" + resolved "https://registry.yarnpkg.com/@emnapi/core/-/core-1.4.4.tgz#76620673f3033626c6d79b1420d69f06a6bb153c" + integrity sha512-A9CnAbC6ARNMKcIcrQwq6HeHCjpcBZ5wSx4U01WXCqEKlrzB9F9315WDNHkrs2xbx7YjjSxbUYxuN6EQzpcY2g== dependencies: - "@emnapi/wasi-threads" "1.0.2" + "@emnapi/wasi-threads" "1.0.3" tslib "^2.4.0" "@emnapi/runtime@^1.1.0", "@emnapi/runtime@^1.4.3": - version "1.4.3" - resolved "https://registry.yarnpkg.com/@emnapi/runtime/-/runtime-1.4.3.tgz#c0564665c80dc81c448adac23f9dfbed6c838f7d" - integrity sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ== + version "1.4.4" + resolved "https://registry.yarnpkg.com/@emnapi/runtime/-/runtime-1.4.4.tgz#19a8f00719c51124e2d0fbf4aaad3fa7b0c92524" + integrity sha512-hHyapA4A3gPaDCNfiqyZUStTMqIkKRshqPIuDOXv1hcBnD4U3l8cP0T1HMCfGRxQ6V64TGCcoswChANyOAwbQg== dependencies: tslib "^2.4.0" -"@emnapi/wasi-threads@1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@emnapi/wasi-threads/-/wasi-threads-1.0.2.tgz#977f44f844eac7d6c138a415a123818c655f874c" - integrity sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA== +"@emnapi/wasi-threads@1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@emnapi/wasi-threads/-/wasi-threads-1.0.3.tgz#83fa228bde0e71668aad6db1af4937473d1d3ab1" + integrity sha512-8K5IFFsQqF9wQNJptGbS6FNKgUTsSRYnTqNCG1vPP8jFdjSv18n2mQfJpkt2Oibo9iBEzcDnDxNwKTzC7svlJw== dependencies: tslib "^2.4.0" @@ -2550,130 +2564,135 @@ esquery "^1.6.0" jsdoc-type-pratt-parser "~4.1.0" -"@esbuild/aix-ppc64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz#4e0f91776c2b340e75558f60552195f6fad09f18" - integrity sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA== - -"@esbuild/android-arm64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.5.tgz#bc766407f1718923f6b8079c8c61bf86ac3a6a4f" - integrity sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg== - -"@esbuild/android-arm@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.5.tgz#4290d6d3407bae3883ad2cded1081a234473ce26" - integrity sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA== - -"@esbuild/android-x64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.5.tgz#40c11d9cbca4f2406548c8a9895d321bc3b35eff" - integrity sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw== - -"@esbuild/darwin-arm64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.5.tgz#49d8bf8b1df95f759ac81eb1d0736018006d7e34" - integrity sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ== - -"@esbuild/darwin-x64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.5.tgz#e27a5d92a14886ef1d492fd50fc61a2d4d87e418" - integrity sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ== - -"@esbuild/freebsd-arm64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.5.tgz#97cede59d638840ca104e605cdb9f1b118ba0b1c" - integrity sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw== - -"@esbuild/freebsd-x64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.5.tgz#71c77812042a1a8190c3d581e140d15b876b9c6f" - integrity sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw== - -"@esbuild/linux-arm64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.5.tgz#f7b7c8f97eff8ffd2e47f6c67eb5c9765f2181b8" - integrity sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg== - -"@esbuild/linux-arm@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.5.tgz#2a0be71b6cd8201fa559aea45598dffabc05d911" - integrity sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw== - -"@esbuild/linux-ia32@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.5.tgz#763414463cd9ea6fa1f96555d2762f9f84c61783" - integrity sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA== - -"@esbuild/linux-loong64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.5.tgz#428cf2213ff786a502a52c96cf29d1fcf1eb8506" - integrity sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg== - -"@esbuild/linux-mips64el@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.5.tgz#5cbcc7fd841b4cd53358afd33527cd394e325d96" - integrity sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg== - -"@esbuild/linux-ppc64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.5.tgz#0d954ab39ce4f5e50f00c4f8c4fd38f976c13ad9" - integrity sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ== - -"@esbuild/linux-riscv64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.5.tgz#0e7dd30730505abd8088321e8497e94b547bfb1e" - integrity sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA== - -"@esbuild/linux-s390x@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.5.tgz#5669af81327a398a336d7e40e320b5bbd6e6e72d" - integrity sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ== - -"@esbuild/linux-x64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.5.tgz#b2357dd153aa49038967ddc1ffd90c68a9d2a0d4" - integrity sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw== - -"@esbuild/netbsd-arm64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.5.tgz#53b4dfb8fe1cee93777c9e366893bd3daa6ba63d" - integrity sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw== - -"@esbuild/netbsd-x64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.5.tgz#a0206f6314ce7dc8713b7732703d0f58de1d1e79" - integrity sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ== - -"@esbuild/openbsd-arm64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.5.tgz#2a796c87c44e8de78001d808c77d948a21ec22fd" - integrity sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw== - -"@esbuild/openbsd-x64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.5.tgz#28d0cd8909b7fa3953af998f2b2ed34f576728f0" - integrity sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg== - -"@esbuild/sunos-x64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.5.tgz#a28164f5b997e8247d407e36c90d3fd5ddbe0dc5" - integrity sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA== - -"@esbuild/win32-arm64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.5.tgz#6eadbead38e8bd12f633a5190e45eff80e24007e" - integrity sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw== - -"@esbuild/win32-ia32@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.5.tgz#bab6288005482f9ed2adb9ded7e88eba9a62cc0d" - integrity sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ== - -"@esbuild/win32-x64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz#7fc114af5f6563f19f73324b5d5ff36ece0803d1" - integrity sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g== +"@esbuild/aix-ppc64@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.6.tgz#164b19122e2ed54f85469df9dea98ddb01d5e79e" + integrity sha512-ShbM/3XxwuxjFiuVBHA+d3j5dyac0aEVVq1oluIDf71hUw0aRF59dV/efUsIwFnR6m8JNM2FjZOzmaZ8yG61kw== + +"@esbuild/android-arm64@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.6.tgz#8f539e7def848f764f6432598e51cc3820fde3a5" + integrity sha512-hd5zdUarsK6strW+3Wxi5qWws+rJhCCbMiC9QZyzoxfk5uHRIE8T287giQxzVpEvCwuJ9Qjg6bEjcRJcgfLqoA== + +"@esbuild/android-arm@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.6.tgz#4ceb0f40113e9861169be83e2a670c260dd234ff" + integrity sha512-S8ToEOVfg++AU/bHwdksHNnyLyVM+eMVAOf6yRKFitnwnbwwPNqKr3srzFRe7nzV69RQKb5DgchIX5pt3L53xg== + +"@esbuild/android-x64@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.6.tgz#ad4f280057622c25fe985c08999443a195dc63a8" + integrity sha512-0Z7KpHSr3VBIO9A/1wcT3NTy7EB4oNC4upJ5ye3R7taCc2GUdeynSLArnon5G8scPwaU866d3H4BCrE5xLW25A== + +"@esbuild/darwin-arm64@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.6.tgz#d1f04027396b3d6afc96bacd0d13167dfd9f01f7" + integrity sha512-FFCssz3XBavjxcFxKsGy2DYK5VSvJqa6y5HXljKzhRZ87LvEi13brPrf/wdyl/BbpbMKJNOr1Sd0jtW4Ge1pAA== + +"@esbuild/darwin-x64@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.6.tgz#2b4a6cedb799f635758d7832d75b23772c8ef68f" + integrity sha512-GfXs5kry/TkGM2vKqK2oyiLFygJRqKVhawu3+DOCk7OxLy/6jYkWXhlHwOoTb0WqGnWGAS7sooxbZowy+pK9Yg== + +"@esbuild/freebsd-arm64@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.6.tgz#a26266cc97dd78dc3c3f3d6788b1b83697b1055d" + integrity sha512-aoLF2c3OvDn2XDTRvn8hN6DRzVVpDlj2B/F66clWd/FHLiHaG3aVZjxQX2DYphA5y/evbdGvC6Us13tvyt4pWg== + +"@esbuild/freebsd-x64@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.6.tgz#9feb8e826735c568ebfd94859b22a3fbb6a9bdd2" + integrity sha512-2SkqTjTSo2dYi/jzFbU9Plt1vk0+nNg8YC8rOXXea+iA3hfNJWebKYPs3xnOUf9+ZWhKAaxnQNUf2X9LOpeiMQ== + +"@esbuild/linux-arm64@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.6.tgz#c07cbed8e249f4c28e7f32781d36fc4695293d28" + integrity sha512-b967hU0gqKd9Drsh/UuAm21Khpoh6mPBSgz8mKRq4P5mVK8bpA+hQzmm/ZwGVULSNBzKdZPQBRT3+WuVavcWsQ== + +"@esbuild/linux-arm@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.6.tgz#d6e2cd8ef3196468065d41f13fa2a61aaa72644a" + integrity sha512-SZHQlzvqv4Du5PrKE2faN0qlbsaW/3QQfUUc6yO2EjFcA83xnwm91UbEEVx4ApZ9Z5oG8Bxz4qPE+HFwtVcfyw== + +"@esbuild/linux-ia32@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.6.tgz#3e682bd47c4eddcc4b8f1393dfc8222482f17997" + integrity sha512-aHWdQ2AAltRkLPOsKdi3xv0mZ8fUGPdlKEjIEhxCPm5yKEThcUjHpWB1idN74lfXGnZ5SULQSgtr5Qos5B0bPw== + +"@esbuild/linux-loong64@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.6.tgz#473f5ea2e52399c08ad4cd6b12e6dbcddd630f05" + integrity sha512-VgKCsHdXRSQ7E1+QXGdRPlQ/e08bN6WMQb27/TMfV+vPjjTImuT9PmLXupRlC90S1JeNNW5lzkAEO/McKeJ2yg== + +"@esbuild/linux-mips64el@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.6.tgz#9960631c9fd61605b0939c19043acf4ef2b51718" + integrity sha512-WViNlpivRKT9/py3kCmkHnn44GkGXVdXfdc4drNmRl15zVQ2+D2uFwdlGh6IuK5AAnGTo2qPB1Djppj+t78rzw== + +"@esbuild/linux-ppc64@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.6.tgz#477cbf8bb04aa034b94f362c32c86b5c31db8d3e" + integrity sha512-wyYKZ9NTdmAMb5730I38lBqVu6cKl4ZfYXIs31Baf8aoOtB4xSGi3THmDYt4BTFHk7/EcVixkOV2uZfwU3Q2Jw== + +"@esbuild/linux-riscv64@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.6.tgz#bcdb46c8fb8e93aa779e9a0a62cd4ac00dcac626" + integrity sha512-KZh7bAGGcrinEj4qzilJ4hqTY3Dg2U82c8bv+e1xqNqZCrCyc+TL9AUEn5WGKDzm3CfC5RODE/qc96OcbIe33w== + +"@esbuild/linux-s390x@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.6.tgz#f412cf5fdf0aea849ff51c73fd817c6c0234d46d" + integrity sha512-9N1LsTwAuE9oj6lHMyyAM+ucxGiVnEqUdp4v7IaMmrwb06ZTEVCIs3oPPplVsnjPfyjmxwHxHMF8b6vzUVAUGw== + +"@esbuild/linux-x64@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.6.tgz#d8233c09b5ebc0c855712dc5eeb835a3a3341108" + integrity sha512-A6bJB41b4lKFWRKNrWoP2LHsjVzNiaurf7wyj/XtFNTsnPuxwEBWHLty+ZE0dWBKuSK1fvKgrKaNjBS7qbFKig== + +"@esbuild/netbsd-arm64@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.6.tgz#f51ae8dd1474172e73cf9cbaf8a38d1c72dd8f1a" + integrity sha512-IjA+DcwoVpjEvyxZddDqBY+uJ2Snc6duLpjmkXm/v4xuS3H+3FkLZlDm9ZsAbF9rsfP3zeA0/ArNDORZgrxR/Q== + +"@esbuild/netbsd-x64@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.6.tgz#a267538602c0e50a858cf41dcfe5d8036f8da8e7" + integrity sha512-dUXuZr5WenIDlMHdMkvDc1FAu4xdWixTCRgP7RQLBOkkGgwuuzaGSYcOpW4jFxzpzL1ejb8yF620UxAqnBrR9g== + +"@esbuild/openbsd-arm64@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.6.tgz#a51be60c425b85c216479b8c344ad0511635f2d2" + integrity sha512-l8ZCvXP0tbTJ3iaqdNf3pjaOSd5ex/e6/omLIQCVBLmHTlfXW3zAxQ4fnDmPLOB1x9xrcSi/xtCWFwCZRIaEwg== + +"@esbuild/openbsd-x64@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.6.tgz#7e4a743c73f75562e29223ba69d0be6c9c9008da" + integrity sha512-hKrmDa0aOFOr71KQ/19JC7az1P0GWtCN1t2ahYAf4O007DHZt/dW8ym5+CUdJhQ/qkZmI1HAF8KkJbEFtCL7gw== + +"@esbuild/openharmony-arm64@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.6.tgz#2087a5028f387879154ebf44bdedfafa17682e5b" + integrity sha512-+SqBcAWoB1fYKmpWoQP4pGtx+pUUC//RNYhFdbcSA16617cchuryuhOCRpPsjCblKukAckWsV+aQ3UKT/RMPcA== + +"@esbuild/sunos-x64@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.6.tgz#56531f861723ea0dc6283a2bb8837304223cb736" + integrity sha512-dyCGxv1/Br7MiSC42qinGL8KkG4kX0pEsdb0+TKhmJZgCUDBGmyo1/ArCjNGiOLiIAgdbWgmWgib4HoCi5t7kA== + +"@esbuild/win32-arm64@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.6.tgz#f4989f033deac6fae323acff58764fa8bc01436e" + integrity sha512-42QOgcZeZOvXfsCBJF5Afw73t4veOId//XD3i+/9gSkhSV6Gk3VPlWncctI+JcOyERv85FUo7RxuxGy+z8A43Q== + +"@esbuild/win32-ia32@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.6.tgz#b260e9df71e3939eb33925076d39f63cec7d1525" + integrity sha512-4AWhgXmDuYN7rJI6ORB+uU9DHLq/erBbuMoAuB4VWJTu5KtCgcKYPynF0YI1VkBNuEfjNlLrFr9KZPJzrtLkrQ== + +"@esbuild/win32-x64@0.25.6": + version "0.25.6" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.6.tgz#4276edd5c105bc28b11c6a1f76fb9d29d1bd25c1" + integrity sha512-NgJPHHbEpLQgDH2MjQu90pzW/5vvXIZ7KOnPyNBm92A6WgZ/7b6fJyUBjoumLqeOQQGqY2QjQxRo97ah4Sj0cA== "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.7.0": version "4.7.0" @@ -2701,14 +2720,7 @@ resolved "https://registry.yarnpkg.com/@eslint/config-helpers/-/config-helpers-0.3.0.tgz#3e09a90dfb87e0005c7694791e58e97077271286" integrity sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw== -"@eslint/core@^0.14.0": - version "0.14.0" - resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.14.0.tgz#326289380968eaf7e96f364e1e4cf8f3adf2d003" - integrity sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg== - dependencies: - "@types/json-schema" "^7.0.15" - -"@eslint/core@^0.15.1": +"@eslint/core@^0.15.0", "@eslint/core@^0.15.1": version "0.15.1" resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.15.1.tgz#d530d44209cbfe2f82ef86d6ba08760196dd3b60" integrity sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA== @@ -2730,10 +2742,10 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@eslint/js@9.30.0": - version "9.30.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.30.0.tgz#c396fa450d5505dd9b7b8846b33f0491aebd9a2d" - integrity sha512-Wzw3wQwPvc9sHM+NjakWTcPx11mbZyiYHuwWa/QfZ7cIRX7WK54PSk7bdyXDaoaopUcMatv1zaQvOAAO8hCdww== +"@eslint/js@9.31.0": + version "9.31.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.31.0.tgz#adb1f39953d8c475c4384b67b67541b0d7206ed8" + integrity sha512-LOm5OVt7D4qiKCqoiPbA7LWmI+tbw1VbTUowBcUMgQSuM6poJufkFkYDcQpo5KfgD39TnNySV26QjOh7VFpSyw== "@eslint/object-schema@^2.1.6": version "2.1.6" @@ -2902,10 +2914,10 @@ resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== -"@jest/console@30.0.2": - version "30.0.2" - resolved "https://registry.yarnpkg.com/@jest/console/-/console-30.0.2.tgz#e2bf6c7703d45f9824d77c7332388c3e1685afd7" - integrity sha512-krGElPU0FipAqpVZ/BRZOy0MZh/ARdJ0Nj+PiH1ykFY1+VpBlYNLjdjVA5CFKxnKR6PFqFutO4Z7cdK9BlGiDA== +"@jest/console@30.0.4": + version "30.0.4" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-30.0.4.tgz#943a62c3c8e3f495290f2e2c3749b7b4516c3e93" + integrity sha512-tMLCDvBJBwPqMm4OAiuKm2uF5y5Qe26KgcMn+nrDSWpEW+eeFmqA0iO4zJfL16GP7gE3bUUQ3hIuUJ22AqVRnw== dependencies: "@jest/types" "30.0.1" "@types/node" "*" @@ -2926,16 +2938,16 @@ jest-util "^29.7.0" slash "^3.0.0" -"@jest/core@30.0.3": - version "30.0.3" - resolved "https://registry.yarnpkg.com/@jest/core/-/core-30.0.3.tgz#87967dd3ea6bd6bc98e99aa4b47bfbb0b7f2a77e" - integrity sha512-Mgs1N+NSHD3Fusl7bOq1jyxv1JDAUwjy+0DhVR93Q6xcBP9/bAQ+oZhXb5TTnP5sQzAHgb7ROCKQ2SnovtxYtg== +"@jest/core@30.0.4": + version "30.0.4" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-30.0.4.tgz#a8fc7fcdc8a650f50f33dd585d774a1f683e9e59" + integrity sha512-MWScSO9GuU5/HoWjpXAOBs6F/iobvK1XlioelgOM9St7S0Z5WTI9kjCQLPeo4eQRRYusyLW25/J7J5lbFkrYXw== dependencies: - "@jest/console" "30.0.2" + "@jest/console" "30.0.4" "@jest/pattern" "30.0.1" - "@jest/reporters" "30.0.2" - "@jest/test-result" "30.0.2" - "@jest/transform" "30.0.2" + "@jest/reporters" "30.0.4" + "@jest/test-result" "30.0.4" + "@jest/transform" "30.0.4" "@jest/types" "30.0.1" "@types/node" "*" ansi-escapes "^4.3.2" @@ -2944,18 +2956,18 @@ exit-x "^0.2.2" graceful-fs "^4.2.11" jest-changed-files "30.0.2" - jest-config "30.0.3" + jest-config "30.0.4" jest-haste-map "30.0.2" jest-message-util "30.0.2" jest-regex-util "30.0.1" jest-resolve "30.0.2" - jest-resolve-dependencies "30.0.3" - jest-runner "30.0.3" - jest-runtime "30.0.3" - jest-snapshot "30.0.3" + jest-resolve-dependencies "30.0.4" + jest-runner "30.0.4" + jest-runtime "30.0.4" + jest-snapshot "30.0.4" jest-util "30.0.2" jest-validate "30.0.2" - jest-watcher "30.0.2" + jest-watcher "30.0.4" micromatch "^4.0.8" pretty-format "30.0.2" slash "^3.0.0" @@ -2999,12 +3011,12 @@ resolved "https://registry.yarnpkg.com/@jest/diff-sequences/-/diff-sequences-30.0.1.tgz#0ededeae4d071f5c8ffe3678d15f3a1be09156be" integrity sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw== -"@jest/environment@30.0.2": - version "30.0.2" - resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-30.0.2.tgz#1b0d055070e97f697e9edb25059e9435221cbe65" - integrity sha512-hRLhZRJNxBiOhxIKSq2UkrlhMt3/zVFQOAi5lvS8T9I03+kxsbflwHJEF+eXEYXCrRGRhHwECT7CDk6DyngsRA== +"@jest/environment@30.0.4": + version "30.0.4" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-30.0.4.tgz#fb0deafd8a3cbb06cd9ce0b52c6bcaf342778428" + integrity sha512-5NT+sr7ZOb8wW7C4r7wOKnRQ8zmRWQT2gW4j73IXAKp5/PX1Z8MCStBLQDYfIG3n1Sw0NRfYGdp0iIPVooBAFQ== dependencies: - "@jest/fake-timers" "30.0.2" + "@jest/fake-timers" "30.0.4" "@jest/types" "30.0.1" "@types/node" "*" jest-mock "30.0.2" @@ -3019,10 +3031,10 @@ "@types/node" "*" jest-mock "^29.7.0" -"@jest/expect-utils@30.0.3": - version "30.0.3" - resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-30.0.3.tgz#2a9fb40110c8a13ae464da41f877df90d2e6bc3b" - integrity sha512-SMtBvf2sfX2agcT0dA9pXwcUrKvOSDqBY4e4iRfT+Hya33XzV35YVg+98YQFErVGA/VR1Gto5Y2+A6G9LSQ3Yg== +"@jest/expect-utils@30.0.4": + version "30.0.4" + resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-30.0.4.tgz#0512fb2588c7fc463ce26fb38c0d47814266d965" + integrity sha512-EgXecHDNfANeqOkcak0DxsoVI4qkDUsR7n/Lr2vtmTBjwLPBnnPOF71S11Q8IObWzxm2QgQoY6f9hzrRD3gHRA== dependencies: "@jest/get-type" "30.0.1" @@ -3033,13 +3045,13 @@ dependencies: jest-get-type "^29.6.3" -"@jest/expect@30.0.3": - version "30.0.3" - resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-30.0.3.tgz#9653e868ca27dd2194f6c20c81b8a690f9669465" - integrity sha512-73BVLqfCeWjYWPEQoYjiRZ4xuQRhQZU0WdgvbyXGRHItKQqg5e6mt2y1kVhzLSuZpmUnccZHbGynoaL7IcLU3A== +"@jest/expect@30.0.4": + version "30.0.4" + resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-30.0.4.tgz#de25549873ccc0302faeef96044acae464f50997" + integrity sha512-Z/DL7t67LBHSX4UzDyeYKqOxE/n7lbrrgEwWM3dGiH5Dgn35nk+YtgzKudmfIrBI8DRRrKYY5BCo3317HZV1Fw== dependencies: - expect "30.0.3" - jest-snapshot "30.0.3" + expect "30.0.4" + jest-snapshot "30.0.4" "@jest/expect@^29.7.0": version "29.7.0" @@ -3049,10 +3061,10 @@ expect "^29.7.0" jest-snapshot "^29.7.0" -"@jest/fake-timers@30.0.2": - version "30.0.2" - resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-30.0.2.tgz#ec758b28ae6f63a49eda9e8d6af274d152d37c09" - integrity sha512-jfx0Xg7l0gmphTY9UKm5RtH12BlLYj/2Plj6wXjVW5Era4FZKfXeIvwC67WX+4q8UCFxYS20IgnMcFBcEU0DtA== +"@jest/fake-timers@30.0.4": + version "30.0.4" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-30.0.4.tgz#fdd4552541a99826e488fc01afdb7626d6ad46cd" + integrity sha512-qZ7nxOcL5+gwBO6LErvwVy5k06VsX/deqo2XnVUSTV0TNC9lrg8FC3dARbi+5lmrr5VyX5drragK+xLcOjvjYw== dependencies: "@jest/types" "30.0.1" "@sinonjs/fake-timers" "^13.0.0" @@ -3078,13 +3090,13 @@ resolved "https://registry.yarnpkg.com/@jest/get-type/-/get-type-30.0.1.tgz#0d32f1bbfba511948ad247ab01b9007724fc9f52" integrity sha512-AyYdemXCptSRFirI5EPazNxyPwAL0jXt3zceFjaj8NFiKP9pOi0bfXonf6qkf82z2t3QWPeLCWWw4stPBzctLw== -"@jest/globals@30.0.3": - version "30.0.3" - resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-30.0.3.tgz#9c9ef55e6f5e6b7e946244bdbf2af85044b7bb04" - integrity sha512-fIduqNyYpMeeSr5iEAiMn15KxCzvrmxl7X7VwLDRGj7t5CoHtbF+7K3EvKk32mOUIJ4kIvFRlaixClMH2h/Vaw== +"@jest/globals@30.0.4": + version "30.0.4" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-30.0.4.tgz#8650aa24c587fae830915b5c3518e82bd2ac5e60" + integrity sha512-avyZuxEHF2EUhFF6NEWVdxkRRV6iXXcIES66DLhuLlU7lXhtFG/ySq/a8SRZmEJSsLkNAFX6z6mm8KWyXe9OEA== dependencies: - "@jest/environment" "30.0.2" - "@jest/expect" "30.0.3" + "@jest/environment" "30.0.4" + "@jest/expect" "30.0.4" "@jest/types" "30.0.1" jest-mock "30.0.2" @@ -3106,15 +3118,15 @@ "@types/node" "*" jest-regex-util "30.0.1" -"@jest/reporters@30.0.2": - version "30.0.2" - resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-30.0.2.tgz#e804435ab77cd05b7e8732b91006cd00bd822399" - integrity sha512-l4QzS/oKf57F8WtPZK+vvF4Io6ukplc6XgNFu4Hd/QxaLEO9f+8dSFzUua62Oe0HKlCUjKHpltKErAgDiMJKsA== +"@jest/reporters@30.0.4": + version "30.0.4" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-30.0.4.tgz#8ff5939713f643f788b48d3edcf15f2c06a00a63" + integrity sha512-6ycNmP0JSJEEys1FbIzHtjl9BP0tOZ/KN6iMeAKrdvGmUsa1qfRdlQRUDKJ4P84hJ3xHw1yTqJt4fvPNHhyE+g== dependencies: "@bcoe/v8-coverage" "^0.2.3" - "@jest/console" "30.0.2" - "@jest/test-result" "30.0.2" - "@jest/transform" "30.0.2" + "@jest/console" "30.0.4" + "@jest/test-result" "30.0.4" + "@jest/transform" "30.0.4" "@jest/types" "30.0.1" "@jridgewell/trace-mapping" "^0.3.25" "@types/node" "*" @@ -3179,10 +3191,10 @@ dependencies: "@sinclair/typebox" "^0.27.8" -"@jest/snapshot-utils@30.0.1": - version "30.0.1" - resolved "https://registry.yarnpkg.com/@jest/snapshot-utils/-/snapshot-utils-30.0.1.tgz#536108aa6b74858d758ae3b5229518c3d818bd68" - integrity sha512-6Dpv7vdtoRiISEFwYF8/c7LIvqXD7xDXtLPNzC2xqAfBznKip0MQM+rkseKwUPUpv2PJ7KW/YsnwWXrIL2xF+A== +"@jest/snapshot-utils@30.0.4": + version "30.0.4" + resolved "https://registry.yarnpkg.com/@jest/snapshot-utils/-/snapshot-utils-30.0.4.tgz#cd5b3d21e19255106b12350d55c1b9bf613fbcfa" + integrity sha512-BEpX8M/Y5lG7MI3fmiO+xCnacOrVsnbqVrcDZIT8aSGkKV1w2WwvRQxSWw5SIS8ozg7+h8tSj5EO1Riqqxcdag== dependencies: "@jest/types" "30.0.1" chalk "^4.1.2" @@ -3207,12 +3219,12 @@ callsites "^3.0.0" graceful-fs "^4.2.9" -"@jest/test-result@30.0.2": - version "30.0.2" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-30.0.2.tgz#786849e33da6060381c508986fa7309ff855a367" - integrity sha512-KKMuBKkkZYP/GfHMhI+cH2/P3+taMZS3qnqqiPC1UXZTJskkCS+YU/ILCtw5anw1+YsTulDHFpDo70mmCedW8w== +"@jest/test-result@30.0.4": + version "30.0.4" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-30.0.4.tgz#0b1c4e8256e3f9ebb9452ede22d4b04b31ea54fe" + integrity sha512-Mfpv8kjyKTHqsuu9YugB6z1gcdB3TSSOaKlehtVaiNlClMkEHY+5ZqCY2CrEE3ntpBMlstX/ShDAf84HKWsyIw== dependencies: - "@jest/console" "30.0.2" + "@jest/console" "30.0.4" "@jest/types" "30.0.1" "@types/istanbul-lib-coverage" "^2.0.6" collect-v8-coverage "^1.0.2" @@ -3227,12 +3239,12 @@ "@types/istanbul-lib-coverage" "^2.0.0" collect-v8-coverage "^1.0.0" -"@jest/test-sequencer@30.0.2": - version "30.0.2" - resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-30.0.2.tgz#2693692d285b1c929ed353f7f0b7cbea51c57515" - integrity sha512-fbyU5HPka0rkalZ3MXVvq0hwZY8dx3Y6SCqR64zRmh+xXlDeFl0IdL4l9e7vp4gxEXTYHbwLFA1D+WW5CucaSw== +"@jest/test-sequencer@30.0.4": + version "30.0.4" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-30.0.4.tgz#4ef749c994beca340e274e67a4c90f0154482e5f" + integrity sha512-bj6ePmqi4uxAE8EHE0Slmk5uBYd9Vd/PcVt06CsBxzH4bbA8nGsI1YbXl/NH+eii4XRtyrRx+Cikub0x8H4vDg== dependencies: - "@jest/test-result" "30.0.2" + "@jest/test-result" "30.0.4" graceful-fs "^4.2.11" jest-haste-map "30.0.2" slash "^3.0.0" @@ -3247,10 +3259,10 @@ jest-haste-map "^29.7.0" slash "^3.0.0" -"@jest/transform@30.0.2": - version "30.0.2" - resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-30.0.2.tgz#62ba84fcc2389ab751e7ec923958c9b1163d90c3" - integrity sha512-kJIuhLMTxRF7sc0gPzPtCDib/V9KwW3I2U25b+lYCYMVqHHSrcZopS8J8H+znx9yixuFv+Iozl8raLt/4MoxrA== +"@jest/transform@30.0.4": + version "30.0.4" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-30.0.4.tgz#a06f8c6fc2a04985241b483096f821bafb99cc93" + integrity sha512-atvy4hRph/UxdCIBp+UB2jhEA/jJiUeGZ7QPgBi9jUUKNgi3WEoMXGNG7zbbELG2+88PMabUNCDchmqgJy3ELg== dependencies: "@babel/core" "^7.27.4" "@jest/types" "30.0.1" @@ -3314,10 +3326,10 @@ "@types/yargs" "^17.0.8" chalk "^4.0.0" -"@jridgewell/gen-mapping@^0.3.5": - version "0.3.9" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.9.tgz#6651c7afca59e19abd00cd40346d13e225026c83" - integrity sha512-xpz6C/vXOegF9VEtlMBlkNNIjHrLhKaFBsO4lmQGr00x5BHp7p+oliR6i7LwIcM5cZU2VjLSwm2R+/zj5IjPWg== +"@jridgewell/gen-mapping@^0.3.12", "@jridgewell/gen-mapping@^0.3.5": + version "0.3.12" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz#2234ce26c62889f03db3d7fea43c1932ab3e927b" + integrity sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg== dependencies: "@jridgewell/sourcemap-codec" "^1.5.0" "@jridgewell/trace-mapping" "^0.3.24" @@ -3328,9 +3340,9 @@ integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== "@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.5.0": - version "1.5.1" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.1.tgz#92bc8eb57aea47c13291476e4d2d246928487720" - integrity sha512-mBLKRHc7Ffw/hObYb9+cunuGNjshQk+vZdwZBJoqiysK/mW3Jq0UXosq8aIhMnLevANhR9yoYfdUEOHg6M9y0g== + version "1.5.4" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz#7358043433b2e5da569aa02cbc4c121da3af27d7" + integrity sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw== "@jridgewell/trace-mapping@0.3.9": version "0.3.9" @@ -3340,10 +3352,10 @@ "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" -"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.23", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": - version "0.3.26" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.26.tgz#c337086fa5c013466b988141e00b0d67c8091a8e" - integrity sha512-Z9rjt4BUVEbLFpw0qjCklVxxf421wrmcbP4w+LmBUxYCyJTYYSclgJD0YsCgGqQCtCIPiz7kjbYYJiAKhjJ3kA== +"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.23", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25", "@jridgewell/trace-mapping@^0.3.28": + version "0.3.29" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz#a58d31eaadaf92c6695680b2e1d464a9b8fbf7fc" + integrity sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ== dependencies: "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" @@ -3416,13 +3428,13 @@ "@tybys/wasm-util" "^0.9.0" "@napi-rs/wasm-runtime@^0.2.11": - version "0.2.11" - resolved "https://registry.yarnpkg.com/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.11.tgz#192c1610e1625048089ab4e35bc0649ce478500e" - integrity sha512-9DPkXtvHydrcOsopiYpUgPHpmj0HWZKMUnL2dZqpvC42lsratuBG06V5ipyno0fUek5VlFsNQ+AcFATSrJXgMA== + version "0.2.12" + resolved "https://registry.yarnpkg.com/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz#3e78a8b96e6c33a6c517e1894efbd5385a7cb6f2" + integrity sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ== dependencies: "@emnapi/core" "^1.4.3" "@emnapi/runtime" "^1.4.3" - "@tybys/wasm-util" "^0.9.0" + "@tybys/wasm-util" "^0.10.0" "@nodelib/fs.scandir@2.1.5": version "2.1.5" @@ -3676,9 +3688,9 @@ integrity sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA== "@octokit/core@^5.0.2": - version "5.2.1" - resolved "https://registry.yarnpkg.com/@octokit/core/-/core-5.2.1.tgz#58c21a5f689ee81e0b883b5aa77573a7ff1b4ea1" - integrity sha512-dKYCMuPO1bmrpuogcjQ8z7ICCH3FP6WmxpwC03yjzGfZhj9fTJg6+bS1+UAplekbN2C+M61UNllGOOoAfGCrdQ== + version "5.2.2" + resolved "https://registry.yarnpkg.com/@octokit/core/-/core-5.2.2.tgz#252805732de9b4e8e4f658d34b80c4c9b2534761" + integrity sha512-/g2d4sW9nUDJOMz3mabVQvOGhVa4e/BN/Um7yca9Bb2XTzPPnfTWHWQg+IsEYO7M3Vx+EXvaM/I2pJWIMun1bg== dependencies: "@octokit/auth-token" "^4.0.0" "@octokit/graphql" "^7.1.0" @@ -3901,9 +3913,9 @@ integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== "@sinclair/typebox@^0.34.0": - version "0.34.37" - resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.34.37.tgz#f331e4db64ff8195e9e3d8449343c85aaa237d6e" - integrity sha512-2TRuQVgQYfy+EzHRTIvkhv2ADEouJ2xNS/Vq+W5EuuewBdOrvATvljZTxHWZSTYr2sTjTHpGvucaGAt67S2akw== + version "0.34.38" + resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.34.38.tgz#2365df7c23406a4d79413a766567bfbca708b49d" + integrity sha512-HpkxMmc2XmZKhvaKIZZThlHmx1L0I/V1hWK1NubtlFnr6ZqdiOpV72TKudZUNQjZNsyDBay72qFEhEvb+bcwcA== "@sinonjs/commons@^1.6.0", "@sinonjs/commons@^1.7.0", "@sinonjs/commons@^1.8.1": version "1.8.6" @@ -4012,10 +4024,10 @@ "@smithy/util-middleware" "^4.0.4" tslib "^2.6.2" -"@smithy/core@^3.6.0": - version "3.6.0" - resolved "https://registry.yarnpkg.com/@smithy/core/-/core-3.6.0.tgz#be02f2a4a56ba83d37298454a0bddc89cbad510b" - integrity sha512-Pgvfb+TQ4wUNLyHzvgCP4aYZMh16y7GcfF59oirRHcgGgkH1e/s9C0nv/v3WP+Quymyr5je71HeFQCwh+44XLg== +"@smithy/core@^3.7.0": + version "3.7.0" + resolved "https://registry.yarnpkg.com/@smithy/core/-/core-3.7.0.tgz#b3a98ccc48b1c408dfdb986aaa22d6affffd7795" + integrity sha512-7ov8hu/4j0uPZv8b27oeOFtIBtlFmM3ibrPv/Omx1uUdoXvcpJ00U+H/OWWC/keAguLlcqwtyL2/jTlSnApgNQ== dependencies: "@smithy/middleware-serde" "^4.0.8" "@smithy/protocol-http" "^5.1.2" @@ -4023,7 +4035,7 @@ "@smithy/util-base64" "^4.0.0" "@smithy/util-body-length-browser" "^4.0.0" "@smithy/util-middleware" "^4.0.4" - "@smithy/util-stream" "^4.2.2" + "@smithy/util-stream" "^4.2.3" "@smithy/util-utf8" "^4.0.0" tslib "^2.6.2" @@ -4083,10 +4095,10 @@ "@smithy/types" "^4.3.1" tslib "^2.6.2" -"@smithy/fetch-http-handler@^5.0.4": - version "5.0.4" - resolved "https://registry.yarnpkg.com/@smithy/fetch-http-handler/-/fetch-http-handler-5.0.4.tgz#c68601b4676787e049b5d464d5f4b825dbb44013" - integrity sha512-AMtBR5pHppYMVD7z7G+OlHHAcgAN7v0kVKEpHuTO4Gb199Gowh0taYi9oDStFeUhetkeP55JLSVlTW1n9rFtUw== +"@smithy/fetch-http-handler@^5.1.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@smithy/fetch-http-handler/-/fetch-http-handler-5.1.0.tgz#387abd9ec6c8ff0af33b268c0f6ccb289c1b1563" + integrity sha512-mADw7MS0bYe2OGKkHYMaqarOXuDwRbO6ArD91XhHcl2ynjGCFF+hvqf0LyQcYxkA1zaWjefSkU7Ne9mqgApSgQ== dependencies: "@smithy/protocol-http" "^5.1.2" "@smithy/querystring-builder" "^4.0.4" @@ -4174,12 +4186,12 @@ "@smithy/util-middleware" "^1.1.0" tslib "^2.5.0" -"@smithy/middleware-endpoint@^4", "@smithy/middleware-endpoint@^4.1.13": - version "4.1.13" - resolved "https://registry.yarnpkg.com/@smithy/middleware-endpoint/-/middleware-endpoint-4.1.13.tgz#7d5b5f8f61600270bd8c59aabf311c99b9127aba" - integrity sha512-xg3EHV/Q5ZdAO5b0UiIMj3RIOCobuS40pBBODguUDVdko6YK6QIzCVRrHTogVuEKglBWqWenRnZ71iZnLL3ZAQ== +"@smithy/middleware-endpoint@^4", "@smithy/middleware-endpoint@^4.1.15": + version "4.1.15" + resolved "https://registry.yarnpkg.com/@smithy/middleware-endpoint/-/middleware-endpoint-4.1.15.tgz#31d93e6f33bbe2dbd120bda0833bce35cf960c39" + integrity sha512-L2M0oz+r6Wv0KZ90MgClXmWkV7G72519Hd5/+K5i3gQMu4WNQykh7ERr58WT3q60dd9NqHSMc3/bAK0FsFg3Fw== dependencies: - "@smithy/core" "^3.6.0" + "@smithy/core" "^3.7.0" "@smithy/middleware-serde" "^4.0.8" "@smithy/node-config-provider" "^4.1.3" "@smithy/shared-ini-file-loader" "^4.0.4" @@ -4188,15 +4200,15 @@ "@smithy/util-middleware" "^4.0.4" tslib "^2.6.2" -"@smithy/middleware-retry@^4.1.14": - version "4.1.14" - resolved "https://registry.yarnpkg.com/@smithy/middleware-retry/-/middleware-retry-4.1.14.tgz#53ce619463a1ce4b95025aaafdf51369ef893196" - integrity sha512-eoXaLlDGpKvdmvt+YBfRXE7HmIEtFF+DJCbTPwuLunP0YUnrydl+C4tS+vEM0+nyxXrX3PSUFqC+lP1+EHB1Tw== +"@smithy/middleware-retry@^4.1.16": + version "4.1.16" + resolved "https://registry.yarnpkg.com/@smithy/middleware-retry/-/middleware-retry-4.1.16.tgz#0e044d0da18e7019052ac61ec02a2956437376fd" + integrity sha512-PpPhMpC6U1fLW0evKnC8gJtmobBYn0oi4RrIKGhN1a86t6XgVEK+Vb9C8dh5PPXb3YDr8lE6aYKh1hd3OikmWw== dependencies: "@smithy/node-config-provider" "^4.1.3" "@smithy/protocol-http" "^5.1.2" "@smithy/service-error-classification" "^4.0.6" - "@smithy/smithy-client" "^4.4.5" + "@smithy/smithy-client" "^4.4.7" "@smithy/types" "^4.3.1" "@smithy/util-middleware" "^4.0.4" "@smithy/util-retry" "^4.0.6" @@ -4238,10 +4250,10 @@ "@smithy/types" "^4.3.1" tslib "^2.6.2" -"@smithy/node-http-handler@^4.0.6": - version "4.0.6" - resolved "https://registry.yarnpkg.com/@smithy/node-http-handler/-/node-http-handler-4.0.6.tgz#a022da499ba3af4b6b4c815104fde973c0eccc40" - integrity sha512-NqbmSz7AW2rvw4kXhKGrYTiJVDHnMsFnX4i+/FzcZAfbOBauPYs2ekuECkSbtqaxETLLTu9Rl/ex6+I2BKErPA== +"@smithy/node-http-handler@^4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@smithy/node-http-handler/-/node-http-handler-4.1.0.tgz#6b528cd0da0c35755b34afba207b7db972b0eb92" + integrity sha512-vqfSiHz2v8b3TTTrdXi03vNz1KLYYS3bhHCDv36FYDqxT7jvTll1mMnCrkD+gOvgwybuunh/2VmvOMqwBegxEg== dependencies: "@smithy/abort-controller" "^4.0.4" "@smithy/protocol-http" "^5.1.2" @@ -4324,17 +4336,17 @@ "@smithy/util-utf8" "^4.0.0" tslib "^2.6.2" -"@smithy/smithy-client@^4.4.5": - version "4.4.5" - resolved "https://registry.yarnpkg.com/@smithy/smithy-client/-/smithy-client-4.4.5.tgz#1c736618f3c4910880cc6862a5826348c1b70d5d" - integrity sha512-+lynZjGuUFJaMdDYSTMnP/uPBBXXukVfrJlP+1U/Dp5SFTEI++w6NMga8DjOENxecOF71V9Z2DllaVDYRnGlkg== +"@smithy/smithy-client@^4.4.7": + version "4.4.7" + resolved "https://registry.yarnpkg.com/@smithy/smithy-client/-/smithy-client-4.4.7.tgz#68e9f7785179060896ed51d52cd4f4cfc1cbffb5" + integrity sha512-x+MxBNOcG7rY9i5QsbdgvvRJngKKvUJrbU5R5bT66PTH3e6htSupJ4Q+kJ3E7t6q854jyl57acjpPi6qG1OY5g== dependencies: - "@smithy/core" "^3.6.0" - "@smithy/middleware-endpoint" "^4.1.13" + "@smithy/core" "^3.7.0" + "@smithy/middleware-endpoint" "^4.1.15" "@smithy/middleware-stack" "^4.0.4" "@smithy/protocol-http" "^5.1.2" "@smithy/types" "^4.3.1" - "@smithy/util-stream" "^4.2.2" + "@smithy/util-stream" "^4.2.3" tslib "^2.6.2" "@smithy/types@^1.2.0": @@ -4415,27 +4427,27 @@ dependencies: tslib "^2.6.2" -"@smithy/util-defaults-mode-browser@^4.0.21": - version "4.0.21" - resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.0.21.tgz#47895e42d64060d2a7f803a443fd160d0a329d83" - integrity sha512-wM0jhTytgXu3wzJoIqpbBAG5U6BwiubZ6QKzSbP7/VbmF1v96xlAbX2Am/mz0Zep0NLvLh84JT0tuZnk3wmYQA== +"@smithy/util-defaults-mode-browser@^4.0.23": + version "4.0.23" + resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.0.23.tgz#74887922f87da4f4acbf523b5c0271f11af5997d" + integrity sha512-NqRi6VvEIwpJ+KSdqI85+HH46H7uVoNqVTs2QO7p1YKnS7k8VZnunJj8R5KdmmVnTojkaL1OMPyZC8uR5F7fSg== dependencies: "@smithy/property-provider" "^4.0.4" - "@smithy/smithy-client" "^4.4.5" + "@smithy/smithy-client" "^4.4.7" "@smithy/types" "^4.3.1" bowser "^2.11.0" tslib "^2.6.2" -"@smithy/util-defaults-mode-node@^4.0.21": - version "4.0.21" - resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.0.21.tgz#4682143fbfb0a4c6e08a6151f13af97018e6950e" - integrity sha512-/F34zkoU0GzpUgLJydHY8Rxu9lBn8xQC/s/0M0U9lLBkYbA1htaAFjWYJzpzsbXPuri5D1H8gjp2jBum05qBrA== +"@smithy/util-defaults-mode-node@^4.0.23": + version "4.0.23" + resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.0.23.tgz#dd22609289183fe3d722f9a1601b6cc618f9efa7" + integrity sha512-NE9NtEVigFa+HHJ5bBeQT7KF3KiltW880CLN9TnWWL55akeou3ziRAHO22QSUPgPZ/nqMfPXi/LGMQ6xQvXPNQ== dependencies: "@smithy/config-resolver" "^4.1.4" "@smithy/credential-provider-imds" "^4.0.6" "@smithy/node-config-provider" "^4.1.3" "@smithy/property-provider" "^4.0.4" - "@smithy/smithy-client" "^4.4.5" + "@smithy/smithy-client" "^4.4.7" "@smithy/types" "^4.3.1" tslib "^2.6.2" @@ -4487,13 +4499,13 @@ "@smithy/types" "^4.3.1" tslib "^2.6.2" -"@smithy/util-stream@^4.2.2": - version "4.2.2" - resolved "https://registry.yarnpkg.com/@smithy/util-stream/-/util-stream-4.2.2.tgz#beeb1edf690db9b7d7983f46ca4fb66e22253608" - integrity sha512-aI+GLi7MJoVxg24/3J1ipwLoYzgkB4kUfogZfnslcYlynj3xsQ0e7vk4TnTro9hhsS5PvX1mwmkRqqHQjwcU7w== +"@smithy/util-stream@^4.2.3": + version "4.2.3" + resolved "https://registry.yarnpkg.com/@smithy/util-stream/-/util-stream-4.2.3.tgz#7980fb94dbee96301b0b2610de8ae1700c7daab1" + integrity sha512-cQn412DWHHFNKrQfbHY8vSFI3nTROY1aIKji9N0tpp8gUABRilr7wdf8fqBbSlXresobM+tQFNk6I+0LXK/YZg== dependencies: - "@smithy/fetch-http-handler" "^5.0.4" - "@smithy/node-http-handler" "^4.0.6" + "@smithy/fetch-http-handler" "^5.1.0" + "@smithy/node-http-handler" "^4.1.0" "@smithy/types" "^4.3.1" "@smithy/util-base64" "^4.0.0" "@smithy/util-buffer-from" "^4.0.0" @@ -4618,6 +4630,13 @@ "@tufjs/canonical-json" "2.0.0" minimatch "^9.0.5" +"@tybys/wasm-util@^0.10.0": + version "0.10.0" + resolved "https://registry.yarnpkg.com/@tybys/wasm-util/-/wasm-util-0.10.0.tgz#2fd3cd754b94b378734ce17058d0507c45c88369" + integrity sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ== + dependencies: + tslib "^2.4.0" + "@tybys/wasm-util@^0.9.0": version "0.9.0" resolved "https://registry.yarnpkg.com/@tybys/wasm-util/-/wasm-util-0.9.0.tgz#3e75eb00604c8d6db470bf18c37b7d984a0e3355" @@ -4709,14 +4728,6 @@ dependencies: "@types/node" "*" -"@types/glob@^7": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.2.0.tgz#bc1b5bf3aa92f25bd5dd39f35c57361bdce5b2eb" - integrity sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA== - dependencies: - "@types/minimatch" "*" - "@types/node" "*" - "@types/graceful-fs@^4.1.3": version "4.1.9" resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.9.tgz#2a06bc0f68a20ab37b3e36aa238be6abdf49e8b4" @@ -4791,20 +4802,15 @@ "@types/lodash" "*" "@types/lodash@*": - version "4.17.19" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.19.tgz#de18c90b7891f00fed7c1273495a2f851efd99c4" - integrity sha512-NYqRyg/hIQrYPT9lbOeYc3kIRabJDn/k4qQHIXUpx88CBDww2fD15Sg5kbXlW86zm2XEW4g0QxkTI3/Kfkc7xQ== + version "4.17.20" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.20.tgz#1ca77361d7363432d29f5e55950d9ec1e1c6ea93" + integrity sha512-H3MHACvFUEiujabxhaI/ImO6gUrd8oOurg7LQtS7mbwIXA/cUqWrvBsaeJ23aZEPk1TAYkurjfMbSELfoCXlGA== "@types/mime@^2": version "2.0.3" resolved "https://registry.yarnpkg.com/@types/mime/-/mime-2.0.3.tgz#c893b73721db73699943bfc3653b1deb7faa4a3a" integrity sha512-Jus9s4CDbqwocc5pOAnh8ShfrnMcPHuJYzVcSUU7lrh8Ni5HuIqX3oilL86p3dlTrk0LzHRCgA/GQ7uNCw6l2Q== -"@types/minimatch@*": - version "5.1.2" - resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-5.1.2.tgz#07508b45797cb81ec3f273011b054cd0755eddca" - integrity sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA== - "@types/minimist@^1.2.0": version "1.2.5" resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.5.tgz#ec10755e871497bcd83efe927e43ec46e8c0747e" @@ -4822,10 +4828,10 @@ resolved "https://registry.yarnpkg.com/@types/mockery/-/mockery-1.4.33.tgz#fb511e702e38b67e95af8b1375a65350b3fb5cab" integrity sha512-vpuuVxCnCEM0OakYNoyFs40mjJFJFJahBHyx0Z0Piysof+YwlDJzNO4V1weRvYySAmtAvlb0UHtxVO2IfTcykw== -"@types/node@*", "@types/node@ts5.6": - version "24.0.7" - resolved "https://registry.yarnpkg.com/@types/node/-/node-24.0.7.tgz#ee580f7850c7eabaeef61ef96b8d8c04fdf94f53" - integrity sha512-YIEUUr4yf8q8oQoXPpSlnvKNVKDQlPMWrmOcgzoduo7kvA2UF0/BwJ/eMKFTiTtkNL17I0M6Xe2tvwFU7be6iw== +"@types/node@*", "@types/node@ts5.8": + version "24.0.14" + resolved "https://registry.yarnpkg.com/@types/node/-/node-24.0.14.tgz#6e3d4fb6d858c48c69707394e1a0e08ce1ecc1bc" + integrity sha512-4zXMWD91vBLGRtHK3YbIoFMia+1nqEz72coM42C5ETjnNCa/heoj7NT1G67iAfOqMmcfhuCZ4uNpyz8EjlAejw== dependencies: undici-types "~7.8.0" @@ -4840,9 +4846,9 @@ integrity sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw== "@types/node@^18", "@types/node@^18.11.9": - version "18.19.113" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.113.tgz#f48df552584e47fb4a8bc0b39e1377112be105de" - integrity sha512-TmSTE9vyebJ9vSEiU+P+0Sp4F5tMgjiEOZaQUW6wA3ODvi6uBgkHQ+EsIu0pbiKvf9QHEvyRCiaz03rV0b+IaA== + version "18.19.119" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.119.tgz#e7c2098b8c0243af0005503a6d5da92e0d989c84" + integrity sha512-d0F6m9itIPaKnrvEMlzE48UjwZaAnFW7Jwibacw9MNdqadjKNpUm9tfJYDwmShJmgqcoqYUX3EMKO1+RWiuuNg== dependencies: undici-types "~5.26.4" @@ -4950,60 +4956,61 @@ integrity sha512-GD4Fk15UoP5NLCNor51YdfL9MSdldKCqOC9EssrRw3HVfar9wUZ5y8Lfnp+qVD6hIinLr8ygklDYnmlnlQo12Q== "@typescript-eslint/eslint-plugin@^8": - version "8.35.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.35.0.tgz#515170100ff867445fe0a17ce05c14fc5fd9ca63" - integrity sha512-ijItUYaiWuce0N1SoSMrEd0b6b6lYkYt99pqCPfybd+HKVXtEvYhICfLdwp42MhiI5mp0oq7PKEL+g1cNiz/Eg== + version "8.37.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.37.0.tgz#332392883f936137cd6252c8eb236d298e514e70" + integrity sha512-jsuVWeIkb6ggzB+wPCsR4e6loj+rM72ohW6IBn2C+5NCvfUVY8s33iFPySSVXqtm5Hu29Ne/9bnA0JmyLmgenA== dependencies: "@eslint-community/regexpp" "^4.10.0" - "@typescript-eslint/scope-manager" "8.35.0" - "@typescript-eslint/type-utils" "8.35.0" - "@typescript-eslint/utils" "8.35.0" - "@typescript-eslint/visitor-keys" "8.35.0" + "@typescript-eslint/scope-manager" "8.37.0" + "@typescript-eslint/type-utils" "8.37.0" + "@typescript-eslint/utils" "8.37.0" + "@typescript-eslint/visitor-keys" "8.37.0" graphemer "^1.4.0" ignore "^7.0.0" natural-compare "^1.4.0" ts-api-utils "^2.1.0" "@typescript-eslint/parser@^8": - version "8.35.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.35.0.tgz#20a0e17778a329a6072722f5ac418d4376b767d2" - integrity sha512-6sMvZePQrnZH2/cJkwRpkT7DxoAWh+g6+GFRK6bV3YQo7ogi3SX5rgF6099r5Q53Ma5qeT7LGmOmuIutF4t3lA== - dependencies: - "@typescript-eslint/scope-manager" "8.35.0" - "@typescript-eslint/types" "8.35.0" - "@typescript-eslint/typescript-estree" "8.35.0" - "@typescript-eslint/visitor-keys" "8.35.0" + version "8.37.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.37.0.tgz#b87f6b61e25ad5cc5bbf8baf809b8da889c89804" + integrity sha512-kVIaQE9vrN9RLCQMQ3iyRlVJpTiDUY6woHGb30JDkfJErqrQEmtdWH3gV0PBAfGZgQXoqzXOO0T3K6ioApbbAA== + dependencies: + "@typescript-eslint/scope-manager" "8.37.0" + "@typescript-eslint/types" "8.37.0" + "@typescript-eslint/typescript-estree" "8.37.0" + "@typescript-eslint/visitor-keys" "8.37.0" debug "^4.3.4" -"@typescript-eslint/project-service@8.35.0": - version "8.35.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/project-service/-/project-service-8.35.0.tgz#00bd77e6845fbdb5684c6ab2d8a400a58dcfb07b" - integrity sha512-41xatqRwWZuhUMF/aZm2fcUsOFKNcG28xqRSS6ZVr9BVJtGExosLAm5A1OxTjRMagx8nJqva+P5zNIGt8RIgbQ== +"@typescript-eslint/project-service@8.37.0": + version "8.37.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/project-service/-/project-service-8.37.0.tgz#0594352e32a4ac9258591b88af77b5653800cdfe" + integrity sha512-BIUXYsbkl5A1aJDdYJCBAo8rCEbAvdquQ8AnLb6z5Lp1u3x5PNgSSx9A/zqYc++Xnr/0DVpls8iQ2cJs/izTXA== dependencies: - "@typescript-eslint/tsconfig-utils" "^8.35.0" - "@typescript-eslint/types" "^8.35.0" + "@typescript-eslint/tsconfig-utils" "^8.37.0" + "@typescript-eslint/types" "^8.37.0" debug "^4.3.4" -"@typescript-eslint/scope-manager@8.35.0": - version "8.35.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.35.0.tgz#8ccb2ab63383544fab98fc4b542d8d141259ff4f" - integrity sha512-+AgL5+mcoLxl1vGjwNfiWq5fLDZM1TmTPYs2UkyHfFhgERxBbqHlNjRzhThJqz+ktBqTChRYY6zwbMwy0591AA== +"@typescript-eslint/scope-manager@8.37.0": + version "8.37.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.37.0.tgz#a31a3c80ca2ef4ed58de13742debb692e7d4c0a4" + integrity sha512-0vGq0yiU1gbjKob2q691ybTg9JX6ShiVXAAfm2jGf3q0hdP6/BruaFjL/ManAR/lj05AvYCH+5bbVo0VtzmjOA== dependencies: - "@typescript-eslint/types" "8.35.0" - "@typescript-eslint/visitor-keys" "8.35.0" + "@typescript-eslint/types" "8.37.0" + "@typescript-eslint/visitor-keys" "8.37.0" -"@typescript-eslint/tsconfig-utils@8.35.0", "@typescript-eslint/tsconfig-utils@^8.35.0": - version "8.35.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.35.0.tgz#6e05aeb999999e31d562ceb4fe144f3cbfbd670e" - integrity sha512-04k/7247kZzFraweuEirmvUj+W3bJLI9fX6fbo1Qm2YykuBvEhRTPl8tcxlYO8kZZW+HIXfkZNoasVb8EV4jpA== +"@typescript-eslint/tsconfig-utils@8.37.0", "@typescript-eslint/tsconfig-utils@^8.37.0": + version "8.37.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.37.0.tgz#47a2760d265c6125f8e7864bc5c8537cad2bd053" + integrity sha512-1/YHvAVTimMM9mmlPvTec9NP4bobA1RkDbMydxG8omqwJJLEW/Iy2C4adsAESIXU3WGLXFHSZUU+C9EoFWl4Zg== -"@typescript-eslint/type-utils@8.35.0": - version "8.35.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.35.0.tgz#0201eae9d83ffcc3451ef8c94f53ecfbf2319ecc" - integrity sha512-ceNNttjfmSEoM9PW87bWLDEIaLAyR+E6BoYJQ5PfaDau37UGca9Nyq3lBk8Bw2ad0AKvYabz6wxc7DMTO2jnNA== +"@typescript-eslint/type-utils@8.37.0": + version "8.37.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.37.0.tgz#2a682e4c6ff5886712dad57e9787b5e417124507" + integrity sha512-SPkXWIkVZxhgwSwVq9rqj/4VFo7MnWwVaRNznfQDc/xPYHjXnPfLWn+4L6FF1cAz6e7dsqBeMawgl7QjUMj4Ow== dependencies: - "@typescript-eslint/typescript-estree" "8.35.0" - "@typescript-eslint/utils" "8.35.0" + "@typescript-eslint/types" "8.37.0" + "@typescript-eslint/typescript-estree" "8.37.0" + "@typescript-eslint/utils" "8.37.0" debug "^4.3.4" ts-api-utils "^2.1.0" @@ -5012,20 +5019,20 @@ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.33.0.tgz#a1e59036a3b53ae8430ceebf2a919dc7f9af6d72" integrity sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ== -"@typescript-eslint/types@8.35.0", "@typescript-eslint/types@^8.11.0", "@typescript-eslint/types@^8.34.1", "@typescript-eslint/types@^8.35.0": - version "8.35.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.35.0.tgz#e60d062907930e30008d796de5c4170f02618a93" - integrity sha512-0mYH3emanku0vHw2aRLNGqe7EXh9WHEhi7kZzscrMDf6IIRUQ5Jk4wp1QrledE/36KtdZrVfKnE32eZCf/vaVQ== +"@typescript-eslint/types@8.37.0", "@typescript-eslint/types@^8.11.0", "@typescript-eslint/types@^8.34.1", "@typescript-eslint/types@^8.37.0": + version "8.37.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.37.0.tgz#09517aa9625eb3c68941dde3ac8835740587b6ff" + integrity sha512-ax0nv7PUF9NOVPs+lmQ7yIE7IQmAf8LGcXbMvHX5Gm+YJUYNAl340XkGnrimxZ0elXyoQJuN5sbg6C4evKA4SQ== -"@typescript-eslint/typescript-estree@8.35.0", "@typescript-eslint/typescript-estree@^8.23.0": - version "8.35.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.35.0.tgz#86141e6c55b75bc1eaecc0781bd39704de14e52a" - integrity sha512-F+BhnaBemgu1Qf8oHrxyw14wq6vbL8xwWKKMwTMwYIRmFFY/1n/9T/jpbobZL8vp7QyEUcC6xGrnAO4ua8Kp7w== +"@typescript-eslint/typescript-estree@8.37.0", "@typescript-eslint/typescript-estree@^8.23.0": + version "8.37.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.37.0.tgz#a07e4574d8e6e4355a558f61323730c987f5fcbc" + integrity sha512-zuWDMDuzMRbQOM+bHyU4/slw27bAUEcKSKKs3hcv2aNnc/tvE/h7w60dwVw8vnal2Pub6RT1T7BI8tFZ1fE+yg== dependencies: - "@typescript-eslint/project-service" "8.35.0" - "@typescript-eslint/tsconfig-utils" "8.35.0" - "@typescript-eslint/types" "8.35.0" - "@typescript-eslint/visitor-keys" "8.35.0" + "@typescript-eslint/project-service" "8.37.0" + "@typescript-eslint/tsconfig-utils" "8.37.0" + "@typescript-eslint/types" "8.37.0" + "@typescript-eslint/visitor-keys" "8.37.0" debug "^4.3.4" fast-glob "^3.3.2" is-glob "^4.0.3" @@ -5046,15 +5053,15 @@ semver "^7.3.5" tsutils "^3.21.0" -"@typescript-eslint/utils@8.35.0", "@typescript-eslint/utils@^6.0.0 || ^7.0.0 || ^8.0.0", "@typescript-eslint/utils@^8.13.0": - version "8.35.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.35.0.tgz#aaf0afab5ab51ea2f1897002907eacd9834606d5" - integrity sha512-nqoMu7WWM7ki5tPgLVsmPM8CkqtoPUG6xXGeefM5t4x3XumOEKMoUZPdi+7F+/EotukN4R9OWdmDxN80fqoZeg== +"@typescript-eslint/utils@8.37.0", "@typescript-eslint/utils@^6.0.0 || ^7.0.0 || ^8.0.0", "@typescript-eslint/utils@^8.13.0": + version "8.37.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.37.0.tgz#189ea59b2709f5d898614611f091a776751ee335" + integrity sha512-TSFvkIW6gGjN2p6zbXo20FzCABbyUAuq6tBvNRGsKdsSQ6a7rnV6ADfZ7f4iI3lIiXc4F4WWvtUfDw9CJ9pO5A== dependencies: "@eslint-community/eslint-utils" "^4.7.0" - "@typescript-eslint/scope-manager" "8.35.0" - "@typescript-eslint/types" "8.35.0" - "@typescript-eslint/typescript-estree" "8.35.0" + "@typescript-eslint/scope-manager" "8.37.0" + "@typescript-eslint/types" "8.37.0" + "@typescript-eslint/typescript-estree" "8.37.0" "@typescript-eslint/visitor-keys@4.33.0": version "4.33.0" @@ -5064,12 +5071,12 @@ "@typescript-eslint/types" "4.33.0" eslint-visitor-keys "^2.0.0" -"@typescript-eslint/visitor-keys@8.35.0": - version "8.35.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.35.0.tgz#93e905e7f1e94d26a79771d1b1eb0024cb159dbf" - integrity sha512-zTh2+1Y8ZpmeQaQVIc/ZZxsx8UzgKJyNg1PTvjzC7WMhPSVS8bfDX34k1SrwOf016qd5RU3az2UxUNue3IfQ5g== +"@typescript-eslint/visitor-keys@8.37.0": + version "8.37.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.37.0.tgz#cdb6a6bd3e8d6dd69bd70c1bdda36e2d18737455" + integrity sha512-YzfhzcTnZVPiLfP/oeKtDp2evwvHLMe0LOy7oe+hb9KKIumLNohYS9Hgp1ifwpu42YWxhZE8yieggz6JpqO/1w== dependencies: - "@typescript-eslint/types" "8.35.0" + "@typescript-eslint/types" "8.37.0" eslint-visitor-keys "^4.2.1" "@ungap/structured-clone@^1.3.0": @@ -5077,102 +5084,102 @@ resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.3.0.tgz#d06bbb384ebcf6c505fde1c3d0ed4ddffe0aaff8" integrity sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g== -"@unrs/resolver-binding-android-arm-eabi@1.9.2": - version "1.9.2" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.9.2.tgz#6cb01dde20bef06397ffd4924f502596cb458851" - integrity sha512-tS+lqTU3N0kkthU+rYp0spAYq15DU8ld9kXkaKg9sbQqJNF+WPMuNHZQGCgdxrUOEO0j22RKMwRVhF1HTl+X8A== - -"@unrs/resolver-binding-android-arm64@1.9.2": - version "1.9.2" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.9.2.tgz#1672b533f01f98119095860683496def93929a2e" - integrity sha512-MffGiZULa/KmkNjHeuuflLVqfhqLv1vZLm8lWIyeADvlElJ/GLSOkoUX+5jf4/EGtfwrNFcEaB8BRas03KT0/Q== - -"@unrs/resolver-binding-darwin-arm64@1.9.2": - version "1.9.2" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.9.2.tgz#dad66a21553b1ba4088c6eb922332846550bd9b2" - integrity sha512-dzJYK5rohS1sYl1DHdJ3mwfwClJj5BClQnQSyAgEfggbUwA9RlROQSSbKBLqrGfsiC/VyrDPtbO8hh56fnkbsQ== - -"@unrs/resolver-binding-darwin-x64@1.9.2": - version "1.9.2" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.9.2.tgz#bfaedca218078862f3d536d44269fed94a6158e2" - integrity sha512-gaIMWK+CWtXcg9gUyznkdV54LzQ90S3X3dn8zlh+QR5Xy7Y+Efqw4Rs4im61K1juy4YNb67vmJsCDAGOnIeffQ== - -"@unrs/resolver-binding-freebsd-x64@1.9.2": - version "1.9.2" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.9.2.tgz#bdab0e754c45831522b16df0b6fe4b0ffde22628" - integrity sha512-S7QpkMbVoVJb0xwHFwujnwCAEDe/596xqY603rpi/ioTn9VDgBHnCCxh+UFrr5yxuMH+dliHfjwCZJXOPJGPnw== - -"@unrs/resolver-binding-linux-arm-gnueabihf@1.9.2": - version "1.9.2" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.9.2.tgz#2bac9c19599888d4ba4787b437b0273ac7a7a9f2" - integrity sha512-+XPUMCuCCI80I46nCDFbGum0ZODP5NWGiwS3Pj8fOgsG5/ctz+/zzuBlq/WmGa+EjWZdue6CF0aWWNv84sE1uw== - -"@unrs/resolver-binding-linux-arm-musleabihf@1.9.2": - version "1.9.2" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.9.2.tgz#49d27d5d63e5f26cf7b93a0731334b302b9b7fec" - integrity sha512-sqvUyAd1JUpwbz33Ce2tuTLJKM+ucSsYpPGl2vuFwZnEIg0CmdxiZ01MHQ3j6ExuRqEDUCy8yvkDKvjYFPb8Zg== - -"@unrs/resolver-binding-linux-arm64-gnu@1.9.2": - version "1.9.2" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.9.2.tgz#95ba5d1654a04b1049d944871e165d786e8da68f" - integrity sha512-UYA0MA8ajkEDCFRQdng/FVx3F6szBvk3EPnkTTQuuO9lV1kPGuTB+V9TmbDxy5ikaEgyWKxa4CI3ySjklZ9lFA== - -"@unrs/resolver-binding-linux-arm64-musl@1.9.2": - version "1.9.2" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.9.2.tgz#23f90a48b1d343189b1c20c89b694140e2d5a210" - integrity sha512-P/CO3ODU9YJIHFqAkHbquKtFst0COxdphc8TKGL5yCX75GOiVpGqd1d15ahpqu8xXVsqP4MGFP2C3LRZnnL5MA== - -"@unrs/resolver-binding-linux-ppc64-gnu@1.9.2": - version "1.9.2" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.9.2.tgz#076f2c2e95dbcd4824cc9929bc504151b402ac11" - integrity sha512-uKStFlOELBxBum2s1hODPtgJhY4NxYJE9pAeyBgNEzHgTqTiVBPjfTlPFJkfxyTjQEuxZbbJlJnMCrRgD7ubzw== - -"@unrs/resolver-binding-linux-riscv64-gnu@1.9.2": - version "1.9.2" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.9.2.tgz#f7de54d45df430c74bbd12794946a55805bed6dd" - integrity sha512-LkbNnZlhINfY9gK30AHs26IIVEZ9PEl9qOScYdmY2o81imJYI4IMnJiW0vJVtXaDHvBvxeAgEy5CflwJFIl3tQ== - -"@unrs/resolver-binding-linux-riscv64-musl@1.9.2": - version "1.9.2" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.9.2.tgz#ad1fcdcf5f112d7432fcfe38269a084bdccad266" - integrity sha512-vI+e6FzLyZHSLFNomPi+nT+qUWN4YSj8pFtQZSFTtmgFoxqB6NyjxSjAxEC1m93qn6hUXhIsh8WMp+fGgxCoRg== - -"@unrs/resolver-binding-linux-s390x-gnu@1.9.2": - version "1.9.2" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.9.2.tgz#d914a4f12b9048e1a4de0040f64d73274104e301" - integrity sha512-sSO4AlAYhSM2RAzBsRpahcJB1msc6uYLAtP6pesPbZtptF8OU/CbCPhSRW6cnYOGuVmEmWVW5xVboAqCnWTeHQ== - -"@unrs/resolver-binding-linux-x64-gnu@1.9.2": - version "1.9.2" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.9.2.tgz#d8f8cddc42ae267ef45ed4b61ff72b9e22aa3b82" - integrity sha512-jkSkwch0uPFva20Mdu8orbQjv2A3G88NExTN2oPTI1AJ+7mZfYW3cDCTyoH6OnctBKbBVeJCEqh0U02lTkqD5w== - -"@unrs/resolver-binding-linux-x64-musl@1.9.2": - version "1.9.2" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.9.2.tgz#7bfce67acb51b3f4a7cff8383f46600f7b055a96" - integrity sha512-Uk64NoiTpQbkpl+bXsbeyOPRpUoMdcUqa+hDC1KhMW7aN1lfW8PBlBH4mJ3n3Y47dYE8qi0XTxy1mBACruYBaw== - -"@unrs/resolver-binding-wasm32-wasi@1.9.2": - version "1.9.2" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.9.2.tgz#b133c9b6941aba54eea007ca2f27ff6ce917ae55" - integrity sha512-EpBGwkcjDicjR/ybC0g8wO5adPNdVuMrNalVgYcWi+gYtC1XYNuxe3rufcO7dA76OHGeVabcO6cSkPJKVcbCXQ== +"@unrs/resolver-binding-android-arm-eabi@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz#9f5b04503088e6a354295e8ea8fe3cb99e43af81" + integrity sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw== + +"@unrs/resolver-binding-android-arm64@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz#7414885431bd7178b989aedc4d25cccb3865bc9f" + integrity sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g== + +"@unrs/resolver-binding-darwin-arm64@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz#b4a8556f42171fb9c9f7bac8235045e82aa0cbdf" + integrity sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g== + +"@unrs/resolver-binding-darwin-x64@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz#fd4d81257b13f4d1a083890a6a17c00de571f0dc" + integrity sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ== + +"@unrs/resolver-binding-freebsd-x64@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz#d2513084d0f37c407757e22f32bd924a78cfd99b" + integrity sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw== + +"@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz#844d2605d057488d77fab09705f2866b86164e0a" + integrity sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw== + +"@unrs/resolver-binding-linux-arm-musleabihf@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz#204892995cefb6bd1d017d52d097193bc61ddad3" + integrity sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw== + +"@unrs/resolver-binding-linux-arm64-gnu@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz#023eb0c3aac46066a10be7a3f362e7b34f3bdf9d" + integrity sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ== + +"@unrs/resolver-binding-linux-arm64-musl@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz#9e6f9abb06424e3140a60ac996139786f5d99be0" + integrity sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w== + +"@unrs/resolver-binding-linux-ppc64-gnu@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz#b111417f17c9d1b02efbec8e08398f0c5527bb44" + integrity sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA== + +"@unrs/resolver-binding-linux-riscv64-gnu@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz#92ffbf02748af3e99873945c9a8a5ead01d508a9" + integrity sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ== + +"@unrs/resolver-binding-linux-riscv64-musl@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz#0bec6f1258fc390e6b305e9ff44256cb207de165" + integrity sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew== + +"@unrs/resolver-binding-linux-s390x-gnu@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz#577843a084c5952f5906770633ccfb89dac9bc94" + integrity sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg== + +"@unrs/resolver-binding-linux-x64-gnu@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz#36fb318eebdd690f6da32ac5e0499a76fa881935" + integrity sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w== + +"@unrs/resolver-binding-linux-x64-musl@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz#bfb9af75f783f98f6a22c4244214efe4df1853d6" + integrity sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA== + +"@unrs/resolver-binding-wasm32-wasi@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz#752c359dd875684b27429500d88226d7cc72f71d" + integrity sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ== dependencies: "@napi-rs/wasm-runtime" "^0.2.11" -"@unrs/resolver-binding-win32-arm64-msvc@1.9.2": - version "1.9.2" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.9.2.tgz#5f95f590f06c1e9ba15b24292c956c21a6294b30" - integrity sha512-EdFbGn7o1SxGmN6aZw9wAkehZJetFPao0VGZ9OMBwKx6TkvDuj6cNeLimF/Psi6ts9lMOe+Dt6z19fZQ9Ye2fw== +"@unrs/resolver-binding-win32-arm64-msvc@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz#ce5735e600e4c2fbb409cd051b3b7da4a399af35" + integrity sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw== -"@unrs/resolver-binding-win32-ia32-msvc@1.9.2": - version "1.9.2" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.9.2.tgz#aac6595c6de6b26e5314372ab977b0f6a869c903" - integrity sha512-JY9hi1p7AG+5c/dMU8o2kWemM8I6VZxfGwn1GCtf3c5i+IKcMo2NQ8OjZ4Z3/itvY/Si3K10jOBQn7qsD/whUA== +"@unrs/resolver-binding-win32-ia32-msvc@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz#72fc57bc7c64ec5c3de0d64ee0d1810317bc60a6" + integrity sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ== -"@unrs/resolver-binding-win32-x64-msvc@1.9.2": - version "1.9.2" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.9.2.tgz#f755c5229f1401bbff7307d037c6e38fa169ad1d" - integrity sha512-ryoo+EB19lMxAd80ln9BVf8pdOAxLb97amrQ3SFN9OCRn/5M5wvwDgAe4i8ZjhpbiHoDeP8yavcTEnpKBo7lZg== +"@unrs/resolver-binding-win32-x64-msvc@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz#538b1e103bf8d9864e7b85cc96fa8d6fb6c40777" + integrity sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g== "@vitest/expect@>1.6.0": version "3.2.4" @@ -5343,9 +5350,9 @@ agent-base@6, agent-base@^6.0.2: debug "4" agent-base@^7.1.0, agent-base@^7.1.2: - version "7.1.3" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.3.tgz#29435eb821bc4194633a5b89e5bc4703bafc25a1" - integrity sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw== + version "7.1.4" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.4.tgz#e3cd76d4c548ee895d3c3fd8dc1f6c5b9032e7a8" + integrity sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ== ajv-draft-04@~1.0.0: version "1.0.0" @@ -5464,9 +5471,9 @@ app-module-path@^2.2.0: integrity sha512-gkco+qxENJV+8vFcDiiFhuoSvRXb2a/QPqpSoWhVz829VNJfOTnELbBmPmNKFxf3xdNnw4DWCkzkDaavcX/1YQ== aproba@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc" - integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== + version "2.1.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.1.0.tgz#75500a190313d95c64e871e7e4284c6ac219f0b1" + integrity sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew== archiver-utils@^5.0.0, archiver-utils@^5.0.2: version "5.0.2" @@ -5690,14 +5697,34 @@ available-typed-arrays@^1.0.7: dependencies: possible-typed-array-names "^1.0.0" -aws-cdk-lib@^2.202.0: - version "2.202.0" - resolved "https://registry.yarnpkg.com/aws-cdk-lib/-/aws-cdk-lib-2.202.0.tgz#5cae32d08e6072cc49e6cb090471a1292efdd867" - integrity sha512-JDycQoE8AxUAeCFXFoCx6FGvR78e6W9zYxPgmfW/uPPbntyNCXXBqwyAYo17RGS/lr0RO3zqD/oCBZSNU2e/Yg== +aws-cdk-lib@2.203.0: + version "2.203.0" + resolved "https://registry.yarnpkg.com/aws-cdk-lib/-/aws-cdk-lib-2.203.0.tgz#36f16c5c5220b621b3e1eae2b90e988a74037c6e" + integrity sha512-9aB/oIZ2nNVfuqCJuZ66122U/pkkOfR4OcC8aXbgRLc1hKSnTXtGC9W2LlortweBZwTaTs4sk4xaQ9TYHgk0CQ== + dependencies: + "@aws-cdk/asset-awscli-v1" "2.2.242" + "@aws-cdk/asset-node-proxy-agent-v6" "^2.1.0" + "@aws-cdk/cloud-assembly-schema" "^44.8.0" + "@balena/dockerignore" "^1.0.2" + case "1.6.3" + fs-extra "^11.3.0" + ignore "^5.3.2" + jsonschema "^1.5.0" + mime-types "^2.1.35" + minimatch "^3.1.2" + punycode "^2.3.1" + semver "^7.7.2" + table "^6.9.0" + yaml "1.10.2" + +aws-cdk-lib@2.205.0: + version "2.205.0" + resolved "https://registry.yarnpkg.com/aws-cdk-lib/-/aws-cdk-lib-2.205.0.tgz#a2bdf2e9701b052cb7d4f472611a7ed2f44dd9a0" + integrity sha512-GZHy/F8jql+1aFlgIhGQuLl9zHvceHL0VRuBgaYngwWrflHc+ZN3eCEtfzCblA2bXmi4NbLljpSUBIGBVx2EEQ== dependencies: - "@aws-cdk/asset-awscli-v1" "2.2.240" + "@aws-cdk/asset-awscli-v1" "2.2.242" "@aws-cdk/asset-node-proxy-agent-v6" "^2.1.0" - "@aws-cdk/cloud-assembly-schema" "^44.2.0" + "@aws-cdk/cloud-assembly-schema" "^45.0.0" "@balena/dockerignore" "^1.0.2" case "1.6.3" fs-extra "^11.3.0" @@ -5747,12 +5774,12 @@ b4a@^1.6.4: resolved "https://registry.yarnpkg.com/b4a/-/b4a-1.6.7.tgz#a99587d4ebbfbd5a6e3b21bdb5d5fa385767abe4" integrity sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg== -babel-jest@30.0.2: - version "30.0.2" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-30.0.2.tgz#f627dc5afc3bd5795fc84735b4f1d74f9d4b8e91" - integrity sha512-A5kqR1/EUTidM2YC2YMEUDP2+19ppgOwK0IAd9Swc3q2KqFb5f9PtRUXVeZcngu0z5mDMyZ9zH2huJZSOMLiTQ== +babel-jest@30.0.4: + version "30.0.4" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-30.0.4.tgz#63945c1b27227312fc687689073124dba5b28282" + integrity sha512-UjG2j7sAOqsp2Xua1mS/e+ekddkSu3wpf4nZUSvXNHuVWdaOUXQ77+uyjJLDE9i0atm5x4kds8K9yb5lRsRtcA== dependencies: - "@jest/transform" "30.0.2" + "@jest/transform" "30.0.4" "@types/babel__core" "^7.20.5" babel-plugin-istanbul "^7.0.0" babel-preset-jest "30.0.1" @@ -5862,9 +5889,9 @@ balanced-match@^1.0.0: integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== bare-events@^2.2.0: - version "2.5.4" - resolved "https://registry.yarnpkg.com/bare-events/-/bare-events-2.5.4.tgz#16143d435e1ed9eafd1ab85f12b89b3357a41745" - integrity sha512-+gFfDkR8pj4/TrWCGUGWmJIkBwuxPS5F+a5yWjOHQt2hHvNZd5YLzadjmDUtFmMM4y429bnKLa8bYBMHcYdnQA== + version "2.6.0" + resolved "https://registry.yarnpkg.com/bare-events/-/bare-events-2.6.0.tgz#11d9506da109e363a2f3af050fbb005ccdb3ee8f" + integrity sha512-EKZ5BTXYExaNqi3I3f9RtEsaI/xBSGjE0XZCZilPzFAV/goswFHuPd9jEZlPIZ/iNZJwDSao9qRiScySz7MbQg== base64-arraybuffer@^0.1.5: version "0.1.5" @@ -6103,19 +6130,19 @@ camelcase@^6, camelcase@^6.2.0, camelcase@^6.3.0: integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== caniuse-lite@^1.0.30001726: - version "1.0.30001726" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001726.tgz#a15bd87d5a4bf01f6b6f70ae7c97fdfd28b5ae47" - integrity sha512-VQAUIUzBiZ/UnlM28fSp2CRF3ivUn1BWEvxMcVTNwpw91Py1pGbPIyIKtd+tzct9C3ouceCVdGAXxZOpZAsgdw== + version "1.0.30001727" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001727.tgz#22e9706422ad37aa50556af8c10e40e2d93a8b85" + integrity sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q== case@1.6.3, case@^1.6.3: version "1.6.3" resolved "https://registry.yarnpkg.com/case/-/case-1.6.3.tgz#0a4386e3e9825351ca2e6216c60467ff5f1ea1c9" integrity sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ== -cdk-from-cfn@^0.226.0: - version "0.226.0" - resolved "https://registry.yarnpkg.com/cdk-from-cfn/-/cdk-from-cfn-0.226.0.tgz#392ab5eb2937b1cd0bafd4e81826cc52ce9e66db" - integrity sha512-FZQYea4pSVhy+DChWQMlUV9MUOzOGHpd2zmYKImPJ82w6kwjFQWVlpGPkmm3SXHp+z+fOGcjoh/QII1hdd+cnQ== +cdk-from-cfn@^0.230.0: + version "0.230.0" + resolved "https://registry.yarnpkg.com/cdk-from-cfn/-/cdk-from-cfn-0.230.0.tgz#685aaa74b057c3a3807384d1ee0f840ceec6c28a" + integrity sha512-eINSdKw6aug5lZfmUBgEscMNkSUzewu6qjeUpETzUYH7yUzwem3F2279tS++CJaZj2VvZieprCL2X/a4N5dAjQ== cdklabs-projen-project-types@^0.3.1: version "0.3.1" @@ -6125,9 +6152,9 @@ cdklabs-projen-project-types@^0.3.1: yaml "^2.8.0" chai@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/chai/-/chai-5.2.0.tgz#1358ee106763624114addf84ab02697e411c9c05" - integrity sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw== + version "5.2.1" + resolved "https://registry.yarnpkg.com/chai/-/chai-5.2.1.tgz#a9502462bdc79cf90b4a0953537a9908aa638b47" + integrity sha512-5nFxhUrX0PqtyogoYOA8IPswy5sZFTOsBFl/9bNsmDLgsxYTzSZQJDPppDnZPTQbzSEm0hqGjWPzRemQCYbD6A== dependencies: assertion-error "^2.0.1" check-error "^2.1.1" @@ -6198,9 +6225,9 @@ ci-info@^3.2.0: integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== ci-info@^4.0.0, ci-info@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-4.2.0.tgz#cbd21386152ebfe1d56f280a3b5feccbd96764c7" - integrity sha512-cYY9mypksY8NRqgDB1XD1RiJL338v/551niynFTGkZOO2LHuB2OmOYxDIe/ttN9AHwrqdum1360G3ald0W9kCg== + version "4.3.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-4.3.0.tgz#c39b1013f8fdbd28cd78e62318357d02da160cd7" + integrity sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ== cidr-regex@^4.1.1: version "4.1.3" @@ -6817,9 +6844,9 @@ decamelize@^5, decamelize@^5.0.1: integrity sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA== decimal.js@^10.4.3: - version "10.5.0" - resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.5.0.tgz#0f371c7cf6c4898ce0afb09836db73cd82010f22" - integrity sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw== + version "10.6.0" + resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.6.0.tgz#e649a43e3ab953a72192ff5983865e509f37ed9a" + integrity sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg== dedent@^1.0.0, dedent@^1.6.0: version "1.6.0" @@ -7224,9 +7251,9 @@ ejs@^3.1.10: jake "^10.8.5" electron-to-chromium@^1.5.173: - version "1.5.177" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.177.tgz#db730d8254959184e65320a3a0b7edcd29c54f60" - integrity sha512-7EH2G59nLsEMj97fpDuvVcYi6lwTcM1xuWw3PssD8xzboAW7zj7iB3COEEEATUfjLHrs5uKBLQT03V/8URx06g== + version "1.5.185" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.185.tgz#b4f9189c4ef652ddf9f1bb37529e2b79f865e912" + integrity sha512-dYOZfUk57hSMPePoIQ1fZWl1Fkj+OshhEVuPacNKWzC1efe56OsHY3l/jCfiAgIICOU3VgOIdoq7ahg7r7n6MQ== emittery@^0.13.1: version "0.13.1" @@ -7417,36 +7444,37 @@ es-to-primitive@^1.3.0: is-date-object "^1.0.5" is-symbol "^1.0.4" -esbuild@^0.25.5, esbuild@~0.25.0: - version "0.25.5" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.25.5.tgz#71075054993fdfae76c66586f9b9c1f8d7edd430" - integrity sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ== +esbuild@^0.25.6, esbuild@~0.25.0: + version "0.25.6" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.25.6.tgz#9b82a3db2fa131aec069ab040fd57ed0a880cdcd" + integrity sha512-GVuzuUwtdsghE3ocJ9Bs8PNoF13HNQ5TXbEi2AhvVb8xU1Iwt9Fos9FEamfoee+u/TOsn7GUWc04lz46n2bbTg== optionalDependencies: - "@esbuild/aix-ppc64" "0.25.5" - "@esbuild/android-arm" "0.25.5" - "@esbuild/android-arm64" "0.25.5" - "@esbuild/android-x64" "0.25.5" - "@esbuild/darwin-arm64" "0.25.5" - "@esbuild/darwin-x64" "0.25.5" - "@esbuild/freebsd-arm64" "0.25.5" - "@esbuild/freebsd-x64" "0.25.5" - "@esbuild/linux-arm" "0.25.5" - "@esbuild/linux-arm64" "0.25.5" - "@esbuild/linux-ia32" "0.25.5" - "@esbuild/linux-loong64" "0.25.5" - "@esbuild/linux-mips64el" "0.25.5" - "@esbuild/linux-ppc64" "0.25.5" - "@esbuild/linux-riscv64" "0.25.5" - "@esbuild/linux-s390x" "0.25.5" - "@esbuild/linux-x64" "0.25.5" - "@esbuild/netbsd-arm64" "0.25.5" - "@esbuild/netbsd-x64" "0.25.5" - "@esbuild/openbsd-arm64" "0.25.5" - "@esbuild/openbsd-x64" "0.25.5" - "@esbuild/sunos-x64" "0.25.5" - "@esbuild/win32-arm64" "0.25.5" - "@esbuild/win32-ia32" "0.25.5" - "@esbuild/win32-x64" "0.25.5" + "@esbuild/aix-ppc64" "0.25.6" + "@esbuild/android-arm" "0.25.6" + "@esbuild/android-arm64" "0.25.6" + "@esbuild/android-x64" "0.25.6" + "@esbuild/darwin-arm64" "0.25.6" + "@esbuild/darwin-x64" "0.25.6" + "@esbuild/freebsd-arm64" "0.25.6" + "@esbuild/freebsd-x64" "0.25.6" + "@esbuild/linux-arm" "0.25.6" + "@esbuild/linux-arm64" "0.25.6" + "@esbuild/linux-ia32" "0.25.6" + "@esbuild/linux-loong64" "0.25.6" + "@esbuild/linux-mips64el" "0.25.6" + "@esbuild/linux-ppc64" "0.25.6" + "@esbuild/linux-riscv64" "0.25.6" + "@esbuild/linux-s390x" "0.25.6" + "@esbuild/linux-x64" "0.25.6" + "@esbuild/netbsd-arm64" "0.25.6" + "@esbuild/netbsd-x64" "0.25.6" + "@esbuild/openbsd-arm64" "0.25.6" + "@esbuild/openbsd-x64" "0.25.6" + "@esbuild/openharmony-arm64" "0.25.6" + "@esbuild/sunos-x64" "0.25.6" + "@esbuild/win32-arm64" "0.25.6" + "@esbuild/win32-ia32" "0.25.6" + "@esbuild/win32-x64" "0.25.6" escalade@^3.1.1, escalade@^3.2.0: version "3.2.0" @@ -7592,10 +7620,10 @@ eslint-plugin-jsdoc@^50.8.0: semver "^7.7.2" spdx-expression-parse "^4.0.0" -eslint-plugin-jsdoc@^51.2.3: - version "51.3.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-51.3.0.tgz#d75c3f5685214908ceb97bc49a14cbc5cd85fdaf" - integrity sha512-XGXFzg+lwoZnhkIRKBS8Fl8Y3Sx3VAhX8jABaYsM/Ympz7pqKiI6gFgBIwqfK1Un3ADdCYNY/pceYDfQydelnw== +eslint-plugin-jsdoc@^51.4.0: + version "51.4.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-51.4.0.tgz#03d3e2f40b5d8dda39f773430e0dad5ce29cd314" + integrity sha512-woooKbcFiQdpfJg1g/WmFHItaZuDE14SZ7QVW3eV/5e3mbOicjtgVz6cFkYJ3MP9n5WL9/ZAvuWuGkAkMFhDYQ== dependencies: "@es-joy/jsdoccomment" "~0.52.0" are-docs-informative "^0.0.2" @@ -7640,17 +7668,17 @@ eslint-visitor-keys@^4.2.0, eslint-visitor-keys@^4.2.1: integrity sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ== eslint@^9: - version "9.30.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.30.0.tgz#fb0c655f5e28fc1b2f4050c28efa1876d78034fc" - integrity sha512-iN/SiPxmQu6EVkf+m1qpBxzUhE12YqFLOSySuOyVLJLEF9nzTf+h/1AJYc1JWzCnktggeNrjvQGLngDzXirU6g== + version "9.31.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.31.0.tgz#9a488e6da75bbe05785cd62e43c5ea99356d21ba" + integrity sha512-QldCVh/ztyKJJZLr4jXNUByx3gR+TDYZCRXEktiZoUR3PGy4qCmSbkxcIle8GEwGpb5JBZazlaJ/CxLidXdEbQ== dependencies: "@eslint-community/eslint-utils" "^4.2.0" "@eslint-community/regexpp" "^4.12.1" "@eslint/config-array" "^0.21.0" "@eslint/config-helpers" "^0.3.0" - "@eslint/core" "^0.14.0" + "@eslint/core" "^0.15.0" "@eslint/eslintrc" "^3.3.1" - "@eslint/js" "9.30.0" + "@eslint/js" "9.31.0" "@eslint/plugin-kit" "^0.3.1" "@humanfs/node" "^0.16.6" "@humanwhocodes/module-importer" "^1.0.1" @@ -7786,14 +7814,14 @@ exit@^0.1.2: resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== -expect@30.0.3, expect@>28.1.3, expect@^30.0.0: - version "30.0.3" - resolved "https://registry.yarnpkg.com/expect/-/expect-30.0.3.tgz#8bf31a67514f78c5e4ac8d67774192ab95d5ec25" - integrity sha512-HXg6NvK35/cSYZCUKAtmlgCFyqKM4frEPbzrav5hRqb0GMz0E0lS5hfzYjSaiaE5ysnp/qI2aeZkeyeIAOeXzQ== +expect@30.0.4, expect@>28.1.3, expect@^30.0.0: + version "30.0.4" + resolved "https://registry.yarnpkg.com/expect/-/expect-30.0.4.tgz#23ce0eaa9a1dcd72fcb78a228b9babdbcf9ddeca" + integrity sha512-dDLGjnP2cKbEppxVICxI/Uf4YemmGMPNy0QytCbfafbpYk9AFQsxb8Uyrxii0RPK7FWgLGlSem+07WirwS3cFQ== dependencies: - "@jest/expect-utils" "30.0.3" + "@jest/expect-utils" "30.0.4" "@jest/get-type" "30.0.1" - jest-matcher-utils "30.0.3" + jest-matcher-utils "30.0.4" jest-message-util "30.0.2" jest-mock "30.0.2" jest-util "30.0.2" @@ -7863,10 +7891,10 @@ fast-check@^3.23.2: dependencies: pure-rand "^6.1.0" -fast-check@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/fast-check/-/fast-check-4.1.1.tgz#bc5ae58550439b7099e841b80d832d51e50b7600" - integrity sha512-8+yQYeNYqBfWem0Nmm7BUnh27wm+qwGvI0xln60c8RPM5rVekxZf/Ildng2GNBfjaG6utIebFmVBPlNtZlBLxg== +fast-check@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/fast-check/-/fast-check-4.2.0.tgz#db9149c073b47d60ab377791e98a7d1a8f288c08" + integrity sha512-buxrKEaSseOwFjt6K1REcGMeFOrb0wk3cXifeMAG8yahcE9kV20PjQn1OdzPGL6OBFTbYXfjleNBARf/aCfV1A== dependencies: pure-rand "^7.0.0" @@ -7916,12 +7944,12 @@ fast-uri@^3.0.1: resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.0.6.tgz#88f130b77cfaea2378d56bf970dea21257a68748" integrity sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw== -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== +fast-xml-parser@5.2.5: + version "5.2.5" + resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-5.2.5.tgz#4809fdfb1310494e341098c25cb1341a01a9144a" + integrity sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ== dependencies: - strnum "^1.0.5" + strnum "^2.1.0" fast-xml-parser@^3.16.0: version "3.21.1" @@ -8332,9 +8360,9 @@ get-tsconfig@^4.10.0, get-tsconfig@^4.10.1, get-tsconfig@^4.7.5: resolve-pkg-maps "^1.0.0" get-uri@^6.0.1: - version "6.0.4" - resolved "https://registry.yarnpkg.com/get-uri/-/get-uri-6.0.4.tgz#6daaee9e12f9759e19e55ba313956883ef50e0a7" - integrity sha512-E1b1lFFLvLgak2whF2xDBcOy6NLVGZBqqjJjsIhvopKfWWEi64pLVTWWehV8KlLerZkfNTA95sTe2OdJKm1OzQ== + version "6.0.5" + resolved "https://registry.yarnpkg.com/get-uri/-/get-uri-6.0.5.tgz#714892aa4a871db671abc5395e5e9447bc306a16" + integrity sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg== dependencies: basic-ftp "^5.0.2" data-uri-to-buffer "^6.0.2" @@ -8415,7 +8443,7 @@ glob@^11.0.3: package-json-from-dist "^1.0.0" path-scurry "^2.0.0" -glob@^7, glob@^7.1.1, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.1.7, glob@^7.2.3: +glob@^7.1.1, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.1.7, glob@^7.2.3: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== @@ -8438,10 +8466,15 @@ glob@^8.1.0: minimatch "^5.0.1" once "^1.3.0" -globals@^11.1.0: - version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== +glob@^9: + version "9.3.5" + resolved "https://registry.yarnpkg.com/glob/-/glob-9.3.5.tgz#ca2ed8ca452781a3009685607fdf025a899dfe21" + integrity sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q== + dependencies: + fs.realpath "^1.0.0" + minimatch "^8.0.2" + minipass "^4.2.4" + path-scurry "^1.6.1" globals@^14.0.0: version "14.0.0" @@ -9272,14 +9305,14 @@ jest-changed-files@^29.7.0: jest-util "^29.7.0" p-limit "^3.1.0" -jest-circus@30.0.3: - version "30.0.3" - resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-30.0.3.tgz#d2de4adb92cfdbce18668e27176c1b9f79afdf5a" - integrity sha512-rD9qq2V28OASJHJWDRVdhoBdRs6k3u3EmBzDYcyuMby8XCO3Ll1uq9kyqM41ZcC4fMiPulMVh3qMw0cBvDbnyg== +jest-circus@30.0.4: + version "30.0.4" + resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-30.0.4.tgz#7bdfc5951eb883283bf0336cc4d624222f09851e" + integrity sha512-o6UNVfbXbmzjYgmVPtSQrr5xFZCtkDZGdTlptYvGFSN80RuOOlTe73djvMrs+QAuSERZWcHBNIOMH+OEqvjWuw== dependencies: - "@jest/environment" "30.0.2" - "@jest/expect" "30.0.3" - "@jest/test-result" "30.0.2" + "@jest/environment" "30.0.4" + "@jest/expect" "30.0.4" + "@jest/test-result" "30.0.4" "@jest/types" "30.0.1" "@types/node" "*" chalk "^4.1.2" @@ -9287,10 +9320,10 @@ jest-circus@30.0.3: dedent "^1.6.0" is-generator-fn "^2.1.0" jest-each "30.0.2" - jest-matcher-utils "30.0.3" + jest-matcher-utils "30.0.4" jest-message-util "30.0.2" - jest-runtime "30.0.3" - jest-snapshot "30.0.3" + jest-runtime "30.0.4" + jest-snapshot "30.0.4" jest-util "30.0.2" p-limit "^3.1.0" pretty-format "30.0.2" @@ -9324,18 +9357,18 @@ jest-circus@^29.7.0: slash "^3.0.0" stack-utils "^2.0.3" -jest-cli@30.0.3: - version "30.0.3" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-30.0.3.tgz#2340b69c580c471fd9f4a197f969025a545608dd" - integrity sha512-UWDSj0ayhumEAxpYRlqQLrssEi29kdQ+kddP94AuHhZknrE+mT0cR0J+zMHKFe9XPfX3dKQOc2TfWki3WhFTsA== +jest-cli@30.0.4: + version "30.0.4" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-30.0.4.tgz#85510c5ebffc4ed31b571b3e166bca3febe7ba4a" + integrity sha512-3dOrP3zqCWBkjoVG1zjYJpD9143N9GUCbwaF2pFF5brnIgRLHmKcCIw+83BvF1LxggfMWBA0gxkn6RuQVuRhIQ== dependencies: - "@jest/core" "30.0.3" - "@jest/test-result" "30.0.2" + "@jest/core" "30.0.4" + "@jest/test-result" "30.0.4" "@jest/types" "30.0.1" chalk "^4.1.2" exit-x "^0.2.2" import-local "^3.2.0" - jest-config "30.0.3" + jest-config "30.0.4" jest-util "30.0.2" jest-validate "30.0.2" yargs "^17.7.2" @@ -9357,28 +9390,28 @@ jest-cli@^29.7.0: jest-validate "^29.7.0" yargs "^17.3.1" -jest-config@30.0.3: - version "30.0.3" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-30.0.3.tgz#978853722b9b0f2d0596025ea423cc6c7b603c07" - integrity sha512-j0L4oRCtJwNyZktXIqwzEiDVQXBbQ4dqXuLD/TZdn++hXIcIfZmjHgrViEy5s/+j4HvITmAXbexVZpQ/jnr0bg== +jest-config@30.0.4: + version "30.0.4" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-30.0.4.tgz#a710897373ae2b0ad8db027cb7a06e6d4a903c41" + integrity sha512-3dzbO6sh34thAGEjJIW0fgT0GA0EVlkski6ZzMcbW6dzhenylXAE/Mj2MI4HonroWbkKc6wU6bLVQ8dvBSZ9lA== dependencies: "@babel/core" "^7.27.4" "@jest/get-type" "30.0.1" "@jest/pattern" "30.0.1" - "@jest/test-sequencer" "30.0.2" + "@jest/test-sequencer" "30.0.4" "@jest/types" "30.0.1" - babel-jest "30.0.2" + babel-jest "30.0.4" chalk "^4.1.2" ci-info "^4.2.0" deepmerge "^4.3.1" glob "^10.3.10" graceful-fs "^4.2.11" - jest-circus "30.0.3" + jest-circus "30.0.4" jest-docblock "30.0.1" - jest-environment-node "30.0.2" + jest-environment-node "30.0.4" jest-regex-util "30.0.1" jest-resolve "30.0.2" - jest-runner "30.0.3" + jest-runner "30.0.4" jest-util "30.0.2" jest-validate "30.0.2" micromatch "^4.0.8" @@ -9415,10 +9448,10 @@ jest-config@^29.7.0: slash "^3.0.0" strip-json-comments "^3.1.1" -jest-diff@30.0.3: - version "30.0.3" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-30.0.3.tgz#50ac056b90fe9151d6266b18a27adeb064c30235" - integrity sha512-Q1TAV0cUcBTic57SVnk/mug0/ASyAqtSIOkr7RAlxx97llRYsM74+E8N5WdGJUlwCKwgxPAkVjKh653h1+HA9A== +jest-diff@30.0.4: + version "30.0.4" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-30.0.4.tgz#f6e71d19ed6e8f5c7f1bead9ac406c0dd6abce5a" + integrity sha512-TSjceIf6797jyd+R64NXqicttROD+Qf98fex7CowmlSn7f8+En0da1Dglwr1AXxDtVizoxXYZBlUQwNhoOXkNw== dependencies: "@jest/diff-sequences" "30.0.1" "@jest/get-type" "30.0.1" @@ -9471,13 +9504,13 @@ jest-each@^29.7.0: jest-util "^29.7.0" pretty-format "^29.7.0" -jest-environment-node@30.0.2: - version "30.0.2" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-30.0.2.tgz#3c24d6becb505f344f52cddb15ea506cf3288543" - integrity sha512-XsGtZ0H+a70RsxAQkKuIh0D3ZlASXdZdhpOSBq9WRPq6lhe0IoQHGW0w9ZUaPiZQ/CpkIdprvlfV1QcXcvIQLQ== +jest-environment-node@30.0.4: + version "30.0.4" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-30.0.4.tgz#080f2d6e438ef35a4701a09207fd2cfa030cd4a3" + integrity sha512-p+rLEzC2eThXqiNh9GHHTC0OW5Ca4ZfcURp7scPjYBcmgpR9HG6750716GuUipYf2AcThU3k20B31USuiaaIEg== dependencies: - "@jest/environment" "30.0.2" - "@jest/fake-timers" "30.0.2" + "@jest/environment" "30.0.4" + "@jest/fake-timers" "30.0.4" "@jest/types" "30.0.1" "@types/node" "*" jest-mock "30.0.2" @@ -9574,14 +9607,14 @@ jest-leak-detector@^29.7.0: jest-get-type "^29.6.3" pretty-format "^29.7.0" -jest-matcher-utils@30.0.3: - version "30.0.3" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-30.0.3.tgz#e07e4776bade71a3a7948a9bf8aeede311c5013a" - integrity sha512-hMpVFGFOhYmIIRGJ0HgM9htC5qUiJ00famcc9sRFchJJiLZbbVKrAztcgE6VnXLRxA3XZ0bvNA7hQWh3oHXo/A== +jest-matcher-utils@30.0.4: + version "30.0.4" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-30.0.4.tgz#1aab71eb7ba401f81d9ef7231feb88392e4a6e54" + integrity sha512-ubCewJ54YzeAZ2JeHHGVoU+eDIpQFsfPQs0xURPWoNiO42LGJ+QGgfSf+hFIRplkZDkhH5MOvuxHKXRTUU3dUQ== dependencies: "@jest/get-type" "30.0.1" chalk "^4.1.2" - jest-diff "30.0.3" + jest-diff "30.0.4" pretty-format "30.0.2" jest-matcher-utils@^29.7.0: @@ -9657,13 +9690,13 @@ jest-regex-util@^29.6.3: resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.6.3.tgz#4a556d9c776af68e1c5f48194f4d0327d24e8a52" integrity sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg== -jest-resolve-dependencies@30.0.3: - version "30.0.3" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-30.0.3.tgz#8278f54a84009028b823f5c1f7033fb968405b2f" - integrity sha512-FlL6u7LiHbF0Oe27k7DHYMq2T2aNpPhxnNo75F7lEtu4A6sSw+TKkNNUGNcVckdFoL0RCWREJsC1HsKDwKRZzQ== +jest-resolve-dependencies@30.0.4: + version "30.0.4" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-30.0.4.tgz#54decdedec040ec0b5b717af43a0b538d638d395" + integrity sha512-EQBYow19B/hKr4gUTn+l8Z+YLlP2X0IoPyp0UydOtrcPbIOYzJ8LKdFd+yrbwztPQvmlBFUwGPPEzHH1bAvFAw== dependencies: jest-regex-util "30.0.1" - jest-snapshot "30.0.3" + jest-snapshot "30.0.4" jest-resolve-dependencies@^29.7.0: version "29.7.0" @@ -9702,15 +9735,15 @@ jest-resolve@^29.7.0: resolve.exports "^2.0.0" slash "^3.0.0" -jest-runner@30.0.3: - version "30.0.3" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-30.0.3.tgz#baa1d5e77655c70cea9aa4138cfb437f6bada607" - integrity sha512-CxYBzu9WStOBBXAKkLXGoUtNOWsiS1RRmUQb6SsdUdTcqVncOau7m8AJ4cW3Mz+YL1O9pOGPSYLyvl8HBdFmkQ== +jest-runner@30.0.4: + version "30.0.4" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-30.0.4.tgz#3647eeb04f2d0b2c0a5769dd73cd861ebc5853f4" + integrity sha512-mxY0vTAEsowJwvFJo5pVivbCpuu6dgdXRmt3v3MXjBxFly7/lTk3Td0PaMyGOeNQUFmSuGEsGYqhbn7PA9OekQ== dependencies: - "@jest/console" "30.0.2" - "@jest/environment" "30.0.2" - "@jest/test-result" "30.0.2" - "@jest/transform" "30.0.2" + "@jest/console" "30.0.4" + "@jest/environment" "30.0.4" + "@jest/test-result" "30.0.4" + "@jest/transform" "30.0.4" "@jest/types" "30.0.1" "@types/node" "*" chalk "^4.1.2" @@ -9718,14 +9751,14 @@ jest-runner@30.0.3: exit-x "^0.2.2" graceful-fs "^4.2.11" jest-docblock "30.0.1" - jest-environment-node "30.0.2" + jest-environment-node "30.0.4" jest-haste-map "30.0.2" jest-leak-detector "30.0.2" jest-message-util "30.0.2" jest-resolve "30.0.2" - jest-runtime "30.0.3" + jest-runtime "30.0.4" jest-util "30.0.2" - jest-watcher "30.0.2" + jest-watcher "30.0.4" jest-worker "30.0.2" p-limit "^3.1.0" source-map-support "0.5.13" @@ -9757,17 +9790,17 @@ jest-runner@^29.7.0: p-limit "^3.1.0" source-map-support "0.5.13" -jest-runtime@30.0.3: - version "30.0.3" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-30.0.3.tgz#1eb112924426e8b90c37f0ea7da1b51966e252bf" - integrity sha512-Xjosq0C48G9XEQOtmgrjXJwPaUPaq3sPJwHDRaiC+5wi4ZWxO6Lx6jNkizK/0JmTulVNuxP8iYwt77LGnfg3/w== +jest-runtime@30.0.4: + version "30.0.4" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-30.0.4.tgz#100f31a5f6c4a6586c2ce91a936a10f1aca64749" + integrity sha512-tUQrZ8+IzoZYIHoPDQEB4jZoPyzBjLjq7sk0KVyd5UPRjRDOsN7o6UlvaGF8ddpGsjznl9PW+KRgWqCNO+Hn7w== dependencies: - "@jest/environment" "30.0.2" - "@jest/fake-timers" "30.0.2" - "@jest/globals" "30.0.3" + "@jest/environment" "30.0.4" + "@jest/fake-timers" "30.0.4" + "@jest/globals" "30.0.4" "@jest/source-map" "30.0.1" - "@jest/test-result" "30.0.2" - "@jest/transform" "30.0.2" + "@jest/test-result" "30.0.4" + "@jest/transform" "30.0.4" "@jest/types" "30.0.1" "@types/node" "*" chalk "^4.1.2" @@ -9780,7 +9813,7 @@ jest-runtime@30.0.3: jest-mock "30.0.2" jest-regex-util "30.0.1" jest-resolve "30.0.2" - jest-snapshot "30.0.3" + jest-snapshot "30.0.4" jest-util "30.0.2" slash "^3.0.0" strip-bom "^4.0.0" @@ -9813,27 +9846,27 @@ jest-runtime@^29.7.0: slash "^3.0.0" strip-bom "^4.0.0" -jest-snapshot@30.0.3: - version "30.0.3" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-30.0.3.tgz#f605254223eee0946d205c6e7ede7238e87be920" - integrity sha512-F05JCohd3OA1N9+5aEPXA6I0qOfZDGIx0zTq5Z4yMBg2i1p5ELfBusjYAWwTkC12c7dHcbyth4QAfQbS7cRjow== +jest-snapshot@30.0.4: + version "30.0.4" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-30.0.4.tgz#21fdc1d944bc077a58f5eda88ef77a26dee4c3ee" + integrity sha512-S/8hmSkeUib8WRUq9pWEb5zMfsOjiYWDWzFzKnjX7eDyKKgimsu9hcmsUEg8a7dPAw8s/FacxsXquq71pDgPjQ== dependencies: "@babel/core" "^7.27.4" "@babel/generator" "^7.27.5" "@babel/plugin-syntax-jsx" "^7.27.1" "@babel/plugin-syntax-typescript" "^7.27.1" "@babel/types" "^7.27.3" - "@jest/expect-utils" "30.0.3" + "@jest/expect-utils" "30.0.4" "@jest/get-type" "30.0.1" - "@jest/snapshot-utils" "30.0.1" - "@jest/transform" "30.0.2" + "@jest/snapshot-utils" "30.0.4" + "@jest/transform" "30.0.4" "@jest/types" "30.0.1" babel-preset-current-node-syntax "^1.1.0" chalk "^4.1.2" - expect "30.0.3" + expect "30.0.4" graceful-fs "^4.2.11" - jest-diff "30.0.3" - jest-matcher-utils "30.0.3" + jest-diff "30.0.4" + jest-matcher-utils "30.0.4" jest-message-util "30.0.2" jest-util "30.0.2" pretty-format "30.0.2" @@ -9914,12 +9947,12 @@ jest-validate@^29.7.0: leven "^3.1.0" pretty-format "^29.7.0" -jest-watcher@30.0.2: - version "30.0.2" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-30.0.2.tgz#ec93ed25183679f549a47f6197267d50ec83ea51" - integrity sha512-vYO5+E7jJuF+XmONr6CrbXdlYrgvZqtkn6pdkgjt/dU64UAdc0v1cAVaAeWtAfUUMScxNmnUjKPUMdCpNVASwg== +jest-watcher@30.0.4: + version "30.0.4" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-30.0.4.tgz#f51b9870760d917851bb5b871e95b3c5f021cb86" + integrity sha512-YESbdHDs7aQOCSSKffG8jXqOKFqw4q4YqR+wHYpR5GWEQioGvL0BfbcjvKIvPEM0XGfsfJrka7jJz3Cc3gI4VQ== dependencies: - "@jest/test-result" "30.0.2" + "@jest/test-result" "30.0.4" "@jest/types" "30.0.1" "@types/node" "*" ansi-escapes "^4.3.2" @@ -9978,15 +10011,15 @@ jest@^29, jest@^29.7.0: import-local "^3.0.2" jest-cli "^29.7.0" -jest@^30.0.3: - version "30.0.3" - resolved "https://registry.yarnpkg.com/jest/-/jest-30.0.3.tgz#fc3b6b370e2820d718ea299d159a7ba4637dbd35" - integrity sha512-Uy8xfeE/WpT2ZLGDXQmaYNzw2v8NUKuYeKGtkS6sDxwsdQihdgYCXaKIYnph1h95DN5H35ubFDm0dfmsQnjn4Q== +jest@^30.0.4: + version "30.0.4" + resolved "https://registry.yarnpkg.com/jest/-/jest-30.0.4.tgz#4596879f2af0560d9b1e588b252531cf10148947" + integrity sha512-9QE0RS4WwTj/TtTC4h/eFVmFAhGNVerSB9XpJh8sqaXlP73ILcPcZ7JWjjEtJJe2m8QyBLKKfPQuK+3F+Xij/g== dependencies: - "@jest/core" "30.0.3" + "@jest/core" "30.0.4" "@jest/types" "30.0.1" import-local "^3.2.0" - jest-cli "30.0.3" + jest-cli "30.0.4" jju@~1.4.0: version "1.4.0" @@ -10068,9 +10101,9 @@ jsii-diff@^1.112.0: yargs "^16.2.0" jsii-docgen@^10.5.0: - version "10.7.5" - resolved "https://registry.yarnpkg.com/jsii-docgen/-/jsii-docgen-10.7.5.tgz#3a6d850d665866d51d1895e73a8ca3dc69e0ca8d" - integrity sha512-XCYz7grFe7VzcMMfg2cCv4W0AmsdQUoKapmVuanZ1oLWjQk0j/2FuCLlaGL9NszfeGsg8R5pzMM8QTDhQRGgAw== + version "10.7.6" + resolved "https://registry.yarnpkg.com/jsii-docgen/-/jsii-docgen-10.7.6.tgz#1e106d16e470a5b02cfee1fd66ad1685c640f09a" + integrity sha512-kRN5567oSx5nzrCycvwW7lKoqX0BcZz76quh99F2Fq6hrFfe5f0P9VyE/iWlOJEcJPbdsVvJN88YJwkFI8ki8Q== dependencies: "@jsii/spec" "^1.112.0" case "^1.6.3" @@ -10111,10 +10144,10 @@ jsii-reflect@^1.112.0: oo-ascii-tree "^1.112.0" yargs "^16.2.0" -jsii-rosetta@5.6: - version "5.6.20" - resolved "https://registry.yarnpkg.com/jsii-rosetta/-/jsii-rosetta-5.6.20.tgz#694b7229759104c0b50c9119601f615027d5295b" - integrity sha512-XPErczwwxUgKWoKObyU3GyIEUXpNeiYFHZg72Y4/Aqdo8pneF9c9XlGCOw46Lz2ZKWD4/jdQKblWlVXN84kilA== +jsii-rosetta@5.8: + version "5.8.11" + resolved "https://registry.yarnpkg.com/jsii-rosetta/-/jsii-rosetta-5.8.11.tgz#65a5c9e9e9360429df448d9231db17d0132990e2" + integrity sha512-wHi5eI8tgTKrGk9dY99a8ZFiYiP9/gPvRECzoX2Vq0so6G5w/R1jd5vb8D6UTX7hDTPSaKChj2Bi0tG1BNod/g== dependencies: "@jsii/check-node" "1.112.0" "@jsii/spec" "^1.112.0" @@ -10122,18 +10155,18 @@ jsii-rosetta@5.6: chalk "^4" commonmark "^0.31.2" fast-glob "^3.3.3" - jsii "~5.6.0" + jsii "~5.8.0" semver "^7.7.2" semver-intersect "^1.5.0" stream-json "^1.9.1" - typescript "~5.6" + typescript "~5.8" workerpool "^6.5.1" yargs "^17.7.2" -jsii@5.6, jsii@~5.6.0: - version "5.6.22" - resolved "https://registry.yarnpkg.com/jsii/-/jsii-5.6.22.tgz#fb28c889d47af112931ad4b737f6300b44b6c0b1" - integrity sha512-hsjZDLs7pw4116XT3CfFkhIILYAxBVi7BiaxkPejImEIKQTZVaudxHZ1hwyxacRZF0sHUJTfYkT3qBTnzSPUhA== +jsii@5.8, jsii@~5.8.0: + version "5.8.15" + resolved "https://registry.yarnpkg.com/jsii/-/jsii-5.8.15.tgz#6a00b738e5543a834f8eb9d0b67dcdfc68f635f2" + integrity sha512-PMA+JhuuXMqGgfb3cGndlr+5NAYoOFHZRMD5uoq+oYNoPvsIejwJbw83Al1BYXhl59f/CI3xTzo5ev3krkqHoQ== dependencies: "@jsii/check-node" "1.112.0" "@jsii/spec" "^1.112.0" @@ -10145,7 +10178,7 @@ jsii@5.6, jsii@~5.6.0: semver-intersect "^1.5.0" sort-json "^2.0.1" spdx-license-list "^6.10.0" - typescript "~5.6" + typescript "~5.8" yargs "^17.7.2" json-buffer@3.0.1: @@ -10645,7 +10678,7 @@ make-error@^1.1.1, make-error@^1.3.6: resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== -make-fetch-happen@^14.0.0, make-fetch-happen@^14.0.1, make-fetch-happen@^14.0.2, make-fetch-happen@^14.0.3: +make-fetch-happen@^14.0.0, make-fetch-happen@^14.0.2, make-fetch-happen@^14.0.3: version "14.0.3" resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-14.0.3.tgz#d74c3ecb0028f08ab604011e0bc6baed483fcdcd" integrity sha512-QMjGbFTP0blj97EeidG5hk/QhKQ3T4ICckQGLgz38QF7Vgbk6e6FTARN8KhKxyBbWn8R0HU+bnw8aSoFPD4qtQ== @@ -10814,6 +10847,13 @@ minimatch@^5.0.1, minimatch@^5.1.0: dependencies: brace-expansion "^2.0.1" +minimatch@^8.0.2: + version "8.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-8.0.4.tgz#847c1b25c014d4e9a7f68aaf63dedd668a626229" + integrity sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA== + dependencies: + brace-expansion "^2.0.1" + minimatch@^9.0.0, minimatch@^9.0.4, minimatch@^9.0.5: version "9.0.5" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" @@ -10888,6 +10928,11 @@ minipass@^3.0.0: dependencies: yallist "^4.0.0" +minipass@^4.2.4: + version "4.2.8" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-4.2.8.tgz#f0010f64393ecfc1d1ccb5f582bcaf45f48e1a3a" + integrity sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ== + minipass@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d" @@ -11046,19 +11091,19 @@ mute-stream@~0.0.4: integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== nan@^2.17.0: - version "2.22.2" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.22.2.tgz#6b504fd029fb8f38c0990e52ad5c26772fdacfbb" - integrity sha512-DANghxFkS1plDdRsX0X9pm0Z6SJNN6gBdtXfanwoZ8hooC5gosGFSBGRYHUVPz1asKA/kMRqDRdHrluZ61SpBQ== + version "2.23.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.23.0.tgz#24aa4ddffcc37613a2d2935b97683c1ec96093c6" + integrity sha512-1UxuyYGdoQHcGg87Lkqm3FzefucTa0NAiOcuRsDmysep3c1LVCRK2krrUDafMWtjSG04htvAmvg96+SDknOmgQ== nanoid@^3.3.11: version "3.3.11" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.11.tgz#4f4f112cefbe303202f2199838128936266d185b" integrity sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w== -napi-postinstall@^0.2.4: - version "0.2.5" - resolved "https://registry.yarnpkg.com/napi-postinstall/-/napi-postinstall-0.2.5.tgz#57d8a142f854e5a510c7b71ca101e89c11eddf35" - integrity sha512-kmsgUvCRIJohHjbZ3V8avP0I1Pekw329MVAMDzVxsrkjgdnqiwvMX5XwR+hWV66vsAtZ+iM+fVnq8RTQawUmCQ== +napi-postinstall@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/napi-postinstall/-/napi-postinstall-0.3.0.tgz#888e51d1fb500e86dcf6ace1baccdbb377e654ce" + integrity sha512-M7NqKyhODKV1gRLdkwE7pDsZP2/SC2a2vHkOYh9MCpKMbWVfyVfUw5MaH83Fv6XMjxr5jryUp3IDDL9rlxsTeA== native-duplexpair@^1.0.0: version "1.0.0" @@ -11126,12 +11171,12 @@ nock@13: json-stringify-safe "^5.0.1" propagate "^2.0.0" -node-backpack@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/node-backpack/-/node-backpack-1.0.0.tgz#09f25e22e5fb89df02ba75f44d70d16fb484906d" - integrity sha512-9C8Ubn1IWgOcL5oILjw/sHT3/X53qKlCtOf8Qw/VsdczVoaHasYYDNxOOKM73coE/ezzqYNKPivfF4/9XIfX9g== +node-backpack@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/node-backpack/-/node-backpack-1.1.0.tgz#491fae79cf9343bf6331871f34a963f12a13ceee" + integrity sha512-5jv1uHBK8oEQJPxD0CKrtYx6F/8ugatEMZLbJawsG8bSnJ7wg5MpDn/CLXP7yD06hZ0RzZyeD4Bj4YWvxQFMCw== dependencies: - esbuild "^0.25.5" + esbuild "^0.25.6" fs-extra "^10.1.0" license-checker "^25.0.1" madge "^5.0.2" @@ -11909,7 +11954,7 @@ 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-scurry@^1.11.1: +path-scurry@^1.11.1, path-scurry@^1.6.1: version "1.11.1" resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== @@ -11975,9 +12020,9 @@ picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1: integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== picomatch@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.2.tgz#77c742931e8f3b8820946c76cd0c1f13730d1dab" - integrity sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg== + version "4.0.3" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.3.tgz#796c76136d1eead715db1e7bad785dedd695a042" + integrity sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q== pify@^2.3.0: version "2.3.0" @@ -12170,10 +12215,10 @@ proggy@^3.0.0: resolved "https://registry.yarnpkg.com/proggy/-/proggy-3.0.0.tgz#874e91fed27fe00a511758e83216a6b65148bd6c" integrity sha512-QE8RApCM3IaRRxVzxrjbgNMpQEX6Wu0p0KBeoSiSEw5/bsGwZHsshF4LCxH2jp/r6BU+bqA3LrMDEYNfJnpD8Q== -projen@^0.94.0: - version "0.94.0" - resolved "https://registry.yarnpkg.com/projen/-/projen-0.94.0.tgz#6d2c7bc3eeb9314e83be79a626a514314259c39e" - integrity sha512-ttlEalyI5pVMgXEtNBvqmDrrE2nA7uIxRyJmGchK8z503AOYHcRk/MKDvQiLicHMQydA4LubAShrK/PCE18hEw== +projen@^0.94.2: + version "0.94.2" + resolved "https://registry.yarnpkg.com/projen/-/projen-0.94.2.tgz#0cadbff58e01af29e31967c4ad5c9633e284747b" + integrity sha512-9ZUaub1El8487FAj3UGFiVJOY0LFKdvy73ueI53WySIDWoFcjNyzRb046O6JWXdA9Lakk8C8EqEkOlVIuGoINw== dependencies: "@iarna/toml" "^2.2.5" case "^1.6.3" @@ -13055,9 +13100,9 @@ socks-proxy-agent@^8.0.3, socks-proxy-agent@^8.0.5: socks "^2.8.3" socks@^2.6.2, socks@^2.8.3: - version "2.8.5" - resolved "https://registry.yarnpkg.com/socks/-/socks-2.8.5.tgz#bfe18f5ead1efc93f5ec90c79fa8bdccbcee2e64" - integrity sha512-iF+tNDQla22geJdTyJB1wM/qrX9DMRwWrciEPwWLPRWAUEM8sQiyxgckLxWT1f7+9VabJS0jTGGr4QgBuvi6Ww== + version "2.8.6" + resolved "https://registry.yarnpkg.com/socks/-/socks-2.8.6.tgz#e335486a2552f34f932f0c27d8dbb93f2be867aa" + integrity sha512-pe4Y2yzru68lXCb38aAqRf5gvN8YdjP1lok5o0J7BOHljkyCGKVz7H3vpVIXKD27rj2giOJ7DwVyk/GWrPHDWA== dependencies: ip-address "^9.0.5" smart-buffer "^4.2.0" @@ -13426,11 +13471,16 @@ strip-json-comments@~2.0.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== -strnum@^1.0.4, strnum@^1.0.5: +strnum@^1.0.4: version "1.1.2" resolved "https://registry.yarnpkg.com/strnum/-/strnum-1.1.2.tgz#57bca4fbaa6f271081715dbc9ed7cee5493e28e4" integrity sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA== +strnum@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/strnum/-/strnum-2.1.1.tgz#cf2a6e0cf903728b8b2c4b971b7e36b4e82d46ab" + integrity sha512-7ZvoFTiCnGxBtDqJ//Cu6fWtZtc7Y3x+QOirG15wztbdngGSkht27o2pyGWrVy0b4WAy3jbKmnoK6g5VlVNUUw== + stylus-lookup@^3.0.1: version "3.0.2" resolved "https://registry.yarnpkg.com/stylus-lookup/-/stylus-lookup-3.0.2.tgz#c9eca3ff799691020f30b382260a67355fefdddd" @@ -13790,13 +13840,13 @@ tsx@^4.20.3: fsevents "~2.3.3" tuf-js@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/tuf-js/-/tuf-js-3.0.1.tgz#e3f07ed3d8e87afaa70607bd1ef801d5c1f57177" - integrity sha512-+68OP1ZzSF84rTckf3FA95vJ1Zlx/uaXyiiKyPd1pA4rZNkpEvDAKmsu1xUSmbF/chCRYgZ6UZkDwC7PmzmAyA== + version "3.1.0" + resolved "https://registry.yarnpkg.com/tuf-js/-/tuf-js-3.1.0.tgz#61b847fe9aa86a7d5bda655a4647e026aa73a1be" + integrity sha512-3T3T04WzowbwV2FDiGXBbr81t64g1MUGGJRgT4x5o97N+8ArdhVCAF9IxFrxuSJmM3E5Asn7nKHkao0ibcZXAg== dependencies: "@tufjs/models" "3.0.1" - debug "^4.3.6" - make-fetch-happen "^14.0.1" + debug "^4.4.1" + make-fetch-happen "^14.0.3" type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" @@ -13917,10 +13967,10 @@ typescript-json-schema@^0.65.1: typescript "~5.5.0" yargs "^17.1.1" -typescript@5.6, typescript@~5.6: - version "5.6.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.6.3.tgz#5f3449e31c9d94febb17de03cc081dd56d81db5b" - integrity sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw== +typescript@5.8, typescript@^5.7.3, typescript@^5.8.3, typescript@~5.8: + version "5.8.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.8.3.tgz#92f8a3e5e3cf497356f4178c34cd65a7f5e8440e" + integrity sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ== typescript@5.8.2: version "5.8.2" @@ -13932,11 +13982,6 @@ typescript@^3.9.10, typescript@^3.9.5, typescript@^3.9.7: resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.10.tgz#70f3910ac7a51ed6bef79da7800690b19bf778b8" integrity sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q== -typescript@^5.7.3, typescript@^5.8.3: - version "5.8.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.8.3.tgz#92f8a3e5e3cf497356f4178c34cd65a7f5e8440e" - integrity sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ== - typescript@~5.5.0: version "5.5.4" resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.5.4.tgz#d9852d6c82bad2d2eda4fd74a5762a8f5909e9ba" @@ -14007,31 +14052,31 @@ unpipe@1.0.0, unpipe@~1.0.0: integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== unrs-resolver@^1.6.2, unrs-resolver@^1.7.11: - version "1.9.2" - resolved "https://registry.yarnpkg.com/unrs-resolver/-/unrs-resolver-1.9.2.tgz#1a7c73335a5e510643664d7bb4bb6f5c28782e36" - integrity sha512-VUyWiTNQD7itdiMuJy+EuLEErLj3uwX/EpHQF8EOf33Dq3Ju6VW1GXm+swk6+1h7a49uv9fKZ+dft9jU7esdLA== + version "1.11.1" + resolved "https://registry.yarnpkg.com/unrs-resolver/-/unrs-resolver-1.11.1.tgz#be9cd8686c99ef53ecb96df2a473c64d304048a9" + integrity sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg== dependencies: - napi-postinstall "^0.2.4" + napi-postinstall "^0.3.0" optionalDependencies: - "@unrs/resolver-binding-android-arm-eabi" "1.9.2" - "@unrs/resolver-binding-android-arm64" "1.9.2" - "@unrs/resolver-binding-darwin-arm64" "1.9.2" - "@unrs/resolver-binding-darwin-x64" "1.9.2" - "@unrs/resolver-binding-freebsd-x64" "1.9.2" - "@unrs/resolver-binding-linux-arm-gnueabihf" "1.9.2" - "@unrs/resolver-binding-linux-arm-musleabihf" "1.9.2" - "@unrs/resolver-binding-linux-arm64-gnu" "1.9.2" - "@unrs/resolver-binding-linux-arm64-musl" "1.9.2" - "@unrs/resolver-binding-linux-ppc64-gnu" "1.9.2" - "@unrs/resolver-binding-linux-riscv64-gnu" "1.9.2" - "@unrs/resolver-binding-linux-riscv64-musl" "1.9.2" - "@unrs/resolver-binding-linux-s390x-gnu" "1.9.2" - "@unrs/resolver-binding-linux-x64-gnu" "1.9.2" - "@unrs/resolver-binding-linux-x64-musl" "1.9.2" - "@unrs/resolver-binding-wasm32-wasi" "1.9.2" - "@unrs/resolver-binding-win32-arm64-msvc" "1.9.2" - "@unrs/resolver-binding-win32-ia32-msvc" "1.9.2" - "@unrs/resolver-binding-win32-x64-msvc" "1.9.2" + "@unrs/resolver-binding-android-arm-eabi" "1.11.1" + "@unrs/resolver-binding-android-arm64" "1.11.1" + "@unrs/resolver-binding-darwin-arm64" "1.11.1" + "@unrs/resolver-binding-darwin-x64" "1.11.1" + "@unrs/resolver-binding-freebsd-x64" "1.11.1" + "@unrs/resolver-binding-linux-arm-gnueabihf" "1.11.1" + "@unrs/resolver-binding-linux-arm-musleabihf" "1.11.1" + "@unrs/resolver-binding-linux-arm64-gnu" "1.11.1" + "@unrs/resolver-binding-linux-arm64-musl" "1.11.1" + "@unrs/resolver-binding-linux-ppc64-gnu" "1.11.1" + "@unrs/resolver-binding-linux-riscv64-gnu" "1.11.1" + "@unrs/resolver-binding-linux-riscv64-musl" "1.11.1" + "@unrs/resolver-binding-linux-s390x-gnu" "1.11.1" + "@unrs/resolver-binding-linux-x64-gnu" "1.11.1" + "@unrs/resolver-binding-linux-x64-musl" "1.11.1" + "@unrs/resolver-binding-wasm32-wasi" "1.11.1" + "@unrs/resolver-binding-win32-arm64-msvc" "1.11.1" + "@unrs/resolver-binding-win32-ia32-msvc" "1.11.1" + "@unrs/resolver-binding-win32-x64-msvc" "1.11.1" update-browserslist-db@^1.1.3: version "1.1.3"