From 991a7b8d3e00eab25850470d0a9b83303fe13243 Mon Sep 17 00:00:00 2001 From: Mark DeCrane Date: Fri, 13 Oct 2023 09:20:59 -0400 Subject: [PATCH 01/23] feat: add resource move functionality --- .../get/generator/models/attribute-model.ts | 2 + packages/cdktf/lib/index.ts | 1 + .../cdktf/lib/terraform-move-addresses.ts | 35 +++++++++ packages/cdktf/lib/terraform-resource.ts | 75 +++++++++++++++++-- packages/cdktf/lib/terraform-stack.ts | 2 + 5 files changed, 109 insertions(+), 6 deletions(-) create mode 100644 packages/cdktf/lib/terraform-move-addresses.ts diff --git a/packages/@cdktf/provider-generator/lib/get/generator/models/attribute-model.ts b/packages/@cdktf/provider-generator/lib/get/generator/models/attribute-model.ts index 009927150e..8f95350d3d 100644 --- a/packages/@cdktf/provider-generator/lib/get/generator/models/attribute-model.ts +++ b/packages/@cdktf/provider-generator/lib/get/generator/models/attribute-model.ts @@ -49,6 +49,8 @@ export function escapeAttributeName(name: string) { if (name === "tfResourceType") return `${name}Attribute`; // `importFrom` has potential for common name collision with providers if (name === "importFrom") return `${name}Attribute`; + // `move` could have common name collision with providers + if (name === "move") return `${name}Attribute`; return name; } diff --git a/packages/cdktf/lib/index.ts b/packages/cdktf/lib/index.ts index 152d2ea11a..6bdd5a1dbf 100644 --- a/packages/cdktf/lib/index.ts +++ b/packages/cdktf/lib/index.ts @@ -38,6 +38,7 @@ export * from "./terraform-provisioner"; export * from "./terraform-conditions"; export * from "./terraform-count"; export * from "./importable-resource"; +export * from "./terraform-move-addresses"; // required for JSII because Fn extends from it export * from "./functions/terraform-functions.generated"; diff --git a/packages/cdktf/lib/terraform-move-addresses.ts b/packages/cdktf/lib/terraform-move-addresses.ts new file mode 100644 index 0000000000..120ab1aa24 --- /dev/null +++ b/packages/cdktf/lib/terraform-move-addresses.ts @@ -0,0 +1,35 @@ +import { Construct } from "constructs"; +import { TerraformResource } from "./terraform-resource"; +import { TerraformStack } from "./terraform-stack"; + +/** + * + */ +export class TerraformMoveAddresses { + private _terraformAddressMap: Map = new Map< + string, + TerraformResource + >(); + + // what do we need? + /** + * map for a tag -> resource path !!! + * function to add to the resource path at a tag + * function to return the specificed resource address at a certain tag + */ + + // Would trying to access this at a higher abstract lead to things not being present? since we only add stuff later on + + public add(resource: TerraformResource, tag: string): void { + this._terraformAddressMap.set(tag, resource); + } + + public getPath(tag: string): TerraformResource | undefined { + return this._terraformAddressMap.get(tag); + } + + public static addresses(scope: Construct) { + return (scope.node.root.node.children[0] as unknown as TerraformStack) + .moveAddresses; // TODO: see if there is a better way of doing this, or if theres any problems with it; + } +} diff --git a/packages/cdktf/lib/terraform-resource.ts b/packages/cdktf/lib/terraform-resource.ts index 38b8979c5b..78071b9913 100644 --- a/packages/cdktf/lib/terraform-resource.ts +++ b/packages/cdktf/lib/terraform-resource.ts @@ -23,6 +23,7 @@ import { RemoteExecProvisioner, } from "./terraform-provisioner"; import { ValidateTerraformVersion } from "./validations/validate-terraform-version"; +import { TerraformStack } from "./terraform-stack"; const TERRAFORM_RESOURCE_SYMBOL = Symbol.for("cdktf/TerraformResource"); @@ -77,6 +78,11 @@ export interface TerraformResourceImport { readonly provider?: TerraformProvider; } +export interface TerraformResourceMove { + readonly from: string; + readonly to: string; +} + // eslint-disable-next-line jsdoc/require-jsdoc export class TerraformResource extends TerraformElement @@ -97,6 +103,8 @@ export class TerraformResource FileProvisioner | LocalExecProvisioner | RemoteExecProvisioner >; private _imported?: TerraformResourceImport; + private _moved?: TerraformResourceMove; + private _scope: Construct; constructor(scope: Construct, id: string, config: TerraformResourceConfig) { super(scope, id, config.terraformResourceType); @@ -115,6 +123,7 @@ export class TerraformResource this.forEach = config.forEach; this.provisioners = config.provisioners; this.connection = config.connection; + this._scope = scope; } public static isTerraformResource(x: any): x is TerraformResource { @@ -208,7 +217,6 @@ export class TerraformResource ...(attributes["//"] ?? {}), ...this.constructNodeMetadata, }; - return { import: this._imported ? [ @@ -219,11 +227,19 @@ export class TerraformResource }, ] : undefined, - resource: { - [this.terraformResourceType]: { - [this.friendlyUniqueId]: attributes, - }, - }, + resource: this._moved + ? undefined + : { + [this.terraformResourceType]: { + [this.friendlyUniqueId]: attributes, + }, + }, + moved: this._moved + ? { + to: this._moved.to, + from: this._moved.from, + } + : undefined, }; } @@ -239,6 +255,11 @@ export class TerraformResource [this.terraformResourceType]: [this.friendlyUniqueId], } : undefined, + moved: this._moved + ? { + [this.terraformResourceType]: [this.friendlyUniqueId], // TODO: anything more we need here? + } + : undefined, }; } @@ -260,4 +281,46 @@ export class TerraformResource ) ); } + + public move( + resource: TerraformResource | undefined, + index?: string | number + ) { + if (resource === undefined) { + throw new Error("tag not set"); // TODO: make better error message + } + const movedToId = index // TODO: make it work with complex types too + ? typeof index === "string" + ? `${this.terraformResourceType}.${resource.friendlyUniqueId}["${index}"]` + : `${this.terraformResourceType}.${resource.friendlyUniqueId}[${index}]` + : `${this.terraformResourceType}.${resource.friendlyUniqueId}`; + const movedFromId = `${this.terraformResourceType}.${this.friendlyUniqueId}`; + this._moved = { to: movedToId, from: movedFromId }; + // TODO: add validation of correct Terraform Version + } + + public addTag(tag: string) { + // get parent stack address map + const stackMoveAddresses = ( + this._scope.node.root.node.children[0] as unknown as TerraformStack + ).moveAddresses; + stackMoveAddresses.add(this, tag); + } + /** + public moveFrom(resource: TerraformResource, index?: string | number) { + const movedFromId = index + ? typeof index === "string" + ? (`${this.terraformResourceType}.${resource.friendlyUniqueId}["${index}"]`) + : (`${this.terraformResourceType}.${resource.friendlyUniqueId}[${index}]`) + : `${this.terraformResourceType}.${resource.friendlyUniqueId}` + const movedToId = `${this.terraformResourceType}.${this.friendlyUniqueId}` + this._moved = { to: movedToId, from: movedFromId } + // TODO: add validation of correct Terraform Version + } +*/ + /** + public hasMoved() { + this._hasMoved = true; + } + */ } diff --git a/packages/cdktf/lib/terraform-stack.ts b/packages/cdktf/lib/terraform-stack.ts index 34c4a00d59..f7157ded89 100644 --- a/packages/cdktf/lib/terraform-stack.ts +++ b/packages/cdktf/lib/terraform-stack.ts @@ -18,6 +18,7 @@ const STACK_SYMBOL = Symbol.for("cdktf/TerraformStack"); import { ValidateProviderPresence } from "./validations"; import { App } from "./app"; import { TerraformBackend } from "./terraform-backend"; +import { TerraformMoveAddresses } from "./terraform-move-addresses"; // eslint-disable-next-line @typescript-eslint/ban-types type StackIdentifier = string; @@ -62,6 +63,7 @@ export class TerraformStack extends Construct { {}; public synthesizer: IStackSynthesizer; public dependencies: TerraformStack[] = []; + public moveAddresses: TerraformMoveAddresses = new TerraformMoveAddresses(); constructor(scope: Construct, id: string) { super(scope, id); From 01f080394ff48782841ad5f939ee2d89efbee434 Mon Sep 17 00:00:00 2001 From: "hashicorp-copywrite[bot]" <110428419+hashicorp-copywrite[bot]@users.noreply.github.com> Date: Thu, 28 Sep 2023 21:34:57 +0000 Subject: [PATCH 02/23] chore: add required copyright headers Signed-off-by: hashicorp-copywrite[bot] <110428419+hashicorp-copywrite[bot]@users.noreply.github.com> --- packages/cdktf/lib/terraform-move-addresses.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/cdktf/lib/terraform-move-addresses.ts b/packages/cdktf/lib/terraform-move-addresses.ts index 120ab1aa24..10a2770ea6 100644 --- a/packages/cdktf/lib/terraform-move-addresses.ts +++ b/packages/cdktf/lib/terraform-move-addresses.ts @@ -1,3 +1,8 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: MPL-2.0 + */ + import { Construct } from "constructs"; import { TerraformResource } from "./terraform-resource"; import { TerraformStack } from "./terraform-stack"; From 39223494ff4eb9d6aa3f47ddd40b1774af8c9ba7 Mon Sep 17 00:00:00 2001 From: Mark DeCrane Date: Fri, 13 Oct 2023 09:22:47 -0400 Subject: [PATCH 03/23] feat: improved move workflow --- packages/cdktf/lib/terraform-resource.ts | 44 +++++++++--------------- 1 file changed, 16 insertions(+), 28 deletions(-) diff --git a/packages/cdktf/lib/terraform-resource.ts b/packages/cdktf/lib/terraform-resource.ts index 78071b9913..48f5695c08 100644 --- a/packages/cdktf/lib/terraform-resource.ts +++ b/packages/cdktf/lib/terraform-resource.ts @@ -23,7 +23,7 @@ import { RemoteExecProvisioner, } from "./terraform-provisioner"; import { ValidateTerraformVersion } from "./validations/validate-terraform-version"; -import { TerraformStack } from "./terraform-stack"; +import { TerraformMoveAddresses } from "./terraform-move-addresses"; const TERRAFORM_RESOURCE_SYMBOL = Symbol.for("cdktf/TerraformResource"); @@ -282,18 +282,25 @@ export class TerraformResource ); } - public move( - resource: TerraformResource | undefined, - index?: string | number - ) { + public move(tag: string, index?: string | number) { + /** if (resource === undefined) { throw new Error("tag not set"); // TODO: make better error message + }*/ + /** + const stackMoveAddresses = ( + this._scope.node.root.node.children[0] as unknown as TerraformStack + ).moveAddresses;*/ + const stackMoveAddresses = TerraformMoveAddresses.addresses(this._scope); + const moveToFriendlyUniqueId = stackMoveAddresses.getPath(tag); + if (!moveToFriendlyUniqueId) { + throw new Error("tag not set"); // TODO: make better error message } const movedToId = index // TODO: make it work with complex types too ? typeof index === "string" - ? `${this.terraformResourceType}.${resource.friendlyUniqueId}["${index}"]` - : `${this.terraformResourceType}.${resource.friendlyUniqueId}[${index}]` - : `${this.terraformResourceType}.${resource.friendlyUniqueId}`; + ? `${this.terraformResourceType}.${moveToFriendlyUniqueId.friendlyUniqueId}["${index}"]` + : `${this.terraformResourceType}.${moveToFriendlyUniqueId.friendlyUniqueId}[${index}]` + : `${this.terraformResourceType}.${moveToFriendlyUniqueId.friendlyUniqueId}`; const movedFromId = `${this.terraformResourceType}.${this.friendlyUniqueId}`; this._moved = { to: movedToId, from: movedFromId }; // TODO: add validation of correct Terraform Version @@ -301,26 +308,7 @@ export class TerraformResource public addTag(tag: string) { // get parent stack address map - const stackMoveAddresses = ( - this._scope.node.root.node.children[0] as unknown as TerraformStack - ).moveAddresses; + const stackMoveAddresses = TerraformMoveAddresses.addresses(this._scope); stackMoveAddresses.add(this, tag); } - /** - public moveFrom(resource: TerraformResource, index?: string | number) { - const movedFromId = index - ? typeof index === "string" - ? (`${this.terraformResourceType}.${resource.friendlyUniqueId}["${index}"]`) - : (`${this.terraformResourceType}.${resource.friendlyUniqueId}[${index}]`) - : `${this.terraformResourceType}.${resource.friendlyUniqueId}` - const movedToId = `${this.terraformResourceType}.${this.friendlyUniqueId}` - this._moved = { to: movedToId, from: movedFromId } - // TODO: add validation of correct Terraform Version - } -*/ - /** - public hasMoved() { - this._hasMoved = true; - } - */ } From 44457b441d2f55987b80d68ed455cb1e5ae6d120 Mon Sep 17 00:00:00 2001 From: Mark DeCrane Date: Fri, 13 Oct 2023 09:23:43 -0400 Subject: [PATCH 04/23] chore: addition of examples, and better naming --- examples/typescript/aws-move/.gitignore | 11 + .../aws-move/__tests__/main-test.ts | 89 + examples/typescript/aws-move/cdktf.json | 10 + .../construct-to-move-to.ts | 10 + .../nested-construct-to-move-to.ts | 13 + examples/typescript/aws-move/help | 51 + examples/typescript/aws-move/jest.config.js | 187 + examples/typescript/aws-move/main.ts | 286 + .../typescript/aws-move/package-lock.json | 7707 +++++++++++++++++ examples/typescript/aws-move/package.json | 35 + examples/typescript/aws-move/setup.js | 2 + .../cdktf/lib/terraform-move-addresses.ts | 44 +- packages/cdktf/lib/terraform-resource.ts | 24 +- packages/cdktf/lib/terraform-stack.ts | 5 +- 14 files changed, 8449 insertions(+), 25 deletions(-) create mode 100644 examples/typescript/aws-move/.gitignore create mode 100644 examples/typescript/aws-move/__tests__/main-test.ts create mode 100644 examples/typescript/aws-move/cdktf.json create mode 100644 examples/typescript/aws-move/constructs-to-move-to/construct-to-move-to.ts create mode 100644 examples/typescript/aws-move/constructs-to-move-to/nested-construct-to-move-to.ts create mode 100644 examples/typescript/aws-move/help create mode 100644 examples/typescript/aws-move/jest.config.js create mode 100644 examples/typescript/aws-move/main.ts create mode 100644 examples/typescript/aws-move/package-lock.json create mode 100644 examples/typescript/aws-move/package.json create mode 100644 examples/typescript/aws-move/setup.js diff --git a/examples/typescript/aws-move/.gitignore b/examples/typescript/aws-move/.gitignore new file mode 100644 index 0000000000..1dfae30c78 --- /dev/null +++ b/examples/typescript/aws-move/.gitignore @@ -0,0 +1,11 @@ +*.d.ts +*.js +node_modules +cdktf.out +cdktf.log +*terraform.*.tfstate* +.gen +.terraform +tsconfig.tsbuildinfo +!jest.config.js +!setup.js \ No newline at end of file diff --git a/examples/typescript/aws-move/__tests__/main-test.ts b/examples/typescript/aws-move/__tests__/main-test.ts new file mode 100644 index 0000000000..5498de8539 --- /dev/null +++ b/examples/typescript/aws-move/__tests__/main-test.ts @@ -0,0 +1,89 @@ +// Copyright (c) HashiCorp, Inc +// SPDX-License-Identifier: MPL-2.0 +import "cdktf/lib/testing/adapters/jest"; // Load types for expect matchers +// import { Testing } from "cdktf"; + +describe("My CDKTF Application", () => { + // The tests below are example tests, you can find more information at + // https://cdk.tf/testing + it.todo("should be tested"); + + // // All Unit tests test the synthesised terraform code, it does not create real-world resources + // describe("Unit testing using assertions", () => { + // it("should contain a resource", () => { + // // import { Image,Container } from "./.gen/providers/docker" + // expect( + // Testing.synthScope((scope) => { + // new MyApplicationsAbstraction(scope, "my-app", {}); + // }) + // ).toHaveResource(Container); + + // expect( + // Testing.synthScope((scope) => { + // new MyApplicationsAbstraction(scope, "my-app", {}); + // }) + // ).toHaveResourceWithProperties(Image, { name: "ubuntu:latest" }); + // }); + // }); + + // describe("Unit testing using snapshots", () => { + // it("Tests the snapshot", () => { + // const app = Testing.app(); + // const stack = new TerraformStack(app, "test"); + + // new TestProvider(stack, "provider", { + // accessKey: "1", + // }); + + // new TestResource(stack, "test", { + // name: "my-resource", + // }); + + // expect(Testing.synth(stack)).toMatchSnapshot(); + // }); + + // it("Tests a combination of resources", () => { + // expect( + // Testing.synthScope((stack) => { + // new TestDataSource(stack, "test-data-source", { + // name: "foo", + // }); + + // new TestResource(stack, "test-resource", { + // name: "bar", + // }); + // }) + // ).toMatchInlineSnapshot(); + // }); + // }); + + // describe("Checking validity", () => { + // it("check if the produced terraform configuration is valid", () => { + // const app = Testing.app(); + // const stack = new TerraformStack(app, "test"); + + // new TestDataSource(stack, "test-data-source", { + // name: "foo", + // }); + + // new TestResource(stack, "test-resource", { + // name: "bar", + // }); + // expect(Testing.fullSynth(app)).toBeValidTerraform(); + // }); + + // it("check if this can be planned", () => { + // const app = Testing.app(); + // const stack = new TerraformStack(app, "test"); + + // new TestDataSource(stack, "test-data-source", { + // name: "foo", + // }); + + // new TestResource(stack, "test-resource", { + // name: "bar", + // }); + // expect(Testing.fullSynth(app)).toPlanSuccessfully(); + // }); + // }); +}); diff --git a/examples/typescript/aws-move/cdktf.json b/examples/typescript/aws-move/cdktf.json new file mode 100644 index 0000000000..af3a9f5397 --- /dev/null +++ b/examples/typescript/aws-move/cdktf.json @@ -0,0 +1,10 @@ +{ + "language": "typescript", + "app": "npx ts-node main.ts", + "sendCrashReports": "false", + "terraformProviders": [ + "aws@~> 5.0" + ], + "terraformModules": [], + "context": {} +} \ No newline at end of file diff --git a/examples/typescript/aws-move/constructs-to-move-to/construct-to-move-to.ts b/examples/typescript/aws-move/constructs-to-move-to/construct-to-move-to.ts new file mode 100644 index 0000000000..fa3e818af3 --- /dev/null +++ b/examples/typescript/aws-move/constructs-to-move-to/construct-to-move-to.ts @@ -0,0 +1,10 @@ +import { Construct } from "constructs"; +import { NestedConstructToMoveTo } from "./nested-construct-to-move-to"; + +export class ConstructToMoveTo extends Construct { + constructor(scope: Construct, id: string) { + super(scope, id); + + new NestedConstructToMoveTo(this, "nested-construct"); + } +} diff --git a/examples/typescript/aws-move/constructs-to-move-to/nested-construct-to-move-to.ts b/examples/typescript/aws-move/constructs-to-move-to/nested-construct-to-move-to.ts new file mode 100644 index 0000000000..6532c34289 --- /dev/null +++ b/examples/typescript/aws-move/constructs-to-move-to/nested-construct-to-move-to.ts @@ -0,0 +1,13 @@ +import { Construct } from "constructs"; +import { S3Bucket } from "../.gen/providers/aws/s3-bucket"; +//import { TerraformMoveAddresses } from "cdktf"; + +export class NestedConstructToMoveTo extends Construct { + constructor(scope: Construct, id: string) { + super(scope, id); + + new S3Bucket(this, "test-bucket", { + bucket: "test-move-bucket-name-1", + }); //.move("move"); + } +} diff --git a/examples/typescript/aws-move/help b/examples/typescript/aws-move/help new file mode 100644 index 0000000000..62207a4f6a --- /dev/null +++ b/examples/typescript/aws-move/help @@ -0,0 +1,51 @@ +======================================================================================================== + + Your cdktf typescript project is ready! + + cat help Print this message + + Compile: + npm run get Import/update Terraform providers and modules (you should check-in this directory) + npm run compile Compile typescript code to javascript (or "npm run watch") + npm run watch Watch for changes and compile typescript in the background + npm run build Compile typescript + + Synthesize: + cdktf synth [stack] Synthesize Terraform resources from stacks to cdktf.out/ (ready for 'terraform apply') + + Diff: + cdktf diff [stack] Perform a diff (terraform plan) for the given stack + + Deploy: + cdktf deploy [stack] Deploy the given stack + + Destroy: + cdktf destroy [stack] Destroy the stack + + Test: + npm run test Runs unit tests (edit __tests__/main-test.ts to add your own tests) + npm run test:watch Watches the tests and reruns them on change + + Upgrades: + npm run upgrade Upgrade cdktf modules to latest version + npm run upgrade:next Upgrade cdktf modules to latest "@next" version (last commit) + + Use Providers: + + You can add prebuilt providers (if available) or locally generated ones using the add command: + + cdktf provider add "aws@~>3.0" null kreuzwerker/docker + + You can find all prebuilt providers on npm: https://www.npmjs.com/search?q=keywords:cdktf + You can also install these providers directly through npm: + + npm install @cdktf/provider-aws + npm install @cdktf/provider-google + npm install @cdktf/provider-azurerm + npm install @cdktf/provider-docker + npm install @cdktf/provider-github + npm install @cdktf/provider-null + + You can also build any module or provider locally. Learn more https://cdk.tf/modules-and-providers + +======================================================================================================== diff --git a/examples/typescript/aws-move/jest.config.js b/examples/typescript/aws-move/jest.config.js new file mode 100644 index 0000000000..a4052f1ab5 --- /dev/null +++ b/examples/typescript/aws-move/jest.config.js @@ -0,0 +1,187 @@ +/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */ +/* + * For a detailed explanation regarding each configuration property, visit: + * https://jestjs.io/docs/configuration + */ + +module.exports = { + + // All imported modules in your tests should be mocked automatically + // automock: false, + + // Stop running tests after `n` failures + // bail: 0, + + // The directory where Jest should store its cached dependency information + // cacheDirectory: "/private/var/folders/z_/v03l33d55fb57nrr3b1q03ch0000gq/T/jest_dz", + + // Automatically clear mock calls and instances between every test + clearMocks: true, + + // Indicates whether the coverage information should be collected while executing the test + // collectCoverage: false, + + // An array of glob patterns indicating a set of files for which coverage information should be collected + // collectCoverageFrom: undefined, + + // The directory where Jest should output its coverage files + // coverageDirectory: undefined, + + // An array of regexp pattern strings used to skip coverage collection + // coveragePathIgnorePatterns: [ + // "/node_modules/" + // ], + + // Indicates which provider should be used to instrument code for coverage + coverageProvider: "v8", + + // A list of reporter names that Jest uses when writing coverage reports + // coverageReporters: [ + // "json", + // "text", + // "lcov", + // "clover" + // ], + + // An object that configures minimum threshold enforcement for coverage results + // coverageThreshold: undefined, + + // A path to a custom dependency extractor + // dependencyExtractor: undefined, + + // Make calling deprecated APIs throw helpful error messages + // errorOnDeprecated: false, + + // Force coverage collection from ignored files using an array of glob patterns + // forceCoverageMatch: [], + + // A path to a module which exports an async function that is triggered once before all test suites + // globalSetup: undefined, + + // A path to a module which exports an async function that is triggered once after all test suites + // globalTeardown: undefined, + + // A set of global variables that need to be available in all test environments + // globals: {}, + + // The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers. + // maxWorkers: "50%", + + // An array of directory names to be searched recursively up from the requiring module's location + // moduleDirectories: [ + // "node_modules" + // ], + + // An array of file extensions your modules use + moduleFileExtensions: ["ts", "js", "json", "node"], + + // A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module + // moduleNameMapper: {}, + + // An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader + // modulePathIgnorePatterns: [], + + // Activates notifications for test results + // notify: false, + + // An enum that specifies notification mode. Requires { notify: true } + // notifyMode: "failure-change", + + // A preset that is used as a base for Jest's configuration + preset: "ts-jest", + + // Run tests from one or more projects + // projects: undefined, + + // Use this configuration option to add custom reporters to Jest + // reporters: undefined, + + // Automatically reset mock state between every test + // resetMocks: false, + + // Reset the module registry before running each individual test + // resetModules: false, + + // A path to a custom resolver + // resolver: undefined, + + // Automatically restore mock state between every test + // restoreMocks: false, + + // The root directory that Jest should scan for tests and modules within + // rootDir: undefined, + + // A list of paths to directories that Jest should use to search for files in + // roots: [ + // "" + // ], + + // Allows you to use a custom runner instead of Jest's default test runner + // runner: "jest-runner", + + // The paths to modules that run some code to configure or set up the testing environment before each test + // setupFiles: [], + + // A list of paths to modules that run some code to configure or set up the testing framework before each test + setupFilesAfterEnv: ["/setup.js"], + + // The number of seconds after which a test is considered as slow and reported as such in the results. + // slowTestThreshold: 5, + + // A list of paths to snapshot serializer modules Jest should use for snapshot testing + // snapshotSerializers: [], + + // The test environment that will be used for testing + testEnvironment: "node", + + // Options that will be passed to the testEnvironment + // testEnvironmentOptions: {}, + + // Adds a location field to test results + // testLocationInResults: false, + + // The glob patterns Jest uses to detect test files + testMatch: [ + "**/__tests__/**/*.ts", + "**/?(*.)+(spec|test).ts" + ], + + // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped + testPathIgnorePatterns: ["/node_modules/", ".d.ts", ".js"], + + // The regexp pattern or array of patterns that Jest uses to detect test files + // testRegex: [], + + // This option allows the use of a custom results processor + // testResultsProcessor: undefined, + + // This option allows use of a custom test runner + // testRunner: "jest-circus/runner", + + // This option sets the URL for the jsdom environment. It is reflected in properties such as location.href + // testURL: "http://localhost", + + // Setting this value to "fake" allows the use of fake timers for functions such as "setTimeout" + // timers: "real", + + // A map from regular expressions to paths to transformers + // transform: undefined, + + // An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation + // transformIgnorePatterns: [ + // "/node_modules/", + // "\\.pnp\\.[^\\/]+$" + // ], + + // An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them + // unmockedModulePathPatterns: undefined, + + // Indicates whether each individual test should be reported during the run + // verbose: undefined, + + // An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode + // watchPathIgnorePatterns: [], + + // Whether to use watchman for file crawling + // watchman: true, +}; diff --git a/examples/typescript/aws-move/main.ts b/examples/typescript/aws-move/main.ts new file mode 100644 index 0000000000..53b5627cb6 --- /dev/null +++ b/examples/typescript/aws-move/main.ts @@ -0,0 +1,286 @@ +import { Construct } from "constructs"; +//import { App, TerraformStack } from "cdktf"; +import { App, TerraformStack, TerraformIterator } from "cdktf"; +import { AwsProvider } from "./.gen/providers/aws/provider"; +import { S3Bucket } from "./.gen/providers/aws/s3-bucket"; + +// UN-NESTING RESOURCE -> resource currently in nested construct, want to move it to higher layer + +// FIRST -> deploy, then comment out +/** +export class UnNestingMoveStack extends TerraformStack { + constructor(scope: Construct, id: string) { + super(scope, id); + + new AwsProvider(this, "aws", { + region: "us-west-2", + }); + new UnNestingConstructToMoveTo(this, "construct-to-move-to"); + } +} + +export class UnNestingConstructToMoveTo extends Construct { + constructor(scope: Construct, id: string) { + super(scope, id); + + new UnNestingNestedConstructToMoveTo(this, "nested-construct"); + } +} + +export class UnNestingNestedConstructToMoveTo extends Construct { + constructor(scope: Construct, id: string) { + super(scope, id); + + new S3Bucket(this, "test-bucket-2", { + bucket: "test-move-bucket-name-1", + }); + } +} +*/ +// SECOND -> uncomment, then plan +export class UnNestingMoveStack extends TerraformStack { + constructor(scope: Construct, id: string) { + super(scope, id); + + new AwsProvider(this, "aws", { + region: "us-west-2", + }); + new S3Bucket(this, "test-bucket-1", { + bucket: "test-move-bucket-name-1", + }).addTag("move"); + console.log("hits tagging"); + new UnNestingConstructToMoveTo(this, "construct-to-move-to"); + /** + console.log("AT ROOT") + console.log("scope", scope) + */ + } +} + +export class UnNestingConstructToMoveTo extends Construct { + constructor(scope: Construct, id: string) { + super(scope, id); + /** + console.log("AT 1st NESTED CONSTRUCT") + console.log("scope", scope) + console.log("scope node", scope.node) +*/ + new UnNestingNestedConstructToMoveTo(this, "nested-construct"); + } +} + +export class UnNestingNestedConstructToMoveTo extends Construct { + constructor(scope: Construct, id: string) { + super(scope, id); + /** + console.log("AT 2nd NESTED CONSTRUCT") + console.log("this", this) + console.log("this", scope) + console.log("scope node", scope.node) + console.log("scope node scope node", scope.node.scope?.node) +*/ + + new S3Bucket(this, "test-bucket-2", { + bucket: "test-move-bucket-name-1", + }).moveTo("move"); + console.log("hits move"); + } +} +// UN-NESTING RESOURCE + +// NESTING RESOURCE -> resource currently at higher abstraction, want to move it into nested construct + +// FIRST -> deploy, then comment out +/** +export class NestingMoveStack extends TerraformStack { + constructor(scope: Construct, id: string) { + super(scope, id); + + new AwsProvider(this, "aws", { + region: "us-west-2", + }); + + new S3Bucket(this, "test-bucket-3", { + bucket: "test-move-bucket-name-3", + }); + + // TODO make new construct for this use case + new NestingConstructToMoveTo(this, "construct-to-move-to"); + } +} + +export class NestingConstructToMoveTo extends Construct { + constructor(scope: Construct, id: string) { + super(scope, id); + new NestingNestedConstructToMoveTo(this, "nested-construct"); + } +} + +export class NestingNestedConstructToMoveTo extends Construct { + constructor(scope: Construct, id: string) { + super(scope, id); + } +} +*/ +// SECOND -> uncomment, then plan +export class NestingMoveStack extends TerraformStack { + constructor(scope: Construct, id: string) { + super(scope, id); + + new AwsProvider(this, "aws", { + region: "us-west-2", + }); + + new S3Bucket(this, "test-bucket-3", { + bucket: "test-move-bucket-name-3", + }).moveTo("move"); // + + // TODO make new construct for this use case + new NestingConstructToMoveTo(this, "construct-to-move-to"); + } +} + +export class NestingConstructToMoveTo extends Construct { + constructor(scope: Construct, id: string) { + super(scope, id); + + new NestingNestedConstructToMoveTo(this, "nested-construct"); + } +} + +export class NestingNestedConstructToMoveTo extends Construct { + constructor(scope: Construct, id: string) { + super(scope, id); + + new S3Bucket(this, "test-bucket-3", { + bucket: "test-move-bucket-name-3", + }).addTag("move"); + } +} +// NESTING RESOURCE + +// MOVE INTO RESOURCE USING LIST ITERATOR + +// FIRST -> deploy, then comment out +/** +export class ListIteratorMoveStack extends TerraformStack { + constructor(scope: Construct, id: string) { + super(scope, id); + + new AwsProvider(this, "aws", { + region: "us-west-2", + }); + + new S3Bucket(this, "moved-bucket-list-iterator", { + bucket: "website-static-file-list-iterator-one", + }) + } +} +*/ +// SECOND -> uncomment, then plan +export class ListIteratorMoveStack extends TerraformStack { + constructor(scope: Construct, id: string) { + super(scope, id); + + new AwsProvider(this, "aws", { + region: "us-west-2", + }); + + const iterator = TerraformIterator.fromList([ + "website-static-file-list-iterator-one", + "website-static-file-list-iterator-two", + ]); + + new S3Bucket(this, "complex-iterator-bucket", { + forEach: iterator, + bucket: iterator.value, + }).addTag("moveToResourceWithListIterator"); + + new S3Bucket(this, "moved-bucket-complex-iterator", { + bucket: "website-static-file-list-iterator-one", + }).moveTo( + "moveToResourceWithListIterator", + "website-static-file-list-iterator-one" + ); + } +} +// MOVE INTO RESOURCE USING LIST ITERATOR + +// MOVE INTO RESOURCE USING COMPLEX ITERATOR + +// FIRST -> deploy, then comment out +/** +export class ComplexIteratorMoveStack extends TerraformStack { + constructor(scope: Construct, id: string) { + super(scope, id); + + new AwsProvider(this, "aws", { + region: "us-west-2", + }); + + new S3Bucket(this, "moved-bucket-complex-iterator", { + bucket: "website-static-file-complex-iterator", + tags: { app: "website" } + }) + } +} +*/ +// SECOND -> uncomment, then plan +export class ComplexIteratorMoveStack extends TerraformStack { + constructor(scope: Construct, id: string) { + super(scope, id); + + new AwsProvider(this, "aws", { + region: "us-west-2", + }); + + const complexIterator = TerraformIterator.fromMap({ + "website-static-file-complex-iterator": { + name: "website-static-file-complex-iterator", + tags: { app: "website" }, + }, + images: { name: "images", tags: { app: "image-converter" } }, + }); + + new S3Bucket(this, "complex-iterator-bucket", { + forEach: complexIterator, + bucket: complexIterator.getString("name"), + tags: complexIterator.getStringMap("tags"), + }).addTag("moveToResourceWithComplexIterator"); + + new S3Bucket(this, "moved-bucket-complex-iterator", { + bucket: "website-static-file-complex-iterator", + tags: { app: "website" }, + }).moveTo( + "moveToResourceWithComplexIterator", + "website-static-file-complex-iterator" + ); + } +} +// MOVE INTO RESOURCE USING COMPLEX ITERATOR + +// MOVE INTO RESOURCE USING COUNT +export class countMoveStack extends TerraformStack { + constructor(scope: Construct, id: string) { + super(scope, id); + + new AwsProvider(this, "aws", { + region: "us-west-2", + }); + + new S3Bucket(this, "test-bucket", { + bucket: "test-move-bucket-name-1", + }); //.addTag("move"); + + // TODO make new construct for this use case + //new ConstructToMoveTo(this, "construct-to-move-to"); + } +} +// MOVE INTO RESOURCE USING COUNT + +const app = new App(); +new UnNestingMoveStack(app, "un-nesting-move-stack"); +new NestingMoveStack(app, "nesting-move-stack"); +new ListIteratorMoveStack(app, "list-iterator-move-stack"); +new ComplexIteratorMoveStack(app, "complex-iterator-move-stack"); +app.synth(); diff --git a/examples/typescript/aws-move/package-lock.json b/examples/typescript/aws-move/package-lock.json new file mode 100644 index 0000000000..20f3493d0c --- /dev/null +++ b/examples/typescript/aws-move/package-lock.json @@ -0,0 +1,7707 @@ +{ + "name": "aws-move", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "aws-move", + "version": "1.0.0", + "license": "MPL-2.0", + "dependencies": { + "cdktf": "^0.17.3", + "constructs": "^10.2.70" + }, + "devDependencies": { + "@types/jest": "^29.5.5", + "@types/node": "^20.7.0", + "jest": "^29.7.0", + "ts-jest": "^29.1.1", + "ts-node": "^10.9.1", + "typescript": "^5.2.2" + }, + "engines": { + "node": ">=16.0" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/code-frame/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/code-frame/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/code-frame/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.20.tgz", + "integrity": "sha512-BQYjKbpXjoXwFW5jGqiizJQQT/aC7pFm9Ok1OWssonuguICi264lbgMzRp2ZMmRSlfkX6DsWDDcsrctK8Rwfiw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.0.tgz", + "integrity": "sha512-97z/ju/Jy1rZmDxybphrBuI+jtJjFVoz7Mr9yUQVVVi+DNZE333uFQeMOqcCIy1x3WYBIbWftUSLmbNXNT7qFQ==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helpers": "^7.23.0", + "@babel/parser": "^7.23.0", + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.0", + "@babel/types": "^7.23.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", + "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.23.0", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz", + "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.22.9", + "@babel/helper-validator-option": "^7.22.15", + "browserslist": "^4.21.9", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "dev": true, + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz", + "integrity": "sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz", + "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.23.1", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.1.tgz", + "integrity": "sha512-chNpneuK18yW5Oxsr+t553UZzzAs3aZnFm4bxhebsNTeshrC95yA7l5yl7GBAG+JG1rF0F7zzD2EixK9mWSDoA==", + "dev": true, + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.0", + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", + "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", + "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz", + "integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.0.tgz", + "integrity": "sha512-t/QaEvyIoIkwzpiZ7aoSKK8kObQYeF7T2v+dazAYCb8SXtp58zEVkWW7zAnju8FNKNdr4ScAOEDmMItbyOmEYw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", + "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dev": true, + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dev": true, + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dev": true, + "dependencies": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", + "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", + "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", + "dev": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true + }, + "node_modules/@types/babel__core": { + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.2.tgz", + "integrity": "sha512-pNpr1T1xLUc2l3xJKuPtsEky3ybxN3m4fJkknfIpTCTfIZCDW57oAg+EfCgIIp2rvCe0Wn++/FfodDS4YXxBwA==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.5", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.5.tgz", + "integrity": "sha512-h9yIuWbJKdOPLJTbmSpPzkF67e659PbQDba7ifWm5BJ8xTv+sDmS7rFmywkWOvXedGTivCdeGSIIX8WLcRTz8w==", + "dev": true, + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.2.tgz", + "integrity": "sha512-/AVzPICMhMOMYoSx9MoKpGDKdBRsIXMNByh1PXSZoa+v6ZoLa8xxtsT/uLQ/NJm0XVAWl/BvId4MlDeXJaeIZQ==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.2.tgz", + "integrity": "sha512-ojlGK1Hsfce93J0+kn3H5R73elidKUaZonirN33GSmgTUMpzI/MIFfSpF3haANe3G1bEBS9/9/QEqwTzwqFsKw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.7.tgz", + "integrity": "sha512-MhzcwU8aUygZroVwL2jeYk6JisJrPl/oov/gsgGCue9mkgl9wjGbzReYQClxiUgFDnib9FuHqTndccKeZKxTRw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "dev": true + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-gPQuzaPR5h/djlAv2apEG1HVOyj1IUs7GpfMZixU0/0KXT3pm64ylHuMUI1/Akh+sq/iikxg6Z2j+fcMDXaaTQ==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.2.tgz", + "integrity": "sha512-kv43F9eb3Lhj+lr/Hn6OcLCs/sSM8bt+fIaP11rCYngfV6NVjzWXJ17owQtDQTL9tQ8WSLUrGsSJ6rJz0F1w1A==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "29.5.5", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.5.tgz", + "integrity": "sha512-ebylz2hnsWR9mYvmBFbXJXr+33UPc4+ZdxyDXh5w0FlPBTfCVN3wPL+kuOiQt3xvrK419v7XWeAs+AeOksafXg==", + "dev": true, + "dependencies": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, + "node_modules/@types/node": { + "version": "20.7.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.7.0.tgz", + "integrity": "sha512-zI22/pJW2wUZOVyguFaUL1HABdmSVxpXrzIqkjsHmyUjNhPoWM1CKfvVuXfetHhIok4RY573cqS0mZ1SJEnoTg==", + "dev": true + }, + "node_modules/@types/stack-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", + "dev": true + }, + "node_modules/@types/yargs": { + "version": "17.0.25", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.25.tgz", + "integrity": "sha512-gy7iPgwnzNvxgAEi2bXOHWCVOG6f7xsprVJH4MjlAWeBmJ7vh/Y1kwMtUrs64ztf24zVIRCpr3n/z6gm9QIkgg==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.1", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.1.tgz", + "integrity": "sha512-axdPBuLuEJt0c4yI5OZssC19K2Mq1uKdrfZBzuxLvaztgqUtFYZUNw7lETExPYJR9jdEoIg4mb7RQKRQzOkeGQ==", + "dev": true + }, + "node_modules/acorn": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "dev": true, + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dev": true, + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.22.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.0.tgz", + "integrity": "sha512-v+Jcv64L2LbfTC6OnRcaxtqJNJuQAVhZKSJfR/6hn7lhnChUXl4amwVviqN1k411BB+3rRoKMitELRn1CojeRA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001539", + "electron-to-chromium": "^1.4.530", + "node-releases": "^2.0.13", + "update-browserslist-db": "^1.0.13" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "dependencies": { + "fast-json-stable-stringify": "2.x" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001540", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001540.tgz", + "integrity": "sha512-9JL38jscuTJBTcuETxm8QLsFr/F6v0CYYTEU6r5+qSM98P2Q0Hmu0eG1dTG5GBUmywU3UlcVOUSIJYY47rdFSw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/cdktf": { + "version": "0.17.3", + "resolved": "https://registry.npmjs.org/cdktf/-/cdktf-0.17.3.tgz", + "integrity": "sha512-bqAzuuYLc8sy0ZoKw/RnohS6SH6fwAhCsU31vxuEiwu0BVcCaExfjQVZx/iJgmF1TJqk/cu2fMCLUgT3PDAuhQ==", + "bundleDependencies": [ + "archiver", + "json-stable-stringify", + "semver" + ], + "dependencies": { + "archiver": "5.3.1", + "json-stable-stringify": "^1.0.2", + "semver": "^7.5.3" + }, + "peerDependencies": { + "constructs": "^10.0.25" + } + }, + "node_modules/cdktf/node_modules/archiver": { + "version": "5.3.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "archiver-utils": "^2.1.0", + "async": "^3.2.3", + "buffer-crc32": "^0.2.1", + "readable-stream": "^3.6.0", + "readdir-glob": "^1.0.0", + "tar-stream": "^2.2.0", + "zip-stream": "^4.1.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/cdktf/node_modules/archiver-utils": { + "version": "2.1.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "glob": "^7.1.4", + "graceful-fs": "^4.2.0", + "lazystream": "^1.0.0", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.union": "^4.6.0", + "normalize-path": "^3.0.0", + "readable-stream": "^2.0.0" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/cdktf/node_modules/archiver-utils/node_modules/readable-stream": { + "version": "2.3.7", + "inBundle": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/cdktf/node_modules/archiver-utils/node_modules/string_decoder": { + "version": "1.1.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/cdktf/node_modules/async": { + "version": "3.2.4", + "inBundle": true, + "license": "MIT" + }, + "node_modules/cdktf/node_modules/balanced-match": { + "version": "1.0.2", + "inBundle": true, + "license": "MIT" + }, + "node_modules/cdktf/node_modules/base64-js": { + "version": "1.5.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "inBundle": true, + "license": "MIT" + }, + "node_modules/cdktf/node_modules/bl": { + "version": "4.1.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/cdktf/node_modules/brace-expansion": { + "version": "2.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/cdktf/node_modules/buffer": { + "version": "5.7.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "inBundle": true, + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/cdktf/node_modules/buffer-crc32": { + "version": "0.2.13", + "inBundle": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/cdktf/node_modules/compress-commons": { + "version": "4.1.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "buffer-crc32": "^0.2.13", + "crc32-stream": "^4.0.2", + "normalize-path": "^3.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/cdktf/node_modules/concat-map": { + "version": "0.0.1", + "inBundle": true, + "license": "MIT" + }, + "node_modules/cdktf/node_modules/core-util-is": { + "version": "1.0.3", + "inBundle": true, + "license": "MIT" + }, + "node_modules/cdktf/node_modules/crc-32": { + "version": "1.2.2", + "inBundle": true, + "license": "Apache-2.0", + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/cdktf/node_modules/crc32-stream": { + "version": "4.0.2", + "inBundle": true, + "license": "MIT", + "dependencies": { + "crc-32": "^1.2.0", + "readable-stream": "^3.4.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/cdktf/node_modules/end-of-stream": { + "version": "1.4.4", + "inBundle": true, + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/cdktf/node_modules/fs-constants": { + "version": "1.0.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/cdktf/node_modules/fs.realpath": { + "version": "1.0.0", + "inBundle": true, + "license": "ISC" + }, + "node_modules/cdktf/node_modules/glob": { + "version": "7.2.3", + "inBundle": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/cdktf/node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.11", + "inBundle": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/cdktf/node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/cdktf/node_modules/graceful-fs": { + "version": "4.2.10", + "inBundle": true, + "license": "ISC" + }, + "node_modules/cdktf/node_modules/ieee754": { + "version": "1.2.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "inBundle": true, + "license": "BSD-3-Clause" + }, + "node_modules/cdktf/node_modules/inflight": { + "version": "1.0.6", + "inBundle": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/cdktf/node_modules/inherits": { + "version": "2.0.4", + "inBundle": true, + "license": "ISC" + }, + "node_modules/cdktf/node_modules/isarray": { + "version": "1.0.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/cdktf/node_modules/json-stable-stringify": { + "version": "1.0.2", + "inBundle": true, + "license": "MIT", + "dependencies": { + "jsonify": "^0.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/cdktf/node_modules/jsonify": { + "version": "0.0.1", + "inBundle": true, + "license": "Public Domain", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/cdktf/node_modules/lazystream": { + "version": "1.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "readable-stream": "^2.0.5" + }, + "engines": { + "node": ">= 0.6.3" + } + }, + "node_modules/cdktf/node_modules/lazystream/node_modules/readable-stream": { + "version": "2.3.7", + "inBundle": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/cdktf/node_modules/lazystream/node_modules/string_decoder": { + "version": "1.1.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/cdktf/node_modules/lodash.defaults": { + "version": "4.2.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/cdktf/node_modules/lodash.difference": { + "version": "4.5.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/cdktf/node_modules/lodash.flatten": { + "version": "4.4.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/cdktf/node_modules/lodash.isplainobject": { + "version": "4.0.6", + "inBundle": true, + "license": "MIT" + }, + "node_modules/cdktf/node_modules/lodash.union": { + "version": "4.6.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/cdktf/node_modules/lru-cache": { + "version": "6.0.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cdktf/node_modules/minimatch": { + "version": "5.1.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cdktf/node_modules/normalize-path": { + "version": "3.0.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cdktf/node_modules/once": { + "version": "1.4.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/cdktf/node_modules/path-is-absolute": { + "version": "1.0.1", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cdktf/node_modules/process-nextick-args": { + "version": "2.0.1", + "inBundle": true, + "license": "MIT" + }, + "node_modules/cdktf/node_modules/readable-stream": { + "version": "3.6.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/cdktf/node_modules/readdir-glob": { + "version": "1.1.2", + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "minimatch": "^5.1.0" + } + }, + "node_modules/cdktf/node_modules/safe-buffer": { + "version": "5.1.2", + "inBundle": true, + "license": "MIT" + }, + "node_modules/cdktf/node_modules/semver": { + "version": "7.5.3", + "inBundle": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cdktf/node_modules/string_decoder": { + "version": "1.3.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/cdktf/node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.2.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "inBundle": true, + "license": "MIT" + }, + "node_modules/cdktf/node_modules/tar-stream": { + "version": "2.2.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/cdktf/node_modules/util-deprecate": { + "version": "1.0.2", + "inBundle": true, + "license": "MIT" + }, + "node_modules/cdktf/node_modules/wrappy": { + "version": "1.0.2", + "inBundle": true, + "license": "ISC" + }, + "node_modules/cdktf/node_modules/yallist": { + "version": "4.0.0", + "inBundle": true, + "license": "ISC" + }, + "node_modules/cdktf/node_modules/zip-stream": { + "version": "4.1.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "archiver-utils": "^2.1.0", + "compress-commons": "^4.1.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/ci-info": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", + "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", + "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", + "dev": true + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", + "dev": true + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/constructs": { + "version": "10.2.70", + "resolved": "https://registry.npmjs.org/constructs/-/constructs-10.2.70.tgz", + "integrity": "sha512-z6zr1E8K/9tzJbCQzY0UGX0/oVKPFKu9C/mzEnghCG6TAJINnvlq0CMKm63XqqeMleadZYm5T3sZGJKcxJS/Pg==", + "engines": { + "node": ">= 16.14.0" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/dedent": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", + "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", + "dev": true, + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.4.531", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.531.tgz", + "integrity": "sha512-H6gi5E41Rn3/mhKlPaT1aIMg/71hTAqn0gYEllSuw9igNWtvQwu185jiCZoZD29n7Zukgh7GVZ3zGf0XvkhqjQ==", + "dev": true + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dev": true, + "dependencies": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-core-module": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", + "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.0.tgz", + "integrity": "sha512-x58orMzEVfzPUKqlbLd1hXCnySCxKdDKa6Rjg97CwuLLRI4g3FHTdnExu1OqffVFay6zeMW+T6/DowFLndWnIw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", + "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", + "dev": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "dev": true, + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "dev": true, + "dependencies": { + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "dev": true, + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "dev": true, + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "dev": true, + "dependencies": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "dev": true, + "dependencies": { + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jest-snapshot/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jest-snapshot/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "dev": true, + "dependencies": { + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-dir/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true + }, + "node_modules/node-releases": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", + "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", + "dev": true + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-locate/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/pure-rand": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.3.tgz", + "integrity": "sha512-KddyFewCsO0j3+np81IQ+SweXLDnDQTs5s67BOnrYmYe/yNmUhttQyGsYzy8yUnoljGAQ9sl38YB4vH8ur7Y+w==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ] + }, + "node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.6", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.6.tgz", + "integrity": "sha512-njhxM7mV12JfufShqGy3Rz8j11RPdLy4xi15UurGJeoHLfJpVXKdh3ueuOqbYUcDZnffr6X739JBo5LzyahEsw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve.exports": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-jest": { + "version": "29.1.1", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz", + "integrity": "sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==", + "dev": true, + "dependencies": { + "bs-logger": "0.x", + "fast-json-stable-stringify": "2.x", + "jest-util": "^29.0.0", + "json5": "^2.2.3", + "lodash.memoize": "4.x", + "make-error": "1.x", + "semver": "^7.5.3", + "yargs-parser": "^21.0.1" + }, + "bin": { + "ts-jest": "cli.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/types": "^29.0.0", + "babel-jest": "^29.0.0", + "jest": "^29.0.0", + "typescript": ">=4.3 <6" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@jest/types": { + "optional": true + }, + "babel-jest": { + "optional": true + }, + "esbuild": { + "optional": true + } + } + }, + "node_modules/ts-jest/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ts-jest/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ts-jest/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", + "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, + "node_modules/v8-to-istanbul": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", + "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/v8-to-istanbul/node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "dev": true + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + }, + "dependencies": { + "@ampproject/remapping": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@babel/code-frame": { + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "dev": true, + "requires": { + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@babel/compat-data": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.20.tgz", + "integrity": "sha512-BQYjKbpXjoXwFW5jGqiizJQQT/aC7pFm9Ok1OWssonuguICi264lbgMzRp2ZMmRSlfkX6DsWDDcsrctK8Rwfiw==", + "dev": true + }, + "@babel/core": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.0.tgz", + "integrity": "sha512-97z/ju/Jy1rZmDxybphrBuI+jtJjFVoz7Mr9yUQVVVi+DNZE333uFQeMOqcCIy1x3WYBIbWftUSLmbNXNT7qFQ==", + "dev": true, + "requires": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helpers": "^7.23.0", + "@babel/parser": "^7.23.0", + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.0", + "@babel/types": "^7.23.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + } + }, + "@babel/generator": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", + "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", + "dev": true, + "requires": { + "@babel/types": "^7.23.0", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz", + "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.22.9", + "@babel/helper-validator-option": "^7.22.15", + "browserslist": "^4.21.9", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + } + }, + "@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "dev": true + }, + "@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "dev": true, + "requires": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-module-imports": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "dev": true, + "requires": { + "@babel/types": "^7.22.15" + } + }, + "@babel/helper-module-transforms": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz", + "integrity": "sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "dev": true + }, + "@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-string-parser": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "dev": true + }, + "@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "dev": true + }, + "@babel/helper-validator-option": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz", + "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==", + "dev": true + }, + "@babel/helpers": { + "version": "7.23.1", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.1.tgz", + "integrity": "sha512-chNpneuK18yW5Oxsr+t553UZzzAs3aZnFm4bxhebsNTeshrC95yA7l5yl7GBAG+JG1rF0F7zzD2EixK9mWSDoA==", + "dev": true, + "requires": { + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.0", + "@babel/types": "^7.23.0" + } + }, + "@babel/highlight": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@babel/parser": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", + "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", + "dev": true + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.12.13" + } + }, + "@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-jsx": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", + "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-typescript": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz", + "integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/template": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" + } + }, + "@babel/traverse": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.0.tgz", + "integrity": "sha512-t/QaEvyIoIkwzpiZ7aoSKK8kObQYeF7T2v+dazAYCb8SXtp58zEVkWW7zAnju8FNKNdr4ScAOEDmMItbyOmEYw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + } + }, + "@babel/types": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", + "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", + "dev": true, + "requires": { + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + } + }, + "@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, + "@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "dependencies": { + "@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + } + } + }, + "@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "requires": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + } + }, + "@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true + }, + "@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + } + }, + "@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dev": true, + "requires": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dev": true, + "requires": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + } + }, + "@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, + "requires": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + } + }, + "@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dev": true, + "requires": { + "jest-get-type": "^29.6.3" + } + }, + "@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + } + }, + "@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, + "requires": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + } + }, + "@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, + "requires": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + } + }, + "@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "requires": { + "@sinclair/typebox": "^0.27.8" + } + }, + "@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + } + }, + "@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dev": true, + "requires": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + } + }, + "@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dev": true, + "requires": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + } + }, + "@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, + "requires": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + } + }, + "@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "requires": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + } + }, + "@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "dev": true + }, + "@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", + "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "@sinonjs/commons": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", + "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", + "dev": true, + "requires": { + "type-detect": "4.0.8" + } + }, + "@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "requires": { + "@sinonjs/commons": "^3.0.0" + } + }, + "@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", + "dev": true + }, + "@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true + }, + "@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true + }, + "@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true + }, + "@types/babel__core": { + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.2.tgz", + "integrity": "sha512-pNpr1T1xLUc2l3xJKuPtsEky3ybxN3m4fJkknfIpTCTfIZCDW57oAg+EfCgIIp2rvCe0Wn++/FfodDS4YXxBwA==", + "dev": true, + "requires": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "@types/babel__generator": { + "version": "7.6.5", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.5.tgz", + "integrity": "sha512-h9yIuWbJKdOPLJTbmSpPzkF67e659PbQDba7ifWm5BJ8xTv+sDmS7rFmywkWOvXedGTivCdeGSIIX8WLcRTz8w==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@types/babel__template": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.2.tgz", + "integrity": "sha512-/AVzPICMhMOMYoSx9MoKpGDKdBRsIXMNByh1PXSZoa+v6ZoLa8xxtsT/uLQ/NJm0XVAWl/BvId4MlDeXJaeIZQ==", + "dev": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@types/babel__traverse": { + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.2.tgz", + "integrity": "sha512-ojlGK1Hsfce93J0+kn3H5R73elidKUaZonirN33GSmgTUMpzI/MIFfSpF3haANe3G1bEBS9/9/QEqwTzwqFsKw==", + "dev": true, + "requires": { + "@babel/types": "^7.20.7" + } + }, + "@types/graceful-fs": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.7.tgz", + "integrity": "sha512-MhzcwU8aUygZroVwL2jeYk6JisJrPl/oov/gsgGCue9mkgl9wjGbzReYQClxiUgFDnib9FuHqTndccKeZKxTRw==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/istanbul-lib-coverage": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "dev": true + }, + "@types/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-gPQuzaPR5h/djlAv2apEG1HVOyj1IUs7GpfMZixU0/0KXT3pm64ylHuMUI1/Akh+sq/iikxg6Z2j+fcMDXaaTQ==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "*" + } + }, + "@types/istanbul-reports": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.2.tgz", + "integrity": "sha512-kv43F9eb3Lhj+lr/Hn6OcLCs/sSM8bt+fIaP11rCYngfV6NVjzWXJ17owQtDQTL9tQ8WSLUrGsSJ6rJz0F1w1A==", + "dev": true, + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@types/jest": { + "version": "29.5.5", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.5.tgz", + "integrity": "sha512-ebylz2hnsWR9mYvmBFbXJXr+33UPc4+ZdxyDXh5w0FlPBTfCVN3wPL+kuOiQt3xvrK419v7XWeAs+AeOksafXg==", + "dev": true, + "requires": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, + "@types/node": { + "version": "20.7.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.7.0.tgz", + "integrity": "sha512-zI22/pJW2wUZOVyguFaUL1HABdmSVxpXrzIqkjsHmyUjNhPoWM1CKfvVuXfetHhIok4RY573cqS0mZ1SJEnoTg==", + "dev": true + }, + "@types/stack-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", + "dev": true + }, + "@types/yargs": { + "version": "17.0.25", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.25.tgz", + "integrity": "sha512-gy7iPgwnzNvxgAEi2bXOHWCVOG6f7xsprVJH4MjlAWeBmJ7vh/Y1kwMtUrs64ztf24zVIRCpr3n/z6gm9QIkgg==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "@types/yargs-parser": { + "version": "21.0.1", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.1.tgz", + "integrity": "sha512-axdPBuLuEJt0c4yI5OZssC19K2Mq1uKdrfZBzuxLvaztgqUtFYZUNw7lETExPYJR9jdEoIg4mb7RQKRQzOkeGQ==", + "dev": true + }, + "acorn": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "dev": true + }, + "acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true + }, + "ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "requires": { + "type-fest": "^0.21.3" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, + "requires": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + } + }, + "babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "dependencies": { + "istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "requires": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + } + } + } + }, + "babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, + "requires": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + } + }, + "babel-preset-current-node-syntax": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "dev": true, + "requires": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + } + }, + "babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dev": true, + "requires": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "browserslist": { + "version": "4.22.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.0.tgz", + "integrity": "sha512-v+Jcv64L2LbfTC6OnRcaxtqJNJuQAVhZKSJfR/6hn7lhnChUXl4amwVviqN1k411BB+3rRoKMitELRn1CojeRA==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001539", + "electron-to-chromium": "^1.4.530", + "node-releases": "^2.0.13", + "update-browserslist-db": "^1.0.13" + } + }, + "bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "requires": { + "fast-json-stable-stringify": "2.x" + } + }, + "bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "requires": { + "node-int64": "^0.4.0" + } + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "caniuse-lite": { + "version": "1.0.30001540", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001540.tgz", + "integrity": "sha512-9JL38jscuTJBTcuETxm8QLsFr/F6v0CYYTEU6r5+qSM98P2Q0Hmu0eG1dTG5GBUmywU3UlcVOUSIJYY47rdFSw==", + "dev": true + }, + "cdktf": { + "version": "0.17.3", + "resolved": "https://registry.npmjs.org/cdktf/-/cdktf-0.17.3.tgz", + "integrity": "sha512-bqAzuuYLc8sy0ZoKw/RnohS6SH6fwAhCsU31vxuEiwu0BVcCaExfjQVZx/iJgmF1TJqk/cu2fMCLUgT3PDAuhQ==", + "requires": { + "archiver": "5.3.1", + "json-stable-stringify": "^1.0.2", + "semver": "^7.5.3" + }, + "dependencies": { + "archiver": { + "version": "5.3.1", + "bundled": true, + "requires": { + "archiver-utils": "^2.1.0", + "async": "^3.2.3", + "buffer-crc32": "^0.2.1", + "readable-stream": "^3.6.0", + "readdir-glob": "^1.0.0", + "tar-stream": "^2.2.0", + "zip-stream": "^4.1.0" + } + }, + "archiver-utils": { + "version": "2.1.0", + "bundled": true, + "requires": { + "glob": "^7.1.4", + "graceful-fs": "^4.2.0", + "lazystream": "^1.0.0", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.union": "^4.6.0", + "normalize-path": "^3.0.0", + "readable-stream": "^2.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "bundled": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "async": { + "version": "3.2.4", + "bundled": true + }, + "balanced-match": { + "version": "1.0.2", + "bundled": true + }, + "base64-js": { + "version": "1.5.1", + "bundled": true + }, + "bl": { + "version": "4.1.0", + "bundled": true, + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "brace-expansion": { + "version": "2.0.1", + "bundled": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "buffer": { + "version": "5.7.1", + "bundled": true, + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "buffer-crc32": { + "version": "0.2.13", + "bundled": true + }, + "compress-commons": { + "version": "4.1.1", + "bundled": true, + "requires": { + "buffer-crc32": "^0.2.13", + "crc32-stream": "^4.0.2", + "normalize-path": "^3.0.0", + "readable-stream": "^3.6.0" + } + }, + "concat-map": { + "version": "0.0.1", + "bundled": true + }, + "core-util-is": { + "version": "1.0.3", + "bundled": true + }, + "crc-32": { + "version": "1.2.2", + "bundled": true + }, + "crc32-stream": { + "version": "4.0.2", + "bundled": true, + "requires": { + "crc-32": "^1.2.0", + "readable-stream": "^3.4.0" + } + }, + "end-of-stream": { + "version": "1.4.4", + "bundled": true, + "requires": { + "once": "^1.4.0" + } + }, + "fs-constants": { + "version": "1.0.0", + "bundled": true + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true + }, + "glob": { + "version": "7.2.3", + "bundled": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "dependencies": { + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "minimatch": { + "version": "3.1.2", + "bundled": true, + "requires": { + "brace-expansion": "^1.1.7" + } + } + } + }, + "graceful-fs": { + "version": "4.2.10", + "bundled": true + }, + "ieee754": { + "version": "1.2.1", + "bundled": true + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "bundled": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true + }, + "json-stable-stringify": { + "version": "1.0.2", + "bundled": true, + "requires": { + "jsonify": "^0.0.1" + } + }, + "jsonify": { + "version": "0.0.1", + "bundled": true + }, + "lazystream": { + "version": "1.0.1", + "bundled": true, + "requires": { + "readable-stream": "^2.0.5" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "bundled": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "lodash.defaults": { + "version": "4.2.0", + "bundled": true + }, + "lodash.difference": { + "version": "4.5.0", + "bundled": true + }, + "lodash.flatten": { + "version": "4.4.0", + "bundled": true + }, + "lodash.isplainobject": { + "version": "4.0.6", + "bundled": true + }, + "lodash.union": { + "version": "4.6.0", + "bundled": true + }, + "lru-cache": { + "version": "6.0.0", + "bundled": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "minimatch": { + "version": "5.1.0", + "bundled": true, + "requires": { + "brace-expansion": "^2.0.1" + } + }, + "normalize-path": { + "version": "3.0.0", + "bundled": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true + }, + "process-nextick-args": { + "version": "2.0.1", + "bundled": true + }, + "readable-stream": { + "version": "3.6.0", + "bundled": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "readdir-glob": { + "version": "1.1.2", + "bundled": true, + "requires": { + "minimatch": "^5.1.0" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true + }, + "semver": { + "version": "7.5.3", + "bundled": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "string_decoder": { + "version": "1.3.0", + "bundled": true, + "requires": { + "safe-buffer": "~5.2.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.1", + "bundled": true + } + } + }, + "tar-stream": { + "version": "2.2.0", + "bundled": true, + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true + }, + "wrappy": { + "version": "1.0.2", + "bundled": true + }, + "yallist": { + "version": "4.0.0", + "bundled": true + }, + "zip-stream": { + "version": "4.1.0", + "bundled": true, + "requires": { + "archiver-utils": "^2.1.0", + "compress-commons": "^4.1.0", + "readable-stream": "^3.6.0" + } + } + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true + }, + "ci-info": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", + "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", + "dev": true + }, + "cjs-module-lexer": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", + "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", + "dev": true + }, + "cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true + }, + "collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", + "dev": true + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "constructs": { + "version": "10.2.70", + "resolved": "https://registry.npmjs.org/constructs/-/constructs-10.2.70.tgz", + "integrity": "sha512-z6zr1E8K/9tzJbCQzY0UGX0/oVKPFKu9C/mzEnghCG6TAJINnvlq0CMKm63XqqeMleadZYm5T3sZGJKcxJS/Pg==" + }, + "convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + } + }, + "create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "dedent": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", + "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", + "dev": true, + "requires": {} + }, + "deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true + }, + "detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true + }, + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + }, + "diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true + }, + "electron-to-chromium": { + "version": "1.4.531", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.531.tgz", + "integrity": "sha512-H6gi5E41Rn3/mhKlPaT1aIMg/71hTAqn0gYEllSuw9igNWtvQwu185jiCZoZD29n7Zukgh7GVZ3zGf0XvkhqjQ==", + "dev": true + }, + "emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + } + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true + }, + "expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dev": true, + "requires": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "requires": { + "bser": "2.1.1" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "optional": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true + }, + "get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true + }, + "import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, + "requires": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "is-core-module": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", + "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.0.tgz", + "integrity": "sha512-x58orMzEVfzPUKqlbLd1hXCnySCxKdDKa6Rjg97CwuLLRI4g3FHTdnExu1OqffVFay6zeMW+T6/DowFLndWnIw==", + "dev": true, + "requires": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + } + }, + "istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + } + }, + "istanbul-reports": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", + "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", + "dev": true, + "requires": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + } + }, + "jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "dev": true, + "requires": { + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + } + }, + "jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "dev": true, + "requires": { + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" + } + }, + "jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "dev": true, + "requires": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + } + }, + "jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "dev": true, + "requires": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + } + }, + "jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, + "requires": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + } + }, + "jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + } + }, + "jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "dev": true, + "requires": { + "detect-newline": "^3.0.0" + } + }, + "jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + } + }, + "jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "dev": true, + "requires": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + } + }, + "jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "dev": true + }, + "jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "fsevents": "^2.3.2", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + } + }, + "jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "dev": true, + "requires": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + } + }, + "jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + } + }, + "jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + } + }, + "jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + } + }, + "jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, + "requires": {} + }, + "jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "dev": true + }, + "jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + } + }, + "jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "dev": true, + "requires": { + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" + } + }, + "jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "dev": true, + "requires": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + } + }, + "jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dev": true, + "requires": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + } + }, + "jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "dev": true, + "requires": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "dependencies": { + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true + } + } + }, + "jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "dev": true, + "requires": { + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" + } + }, + "jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, + "requires": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "dependencies": { + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true + }, + "kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true + }, + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true + }, + "lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "requires": { + "semver": "^7.5.3" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "requires": { + "tmpl": "1.0.5" + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "requires": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true + }, + "node-releases": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", + "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", + "dev": true + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + }, + "dependencies": { + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + } + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true + }, + "pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + } + }, + "pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "requires": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true + } + } + }, + "prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "requires": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + } + }, + "pure-rand": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.3.tgz", + "integrity": "sha512-KddyFewCsO0j3+np81IQ+SweXLDnDQTs5s67BOnrYmYe/yNmUhttQyGsYzy8yUnoljGAQ9sl38YB4vH8ur7Y+w==", + "dev": true + }, + "react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true + }, + "resolve": { + "version": "1.22.6", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.6.tgz", + "integrity": "sha512-njhxM7mV12JfufShqGy3Rz8j11RPdLy4xi15UurGJeoHLfJpVXKdh3ueuOqbYUcDZnffr6X739JBo5LzyahEsw==", + "dev": true, + "requires": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "requires": { + "resolve-from": "^5.0.0" + } + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + }, + "resolve.exports": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "dev": true + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "requires": { + "escape-string-regexp": "^2.0.0" + } + }, + "string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "requires": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + } + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true + }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true + }, + "test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "requires": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + } + }, + "tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "ts-jest": { + "version": "29.1.1", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz", + "integrity": "sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==", + "dev": true, + "requires": { + "bs-logger": "0.x", + "fast-json-stable-stringify": "2.x", + "jest-util": "^29.0.0", + "json5": "^2.2.3", + "lodash.memoize": "4.x", + "make-error": "1.x", + "semver": "^7.5.3", + "yargs-parser": "^21.0.1" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "dev": true, + "requires": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + } + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + }, + "type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true + }, + "typescript": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", + "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "dev": true + }, + "update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "dev": true, + "requires": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + } + }, + "v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, + "v8-to-istanbul": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", + "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0" + }, + "dependencies": { + "convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "dev": true + } + } + }, + "walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "requires": { + "makeerror": "1.0.12" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + } + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "requires": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + } + }, + "yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true + }, + "yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true + } + } +} diff --git a/examples/typescript/aws-move/package.json b/examples/typescript/aws-move/package.json new file mode 100644 index 0000000000..df92522716 --- /dev/null +++ b/examples/typescript/aws-move/package.json @@ -0,0 +1,35 @@ +{ + "//": "This example test is disabled via the 'private' attribute since Terraform 1.5 is required for proper synth, and as of writing CI has a lesser version", + "name": "@examples/typescript-aws-move", + "private": true, + "version": "1.0.0", + "main": "main.js", + "types": "main.ts", + "license": "MPL-2.0", + "scripts": { + "get": "cdktf get", + "build": "tsc", + "synth": "cdktf synth", + "compile": "tsc --pretty", + "watch": "tsc -w", + "test": "jest", + "test:watch": "jest --watch", + "upgrade": "npm i cdktf@latest cdktf-cli@latest", + "upgrade:next": "npm i cdktf@next cdktf-cli@next" + }, + "engines": { + "node": ">=16.0" + }, + "dependencies": { + "cdktf": "0.0.0", + "constructs": "^10.0.25" + }, + "devDependencies": { + "@types/jest": "27.5.2", + "@types/node": "16.18.23", + "cdktf-cli": "0.0.0", + "jest": "^27.5.1", + "ts-node": "^10.9.1", + "typescript": "^5.0.2" + } +} \ No newline at end of file diff --git a/examples/typescript/aws-move/setup.js b/examples/typescript/aws-move/setup.js new file mode 100644 index 0000000000..0b7e72f07b --- /dev/null +++ b/examples/typescript/aws-move/setup.js @@ -0,0 +1,2 @@ +const cdktf = require("cdktf"); +cdktf.Testing.setupJest(); diff --git a/packages/cdktf/lib/terraform-move-addresses.ts b/packages/cdktf/lib/terraform-move-addresses.ts index 10a2770ea6..e10f6cd50f 100644 --- a/packages/cdktf/lib/terraform-move-addresses.ts +++ b/packages/cdktf/lib/terraform-move-addresses.ts @@ -3,14 +3,15 @@ * SPDX-License-Identifier: MPL-2.0 */ -import { Construct } from "constructs"; +import { IConstruct } from "constructs"; import { TerraformResource } from "./terraform-resource"; import { TerraformStack } from "./terraform-stack"; +import { App } from "./app"; /** * */ -export class TerraformMoveAddresses { +export class TerraformResourceAddressMap { private _terraformAddressMap: Map = new Map< string, TerraformResource @@ -23,18 +24,45 @@ export class TerraformMoveAddresses { * function to return the specificed resource address at a certain tag */ - // Would trying to access this at a higher abstract lead to things not being present? since we only add stuff later on - public add(resource: TerraformResource, tag: string): void { this._terraformAddressMap.set(tag, resource); } - public getPath(tag: string): TerraformResource | undefined { + public getResourceAddress(tag: string): TerraformResource | undefined { return this._terraformAddressMap.get(tag); } - public static addresses(scope: Construct) { - return (scope.node.root.node.children[0] as unknown as TerraformStack) - .moveAddresses; // TODO: see if there is a better way of doing this, or if theres any problems with it; + public static parentStackAddressMap(scope: IConstruct) { + // SO, in a nested construct, the stack is accessable at scope.node.scope ACTUALLY NOT TRUE + // -- only thought that was the case as scope.node.scope just happened to be the stack + // But, if you are already at the root level it is undefined + // what if we keep trying to access the scope until it is undefined + + // if scope.scope === undefined we are at the stack level + + let currAbstractionLevel: IConstruct | undefined = scope; + let oneHigher: IConstruct | undefined = currAbstractionLevel.node.scope; + while (!App.isApp(oneHigher)) { + currAbstractionLevel = currAbstractionLevel?.node.scope; + oneHigher = currAbstractionLevel?.node.scope; + } + console.log("result", currAbstractionLevel); + const stackId = currAbstractionLevel?.node.id; + const children = scope.node.root.node.children; + let i = 0; + for (const child of children) { + if (child.node.id === stackId) { + break; + } else { + i = i + 1; + } + } + + console.log("result", scope.node.root.node.children[i]); + // AHHHH I give up, guess you can only do moves one stack at a time + return (scope.node.root.node.children[0] as TerraformStack) + .resourceAddresses; // TODO: see if there is a better way of doing this, or if theres any problems with it; + + // when scope.node.scope == undefined, we are at the app } } diff --git a/packages/cdktf/lib/terraform-resource.ts b/packages/cdktf/lib/terraform-resource.ts index 48f5695c08..7380448eab 100644 --- a/packages/cdktf/lib/terraform-resource.ts +++ b/packages/cdktf/lib/terraform-resource.ts @@ -23,7 +23,7 @@ import { RemoteExecProvisioner, } from "./terraform-provisioner"; import { ValidateTerraformVersion } from "./validations/validate-terraform-version"; -import { TerraformMoveAddresses } from "./terraform-move-addresses"; +import { TerraformResourceAddressMap } from "./terraform-move-addresses"; const TERRAFORM_RESOURCE_SYMBOL = Symbol.for("cdktf/TerraformResource"); @@ -282,19 +282,12 @@ export class TerraformResource ); } - public move(tag: string, index?: string | number) { - /** - if (resource === undefined) { - throw new Error("tag not set"); // TODO: make better error message - }*/ - /** - const stackMoveAddresses = ( - this._scope.node.root.node.children[0] as unknown as TerraformStack - ).moveAddresses;*/ - const stackMoveAddresses = TerraformMoveAddresses.addresses(this._scope); - const moveToFriendlyUniqueId = stackMoveAddresses.getPath(tag); + public moveTo(tag: string, index?: string | number) { + const stackMoveAddresses = + TerraformResourceAddressMap.parentStackAddressMap(this._scope); + const moveToFriendlyUniqueId = stackMoveAddresses.getResourceAddress(tag); if (!moveToFriendlyUniqueId) { - throw new Error("tag not set"); // TODO: make better error message + throw new Error("tag not set"); // TODO: make better error message, maybe add list of current tags, add note about making sure that you add the tag before a construct you are moving to is instantiated (and vice versa) } const movedToId = index // TODO: make it work with complex types too ? typeof index === "string" @@ -307,8 +300,9 @@ export class TerraformResource } public addTag(tag: string) { - // get parent stack address map - const stackMoveAddresses = TerraformMoveAddresses.addresses(this._scope); + console.log(this.terraformResourceType, this.friendlyUniqueId); + const stackMoveAddresses = + TerraformResourceAddressMap.parentStackAddressMap(this._scope); stackMoveAddresses.add(this, tag); } } diff --git a/packages/cdktf/lib/terraform-stack.ts b/packages/cdktf/lib/terraform-stack.ts index f7157ded89..19de802aeb 100644 --- a/packages/cdktf/lib/terraform-stack.ts +++ b/packages/cdktf/lib/terraform-stack.ts @@ -18,7 +18,7 @@ const STACK_SYMBOL = Symbol.for("cdktf/TerraformStack"); import { ValidateProviderPresence } from "./validations"; import { App } from "./app"; import { TerraformBackend } from "./terraform-backend"; -import { TerraformMoveAddresses } from "./terraform-move-addresses"; +import { TerraformResourceAddressMap } from "./terraform-move-addresses"; // eslint-disable-next-line @typescript-eslint/ban-types type StackIdentifier = string; @@ -63,7 +63,8 @@ export class TerraformStack extends Construct { {}; public synthesizer: IStackSynthesizer; public dependencies: TerraformStack[] = []; - public moveAddresses: TerraformMoveAddresses = new TerraformMoveAddresses(); + public resourceAddresses: TerraformResourceAddressMap = + new TerraformResourceAddressMap(); constructor(scope: Construct, id: string) { super(scope, id); From 3539b6319074b112998fbee334f0c97502b75fb7 Mon Sep 17 00:00:00 2001 From: "hashicorp-copywrite[bot]" <110428419+hashicorp-copywrite[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 17:39:20 +0000 Subject: [PATCH 05/23] chore: add required copyright headers Signed-off-by: hashicorp-copywrite[bot] <110428419+hashicorp-copywrite[bot]@users.noreply.github.com> --- .../aws-move/constructs-to-move-to/construct-to-move-to.ts | 5 +++++ .../constructs-to-move-to/nested-construct-to-move-to.ts | 5 +++++ examples/typescript/aws-move/jest.config.js | 5 +++++ examples/typescript/aws-move/main.ts | 5 +++++ examples/typescript/aws-move/setup.js | 5 +++++ 5 files changed, 25 insertions(+) diff --git a/examples/typescript/aws-move/constructs-to-move-to/construct-to-move-to.ts b/examples/typescript/aws-move/constructs-to-move-to/construct-to-move-to.ts index fa3e818af3..fddf840c61 100644 --- a/examples/typescript/aws-move/constructs-to-move-to/construct-to-move-to.ts +++ b/examples/typescript/aws-move/constructs-to-move-to/construct-to-move-to.ts @@ -1,3 +1,8 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: MPL-2.0 + */ + import { Construct } from "constructs"; import { NestedConstructToMoveTo } from "./nested-construct-to-move-to"; diff --git a/examples/typescript/aws-move/constructs-to-move-to/nested-construct-to-move-to.ts b/examples/typescript/aws-move/constructs-to-move-to/nested-construct-to-move-to.ts index 6532c34289..de87e05961 100644 --- a/examples/typescript/aws-move/constructs-to-move-to/nested-construct-to-move-to.ts +++ b/examples/typescript/aws-move/constructs-to-move-to/nested-construct-to-move-to.ts @@ -1,3 +1,8 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: MPL-2.0 + */ + import { Construct } from "constructs"; import { S3Bucket } from "../.gen/providers/aws/s3-bucket"; //import { TerraformMoveAddresses } from "cdktf"; diff --git a/examples/typescript/aws-move/jest.config.js b/examples/typescript/aws-move/jest.config.js index a4052f1ab5..65a1a44ee8 100644 --- a/examples/typescript/aws-move/jest.config.js +++ b/examples/typescript/aws-move/jest.config.js @@ -1,3 +1,8 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: MPL-2.0 + */ + /** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */ /* * For a detailed explanation regarding each configuration property, visit: diff --git a/examples/typescript/aws-move/main.ts b/examples/typescript/aws-move/main.ts index 53b5627cb6..4ea070a027 100644 --- a/examples/typescript/aws-move/main.ts +++ b/examples/typescript/aws-move/main.ts @@ -1,3 +1,8 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: MPL-2.0 + */ + import { Construct } from "constructs"; //import { App, TerraformStack } from "cdktf"; import { App, TerraformStack, TerraformIterator } from "cdktf"; diff --git a/examples/typescript/aws-move/setup.js b/examples/typescript/aws-move/setup.js index 0b7e72f07b..cabf53825f 100644 --- a/examples/typescript/aws-move/setup.js +++ b/examples/typescript/aws-move/setup.js @@ -1,2 +1,7 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: MPL-2.0 + */ + const cdktf = require("cdktf"); cdktf.Testing.setupJest(); From d77ca7d1798f7feae7316d0828b4fe4fc7348532 Mon Sep 17 00:00:00 2001 From: Mark DeCrane Date: Fri, 13 Oct 2023 09:24:48 -0400 Subject: [PATCH 06/23] feat: added support for multi-stack deploys with move, added renameResourceId function --- packages/cdktf/lib/terraform-element.ts | 10 ++- .../cdktf/lib/terraform-move-addresses.ts | 44 ------------- packages/cdktf/lib/terraform-resource.ts | 63 ++++++++++++++----- 3 files changed, 53 insertions(+), 64 deletions(-) diff --git a/packages/cdktf/lib/terraform-element.ts b/packages/cdktf/lib/terraform-element.ts index f96c3db407..3709e1ece9 100644 --- a/packages/cdktf/lib/terraform-element.ts +++ b/packages/cdktf/lib/terraform-element.ts @@ -76,12 +76,10 @@ export class TerraformElement extends Construct { private _friendlyUniqueId?: string; public get friendlyUniqueId() { - if (!this._friendlyUniqueId) { - if (this._logicalIdOverride) { - this._friendlyUniqueId = this._logicalIdOverride; - } else { - this._friendlyUniqueId = this.cdktfStack.getLogicalId(this); - } + if (this._logicalIdOverride) { + this._friendlyUniqueId = this._logicalIdOverride; + } else if (!this._friendlyUniqueId) { + this._friendlyUniqueId = this.cdktfStack.getLogicalId(this); } return this._friendlyUniqueId; } diff --git a/packages/cdktf/lib/terraform-move-addresses.ts b/packages/cdktf/lib/terraform-move-addresses.ts index e10f6cd50f..beac24c367 100644 --- a/packages/cdktf/lib/terraform-move-addresses.ts +++ b/packages/cdktf/lib/terraform-move-addresses.ts @@ -3,10 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -import { IConstruct } from "constructs"; import { TerraformResource } from "./terraform-resource"; -import { TerraformStack } from "./terraform-stack"; -import { App } from "./app"; /** * @@ -17,13 +14,6 @@ export class TerraformResourceAddressMap { TerraformResource >(); - // what do we need? - /** - * map for a tag -> resource path !!! - * function to add to the resource path at a tag - * function to return the specificed resource address at a certain tag - */ - public add(resource: TerraformResource, tag: string): void { this._terraformAddressMap.set(tag, resource); } @@ -31,38 +21,4 @@ export class TerraformResourceAddressMap { public getResourceAddress(tag: string): TerraformResource | undefined { return this._terraformAddressMap.get(tag); } - - public static parentStackAddressMap(scope: IConstruct) { - // SO, in a nested construct, the stack is accessable at scope.node.scope ACTUALLY NOT TRUE - // -- only thought that was the case as scope.node.scope just happened to be the stack - // But, if you are already at the root level it is undefined - // what if we keep trying to access the scope until it is undefined - - // if scope.scope === undefined we are at the stack level - - let currAbstractionLevel: IConstruct | undefined = scope; - let oneHigher: IConstruct | undefined = currAbstractionLevel.node.scope; - while (!App.isApp(oneHigher)) { - currAbstractionLevel = currAbstractionLevel?.node.scope; - oneHigher = currAbstractionLevel?.node.scope; - } - console.log("result", currAbstractionLevel); - const stackId = currAbstractionLevel?.node.id; - const children = scope.node.root.node.children; - let i = 0; - for (const child of children) { - if (child.node.id === stackId) { - break; - } else { - i = i + 1; - } - } - - console.log("result", scope.node.root.node.children[i]); - // AHHHH I give up, guess you can only do moves one stack at a time - return (scope.node.root.node.children[0] as TerraformStack) - .resourceAddresses; // TODO: see if there is a better way of doing this, or if theres any problems with it; - - // when scope.node.scope == undefined, we are at the app - } } diff --git a/packages/cdktf/lib/terraform-resource.ts b/packages/cdktf/lib/terraform-resource.ts index 7380448eab..1eadd5be5a 100644 --- a/packages/cdktf/lib/terraform-resource.ts +++ b/packages/cdktf/lib/terraform-resource.ts @@ -23,7 +23,7 @@ import { RemoteExecProvisioner, } from "./terraform-provisioner"; import { ValidateTerraformVersion } from "./validations/validate-terraform-version"; -import { TerraformResourceAddressMap } from "./terraform-move-addresses"; +import { TerraformStack } from "./terraform-stack"; const TERRAFORM_RESOURCE_SYMBOL = Symbol.for("cdktf/TerraformResource"); @@ -81,6 +81,7 @@ export interface TerraformResourceImport { export interface TerraformResourceMove { readonly from: string; readonly to: string; + readonly renamed: boolean; } // eslint-disable-next-line jsdoc/require-jsdoc @@ -227,13 +228,14 @@ export class TerraformResource }, ] : undefined, - resource: this._moved - ? undefined - : { - [this.terraformResourceType]: { - [this.friendlyUniqueId]: attributes, + resource: + this._moved && !this._moved.renamed + ? undefined + : { + [this.terraformResourceType]: { + [this.friendlyUniqueId]: attributes, + }, }, - }, moved: this._moved ? { to: this._moved.to, @@ -282,27 +284,60 @@ export class TerraformResource ); } + public parentStackAddressMap() { + return TerraformStack.of(this._scope).resourceAddresses; + } + + /** + * + * @param tag + * @param index + */ public moveTo(tag: string, index?: string | number) { - const stackMoveAddresses = - TerraformResourceAddressMap.parentStackAddressMap(this._scope); + const stackMoveAddresses = this.parentStackAddressMap(); const moveToFriendlyUniqueId = stackMoveAddresses.getResourceAddress(tag); if (!moveToFriendlyUniqueId) { throw new Error("tag not set"); // TODO: make better error message, maybe add list of current tags, add note about making sure that you add the tag before a construct you are moving to is instantiated (and vice versa) } - const movedToId = index // TODO: make it work with complex types too + const movedToId = index ? typeof index === "string" ? `${this.terraformResourceType}.${moveToFriendlyUniqueId.friendlyUniqueId}["${index}"]` : `${this.terraformResourceType}.${moveToFriendlyUniqueId.friendlyUniqueId}[${index}]` : `${this.terraformResourceType}.${moveToFriendlyUniqueId.friendlyUniqueId}`; const movedFromId = `${this.terraformResourceType}.${this.friendlyUniqueId}`; - this._moved = { to: movedToId, from: movedFromId }; + this._moved = { to: movedToId, from: movedFromId, renamed: false }; // TODO: add validation of correct Terraform Version } + /** + * + * @param tag + */ public addTag(tag: string) { - console.log(this.terraformResourceType, this.friendlyUniqueId); - const stackMoveAddresses = - TerraformResourceAddressMap.parentStackAddressMap(this._scope); + const stackMoveAddresses = this.parentStackAddressMap(); stackMoveAddresses.add(this, tag); } + + /** + * + * @param name + */ + public renameResourceId(name: string) { + const oldId = this.friendlyUniqueId; + const oldIdParts = oldId.split("."); + oldIdParts[oldIdParts.length - 1] = name; + + const intialValue = oldIdParts[0]; + oldIdParts.shift(); + const newId = oldIdParts.reduce( + (accum, curr) => accum + "." + curr, + intialValue + ); + this.overrideLogicalId(newId); + this._moved = { + to: `${this.terraformResourceType}.${newId}`, + from: `${this.terraformResourceType}.${oldId}`, + renamed: true, + }; + } } From 870b14fdae623e6c1cee9c6e769b638c9135e180 Mon Sep 17 00:00:00 2001 From: Mark DeCrane Date: Fri, 13 Oct 2023 09:25:41 -0400 Subject: [PATCH 07/23] chore: better naming, refactoring, error handling --- examples/typescript/aws-move/main.ts | 31 +++--------- packages/cdktf/lib/index.ts | 2 +- .../cdktf/lib/terraform-move-addresses.ts | 24 ---------- packages/cdktf/lib/terraform-resource-tags.ts | 47 +++++++++++++++++++ packages/cdktf/lib/terraform-resource.ts | 29 +++++------- packages/cdktf/lib/terraform-stack.ts | 5 +- 6 files changed, 68 insertions(+), 70 deletions(-) delete mode 100644 packages/cdktf/lib/terraform-move-addresses.ts create mode 100644 packages/cdktf/lib/terraform-resource-tags.ts diff --git a/examples/typescript/aws-move/main.ts b/examples/typescript/aws-move/main.ts index 4ea070a027..92c928e742 100644 --- a/examples/typescript/aws-move/main.ts +++ b/examples/typescript/aws-move/main.ts @@ -52,24 +52,14 @@ export class UnNestingMoveStack extends TerraformStack { }); new S3Bucket(this, "test-bucket-1", { bucket: "test-move-bucket-name-1", - }).addTag("move"); - console.log("hits tagging"); + }).addResourceTag("move"); new UnNestingConstructToMoveTo(this, "construct-to-move-to"); - /** - console.log("AT ROOT") - console.log("scope", scope) - */ } } export class UnNestingConstructToMoveTo extends Construct { constructor(scope: Construct, id: string) { super(scope, id); - /** - console.log("AT 1st NESTED CONSTRUCT") - console.log("scope", scope) - console.log("scope node", scope.node) -*/ new UnNestingNestedConstructToMoveTo(this, "nested-construct"); } } @@ -77,18 +67,10 @@ export class UnNestingConstructToMoveTo extends Construct { export class UnNestingNestedConstructToMoveTo extends Construct { constructor(scope: Construct, id: string) { super(scope, id); - /** - console.log("AT 2nd NESTED CONSTRUCT") - console.log("this", this) - console.log("this", scope) - console.log("scope node", scope.node) - console.log("scope node scope node", scope.node.scope?.node) -*/ new S3Bucket(this, "test-bucket-2", { bucket: "test-move-bucket-name-1", }).moveTo("move"); - console.log("hits move"); } } // UN-NESTING RESOURCE @@ -136,12 +118,11 @@ export class NestingMoveStack extends TerraformStack { region: "us-west-2", }); + new NestingConstructToMoveTo(this, "construct-to-move-to"); + new S3Bucket(this, "test-bucket-3", { bucket: "test-move-bucket-name-3", }).moveTo("move"); // - - // TODO make new construct for this use case - new NestingConstructToMoveTo(this, "construct-to-move-to"); } } @@ -159,7 +140,7 @@ export class NestingNestedConstructToMoveTo extends Construct { new S3Bucket(this, "test-bucket-3", { bucket: "test-move-bucket-name-3", - }).addTag("move"); + }).addResourceTag("move"); } } // NESTING RESOURCE @@ -199,7 +180,7 @@ export class ListIteratorMoveStack extends TerraformStack { new S3Bucket(this, "complex-iterator-bucket", { forEach: iterator, bucket: iterator.value, - }).addTag("moveToResourceWithListIterator"); + }).addResourceTag("moveToResourceWithListIterator"); new S3Bucket(this, "moved-bucket-complex-iterator", { bucket: "website-static-file-list-iterator-one", @@ -251,7 +232,7 @@ export class ComplexIteratorMoveStack extends TerraformStack { forEach: complexIterator, bucket: complexIterator.getString("name"), tags: complexIterator.getStringMap("tags"), - }).addTag("moveToResourceWithComplexIterator"); + }).addResourceTag("moveToResourceWithComplexIterator"); new S3Bucket(this, "moved-bucket-complex-iterator", { bucket: "website-static-file-complex-iterator", diff --git a/packages/cdktf/lib/index.ts b/packages/cdktf/lib/index.ts index 6bdd5a1dbf..a19cfd215a 100644 --- a/packages/cdktf/lib/index.ts +++ b/packages/cdktf/lib/index.ts @@ -38,7 +38,7 @@ export * from "./terraform-provisioner"; export * from "./terraform-conditions"; export * from "./terraform-count"; export * from "./importable-resource"; -export * from "./terraform-move-addresses"; +export * from "./terraform-resource-tags"; // required for JSII because Fn extends from it export * from "./functions/terraform-functions.generated"; diff --git a/packages/cdktf/lib/terraform-move-addresses.ts b/packages/cdktf/lib/terraform-move-addresses.ts deleted file mode 100644 index beac24c367..0000000000 --- a/packages/cdktf/lib/terraform-move-addresses.ts +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: MPL-2.0 - */ - -import { TerraformResource } from "./terraform-resource"; - -/** - * - */ -export class TerraformResourceAddressMap { - private _terraformAddressMap: Map = new Map< - string, - TerraformResource - >(); - - public add(resource: TerraformResource, tag: string): void { - this._terraformAddressMap.set(tag, resource); - } - - public getResourceAddress(tag: string): TerraformResource | undefined { - return this._terraformAddressMap.get(tag); - } -} diff --git a/packages/cdktf/lib/terraform-resource-tags.ts b/packages/cdktf/lib/terraform-resource-tags.ts new file mode 100644 index 0000000000..cce238d7b7 --- /dev/null +++ b/packages/cdktf/lib/terraform-resource-tags.ts @@ -0,0 +1,47 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: MPL-2.0 + */ + +import { TerraformResource } from "./terraform-resource"; + +/** + * + */ +export class TerraformResourceTags { + private _taggedResourceMap: Map = new Map< + string, + TerraformResource + >(); + + private prettyPrintEntries() { + return [...this._taggedResourceMap.entries()].reduce( + (accum, curr) => accum + "\n" + `${curr[0]}: ${curr[1]}`, + "" + ); + } + + public addResourceTag(resource: TerraformResource, tag: string): void { + if (this._taggedResourceMap.has(tag)) { + throw new Error( + `Tag "${tag}" has already been set at ${ + this._taggedResourceMap.get(tag)?.friendlyUniqueId + }` + ); + } + this._taggedResourceMap.set(tag, resource); + } + + public getResourceByTag(tag: string): TerraformResource { + const result = this._taggedResourceMap.get(tag); + if (!result) { + throw new Error(`Tag "${tag}" has not been set: + + Current Tag Entries:\n ${this.prettyPrintEntries()} + + Make sure the resource being moved to has been tagged before .movedTo() has been called + `); + } + return result; + } +} diff --git a/packages/cdktf/lib/terraform-resource.ts b/packages/cdktf/lib/terraform-resource.ts index 1eadd5be5a..206ab41c7c 100644 --- a/packages/cdktf/lib/terraform-resource.ts +++ b/packages/cdktf/lib/terraform-resource.ts @@ -105,7 +105,6 @@ export class TerraformResource >; private _imported?: TerraformResourceImport; private _moved?: TerraformResourceMove; - private _scope: Construct; constructor(scope: Construct, id: string, config: TerraformResourceConfig) { super(scope, id, config.terraformResourceType); @@ -124,7 +123,6 @@ export class TerraformResource this.forEach = config.forEach; this.provisioners = config.provisioners; this.connection = config.connection; - this._scope = scope; } public static isTerraformResource(x: any): x is TerraformResource { @@ -284,8 +282,8 @@ export class TerraformResource ); } - public parentStackAddressMap() { - return TerraformStack.of(this._scope).resourceAddresses; + private parentStackResourceAddressMap() { + return TerraformStack.of(this).resourceAddresses; } /** @@ -294,11 +292,8 @@ export class TerraformResource * @param index */ public moveTo(tag: string, index?: string | number) { - const stackMoveAddresses = this.parentStackAddressMap(); - const moveToFriendlyUniqueId = stackMoveAddresses.getResourceAddress(tag); - if (!moveToFriendlyUniqueId) { - throw new Error("tag not set"); // TODO: make better error message, maybe add list of current tags, add note about making sure that you add the tag before a construct you are moving to is instantiated (and vice versa) - } + const stackMoveAddresses = this.parentStackResourceAddressMap(); + const moveToFriendlyUniqueId = stackMoveAddresses.getResourceByTag(tag); const movedToId = index ? typeof index === "string" ? `${this.terraformResourceType}.${moveToFriendlyUniqueId.friendlyUniqueId}["${index}"]` @@ -313,9 +308,9 @@ export class TerraformResource * * @param tag */ - public addTag(tag: string) { - const stackMoveAddresses = this.parentStackAddressMap(); - stackMoveAddresses.add(this, tag); + public addResourceTag(tag: string) { + const stackMoveAddresses = this.parentStackResourceAddressMap(); + stackMoveAddresses.addResourceTag(this, tag); } /** @@ -324,12 +319,12 @@ export class TerraformResource */ public renameResourceId(name: string) { const oldId = this.friendlyUniqueId; - const oldIdParts = oldId.split("."); - oldIdParts[oldIdParts.length - 1] = name; + const idParts = oldId.split("."); + idParts[idParts.length - 1] = name; - const intialValue = oldIdParts[0]; - oldIdParts.shift(); - const newId = oldIdParts.reduce( + const intialValue = idParts[0]; + idParts.shift(); + const newId = idParts.reduce( (accum, curr) => accum + "." + curr, intialValue ); diff --git a/packages/cdktf/lib/terraform-stack.ts b/packages/cdktf/lib/terraform-stack.ts index 19de802aeb..93395de7f2 100644 --- a/packages/cdktf/lib/terraform-stack.ts +++ b/packages/cdktf/lib/terraform-stack.ts @@ -18,7 +18,7 @@ const STACK_SYMBOL = Symbol.for("cdktf/TerraformStack"); import { ValidateProviderPresence } from "./validations"; import { App } from "./app"; import { TerraformBackend } from "./terraform-backend"; -import { TerraformResourceAddressMap } from "./terraform-move-addresses"; +import { TerraformResourceTags } from "./terraform-resource-tags"; // eslint-disable-next-line @typescript-eslint/ban-types type StackIdentifier = string; @@ -63,8 +63,7 @@ export class TerraformStack extends Construct { {}; public synthesizer: IStackSynthesizer; public dependencies: TerraformStack[] = []; - public resourceAddresses: TerraformResourceAddressMap = - new TerraformResourceAddressMap(); + public resourceAddresses: TerraformResourceTags = new TerraformResourceTags(); constructor(scope: Construct, id: string) { super(scope, id); From c7c7c66ce60f9425d98dc83c8e3eb32aa236896b Mon Sep 17 00:00:00 2001 From: Mark DeCrane Date: Fri, 13 Oct 2023 09:27:52 -0400 Subject: [PATCH 08/23] chore: add unit testing for additions to TerraformResource --- packages/cdktf/lib/terraform-resource.ts | 8 +- packages/cdktf/lib/terraform-stack.ts | 2 +- .../test/__snapshots__/resource.test.ts.snap | 229 ++++++++++++++++++ packages/cdktf/test/resource.test.ts | 148 ++++++++++- 4 files changed, 381 insertions(+), 6 deletions(-) diff --git a/packages/cdktf/lib/terraform-resource.ts b/packages/cdktf/lib/terraform-resource.ts index 206ab41c7c..8cdbee6fe7 100644 --- a/packages/cdktf/lib/terraform-resource.ts +++ b/packages/cdktf/lib/terraform-resource.ts @@ -282,8 +282,8 @@ export class TerraformResource ); } - private parentStackResourceAddressMap() { - return TerraformStack.of(this).resourceAddresses; + private parentStackResourceTags() { + return TerraformStack.of(this).resourceTags; } /** @@ -292,7 +292,7 @@ export class TerraformResource * @param index */ public moveTo(tag: string, index?: string | number) { - const stackMoveAddresses = this.parentStackResourceAddressMap(); + const stackMoveAddresses = this.parentStackResourceTags(); const moveToFriendlyUniqueId = stackMoveAddresses.getResourceByTag(tag); const movedToId = index ? typeof index === "string" @@ -309,7 +309,7 @@ export class TerraformResource * @param tag */ public addResourceTag(tag: string) { - const stackMoveAddresses = this.parentStackResourceAddressMap(); + const stackMoveAddresses = this.parentStackResourceTags(); stackMoveAddresses.addResourceTag(this, tag); } diff --git a/packages/cdktf/lib/terraform-stack.ts b/packages/cdktf/lib/terraform-stack.ts index 93395de7f2..71802569a6 100644 --- a/packages/cdktf/lib/terraform-stack.ts +++ b/packages/cdktf/lib/terraform-stack.ts @@ -63,7 +63,7 @@ export class TerraformStack extends Construct { {}; public synthesizer: IStackSynthesizer; public dependencies: TerraformStack[] = []; - public resourceAddresses: TerraformResourceTags = new TerraformResourceTags(); + public resourceTags: TerraformResourceTags = new TerraformResourceTags(); constructor(scope: Construct, id: string) { super(scope, id); diff --git a/packages/cdktf/test/__snapshots__/resource.test.ts.snap b/packages/cdktf/test/__snapshots__/resource.test.ts.snap index 7a43ab856b..6aca146c67 100644 --- a/packages/cdktf/test/__snapshots__/resource.test.ts.snap +++ b/packages/cdktf/test/__snapshots__/resource.test.ts.snap @@ -222,6 +222,235 @@ exports[`minimal configuration 1`] = ` }" `; +exports[`moves resource to a lesser nesting from contained construct 1`] = ` +"{ + "moved": { + "from": "test_resource.construct_nested-construct_simple_2C3755B0", + "to": "test_resource.simple" + }, + "provider": { + "test": [ + { + } + ] + }, + "resource": { + "test_resource": { + "simple": { + "name": "foo", + "provisioner": [ + { + "local-exec": { + "command": "echo 'hello' > world.txt" + } + }, + { + "local-exec": { + "command": "echo 'hello' > world1.txt" + } + }, + { + "local-exec": { + "command": "echo 'hello' > world2.txt" + } + } + ] + } + } + }, + "terraform": { + "required_providers": { + "test": { + "version": "~> 2.0" + } + } + } +}" +`; + +exports[`moves resource to be in composition with foreach using complex iterator 1`] = ` +"{ + "moved": { + "from": "test_resource.simple", + "to": "test_resource.simple-foreach[\\"simple-foreach-one\\"]" + }, + "provider": { + "test": [ + { + } + ] + }, + "resource": { + "test_resource": { + "simple-foreach": { + "for_each": { + "simple-foreach-one": { + "name": "foo-one", + "tags": { + "tag1": "tag1" + } + }, + "simple-foreach-two": { + "name": "foo-two", + "tags": { + "tag2": "tag2" + } + } + }, + "name": "\${each.value.name}", + "tags": "\${each.value.tags}" + } + } + }, + "terraform": { + "required_providers": { + "test": { + "version": "~> 2.0" + } + } + } +}" +`; + +exports[`moves resource to be in composition with foreach using list iterator 1`] = ` +"{ + "moved": { + "from": "test_resource.simple", + "to": "test_resource.simple-foreach[\\"foo-one\\"]" + }, + "provider": { + "test": [ + { + } + ] + }, + "resource": { + "test_resource": { + "simple-foreach": { + "for_each": "\${toset([\\"foo-one\\", \\"foo-two\\"])}", + "name": "\${each.value}", + "provisioner": [ + { + "local-exec": { + "command": "echo 'hello' > world.txt" + } + }, + { + "local-exec": { + "command": "echo 'hello' > world1.txt" + } + }, + { + "local-exec": { + "command": "echo 'hello' > world2.txt" + } + } + ] + } + } + }, + "terraform": { + "required_providers": { + "test": { + "version": "~> 2.0" + } + } + } +}" +`; + +exports[`moves resource to greater nesting in contained construct 1`] = ` +"{ + "moved": { + "from": "test_resource.simple", + "to": "test_resource.construct_nested-construct_simple_2C3755B0" + }, + "provider": { + "test": [ + { + } + ] + }, + "resource": { + "test_resource": { + "construct_nested-construct_simple_2C3755B0": { + "name": "foo", + "provisioner": [ + { + "local-exec": { + "command": "echo 'hello' > world.txt" + } + }, + { + "local-exec": { + "command": "echo 'hello' > world1.txt" + } + }, + { + "local-exec": { + "command": "echo 'hello' > world2.txt" + } + } + ] + } + } + }, + "terraform": { + "required_providers": { + "test": { + "version": "~> 2.0" + } + } + } +}" +`; + +exports[`moves resource to resource with rename 1`] = ` +"{ + "moved": { + "from": "test_resource.simple", + "to": "test_resource.simple-rename" + }, + "provider": { + "test": [ + { + } + ] + }, + "resource": { + "test_resource": { + "simple-rename": { + "name": "foo", + "provisioner": [ + { + "local-exec": { + "command": "echo 'hello' > world.txt" + } + }, + { + "local-exec": { + "command": "echo 'hello' > world1.txt" + } + }, + { + "local-exec": { + "command": "echo 'hello' > world2.txt" + } + } + ] + } + } + }, + "terraform": { + "required_providers": { + "test": { + "version": "~> 2.0" + } + } + } +}" +`; + exports[`number[] attributes 1`] = ` "{ "output": { diff --git a/packages/cdktf/test/resource.test.ts b/packages/cdktf/test/resource.test.ts index 38d12c134d..feb7d1ef5b 100644 --- a/packages/cdktf/test/resource.test.ts +++ b/packages/cdktf/test/resource.test.ts @@ -1,9 +1,16 @@ // Copyright (c) HashiCorp, Inc // SPDX-License-Identifier: MPL-2.0 -import { Testing, TerraformStack, TerraformElement, Fn } from "../lib"; +import { + Testing, + TerraformStack, + TerraformElement, + Fn, + TerraformIterator, +} from "../lib"; import { TestProvider, TestResource, OtherTestResource } from "./helper"; import { TestDataSource } from "./helper/data-source"; import { TerraformOutput } from "../lib/terraform-output"; +import { Construct } from "constructs"; test("minimal configuration", () => { const app = Testing.app(); @@ -343,3 +350,142 @@ test("includes import block when import is present, provider given", () => { }).importFrom("testId", provider); expect(Testing.synth(stack)).toMatchSnapshot(); }); + +it("moves resource to greater nesting in contained construct", () => { + const app = Testing.app(); + const stack = new TerraformStack(app, "test"); + new TestProvider(stack, "provider", {}); + + const construct = new Construct(stack, "construct"); + const nestedContruct = new Construct(construct, "nested-construct"); + + new TestResource(nestedContruct, "simple", { + name: "foo", + provisioners: [ + { type: "local-exec", command: "echo 'hello' > world.txt" }, + { type: "local-exec", command: "echo 'hello' > world1.txt" }, + { type: "local-exec", command: "echo 'hello' > world2.txt" }, + ], + }).addResourceTag("test"); + + new TestResource(stack, "simple", { + name: "foo", + provisioners: [ + { type: "local-exec", command: "echo 'hello' > world.txt" }, + { type: "local-exec", command: "echo 'hello' > world1.txt" }, + { type: "local-exec", command: "echo 'hello' > world2.txt" }, + ], + }).moveTo("test"); + + expect(Testing.synth(stack)).toMatchSnapshot(); +}); + +it("moves resource to a lesser nesting from contained construct", () => { + const app = Testing.app(); + const stack = new TerraformStack(app, "test"); + new TestProvider(stack, "provider", {}); + + new TestResource(stack, "simple", { + name: "foo", + provisioners: [ + { type: "local-exec", command: "echo 'hello' > world.txt" }, + { type: "local-exec", command: "echo 'hello' > world1.txt" }, + { type: "local-exec", command: "echo 'hello' > world2.txt" }, + ], + }).addResourceTag("test"); + const construct = new Construct(stack, "construct"); + const nestedContruct = new Construct(construct, "nested-construct"); + + new TestResource(nestedContruct, "simple", { + name: "foo", + provisioners: [ + { type: "local-exec", command: "echo 'hello' > world.txt" }, + { type: "local-exec", command: "echo 'hello' > world1.txt" }, + { type: "local-exec", command: "echo 'hello' > world2.txt" }, + ], + }).moveTo("test"); + + expect(Testing.synth(stack)).toMatchSnapshot(); +}); + +it("moves resource to be in composition with foreach using list iterator", () => { + const app = Testing.app(); + const stack = new TerraformStack(app, "test"); + new TestProvider(stack, "provider", {}); + + const iterator = TerraformIterator.fromList(["foo-one", "foo-two"]); + + new TestResource(stack, "simple-foreach", { + forEach: iterator, + name: iterator.value, + provisioners: [ + { type: "local-exec", command: "echo 'hello' > world.txt" }, + { type: "local-exec", command: "echo 'hello' > world1.txt" }, + { type: "local-exec", command: "echo 'hello' > world2.txt" }, + ], + }).addResourceTag("test"); + + new TestResource(stack, "simple", { + name: "foo-one", + provisioners: [ + { type: "local-exec", command: "echo 'hello' > world.txt" }, + { type: "local-exec", command: "echo 'hello' > world1.txt" }, + { type: "local-exec", command: "echo 'hello' > world2.txt" }, + ], + }).moveTo("test", "foo-one"); + + expect(Testing.synth(stack)).toMatchSnapshot(); +}); + +it("moves resource to be in composition with foreach using complex iterator", () => { + const app = Testing.app(); + const stack = new TerraformStack(app, "test"); + new TestProvider(stack, "provider", {}); + + const complexIterator = TerraformIterator.fromMap({ + "simple-foreach-one": { + name: "foo-one", + tags: { + tag1: "tag1", + }, + }, + "simple-foreach-two": { + name: "foo-two", + tags: { + tag2: "tag2", + }, + }, + }); + + new TestResource(stack, "simple-foreach", { + forEach: complexIterator, + name: complexIterator.getString("name"), + tags: complexIterator.getMap("tags"), + }).addResourceTag("test"); + + new TestResource(stack, "simple", { + name: "foo-one", + tags: { + tag1: "tag1", + }, + }).moveTo("test", "simple-foreach-one"); + + expect(Testing.synth(stack)).toMatchSnapshot(); +}); + +it("moves resource to resource with rename", () => { + const app = Testing.app(); + const stack = new TerraformStack(app, "test"); + new TestProvider(stack, "provider", {}); + + new TestResource(stack, "simple", { + name: "foo", + provisioners: [ + { type: "local-exec", command: "echo 'hello' > world.txt" }, + { type: "local-exec", command: "echo 'hello' > world1.txt" }, + { type: "local-exec", command: "echo 'hello' > world2.txt" }, + ], + }).renameResourceId("simple-rename"); + + expect(Testing.synth(stack)).toMatchSnapshot(); +}); From 39442e0121e2b1e6fa91af312294fe5372bd7db0 Mon Sep 17 00:00:00 2001 From: Mark DeCrane Date: Fri, 13 Oct 2023 09:28:45 -0400 Subject: [PATCH 09/23] chore: changed naming conventions, added some more error handling --- packages/cdktf/lib/index.ts | 2 +- packages/cdktf/lib/terraform-resource-tags.ts | 47 ----------------- .../cdktf/lib/terraform-resource-targets.ts | 47 +++++++++++++++++ packages/cdktf/lib/terraform-resource.ts | 50 +++++++++++-------- packages/cdktf/lib/terraform-stack.ts | 4 +- packages/cdktf/test/resource.test.ts | 8 +-- 6 files changed, 82 insertions(+), 76 deletions(-) delete mode 100644 packages/cdktf/lib/terraform-resource-tags.ts create mode 100644 packages/cdktf/lib/terraform-resource-targets.ts diff --git a/packages/cdktf/lib/index.ts b/packages/cdktf/lib/index.ts index a19cfd215a..f038b48dc6 100644 --- a/packages/cdktf/lib/index.ts +++ b/packages/cdktf/lib/index.ts @@ -38,7 +38,7 @@ export * from "./terraform-provisioner"; export * from "./terraform-conditions"; export * from "./terraform-count"; export * from "./importable-resource"; -export * from "./terraform-resource-tags"; +export * from "./terraform-resource-targets"; // required for JSII because Fn extends from it export * from "./functions/terraform-functions.generated"; diff --git a/packages/cdktf/lib/terraform-resource-tags.ts b/packages/cdktf/lib/terraform-resource-tags.ts deleted file mode 100644 index cce238d7b7..0000000000 --- a/packages/cdktf/lib/terraform-resource-tags.ts +++ /dev/null @@ -1,47 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: MPL-2.0 - */ - -import { TerraformResource } from "./terraform-resource"; - -/** - * - */ -export class TerraformResourceTags { - private _taggedResourceMap: Map = new Map< - string, - TerraformResource - >(); - - private prettyPrintEntries() { - return [...this._taggedResourceMap.entries()].reduce( - (accum, curr) => accum + "\n" + `${curr[0]}: ${curr[1]}`, - "" - ); - } - - public addResourceTag(resource: TerraformResource, tag: string): void { - if (this._taggedResourceMap.has(tag)) { - throw new Error( - `Tag "${tag}" has already been set at ${ - this._taggedResourceMap.get(tag)?.friendlyUniqueId - }` - ); - } - this._taggedResourceMap.set(tag, resource); - } - - public getResourceByTag(tag: string): TerraformResource { - const result = this._taggedResourceMap.get(tag); - if (!result) { - throw new Error(`Tag "${tag}" has not been set: - - Current Tag Entries:\n ${this.prettyPrintEntries()} - - Make sure the resource being moved to has been tagged before .movedTo() has been called - `); - } - return result; - } -} diff --git a/packages/cdktf/lib/terraform-resource-targets.ts b/packages/cdktf/lib/terraform-resource-targets.ts new file mode 100644 index 0000000000..df62c69a08 --- /dev/null +++ b/packages/cdktf/lib/terraform-resource-targets.ts @@ -0,0 +1,47 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: MPL-2.0 + */ + +import { TerraformResource } from "./terraform-resource"; + +/** + * + */ +export class TerraformResourceTargets { + private _resourceTargetMap: Map = new Map< + string, + TerraformResource + >(); + + private prettyPrintEntries() { + return [...this._resourceTargetMap.entries()].reduce( + (accum, curr) => accum + "\n" + `${curr[0]}: ${curr[1].friendlyUniqueId}`, + "" + ); + } + + public addResourceTarget(resource: TerraformResource, target: string): void { + if (this._resourceTargetMap.has(target)) { + throw new Error( + `Tag "${target}" has already been set at ${ + this._resourceTargetMap.get(target)?.friendlyUniqueId + }` + ); + } + this._resourceTargetMap.set(target, resource); + } + + public getResourceAddressByTarget(target: string): TerraformResource { + const result = this._resourceTargetMap.get(target); + if (!result) { + throw new Error(`Tag "${target}" has not been set: + + Current Tag Entries:\n ${this.prettyPrintEntries()} + + Make sure the resource being moved to has been tagged before .movedTo() has been called + `); + } + return result; + } +} diff --git a/packages/cdktf/lib/terraform-resource.ts b/packages/cdktf/lib/terraform-resource.ts index 8cdbee6fe7..0f19872f9b 100644 --- a/packages/cdktf/lib/terraform-resource.ts +++ b/packages/cdktf/lib/terraform-resource.ts @@ -282,23 +282,29 @@ export class TerraformResource ); } - private parentStackResourceTags() { - return TerraformStack.of(this).resourceTags; + private parentStackResourceTargets() { + return TerraformStack.of(this).moveTargets; } /** * - * @param tag + * @param moveTarget * @param index */ - public moveTo(tag: string, index?: string | number) { - const stackMoveAddresses = this.parentStackResourceTags(); - const moveToFriendlyUniqueId = stackMoveAddresses.getResourceByTag(tag); + public moveTo(moveTarget: string, index?: string | number) { + const stackMoveTargets = this.parentStackResourceTargets(); + const resourceToMoveTo = + stackMoveTargets.getResourceAddressByTarget(moveTarget); + if (this.terraformResourceType !== resourceToMoveTo.terraformResourceType) { + throw new Error( + `The move target "${moveTarget}" corresponding to the resource of type ${resourceToMoveTo.terraformResourceType} to move to differs from resource being of type ${this.terraformResourceType} being moved from` + ); + } const movedToId = index ? typeof index === "string" - ? `${this.terraformResourceType}.${moveToFriendlyUniqueId.friendlyUniqueId}["${index}"]` - : `${this.terraformResourceType}.${moveToFriendlyUniqueId.friendlyUniqueId}[${index}]` - : `${this.terraformResourceType}.${moveToFriendlyUniqueId.friendlyUniqueId}`; + ? `${this.terraformResourceType}.${resourceToMoveTo.friendlyUniqueId}["${index}"]` + : `${this.terraformResourceType}.${resourceToMoveTo.friendlyUniqueId}[${index}]` + : `${this.terraformResourceType}.${resourceToMoveTo.friendlyUniqueId}`; const movedFromId = `${this.terraformResourceType}.${this.friendlyUniqueId}`; this._moved = { to: movedToId, from: movedFromId, renamed: false }; // TODO: add validation of correct Terraform Version @@ -306,32 +312,32 @@ export class TerraformResource /** * - * @param tag + * @param moveTarget */ - public addResourceTag(tag: string) { - const stackMoveAddresses = this.parentStackResourceTags(); - stackMoveAddresses.addResourceTag(this, tag); + public addMoveTarget(moveTarget: string) { + const stackMoveTargets = this.parentStackResourceTargets(); + stackMoveTargets.addResourceTarget(this, moveTarget); } /** * - * @param name + * @param newId */ - public renameResourceId(name: string) { - const oldId = this.friendlyUniqueId; - const idParts = oldId.split("."); - idParts[idParts.length - 1] = name; + public renameResourceId(newId: string) { + const oldUniqueId = this.friendlyUniqueId; + const idParts = oldUniqueId.split("."); + idParts[idParts.length - 1] = newId; const intialValue = idParts[0]; idParts.shift(); - const newId = idParts.reduce( + const newUniqueId = idParts.reduce( (accum, curr) => accum + "." + curr, intialValue ); - this.overrideLogicalId(newId); + this.overrideLogicalId(newUniqueId); this._moved = { - to: `${this.terraformResourceType}.${newId}`, - from: `${this.terraformResourceType}.${oldId}`, + to: `${this.terraformResourceType}.${newUniqueId}`, + from: `${this.terraformResourceType}.${oldUniqueId}`, renamed: true, }; } diff --git a/packages/cdktf/lib/terraform-stack.ts b/packages/cdktf/lib/terraform-stack.ts index 71802569a6..26859cc807 100644 --- a/packages/cdktf/lib/terraform-stack.ts +++ b/packages/cdktf/lib/terraform-stack.ts @@ -18,7 +18,7 @@ const STACK_SYMBOL = Symbol.for("cdktf/TerraformStack"); import { ValidateProviderPresence } from "./validations"; import { App } from "./app"; import { TerraformBackend } from "./terraform-backend"; -import { TerraformResourceTags } from "./terraform-resource-tags"; +import { TerraformResourceTargets } from "./terraform-resource-targets"; // eslint-disable-next-line @typescript-eslint/ban-types type StackIdentifier = string; @@ -63,7 +63,7 @@ export class TerraformStack extends Construct { {}; public synthesizer: IStackSynthesizer; public dependencies: TerraformStack[] = []; - public resourceTags: TerraformResourceTags = new TerraformResourceTags(); + public moveTargets: TerraformResourceTargets = new TerraformResourceTargets(); constructor(scope: Construct, id: string) { super(scope, id); diff --git a/packages/cdktf/test/resource.test.ts b/packages/cdktf/test/resource.test.ts index feb7d1ef5b..c758d54325 100644 --- a/packages/cdktf/test/resource.test.ts +++ b/packages/cdktf/test/resource.test.ts @@ -366,7 +366,7 @@ it("moves resource to greater nesting in contained construct", () => { { type: "local-exec", command: "echo 'hello' > world1.txt" }, { type: "local-exec", command: "echo 'hello' > world2.txt" }, ], - }).addResourceTag("test"); + }).addMoveTarget("test"); new TestResource(stack, "simple", { name: "foo", @@ -392,7 +392,7 @@ it("moves resource to a lesser nesting from contained construct", () => { { type: "local-exec", command: "echo 'hello' > world1.txt" }, { type: "local-exec", command: "echo 'hello' > world2.txt" }, ], - }).addResourceTag("test"); + }).addMoveTarget("test"); const construct = new Construct(stack, "construct"); const nestedContruct = new Construct(construct, "nested-construct"); @@ -423,7 +423,7 @@ it("moves resource to be in composition with foreach using list iterator", () => { type: "local-exec", command: "echo 'hello' > world1.txt" }, { type: "local-exec", command: "echo 'hello' > world2.txt" }, ], - }).addResourceTag("test"); + }).addMoveTarget("test"); new TestResource(stack, "simple", { name: "foo-one", @@ -461,7 +461,7 @@ it("moves resource to be in composition with foreach using complex iterator", () forEach: complexIterator, name: complexIterator.getString("name"), tags: complexIterator.getMap("tags"), - }).addResourceTag("test"); + }).addMoveTarget("test"); new TestResource(stack, "simple", { name: "foo-one", From 1622fb07f00ec09e42a3ee1c14f19fccfa72499a Mon Sep 17 00:00:00 2001 From: Mark DeCrane Date: Wed, 4 Oct 2023 10:09:10 -0400 Subject: [PATCH 10/23] chore: add documentation and docstrings --- .../construct-to-move-to.ts | 15 ---- .../nested-construct-to-move-to.ts | 18 ----- examples/typescript/aws-move/main.ts | 37 +++++---- packages/cdktf/lib/terraform-resource.ts | 16 ++-- website/docs/cdktf/concepts/resources.mdx | 78 +++++++++++++++++++ 5 files changed, 110 insertions(+), 54 deletions(-) delete mode 100644 examples/typescript/aws-move/constructs-to-move-to/construct-to-move-to.ts delete mode 100644 examples/typescript/aws-move/constructs-to-move-to/nested-construct-to-move-to.ts diff --git a/examples/typescript/aws-move/constructs-to-move-to/construct-to-move-to.ts b/examples/typescript/aws-move/constructs-to-move-to/construct-to-move-to.ts deleted file mode 100644 index fddf840c61..0000000000 --- a/examples/typescript/aws-move/constructs-to-move-to/construct-to-move-to.ts +++ /dev/null @@ -1,15 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: MPL-2.0 - */ - -import { Construct } from "constructs"; -import { NestedConstructToMoveTo } from "./nested-construct-to-move-to"; - -export class ConstructToMoveTo extends Construct { - constructor(scope: Construct, id: string) { - super(scope, id); - - new NestedConstructToMoveTo(this, "nested-construct"); - } -} diff --git a/examples/typescript/aws-move/constructs-to-move-to/nested-construct-to-move-to.ts b/examples/typescript/aws-move/constructs-to-move-to/nested-construct-to-move-to.ts deleted file mode 100644 index de87e05961..0000000000 --- a/examples/typescript/aws-move/constructs-to-move-to/nested-construct-to-move-to.ts +++ /dev/null @@ -1,18 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: MPL-2.0 - */ - -import { Construct } from "constructs"; -import { S3Bucket } from "../.gen/providers/aws/s3-bucket"; -//import { TerraformMoveAddresses } from "cdktf"; - -export class NestedConstructToMoveTo extends Construct { - constructor(scope: Construct, id: string) { - super(scope, id); - - new S3Bucket(this, "test-bucket", { - bucket: "test-move-bucket-name-1", - }); //.move("move"); - } -} diff --git a/examples/typescript/aws-move/main.ts b/examples/typescript/aws-move/main.ts index 92c928e742..21850ef1fa 100644 --- a/examples/typescript/aws-move/main.ts +++ b/examples/typescript/aws-move/main.ts @@ -52,7 +52,7 @@ export class UnNestingMoveStack extends TerraformStack { }); new S3Bucket(this, "test-bucket-1", { bucket: "test-move-bucket-name-1", - }).addResourceTag("move"); + }).addMoveTarget("move"); new UnNestingConstructToMoveTo(this, "construct-to-move-to"); } } @@ -140,7 +140,7 @@ export class NestingNestedConstructToMoveTo extends Construct { new S3Bucket(this, "test-bucket-3", { bucket: "test-move-bucket-name-3", - }).addResourceTag("move"); + }).addMoveTarget("move"); } } // NESTING RESOURCE @@ -180,7 +180,7 @@ export class ListIteratorMoveStack extends TerraformStack { new S3Bucket(this, "complex-iterator-bucket", { forEach: iterator, bucket: iterator.value, - }).addResourceTag("moveToResourceWithListIterator"); + }).addMoveTarget("moveToResourceWithListIterator"); new S3Bucket(this, "moved-bucket-complex-iterator", { bucket: "website-static-file-list-iterator-one", @@ -221,8 +221,8 @@ export class ComplexIteratorMoveStack extends TerraformStack { }); const complexIterator = TerraformIterator.fromMap({ - "website-static-file-complex-iterator": { - name: "website-static-file-complex-iterator", + "website-static-files": { + name: "website-static-files", tags: { app: "website" }, }, images: { name: "images", tags: { app: "image-converter" } }, @@ -232,21 +232,18 @@ export class ComplexIteratorMoveStack extends TerraformStack { forEach: complexIterator, bucket: complexIterator.getString("name"), tags: complexIterator.getStringMap("tags"), - }).addResourceTag("moveToResourceWithComplexIterator"); + }).addMoveTarget("resourceWithComplexIterator"); - new S3Bucket(this, "moved-bucket-complex-iterator", { - bucket: "website-static-file-complex-iterator", + new S3Bucket(this, "moved-bucket", { + bucket: "website-static-files", tags: { app: "website" }, - }).moveTo( - "moveToResourceWithComplexIterator", - "website-static-file-complex-iterator" - ); + }).moveTo("resourceWithComplexIterator", "website-static-files"); } } // MOVE INTO RESOURCE USING COMPLEX ITERATOR // MOVE INTO RESOURCE USING COUNT -export class countMoveStack extends TerraformStack { +export class CountMoveStack extends TerraformStack { constructor(scope: Construct, id: string) { super(scope, id); @@ -264,6 +261,20 @@ export class countMoveStack extends TerraformStack { } // MOVE INTO RESOURCE USING COUNT +export class RenameResourceStack extends TerraformStack { + constructor(scope: Construct, id: string) { + super(scope, id); + + new AwsProvider(this, "aws", { + region: "us-west-2", + }); + + new S3Bucket(this, "test-bucket", { + bucket: "test-bucket-rename", + }).renameResourceId("test-bucket-rename"); + } +} + const app = new App(); new UnNestingMoveStack(app, "un-nesting-move-stack"); new NestingMoveStack(app, "nesting-move-stack"); diff --git a/packages/cdktf/lib/terraform-resource.ts b/packages/cdktf/lib/terraform-resource.ts index 0f19872f9b..85af008585 100644 --- a/packages/cdktf/lib/terraform-resource.ts +++ b/packages/cdktf/lib/terraform-resource.ts @@ -287,9 +287,9 @@ export class TerraformResource } /** - * - * @param moveTarget - * @param index + * Moves this resource to the location denoted by moveTarget. + * @param moveTarget The previously set string moveTarget denoting the location of the move + * @param index Optional The index corresponding to the key the resource is to appear in the foreach of a resource to move to */ public moveTo(moveTarget: string, index?: string | number) { const stackMoveTargets = this.parentStackResourceTargets(); @@ -297,7 +297,7 @@ export class TerraformResource stackMoveTargets.getResourceAddressByTarget(moveTarget); if (this.terraformResourceType !== resourceToMoveTo.terraformResourceType) { throw new Error( - `The move target "${moveTarget}" corresponding to the resource of type ${resourceToMoveTo.terraformResourceType} to move to differs from resource being of type ${this.terraformResourceType} being moved from` + `The move target "${moveTarget}" corresponding to the resource of type ${resourceToMoveTo.terraformResourceType} to move to differs from the resource of type ${this.terraformResourceType} being moved from` ); } const movedToId = index @@ -311,8 +311,8 @@ export class TerraformResource } /** - * - * @param moveTarget + * Adds a string moveTarget to this resource + * @param moveTarget The string move target that corresponds to the address of this resource */ public addMoveTarget(moveTarget: string) { const stackMoveTargets = this.parentStackResourceTargets(); @@ -320,8 +320,8 @@ export class TerraformResource } /** - * - * @param newId + * Renames the id of this resource to newId + * @param newId The new id to replace the current id */ public renameResourceId(newId: string) { const oldUniqueId = this.friendlyUniqueId; diff --git a/website/docs/cdktf/concepts/resources.mdx b/website/docs/cdktf/concepts/resources.mdx index 49ade20959..e00e41cb4e 100644 --- a/website/docs/cdktf/concepts/resources.mdx +++ b/website/docs/cdktf/concepts/resources.mdx @@ -370,6 +370,84 @@ import imports.kubernetes.namespace.NamespaceMetadata; +## Refactoring & Renaming Resources + +By default moving and/or renaming resource will be regarded with the intent to destroy the resource and re-create it. If such behavior must be avoided, but there is need to refactor your infrastructure definitions and/or rename resources in it, the function `moveTo` can serve your purpose. + +### Performing Resource Moves + +The function `moveTo` is present on all resources and takes a string `moveTarget` that denotes the location of the move. To set the `moveTarget`, use the function `addMoveTarget` that is present on the resource you desire to move to and provide its string target. + +Note that the `moveTarget` must be set prior to the call of `moveTo`. + +```ts +new S3Bucket(this, "test-bucket-move-to", { + bucket: "move-bucket-name", +}).addMoveTarget("move-s3"); + +new S3Bucket(this, "test-bucket-move-from", { + bucket: "move-bucket-name", +}).moveTo("move-s3"); +``` + +After deployment, both the resource being moved, and the move target on the resource being moved to can be removed. + +#### Move Targets + +A `moveTarget` is accessible anywhere in the context of the stack it is created. + +For instance, a `moveTarget` set at the root of the stack can be accessed within a nested construct. Conversely, a `moveTarget` set in a nested construct can be accessed at the root of the stack. + +Note that the `moveTarget` must be set prior to the call of `moveTo`. For example, in the instance where you are moving a resource into a nested construct, the nested construct must be instantiated prior to the call of `moveTo` on the resource being moved. + +```ts +// Contains resource with moveTarget "move" +new NestedConstructToMoveTo(this, "construct-to-move-to"); + +new S3Bucket(this, "test-bucket-1", { + bucket: "test-move-bucket-name-1", +}).moveTo("move"); +``` + +### Renaming a Resource + +To rename a resource, all that is needed is to call the `renameResourceId` function that is present on the resource. + +```ts +new S3Bucket(this, "bucket-id", { + bucket: "bucket-rename", +}).renameResourceId("bucket-new-id"); +``` + +Once the resource has been deployed, the original id can be changed to use the desired renamed resource id, and the call `renameResourceId` can be removed. + +### Enabling `foreach` on a Resource + +If you desire to move a deployed resource to be in composition of a resource using `foreach`, the index argument of `moveTo` can place the deployed resource in a `foreach` composition without its destruction. + +Here the index `website-static-files` is provided, corresponding to the key that appears in the TerraformIterator `iterator`. + +```ts +const iterator = TerraformIterator.fromMap({ + "website-static-files": { + name: "website-static-files", + tags: { app: "website" }, + }, + images: { name: "images", tags: { app: "image-converter" } }, +}); + +new S3Bucket(this, "iterator-bucket", { + forEach: iterator, + bucket: iterator.getString("name"), + tags: iterator.getStringMap("tags"), +}).addMoveTarget("resourceWithIterator"); + +new S3Bucket(this, "moved-bucket", { + bucket: "website-static-files", + tags: { app: "website" }, +}).moveTo("resourceWithIterator", "website-static-files"); +``` + ## Provisioners Provisioners can be used to model specific actions on the local machine or on a remote machine in order to prepare servers or other infrastructure objects for service. You can find more information on the concept of provisioners in the [Terraform docs](/terraform/language/resources/provisioners/syntax). You can pass the `provisioners` key to define a list of provisioners, connections can be configured with the `connection` key. A working example can be found at [examples/typescript/provisioner](https://github.com/hashicorp/terraform-cdk/blob/main/examples/typescript/provisioner/main.ts). From 388cdbfa52d4e5e32c1cb9793f77fd8c6b38e3a7 Mon Sep 17 00:00:00 2001 From: Mark DeCrane Date: Wed, 4 Oct 2023 14:50:01 -0400 Subject: [PATCH 11/23] chore: make unit testing more explicit --- .../test/__snapshots__/resource.test.ts.snap | 229 ------------------ packages/cdktf/test/resource.test.ts | 61 ++++- 2 files changed, 56 insertions(+), 234 deletions(-) diff --git a/packages/cdktf/test/__snapshots__/resource.test.ts.snap b/packages/cdktf/test/__snapshots__/resource.test.ts.snap index 6aca146c67..7a43ab856b 100644 --- a/packages/cdktf/test/__snapshots__/resource.test.ts.snap +++ b/packages/cdktf/test/__snapshots__/resource.test.ts.snap @@ -222,235 +222,6 @@ exports[`minimal configuration 1`] = ` }" `; -exports[`moves resource to a lesser nesting from contained construct 1`] = ` -"{ - "moved": { - "from": "test_resource.construct_nested-construct_simple_2C3755B0", - "to": "test_resource.simple" - }, - "provider": { - "test": [ - { - } - ] - }, - "resource": { - "test_resource": { - "simple": { - "name": "foo", - "provisioner": [ - { - "local-exec": { - "command": "echo 'hello' > world.txt" - } - }, - { - "local-exec": { - "command": "echo 'hello' > world1.txt" - } - }, - { - "local-exec": { - "command": "echo 'hello' > world2.txt" - } - } - ] - } - } - }, - "terraform": { - "required_providers": { - "test": { - "version": "~> 2.0" - } - } - } -}" -`; - -exports[`moves resource to be in composition with foreach using complex iterator 1`] = ` -"{ - "moved": { - "from": "test_resource.simple", - "to": "test_resource.simple-foreach[\\"simple-foreach-one\\"]" - }, - "provider": { - "test": [ - { - } - ] - }, - "resource": { - "test_resource": { - "simple-foreach": { - "for_each": { - "simple-foreach-one": { - "name": "foo-one", - "tags": { - "tag1": "tag1" - } - }, - "simple-foreach-two": { - "name": "foo-two", - "tags": { - "tag2": "tag2" - } - } - }, - "name": "\${each.value.name}", - "tags": "\${each.value.tags}" - } - } - }, - "terraform": { - "required_providers": { - "test": { - "version": "~> 2.0" - } - } - } -}" -`; - -exports[`moves resource to be in composition with foreach using list iterator 1`] = ` -"{ - "moved": { - "from": "test_resource.simple", - "to": "test_resource.simple-foreach[\\"foo-one\\"]" - }, - "provider": { - "test": [ - { - } - ] - }, - "resource": { - "test_resource": { - "simple-foreach": { - "for_each": "\${toset([\\"foo-one\\", \\"foo-two\\"])}", - "name": "\${each.value}", - "provisioner": [ - { - "local-exec": { - "command": "echo 'hello' > world.txt" - } - }, - { - "local-exec": { - "command": "echo 'hello' > world1.txt" - } - }, - { - "local-exec": { - "command": "echo 'hello' > world2.txt" - } - } - ] - } - } - }, - "terraform": { - "required_providers": { - "test": { - "version": "~> 2.0" - } - } - } -}" -`; - -exports[`moves resource to greater nesting in contained construct 1`] = ` -"{ - "moved": { - "from": "test_resource.simple", - "to": "test_resource.construct_nested-construct_simple_2C3755B0" - }, - "provider": { - "test": [ - { - } - ] - }, - "resource": { - "test_resource": { - "construct_nested-construct_simple_2C3755B0": { - "name": "foo", - "provisioner": [ - { - "local-exec": { - "command": "echo 'hello' > world.txt" - } - }, - { - "local-exec": { - "command": "echo 'hello' > world1.txt" - } - }, - { - "local-exec": { - "command": "echo 'hello' > world2.txt" - } - } - ] - } - } - }, - "terraform": { - "required_providers": { - "test": { - "version": "~> 2.0" - } - } - } -}" -`; - -exports[`moves resource to resource with rename 1`] = ` -"{ - "moved": { - "from": "test_resource.simple", - "to": "test_resource.simple-rename" - }, - "provider": { - "test": [ - { - } - ] - }, - "resource": { - "test_resource": { - "simple-rename": { - "name": "foo", - "provisioner": [ - { - "local-exec": { - "command": "echo 'hello' > world.txt" - } - }, - { - "local-exec": { - "command": "echo 'hello' > world1.txt" - } - }, - { - "local-exec": { - "command": "echo 'hello' > world2.txt" - } - } - ] - } - } - }, - "terraform": { - "required_providers": { - "test": { - "version": "~> 2.0" - } - } - } -}" -`; - exports[`number[] attributes 1`] = ` "{ "output": { diff --git a/packages/cdktf/test/resource.test.ts b/packages/cdktf/test/resource.test.ts index c758d54325..2514aae4cd 100644 --- a/packages/cdktf/test/resource.test.ts +++ b/packages/cdktf/test/resource.test.ts @@ -377,7 +377,18 @@ it("moves resource to greater nesting in contained construct", () => { ], }).moveTo("test"); - expect(Testing.synth(stack)).toMatchSnapshot(); + const synthedStack = JSON.parse(Testing.synth(stack)); + expect(synthedStack.moved.from).toEqual("test_resource.simple"); + expect(synthedStack.moved.to).toEqual( + "test_resource.construct_nested-construct_simple_2C3755B0" + ); + expect(Object.keys(synthedStack.resource.test_resource)).toContain( + "construct_nested-construct_simple_2C3755B0" + ); + // Must not include old resource being moved from + expect(Object.keys(synthedStack.resource.test_resource)).not.toContain( + "simple" + ); }); it("moves resource to a lesser nesting from contained construct", () => { @@ -405,7 +416,16 @@ it("moves resource to a lesser nesting from contained construct", () => { ], }).moveTo("test"); - expect(Testing.synth(stack)).toMatchSnapshot(); + const synthedStack = JSON.parse(Testing.synth(stack)); + expect(synthedStack.moved.from).toEqual( + "test_resource.construct_nested-construct_simple_2C3755B0" + ); + expect(synthedStack.moved.to).toEqual("test_resource.simple"); + expect(Object.keys(synthedStack.resource.test_resource)).toContain("simple"); + // Must not include old resource being moved from + expect(Object.keys(synthedStack.resource.test_resource)).not.toContain( + "construct_nested-construct_simple_2C3755B0" + ); }); it("moves resource to be in composition with foreach using list iterator", () => { @@ -434,7 +454,18 @@ it("moves resource to be in composition with foreach using list iterator", () => ], }).moveTo("test", "foo-one"); - expect(Testing.synth(stack)).toMatchSnapshot(); + const synthedStack = JSON.parse(Testing.synth(stack)); + expect(synthedStack.moved.from).toEqual("test_resource.simple"); + expect(synthedStack.moved.to).toEqual( + `test_resource.simple-foreach[\"foo-one\"]` + ); + expect(Object.keys(synthedStack.resource.test_resource)).toContain( + "simple-foreach" + ); + // Must not include old resource being moved from + expect(Object.keys(synthedStack.resource.test_resource)).not.toContain( + "simple" + ); }); it("moves resource to be in composition with foreach using complex iterator", () => { @@ -470,7 +501,18 @@ it("moves resource to be in composition with foreach using complex iterator", () }, }).moveTo("test", "simple-foreach-one"); - expect(Testing.synth(stack)).toMatchSnapshot(); + const synthedStack = JSON.parse(Testing.synth(stack)); + expect(synthedStack.moved.from).toEqual("test_resource.simple"); + expect(synthedStack.moved.to).toEqual( + `test_resource.simple-foreach[\"simple-foreach-one\"]` + ); + expect(Object.keys(synthedStack.resource.test_resource)).toContain( + "simple-foreach" + ); + // Must not include old resource being moved from + expect(Object.keys(synthedStack.resource.test_resource)).not.toContain( + "simple" + ); }); it("moves resource to resource with rename", () => { @@ -487,5 +529,14 @@ it("moves resource to resource with rename", () => { ], }).renameResourceId("simple-rename"); - expect(Testing.synth(stack)).toMatchSnapshot(); + const synthedStack = JSON.parse(Testing.synth(stack)); + expect(synthedStack.moved.from).toEqual("test_resource.simple"); + expect(synthedStack.moved.to).toEqual("test_resource.simple-rename"); + expect(Object.keys(synthedStack.resource.test_resource)).toContain( + "simple-rename" + ); + // Must not include old resource being moved from + expect(Object.keys(synthedStack.resource.test_resource)).not.toContain( + "simple" + ); }); From aaf719168086827af07ff7eb4b848dd4f8f5b0e5 Mon Sep 17 00:00:00 2001 From: Mark DeCrane Date: Thu, 5 Oct 2023 09:42:26 -0400 Subject: [PATCH 12/23] chore: add validations for proper terrafrom version --- packages/cdktf/lib/terraform-resource.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/cdktf/lib/terraform-resource.ts b/packages/cdktf/lib/terraform-resource.ts index 85af008585..70506c68b1 100644 --- a/packages/cdktf/lib/terraform-resource.ts +++ b/packages/cdktf/lib/terraform-resource.ts @@ -307,7 +307,12 @@ export class TerraformResource : `${this.terraformResourceType}.${resourceToMoveTo.friendlyUniqueId}`; const movedFromId = `${this.terraformResourceType}.${this.friendlyUniqueId}`; this._moved = { to: movedToId, from: movedFromId, renamed: false }; - // TODO: add validation of correct Terraform Version + this.node.addValidation( + new ValidateTerraformVersion( + ">=1.5", + `Resource move functionality is only supported for Terraform >=1.5. Please upgrade your Terraform version.` + ) + ); } /** @@ -340,5 +345,9 @@ export class TerraformResource from: `${this.terraformResourceType}.${oldUniqueId}`, renamed: true, }; + new ValidateTerraformVersion( + ">=1.5", + `Resource rename functionality is only supported for Terraform >=1.5. Please upgrade your Terraform version.` + ); } } From ca02eb71b2fdfd182bcf4f7334d15854ffe81a1c Mon Sep 17 00:00:00 2001 From: Mark DeCrane Date: Thu, 5 Oct 2023 14:42:52 -0400 Subject: [PATCH 13/23] chore: update error messages and js docs with feedback --- packages/cdktf/lib/terraform-resource-targets.ts | 12 +++++++----- packages/cdktf/lib/terraform-resource.ts | 15 +++++++++------ 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/packages/cdktf/lib/terraform-resource-targets.ts b/packages/cdktf/lib/terraform-resource-targets.ts index df62c69a08..6e688503a5 100644 --- a/packages/cdktf/lib/terraform-resource-targets.ts +++ b/packages/cdktf/lib/terraform-resource-targets.ts @@ -24,7 +24,7 @@ export class TerraformResourceTargets { public addResourceTarget(resource: TerraformResource, target: string): void { if (this._resourceTargetMap.has(target)) { throw new Error( - `Tag "${target}" has already been set at ${ + `Target "${target}" has already been set at ${ this._resourceTargetMap.get(target)?.friendlyUniqueId }` ); @@ -35,11 +35,13 @@ export class TerraformResourceTargets { public getResourceAddressByTarget(target: string): TerraformResource { const result = this._resourceTargetMap.get(target); if (!result) { - throw new Error(`Tag "${target}" has not been set: + throw new Error(`Target "${target}" has not been set: - Current Tag Entries:\n ${this.prettyPrintEntries()} - - Make sure the resource being moved to has been tagged before .movedTo() has been called + Current Target Entries:\n ${this.prettyPrintEntries()} + + To add this target, call .addMoveTarget("${target}") on the instance of the resource to move to. + + Make sure the resource being moved to has been given a moveTarget before .movedTo() has been called //TODO: add aspect that avoids this pain point and remove `); } return result; diff --git a/packages/cdktf/lib/terraform-resource.ts b/packages/cdktf/lib/terraform-resource.ts index 70506c68b1..b9c32a33e9 100644 --- a/packages/cdktf/lib/terraform-resource.ts +++ b/packages/cdktf/lib/terraform-resource.ts @@ -257,7 +257,7 @@ export class TerraformResource : undefined, moved: this._moved ? { - [this.terraformResourceType]: [this.friendlyUniqueId], // TODO: anything more we need here? + [this.terraformResourceType]: [this.friendlyUniqueId], } : undefined, }; @@ -287,8 +287,8 @@ export class TerraformResource } /** - * Moves this resource to the location denoted by moveTarget. - * @param moveTarget The previously set string moveTarget denoting the location of the move + * Moves this resource to the target resource given by moveTarget. + * @param moveTarget The previously set user defined string set by .addMoveTarget() corresponding to the resource to move to. * @param index Optional The index corresponding to the key the resource is to appear in the foreach of a resource to move to */ public moveTo(moveTarget: string, index?: string | number) { @@ -297,7 +297,10 @@ export class TerraformResource stackMoveTargets.getResourceAddressByTarget(moveTarget); if (this.terraformResourceType !== resourceToMoveTo.terraformResourceType) { throw new Error( - `The move target "${moveTarget}" corresponding to the resource of type ${resourceToMoveTo.terraformResourceType} to move to differs from the resource of type ${this.terraformResourceType} being moved from` + `You have tried to move a resource to a different type: + + The move target "${moveTarget}" corresponding to the resource of type ${resourceToMoveTo.terraformResourceType} to move to differs from the resource of type ${this.terraformResourceType} being moved from + ` ); } const movedToId = index @@ -316,8 +319,8 @@ export class TerraformResource } /** - * Adds a string moveTarget to this resource - * @param moveTarget The string move target that corresponds to the address of this resource + * Adds a user defined moveTarget string to this resource to be later used in .moveTo(moveTarget) to resolve the location of the move. + * @param moveTarget The string move target that will correspond to this resource */ public addMoveTarget(moveTarget: string) { const stackMoveTargets = this.parentStackResourceTargets(); From e98311adc3da51607db220d14de1d42e91a3c4f9 Mon Sep 17 00:00:00 2001 From: Mark DeCrane Date: Fri, 6 Oct 2023 09:40:02 -0400 Subject: [PATCH 14/23] chore: doc improvements --- examples/typescript/aws-move/main.ts | 1 + website/docs/cdktf/concepts/resources.mdx | 22 +++++++++------------- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/examples/typescript/aws-move/main.ts b/examples/typescript/aws-move/main.ts index 21850ef1fa..6f67986a89 100644 --- a/examples/typescript/aws-move/main.ts +++ b/examples/typescript/aws-move/main.ts @@ -280,4 +280,5 @@ new UnNestingMoveStack(app, "un-nesting-move-stack"); new NestingMoveStack(app, "nesting-move-stack"); new ListIteratorMoveStack(app, "list-iterator-move-stack"); new ComplexIteratorMoveStack(app, "complex-iterator-move-stack"); +new RenameResourceStack(app, "rename-stack"); app.synth(); diff --git a/website/docs/cdktf/concepts/resources.mdx b/website/docs/cdktf/concepts/resources.mdx index e00e41cb4e..414cdb8d6c 100644 --- a/website/docs/cdktf/concepts/resources.mdx +++ b/website/docs/cdktf/concepts/resources.mdx @@ -372,11 +372,11 @@ import imports.kubernetes.namespace.NamespaceMetadata; ## Refactoring & Renaming Resources -By default moving and/or renaming resource will be regarded with the intent to destroy the resource and re-create it. If such behavior must be avoided, but there is need to refactor your infrastructure definitions and/or rename resources in it, the function `moveTo` can serve your purpose. +When working with your infrastructure definitions and the need arises to refactor or rename resources without destroying and recreating them, you can leverage the `moveTo` function. This section outlines how to perform resource moves, rename resources, and enable foreach on existing resources in your CDKTF project. ### Performing Resource Moves -The function `moveTo` is present on all resources and takes a string `moveTarget` that denotes the location of the move. To set the `moveTarget`, use the function `addMoveTarget` that is present on the resource you desire to move to and provide its string target. +The `moveTo` function is available on all resources and is used for relocating a resource to the location specified by the string target `moveTarget`. To set the `moveTarget` for a resource, utilize the `addMoveTarget` function that is present on the resource to move to. Note that the `moveTarget` must be set prior to the call of `moveTo`. @@ -390,15 +390,11 @@ new S3Bucket(this, "test-bucket-move-from", { }).moveTo("move-s3"); ``` -After deployment, both the resource being moved, and the move target on the resource being moved to can be removed. +After deployment, both the resource being moved and the move target on the destination resource can be removed. #### Move Targets -A `moveTarget` is accessible anywhere in the context of the stack it is created. - -For instance, a `moveTarget` set at the root of the stack can be accessed within a nested construct. Conversely, a `moveTarget` set in a nested construct can be accessed at the root of the stack. - -Note that the `moveTarget` must be set prior to the call of `moveTo`. For example, in the instance where you are moving a resource into a nested construct, the nested construct must be instantiated prior to the call of `moveTo` on the resource being moved. +A `moveTarget` is accessible within the context of the stack where it is created. Whether it's set at the root of the stack or within a nested construct, you can access it accordingly. However, it's crucial to ensure that the `moveTarget` is configured before invoking the `moveTo` function. For example, when moving a resource into a nested construct, make sure the nested construct is instantiated prior to calling `moveTo` on the resource being moved. ```ts // Contains resource with moveTarget "move" @@ -411,7 +407,7 @@ new S3Bucket(this, "test-bucket-1", { ### Renaming a Resource -To rename a resource, all that is needed is to call the `renameResourceId` function that is present on the resource. +To rename a resource, you can simply use the `renameResourceId` function available on the resource. ```ts new S3Bucket(this, "bucket-id", { @@ -419,13 +415,11 @@ new S3Bucket(this, "bucket-id", { }).renameResourceId("bucket-new-id"); ``` -Once the resource has been deployed, the original id can be changed to use the desired renamed resource id, and the call `renameResourceId` can be removed. +After deploying the resource, you can update your resource to use the newly assigned resource ID, and the `renameResourceId` call can be safely removed. ### Enabling `foreach` on a Resource -If you desire to move a deployed resource to be in composition of a resource using `foreach`, the index argument of `moveTo` can place the deployed resource in a `foreach` composition without its destruction. - -Here the index `website-static-files` is provided, corresponding to the key that appears in the TerraformIterator `iterator`. +If you wish to incorporate a deployed resource into a composition using `foreach`, you can achieve this without destroying the resource by specifying the desired index using the `moveTo` function. The index should correspond to the key found in the `TerraformIterator` named iterator ```ts const iterator = TerraformIterator.fromMap({ @@ -448,6 +442,8 @@ new S3Bucket(this, "moved-bucket", { }).moveTo("resourceWithIterator", "website-static-files"); ``` +This allows you to efficiently integrate existing resources into a `foreach` composition without the need for resource destruction. + ## Provisioners Provisioners can be used to model specific actions on the local machine or on a remote machine in order to prepare servers or other infrastructure objects for service. You can find more information on the concept of provisioners in the [Terraform docs](/terraform/language/resources/provisioners/syntax). You can pass the `provisioners` key to define a list of provisioners, connections can be configured with the `connection` key. A working example can be found at [examples/typescript/provisioner](https://github.com/hashicorp/terraform-cdk/blob/main/examples/typescript/provisioner/main.ts). From 18a8793f1090538fe4fcbfeca1ea036f45e22c4e Mon Sep 17 00:00:00 2001 From: Mark DeCrane Date: Fri, 13 Oct 2023 09:35:18 -0400 Subject: [PATCH 15/23] feat: moved building of move blocks to toTerraform --- examples/typescript/aws-move/main.ts | 20 +++- packages/cdktf/lib/terraform-resource.ts | 117 +++++++++++++++-------- packages/cdktf/test/resource.test.ts | 48 ++++++++++ 3 files changed, 138 insertions(+), 47 deletions(-) diff --git a/examples/typescript/aws-move/main.ts b/examples/typescript/aws-move/main.ts index 6f67986a89..82ae2ca971 100644 --- a/examples/typescript/aws-move/main.ts +++ b/examples/typescript/aws-move/main.ts @@ -118,11 +118,17 @@ export class NestingMoveStack extends TerraformStack { region: "us-west-2", }); - new NestingConstructToMoveTo(this, "construct-to-move-to"); - new S3Bucket(this, "test-bucket-3", { bucket: "test-move-bucket-name-3", - }).moveTo("move"); // + }).moveTo("move"); + + new S3Bucket(this, "test-bucket-4", { + bucket: "test-move-bucket-name-4", + }).moveTo("move"); + + new NestingConstructToMoveTo(this, "construct-to-move-to"); + + // } } @@ -141,6 +147,9 @@ export class NestingNestedConstructToMoveTo extends Construct { new S3Bucket(this, "test-bucket-3", { bucket: "test-move-bucket-name-3", }).addMoveTarget("move"); + new S3Bucket(this, "test-bucket-4", { + bucket: "test-move-bucket-name-4", + }).addMoveTarget("moveTo"); } } // NESTING RESOURCE @@ -260,7 +269,7 @@ export class CountMoveStack extends TerraformStack { } } // MOVE INTO RESOURCE USING COUNT - +/** export class RenameResourceStack extends TerraformStack { constructor(scope: Construct, id: string) { super(scope, id); @@ -274,11 +283,12 @@ export class RenameResourceStack extends TerraformStack { }).renameResourceId("test-bucket-rename"); } } +*/ const app = new App(); new UnNestingMoveStack(app, "un-nesting-move-stack"); new NestingMoveStack(app, "nesting-move-stack"); new ListIteratorMoveStack(app, "list-iterator-move-stack"); new ComplexIteratorMoveStack(app, "complex-iterator-move-stack"); -new RenameResourceStack(app, "rename-stack"); +//new RenameResourceStack(app, "rename-stack"); app.synth(); diff --git a/packages/cdktf/lib/terraform-resource.ts b/packages/cdktf/lib/terraform-resource.ts index b9c32a33e9..9fb13a5dfe 100644 --- a/packages/cdktf/lib/terraform-resource.ts +++ b/packages/cdktf/lib/terraform-resource.ts @@ -73,17 +73,21 @@ export interface TerraformResourceConfig extends TerraformMetaArguments { readonly terraformGeneratorMetadata?: TerraformProviderGeneratorMetadata; } +export interface TerraformResourceMove { + readonly moveTarget: string; + readonly index?: string | number; +} + +export interface TerraformResourceRename { + readonly newId: string; + readonly oldId: string; +} + export interface TerraformResourceImport { readonly id: string; readonly provider?: TerraformProvider; } -export interface TerraformResourceMove { - readonly from: string; - readonly to: string; - readonly renamed: boolean; -} - // eslint-disable-next-line jsdoc/require-jsdoc export class TerraformResource extends TerraformElement @@ -104,7 +108,7 @@ export class TerraformResource FileProvisioner | LocalExecProvisioner | RemoteExecProvisioner >; private _imported?: TerraformResourceImport; - private _moved?: TerraformResourceMove; + private _moved?: TerraformResourceMove | TerraformResourceRename; constructor(scope: Construct, id: string, config: TerraformResourceConfig) { super(scope, id, config.terraformResourceType); @@ -216,7 +220,24 @@ export class TerraformResource ...(attributes["//"] ?? {}), ...this.constructNodeMetadata, }; + const movedBlock = this.buildMoveBlocks(); return { + resource: + movedBlock && !movedBlock.renamed + ? undefined + : { + [this.terraformResourceType]: { + [this.friendlyUniqueId]: attributes, + }, + }, + moved: movedBlock + ? [ + { + to: movedBlock.to, + from: movedBlock.from, + }, + ] + : undefined, import: this._imported ? [ { @@ -226,20 +247,6 @@ export class TerraformResource }, ] : undefined, - resource: - this._moved && !this._moved.renamed - ? undefined - : { - [this.terraformResourceType]: { - [this.friendlyUniqueId]: attributes, - }, - }, - moved: this._moved - ? { - to: this._moved.to, - from: this._moved.from, - } - : undefined, }; } @@ -286,30 +293,56 @@ export class TerraformResource return TerraformStack.of(this).moveTargets; } + private instanceOfTerraformResourceMove( + move: any + ): move is TerraformResourceMove { + return "moveTarget" in move && `index` in move; + } + + private instanceOfTerraformResourceRename( + move: any + ): move is TerraformResourceRename { + return "newId" in move && `oldId` in move; + } + + private buildMoveBlocks() { + if (this.instanceOfTerraformResourceMove(this._moved)) { + const { moveTarget, index } = this._moved; + const stackMoveTargets = this.parentStackResourceTargets(); + const resourceToMoveTo = + stackMoveTargets.getResourceAddressByTarget(moveTarget); + if ( + this.terraformResourceType !== resourceToMoveTo.terraformResourceType + ) { + throw new Error( + `You have tried to move a resource to a different type: + + The move target "${moveTarget}" corresponding to the resource of type ${resourceToMoveTo.terraformResourceType} to move to differs from the resource of type ${this.terraformResourceType} being moved from + ` + ); + } + const movedToId = index + ? typeof index === "string" + ? `${this.terraformResourceType}.${resourceToMoveTo.friendlyUniqueId}["${index}"]` + : `${this.terraformResourceType}.${resourceToMoveTo.friendlyUniqueId}[${index}]` + : `${this.terraformResourceType}.${resourceToMoveTo.friendlyUniqueId}`; + const movedFromId = `${this.terraformResourceType}.${this.friendlyUniqueId}`; + return { to: movedToId, from: movedFromId, renamed: false }; + } else if (this.instanceOfTerraformResourceRename(this._moved)) { + const { newId, oldId } = this._moved; + return { to: newId, from: oldId, renamed: true }; + } else { + return undefined; + } + } + /** * Moves this resource to the target resource given by moveTarget. * @param moveTarget The previously set user defined string set by .addMoveTarget() corresponding to the resource to move to. * @param index Optional The index corresponding to the key the resource is to appear in the foreach of a resource to move to */ public moveTo(moveTarget: string, index?: string | number) { - const stackMoveTargets = this.parentStackResourceTargets(); - const resourceToMoveTo = - stackMoveTargets.getResourceAddressByTarget(moveTarget); - if (this.terraformResourceType !== resourceToMoveTo.terraformResourceType) { - throw new Error( - `You have tried to move a resource to a different type: - - The move target "${moveTarget}" corresponding to the resource of type ${resourceToMoveTo.terraformResourceType} to move to differs from the resource of type ${this.terraformResourceType} being moved from - ` - ); - } - const movedToId = index - ? typeof index === "string" - ? `${this.terraformResourceType}.${resourceToMoveTo.friendlyUniqueId}["${index}"]` - : `${this.terraformResourceType}.${resourceToMoveTo.friendlyUniqueId}[${index}]` - : `${this.terraformResourceType}.${resourceToMoveTo.friendlyUniqueId}`; - const movedFromId = `${this.terraformResourceType}.${this.friendlyUniqueId}`; - this._moved = { to: movedToId, from: movedFromId, renamed: false }; + this._moved = { moveTarget, index }; this.node.addValidation( new ValidateTerraformVersion( ">=1.5", @@ -331,6 +364,7 @@ export class TerraformResource * Renames the id of this resource to newId * @param newId The new id to replace the current id */ + public renameResourceId(newId: string) { const oldUniqueId = this.friendlyUniqueId; const idParts = oldUniqueId.split("."); @@ -344,9 +378,8 @@ export class TerraformResource ); this.overrideLogicalId(newUniqueId); this._moved = { - to: `${this.terraformResourceType}.${newUniqueId}`, - from: `${this.terraformResourceType}.${oldUniqueId}`, - renamed: true, + newId: `${this.terraformResourceType}.${newUniqueId}`, + oldId: `${this.terraformResourceType}.${oldUniqueId}`, }; new ValidateTerraformVersion( ">=1.5", diff --git a/packages/cdktf/test/resource.test.ts b/packages/cdktf/test/resource.test.ts index 2514aae4cd..3d37b4954a 100644 --- a/packages/cdktf/test/resource.test.ts +++ b/packages/cdktf/test/resource.test.ts @@ -540,3 +540,51 @@ it("moves resource to resource with rename", () => { "simple" ); }); + +// TODO: Add resource test for multiple move blocks and out of order tags and moves +it("moves multiple resources", () => { + const app = Testing.app(); + const stack = new TerraformStack(app, "test"); + new TestProvider(stack, "provider", {}); + + const construct = new Construct(stack, "construct"); + const nestedContruct = new Construct(construct, "nested-construct"); + + new TestResource(nestedContruct, "simple", { + name: "foo", + provisioners: [ + { type: "local-exec", command: "echo 'hello' > world.txt" }, + { type: "local-exec", command: "echo 'hello' > world1.txt" }, + { type: "local-exec", command: "echo 'hello' > world2.txt" }, + ], + }).addMoveTarget("test-1"); + + new TestResource(nestedContruct, "simple-2", { + name: "foo", + provisioners: [ + { type: "local-exec", command: "echo 'hello' > world.txt" }, + { type: "local-exec", command: "echo 'hello' > world1.txt" }, + { type: "local-exec", command: "echo 'hello' > world2.txt" }, + ], + }).addMoveTarget("test-2"); + + new TestResource(stack, "simple", { + name: "foo", + provisioners: [ + { type: "local-exec", command: "echo 'hello' > world.txt" }, + { type: "local-exec", command: "echo 'hello' > world1.txt" }, + { type: "local-exec", command: "echo 'hello' > world2.txt" }, + ], + }).moveTo("test-1"); + + new TestResource(stack, "simple-2", { + name: "foo", + provisioners: [ + { type: "local-exec", command: "echo 'hello' > world.txt" }, + { type: "local-exec", command: "echo 'hello' > world1.txt" }, + { type: "local-exec", command: "echo 'hello' > world2.txt" }, + ], + }).moveTo("test-2"); + + expect(Testing.synth(stack)).toMatchSnapshot(); +}); From 14b8da2855ed9a8dcc63cc89f9a03466921b39c2 Mon Sep 17 00:00:00 2001 From: Mark DeCrane Date: Mon, 9 Oct 2023 11:02:15 -0400 Subject: [PATCH 16/23] chore: docs update --- website/docs/cdktf/concepts/resources.mdx | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/website/docs/cdktf/concepts/resources.mdx b/website/docs/cdktf/concepts/resources.mdx index 414cdb8d6c..1e4dcf98f8 100644 --- a/website/docs/cdktf/concepts/resources.mdx +++ b/website/docs/cdktf/concepts/resources.mdx @@ -378,8 +378,6 @@ When working with your infrastructure definitions and the need arises to refacto The `moveTo` function is available on all resources and is used for relocating a resource to the location specified by the string target `moveTarget`. To set the `moveTarget` for a resource, utilize the `addMoveTarget` function that is present on the resource to move to. -Note that the `moveTarget` must be set prior to the call of `moveTo`. - ```ts new S3Bucket(this, "test-bucket-move-to", { bucket: "move-bucket-name", @@ -394,15 +392,15 @@ After deployment, both the resource being moved and the move target on the desti #### Move Targets -A `moveTarget` is accessible within the context of the stack where it is created. Whether it's set at the root of the stack or within a nested construct, you can access it accordingly. However, it's crucial to ensure that the `moveTarget` is configured before invoking the `moveTo` function. For example, when moving a resource into a nested construct, make sure the nested construct is instantiated prior to calling `moveTo` on the resource being moved. +A `moveTarget` is accessible anywhere within the context of the stack where it is created. Whether it's set at the root of the stack or within a nested construct, you can access it accordingly. ```ts -// Contains resource with moveTarget "move" -new NestedConstructToMoveTo(this, "construct-to-move-to"); - new S3Bucket(this, "test-bucket-1", { bucket: "test-move-bucket-name-1", }).moveTo("move"); + +// Contains resource with moveTarget "move" +new NestedConstructToMoveTo(this, "construct-to-move-to"); ``` ### Renaming a Resource @@ -442,7 +440,7 @@ new S3Bucket(this, "moved-bucket", { }).moveTo("resourceWithIterator", "website-static-files"); ``` -This allows you to efficiently integrate existing resources into a `foreach` composition without the need for resource destruction. +This allows you to efficiently integrate existing resources into a `foreach` composition without destroying the existing deployed resource. ## Provisioners From 757295142ebb14c099232f2c50cc080e54cf7fe4 Mon Sep 17 00:00:00 2001 From: Mark DeCrane Date: Fri, 13 Oct 2023 09:51:03 -0400 Subject: [PATCH 17/23] chore: refactor of move functionality --- .../cdktf/lib/terraform-resource-targets.ts | 2 - packages/cdktf/lib/terraform-resource.ts | 179 ++++++++++++------ .../test/__snapshots__/resource.test.ts.snap | 72 +++++++ packages/cdktf/test/resource.test.ts | 60 +++++- 4 files changed, 243 insertions(+), 70 deletions(-) diff --git a/packages/cdktf/lib/terraform-resource-targets.ts b/packages/cdktf/lib/terraform-resource-targets.ts index 6e688503a5..7055674c10 100644 --- a/packages/cdktf/lib/terraform-resource-targets.ts +++ b/packages/cdktf/lib/terraform-resource-targets.ts @@ -40,8 +40,6 @@ export class TerraformResourceTargets { Current Target Entries:\n ${this.prettyPrintEntries()} To add this target, call .addMoveTarget("${target}") on the instance of the resource to move to. - - Make sure the resource being moved to has been given a moveTarget before .movedTo() has been called //TODO: add aspect that avoids this pain point and remove `); } return result; diff --git a/packages/cdktf/lib/terraform-resource.ts b/packages/cdktf/lib/terraform-resource.ts index 9fb13a5dfe..467140bfa5 100644 --- a/packages/cdktf/lib/terraform-resource.ts +++ b/packages/cdktf/lib/terraform-resource.ts @@ -73,14 +73,13 @@ export interface TerraformResourceConfig extends TerraformMetaArguments { readonly terraformGeneratorMetadata?: TerraformProviderGeneratorMetadata; } -export interface TerraformResourceMove { +export interface TerraformResourceRefactor { readonly moveTarget: string; readonly index?: string | number; } export interface TerraformResourceRename { readonly newId: string; - readonly oldId: string; } export interface TerraformResourceImport { @@ -108,7 +107,7 @@ export class TerraformResource FileProvisioner | LocalExecProvisioner | RemoteExecProvisioner >; private _imported?: TerraformResourceImport; - private _moved?: TerraformResourceMove | TerraformResourceRename; + private _moved?: TerraformResourceRefactor | TerraformResourceRename; constructor(scope: Construct, id: string, config: TerraformResourceConfig) { super(scope, id, config.terraformResourceType); @@ -135,6 +134,14 @@ export class TerraformResource ); } + private isResourceRefactor(move: any): move is TerraformResourceRefactor { + return move !== undefined && "moveTarget" in move && `index` in move; + } + + private isResourceRename(move: any): move is TerraformResourceRename { + return this._moved !== undefined && "newId" in move; + } + public getStringAttribute(terraformAttribute: string) { return Token.asString(this.interpolationForAttribute(terraformAttribute)); } @@ -220,7 +227,7 @@ export class TerraformResource ...(attributes["//"] ?? {}), ...this.constructNodeMetadata, }; - const movedBlock = this.buildMoveBlocks(); + const movedBlock = this._buildMoveBlock(); return { resource: movedBlock && !movedBlock.renamed @@ -289,28 +296,63 @@ export class TerraformResource ); } - private parentStackResourceTargets() { - return TerraformStack.of(this).moveTargets; + private _getResourceTarget(moveTarget: string) { + return TerraformStack.of(this).moveTargets.getResourceAddressByTarget( + moveTarget + ); } - private instanceOfTerraformResourceMove( - move: any - ): move is TerraformResourceMove { - return "moveTarget" in move && `index` in move; + private _addResourceTarget(moveTarget: string) { + return TerraformStack.of(this).moveTargets.addResourceTarget( + this, + moveTarget + ); } - private instanceOfTerraformResourceRename( - move: any - ): move is TerraformResourceRename { - return "newId" in move && `oldId` in move; - } + private _buildMoveBlock() { + // eslint-disable-next-line jsdoc/require-jsdoc + function buildResourceMove({ + resourceType, + moveToId, + moveFromId, + index, + }: { + resourceType: string; + moveToId: string; + moveFromId: string; + index: string | number | undefined; + }): { to: string; from: string } { + const to = index + ? typeof index === "string" + ? `${resourceType}.${moveToId}["${index}"]` + : `${resourceType}.${moveToId}[${index}]` + : `${resourceType}.${moveToId}`; + const from = `${resourceType}.${moveFromId}`; + return { to, from }; + } + // eslint-disable-next-line jsdoc/require-jsdoc + function buildResourceRename({ + newResourceId, + moveFromId, + }: { + newResourceId: string; + moveFromId: string; + }): { newUniqueId: string; oldUniqueId: string } { + const oldUniqueId = moveFromId; + const idParts = oldUniqueId.split("."); + idParts[idParts.length - 1] = newResourceId; + const intialValue = idParts[0]; + idParts.shift(); + const newUniqueId = idParts.reduce( + (accum, curr) => accum + "." + curr, + intialValue + ); + return { newUniqueId, oldUniqueId }; + } - private buildMoveBlocks() { - if (this.instanceOfTerraformResourceMove(this._moved)) { + if (this.isResourceRefactor(this._moved)) { const { moveTarget, index } = this._moved; - const stackMoveTargets = this.parentStackResourceTargets(); - const resourceToMoveTo = - stackMoveTargets.getResourceAddressByTarget(moveTarget); + const resourceToMoveTo = this._getResourceTarget(moveTarget); if ( this.terraformResourceType !== resourceToMoveTo.terraformResourceType ) { @@ -321,16 +363,25 @@ export class TerraformResource ` ); } - const movedToId = index - ? typeof index === "string" - ? `${this.terraformResourceType}.${resourceToMoveTo.friendlyUniqueId}["${index}"]` - : `${this.terraformResourceType}.${resourceToMoveTo.friendlyUniqueId}[${index}]` - : `${this.terraformResourceType}.${resourceToMoveTo.friendlyUniqueId}`; - const movedFromId = `${this.terraformResourceType}.${this.friendlyUniqueId}`; - return { to: movedToId, from: movedFromId, renamed: false }; - } else if (this.instanceOfTerraformResourceRename(this._moved)) { - const { newId, oldId } = this._moved; - return { to: newId, from: oldId, renamed: true }; + const { to, from } = buildResourceMove({ + resourceType: this.terraformResourceType, + moveToId: resourceToMoveTo.friendlyUniqueId, + moveFromId: this.friendlyUniqueId, + index, + }); + return { to, from, renamed: false }; + } else if (this.isResourceRename(this._moved)) { + const { newId } = this._moved; + const { newUniqueId, oldUniqueId } = buildResourceRename({ + newResourceId: newId, + moveFromId: this.friendlyUniqueId, + }); + this.overrideLogicalId(newUniqueId); + return { + to: `${this.terraformResourceType}.${newUniqueId}`, + from: `${this.terraformResourceType}.${oldUniqueId}`, + renamed: true, + }; } else { return undefined; } @@ -342,6 +393,20 @@ export class TerraformResource * @param index Optional The index corresponding to the key the resource is to appear in the foreach of a resource to move to */ public moveTo(moveTarget: string, index?: string | number) { + if (this._moved) { + if (this.isResourceRefactor(this._moved)) { + throw new Error(`The resource ${this.friendlyUniqueId} has been given two moveTargets: "${this._moved.moveTarget}" and "${moveTarget}" + + Resources can only be moved once per plan/apply + `); + } + if (this.isResourceRename(this._moved)) { + throw new Error(`The resource ${this.friendlyUniqueId} has been renamed to "${this._moved.newId}" and given the moveTarget "${moveTarget}" + + If you wish to rename and move the resource, specify the change in ID in the instantiation of the targeted resource. + `); + } + } this._moved = { moveTarget, index }; this.node.addValidation( new ValidateTerraformVersion( @@ -351,39 +416,37 @@ export class TerraformResource ); } - /** - * Adds a user defined moveTarget string to this resource to be later used in .moveTo(moveTarget) to resolve the location of the move. - * @param moveTarget The string move target that will correspond to this resource - */ - public addMoveTarget(moveTarget: string) { - const stackMoveTargets = this.parentStackResourceTargets(); - stackMoveTargets.addResourceTarget(this, moveTarget); - } - /** * Renames the id of this resource to newId * @param newId The new id to replace the current id */ - public renameResourceId(newId: string) { - const oldUniqueId = this.friendlyUniqueId; - const idParts = oldUniqueId.split("."); - idParts[idParts.length - 1] = newId; - - const intialValue = idParts[0]; - idParts.shift(); - const newUniqueId = idParts.reduce( - (accum, curr) => accum + "." + curr, - intialValue - ); - this.overrideLogicalId(newUniqueId); - this._moved = { - newId: `${this.terraformResourceType}.${newUniqueId}`, - oldId: `${this.terraformResourceType}.${oldUniqueId}`, - }; - new ValidateTerraformVersion( - ">=1.5", - `Resource rename functionality is only supported for Terraform >=1.5. Please upgrade your Terraform version.` + if (this.isResourceRefactor(this._moved)) { + throw new Error(`The resource ${this.friendlyUniqueId} has been renamed to "${newId}" and given the moveTarget "${this._moved.moveTarget}" + + If you wish to rename and move the resource, specify the change in ID in the instantiation of the targeted resource. + `); + } + if (this.isResourceRename(this._moved)) { + throw new Error(`The resource ${this.friendlyUniqueId} has been given two renames: "${this._moved.newId}" and "${newId}" + + Resources can only be renamed once per plan/apply + `); + } + this._moved = { newId }; + this.node.addValidation( + new ValidateTerraformVersion( + ">=1.5", + `Resource rename functionality is only supported for Terraform >=1.5. Please upgrade your Terraform version.` + ) ); } + + /** + * Adds a user defined moveTarget string to this resource to be later used in .moveTo(moveTarget) to resolve the location of the move. + * @param moveTarget The string move target that will correspond to this resource + */ + public addMoveTarget(moveTarget: string) { + this._addResourceTarget(moveTarget); + } } diff --git a/packages/cdktf/test/__snapshots__/resource.test.ts.snap b/packages/cdktf/test/__snapshots__/resource.test.ts.snap index 7a43ab856b..bdd4d61aa3 100644 --- a/packages/cdktf/test/__snapshots__/resource.test.ts.snap +++ b/packages/cdktf/test/__snapshots__/resource.test.ts.snap @@ -222,6 +222,78 @@ exports[`minimal configuration 1`] = ` }" `; +exports[`moves multiple resources 1`] = ` +"{ + "moved": [ + { + "from": "test_resource.simple", + "to": "test_resource.construct_nested-construct_simple_2C3755B0" + }, + { + "from": "test_resource.simple-2", + "to": "test_resource.construct_nested-construct_simple-2_078CE0AF" + } + ], + "provider": { + "test": [ + { + } + ] + }, + "resource": { + "test_resource": { + "construct_nested-construct_simple-2_078CE0AF": { + "name": "foo", + "provisioner": [ + { + "local-exec": { + "command": "echo 'hello' > world.txt" + } + }, + { + "local-exec": { + "command": "echo 'hello' > world1.txt" + } + }, + { + "local-exec": { + "command": "echo 'hello' > world2.txt" + } + } + ] + }, + "construct_nested-construct_simple_2C3755B0": { + "name": "foo", + "provisioner": [ + { + "local-exec": { + "command": "echo 'hello' > world.txt" + } + }, + { + "local-exec": { + "command": "echo 'hello' > world1.txt" + } + }, + { + "local-exec": { + "command": "echo 'hello' > world2.txt" + } + } + ] + } + } + }, + "terraform": { + "required_providers": { + "test": { + "version": "~> 2.0" + } + } + } +}" +`; + exports[`number[] attributes 1`] = ` "{ "output": { diff --git a/packages/cdktf/test/resource.test.ts b/packages/cdktf/test/resource.test.ts index 3d37b4954a..2a5e93f1c0 100644 --- a/packages/cdktf/test/resource.test.ts +++ b/packages/cdktf/test/resource.test.ts @@ -378,8 +378,8 @@ it("moves resource to greater nesting in contained construct", () => { }).moveTo("test"); const synthedStack = JSON.parse(Testing.synth(stack)); - expect(synthedStack.moved.from).toEqual("test_resource.simple"); - expect(synthedStack.moved.to).toEqual( + expect(synthedStack.moved[0].from).toEqual("test_resource.simple"); + expect(synthedStack.moved[0].to).toEqual( "test_resource.construct_nested-construct_simple_2C3755B0" ); expect(Object.keys(synthedStack.resource.test_resource)).toContain( @@ -417,10 +417,10 @@ it("moves resource to a lesser nesting from contained construct", () => { }).moveTo("test"); const synthedStack = JSON.parse(Testing.synth(stack)); - expect(synthedStack.moved.from).toEqual( + expect(synthedStack.moved[0].from).toEqual( "test_resource.construct_nested-construct_simple_2C3755B0" ); - expect(synthedStack.moved.to).toEqual("test_resource.simple"); + expect(synthedStack.moved[0].to).toEqual("test_resource.simple"); expect(Object.keys(synthedStack.resource.test_resource)).toContain("simple"); // Must not include old resource being moved from expect(Object.keys(synthedStack.resource.test_resource)).not.toContain( @@ -455,8 +455,8 @@ it("moves resource to be in composition with foreach using list iterator", () => }).moveTo("test", "foo-one"); const synthedStack = JSON.parse(Testing.synth(stack)); - expect(synthedStack.moved.from).toEqual("test_resource.simple"); - expect(synthedStack.moved.to).toEqual( + expect(synthedStack.moved[0].from).toEqual("test_resource.simple"); + expect(synthedStack.moved[0].to).toEqual( `test_resource.simple-foreach[\"foo-one\"]` ); expect(Object.keys(synthedStack.resource.test_resource)).toContain( @@ -502,8 +502,8 @@ it("moves resource to be in composition with foreach using complex iterator", () }).moveTo("test", "simple-foreach-one"); const synthedStack = JSON.parse(Testing.synth(stack)); - expect(synthedStack.moved.from).toEqual("test_resource.simple"); - expect(synthedStack.moved.to).toEqual( + expect(synthedStack.moved[0].from).toEqual("test_resource.simple"); + expect(synthedStack.moved[0].to).toEqual( `test_resource.simple-foreach[\"simple-foreach-one\"]` ); expect(Object.keys(synthedStack.resource.test_resource)).toContain( @@ -530,8 +530,8 @@ it("moves resource to resource with rename", () => { }).renameResourceId("simple-rename"); const synthedStack = JSON.parse(Testing.synth(stack)); - expect(synthedStack.moved.from).toEqual("test_resource.simple"); - expect(synthedStack.moved.to).toEqual("test_resource.simple-rename"); + expect(synthedStack.moved[0].from).toEqual("test_resource.simple"); + expect(synthedStack.moved[0].to).toEqual("test_resource.simple-rename"); expect(Object.keys(synthedStack.resource.test_resource)).toContain( "simple-rename" ); @@ -588,3 +588,43 @@ it("moves multiple resources", () => { expect(Testing.synth(stack)).toMatchSnapshot(); }); + +it("moves correctly when target set after call to moveTo", () => { + const app = Testing.app(); + const stack = new TerraformStack(app, "test"); + new TestProvider(stack, "provider", {}); + + const construct = new Construct(stack, "construct"); + const nestedContruct = new Construct(construct, "nested-construct"); + + new TestResource(stack, "simple", { + name: "foo", + provisioners: [ + { type: "local-exec", command: "echo 'hello' > world.txt" }, + { type: "local-exec", command: "echo 'hello' > world1.txt" }, + { type: "local-exec", command: "echo 'hello' > world2.txt" }, + ], + }).moveTo("test"); + + new TestResource(nestedContruct, "simple", { + name: "foo", + provisioners: [ + { type: "local-exec", command: "echo 'hello' > world.txt" }, + { type: "local-exec", command: "echo 'hello' > world1.txt" }, + { type: "local-exec", command: "echo 'hello' > world2.txt" }, + ], + }).addMoveTarget("test"); + + const synthedStack = JSON.parse(Testing.synth(stack)); + expect(synthedStack.moved[0].from).toEqual("test_resource.simple"); + expect(synthedStack.moved[0].to).toEqual( + "test_resource.construct_nested-construct_simple_2C3755B0" + ); + expect(Object.keys(synthedStack.resource.test_resource)).toContain( + "construct_nested-construct_simple_2C3755B0" + ); + // Must not include old resource being moved from + expect(Object.keys(synthedStack.resource.test_resource)).not.toContain( + "simple" + ); +}); From cbd7fa3b54af9ff7311c2579e1ac705d4997aac3 Mon Sep 17 00:00:00 2001 From: Mark DeCrane Date: Mon, 9 Oct 2023 18:04:34 -0400 Subject: [PATCH 18/23] chore: update docs with feedback --- website/docs/cdktf/concepts/resources.mdx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/website/docs/cdktf/concepts/resources.mdx b/website/docs/cdktf/concepts/resources.mdx index 1e4dcf98f8..b275e05a64 100644 --- a/website/docs/cdktf/concepts/resources.mdx +++ b/website/docs/cdktf/concepts/resources.mdx @@ -376,7 +376,7 @@ When working with your infrastructure definitions and the need arises to refacto ### Performing Resource Moves -The `moveTo` function is available on all resources and is used for relocating a resource to the location specified by the string target `moveTarget`. To set the `moveTarget` for a resource, utilize the `addMoveTarget` function that is present on the resource to move to. +The `moveTo` function is available on all resources and is used for relocating a resource to the location specified by the string target `moveTarget`. To set a resource's `moveTarget`, use the `addMoveTarget` function that is present on the resource to move to. You can specify an arbitrary string for the `moveTarget`, but it must be unique within your stack. ```ts new S3Bucket(this, "test-bucket-move-to", { @@ -392,7 +392,7 @@ After deployment, both the resource being moved and the move target on the desti #### Move Targets -A `moveTarget` is accessible anywhere within the context of the stack where it is created. Whether it's set at the root of the stack or within a nested construct, you can access it accordingly. +A `moveTarget` is accessible anywhere within the context of the stack where it is created, including the root of the stack and within a nested construct. Moving resources to a different stack is not supported. ```ts new S3Bucket(this, "test-bucket-1", { @@ -417,7 +417,7 @@ After deploying the resource, you can update your resource to use the newly assi ### Enabling `foreach` on a Resource -If you wish to incorporate a deployed resource into a composition using `foreach`, you can achieve this without destroying the resource by specifying the desired index using the `moveTo` function. The index should correspond to the key found in the `TerraformIterator` named iterator +To incorporate a deployed resource into a `foreach` composition without destroying the resource, specify an index as a second argument in the `moveTo` function. The index should correspond to the key in the `TerraformIterator` named `iterator`. ```ts const iterator = TerraformIterator.fromMap({ From 1b58ca444ec57697eba85588dd0d0c049614b602 Mon Sep 17 00:00:00 2001 From: Mark DeCrane Date: Mon, 9 Oct 2023 18:51:02 -0400 Subject: [PATCH 19/23] chore: add plan and deploy flags for move example --- examples/typescript/aws-move/main.ts | 288 ++++++++--------------- packages/cdktf/lib/terraform-resource.ts | 4 +- 2 files changed, 102 insertions(+), 190 deletions(-) diff --git a/examples/typescript/aws-move/main.ts b/examples/typescript/aws-move/main.ts index 82ae2ca971..24efd0b58d 100644 --- a/examples/typescript/aws-move/main.ts +++ b/examples/typescript/aws-move/main.ts @@ -4,45 +4,16 @@ */ import { Construct } from "constructs"; -//import { App, TerraformStack } from "cdktf"; import { App, TerraformStack, TerraformIterator } from "cdktf"; import { AwsProvider } from "./.gen/providers/aws/provider"; import { S3Bucket } from "./.gen/providers/aws/s3-bucket"; -// UN-NESTING RESOURCE -> resource currently in nested construct, want to move it to higher layer - -// FIRST -> deploy, then comment out -/** -export class UnNestingMoveStack extends TerraformStack { - constructor(scope: Construct, id: string) { - super(scope, id); - - new AwsProvider(this, "aws", { - region: "us-west-2", - }); - new UnNestingConstructToMoveTo(this, "construct-to-move-to"); - } -} - -export class UnNestingConstructToMoveTo extends Construct { - constructor(scope: Construct, id: string) { - super(scope, id); - - new UnNestingNestedConstructToMoveTo(this, "nested-construct"); - } -} - -export class UnNestingNestedConstructToMoveTo extends Construct { - constructor(scope: Construct, id: string) { - super(scope, id); +/** + * To properly see the move functionality in action, the resource being moved needs to be deployed + * First run "deploy" with the DEPLOY env flag set, then "plan" with the PLAN env flag set + */ - new S3Bucket(this, "test-bucket-2", { - bucket: "test-move-bucket-name-1", - }); - } -} -*/ -// SECOND -> uncomment, then plan +// UN-NESTING RESOURCE -> resource currently in nested construct, want to move it to higher layer export class UnNestingMoveStack extends TerraformStack { constructor(scope: Construct, id: string) { super(scope, id); @@ -50,10 +21,15 @@ export class UnNestingMoveStack extends TerraformStack { new AwsProvider(this, "aws", { region: "us-west-2", }); - new S3Bucket(this, "test-bucket-1", { - bucket: "test-move-bucket-name-1", - }).addMoveTarget("move"); - new UnNestingConstructToMoveTo(this, "construct-to-move-to"); + if (process.env.PLAN) { + new S3Bucket(this, "test-bucket-1", { + bucket: "test-move-bucket-name-1", + }).addMoveTarget("move"); + new UnNestingConstructToMoveTo(this, "construct-to-move-to"); + } + if (process.env.DEPLOY) { + new UnNestingConstructToMoveTo(this, "construct-to-move-to"); + } } } @@ -67,49 +43,21 @@ export class UnNestingConstructToMoveTo extends Construct { export class UnNestingNestedConstructToMoveTo extends Construct { constructor(scope: Construct, id: string) { super(scope, id); - - new S3Bucket(this, "test-bucket-2", { - bucket: "test-move-bucket-name-1", - }).moveTo("move"); + if (process.env.PLAN) { + new S3Bucket(this, "test-bucket-2", { + bucket: "test-move-bucket-name-1", + }).moveTo("move"); + } + if (process.env.DEPLOY) { + new S3Bucket(this, "test-bucket-2", { + bucket: "test-move-bucket-name-1", + }); + } } } // UN-NESTING RESOURCE // NESTING RESOURCE -> resource currently at higher abstraction, want to move it into nested construct - -// FIRST -> deploy, then comment out -/** -export class NestingMoveStack extends TerraformStack { - constructor(scope: Construct, id: string) { - super(scope, id); - - new AwsProvider(this, "aws", { - region: "us-west-2", - }); - - new S3Bucket(this, "test-bucket-3", { - bucket: "test-move-bucket-name-3", - }); - - // TODO make new construct for this use case - new NestingConstructToMoveTo(this, "construct-to-move-to"); - } -} - -export class NestingConstructToMoveTo extends Construct { - constructor(scope: Construct, id: string) { - super(scope, id); - new NestingNestedConstructToMoveTo(this, "nested-construct"); - } -} - -export class NestingNestedConstructToMoveTo extends Construct { - constructor(scope: Construct, id: string) { - super(scope, id); - } -} -*/ -// SECOND -> uncomment, then plan export class NestingMoveStack extends TerraformStack { constructor(scope: Construct, id: string) { super(scope, id); @@ -118,17 +66,18 @@ export class NestingMoveStack extends TerraformStack { region: "us-west-2", }); - new S3Bucket(this, "test-bucket-3", { - bucket: "test-move-bucket-name-3", - }).moveTo("move"); - - new S3Bucket(this, "test-bucket-4", { - bucket: "test-move-bucket-name-4", - }).moveTo("move"); + if (process.env.PLAN) { + new S3Bucket(this, "test-bucket-3", { + bucket: "test-move-bucket-name-3", + }).moveTo("move"); + } + if (process.env.DEPLOY) { + new S3Bucket(this, "test-bucket-3", { + bucket: "test-move-bucket-name-3", + }); + } new NestingConstructToMoveTo(this, "construct-to-move-to"); - - // } } @@ -143,36 +92,18 @@ export class NestingConstructToMoveTo extends Construct { export class NestingNestedConstructToMoveTo extends Construct { constructor(scope: Construct, id: string) { super(scope, id); - - new S3Bucket(this, "test-bucket-3", { - bucket: "test-move-bucket-name-3", - }).addMoveTarget("move"); - new S3Bucket(this, "test-bucket-4", { - bucket: "test-move-bucket-name-4", - }).addMoveTarget("moveTo"); + if (process.env.PLAN) { + new S3Bucket(this, "test-bucket-3", { + bucket: "test-move-bucket-name-3", + }).addMoveTarget("move"); + } + if (process.env.DEPLOY) { + } } } // NESTING RESOURCE // MOVE INTO RESOURCE USING LIST ITERATOR - -// FIRST -> deploy, then comment out -/** -export class ListIteratorMoveStack extends TerraformStack { - constructor(scope: Construct, id: string) { - super(scope, id); - - new AwsProvider(this, "aws", { - region: "us-west-2", - }); - - new S3Bucket(this, "moved-bucket-list-iterator", { - bucket: "website-static-file-list-iterator-one", - }) - } -} -*/ -// SECOND -> uncomment, then plan export class ListIteratorMoveStack extends TerraformStack { constructor(scope: Construct, id: string) { super(scope, id); @@ -180,31 +111,34 @@ export class ListIteratorMoveStack extends TerraformStack { new AwsProvider(this, "aws", { region: "us-west-2", }); - - const iterator = TerraformIterator.fromList([ - "website-static-file-list-iterator-one", - "website-static-file-list-iterator-two", - ]); - - new S3Bucket(this, "complex-iterator-bucket", { - forEach: iterator, - bucket: iterator.value, - }).addMoveTarget("moveToResourceWithListIterator"); - - new S3Bucket(this, "moved-bucket-complex-iterator", { - bucket: "website-static-file-list-iterator-one", - }).moveTo( - "moveToResourceWithListIterator", - "website-static-file-list-iterator-one" - ); + if (process.env.PLAN) { + const iterator = TerraformIterator.fromList([ + "website-static-file-list-iterator-one", + "website-static-file-list-iterator-two", + ]); + + new S3Bucket(this, "complex-iterator-bucket", { + forEach: iterator, + bucket: iterator.value, + }).addMoveTarget("moveToResourceWithListIterator"); + + new S3Bucket(this, "moved-bucket-complex-iterator", { + bucket: "website-static-file-list-iterator-one", + }).moveTo( + "moveToResourceWithListIterator", + "website-static-file-list-iterator-one" + ); + } + if (process.env.DEPLOY) { + new S3Bucket(this, "moved-bucket-complex-iterator", { + bucket: "website-static-file-list-iterator-one", + }); + } } } // MOVE INTO RESOURCE USING LIST ITERATOR // MOVE INTO RESOURCE USING COMPLEX ITERATOR - -// FIRST -> deploy, then comment out -/** export class ComplexIteratorMoveStack extends TerraformStack { constructor(scope: Construct, id: string) { super(scope, id); @@ -212,64 +146,37 @@ export class ComplexIteratorMoveStack extends TerraformStack { new AwsProvider(this, "aws", { region: "us-west-2", }); - - new S3Bucket(this, "moved-bucket-complex-iterator", { - bucket: "website-static-file-complex-iterator", - tags: { app: "website" } - }) - } -} -*/ -// SECOND -> uncomment, then plan -export class ComplexIteratorMoveStack extends TerraformStack { - constructor(scope: Construct, id: string) { - super(scope, id); - - new AwsProvider(this, "aws", { - region: "us-west-2", - }); - - const complexIterator = TerraformIterator.fromMap({ - "website-static-files": { - name: "website-static-files", + if (process.env.PLAN) { + const complexIterator = TerraformIterator.fromMap({ + "website-static-files": { + name: "website-static-files", + tags: { app: "website" }, + }, + images: { name: "images", tags: { app: "image-converter" } }, + }); + + new S3Bucket(this, "complex-iterator-bucket", { + forEach: complexIterator, + bucket: complexIterator.getString("name"), + tags: complexIterator.getStringMap("tags"), + }).addMoveTarget("resourceWithComplexIterator"); + + new S3Bucket(this, "moved-bucket", { + bucket: "website-static-files", tags: { app: "website" }, - }, - images: { name: "images", tags: { app: "image-converter" } }, - }); - - new S3Bucket(this, "complex-iterator-bucket", { - forEach: complexIterator, - bucket: complexIterator.getString("name"), - tags: complexIterator.getStringMap("tags"), - }).addMoveTarget("resourceWithComplexIterator"); - - new S3Bucket(this, "moved-bucket", { - bucket: "website-static-files", - tags: { app: "website" }, - }).moveTo("resourceWithComplexIterator", "website-static-files"); + }).moveTo("resourceWithComplexIterator", "website-static-files"); + } + if (process.env.DEPLOY) { + new S3Bucket(this, "moved-bucket", { + bucket: "website-static-files", + tags: { app: "website" }, + }); + } } } // MOVE INTO RESOURCE USING COMPLEX ITERATOR // MOVE INTO RESOURCE USING COUNT -export class CountMoveStack extends TerraformStack { - constructor(scope: Construct, id: string) { - super(scope, id); - - new AwsProvider(this, "aws", { - region: "us-west-2", - }); - - new S3Bucket(this, "test-bucket", { - bucket: "test-move-bucket-name-1", - }); //.addTag("move"); - - // TODO make new construct for this use case - //new ConstructToMoveTo(this, "construct-to-move-to"); - } -} -// MOVE INTO RESOURCE USING COUNT -/** export class RenameResourceStack extends TerraformStack { constructor(scope: Construct, id: string) { super(scope, id); @@ -277,18 +184,23 @@ export class RenameResourceStack extends TerraformStack { new AwsProvider(this, "aws", { region: "us-west-2", }); - - new S3Bucket(this, "test-bucket", { - bucket: "test-bucket-rename", - }).renameResourceId("test-bucket-rename"); + if (process.env.PLAN) { + new S3Bucket(this, "test-bucket", { + bucket: "test-bucket-rename", + }).renameResourceId("test-bucket-rename"); + } + if (process.env.DEPLOY) { + new S3Bucket(this, "test-bucket", { + bucket: "test-bucket-rename", + }); + } } } -*/ const app = new App(); new UnNestingMoveStack(app, "un-nesting-move-stack"); new NestingMoveStack(app, "nesting-move-stack"); new ListIteratorMoveStack(app, "list-iterator-move-stack"); new ComplexIteratorMoveStack(app, "complex-iterator-move-stack"); -//new RenameResourceStack(app, "rename-stack"); +new RenameResourceStack(app, "rename-stack"); app.synth(); diff --git a/packages/cdktf/lib/terraform-resource.ts b/packages/cdktf/lib/terraform-resource.ts index 467140bfa5..55560a1d1b 100644 --- a/packages/cdktf/lib/terraform-resource.ts +++ b/packages/cdktf/lib/terraform-resource.ts @@ -227,7 +227,7 @@ export class TerraformResource ...(attributes["//"] ?? {}), ...this.constructNodeMetadata, }; - const movedBlock = this._buildMoveBlock(); + const movedBlock = this._buildMovedBlock(); return { resource: movedBlock && !movedBlock.renamed @@ -309,7 +309,7 @@ export class TerraformResource ); } - private _buildMoveBlock() { + private _buildMovedBlock() { // eslint-disable-next-line jsdoc/require-jsdoc function buildResourceMove({ resourceType, From 5203942ba4b137aa84cb4832ce1e66ca3294eb56 Mon Sep 17 00:00:00 2001 From: Mark DeCrane Date: Tue, 10 Oct 2023 15:17:22 -0400 Subject: [PATCH 20/23] chore: descope renameResourceId, move example and test improvement --- examples/typescript/aws-move/main.ts | 48 ++---- packages/cdktf/lib/terraform-element.ts | 11 +- .../cdktf/lib/terraform-resource-targets.ts | 2 +- packages/cdktf/lib/terraform-resource.ts | 162 ++++-------------- .../test/__snapshots__/resource.test.ts.snap | 72 -------- packages/cdktf/test/resource.test.ts | 52 +++--- website/docs/cdktf/concepts/resources.mdx | 14 +- 7 files changed, 74 insertions(+), 287 deletions(-) diff --git a/examples/typescript/aws-move/main.ts b/examples/typescript/aws-move/main.ts index 24efd0b58d..9fa175ccad 100644 --- a/examples/typescript/aws-move/main.ts +++ b/examples/typescript/aws-move/main.ts @@ -10,7 +10,7 @@ import { S3Bucket } from "./.gen/providers/aws/s3-bucket"; /** * To properly see the move functionality in action, the resource being moved needs to be deployed - * First run "deploy" with the DEPLOY env flag set, then "plan" with the PLAN env flag set + * First run "deploy" with the STEP_1 env flag set, then "plan" with the STEP_2 env flag set */ // UN-NESTING RESOURCE -> resource currently in nested construct, want to move it to higher layer @@ -21,13 +21,13 @@ export class UnNestingMoveStack extends TerraformStack { new AwsProvider(this, "aws", { region: "us-west-2", }); - if (process.env.PLAN) { + if (process.env.STEP_2) { new S3Bucket(this, "test-bucket-1", { bucket: "test-move-bucket-name-1", }).addMoveTarget("move"); new UnNestingConstructToMoveTo(this, "construct-to-move-to"); } - if (process.env.DEPLOY) { + if (process.env.STEP_1) { new UnNestingConstructToMoveTo(this, "construct-to-move-to"); } } @@ -43,12 +43,12 @@ export class UnNestingConstructToMoveTo extends Construct { export class UnNestingNestedConstructToMoveTo extends Construct { constructor(scope: Construct, id: string) { super(scope, id); - if (process.env.PLAN) { + if (process.env.STEP_2) { new S3Bucket(this, "test-bucket-2", { bucket: "test-move-bucket-name-1", }).moveTo("move"); } - if (process.env.DEPLOY) { + if (process.env.STEP_1) { new S3Bucket(this, "test-bucket-2", { bucket: "test-move-bucket-name-1", }); @@ -66,12 +66,12 @@ export class NestingMoveStack extends TerraformStack { region: "us-west-2", }); - if (process.env.PLAN) { + if (process.env.STEP_2) { new S3Bucket(this, "test-bucket-3", { bucket: "test-move-bucket-name-3", }).moveTo("move"); } - if (process.env.DEPLOY) { + if (process.env.STEP_1) { new S3Bucket(this, "test-bucket-3", { bucket: "test-move-bucket-name-3", }); @@ -92,12 +92,12 @@ export class NestingConstructToMoveTo extends Construct { export class NestingNestedConstructToMoveTo extends Construct { constructor(scope: Construct, id: string) { super(scope, id); - if (process.env.PLAN) { + if (process.env.STEP_2) { new S3Bucket(this, "test-bucket-3", { bucket: "test-move-bucket-name-3", }).addMoveTarget("move"); } - if (process.env.DEPLOY) { + if (process.env.STEP_1) { } } } @@ -111,7 +111,7 @@ export class ListIteratorMoveStack extends TerraformStack { new AwsProvider(this, "aws", { region: "us-west-2", }); - if (process.env.PLAN) { + if (process.env.STEP_2) { const iterator = TerraformIterator.fromList([ "website-static-file-list-iterator-one", "website-static-file-list-iterator-two", @@ -129,7 +129,7 @@ export class ListIteratorMoveStack extends TerraformStack { "website-static-file-list-iterator-one" ); } - if (process.env.DEPLOY) { + if (process.env.STEP_1) { new S3Bucket(this, "moved-bucket-complex-iterator", { bucket: "website-static-file-list-iterator-one", }); @@ -146,7 +146,7 @@ export class ComplexIteratorMoveStack extends TerraformStack { new AwsProvider(this, "aws", { region: "us-west-2", }); - if (process.env.PLAN) { + if (process.env.STEP_2) { const complexIterator = TerraformIterator.fromMap({ "website-static-files": { name: "website-static-files", @@ -166,7 +166,7 @@ export class ComplexIteratorMoveStack extends TerraformStack { tags: { app: "website" }, }).moveTo("resourceWithComplexIterator", "website-static-files"); } - if (process.env.DEPLOY) { + if (process.env.STEP_1) { new S3Bucket(this, "moved-bucket", { bucket: "website-static-files", tags: { app: "website" }, @@ -176,31 +176,9 @@ export class ComplexIteratorMoveStack extends TerraformStack { } // MOVE INTO RESOURCE USING COMPLEX ITERATOR -// MOVE INTO RESOURCE USING COUNT -export class RenameResourceStack extends TerraformStack { - constructor(scope: Construct, id: string) { - super(scope, id); - - new AwsProvider(this, "aws", { - region: "us-west-2", - }); - if (process.env.PLAN) { - new S3Bucket(this, "test-bucket", { - bucket: "test-bucket-rename", - }).renameResourceId("test-bucket-rename"); - } - if (process.env.DEPLOY) { - new S3Bucket(this, "test-bucket", { - bucket: "test-bucket-rename", - }); - } - } -} - const app = new App(); new UnNestingMoveStack(app, "un-nesting-move-stack"); new NestingMoveStack(app, "nesting-move-stack"); new ListIteratorMoveStack(app, "list-iterator-move-stack"); new ComplexIteratorMoveStack(app, "complex-iterator-move-stack"); -new RenameResourceStack(app, "rename-stack"); app.synth(); diff --git a/packages/cdktf/lib/terraform-element.ts b/packages/cdktf/lib/terraform-element.ts index 3709e1ece9..334fe4b112 100644 --- a/packages/cdktf/lib/terraform-element.ts +++ b/packages/cdktf/lib/terraform-element.ts @@ -76,14 +76,15 @@ export class TerraformElement extends Construct { private _friendlyUniqueId?: string; public get friendlyUniqueId() { - if (this._logicalIdOverride) { - this._friendlyUniqueId = this._logicalIdOverride; - } else if (!this._friendlyUniqueId) { - this._friendlyUniqueId = this.cdktfStack.getLogicalId(this); + if (!this._friendlyUniqueId) { + if (this._logicalIdOverride) { + this._friendlyUniqueId = this._logicalIdOverride; + } else { + this._friendlyUniqueId = this.cdktfStack.getLogicalId(this); + } } return this._friendlyUniqueId; } - /** * Overrides the auto-generated logical ID with a specific ID. * @param newLogicalId The new logical ID to use for this stack element. diff --git a/packages/cdktf/lib/terraform-resource-targets.ts b/packages/cdktf/lib/terraform-resource-targets.ts index 7055674c10..493d9d112e 100644 --- a/packages/cdktf/lib/terraform-resource-targets.ts +++ b/packages/cdktf/lib/terraform-resource-targets.ts @@ -32,7 +32,7 @@ export class TerraformResourceTargets { this._resourceTargetMap.set(target, resource); } - public getResourceAddressByTarget(target: string): TerraformResource { + public getResourceByTarget(target: string): TerraformResource { const result = this._resourceTargetMap.get(target); if (!result) { throw new Error(`Target "${target}" has not been set: diff --git a/packages/cdktf/lib/terraform-resource.ts b/packages/cdktf/lib/terraform-resource.ts index 55560a1d1b..6a2e543a7c 100644 --- a/packages/cdktf/lib/terraform-resource.ts +++ b/packages/cdktf/lib/terraform-resource.ts @@ -73,15 +73,11 @@ export interface TerraformResourceConfig extends TerraformMetaArguments { readonly terraformGeneratorMetadata?: TerraformProviderGeneratorMetadata; } -export interface TerraformResourceRefactor { +export interface TerraformResourceMove { readonly moveTarget: string; readonly index?: string | number; } -export interface TerraformResourceRename { - readonly newId: string; -} - export interface TerraformResourceImport { readonly id: string; readonly provider?: TerraformProvider; @@ -107,7 +103,7 @@ export class TerraformResource FileProvisioner | LocalExecProvisioner | RemoteExecProvisioner >; private _imported?: TerraformResourceImport; - private _moved?: TerraformResourceRefactor | TerraformResourceRename; + private _moved?: TerraformResourceMove; constructor(scope: Construct, id: string, config: TerraformResourceConfig) { super(scope, id, config.terraformResourceType); @@ -134,14 +130,6 @@ export class TerraformResource ); } - private isResourceRefactor(move: any): move is TerraformResourceRefactor { - return move !== undefined && "moveTarget" in move && `index` in move; - } - - private isResourceRename(move: any): move is TerraformResourceRename { - return this._moved !== undefined && "newId" in move; - } - public getStringAttribute(terraformAttribute: string) { return Token.asString(this.interpolationForAttribute(terraformAttribute)); } @@ -229,14 +217,13 @@ export class TerraformResource }; const movedBlock = this._buildMovedBlock(); return { - resource: - movedBlock && !movedBlock.renamed - ? undefined - : { - [this.terraformResourceType]: { - [this.friendlyUniqueId]: attributes, - }, + resource: movedBlock + ? undefined + : { + [this.terraformResourceType]: { + [this.friendlyUniqueId]: attributes, }, + }, moved: movedBlock ? [ { @@ -297,9 +284,7 @@ export class TerraformResource } private _getResourceTarget(moveTarget: string) { - return TerraformStack.of(this).moveTargets.getResourceAddressByTarget( - moveTarget - ); + return TerraformStack.of(this).moveTargets.getResourceByTarget(moveTarget); } private _addResourceTarget(moveTarget: string) { @@ -310,81 +295,26 @@ export class TerraformResource } private _buildMovedBlock() { - // eslint-disable-next-line jsdoc/require-jsdoc - function buildResourceMove({ - resourceType, - moveToId, - moveFromId, - index, - }: { - resourceType: string; - moveToId: string; - moveFromId: string; - index: string | number | undefined; - }): { to: string; from: string } { - const to = index - ? typeof index === "string" - ? `${resourceType}.${moveToId}["${index}"]` - : `${resourceType}.${moveToId}[${index}]` - : `${resourceType}.${moveToId}`; - const from = `${resourceType}.${moveFromId}`; - return { to, from }; - } - // eslint-disable-next-line jsdoc/require-jsdoc - function buildResourceRename({ - newResourceId, - moveFromId, - }: { - newResourceId: string; - moveFromId: string; - }): { newUniqueId: string; oldUniqueId: string } { - const oldUniqueId = moveFromId; - const idParts = oldUniqueId.split("."); - idParts[idParts.length - 1] = newResourceId; - const intialValue = idParts[0]; - idParts.shift(); - const newUniqueId = idParts.reduce( - (accum, curr) => accum + "." + curr, - intialValue - ); - return { newUniqueId, oldUniqueId }; + if (!this._moved) { + return undefined; } - - if (this.isResourceRefactor(this._moved)) { - const { moveTarget, index } = this._moved; - const resourceToMoveTo = this._getResourceTarget(moveTarget); - if ( - this.terraformResourceType !== resourceToMoveTo.terraformResourceType - ) { - throw new Error( - `You have tried to move a resource to a different type: + const { moveTarget, index } = this._moved; + const resourceToMoveTo = this._getResourceTarget(moveTarget); + if (this.terraformResourceType !== resourceToMoveTo.terraformResourceType) { + throw new Error( + `You have tried to move a resource to a different type: The move target "${moveTarget}" corresponding to the resource of type ${resourceToMoveTo.terraformResourceType} to move to differs from the resource of type ${this.terraformResourceType} being moved from ` - ); - } - const { to, from } = buildResourceMove({ - resourceType: this.terraformResourceType, - moveToId: resourceToMoveTo.friendlyUniqueId, - moveFromId: this.friendlyUniqueId, - index, - }); - return { to, from, renamed: false }; - } else if (this.isResourceRename(this._moved)) { - const { newId } = this._moved; - const { newUniqueId, oldUniqueId } = buildResourceRename({ - newResourceId: newId, - moveFromId: this.friendlyUniqueId, - }); - this.overrideLogicalId(newUniqueId); - return { - to: `${this.terraformResourceType}.${newUniqueId}`, - from: `${this.terraformResourceType}.${oldUniqueId}`, - renamed: true, - }; - } else { - return undefined; + ); } + const to = index + ? typeof index === "string" + ? `${this.terraformResourceType}.${resourceToMoveTo.friendlyUniqueId}["${index}"]` + : `${this.terraformResourceType}.${resourceToMoveTo.friendlyUniqueId}[${index}]` + : `${this.terraformResourceType}.${resourceToMoveTo.friendlyUniqueId}`; + const from = `${this.terraformResourceType}.${this.friendlyUniqueId}`; + return { to, from }; } /** @@ -394,18 +324,12 @@ export class TerraformResource */ public moveTo(moveTarget: string, index?: string | number) { if (this._moved) { - if (this.isResourceRefactor(this._moved)) { - throw new Error(`The resource ${this.friendlyUniqueId} has been given two moveTargets: "${this._moved.moveTarget}" and "${moveTarget}" - - Resources can only be moved once per plan/apply - `); - } - if (this.isResourceRename(this._moved)) { - throw new Error(`The resource ${this.friendlyUniqueId} has been renamed to "${this._moved.newId}" and given the moveTarget "${moveTarget}" - - If you wish to rename and move the resource, specify the change in ID in the instantiation of the targeted resource. - `); - } + throw new Error( + `The resource ${this.friendlyUniqueId} has been given two moveTargets: "${this._moved.moveTarget}" and "${moveTarget}" + + A resource can only be moved once per plan/apply + ` + ); } this._moved = { moveTarget, index }; this.node.addValidation( @@ -416,32 +340,6 @@ export class TerraformResource ); } - /** - * Renames the id of this resource to newId - * @param newId The new id to replace the current id - */ - public renameResourceId(newId: string) { - if (this.isResourceRefactor(this._moved)) { - throw new Error(`The resource ${this.friendlyUniqueId} has been renamed to "${newId}" and given the moveTarget "${this._moved.moveTarget}" - - If you wish to rename and move the resource, specify the change in ID in the instantiation of the targeted resource. - `); - } - if (this.isResourceRename(this._moved)) { - throw new Error(`The resource ${this.friendlyUniqueId} has been given two renames: "${this._moved.newId}" and "${newId}" - - Resources can only be renamed once per plan/apply - `); - } - this._moved = { newId }; - this.node.addValidation( - new ValidateTerraformVersion( - ">=1.5", - `Resource rename functionality is only supported for Terraform >=1.5. Please upgrade your Terraform version.` - ) - ); - } - /** * Adds a user defined moveTarget string to this resource to be later used in .moveTo(moveTarget) to resolve the location of the move. * @param moveTarget The string move target that will correspond to this resource diff --git a/packages/cdktf/test/__snapshots__/resource.test.ts.snap b/packages/cdktf/test/__snapshots__/resource.test.ts.snap index bdd4d61aa3..7a43ab856b 100644 --- a/packages/cdktf/test/__snapshots__/resource.test.ts.snap +++ b/packages/cdktf/test/__snapshots__/resource.test.ts.snap @@ -222,78 +222,6 @@ exports[`minimal configuration 1`] = ` }" `; -exports[`moves multiple resources 1`] = ` -"{ - "moved": [ - { - "from": "test_resource.simple", - "to": "test_resource.construct_nested-construct_simple_2C3755B0" - }, - { - "from": "test_resource.simple-2", - "to": "test_resource.construct_nested-construct_simple-2_078CE0AF" - } - ], - "provider": { - "test": [ - { - } - ] - }, - "resource": { - "test_resource": { - "construct_nested-construct_simple-2_078CE0AF": { - "name": "foo", - "provisioner": [ - { - "local-exec": { - "command": "echo 'hello' > world.txt" - } - }, - { - "local-exec": { - "command": "echo 'hello' > world1.txt" - } - }, - { - "local-exec": { - "command": "echo 'hello' > world2.txt" - } - } - ] - }, - "construct_nested-construct_simple_2C3755B0": { - "name": "foo", - "provisioner": [ - { - "local-exec": { - "command": "echo 'hello' > world.txt" - } - }, - { - "local-exec": { - "command": "echo 'hello' > world1.txt" - } - }, - { - "local-exec": { - "command": "echo 'hello' > world2.txt" - } - } - ] - } - } - }, - "terraform": { - "required_providers": { - "test": { - "version": "~> 2.0" - } - } - } -}" -`; - exports[`number[] attributes 1`] = ` "{ "output": { diff --git a/packages/cdktf/test/resource.test.ts b/packages/cdktf/test/resource.test.ts index 2a5e93f1c0..538a997b0b 100644 --- a/packages/cdktf/test/resource.test.ts +++ b/packages/cdktf/test/resource.test.ts @@ -515,33 +515,6 @@ it("moves resource to be in composition with foreach using complex iterator", () ); }); -it("moves resource to resource with rename", () => { - const app = Testing.app(); - const stack = new TerraformStack(app, "test"); - new TestProvider(stack, "provider", {}); - - new TestResource(stack, "simple", { - name: "foo", - provisioners: [ - { type: "local-exec", command: "echo 'hello' > world.txt" }, - { type: "local-exec", command: "echo 'hello' > world1.txt" }, - { type: "local-exec", command: "echo 'hello' > world2.txt" }, - ], - }).renameResourceId("simple-rename"); - - const synthedStack = JSON.parse(Testing.synth(stack)); - expect(synthedStack.moved[0].from).toEqual("test_resource.simple"); - expect(synthedStack.moved[0].to).toEqual("test_resource.simple-rename"); - expect(Object.keys(synthedStack.resource.test_resource)).toContain( - "simple-rename" - ); - // Must not include old resource being moved from - expect(Object.keys(synthedStack.resource.test_resource)).not.toContain( - "simple" - ); -}); - -// TODO: Add resource test for multiple move blocks and out of order tags and moves it("moves multiple resources", () => { const app = Testing.app(); const stack = new TerraformStack(app, "test"); @@ -585,8 +558,29 @@ it("moves multiple resources", () => { { type: "local-exec", command: "echo 'hello' > world2.txt" }, ], }).moveTo("test-2"); - - expect(Testing.synth(stack)).toMatchSnapshot(); + //console.log(Testing.synth(stack)) + const synthedStack = JSON.parse(Testing.synth(stack)); + expect(synthedStack.moved[0].from).toEqual("test_resource.simple"); + expect(synthedStack.moved[0].to).toEqual( + "test_resource.construct_nested-construct_simple_2C3755B0" + ); + expect(synthedStack.moved[1].from).toEqual("test_resource.simple-2"); + expect(synthedStack.moved[1].to).toEqual( + "test_resource.construct_nested-construct_simple-2_078CE0AF" + ); + expect(Object.keys(synthedStack.resource.test_resource)).toContain( + "construct_nested-construct_simple-2_078CE0AF" + ); + expect(Object.keys(synthedStack.resource.test_resource)).toContain( + "construct_nested-construct_simple_2C3755B0" + ); + // Must not include old resources being moved from + expect(Object.keys(synthedStack.resource.test_resource)).not.toContain( + "simple" + ); + expect(Object.keys(synthedStack.resource.test_resource)).not.toContain( + "simple-2" + ); }); it("moves correctly when target set after call to moveTo", () => { diff --git a/website/docs/cdktf/concepts/resources.mdx b/website/docs/cdktf/concepts/resources.mdx index b275e05a64..50110765d2 100644 --- a/website/docs/cdktf/concepts/resources.mdx +++ b/website/docs/cdktf/concepts/resources.mdx @@ -372,7 +372,7 @@ import imports.kubernetes.namespace.NamespaceMetadata; ## Refactoring & Renaming Resources -When working with your infrastructure definitions and the need arises to refactor or rename resources without destroying and recreating them, you can leverage the `moveTo` function. This section outlines how to perform resource moves, rename resources, and enable foreach on existing resources in your CDKTF project. +When working with your infrastructure definitions and the need arises to refactor or rename resources without destroying and recreating them, you can leverage the `moveTo` function. This section outlines how to perform resource moves and enable foreach on existing resources in your CDKTF project. ### Performing Resource Moves @@ -403,18 +403,6 @@ new S3Bucket(this, "test-bucket-1", { new NestedConstructToMoveTo(this, "construct-to-move-to"); ``` -### Renaming a Resource - -To rename a resource, you can simply use the `renameResourceId` function available on the resource. - -```ts -new S3Bucket(this, "bucket-id", { - bucket: "bucket-rename", -}).renameResourceId("bucket-new-id"); -``` - -After deploying the resource, you can update your resource to use the newly assigned resource ID, and the `renameResourceId` call can be safely removed. - ### Enabling `foreach` on a Resource To incorporate a deployed resource into a `foreach` composition without destroying the resource, specify an index as a second argument in the `moveTo` function. The index should correspond to the key in the `TerraformIterator` named `iterator`. From c2e2e993738b9602491f93a62a7116bda1bb3a3d Mon Sep 17 00:00:00 2001 From: Mark DeCrane Date: Fri, 13 Oct 2023 09:51:58 -0400 Subject: [PATCH 21/23] chore: update CHANGELOG, add upgrade guide, move resource refactor docs, python move example --- CHANGELOG.md | 4 + examples/python/aws-move/.gitignore | 3 + examples/python/aws-move/Pipfile | 10 ++ examples/python/aws-move/Pipfile.lock | 131 +++++++++++++++++ examples/python/aws-move/README.md | 70 +++++++++ examples/python/aws-move/cdktf.json | 11 ++ examples/python/aws-move/help | 22 +++ examples/python/aws-move/main.py | 30 ++++ examples/python/aws-move/package.json | 12 ++ examples/typescript/aws-move/main.ts | 2 +- website/docs/cdktf/concepts/resources.mdx | 48 +----- .../cdktf/examples-and-guides/refactoring.mdx | 137 +++++++++++------- .../cdktf/release/upgrade-guide-v0-19.mdx | 13 ++ 13 files changed, 391 insertions(+), 102 deletions(-) create mode 100644 examples/python/aws-move/.gitignore create mode 100644 examples/python/aws-move/Pipfile create mode 100644 examples/python/aws-move/Pipfile.lock create mode 100644 examples/python/aws-move/README.md create mode 100644 examples/python/aws-move/cdktf.json create mode 100644 examples/python/aws-move/help create mode 100755 examples/python/aws-move/main.py create mode 100644 examples/python/aws-move/package.json create mode 100644 website/docs/cdktf/release/upgrade-guide-v0-19.mdx diff --git a/CHANGELOG.md b/CHANGELOG.md index 4ed0d5197e..dd846423d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ Since the long-term support for Node.js 16 ended on 2023-09-11, we updated our minimum compatible Node.js version to 18.12. +### Potential provider naming collision with instance function `moveTo` on `TerraformResource` + +We have added support for resource refactoring and renaming with the addition of the instance function `moveTo` on `TerraformResource`. We forsee the potential for naming collision with providers using `moveTo` as an attribute. In instances where provider bindings fail to compile due to the collision, regenerate your provider bindings and replace the provider related usage of `moveTo` to `moveToAttribute` in your configuration if applicable. + ## 0.18.2 Fixes a bug in 0.18.1 that broke crash reporting due to a partial dependency upgrade. diff --git a/examples/python/aws-move/.gitignore b/examples/python/aws-move/.gitignore new file mode 100644 index 0000000000..97a62936eb --- /dev/null +++ b/examples/python/aws-move/.gitignore @@ -0,0 +1,3 @@ +dist/ +imports/ +terraform.tfstate* \ No newline at end of file diff --git a/examples/python/aws-move/Pipfile b/examples/python/aws-move/Pipfile new file mode 100644 index 0000000000..61782f1abd --- /dev/null +++ b/examples/python/aws-move/Pipfile @@ -0,0 +1,10 @@ +[[source]] +name = "pypi" +url = "https://pypi.org/simple" +verify_ssl = true + +[requires] +python_version = "3.7" + +[packages] +cdktf = {path = "./../../../dist/python/cdktf-0.0.0-py3-none-any.whl"} diff --git a/examples/python/aws-move/Pipfile.lock b/examples/python/aws-move/Pipfile.lock new file mode 100644 index 0000000000..d123c80175 --- /dev/null +++ b/examples/python/aws-move/Pipfile.lock @@ -0,0 +1,131 @@ +{ + "_meta": { + "hash": { + "sha256": "4d795221fae1915a3c9346d1137bbd6adb709356a0278af165e98d47c32e6ded" + }, + "pipfile-spec": 6, + "requires": { + "python_version": "3.7" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "attrs": { + "hashes": [ + "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04", + "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015" + ], + "markers": "python_version >= '3.7'", + "version": "==23.1.0" + }, + "cattrs": { + "hashes": [ + "sha256:b2bb14311ac17bed0d58785e5a60f022e5431aca3932e3fc5cc8ed8639de50a4", + "sha256:db1c821b8c537382b2c7c66678c3790091ca0275ac486c76f3c8f3920e83c657" + ], + "markers": "python_version >= '3.7'", + "version": "==23.1.2" + }, + "cdktf": { + "hashes": [ + "sha256:3883587406f408b46c77f9d3e179b8b2ba52506d3fbebc023e6cbda2d300958c" + ], + "path": "./../../../dist/python/cdktf-0.0.0-py3-none-any.whl", + "version": "==0.0.0" + }, + "constructs": { + "hashes": [ + "sha256:2972f514837565ff5b09171cfba50c0159dfa75ee86a42921ea8c86f2941b3d2", + "sha256:518551135ec236f9cc6b86500f4fbbe83b803ccdc6c2cb7684e0b7c4d234e7b1" + ], + "markers": "python_version ~= '3.7'", + "version": "==10.3.0" + }, + "exceptiongroup": { + "hashes": [ + "sha256:097acd85d473d75af5bb98e41b61ff7fe35efe6675e4f9370ec6ec5126d160e9", + "sha256:343280667a4585d195ca1cf9cef84a4e178c4b6cf2274caef9859782b567d5e3" + ], + "markers": "python_version < '3.11'", + "version": "==1.1.3" + }, + "importlib-metadata": { + "hashes": [ + "sha256:1aaf550d4f73e5d6783e7acb77aec43d49da8017410afae93822cc9cca98c4d4", + "sha256:cb52082e659e97afc5dac71e79de97d8681de3aa07ff18578330904a9d18e5b5" + ], + "markers": "python_version < '3.8'", + "version": "==6.7.0" + }, + "importlib-resources": { + "hashes": [ + "sha256:4be82589bf5c1d7999aedf2a45159d10cb3ca4f19b2271f8792bc8e6da7b22f6", + "sha256:7b1deeebbf351c7578e09bf2f63fa2ce8b5ffec296e0d349139d43cca061a81a" + ], + "markers": "python_version >= '3.7'", + "version": "==5.12.0" + }, + "jsii": { + "hashes": [ + "sha256:2fcc68d8cf88260bc8e502789d43ab46e7672b6f82d498ed62a52a4366fbccc5", + "sha256:e8a9a94c5116da96f11e79f16d4a290e1e7e1652b4addb8cce5c56f8ef570479" + ], + "markers": "python_version ~= '3.7'", + "version": "==1.90.0" + }, + "publication": { + "hashes": [ + "sha256:0248885351febc11d8a1098d5c8e3ab2dabcf3e8c0c96db1e17ecd12b53afbe6", + "sha256:68416a0de76dddcdd2930d1c8ef853a743cc96c82416c4e4d3b5d901c6276dc4" + ], + "version": "==0.0.3" + }, + "python-dateutil": { + "hashes": [ + "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86", + "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", + "version": "==2.8.2" + }, + "six": { + "hashes": [ + "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", + "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", + "version": "==1.16.0" + }, + "typeguard": { + "hashes": [ + "sha256:00edaa8da3a133674796cf5ea87d9f4b4c367d77476e185e80251cc13dfbb8c4", + "sha256:5e3e3be01e887e7eafae5af63d1f36c849aaa94e3a0112097312aabfa16284f1" + ], + "markers": "python_full_version >= '3.5.3'", + "version": "==2.13.3" + }, + "typing-extensions": { + "hashes": [ + "sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36", + "sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2" + ], + "markers": "python_version >= '3.7'", + "version": "==4.7.1" + }, + "zipp": { + "hashes": [ + "sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b", + "sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556" + ], + "markers": "python_version < '3.10'", + "version": "==3.15.0" + } + }, + "develop": {} +} diff --git a/examples/python/aws-move/README.md b/examples/python/aws-move/README.md new file mode 100644 index 0000000000..a002bbdcbe --- /dev/null +++ b/examples/python/aws-move/README.md @@ -0,0 +1,70 @@ +# python-aws + +A CDK for Terraform application in Python. + +## Usage + +Install Pipenv using Homebrew by running: + +```bash +$ brew install pipenv +``` + +You can install Pipenv by visiting the [website](https://pipenv.pypa.io/en/latest/). + +Install project dependencies + +```shell +pipenv install +``` + +Generate CDK for Terraform constructs for Terraform providers and modules used in the project. + +```bash +cdktf get +``` + +You can now edit the `main.py` file if you want to modify any code. + +```python +vim main.py +#!/usr/bin/env python +from constructs import Construct +from cdktf import App, TerraformStack +from imports.aws import SnsTopic, AwsProvider +from imports.terraform_aws_modules.vpc.aws import Vpc + +class MyStack(TerraformStack): + def __init__(self, scope: Construct, ns: str): + super().__init__(scope, ns) + + AwsProvider(self, 'Aws', region='eu-central-1') + + Vpc(self, 'CustomVpc', + name='custom-vpc', + cidr='10.0.0.0/16', + azs=["us-east-1a", "us-east-1b"], + public_subnets=["10.0.1.0/24", "10.0.2.0/24"] + ) + SnsTopic(self, 'Topic', display_name='my-first-sns-topic') + +app = App() +MyStack(app, "python-aws") + +app.synth() +``` + +Compile and generate Terraform configuration + +```bash +cdktf synth +``` + +The above command will create a folder called `cdktf.out` that contains all Terraform JSON configuration that was generated. + +Run cdktf-cli commands + +```bash +cdktf diff +cdktf deploy +``` diff --git a/examples/python/aws-move/cdktf.json b/examples/python/aws-move/cdktf.json new file mode 100644 index 0000000000..82622648bd --- /dev/null +++ b/examples/python/aws-move/cdktf.json @@ -0,0 +1,11 @@ +{ + "language": "python", + "app": "pipenv run python main.py", + "terraformProviders": [ + "aws@~> 3.0" + ], + "terraformModules": [ + "terraform-aws-modules/vpc/aws@2.77.0" + ], + "codeMakerOutput": "imports" +} \ No newline at end of file diff --git a/examples/python/aws-move/help b/examples/python/aws-move/help new file mode 100644 index 0000000000..4195bd516b --- /dev/null +++ b/examples/python/aws-move/help @@ -0,0 +1,22 @@ +======================================================================================================== + +Your cdktf Python project is ready! + +cat help Prints this message + +Compile: +pipenv run ./main.py Compile and run the python code. + +Synthesize: +cdktf synth Synthesize Terraform resources to cdktf.out/ + +Diff: +cdktf diff Perform a diff (terraform plan) for the given stack + +Deploy: +cdktf deploy Deploy the given stack + +Destroy: +cdktf destroy Destroy the given stack + +======================================================================================================== diff --git a/examples/python/aws-move/main.py b/examples/python/aws-move/main.py new file mode 100755 index 0000000000..a8422fd1f2 --- /dev/null +++ b/examples/python/aws-move/main.py @@ -0,0 +1,30 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +from constructs import Construct +from cdktf import App, TerraformStack +import os +from imports.aws.provider import AwsProvider +from imports.aws.s3_bucket import S3Bucket + +# To properly see the move functionality in action, the resource being moved needs to be deployed +# First run "deploy" with the STEP_1 env flag set, then "plan" or "deploy" with the STEP_2 env flag set + +class MyStack(TerraformStack): + def __init__(self, scope: Construct, ns: str): + super().__init__(scope, ns) + + AwsProvider(self, 'Aws', region='eu-central-1') + + if os.environ.get('STEP_1')=='True': + S3Bucket(self, "old-bucket", bucket='python-move-test-bucket') + + if os.environ.get('STEP_2')=='True': + S3Bucket(self, "old-bucket", bucket='python-move-test-bucket').move_to("move-s3") + S3Bucket(self, "new-bucket", bucket='python-move-test-bucket').add_move_target("move-s3") + + +app = App() +MyStack(app, "python-aws-move") + +app.synth() diff --git a/examples/python/aws-move/package.json b/examples/python/aws-move/package.json new file mode 100644 index 0000000000..bf77c1ba6a --- /dev/null +++ b/examples/python/aws-move/package.json @@ -0,0 +1,12 @@ +{ + "//": "This example test is disabled via the 'private' attribute since Terraform 1.5 is required for proper synth, and as of writing CI has a lesser version", + "private": true, + "name": "@examples/python-aws-move", + "version": "0.0.0", + "license": "MPL-2.0", + "scripts": { + "reinstall": "rm Pipfile.lock && PIPENV_IGNORE_VIRTUALENVS=1 pipenv install ./../../../dist/python/*.whl", + "build": "cdktf get", + "synth": "cdktf synth" + } +} \ No newline at end of file diff --git a/examples/typescript/aws-move/main.ts b/examples/typescript/aws-move/main.ts index 9fa175ccad..baba148df3 100644 --- a/examples/typescript/aws-move/main.ts +++ b/examples/typescript/aws-move/main.ts @@ -10,7 +10,7 @@ import { S3Bucket } from "./.gen/providers/aws/s3-bucket"; /** * To properly see the move functionality in action, the resource being moved needs to be deployed - * First run "deploy" with the STEP_1 env flag set, then "plan" with the STEP_2 env flag set + * First run "deploy" with the STEP_1 env flag set, then "plan" or "deploy" with the STEP_2 env flag set */ // UN-NESTING RESOURCE -> resource currently in nested construct, want to move it to higher layer diff --git a/website/docs/cdktf/concepts/resources.mdx b/website/docs/cdktf/concepts/resources.mdx index 50110765d2..b6eed04d42 100644 --- a/website/docs/cdktf/concepts/resources.mdx +++ b/website/docs/cdktf/concepts/resources.mdx @@ -372,11 +372,7 @@ import imports.kubernetes.namespace.NamespaceMetadata; ## Refactoring & Renaming Resources -When working with your infrastructure definitions and the need arises to refactor or rename resources without destroying and recreating them, you can leverage the `moveTo` function. This section outlines how to perform resource moves and enable foreach on existing resources in your CDKTF project. - -### Performing Resource Moves - -The `moveTo` function is available on all resources and is used for relocating a resource to the location specified by the string target `moveTarget`. To set a resource's `moveTarget`, use the `addMoveTarget` function that is present on the resource to move to. You can specify an arbitrary string for the `moveTarget`, but it must be unique within your stack. +When working with your infrastructure definitions and the need arises to refactor or rename resources without destroying and recreating them, you can leverage the `moveTo` function like so: ```ts new S3Bucket(this, "test-bucket-move-to", { @@ -388,47 +384,7 @@ new S3Bucket(this, "test-bucket-move-from", { }).moveTo("move-s3"); ``` -After deployment, both the resource being moved and the move target on the destination resource can be removed. - -#### Move Targets - -A `moveTarget` is accessible anywhere within the context of the stack where it is created, including the root of the stack and within a nested construct. Moving resources to a different stack is not supported. - -```ts -new S3Bucket(this, "test-bucket-1", { - bucket: "test-move-bucket-name-1", -}).moveTo("move"); - -// Contains resource with moveTarget "move" -new NestedConstructToMoveTo(this, "construct-to-move-to"); -``` - -### Enabling `foreach` on a Resource - -To incorporate a deployed resource into a `foreach` composition without destroying the resource, specify an index as a second argument in the `moveTo` function. The index should correspond to the key in the `TerraformIterator` named `iterator`. - -```ts -const iterator = TerraformIterator.fromMap({ - "website-static-files": { - name: "website-static-files", - tags: { app: "website" }, - }, - images: { name: "images", tags: { app: "image-converter" } }, -}); - -new S3Bucket(this, "iterator-bucket", { - forEach: iterator, - bucket: iterator.getString("name"), - tags: iterator.getStringMap("tags"), -}).addMoveTarget("resourceWithIterator"); - -new S3Bucket(this, "moved-bucket", { - bucket: "website-static-files", - tags: { app: "website" }, -}).moveTo("resourceWithIterator", "website-static-files"); -``` - -This allows you to efficiently integrate existing resources into a `foreach` composition without destroying the existing deployed resource. +Refer to our [Refactoring Guide](/terraform/cdktf/examples-and-guides/#moving-&-renaming-resources-within-a-stack) for more information ## Provisioners diff --git a/website/docs/cdktf/examples-and-guides/refactoring.mdx b/website/docs/cdktf/examples-and-guides/refactoring.mdx index 3f47d74464..82c669b6ad 100644 --- a/website/docs/cdktf/examples-and-guides/refactoring.mdx +++ b/website/docs/cdktf/examples-and-guides/refactoring.mdx @@ -8,9 +8,9 @@ description: >- You may need to move resources between stacks as your CDK for Terraform (CDKTF) application grows in size and complexity. This guide demonstrates how to refactor your stacks. In general you can change the names of stacks freely without an effect on the synthesized code. If you change the name of a resource this might lead to a re-creation of the resource, especially if you move the resource from one stack to another. -## Moving Resources Inside a Stack +## Moving & Renaming Resources Within a Stack -You may want to rename a stack deployed with an aws `S3Bucket` resource, like the following example. +You may want to rename a deployed resource in a stack, like the `S3Bucket` in the following example. ```typescript import { Construct } from "constructs"; @@ -26,14 +26,14 @@ class MyStack extends TerraformStack { region: "us-east-1", }); - // Old S3Bucket definition + // old S3Bucket definition // new S3Bucket(this, "my-bucket", { - // bucketPrefix: "my-bucket", + // bucketprefix: "my-bucket", // }); - // New S3Bucket definition + // new S3Bucket definition new S3Bucket(this, "new-bucket", { - bucketPrefix: "my-bucket", + bucketprefix: "my-bucket", }); } } @@ -56,69 +56,90 @@ refactoring-example # aws_s3_bucket.new-bucket (new-bucket) will be created Terraform plans to destroy the old bucket and create a new one to replace it. The replacement can be harmful if there is already state in the resource, such as files in the bucket or data in the database. -To avoid the recreation of the resource, use the [`terraform state mv`](/terraform/cli/commands/state/mv) command to move the state before the next apply. Before we can make the change, we need to find the Terraform name of the Resource. The name can be different from the one we have in the constructor, see the information below. +To avoid the recreation of the resource, use the `moveTo` function. -```shell-session -$ cat cdktf.out/stacks/refactoring-example/cdk.tf.json | jq '.resource.aws_s3_bucket' -{ - "my-bucket": { - "//": { - "metadata": { - "path": "refactoring-example/my-bucket", - "uniqueId": "my-bucket" - } - }, - "bucket_prefix": "my-bucket" - } -} -``` +```typescript +import { Construct } from "constructs"; +import { App, TerraformStack } from "cdktf"; +import { AwsProvider } from "@cdktf/provider-aws/lib/provider"; +import { S3Bucket } from "@cdktf/provider-aws/lib/s3-bucket"; -The id is the key of the object, in this case it is "new-bucket". If you have multiple resources of the same type, you can use the path to find the right one. Now change your code and synthesize it, so you can get the new name of the resource. +class MyStack extends TerraformStack { + constructor(scope: Construct, id: string) { + super(scope, id); -```shell-session -$ cdktf synth -$ cat cdktf.out/stacks/refactoring-example/cdk.tf.json | jq '.resource.aws_s3_bucket' -{ - "my-bucket": { - "//": { - "metadata": { - "path": "refactoring-example/new-bucket", - "uniqueId": "new-bucket" - } - }, - "bucket_prefix": "new-bucket" + new AwsProvider(this, "aws", { + region: "us-east-1", + }); + + // old S3Bucket definition + new S3Bucket(this, "my-bucket", { + bucketprefix: "my-bucket", + }).moveTo("new-s3-bucket"); + + // new S3Bucket definition + new S3Bucket(this, "new-bucket", { + bucketprefix: "my-bucket", + }).addMoveTarget("new-s3-bucket"); } } ``` -Now that we know the old name is "my-bucket" and the new name is "new-bucket" we can move the state. +### Performing Resource Moves -```shell-session -# We need to run the next steps in the synthesized folder for the stack. -$ cd cdktf.out/stacks/refactoring-example -$ terraform init -# move the state -$ terraform state mv aws_s3_bucket.my-bucket aws_s3_bucket.new-bucket -Move "aws_s3_bucket.my-bucket" to "aws_s3_bucket.new-bucket" -Successfully moved 1 object(s). -$ cd ../../.. # back to our root directory -``` +The `moveTo` function is available on all resources and is used for relocating a resource to the location specified by the string target `moveTarget`. To set a resource's `moveTarget`, use the `addMoveTarget` function that is present on the resource to move to. You can specify an arbitrary string for the `moveTarget`, but it must be unique within your stack. -Now you can apply the changes. +```ts +new S3Bucket(this, "test-bucket-move-to", { + bucket: "move-bucket-name", +}).addMoveTarget("move-s3"); -```shell-session -$ cdktf deploy -.... -refactoring-example aws_s3_bucket.new-bucket (new-bucket): Refreshing state... [id=my-bucket20221208132144348300000001] -refactoring-example No changes. Your infrastructure matches the configuration. -... +new S3Bucket(this, "test-bucket-move-from", { + bucket: "move-bucket-name", +}).moveTo("move-s3"); ``` -### Why Do I Need To Find The Terraform Name Of The Resource? +After deployment, both the resource being moved and the move target on the destination resource can be removed. -If you use Constructs to organize your code, you might have a level between the generated provider constructs and the `TerraformStack` construct to organize your code. +#### Move Targets -This extra level adds a prefix to the name of the resource to ensure uniqueness. Refer to [Constructs](/terraform/cdktf/concepts/constructs#scope) for more details. +A `moveTarget` is accessible anywhere within the context of the stack where it is created, including the root of the stack and within a nested construct. This workflow does not support moving resources to a different stack. + +```ts +new S3Bucket(this, "test-bucket-1", { + bucket: "test-move-bucket-name-1", +}).moveTo("move"); + +// Contains resource with moveTarget "move" +new NestedConstructToMoveTo(this, "construct-to-move-to"); +``` + +### Enabling `foreach` on a Resource + +To incorporate a deployed resource into a `foreach` composition without destroying the resource, specify an index as a second argument in the `moveTo` function. The index should correspond to the key in the `TerraformIterator` named `iterator`. + +```ts +const iterator = TerraformIterator.fromMap({ + "website-static-files": { + name: "website-static-files", + tags: { app: "website" }, + }, + images: { name: "images", tags: { app: "image-converter" } }, +}); + +new S3Bucket(this, "iterator-bucket", { + forEach: iterator, + bucket: iterator.getString("name"), + tags: iterator.getStringMap("tags"), +}).addMoveTarget("resourceWithIterator"); + +new S3Bucket(this, "moved-bucket", { + bucket: "website-static-files", + tags: { app: "website" }, +}).moveTo("resourceWithIterator", "website-static-files"); +``` + +This allows you to efficiently integrate existing resources into a `foreach` composition without destroying the existing deployed resource. ## Moving Resources From One Stack To Another @@ -270,3 +291,9 @@ $ cd ../../.. # Back to the root of the project # The next deploy should show no changes $ cdktf deploy '*' ``` + +### Why Do I Need To Find The Terraform Name Of The Resource? + +If you use Constructs to organize your code, you might have a level between the generated provider constructs and the `TerraformStack` construct to organize your code. + +This extra level adds a prefix to the name of the resource to ensure uniqueness. Refer to [Constructs](/terraform/cdktf/concepts/constructs#scope) for more details. diff --git a/website/docs/cdktf/release/upgrade-guide-v0-19.mdx b/website/docs/cdktf/release/upgrade-guide-v0-19.mdx new file mode 100644 index 0000000000..1367cae9dd --- /dev/null +++ b/website/docs/cdktf/release/upgrade-guide-v0-19.mdx @@ -0,0 +1,13 @@ +--- +page_title: Upgrading to CDKTF Version 0.19 +description: >- + Potential provider naming collision with new instance function `moveTo` +--- + +# Upgrading to CDK for Terraform Version 0.19 + +0.19 brings new workflows to import existing resources from cloud providers and refactor exisiting resources in your CDKTF project. + +## Potential provider naming collision with instance function `moveTo` on `TerraformResource` + +We have added support for resource refactoring and renaming with the addition of the instance function `moveTo` on `TerraformResource`. We forsee the potential for naming collision with providers using `moveTo` as an attribute. In instances where provider bindings fail to compile due to the collision, regenerate your provider bindings and replace the provider related usage of `moveTo` to `moveToAttribute` in your configuration if applicable. From d5d437f1385327b2607b079a841dfaa0f0de4731 Mon Sep 17 00:00:00 2001 From: Mark DeCrane Date: Wed, 11 Oct 2023 13:06:19 -0400 Subject: [PATCH 22/23] fix: add new upgrade guide to index --- website/docs/cdktf/release/index.mdx | 1 + 1 file changed, 1 insertion(+) diff --git a/website/docs/cdktf/release/index.mdx b/website/docs/cdktf/release/index.mdx index 8409cea97a..d259b6c53c 100644 --- a/website/docs/cdktf/release/index.mdx +++ b/website/docs/cdktf/release/index.mdx @@ -12,6 +12,7 @@ We release CDK for Terraform (CDKTF) regularly. The [CHANGELOG on Github](https: CDKTF includes upgrade guides for releases that have breaking changes. +- [Upgrading to v0.19](/terraform/cdktf/release/upgrade-guide-v0-19) - [Upgrading to v0.17](/terraform/cdktf/release/upgrade-guide-v0-17) - [Upgrading to v0.15](/terraform/cdktf/release/upgrade-guide-v0-15) - [Upgrading to v0.13](/terraform/cdktf/release/upgrade-guide-v0-13) From ca192c0d139b3f0902fda3e9a160e161959e816f Mon Sep 17 00:00:00 2001 From: Mark DeCrane Date: Wed, 11 Oct 2023 13:27:43 -0400 Subject: [PATCH 23/23] chore: add upgrade guide to nav data --- website/data/cdktf-nav-data.json | 50 +++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 10 deletions(-) diff --git a/website/data/cdktf-nav-data.json b/website/data/cdktf-nav-data.json index 4638796525..b4701e49af 100644 --- a/website/data/cdktf-nav-data.json +++ b/website/data/cdktf-nav-data.json @@ -1,6 +1,11 @@ [ - { "heading": "CDK for Terraform" }, - { "title": "Overview", "path": "" }, + { + "heading": "CDK for Terraform" + }, + { + "title": "Overview", + "path": "" + }, { "title": "Get Started", "href": "https://learn.hashicorp.com/tutorials/terraform/cdktf-install?in=terraform/cdktf" @@ -86,12 +91,18 @@ { "title": "Create and Deploy Applications", "routes": [ - { "title": "Project Setup", "path": "create-and-deploy/project-setup" }, + { + "title": "Project Setup", + "path": "create-and-deploy/project-setup" + }, { "title": "Configuration File", "path": "create-and-deploy/configuration-file" }, - { "title": "Best Practices", "path": "create-and-deploy/best-practices" }, + { + "title": "Best Practices", + "path": "create-and-deploy/best-practices" + }, { "title": "Environment Variables", "path": "create-and-deploy/environment-variables" @@ -134,8 +145,14 @@ { "title": "Test and Debug", "routes": [ - { "title": "Unit Tests", "path": "test/unit-tests" }, - { "title": "Debugging", "path": "test/debugging" } + { + "title": "Unit Tests", + "path": "test/unit-tests" + }, + { + "title": "Debugging", + "path": "test/debugging" + } ] }, { @@ -145,7 +162,10 @@ "title": "CLI Configuration", "path": "cli-reference/cli-configuration" }, - { "title": "Commands", "path": "cli-reference/commands" } + { + "title": "Commands", + "path": "cli-reference/commands" + } ] }, { @@ -188,6 +208,10 @@ "title": "Overview", "path": "release" }, + { + "title": "Upgrading to Version 0.19", + "path": "release/upgrade-guide-v0-19" + }, { "title": "Upgrading to Version 0.18", "path": "release/upgrade-guide-v0-18" @@ -230,6 +254,12 @@ } ] }, - { "title": "Community", "path": "community" }, - { "title": "Telemetry", "path": "telemetry" } -] + { + "title": "Community", + "path": "community" + }, + { + "title": "Telemetry", + "path": "telemetry" + } +] \ No newline at end of file