From 492c4c456695b97354212fdea97ab77e16d7d861 Mon Sep 17 00:00:00 2001 From: William Putra Intan <61998484+williamputraintan@users.noreply.github.com> Date: Wed, 29 Nov 2023 18:13:52 +1100 Subject: [PATCH] Init for MetadataManager (#67) --- .../stateless/metadata_manager/src/.gitignore | 2 + .../stateless/metadata_manager/src/Dockerfile | 14 + .../stateless/metadata_manager/src/Makefile | 59 + .../stateless/metadata_manager/src/README.md | 177 +- .../metadata_manager/src/compose.yaml | 28 + .../metadata_manager/src/dbschema/audit.esdl | 21 +- .../src/dbschema/metadata.esdl | 47 +- .../src/dbschema/migrations/00001.edgeql | 35 +- .../audit/insertSystemAuditEvent.edgeql | 2 - .../audit/updateSystemAuditEvent.edgeql | 2 - .../library/deleteLibraryByOrcaBusId.edgeql | 2 + .../library/insertLibraryQuery.edgeql | 8 +- .../library/selectAllLibraryQuery.edgeql | 3 + ... => selectLibraryByInternalIdQuery.edgeql} | 0 .../library/updateLibraryQuery.edgeql | 14 +- .../specimen/deleteSpecimenByOrcaBusId.edgeql | 2 + .../specimen/selectAllSpecimenQuery.edgeql | 3 + ...=> selectSpecimenByInternalIdQuery.edgeql} | 0 .../specimen/updateSpecimenQuery.edgeql | 6 +- .../subject/deleteSubjectByOrcaBusId.edgeql | 2 + .../subject/selectAllSubjectQuery.edgeql | 3 + ... => selectSubjectByInternalIdQuery.edgeql} | 0 .../subject/updateSubjectQuery.edgeql | 4 +- .../metadata_manager/src/deploy/.gitignore | 10 + .../metadata_manager/src/deploy/.npmignore | 6 + .../metadata_manager/src/deploy/README.md | 14 + .../src/deploy/asset/README.md | 49 + .../metadata_manager/src/deploy/bin/deploy.ts | 40 + .../metadata_manager/src/deploy/cdk.json | 63 + .../src/deploy/construct/app/Dockerfile | 46 + .../src/deploy/construct/app/app-construct.ts | 174 + .../src/deploy/construct/edge-db/Dockerfile | 8 + .../construct/edge-db/edge-db-construct.ts | 105 + ...dge-db-load-balancer-protocol-construct.ts | 102 + .../edge-db/edge-db-service-construct.ts | 219 + .../construct/postgres-rds/base-database.ts | 64 + .../infrastructure-stack-database-props.ts | 92 + .../postgres-rds/postgres-db-construct.ts | 122 + .../src/deploy/jest.config.js | 8 + .../src/deploy/lib/metadataManagerStack.ts | 105 + .../src/deploy/package-lock.json | 7466 +++++++++++++++++ .../metadata_manager/src/deploy/package.json | 29 + .../src/deploy/test/deploy.test.ts | 16 + .../metadata_manager/src/deploy/tsconfig.json | 31 + .../src/docs/edgedb-schema.png | Bin 0 -> 115496 bytes .../src/docs/relationship.drawio.svg | 87 + .../metadata_manager/src/edgedb.toml | 2 - .../src/{jest.config.ts => jest.config.js} | 3 +- .../metadata_manager/src/package.json | 17 +- .../src/src/api/routes/graphql-routes.ts | 43 + .../src/src/api/routes/internal-routes.ts | 19 +- .../stateless/metadata_manager/src/src/app.ts | 28 +- .../src/src/bootstrap/dependency-injection.ts | 24 +- .../src/src/handler/server.ts | 16 + .../metadata_manager/src/src/handler/sync.ts | 29 + .../metadata_manager/src/src/index.ts | 2 +- .../src/src/service/helpers/audit-helper.ts | 6 +- .../helpers/metadata/library-helper.ts | 10 +- .../src/service/loader-method/googleSheet.ts | 320 +- .../src/src/service/metadata-loader.ts | 11 - .../src/src/service/metadata.ts | 358 + .../src/src/test-data/index.ts | 27 + .../src/src/test-data/scenario-1.ts | 12 - .../src/src/test-data/scenarios/metadata.xlsx | Bin 0 -> 12660 bytes .../src/src/test-data/scenarios/scenario-1.ts | 18 + .../src/src/test-data/scenarios/scenario-2.ts | 37 + .../src/src/test-data/utils.ts | 8 + .../metadata_manager/src/src/utils.ts | 38 + .../src/tests/service/gsheet.test.ts | 94 - .../service/{ => loader}/gsheet.common.ts | 15 +- .../src/tests/service/loader/gsheet.test.ts | 34 + .../src/tests/service/metadata.common.ts | 59 + .../src/tests/service/metadata.test.ts | 153 + .../tests/service/test-dependency.common.ts | 15 +- .../metadata_manager/src/tsconfig.json | 7 +- .../stateless/metadata_manager/src/yarn.lock | 1562 ++-- 76 files changed, 10659 insertions(+), 1598 deletions(-) create mode 100644 lib/workload/stateless/metadata_manager/src/Dockerfile create mode 100644 lib/workload/stateless/metadata_manager/src/Makefile create mode 100644 lib/workload/stateless/metadata_manager/src/compose.yaml create mode 100644 lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/library/deleteLibraryByOrcaBusId.edgeql create mode 100644 lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/library/selectAllLibraryQuery.edgeql rename lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/library/{selectLibraryByIdQuery.edgeql => selectLibraryByInternalIdQuery.edgeql} (100%) create mode 100644 lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/specimen/deleteSpecimenByOrcaBusId.edgeql create mode 100644 lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/specimen/selectAllSpecimenQuery.edgeql rename lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/specimen/{selectSpecimenByIdQuery.edgeql => selectSpecimenByInternalIdQuery.edgeql} (100%) create mode 100644 lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/subject/deleteSubjectByOrcaBusId.edgeql create mode 100644 lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/subject/selectAllSubjectQuery.edgeql rename lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/subject/{selectSubjectByIdQuery.edgeql => selectSubjectByInternalIdQuery.edgeql} (100%) create mode 100644 lib/workload/stateless/metadata_manager/src/deploy/.gitignore create mode 100644 lib/workload/stateless/metadata_manager/src/deploy/.npmignore create mode 100644 lib/workload/stateless/metadata_manager/src/deploy/README.md create mode 100644 lib/workload/stateless/metadata_manager/src/deploy/asset/README.md create mode 100644 lib/workload/stateless/metadata_manager/src/deploy/bin/deploy.ts create mode 100644 lib/workload/stateless/metadata_manager/src/deploy/cdk.json create mode 100644 lib/workload/stateless/metadata_manager/src/deploy/construct/app/Dockerfile create mode 100644 lib/workload/stateless/metadata_manager/src/deploy/construct/app/app-construct.ts create mode 100644 lib/workload/stateless/metadata_manager/src/deploy/construct/edge-db/Dockerfile create mode 100644 lib/workload/stateless/metadata_manager/src/deploy/construct/edge-db/edge-db-construct.ts create mode 100644 lib/workload/stateless/metadata_manager/src/deploy/construct/edge-db/edge-db-load-balancer-protocol-construct.ts create mode 100644 lib/workload/stateless/metadata_manager/src/deploy/construct/edge-db/edge-db-service-construct.ts create mode 100644 lib/workload/stateless/metadata_manager/src/deploy/construct/postgres-rds/base-database.ts create mode 100644 lib/workload/stateless/metadata_manager/src/deploy/construct/postgres-rds/infrastructure-stack-database-props.ts create mode 100644 lib/workload/stateless/metadata_manager/src/deploy/construct/postgres-rds/postgres-db-construct.ts create mode 100644 lib/workload/stateless/metadata_manager/src/deploy/jest.config.js create mode 100644 lib/workload/stateless/metadata_manager/src/deploy/lib/metadataManagerStack.ts create mode 100644 lib/workload/stateless/metadata_manager/src/deploy/package-lock.json create mode 100644 lib/workload/stateless/metadata_manager/src/deploy/package.json create mode 100644 lib/workload/stateless/metadata_manager/src/deploy/test/deploy.test.ts create mode 100644 lib/workload/stateless/metadata_manager/src/deploy/tsconfig.json create mode 100644 lib/workload/stateless/metadata_manager/src/docs/edgedb-schema.png create mode 100644 lib/workload/stateless/metadata_manager/src/docs/relationship.drawio.svg delete mode 100644 lib/workload/stateless/metadata_manager/src/edgedb.toml rename lib/workload/stateless/metadata_manager/src/{jest.config.ts => jest.config.js} (69%) create mode 100644 lib/workload/stateless/metadata_manager/src/src/api/routes/graphql-routes.ts create mode 100644 lib/workload/stateless/metadata_manager/src/src/handler/server.ts create mode 100644 lib/workload/stateless/metadata_manager/src/src/handler/sync.ts delete mode 100644 lib/workload/stateless/metadata_manager/src/src/service/metadata-loader.ts create mode 100644 lib/workload/stateless/metadata_manager/src/src/service/metadata.ts create mode 100644 lib/workload/stateless/metadata_manager/src/src/test-data/index.ts delete mode 100644 lib/workload/stateless/metadata_manager/src/src/test-data/scenario-1.ts create mode 100644 lib/workload/stateless/metadata_manager/src/src/test-data/scenarios/metadata.xlsx create mode 100644 lib/workload/stateless/metadata_manager/src/src/test-data/scenarios/scenario-1.ts create mode 100644 lib/workload/stateless/metadata_manager/src/src/test-data/scenarios/scenario-2.ts create mode 100644 lib/workload/stateless/metadata_manager/src/src/test-data/utils.ts create mode 100644 lib/workload/stateless/metadata_manager/src/src/utils.ts delete mode 100644 lib/workload/stateless/metadata_manager/src/tests/service/gsheet.test.ts rename lib/workload/stateless/metadata_manager/src/tests/service/{ => loader}/gsheet.common.ts (88%) create mode 100644 lib/workload/stateless/metadata_manager/src/tests/service/loader/gsheet.test.ts create mode 100644 lib/workload/stateless/metadata_manager/src/tests/service/metadata.common.ts create mode 100644 lib/workload/stateless/metadata_manager/src/tests/service/metadata.test.ts diff --git a/lib/workload/stateless/metadata_manager/src/.gitignore b/lib/workload/stateless/metadata_manager/src/.gitignore index 30578c9f3..5385865a2 100644 --- a/lib/workload/stateless/metadata_manager/src/.gitignore +++ b/lib/workload/stateless/metadata_manager/src/.gitignore @@ -137,3 +137,5 @@ dist dbschema/edgeql-js dbschema/queries.* dbschema/interfaces.ts + +asset/ \ No newline at end of file diff --git a/lib/workload/stateless/metadata_manager/src/Dockerfile b/lib/workload/stateless/metadata_manager/src/Dockerfile new file mode 100644 index 000000000..2e79a6598 --- /dev/null +++ b/lib/workload/stateless/metadata_manager/src/Dockerfile @@ -0,0 +1,14 @@ +FROM node:20 +WORKDIR /app + +COPY Makefile package.json yarn.lock tsconfig.json jest.config.js ./ +COPY src/ ./src/ +COPY tests/ ./tests/ + +COPY dbschema/queries ./dbschema/queries +COPY dbschema/migrations ./dbschema/migrations +COPY dbschema/*.esdl ./dbschema/ + +RUN make install + +ENTRYPOINT [ "make", "start", "EDGEDB_HOST=edgedb" ] diff --git a/lib/workload/stateless/metadata_manager/src/Makefile b/lib/workload/stateless/metadata_manager/src/Makefile new file mode 100644 index 000000000..ce22a2867 --- /dev/null +++ b/lib/workload/stateless/metadata_manager/src/Makefile @@ -0,0 +1,59 @@ +EDGEDB_HOST ?= localhost + +# Installation +install: + @yarn install + +# To run docker compose +up: + @docker compose up -d + +down: + @docker compose down + +stop: + @docker compose down + +# Build the app for deployment + +edgetypes: + @npx generate queries --target ts --file --dsn edgedb://orcabus_admin:admin@$(EDGEDB_HOST):5656 --tls-security insecure # pragma: allowlist secret + @npx generate edgeql-js --target ts --output-dir dbschema/edgeql-js --dsn edgedb://orcabus_admin:admin@$(EDGEDB_HOST):5656 --tls-security insecure # pragma: allowlist secret + @npx generate interfaces --file dbschema/interfaces.ts --dsn edgedb://orcabus_admin:admin@$(EDGEDB_HOST):5656 --tls-security insecure # pragma: allowlist secret + +build: edgetypes + @rm -rf asset + @mkdir -p asset + @yarn run build-src + @cd dist && zip -r ../asset/src.zip . + + @mkdir -p nodejs + @cp -r node_modules ./nodejs + @zip -r asset/dependency.zip nodejs + @rm -rf nodejs + + +# Testing +test: + @yarn test + +# Starting server +start: edgetypes + @yarn start +start-scenario-1: edgetypes + @yarn run insert-scenario-1 + @yarn start + +# Inserting scenarios +insert-scenario-2: + @yarn run insert-scenario-2 + +# Shortcut of edgedb cli +edgedb: + @edgedb --dsn edgedb://orcabus_admin:admin@$(EDGEDB_HOST):5656 --tls-security insecure # pragma: allowlist secret +edgedb-ui: + @edgedb ui --dsn edgedb://orcabus_admin:admin@$(EDGEDB_HOST):5656 --tls-security insecure --no-server-check # pragma: allowlist secret +edgedb-migrate: + @edgedb migrate --dsn edgedb://orcabus_admin:admin@$(EDGEDB_HOST):5656 --tls-security insecure # pragma: allowlist secret +edgedb-migration-create: + @edgedb migration create --dsn edgedb://orcabus_admin:admin@$(EDGEDB_HOST):5656 --tls-security insecure # pragma: allowlist secret diff --git a/lib/workload/stateless/metadata_manager/src/README.md b/lib/workload/stateless/metadata_manager/src/README.md index 8c307890f..1ab73fa47 100644 --- a/lib/workload/stateless/metadata_manager/src/README.md +++ b/lib/workload/stateless/metadata_manager/src/README.md @@ -1,46 +1,171 @@ -# Metadata manager +# Metadata Manager for OrcaBus -The `MetadataManager` is one of the microservice within the UMCCR OrcaBus that manages the metadata records used for the -BioInformatics pipelines. The service will be responsible to make records to stay up to date and able to sync records -from multiple sources. +One of the microservices in the Orcabus handles all the metadata information. -## Development +## Schema -### Git Checkout -As this microservice is part of a monorepo from the main OrcaBus project, the process Git Flow process -will follow on the root of this project. +The EdgeDb schema looks like this as follows. You could also open this view with the make command: `make edgedb-ui` (see development +section below) -### Development +![schema](./docs/edgedb-schema.png) + +Relationship between schema + +![relationship](docs/relationship.drawio.svg) + +The mapping between the metadata spreadsheet to the schema are +| Metadata Header | Table | Field Name | +|-------------------|----------------------|------------| +| SubjectID | `metadata::Subject` | internalId | +| ExternalSubjectID | `metadata::Subject` | externalId | +| SampleID | `metadata::Specimen` | internalId | +| ExternalSampleID | `metadata::Specimen` | externalId | +| Source | `metadata::Specimen` | source | +| LibraryID | `metadata::Library` | internalId | +| Phenotype | `metadata::Library` | phenotype | +| Quality | `metadata::Library` | quality | +| Type | `metadata::Library` | type | +| Assay | `metadata::Library` | assay | +| Workflow | `metadata::Library` | workflow | +| Coverage (X) | `metadata::Library` | coverage | + +Notes: + +- The `orcabusId` is constructed uniquely for ocabusId with the structure of prefixes either `spc.`, `lib.`, `sbj.` + (for specimen, library, and subject, respectively) and followed by [ulid](https://github.com/ulid/spec) id. -#### Setup + e.g. `sbj.01HF6B4D6GHCYT3ZVF0S6087W3` +- The audit event schema will record the generation of success/failure of an insertion/deletion. + + ```curl + select audit::AuditEvent {*} filter .id='04ec4232-82be-11ee-870c-6b78b11f565f'; + { + audit::SystemAuditEvent { + id: 04ec4232-82be-11ee-870c-6b78b11f565f, + actionCategory: C, + actionDescription: 'Insert new subject record: sbj.01HF6B4DJPWGYZK8RZDN9BK454', + actionOutcome: success, + details: Json("{\"id\": \"04f3ea1e-82be-11ee-870c-4f6a4d334d37\", \"orcaBusId\": \"sbj.01HF6B4DJPWGYZK8RZDN9BK454\", \"externalId\": \"EXTSUB002\", \"internalId\": \"SBJ220002\"}"), + updatedDateTime: '2023-11-14T07:18:33.366109Z', + }, + } + ``` -Change the terminal directory from the OrcaBus root to this directory: +## Local Deployment + +Requirement: + +- Docker +- Node.js with Yarn + +```bash +docker -v +Docker version 20.10.12, build e91ed5707e + +node -v +v20.9.0 ``` -cd lib/workload/stateless/metadata_manager/src + +### Installation + +To install dependency, yarn is needed for this purpose + +```bash +npm i -g yarn ``` -Requirement for this project: - - nodejs - - edgedb (see ) +To install all dependencies, a make file is provided and can be done by: -To install the dependency of this project +```bash +make install ``` -yarn + +### Start + + +To start the database and server use the following make command. This will run the server and database in +docker-compose. The server will run at port 8080. (http://localhost:8080). +The database used here is [EdgeDb](https://www.edgedb.com/) which is a graph-relational database that uses SQL as their +underlying database. The configuration for this has been bundled up into a docker-compose and could be run as follows. + +```bash +make up ``` -Setup the database + +To start the server up use the following command + +```bash +make start ``` -yarn init-db -yarn migrate-db + +We could also start data by resetting and inserting some mock test data. + +```bash +make start-scenario-1 ``` -#### Build -```yarn edgetypes``` +This should run at localhost port 8080. Valid endpoints are as follows + +```bash + +http://localhost:8080/subject +http://localhost:8080/library +http://localhost:8080/specimen + + + +http://localhost:8080/graphql/explore (UI) +http://localhost:8080/graphql (Only for graphql POST method) +``` + +If you need to serve from existing metadata locally. You could copy and paste +the `.xlsx` file into [./src/test-data/scenarios/metadata.xlsx](./src/test-data/scenarios/metadata.xlsx). +Then to dump and reload with this metadata spreadsheet run the following: + +```bash +make insert-scenario-2 +``` + +### Testing + +```bash +make test + +Test Suites: 2 passed, 2 total +Tests: 6 passed, 6 total +Snapshots: 0 total +Time: 36.073 s +``` + +### Build + +To build for deployment the following will generate assets that could be deployed to lambdas. +For more details on the deployment [deploy-readme](./deploy/README.md). + +```bash +make build +``` + +### Development + +edgedb-cli is expected to be installed in the dev environment. See the [installation guide](https://www.edgedb.com/install#macos-homebrew) for details. + +Homebrew user: + +```curl +brew tap edgedb/tap +brew install edgedb-cli +``` +Since the EdgeDb is running in a container, some EdgeDb commands will need to pass in their connection parameter +to get connected with the container. Some make commands are added in the makefile for convenience. -### Run -```yarn watch``` +List available makefile command equivalent to edgedb-cli: -#### Testing -```yarn test``` +- `make edgedb` (`edgedb`)- to run EdgeDb +- `make edgedb-ui` (`edgedb ui`) - to open EdgeDb UI (username: `orcabus_admin`; password: `admin`) // pragma: allowlist secret +- `make edgedb-migrate` (`edgedb migrate`) - to apply new migration +- `make edgedb-migration-create` (`edgedb migration create`) - to create new migrations +- `make edgetypes` - to make EdgeDb files (e.g. `*.edgeql`) recognizable by typescript diff --git a/lib/workload/stateless/metadata_manager/src/compose.yaml b/lib/workload/stateless/metadata_manager/src/compose.yaml new file mode 100644 index 000000000..d4706e841 --- /dev/null +++ b/lib/workload/stateless/metadata_manager/src/compose.yaml @@ -0,0 +1,28 @@ +version: '3.8' +services: + edgedb: + image: edgedb/edgedb:3.5 + environment: + EDGEDB_DOCKER_LOG_LEVEL: 'debug' + EDGEDB_SERVER_SECURITY: insecure_dev_mode + EDGEDB_SERVER_ADMIN_UI: enabled + EDGEDB_SERVER_USER: 'orcabus_admin' + EDGEDB_SERVER_PASSWORD: 'admin' # pragma: allowlist secret + volumes: + - './dbschema:/dbschema' + ports: + - '5656:5656' + + app: + build: . + environment: + # EdgedDb related config + EDGEDB_HOST: edgedb + + # Fastify config + PORT: '8080' + HOST: '0.0.0.0' + ports: + - '8080:8080' + links: + - edgedb diff --git a/lib/workload/stateless/metadata_manager/src/dbschema/audit.esdl b/lib/workload/stateless/metadata_manager/src/dbschema/audit.esdl index 729b1acb3..b4d09a7c8 100644 --- a/lib/workload/stateless/metadata_manager/src/dbschema/audit.esdl +++ b/lib/workload/stateless/metadata_manager/src/dbschema/audit.esdl @@ -1,9 +1,10 @@ +using extension graphql; module audit { # NOTE: TODO How to query deleted library?? # ActionType definition - # Ref: http://hl7.org/fhir/audit-even t-action + # Ref: http://hl7.org/fhir/audit-event-action scalar type ActionType extending enum<'C', 'R', 'U', 'D', 'E'>; # ActionOutcome definition @@ -18,36 +19,18 @@ module audit { # any details will appear later in the details JSON required actionDescription: str; - # when this audit record has been made (should be close to occurredDateTime) - required recordedDateTime: datetime { - default := datetime_current(); - readonly := true; - } - required occurredDateTime: datetime { - default := datetime_current(); - } - required occurredDuration: duration { - rewrite insert, update using ( - select __subject__.occurredDateTime - __subject__.recordedDateTime - ) - } - # when this audit record is last updated (e.g. completion/failure of an event) # Using `rewrite` to re-update this automatically required updatedDateTime: datetime { rewrite insert, update using (datetime_of_statement()) } - # bespoke JSON with details of the event details: json; - # Whether its expected that this audit event will be updated. - required inProgress: bool; } type SystemAuditEvent extending AuditEvent { } - } diff --git a/lib/workload/stateless/metadata_manager/src/dbschema/metadata.esdl b/lib/workload/stateless/metadata_manager/src/dbschema/metadata.esdl index 5d459f8f9..7862b282e 100644 --- a/lib/workload/stateless/metadata_manager/src/dbschema/metadata.esdl +++ b/lib/workload/stateless/metadata_manager/src/dbschema/metadata.esdl @@ -1,23 +1,28 @@ - +using extension graphql; module metadata { - scalar type Phenotype extending enum<'normal', 'tumor', 'negative-control'>; - scalar type Quality extending enum<'very-poor', 'poor', 'good', 'borderline'>; scalar type WorkflowTypes extending enum<'clinical', 'research', 'qc', 'control', 'bcl', 'manual'>; - scalar type LibraryTypes extending enum< - '10X', - 'ctDNA', - 'ctTSO', - 'exome', - 'Metagenm', - 'MethylSeq', - 'other', - 'TSO-DNA', - 'TSO-RNA', - 'WGS', - 'WTS', - 'BiModal' - >; + + # Apparently GraphQL has some trouble on setting enums that containin hyphens + # and str startswith number + # Regex pattern accepted: /^[_a-zA-Z][_a-zA-Z0-9]*$/ + # + # scalar type Phenotype extending enum<'normal', 'tumor', 'negative-control'>; + # scalar type Quality extending enum<'very-poor', 'poor', 'good', 'borderline'>; + # scalar type LibraryTypes extending enum< + # '10X', + # 'ctDNA', + # 'ctTSO', + # 'exome', + # 'Metagenm', + # 'MethylSeq', + # 'other', + # 'TSO-DNA', + # 'TSO-RNA', + # 'WGS', + # 'WTS', + # 'BiModal' + # >; abstract type MetadataIdentifiable { required orcaBusId: str { @@ -30,12 +35,12 @@ module metadata { } type Library extending MetadataIdentifiable { - phenotype: Phenotype; + phenotype: str; workflow: WorkflowTypes; - quality: Quality; - type: LibraryTypes; + quality: str; + type: str; assay: str; - coverage: decimal; + coverage: str; single link specimen: Specimen { on target delete allow diff --git a/lib/workload/stateless/metadata_manager/src/dbschema/migrations/00001.edgeql b/lib/workload/stateless/metadata_manager/src/dbschema/migrations/00001.edgeql index 397bd47e0..d2a37329a 100644 --- a/lib/workload/stateless/metadata_manager/src/dbschema/migrations/00001.edgeql +++ b/lib/workload/stateless/metadata_manager/src/dbschema/migrations/00001.edgeql @@ -1,6 +1,7 @@ -CREATE MIGRATION m1gwyr7syw4wgds4mz3jflyrnljxi6r64jzvd6ccko6olwo3erqj4a +CREATE MIGRATION m14icr2t2ykpgsskmquyvwoduwtjo7q7qbwfadvqsblckzhdhl7uqq ONTO initial { + CREATE EXTENSION graphql VERSION '1.0'; CREATE MODULE audit IF NOT EXISTS; CREATE MODULE metadata IF NOT EXISTS; CREATE SCALAR TYPE audit::ActionOutcome EXTENDING enum; @@ -10,15 +11,6 @@ CREATE MIGRATION m1gwyr7syw4wgds4mz3jflyrnljxi6r64jzvd6ccko6olwo3erqj4a CREATE REQUIRED PROPERTY actionDescription: std::str; CREATE REQUIRED PROPERTY actionOutcome: audit::ActionOutcome; CREATE PROPERTY details: std::json; - CREATE REQUIRED PROPERTY inProgress: std::bool; - CREATE REQUIRED PROPERTY occurredDateTime: std::datetime { - SET default := (std::datetime_current()); - }; - CREATE REQUIRED PROPERTY occurredDuration: std::duration; - CREATE REQUIRED PROPERTY recordedDateTime: std::datetime { - SET default := (std::datetime_current()); - SET readonly := true; - }; CREATE REQUIRED PROPERTY updatedDateTime: std::datetime { CREATE REWRITE INSERT @@ -27,18 +19,6 @@ CREATE MIGRATION m1gwyr7syw4wgds4mz3jflyrnljxi6r64jzvd6ccko6olwo3erqj4a UPDATE USING (std::datetime_of_statement()); }; - ALTER PROPERTY occurredDuration { - CREATE REWRITE - INSERT - USING (SELECT - (__subject__.occurredDateTime - __subject__.recordedDateTime) - ); - CREATE REWRITE - UPDATE - USING (SELECT - (__subject__.occurredDateTime - __subject__.recordedDateTime) - ); - }; }; CREATE TYPE audit::SystemAuditEvent EXTENDING audit::AuditEvent; CREATE ABSTRACT TYPE metadata::MetadataIdentifiable { @@ -50,16 +30,13 @@ CREATE MIGRATION m1gwyr7syw4wgds4mz3jflyrnljxi6r64jzvd6ccko6olwo3erqj4a CREATE CONSTRAINT std::exclusive ON (std::str_lower(__subject__)); }; }; - CREATE SCALAR TYPE metadata::LibraryTypes EXTENDING enum<`10X`, ctDNA, ctTSO, exome, Metagenm, MethylSeq, other, `TSO-DNA`, `TSO-RNA`, WGS, WTS, BiModal>; - CREATE SCALAR TYPE metadata::Phenotype EXTENDING enum; - CREATE SCALAR TYPE metadata::Quality EXTENDING enum<`very-poor`, poor, good, borderline>; CREATE SCALAR TYPE metadata::WorkflowTypes EXTENDING enum; CREATE TYPE metadata::Library EXTENDING metadata::MetadataIdentifiable { CREATE PROPERTY assay: std::str; - CREATE PROPERTY coverage: std::decimal; - CREATE PROPERTY phenotype: metadata::Phenotype; - CREATE PROPERTY quality: metadata::Quality; - CREATE PROPERTY type: metadata::LibraryTypes; + CREATE PROPERTY coverage: std::str; + CREATE PROPERTY phenotype: std::str; + CREATE PROPERTY quality: std::str; + CREATE PROPERTY type: std::str; CREATE PROPERTY workflow: metadata::WorkflowTypes; }; CREATE TYPE metadata::Specimen EXTENDING metadata::MetadataIdentifiable { diff --git a/lib/workload/stateless/metadata_manager/src/dbschema/queries/audit/insertSystemAuditEvent.edgeql b/lib/workload/stateless/metadata_manager/src/dbschema/queries/audit/insertSystemAuditEvent.edgeql index 1fe501c39..453ebb382 100644 --- a/lib/workload/stateless/metadata_manager/src/dbschema/queries/audit/insertSystemAuditEvent.edgeql +++ b/lib/workload/stateless/metadata_manager/src/dbschema/queries/audit/insertSystemAuditEvent.edgeql @@ -6,8 +6,6 @@ insert SystemAuditEvent { actionDescription := $actionDescription ?? "", actionOutcome := $actionOutcome ?? ActionOutcome.success, - occurredDateTime := $occurredDateTime ?? datetime_current(), details := $details ?? {}, - inProgress := $inProgress ?? false }; diff --git a/lib/workload/stateless/metadata_manager/src/dbschema/queries/audit/updateSystemAuditEvent.edgeql b/lib/workload/stateless/metadata_manager/src/dbschema/queries/audit/updateSystemAuditEvent.edgeql index 7e3af682b..2ccc7ba72 100644 --- a/lib/workload/stateless/metadata_manager/src/dbschema/queries/audit/updateSystemAuditEvent.edgeql +++ b/lib/workload/stateless/metadata_manager/src/dbschema/queries/audit/updateSystemAuditEvent.edgeql @@ -6,6 +6,4 @@ set { actionOutcome := $actionOutcome, details := $details, - occurredDateTime := $occurredDateTime, - inProgress := $inProgress } diff --git a/lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/library/deleteLibraryByOrcaBusId.edgeql b/lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/library/deleteLibraryByOrcaBusId.edgeql new file mode 100644 index 000000000..2cc2664e7 --- /dev/null +++ b/lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/library/deleteLibraryByOrcaBusId.edgeql @@ -0,0 +1,2 @@ +delete metadata::Library +filter .orcaBusId = $orcaBusId diff --git a/lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/library/insertLibraryQuery.edgeql b/lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/library/insertLibraryQuery.edgeql index 6ee8f5285..bb2c21021 100644 --- a/lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/library/insertLibraryQuery.edgeql +++ b/lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/library/insertLibraryQuery.edgeql @@ -3,12 +3,12 @@ select ( insert metadata::Library { orcaBusId := $orcaBusId, internalId := $internalId, - phenotype := $phenotype, + phenotype := $phenotype, workflow := $workflow, - quality := $quality, - type := $type, + quality := $quality, + type := $type, assay := $assay, - coverage := $coverage, + coverage := $coverage, specimen := ( select assert_single(( diff --git a/lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/library/selectAllLibraryQuery.edgeql b/lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/library/selectAllLibraryQuery.edgeql new file mode 100644 index 000000000..c82b2c793 --- /dev/null +++ b/lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/library/selectAllLibraryQuery.edgeql @@ -0,0 +1,3 @@ +select metadata::Library{ + * +} diff --git a/lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/library/selectLibraryByIdQuery.edgeql b/lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/library/selectLibraryByInternalIdQuery.edgeql similarity index 100% rename from lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/library/selectLibraryByIdQuery.edgeql rename to lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/library/selectLibraryByInternalIdQuery.edgeql diff --git a/lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/library/updateLibraryQuery.edgeql b/lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/library/updateLibraryQuery.edgeql index 4736279f4..11f902035 100644 --- a/lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/library/updateLibraryQuery.edgeql +++ b/lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/library/updateLibraryQuery.edgeql @@ -4,14 +4,14 @@ select assert_single(( filter .orcaBusId = $orcaBusId set { - internalId := $internalId ?? .internalId, + internalId := $internalId, - phenotype := $phenotype ?? .phenotype, - workflow := $workflow ?? .workflow, - quality := $quality ?? .quality, - type := $type ?? .type, - assay := $assay ?? .assay, - coverage := $coverage ?? .coverage, + phenotype := $phenotype, + workflow := $workflow, + quality := $quality, + type := $type, + assay := $assay, + coverage := $coverage, specimen := ( select assert_single(( diff --git a/lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/specimen/deleteSpecimenByOrcaBusId.edgeql b/lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/specimen/deleteSpecimenByOrcaBusId.edgeql new file mode 100644 index 000000000..ce28d87f6 --- /dev/null +++ b/lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/specimen/deleteSpecimenByOrcaBusId.edgeql @@ -0,0 +1,2 @@ +delete metadata::Specimen +filter .orcaBusId = $orcaBusId diff --git a/lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/specimen/selectAllSpecimenQuery.edgeql b/lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/specimen/selectAllSpecimenQuery.edgeql new file mode 100644 index 000000000..57663f1e7 --- /dev/null +++ b/lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/specimen/selectAllSpecimenQuery.edgeql @@ -0,0 +1,3 @@ +select metadata::Specimen{ + * +} diff --git a/lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/specimen/selectSpecimenByIdQuery.edgeql b/lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/specimen/selectSpecimenByInternalIdQuery.edgeql similarity index 100% rename from lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/specimen/selectSpecimenByIdQuery.edgeql rename to lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/specimen/selectSpecimenByInternalIdQuery.edgeql diff --git a/lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/specimen/updateSpecimenQuery.edgeql b/lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/specimen/updateSpecimenQuery.edgeql index 0e578abb5..7e51de960 100644 --- a/lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/specimen/updateSpecimenQuery.edgeql +++ b/lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/specimen/updateSpecimenQuery.edgeql @@ -4,9 +4,9 @@ select assert_single(( filter .orcaBusId = $orcaBusId set { - internalId := $internalId ?? .internalId, - externalId := $externalId ?? .externalId, - source := $source ?? .source, + internalId := $internalId, + externalId := $externalId, + source := $source, subject := ( select assert_single(( diff --git a/lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/subject/deleteSubjectByOrcaBusId.edgeql b/lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/subject/deleteSubjectByOrcaBusId.edgeql new file mode 100644 index 000000000..d8ef180d8 --- /dev/null +++ b/lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/subject/deleteSubjectByOrcaBusId.edgeql @@ -0,0 +1,2 @@ +delete metadata::Subject +filter .orcaBusId = $orcaBusId diff --git a/lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/subject/selectAllSubjectQuery.edgeql b/lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/subject/selectAllSubjectQuery.edgeql new file mode 100644 index 000000000..3828799d4 --- /dev/null +++ b/lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/subject/selectAllSubjectQuery.edgeql @@ -0,0 +1,3 @@ +select metadata::Subject{ + * +} diff --git a/lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/subject/selectSubjectByIdQuery.edgeql b/lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/subject/selectSubjectByInternalIdQuery.edgeql similarity index 100% rename from lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/subject/selectSubjectByIdQuery.edgeql rename to lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/subject/selectSubjectByInternalIdQuery.edgeql diff --git a/lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/subject/updateSubjectQuery.edgeql b/lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/subject/updateSubjectQuery.edgeql index 9c7cb3622..1ba14b5ef 100644 --- a/lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/subject/updateSubjectQuery.edgeql +++ b/lib/workload/stateless/metadata_manager/src/dbschema/queries/metadata/subject/updateSubjectQuery.edgeql @@ -3,8 +3,8 @@ select assert_single(( filter .orcaBusId = $orcaBusId set { - internalId := $internalId ?? .internalId, - externalId := $externalId ?? .externalId + internalId := $internalId, + externalId := $externalId } )){ *, diff --git a/lib/workload/stateless/metadata_manager/src/deploy/.gitignore b/lib/workload/stateless/metadata_manager/src/deploy/.gitignore new file mode 100644 index 000000000..581904102 --- /dev/null +++ b/lib/workload/stateless/metadata_manager/src/deploy/.gitignore @@ -0,0 +1,10 @@ +*.js +!jest.config.js +*.d.ts +node_modules + +# CDK asset staging directory +.cdk.staging +cdk.out + +/volume/ \ No newline at end of file diff --git a/lib/workload/stateless/metadata_manager/src/deploy/.npmignore b/lib/workload/stateless/metadata_manager/src/deploy/.npmignore new file mode 100644 index 000000000..c1d6d45dc --- /dev/null +++ b/lib/workload/stateless/metadata_manager/src/deploy/.npmignore @@ -0,0 +1,6 @@ +*.ts +!*.d.ts + +# CDK asset staging directory +.cdk.staging +cdk.out diff --git a/lib/workload/stateless/metadata_manager/src/deploy/README.md b/lib/workload/stateless/metadata_manager/src/deploy/README.md new file mode 100644 index 000000000..320efc02a --- /dev/null +++ b/lib/workload/stateless/metadata_manager/src/deploy/README.md @@ -0,0 +1,14 @@ +# Welcome to your CDK TypeScript project + +This is a blank project for CDK development with TypeScript. + +The `cdk.json` file tells the CDK Toolkit how to execute your app. + +## Useful commands + +* `npm run build` compile typescript to js +* `npm run watch` watch for changes and compile +* `npm run test` perform the jest unit tests +* `cdk deploy` deploy this stack to your default AWS account/region +* `cdk diff` compare deployed stack with current state +* `cdk synth` emits the synthesized CloudFormation template diff --git a/lib/workload/stateless/metadata_manager/src/deploy/asset/README.md b/lib/workload/stateless/metadata_manager/src/deploy/asset/README.md new file mode 100644 index 000000000..8df6cd8bd --- /dev/null +++ b/lib/workload/stateless/metadata_manager/src/deploy/asset/README.md @@ -0,0 +1,49 @@ +# Metadata manager + +The `MetadataManager` is one of the microservices within the UMCCR OrcaBus that manages the metadata records used for the +BioInformatics pipelines. The service will be responsible to make records to stay up to date and able to sync records +from multiple sources. + +## Development + +### Git Checkout +As this microservice is part of a monorepo from the main OrcaBus project, the process Git Flow process +will follow on the root of this project. + +### Development + +#### Setup + +Change the terminal directory from the OrcaBus root to this directory: + +``` +cd lib/workload/stateless/metadata_manager/src +``` + +Requirement for this project: + - nodejs + - edgedb (see ) + +To install the dependency of this project +``` +yarn +``` + +Setup the database +``` +yarn init-db +yarn migrate-db +``` + +#### Build +```yarn edgetypes``` + + +### Run +```yarn watch``` + +#### Testing +```yarn test``` + +### Notes +- If google records have multiple records, the last record will replace the first request. \ No newline at end of file diff --git a/lib/workload/stateless/metadata_manager/src/deploy/bin/deploy.ts b/lib/workload/stateless/metadata_manager/src/deploy/bin/deploy.ts new file mode 100644 index 000000000..1c2ffd841 --- /dev/null +++ b/lib/workload/stateless/metadata_manager/src/deploy/bin/deploy.ts @@ -0,0 +1,40 @@ +#!/usr/bin/env node +import 'source-map-support/register'; +import * as cdk from 'aws-cdk-lib'; +import { MetadataManagerStack } from '../lib/metadataManagerStack'; + +// tags for our stacks +const tags = { + 'umccr-org:Stack': 'orcabusMetadataManager', +}; + +const description = 'MetadataManager for OrcaBus'; + +const app = new cdk.App(); +new MetadataManagerStack(app, 'MetadataManagerStack', { + env: { + region: 'ap-southeast-2', + }, + tags: tags, + description: description, + network: { + vpcName: 'main-vpc', + }, + edgeDb: { + secretPrefix: 'orcabusMetadataManager', // pragma: allowlist secret + version: '3.4', + }, + appConfiguration: { + triggerLoadSchedule: cdk.aws_events.Schedule.cron({ minute: '0', hour: '1' }), + }, + // Ideally this should be reusable RDS across the orcabus microservices + database: { + name: 'orcabus', + adminUser: 'orcabus_admin', + enableMonitoring: { + cloudwatchLogsExports: ['postgresql'], + enablePerformanceInsights: true, + monitoringInterval: cdk.Duration.seconds(60), + }, + }, +}); diff --git a/lib/workload/stateless/metadata_manager/src/deploy/cdk.json b/lib/workload/stateless/metadata_manager/src/deploy/cdk.json new file mode 100644 index 000000000..9fef773d9 --- /dev/null +++ b/lib/workload/stateless/metadata_manager/src/deploy/cdk.json @@ -0,0 +1,63 @@ +{ + "app": "npx ts-node --prefer-ts-exts bin/deploy.ts", + "watch": { + "include": [ + "**" + ], + "exclude": [ + "README.md", + "cdk*.json", + "**/*.d.ts", + "**/*.js", + "tsconfig.json", + "package*.json", + "yarn.lock", + "node_modules", + "test" + ] + }, + "context": { + "@aws-cdk/aws-lambda:recognizeLayerVersion": true, + "@aws-cdk/core:checkSecretUsage": true, + "@aws-cdk/core:target-partitions": [ + "aws", + "aws-cn" + ], + "@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true, + "@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true, + "@aws-cdk/aws-ecs:arnFormatIncludesClusterName": true, + "@aws-cdk/aws-iam:minimizePolicies": true, + "@aws-cdk/core:validateSnapshotRemovalPolicy": true, + "@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": true, + "@aws-cdk/aws-s3:createDefaultLoggingPolicy": true, + "@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": true, + "@aws-cdk/aws-apigateway:disableCloudWatchRole": true, + "@aws-cdk/core:enablePartitionLiterals": true, + "@aws-cdk/aws-events:eventsTargetQueueSameAccount": true, + "@aws-cdk/aws-iam:standardizedServicePrincipals": true, + "@aws-cdk/aws-ecs:disableExplicitDeploymentControllerForCircuitBreaker": true, + "@aws-cdk/aws-iam:importedRoleStackSafeDefaultPolicyName": true, + "@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy": true, + "@aws-cdk/aws-route53-patters:useCertificate": true, + "@aws-cdk/customresources:installLatestAwsSdkDefault": false, + "@aws-cdk/aws-rds:databaseProxyUniqueResourceName": true, + "@aws-cdk/aws-codedeploy:removeAlarmsFromDeploymentGroup": true, + "@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId": true, + "@aws-cdk/aws-ec2:launchTemplateDefaultUserData": true, + "@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments": true, + "@aws-cdk/aws-redshift:columnId": true, + "@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2": true, + "@aws-cdk/aws-ec2:restrictDefaultSecurityGroup": true, + "@aws-cdk/aws-apigateway:requestValidatorUniqueId": true, + "@aws-cdk/aws-kms:aliasNameRef": true, + "@aws-cdk/aws-autoscaling:generateLaunchTemplateInsteadOfLaunchConfig": true, + "@aws-cdk/core:includePrefixInUniqueNameGeneration": true, + "@aws-cdk/aws-efs:denyAnonymousAccess": true, + "@aws-cdk/aws-opensearchservice:enableOpensearchMultiAzWithStandby": true, + "@aws-cdk/aws-lambda-nodejs:useLatestRuntimeVersion": true, + "@aws-cdk/aws-efs:mountTargetOrderInsensitiveLogicalId": true, + "@aws-cdk/aws-rds:auroraClusterChangeScopeOfInstanceParameterGroupWithEachParameters": true, + "@aws-cdk/aws-appsync:useArnForSourceApiAssociationIdentifier": true, + "@aws-cdk/aws-rds:preventRenderingDeprecatedCredentials": true + } +} diff --git a/lib/workload/stateless/metadata_manager/src/deploy/construct/app/Dockerfile b/lib/workload/stateless/metadata_manager/src/deploy/construct/app/Dockerfile new file mode 100644 index 000000000..5043d808e --- /dev/null +++ b/lib/workload/stateless/metadata_manager/src/deploy/construct/app/Dockerfile @@ -0,0 +1,46 @@ +FROM alpine:latest as layer-copy + +ARG AWS_ACCESS_KEY_ID +ARG AWS_SECRET_ACCESS_KEY +ARG AWS_SESSION_TOKEN +ENV AWS_DEFAULT_REGION="ap-southeast-2" +ENV AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID +ENV AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY +ENV AWS_SESSION_TOKEN=$AWS_SESSION_TOKEN + +RUN apk add aws-cli curl unzip +RUN mkdir -p /opt + +# Getting AWS managed lambda layer injected in the image +# We are using the extension for access secrets and parameter +# Ref: Ref: https://docs.aws.amazon.com/secretsmanager/latest/userguide/retrieving-secrets_lambda.html +RUN curl $(aws lambda get-layer-version-by-arn --arn arn:aws:lambda:ap-southeast-2:665172237481:layer:AWS-Parameters-and-Secrets-Lambda-Extension-Arm64:11 --query 'Content.Location' --output text) --output layer.zip +RUN unzip layer.zip -d /opt +RUN rm layer.zip + +FROM public.ecr.aws/lambda/nodejs:20-arm64 as builder +WORKDIR /usr/app + +# Copying existing required file to the image +# `make edgetypes` that is for querying edgedb must exist before this +COPY package.json yarn.lock tsconfig.json jest.config.js ./ +COPY dbschema/ ./dbschema/ +COPY src/ ./src/ +COPY tests/ ./tests/ + +# Building necessary file for the lambda +RUN npm install -g yarn +RUN yarn -v +RUN yarn install +RUN yarn run build-src + +FROM public.ecr.aws/lambda/nodejs:20-arm64 + +# Copy the extensions here +WORKDIR /opt +COPY --from=layer-copy /opt/ . + +# Copy the rest of the code +WORKDIR ${LAMBDA_TASK_ROOT} +COPY --from=builder /usr/app/dist/ ./ +COPY --from=builder /usr/app/node_modules/ ./node_modules/ diff --git a/lib/workload/stateless/metadata_manager/src/deploy/construct/app/app-construct.ts b/lib/workload/stateless/metadata_manager/src/deploy/construct/app/app-construct.ts new file mode 100644 index 000000000..2ecc9b194 --- /dev/null +++ b/lib/workload/stateless/metadata_manager/src/deploy/construct/app/app-construct.ts @@ -0,0 +1,174 @@ +import { + aws_ec2 as ec2, + aws_secretsmanager as secretsmanager, + aws_lambda as lambda, + aws_ssm as ssm, + aws_events as events, + aws_events_targets as targets, + Duration, +} from 'aws-cdk-lib'; +import * as path from 'path'; +import { Construct } from 'constructs'; +import { ISecurityGroup } from 'aws-cdk-lib/aws-ec2'; +import { HttpLambdaIntegration } from '@aws-cdk/aws-apigatewayv2-integrations-alpha'; +import { CorsHttpMethod, HttpApi, HttpMethod } from '@aws-cdk/aws-apigatewayv2-alpha'; +import { EdgeDbConfigurationProps } from '../edge-db/edge-db-construct'; + +export interface appProps { + edgedDb: { + edgeDbConfiguration: EdgeDbConfigurationProps; + secret: secretsmanager.ISecret; + securityGroup: ISecurityGroup; + }; + network: { + vpc: ec2.IVpc; + apiGatewayHttpApiId?: string; + }; + configuration: appConfigurationProps; +} + +export interface appConfigurationProps { + triggerLoadSchedule: events.Schedule; +} + +/** + * A construct wrapping an installation of EdgeDb as a service (assuming + * an existing RDS postgres). + */ +export class AppConstruct extends Construct { + constructor(scope: Construct, id: string, props: appProps) { + super(scope, id); + + // edgeDb environment to make connection the edgeDb instance + const edgeDbConnectionEnv = { + ...props.edgedDb.edgeDbConfiguration, + EDGEDB_CLIENT_TLS_SECURITY: 'insecure', + METADATA_MANAGER_EDGEDB_SECRET_NAME: props.edgedDb.secret.secretName, + }; + + // Lambda would need to access Secret Manager to retrieve edgeDb password + // thus need an outbound traffic from SG to secret manager + const outboundSG = new ec2.SecurityGroup(this, 'OutboundSecurityGroup', { + vpc: props.network.vpc, + allowAllOutbound: true, + description: + 'Security group that allows the app service to reach out over the network (e.g. secret manager)', + }); + + // There are 2 lambdas for this app + // 1. To handle API calls (inc graphql endpoint) + // 2. To sync db with external sources (e.g. metadata in gsheet) + + // (1) Lambda that handles API queries + const apiLambda = new lambda.DockerImageFunction(this, 'APILambda', { + description: 'handles API query for Metadata Manager in OrcaBus', + code: lambda.DockerImageCode.fromImageAsset(path.join(__dirname, '../../../'), { + file: 'deploy/construct/app/Dockerfile', + exclude: ['deploy/cdk.out', 'deploy/asset', '.yarn'], + cmd: ['src/handler/server.handler'], + buildArgs: { + AWS_ACCESS_KEY_ID: process.env.AWS_ACCESS_KEY_ID ?? '', + AWS_SECRET_ACCESS_KEY: process.env.AWS_SECRET_ACCESS_KEY ?? '', + AWS_SESSION_TOKEN: process.env.AWS_SESSION_TOKEN ?? '', + }, + }), + architecture: lambda.Architecture.ARM_64, + timeout: Duration.minutes(15), + environment: { ...edgeDbConnectionEnv }, + securityGroups: [props.edgedDb.securityGroup, outboundSG], + vpc: props.network.vpc, + }); + + // (2) Lambda that handles updates + const trackingSheetCredSSM = ssm.StringParameter.fromSecureStringParameterAttributes( + this, + 'GSheetCredSSM', + { parameterName: '/umccr/google/drive/lims_service_account_json' } + ); + const trackingSheetIdSSM = ssm.StringParameter.fromSecureStringParameterAttributes( + this, + 'TrackingSheetIdSSM', + { parameterName: '/umccr/google/drive/tracking_sheet_id' } + ); + + const loaderLambda = new lambda.DockerImageFunction(this, 'loaderLambda', { + description: 'handles loading metadata to the Metadata Manager', + code: lambda.DockerImageCode.fromImageAsset(path.join(__dirname, '../../../'), { + file: 'deploy/construct/app/Dockerfile', + exclude: ['deploy/cdk.out', 'deploy/asset', '.yarn'], + cmd: ['src/handler/sync.handler'], + buildArgs: { + AWS_ACCESS_KEY_ID: process.env.AWS_ACCESS_KEY_ID ?? '', + AWS_SECRET_ACCESS_KEY: process.env.AWS_SECRET_ACCESS_KEY ?? '', + AWS_SESSION_TOKEN: process.env.AWS_SESSION_TOKEN ?? '', + }, + }), + architecture: lambda.Architecture.ARM_64, + timeout: Duration.seconds(300), + environment: { + ...edgeDbConnectionEnv, + GDRIVE_SERVICE_ACCOUNT_PARAMETER_NAME: trackingSheetCredSSM.parameterName, + TRACKING_SHEET_ID_PARAMETER_NAME: trackingSheetIdSSM.parameterName, + }, + securityGroups: [props.edgedDb.securityGroup, outboundSG], + vpc: props.network.vpc, + }); + // Lambda loader need to able to access parameter store that save google credentials + trackingSheetCredSSM.grantRead(loaderLambda); + trackingSheetIdSSM.grantRead(loaderLambda); + + // The lambda ideally will be on a scheduled interval + new events.Rule(this, 'AutoSyncLambdaRule', { + description: 'this rule is to trigger the metadata load', + schedule: props.configuration.triggerLoadSchedule, + targets: [new targets.LambdaFunction(loaderLambda)], + }); + + // Both lambda would need access for edgeDb password secret for the connection + props.edgedDb.secret.grantRead(apiLambda); + props.edgedDb.secret.grantRead(loaderLambda); + + // The API lambda will have integration with an API Gateway + const metadataApiLambdaIntegration = new HttpLambdaIntegration( + 'metadataManagerApiIntegration', + apiLambda + ); + + if (props.network.apiGatewayHttpApiId) { + throw new Error('Not yet implemented'); + + // Ref: Possible solution is to use HttpRoute, but need to test compatibility + // https://github.com/aws/aws-cdk/issues/12337#issuecomment-991092668 + + // const httpApi = HttpApi.fromHttpApiAttributes(this, 'MetadataManagerOrcabusHttpApi', { + // httpApiId: props.network.apiGatewayHttpApiId, + // }); + + // new HttpRoute(this, id, { + // httpApi: httpApi, + // integration: metadataApiLambdaIntegration, + // routeKey: HttpRouteKey.with('/{proxy+}'), + // }); + } else { + const httpApi = new HttpApi(this, 'MetadataManagerHttpApi', { + corsPreflight: { + allowHeaders: ['Authorization'], + allowMethods: [ + CorsHttpMethod.GET, + CorsHttpMethod.HEAD, + CorsHttpMethod.OPTIONS, + CorsHttpMethod.POST, + ], + allowOrigins: ['*'], // TODO to get this allowed origins from config constant + maxAge: Duration.days(10), + }, + description: 'API for orcabus metadata manager lambda', + }); + httpApi.addRoutes({ + integration: metadataApiLambdaIntegration, + path: '/{proxy+}', + methods: [HttpMethod.ANY], + }); + } + } +} diff --git a/lib/workload/stateless/metadata_manager/src/deploy/construct/edge-db/Dockerfile b/lib/workload/stateless/metadata_manager/src/deploy/construct/edge-db/Dockerfile new file mode 100644 index 000000000..ceb8fa6c4 --- /dev/null +++ b/lib/workload/stateless/metadata_manager/src/deploy/construct/edge-db/Dockerfile @@ -0,0 +1,8 @@ +ARG EDGEDB_VERSION + +FROM edgedb/edgedb:${EDGEDB_VERSION} + +# Copy dbschema which contain the migrations to the image +# Migrations will automatically applied +# Ref: https://www.edgedb.com/docs/guides/deployment/docker#schema-migrations +COPY dbschema/ ./dbschema/ diff --git a/lib/workload/stateless/metadata_manager/src/deploy/construct/edge-db/edge-db-construct.ts b/lib/workload/stateless/metadata_manager/src/deploy/construct/edge-db/edge-db-construct.ts new file mode 100644 index 000000000..1223ee08d --- /dev/null +++ b/lib/workload/stateless/metadata_manager/src/deploy/construct/edge-db/edge-db-construct.ts @@ -0,0 +1,105 @@ +import { aws_ec2 as ec2, aws_secretsmanager as secretsmanager } from 'aws-cdk-lib'; +import { Construct } from 'constructs'; +import { EdgeDbServiceConstruct, EdgeDbServicePassthroughProps } from './edge-db-service-construct'; +import { + EdgeDbLoadBalancerProtocolConstruct, + EdgeDbLoadBalancerProtocolPassthroughProps, +} from './edge-db-load-balancer-protocol-construct'; +import { ISecret } from 'aws-cdk-lib/aws-secretsmanager'; +import { ISecurityGroup } from 'aws-cdk-lib/aws-ec2'; + +export interface EdgeDbProps { + // a prefix that is used for constructing AWS secrets for edgedb + secretsPrefix: string; + + // purely for information/descriptive purposes - the friendly short name of + // the RDS instance we are wrapping + rdsDatabaseDisplayName: string; + + // the underlying network infrastructure that has already + // been set up and that we will be installing into + vpc: ec2.IVpc; + + // the configuration of the fargate service that is edge db itself + edgeDbService: EdgeDbServicePassthroughProps; + + // the configuration of the internal network load balancer that provides EdgeDb protocol access + edgeDbLoadBalancerProtocol: EdgeDbLoadBalancerProtocolPassthroughProps; +} + +export interface EdgeDbConfigurationProps { + EDGEDB_HOST: string; + EDGEDB_PORT: string; + EDGEDB_USER: string; + EDGEDB_DATABASE: string; +} + +/** + * A construct wrapping an installation of EdgeDb as a service (assuming + * an existing RDS postgres). + */ +export class EdgeDbConstruct extends Construct { + private readonly _edgeDbPasswordSecret: ISecret; + private readonly _edgeDbSecurityGroup: ISecurityGroup; + + private readonly host: string; + private readonly port: string; + private readonly user: string; + private readonly dbName: string; + + constructor(scope: Construct, id: string, props: EdgeDbProps) { + super(scope, id); + + this.user = props.edgeDbService.superUser; + this.dbName = props.edgeDbService.databaseName; + this.port = `${props.edgeDbLoadBalancerProtocol.tcpPassthroughPort ?? 5656}`; + + // create a new secret for our edge db database with an autogenerated password + this._edgeDbPasswordSecret = new secretsmanager.Secret(this, 'EdgeDbSecret', { + description: `For database ${props.rdsDatabaseDisplayName} - secret containing EdgeDb super user password`, + secretName: `${props.secretsPrefix}EdgeDb`, + generateSecretString: { + excludePunctuation: true, + }, + }); + + const edgeDbService = new EdgeDbServiceConstruct(this, 'EdgeDbService', { + ...props.edgeDbService, + vpc: props.vpc, + superUserSecret: this._edgeDbPasswordSecret, + }); + + this._edgeDbSecurityGroup = edgeDbService.securityGroup; + + const edgeDbLoadBalancer = new EdgeDbLoadBalancerProtocolConstruct( + this, + 'EdgeDbLoadBalancerProtocol', + { + vpc: props.vpc, + service: edgeDbService.service, + servicePort: edgeDbService.servicePort, + serviceSecurityGroup: edgeDbService.securityGroup, + ...props.edgeDbLoadBalancerProtocol, + } + ); + + this.host = edgeDbLoadBalancer.dnsName; + } + + public get edgeDbConnectionVariable(): EdgeDbConfigurationProps { + return { + EDGEDB_HOST: this.host, + EDGEDB_PORT: this.port, + EDGEDB_USER: this.user, + EDGEDB_DATABASE: this.dbName, + }; + } + + public get passwordSecret(): ISecret { + return this._edgeDbPasswordSecret; + } + + public get securityGroup(): ISecurityGroup { + return this._edgeDbSecurityGroup; + } +} diff --git a/lib/workload/stateless/metadata_manager/src/deploy/construct/edge-db/edge-db-load-balancer-protocol-construct.ts b/lib/workload/stateless/metadata_manager/src/deploy/construct/edge-db/edge-db-load-balancer-protocol-construct.ts new file mode 100644 index 000000000..dce4c9d1e --- /dev/null +++ b/lib/workload/stateless/metadata_manager/src/deploy/construct/edge-db/edge-db-load-balancer-protocol-construct.ts @@ -0,0 +1,102 @@ +import { aws_ec2 as ec2, Duration } from 'aws-cdk-lib'; +import { Construct } from 'constructs'; +import { FargateService } from 'aws-cdk-lib/aws-ecs'; +import { + CfnLoadBalancer, + NetworkLoadBalancer, + Protocol, +} from 'aws-cdk-lib/aws-elasticloadbalancingv2'; +import { ISecurityGroup, SecurityGroup, SubnetType } from 'aws-cdk-lib/aws-ec2'; + +export type EdgeDbLoadBalancerProtocolPassthroughProps = { + // the port that the load balancer will listen on for TCP pass through work - this is the normal + // way for interacting with EdgeDb (i.e. edgedb:// protocol) + tcpPassthroughPort: number; +}; + +type Props = EdgeDbLoadBalancerProtocolPassthroughProps & { + // the VPC that the load balancer back side will live in + vpc: ec2.IVpc; + + // the service we will balance to + service: FargateService; + + // the service port we will balance to + servicePort: number; + + // the security group we need to place the NLB in to access the service + serviceSecurityGroup: ISecurityGroup; +}; + +/** + * A network load balancer that can sit in front of a Fargate EdgeDb service + * and provides direct protocol access. + * https://www.edgedb.com/docs/reference/protocol/index + */ +export class EdgeDbLoadBalancerProtocolConstruct extends Construct { + private readonly _lb: NetworkLoadBalancer; + + constructor(scope: Construct, id: string, props: Props) { + super(scope, id); + + this._lb = new NetworkLoadBalancer(this, 'LoadBalancer', { + vpc: props.vpc, + vpcSubnets: { + subnetType: SubnetType.PRIVATE_WITH_EGRESS, + }, + // the edgeDb can only be accessed internally for protocol access + internetFacing: false, + }); + + const nlbSecurityGroup = new SecurityGroup(this, 'LbProtocolSecurityGroup', { + vpc: props.vpc, + allowAllOutbound: false, + allowAllIpv6Outbound: false, + description: + 'Security group of the NLB (EdgeDb protocol) allowing egress to the EdgeDb service on its port', + }); + nlbSecurityGroup.addEgressRule(props.serviceSecurityGroup, ec2.Port.tcp(props.servicePort)); + + // NLBs now have security groups - but not in CDK yet - this is a workaround - Aug 2023 + // review at some point and replace this with proper CDK usage + const cfnLb = this._lb.node.defaultChild as CfnLoadBalancer; + cfnLb.addPropertyOverride('SecurityGroups', [ + nlbSecurityGroup.securityGroupId, + props.serviceSecurityGroup.securityGroupId, + ]); + + // note for protocol access the NLB does not do *any* TLS handling itself + // it just passes connection through directly + const tcpListener = this._lb.addListener('TcpListener', { + port: props.tcpPassthroughPort, + protocol: Protocol.TCP, + }); + + const tg = tcpListener.addTargets('TcpTargetGroup', { + port: props.servicePort, + protocol: Protocol.TCP, + targets: [props.service], + // the assumption is our code/db will handle reasonably quick shutdown of the + // service and just abort transactions etc (I mean, that's what a database is for) + deregistrationDelay: Duration.seconds(15), + }); + // whilst all the IPs hitting us will be internal IPs - we prefer to be logging the actual IPs + // of the client rather than the NLB interface IPs + tg.setAttribute('preserve_client_ip.enabled', 'true'); + tg.configureHealthCheck({ + enabled: true, + interval: Duration.seconds(10), + timeout: Duration.seconds(5), + healthyThresholdCount: 2, + unhealthyThresholdCount: 2, + }); + } + + public get loadBalancer(): NetworkLoadBalancer { + return this._lb; + } + + public get dnsName(): string { + return this._lb.loadBalancerDnsName; + } +} diff --git a/lib/workload/stateless/metadata_manager/src/deploy/construct/edge-db/edge-db-service-construct.ts b/lib/workload/stateless/metadata_manager/src/deploy/construct/edge-db/edge-db-service-construct.ts new file mode 100644 index 000000000..f7cd89c03 --- /dev/null +++ b/lib/workload/stateless/metadata_manager/src/deploy/construct/edge-db/edge-db-service-construct.ts @@ -0,0 +1,219 @@ +import { + aws_ec2 as ec2, + aws_ecs as ecs, + aws_iam as iam, + aws_logs as logs, + Duration, +} from 'aws-cdk-lib'; +import * as path from 'path'; +import { Construct } from 'constructs'; +import { + CpuArchitecture, + FargateService, + FargateTaskDefinition, + LogDrivers, + OperatingSystemFamily, + Protocol, +} from 'aws-cdk-lib/aws-ecs'; +import { ISecret } from 'aws-cdk-lib/aws-secretsmanager'; +import { ISecurityGroup, IVpc, SecurityGroup } from 'aws-cdk-lib/aws-ec2'; + +/** + * A collection of props that are set in the highest level EdgeDb construct + * but which are then passed through to this construct. + */ +export type EdgeDbServicePassthroughProps = { + // the DSN of the Postgres db it will use for its store (the DSN must include base db user/pw) + postgresDsn: string; + postgresSecurityGroup: ISecurityGroup; + + // the settings for containers of the service + desiredCount: number; + cpu: number; + memory: number; + superUser: string; + databaseName: string; + + // edge db version string for the docker image used for edge db e.g. "3.4" + edgeDbVersion: string; + + // if present and true, enable the EdgeDb feature flag to switch on the UI + // NOTE there are other settings that need to be true for the UI to actually be on the internet! + enableUiFeatureFlag?: boolean; +}; + +/** + * An augmenting of the high level pass through props with other + * settings we have created on the way. + */ +type EdgeDbServiceProps = EdgeDbServicePassthroughProps & { + // the VPC that the service will live in + vpc: ec2.IVpc; + + // the secret holding the EdgeDb superuser password + superUserSecret: ISecret; +}; + +/** + * The EdgeDb service is a Fargate task cluster running the EdgeDb + * Docker image and pointing to an existing Postgres database. + * + * The service is set up to use self-signed certs assuming + * - network load balancer will sit in front of it and that NLB will deal with TLS termination + * - a client will connect and the client will ignore certs + */ +export class EdgeDbServiceConstruct extends Construct { + // this construct is predicated on using the default EdgeDb port + // so if you want to change this then you'll have to add some extra PORT settings in various places + private readonly EDGE_DB_PORT = 5656; + + private readonly _service: FargateService; + private readonly _securityGroup: SecurityGroup; + + constructor(scope: Construct, id: string, props: EdgeDbServiceProps) { + super(scope, id); + + const cluster = new ecs.Cluster(this, 'Cluster', { + vpc: props.vpc, + }); + + const executionRole = new iam.Role(this, 'ExecutionRole', { + assumedBy: new iam.ServicePrincipal('ecs-tasks.amazonaws.com'), + managedPolicies: [ + iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AmazonECSTaskExecutionRolePolicy'), + ], + }); + + const clusterLogGroup = new logs.LogGroup(this, 'ServiceLog', { + retention: logs.RetentionDays.ONE_WEEK, + }); + + // we do the task definition by hand as we have some specialised settings (ARM64 etc) + const taskDefinition = new FargateTaskDefinition(this, 'TaskDefinition', { + runtimePlatform: { + operatingSystemFamily: OperatingSystemFamily.LINUX, + cpuArchitecture: CpuArchitecture.ARM64, + }, + memoryLimitMiB: props.memory, + cpu: props.cpu, + executionRole: executionRole, + family: 'orcabus-metadata-manager-edge-db', + }); + + const containerName = 'edge-db'; + + const env: { [k: string]: string } = { + EDGEDB_DOCKER_LOG_LEVEL: 'debug', + // the DSN (including postgres user/pw) pointing to the base database + EDGEDB_SERVER_BACKEND_DSN: props.postgresDsn, + // we allow the superuser name to be set + EDGEDB_SERVER_USER: props.superUser, + // we don't do edgedb certs at all - rely on self-signed always + // when putting a TLS terminated network load balancer in front of this - we can + // use a self-signed cert as the internal target TLS + // NLBs are comfortable using self-signed certs purely for traffic encryption + // https://kevin.burke.dev/kevin/aws-alb-validation-tls-reply/ + // that way we can avoid needing to manage custom certs/cas + EDGEDB_SERVER_TLS_CERT_MODE: 'generate_self_signed', + EDGEDB_DATABASE: props.databaseName, + // DO NOT ENABLE + // EDGEDB_SERVER_DEFAULT_AUTH_METHOD: "Trust" + }; + + const secrets: { [k: string]: ecs.Secret } = { + // CDK is smart enough to grant permissions to read these secrets to the execution role + EDGEDB_SERVER_PASSWORD: ecs.Secret.fromSecretsManager(props.superUserSecret), + }; + + taskDefinition.addContainer(containerName, { + image: ecs.ContainerImage.fromAsset(path.join(__dirname, '../../../'), { + file: 'deploy/construct/edge-db/Dockerfile', + exclude: ['deploy/cdk.out', 'deploy/asset', '.yarn'], + buildArgs: { + EDGEDB_VERSION: props.edgeDbVersion, + }, + }), + environment: env, + secrets: secrets, + logging: LogDrivers.awsLogs({ + streamPrefix: 'edge-db', + logGroup: clusterLogGroup, + }), + portMappings: [ + { + containerPort: this.EDGE_DB_PORT, + protocol: Protocol.TCP, + }, + ], + }); + + // the membership security group is a group that defines who is allowed to connect to the EdgeDb + this._securityGroup = this.createMembershipSecurityGroup(props.vpc); + + this._service = new FargateService(this, 'Service', { + // even in dev mode we never want to assign public ips to the fargate service... + // we *ALWAYS* want to access via network load balancer - and that NLB can either be internal or external + assignPublicIp: false, + cluster: cluster, + desiredCount: props.desiredCount, + taskDefinition: taskDefinition, + vpcSubnets: { + // we need egress in order to fetch images?? if we setup with private link maybe avoid? one to investigate? + // again - we are *always* putting the service containers in private - it is our network load balancer + // that can live in public/private + subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS, + }, + // in practice an EdgeDb startup (from logs) went (timestamps) + // from 10:03:17 + // to 10:03:26 + // i.e. 10 seconds - so allocating 30 seconds to be safe + healthCheckGracePeriod: Duration.seconds(30), + securityGroups: [ + // a security group that allows the EdgeDb to reach the world + new ec2.SecurityGroup(this, 'EgressSecurityGroup', { + vpc: props.vpc, + allowAllOutbound: true, + description: + 'Security group that allows the EdgeDb service to reach out over the network', + }), + // a security group allowing access from the internal IPs (needed for the NLBs) + this._securityGroup, + // a security group that the service needs that gives it the "ability to connect to RDS" + props.postgresSecurityGroup, + ], + }); + } + + private createMembershipSecurityGroup(vpc: IVpc) { + const sg = new SecurityGroup(this, 'MembershipSecurityGroup', { + vpc: vpc, + // databases don't use outbound traffic via a security group unless you are getting them to reach + // out via a stored procedure or something + allowAllOutbound: false, + allowAllIpv6Outbound: false, + description: + 'Security group for resources that can communicate to the contained EdgeDb service', + }); + // the ingress is self-referential - only allowing traffic from itself to the edge port + sg.addIngressRule(sg, ec2.Port.tcp(this.EDGE_DB_PORT)); + // the egress is also self-referential - and allowing outbound traffic to anyone in the same + // group (the all-traffic is safe because the other resources are responsible for setting their + // ingress rules to a set port0 + + sg.addIngressRule(sg, ec2.Port.tcp(80)); + sg.addEgressRule(sg, ec2.Port.allTraffic()); + return sg; + } + + public get service(): FargateService { + return this._service; + } + + public get securityGroup(): ISecurityGroup { + return this._securityGroup; + } + + public get servicePort(): number { + return this.EDGE_DB_PORT; + } +} diff --git a/lib/workload/stateless/metadata_manager/src/deploy/construct/postgres-rds/base-database.ts b/lib/workload/stateless/metadata_manager/src/deploy/construct/postgres-rds/base-database.ts new file mode 100644 index 000000000..8ba1abede --- /dev/null +++ b/lib/workload/stateless/metadata_manager/src/deploy/construct/postgres-rds/base-database.ts @@ -0,0 +1,64 @@ +import { Construct } from 'constructs'; +import { ISecurityGroup, IVpc, SecurityGroup } from 'aws-cdk-lib/aws-ec2'; +import { aws_ec2 as ec2 } from 'aws-cdk-lib'; +import { ManagedPolicy, Role, ServicePrincipal } from 'aws-cdk-lib/aws-iam'; + +/** + * An abstract concept that helps us wrap the CDK concepts of + * a RDS instance v a RDS cluster v RDS serverless - which + * are all _basically_ the same from our perspective but are + * different enough types in CDK that it is annoying. + */ +export abstract class BaseDatabase extends Construct { + protected constructor(scope: Construct, id: string) { + super(scope, id); + } + + protected createMonitoringRole() { + const monitoringRole = new Role(this, 'DatabaseMonitoringRole', { + assumedBy: new ServicePrincipal('monitoring.rds.amazonaws.com'), + }); + monitoringRole.addManagedPolicy( + ManagedPolicy.fromAwsManagedPolicyName('service-role/AmazonRDSEnhancedMonitoringRole') + ); + return monitoringRole; + } + + protected createMembershipSecurityGroup(vpc: IVpc) { + return new SecurityGroup(this, 'MembershipSecurityGroup', { + vpc: vpc, + // databases don't use outbound traffic via a security group unless you are getting them to reach + // out via a stored procedure or something + allowAllOutbound: false, + allowAllIpv6Outbound: false, + description: + 'Security group for resources that can communicate to the contained RDS instance', + }); + } + + /** + * To the security group apply ingress rules giving access to the database + * (either from the public or from the security group itself) + * + * @param securityGroup + * @param databasePort + * @protected + */ + protected applySecurityGroupRules(securityGroup: ISecurityGroup, databasePort: number) { + securityGroup.addIngressRule(securityGroup, ec2.Port.tcp(databasePort)); + // our membership security group allows outgoing access to things in the SAME SECURITY GROUP + // (we use allTraffic safely for egress here - as those other services will be responsible + // for protected their incoming ports with their own ingress rules) + securityGroup.addEgressRule(securityGroup, ec2.Port.allTraffic()); + } + + public abstract get dsnWithTokens(): string; + + public abstract get dsnNoPassword(): string; + + public abstract get hostname(): string; + + public abstract get port(): number; + + public abstract get securityGroup(): ISecurityGroup; +} diff --git a/lib/workload/stateless/metadata_manager/src/deploy/construct/postgres-rds/infrastructure-stack-database-props.ts b/lib/workload/stateless/metadata_manager/src/deploy/construct/postgres-rds/infrastructure-stack-database-props.ts new file mode 100644 index 000000000..7b414208e --- /dev/null +++ b/lib/workload/stateless/metadata_manager/src/deploy/construct/postgres-rds/infrastructure-stack-database-props.ts @@ -0,0 +1,92 @@ +import { Duration } from 'aws-cdk-lib'; + +// NOTE: this was all set up with some nice typescript types - that separated +// out different postgres settings.. unfortunately - those types are not compatible +// with JSII, so we have had to merge all the fields into one mega Common type. +// Basically this is now all a bit yuck but is necessary to support languages other +// than typescript + +export interface PostgresCommon { + /** + * The name of the database to create + */ + readonly name: string; + + /** + * The name of the admin user to create in the database + */ + readonly adminUser: string; + + /** + * If set will override the allocated storage for the db - otherwise + * we will have this set to smallest database size allowed (20 Gib) + */ + readonly overrideAllocatedStorage?: number; + + /** + * If present switches on monitoring features such as postgres + * logs exported to cloudwatch and performance insights. + */ + readonly enableMonitoring?: PostgresCommonMonitoring; + + // ------------- + // Settings below are only for serverless Postgres + // ------------- + + /** + * The minimum number of ACU - or default to the minimum of 0.5 + */ + readonly minCapacity?: number; + + /** + * The maximum number of ACU - or default to a sensible 4 + */ + readonly maxCapacity?: number; +} + +export interface PostgresCommonMonitoring { + readonly cloudwatchLogsExports: string[]; + readonly enablePerformanceInsights: boolean; + readonly monitoringInterval: Duration; +} + +/** + * Settings that instruct us to connect an EdgeDb + * in front of the given postgres instance + */ +export interface EdgeDbCommon { + /** + * The version string of EdgeDb that will be used for the spun up EdgeDb image + */ + readonly version: string; + + /** + * The memory assigned to the Edge Db service - defaults to a sensible value + */ + readonly memoryLimitMiB?: number; + + /** + * The cpu assigned to the Edge Db service - defaults to a sensible value + */ + readonly cpu?: number; + + /** + * The port number to assign for EdgeDb protocol - defaults to 5656 which + * is what is assumed for edgedb connections + */ + readonly dbPort?: number; +} + +export interface EdgeDbPublic { + /** + * the DNS prefix to expose the EdgeDb UI as + */ + readonly urlPrefix: string; + + /** + * The port number to assign for UI access - defaults to 443. Whilst 443 is + * entirely sensible - I guess you could add a level of security obscurity by + * mapping this to another port. + */ + readonly uiPort?: number; +} diff --git a/lib/workload/stateless/metadata_manager/src/deploy/construct/postgres-rds/postgres-db-construct.ts b/lib/workload/stateless/metadata_manager/src/deploy/construct/postgres-rds/postgres-db-construct.ts new file mode 100644 index 000000000..0207d5cd6 --- /dev/null +++ b/lib/workload/stateless/metadata_manager/src/deploy/construct/postgres-rds/postgres-db-construct.ts @@ -0,0 +1,122 @@ +import { ISecurityGroup, IVpc, SecurityGroup } from 'aws-cdk-lib/aws-ec2'; +import { ISecret } from 'aws-cdk-lib/aws-secretsmanager'; +import { ServerlessCluster } from 'aws-cdk-lib/aws-rds'; +import { Construct } from 'constructs'; +import { aws_ec2 as ec2, aws_rds as rds, RemovalPolicy } from 'aws-cdk-lib'; +import { BaseDatabase } from './base-database'; +import { PostgresCommon } from './infrastructure-stack-database-props'; + +type ServerlessBaseDatabaseProps = PostgresCommon & { + vpc: IVpc; + + databaseName: string; + + secret: ISecret; +}; + +/** + * A construct representing the base database we might use with EdgeDb - in this + * case representing a V2 Serverless Aurora (in postgres mode). + */ +export class ServerlessBaseDatabase extends BaseDatabase { + private readonly _cluster: ServerlessCluster; + private readonly _securityGroup: SecurityGroup; + private readonly _dsnWithTokens: string; + private readonly _dsnNoPassword: string; + + constructor(scope: Construct, id: string, props: ServerlessBaseDatabaseProps) { + super(scope, id); + + // we create a security group and export its id - so we can use that as a security boundary + // for services that "can connect to database" + this._securityGroup = this.createMembershipSecurityGroup(props.vpc); + + this._cluster = new ServerlessCluster(this, 'ServerlessCluster', { + vpc: props.vpc, + securityGroups: [this._securityGroup], + vpcSubnets: { + subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS, + }, + engine: rds.DatabaseClusterEngine.auroraPostgres({ + version: rds.AuroraPostgresEngineVersion.VER_14_7, + }), + // the default database to create in the cluster - we insist on it being named otherwise no default db is made + defaultDatabaseName: props.databaseName, + credentials: rds.Credentials.fromSecret(props.secret), + // The Db should come from orcaBus master, and if the Db is from this service, it is supposed to be for dev which + // should removed on destroy + removalPolicy: RemovalPolicy.DESTROY, + }); + + // temporary fix to broken CDK constructs + // https://github.com/aws/aws-cdk/issues/20197#issuecomment-1272360016 + { + const cfnDBCluster = this._cluster.node.children.find( + (node) => node instanceof rds.CfnDBCluster + ) as rds.CfnDBCluster; + cfnDBCluster.serverlessV2ScalingConfiguration = { + minCapacity: props.minCapacity ?? 0.5, + maxCapacity: props.maxCapacity ?? rds.AuroraCapacityUnit.ACU_4, + }; + cfnDBCluster.engineMode = undefined; + } + + let enableMonitoring; + if (props.enableMonitoring) { + const monitoringRole = this.createMonitoringRole(); + + enableMonitoring = { + enablePerformanceInsights: props.enableMonitoring.enablePerformanceInsights, + cloudwatchLogsExports: props.enableMonitoring.cloudwatchLogsExports, + monitoringInterval: props.enableMonitoring.monitoringInterval.toSeconds(), + monitoringRoleArn: monitoringRole.roleArn, + }; + } + + new rds.CfnDBInstance(this, 'Writer', { + dbInstanceClass: 'db.serverless', + dbClusterIdentifier: this._cluster.clusterIdentifier, + engine: 'aurora-postgresql', + publiclyAccessible: false, + ...(enableMonitoring && { ...enableMonitoring }), + }); + + this.applySecurityGroupRules(this._securityGroup, this._cluster.clusterEndpoint.port); + + this._dsnWithTokens = + `postgres://` + + `${props.secret.secretValueFromJson('username').unsafeUnwrap()}` + + `:` + + `${props.secret.secretValueFromJson('password').unsafeUnwrap()}` + + `@` + + `${this._cluster.clusterEndpoint.hostname}` + + `:` + + `${this._cluster.clusterEndpoint.port}` + + `/` + + `${props.databaseName}`; + + this._dsnNoPassword = + `postgres://` + + `${props.adminUser}@${this._cluster.clusterEndpoint.hostname}:${this._cluster.clusterEndpoint.port}/${props.databaseName}`; + } + + public get dsnWithTokens(): string { + return this._dsnWithTokens; + } + + public get dsnNoPassword(): string { + return this._dsnNoPassword; + } + + public get hostname(): string { + return this._cluster.clusterEndpoint.hostname; + } + + public get port(): number { + return this._cluster.clusterEndpoint.port; + } + + public get securityGroup(): ISecurityGroup { + return this._securityGroup; + } +} diff --git a/lib/workload/stateless/metadata_manager/src/deploy/jest.config.js b/lib/workload/stateless/metadata_manager/src/deploy/jest.config.js new file mode 100644 index 000000000..44ead8540 --- /dev/null +++ b/lib/workload/stateless/metadata_manager/src/deploy/jest.config.js @@ -0,0 +1,8 @@ +module.exports = { + testEnvironment: 'node', + roots: ['/test'], + testMatch: ['**/*.test.ts'], + transform: { + '^.+\\.tsx?$': 'ts-jest', + }, +}; diff --git a/lib/workload/stateless/metadata_manager/src/deploy/lib/metadataManagerStack.ts b/lib/workload/stateless/metadata_manager/src/deploy/lib/metadataManagerStack.ts new file mode 100644 index 000000000..81f700941 --- /dev/null +++ b/lib/workload/stateless/metadata_manager/src/deploy/lib/metadataManagerStack.ts @@ -0,0 +1,105 @@ +import { Stack, StackProps, aws_ec2 as ec2 } from 'aws-cdk-lib'; +import { Construct } from 'constructs'; +import { EdgeDbConstruct } from '../construct/edge-db/edge-db-construct'; +import { Vpc } from 'aws-cdk-lib/aws-ec2'; +import { Secret } from 'aws-cdk-lib/aws-secretsmanager'; +import { ServerlessBaseDatabase } from '../construct/postgres-rds/postgres-db-construct'; +import { PostgresCommon } from '../construct/postgres-rds/infrastructure-stack-database-props'; +import { AppConstruct, appConfigurationProps } from '../construct/app/app-construct'; + +export interface EdgeDbCommon { + secretPrefix: string; + /** + * The version string of EdgeDb that will be used for the spun up EdgeDb image + */ + readonly version: string; + + /** + * The memory assigned to the Edge Db service - defaults to a sensible value + */ + readonly memoryLimitMiB?: number; + + /** + * The cpu assigned to the Edge Db service - defaults to a sensible value + */ + readonly cpu?: number; + + /** + * The port number to assign for EdgeDb protocol - defaults to 5656 which + * is what is assumed for edgedb connections + */ + readonly dbPort?: number; +} + +export interface MetadataManagerStackProps extends StackProps { + database: PostgresCommon; + edgeDb: EdgeDbCommon; + network: { + vpcName: string; + }; + appConfiguration: appConfigurationProps; +} + +export class MetadataManagerStack extends Stack { + constructor(scope: Construct, id: string, props: MetadataManagerStackProps) { + super(scope, id, props); + + const vpc = Vpc.fromLookup(this, 'mainVpc', { vpcName: props.network.vpcName }); + + // create a new secret for our base database with an autogenerated password + const postgresSecret = new Secret(this, `Secret`, { + description: `For database ${props.database.name} - secret containing RDS details such as admin username and password`, + generateSecretString: { + excludePunctuation: true, + secretStringTemplate: JSON.stringify({ + username: props.database.adminUser, + password: '', + }), + generateStringKey: 'password', + }, + }); + const postgresDb = new ServerlessBaseDatabase(this, 'metadataManagerRds', { + vpc: vpc, + databaseName: props.database.name, + secret: postgresSecret, + ...props.database, + }); + + /** + * Create EdgeDb server + */ + const edgeDb = new EdgeDbConstruct(this, `EdgeDb`, { + vpc: vpc, + rdsDatabaseDisplayName: props.database.name, + secretsPrefix: props.edgeDb.secretPrefix, + edgeDbService: { + // Postgres Config + postgresDsn: postgresDb.dsnWithTokens, + postgresSecurityGroup: postgresDb.securityGroup, + + // edge db Config + databaseName: 'orcabus', + superUser: 'orcabus_superuser', + edgeDbVersion: props.edgeDb.version, + desiredCount: 1, + cpu: props.edgeDb.cpu ?? 1024, + memory: props.edgeDb.memoryLimitMiB ?? 2048, + }, + edgeDbLoadBalancerProtocol: { + tcpPassthroughPort: props.edgeDb.dbPort || 5656, + }, + }); + + new AppConstruct(this, 'app', { + edgedDb: { + edgeDbConfiguration: edgeDb.edgeDbConnectionVariable, + secret: edgeDb.passwordSecret, + securityGroup: edgeDb.securityGroup, + }, + network: { + vpc: vpc, + }, + configuration: props.appConfiguration, + }); + } +} diff --git a/lib/workload/stateless/metadata_manager/src/deploy/package-lock.json b/lib/workload/stateless/metadata_manager/src/deploy/package-lock.json new file mode 100644 index 000000000..df2e597f6 --- /dev/null +++ b/lib/workload/stateless/metadata_manager/src/deploy/package-lock.json @@ -0,0 +1,7466 @@ +{ + "name": "deploy", + "version": "0.1.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "deploy", + "version": "0.1.0", + "dependencies": { + "@aws-cdk/aws-apigatewayv2-alpha": "^2.99.1-alpha.0", + "@aws-cdk/aws-apigatewayv2-integrations-alpha": "^2.99.1-alpha.0", + "aws-cdk-lib": "2.99.1", + "constructs": "^10.0.0", + "source-map-support": "^0.5.21" + }, + "bin": { + "deploy": "bin/deploy.js" + }, + "devDependencies": { + "@types/jest": "^29.5.5", + "@types/node": "20.6.3", + "aws-cdk": "2.99.1", + "jest": "^29.7.0", + "ts-jest": "^29.1.1", + "ts-node": "^10.9.1", + "typescript": "~5.2.2" + } + }, + "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/@aws-cdk/asset-awscli-v1": { + "version": "2.2.200", + "resolved": "https://registry.npmjs.org/@aws-cdk/asset-awscli-v1/-/asset-awscli-v1-2.2.200.tgz", + "integrity": "sha512-Kf5J8DfJK4wZFWT2Myca0lhwke7LwHcHBo+4TvWOGJrFVVKVuuiLCkzPPRBQQVDj0Vtn2NBokZAz8pfMpAqAKg==" + }, + "node_modules/@aws-cdk/asset-kubectl-v20": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@aws-cdk/asset-kubectl-v20/-/asset-kubectl-v20-2.1.2.tgz", + "integrity": "sha512-3M2tELJOxQv0apCIiuKQ4pAbncz9GuLwnKFqxifWfe77wuMxyTRPmxssYHs42ePqzap1LT6GDcPygGs+hHstLg==" + }, + "node_modules/@aws-cdk/asset-node-proxy-agent-v6": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@aws-cdk/asset-node-proxy-agent-v6/-/asset-node-proxy-agent-v6-2.0.1.tgz", + "integrity": "sha512-DDt4SLdLOwWCjGtltH4VCST7hpOI5DzieuhGZsBpZ+AgJdSI2GCjklCXm0GCTwJG/SolkL5dtQXyUKgg9luBDg==" + }, + "node_modules/@aws-cdk/aws-apigatewayv2-alpha": { + "version": "2.99.1-alpha.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-apigatewayv2-alpha/-/aws-apigatewayv2-alpha-2.99.1-alpha.0.tgz", + "integrity": "sha512-BgHAo0E28c1AgXFZIIFSRPZCfpnASl8KHggJKqMNwDVMVccANIyHh7cUAYi90+lIhi87o3GsrkwCKRVCLNCBvg==", + "engines": { + "node": ">= 14.15.0" + }, + "peerDependencies": { + "aws-cdk-lib": "2.99.1", + "constructs": "^10.0.0" + } + }, + "node_modules/@aws-cdk/aws-apigatewayv2-integrations-alpha": { + "version": "2.99.1-alpha.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-apigatewayv2-integrations-alpha/-/aws-apigatewayv2-integrations-alpha-2.99.1-alpha.0.tgz", + "integrity": "sha512-hJ+4oSBI1n4kD8+beXKr+qNT1mKiXprOJB6q2R07So3Wm2PCUBEhg58mNS51UI+eS+QWCen957AoJI5BzJfO/w==", + "engines": { + "node": ">= 14.15.0" + }, + "peerDependencies": { + "@aws-cdk/aws-apigatewayv2-alpha": "2.99.1-alpha.0", + "aws-cdk-lib": "2.99.1", + "constructs": "^10.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "dev": true, + "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.6.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.6.3.tgz", + "integrity": "sha512-HksnYH4Ljr4VQgEy2lTStbCKv/P590tmPe5HqOnv9Gprffgv5WXAY+Y5Gqniu0GGqeTCUdBnzC3QSrzPkBkAMA==", + "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.26", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.26.tgz", + "integrity": "sha512-Y3vDy2X6zw/ZCumcwLpdhM5L7jmyGpmBCTYMHDLqT2IKVMYRRLdv6ZakA+wxhra6Z/3bwhNbNl9bDGXaFU+6rw==", + "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/aws-cdk": { + "version": "2.99.1", + "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.99.1.tgz", + "integrity": "sha512-uWg4xhBrHNoRMlEgvWzr0MacJ92dLFeJ5AvT7nruxrgShU1fgt/Rsxw1WCXSASaVUsIUGgtO+P89x8cRU2nf7w==", + "dev": true, + "bin": { + "cdk": "bin/cdk" + }, + "engines": { + "node": ">= 14.15.0" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/aws-cdk-lib": { + "version": "2.99.1", + "resolved": "https://registry.npmjs.org/aws-cdk-lib/-/aws-cdk-lib-2.99.1.tgz", + "integrity": "sha512-mUhuT2JTy3VyX9o9IOSuy7UYDimFHGnmpASwTb4rD10Hksb1dTqqN2BsXU5kogHakYevBD3vwYc87rOVso4M7Q==", + "bundleDependencies": [ + "@balena/dockerignore", + "case", + "fs-extra", + "ignore", + "jsonschema", + "minimatch", + "punycode", + "semver", + "table", + "yaml" + ], + "dependencies": { + "@aws-cdk/asset-awscli-v1": "^2.2.200", + "@aws-cdk/asset-kubectl-v20": "^2.1.2", + "@aws-cdk/asset-node-proxy-agent-v6": "^2.0.1", + "@balena/dockerignore": "^1.0.2", + "case": "1.6.3", + "fs-extra": "^11.1.1", + "ignore": "^5.2.4", + "jsonschema": "^1.4.1", + "minimatch": "^3.1.2", + "punycode": "^2.3.0", + "semver": "^7.5.4", + "table": "^6.8.1", + "yaml": "1.10.2" + }, + "engines": { + "node": ">= 14.15.0" + }, + "peerDependencies": { + "constructs": "^10.0.0" + } + }, + "node_modules/aws-cdk-lib/node_modules/@balena/dockerignore": { + "version": "1.0.2", + "inBundle": true, + "license": "Apache-2.0" + }, + "node_modules/aws-cdk-lib/node_modules/ajv": { + "version": "8.12.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/aws-cdk-lib/node_modules/ansi-regex": { + "version": "5.0.1", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/aws-cdk-lib/node_modules/ansi-styles": { + "version": "4.3.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/aws-cdk-lib/node_modules/astral-regex": { + "version": "2.0.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/aws-cdk-lib/node_modules/balanced-match": { + "version": "1.0.2", + "inBundle": true, + "license": "MIT" + }, + "node_modules/aws-cdk-lib/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/aws-cdk-lib/node_modules/case": { + "version": "1.6.3", + "inBundle": true, + "license": "(MIT OR GPL-3.0-or-later)", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/aws-cdk-lib/node_modules/color-convert": { + "version": "2.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/aws-cdk-lib/node_modules/color-name": { + "version": "1.1.4", + "inBundle": true, + "license": "MIT" + }, + "node_modules/aws-cdk-lib/node_modules/concat-map": { + "version": "0.0.1", + "inBundle": true, + "license": "MIT" + }, + "node_modules/aws-cdk-lib/node_modules/emoji-regex": { + "version": "8.0.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/aws-cdk-lib/node_modules/fast-deep-equal": { + "version": "3.1.3", + "inBundle": true, + "license": "MIT" + }, + "node_modules/aws-cdk-lib/node_modules/fs-extra": { + "version": "11.1.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/aws-cdk-lib/node_modules/graceful-fs": { + "version": "4.2.11", + "inBundle": true, + "license": "ISC" + }, + "node_modules/aws-cdk-lib/node_modules/ignore": { + "version": "5.2.4", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/aws-cdk-lib/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/aws-cdk-lib/node_modules/json-schema-traverse": { + "version": "1.0.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/aws-cdk-lib/node_modules/jsonfile": { + "version": "6.1.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/aws-cdk-lib/node_modules/jsonschema": { + "version": "1.4.1", + "inBundle": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/aws-cdk-lib/node_modules/lodash.truncate": { + "version": "4.4.2", + "inBundle": true, + "license": "MIT" + }, + "node_modules/aws-cdk-lib/node_modules/lru-cache": { + "version": "6.0.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/aws-cdk-lib/node_modules/minimatch": { + "version": "3.1.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/aws-cdk-lib/node_modules/punycode": { + "version": "2.3.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/aws-cdk-lib/node_modules/require-from-string": { + "version": "2.0.2", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/aws-cdk-lib/node_modules/semver": { + "version": "7.5.4", + "inBundle": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/aws-cdk-lib/node_modules/slice-ansi": { + "version": "4.0.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/aws-cdk-lib/node_modules/string-width": { + "version": "4.2.3", + "inBundle": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/aws-cdk-lib/node_modules/strip-ansi": { + "version": "6.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/aws-cdk-lib/node_modules/table": { + "version": "6.8.1", + "inBundle": true, + "license": "BSD-3-Clause", + "dependencies": { + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/aws-cdk-lib/node_modules/universalify": { + "version": "2.0.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/aws-cdk-lib/node_modules/uri-js": { + "version": "4.4.1", + "inBundle": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/aws-cdk-lib/node_modules/yallist": { + "version": "4.0.0", + "inBundle": true, + "license": "ISC" + }, + "node_modules/aws-cdk-lib/node_modules/yaml": { + "version": "1.10.2", + "inBundle": true, + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, + "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.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", + "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", + "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.30001541", + "electron-to-chromium": "^1.4.535", + "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==" + }, + "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.30001542", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001542.tgz", + "integrity": "sha512-UrtAXVcj1mvPBFQ4sKd38daP8dEcXXr5sQe6QNNinaPd0iA/cxg9/l3VrSdL73jgw5sKyuQ6jNgiKO12W3SsVA==", + "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/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.539", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.539.tgz", + "integrity": "sha512-wRmWJ8F7rgmINuI32S6r2SLrw/h/bJQsDSvBiq9GBfvc2Lh73qTOwn73r3Cf67mjVgFGJYcYtmERzySa5jIWlg==", + "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.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "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-runner/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/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.4", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.4.tgz", + "integrity": "sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA==", + "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==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "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" + } + }, + "@aws-cdk/asset-awscli-v1": { + "version": "2.2.200", + "resolved": "https://registry.npmjs.org/@aws-cdk/asset-awscli-v1/-/asset-awscli-v1-2.2.200.tgz", + "integrity": "sha512-Kf5J8DfJK4wZFWT2Myca0lhwke7LwHcHBo+4TvWOGJrFVVKVuuiLCkzPPRBQQVDj0Vtn2NBokZAz8pfMpAqAKg==" + }, + "@aws-cdk/asset-kubectl-v20": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@aws-cdk/asset-kubectl-v20/-/asset-kubectl-v20-2.1.2.tgz", + "integrity": "sha512-3M2tELJOxQv0apCIiuKQ4pAbncz9GuLwnKFqxifWfe77wuMxyTRPmxssYHs42ePqzap1LT6GDcPygGs+hHstLg==" + }, + "@aws-cdk/asset-node-proxy-agent-v6": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@aws-cdk/asset-node-proxy-agent-v6/-/asset-node-proxy-agent-v6-2.0.1.tgz", + "integrity": "sha512-DDt4SLdLOwWCjGtltH4VCST7hpOI5DzieuhGZsBpZ+AgJdSI2GCjklCXm0GCTwJG/SolkL5dtQXyUKgg9luBDg==" + }, + "@aws-cdk/aws-apigatewayv2-alpha": { + "version": "2.99.1-alpha.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-apigatewayv2-alpha/-/aws-apigatewayv2-alpha-2.99.1-alpha.0.tgz", + "integrity": "sha512-BgHAo0E28c1AgXFZIIFSRPZCfpnASl8KHggJKqMNwDVMVccANIyHh7cUAYi90+lIhi87o3GsrkwCKRVCLNCBvg==", + "requires": {} + }, + "@aws-cdk/aws-apigatewayv2-integrations-alpha": { + "version": "2.99.1-alpha.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-apigatewayv2-integrations-alpha/-/aws-apigatewayv2-integrations-alpha-2.99.1-alpha.0.tgz", + "integrity": "sha512-hJ+4oSBI1n4kD8+beXKr+qNT1mKiXprOJB6q2R07So3Wm2PCUBEhg58mNS51UI+eS+QWCen957AoJI5BzJfO/w==", + "requires": {} + }, + "@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.6.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.6.3.tgz", + "integrity": "sha512-HksnYH4Ljr4VQgEy2lTStbCKv/P590tmPe5HqOnv9Gprffgv5WXAY+Y5Gqniu0GGqeTCUdBnzC3QSrzPkBkAMA==", + "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.26", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.26.tgz", + "integrity": "sha512-Y3vDy2X6zw/ZCumcwLpdhM5L7jmyGpmBCTYMHDLqT2IKVMYRRLdv6ZakA+wxhra6Z/3bwhNbNl9bDGXaFU+6rw==", + "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" + } + }, + "aws-cdk": { + "version": "2.99.1", + "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.99.1.tgz", + "integrity": "sha512-uWg4xhBrHNoRMlEgvWzr0MacJ92dLFeJ5AvT7nruxrgShU1fgt/Rsxw1WCXSASaVUsIUGgtO+P89x8cRU2nf7w==", + "dev": true, + "requires": { + "fsevents": "2.3.2" + } + }, + "aws-cdk-lib": { + "version": "2.99.1", + "resolved": "https://registry.npmjs.org/aws-cdk-lib/-/aws-cdk-lib-2.99.1.tgz", + "integrity": "sha512-mUhuT2JTy3VyX9o9IOSuy7UYDimFHGnmpASwTb4rD10Hksb1dTqqN2BsXU5kogHakYevBD3vwYc87rOVso4M7Q==", + "requires": { + "@aws-cdk/asset-awscli-v1": "^2.2.200", + "@aws-cdk/asset-kubectl-v20": "^2.1.2", + "@aws-cdk/asset-node-proxy-agent-v6": "^2.0.1", + "@balena/dockerignore": "^1.0.2", + "case": "1.6.3", + "fs-extra": "^11.1.1", + "ignore": "^5.2.4", + "jsonschema": "^1.4.1", + "minimatch": "^3.1.2", + "punycode": "^2.3.0", + "semver": "^7.5.4", + "table": "^6.8.1", + "yaml": "1.10.2" + }, + "dependencies": { + "@balena/dockerignore": { + "version": "1.0.2", + "bundled": true + }, + "ajv": { + "version": "8.12.0", + "bundled": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "ansi-regex": { + "version": "5.0.1", + "bundled": true + }, + "ansi-styles": { + "version": "4.3.0", + "bundled": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "astral-regex": { + "version": "2.0.0", + "bundled": true + }, + "balanced-match": { + "version": "1.0.2", + "bundled": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "case": { + "version": "1.6.3", + "bundled": true + }, + "color-convert": { + "version": "2.0.1", + "bundled": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "bundled": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true + }, + "emoji-regex": { + "version": "8.0.0", + "bundled": true + }, + "fast-deep-equal": { + "version": "3.1.3", + "bundled": true + }, + "fs-extra": { + "version": "11.1.1", + "bundled": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "graceful-fs": { + "version": "4.2.11", + "bundled": true + }, + "ignore": { + "version": "5.2.4", + "bundled": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "bundled": true + }, + "json-schema-traverse": { + "version": "1.0.0", + "bundled": true + }, + "jsonfile": { + "version": "6.1.0", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "jsonschema": { + "version": "1.4.1", + "bundled": true + }, + "lodash.truncate": { + "version": "4.4.2", + "bundled": true + }, + "lru-cache": { + "version": "6.0.0", + "bundled": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "minimatch": { + "version": "3.1.2", + "bundled": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "punycode": { + "version": "2.3.0", + "bundled": true + }, + "require-from-string": { + "version": "2.0.2", + "bundled": true + }, + "semver": { + "version": "7.5.4", + "bundled": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "slice-ansi": { + "version": "4.0.0", + "bundled": true, + "requires": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + } + }, + "string-width": { + "version": "4.2.3", + "bundled": 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", + "bundled": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "table": { + "version": "6.8.1", + "bundled": true, + "requires": { + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + } + }, + "universalify": { + "version": "2.0.0", + "bundled": true + }, + "uri-js": { + "version": "4.4.1", + "bundled": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "yallist": { + "version": "4.0.0", + "bundled": true + }, + "yaml": { + "version": "1.10.2", + "bundled": true + } + } + }, + "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.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", + "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001541", + "electron-to-chromium": "^1.4.535", + "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==" + }, + "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.30001542", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001542.tgz", + "integrity": "sha512-UrtAXVcj1mvPBFQ4sKd38daP8dEcXXr5sQe6QNNinaPd0iA/cxg9/l3VrSdL73jgw5sKyuQ6jNgiKO12W3SsVA==", + "dev": true + }, + "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.539", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.539.tgz", + "integrity": "sha512-wRmWJ8F7rgmINuI32S6r2SLrw/h/bJQsDSvBiq9GBfvc2Lh73qTOwn73r3Cf67mjVgFGJYcYtmERzySa5jIWlg==", + "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.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "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" + }, + "dependencies": { + "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" + } + } + } + }, + "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.4", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.4.tgz", + "integrity": "sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA==", + "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==" + }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "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/lib/workload/stateless/metadata_manager/src/deploy/package.json b/lib/workload/stateless/metadata_manager/src/deploy/package.json new file mode 100644 index 000000000..4f2efd7b8 --- /dev/null +++ b/lib/workload/stateless/metadata_manager/src/deploy/package.json @@ -0,0 +1,29 @@ +{ + "name": "deploy", + "version": "0.1.0", + "bin": { + "deploy": "bin/deploy.js" + }, + "scripts": { + "build": "tsc && exit 0", + "watch": "tsc -w", + "test": "jest", + "cdk": "cdk" + }, + "devDependencies": { + "@types/jest": "^29.5.5", + "@types/node": "20.6.3", + "aws-cdk": "2.99.1", + "jest": "^29.7.0", + "ts-jest": "^29.1.1", + "ts-node": "^10.9.1", + "typescript": "~5.2.2" + }, + "dependencies": { + "@aws-cdk/aws-apigatewayv2-alpha": "^2.99.1-alpha.0", + "@aws-cdk/aws-apigatewayv2-integrations-alpha": "^2.99.1-alpha.0", + "aws-cdk-lib": "2.99.1", + "constructs": "^10.0.0", + "source-map-support": "^0.5.21" + } +} diff --git a/lib/workload/stateless/metadata_manager/src/deploy/test/deploy.test.ts b/lib/workload/stateless/metadata_manager/src/deploy/test/deploy.test.ts new file mode 100644 index 000000000..c40ef8289 --- /dev/null +++ b/lib/workload/stateless/metadata_manager/src/deploy/test/deploy.test.ts @@ -0,0 +1,16 @@ +// import * as cdk from 'aws-cdk-lib'; +// import { Template } from 'aws-cdk-lib/assertions'; +// import * as Deploy from '../lib/deploy-stack'; + +// example test. To run these tests, uncomment this file along with the +// example resource in lib/deploy-stack.ts +test('SQS Queue Created', () => { + // const app = new cdk.App(); + // // WHEN + // const stack = new Deploy.DeployStack(app, 'MyTestStack'); + // // THEN + // const template = Template.fromStack(stack); + // template.hasResourceProperties('AWS::SQS::Queue', { + // VisibilityTimeout: 300 + // }); +}); diff --git a/lib/workload/stateless/metadata_manager/src/deploy/tsconfig.json b/lib/workload/stateless/metadata_manager/src/deploy/tsconfig.json new file mode 100644 index 000000000..aaa7dc510 --- /dev/null +++ b/lib/workload/stateless/metadata_manager/src/deploy/tsconfig.json @@ -0,0 +1,31 @@ +{ + "compilerOptions": { + "target": "ES2020", + "module": "commonjs", + "lib": [ + "es2020", + "dom" + ], + "declaration": true, + "strict": true, + "noImplicitAny": true, + "strictNullChecks": true, + "noImplicitThis": true, + "alwaysStrict": true, + "noUnusedLocals": false, + "noUnusedParameters": false, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": false, + "inlineSourceMap": true, + "inlineSources": true, + "experimentalDecorators": true, + "strictPropertyInitialization": false, + "typeRoots": [ + "./node_modules/@types" + ] + }, + "exclude": [ + "node_modules", + "cdk.out" + ] +} diff --git a/lib/workload/stateless/metadata_manager/src/docs/edgedb-schema.png b/lib/workload/stateless/metadata_manager/src/docs/edgedb-schema.png new file mode 100644 index 0000000000000000000000000000000000000000..90c0d2bd68c8d7b58363a067449bd96881108472 GIT binary patch literal 115496 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�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 literal 0 HcmV?d00001 diff --git a/lib/workload/stateless/metadata_manager/src/docs/relationship.drawio.svg b/lib/workload/stateless/metadata_manager/src/docs/relationship.drawio.svg new file mode 100644 index 000000000..7da216257 --- /dev/null +++ b/lib/workload/stateless/metadata_manager/src/docs/relationship.drawio.svg @@ -0,0 +1,87 @@ + + + + + + + + + + +
+
+
+ metadata::Subject +
+
+
+
+ + metadata::Subject + +
+
+ + + + +
+
+
+ metadata::Library +
+
+
+
+ + metadata::Library + +
+
+ + + + +
+
+
+ metadata::Specimen +
+
+
+
+ + metadata::Specimen + +
+
+ + + + + + + +
+
+
+ RELATIONSHIP: +
+
+
+
+ + RELATIONSHIP: + +
+
+
+ + + + + Text is not SVG - cannot display + + + +
\ No newline at end of file diff --git a/lib/workload/stateless/metadata_manager/src/edgedb.toml b/lib/workload/stateless/metadata_manager/src/edgedb.toml deleted file mode 100644 index 5ad3cbd21..000000000 --- a/lib/workload/stateless/metadata_manager/src/edgedb.toml +++ /dev/null @@ -1,2 +0,0 @@ -[edgedb] -server-version = "3.1" diff --git a/lib/workload/stateless/metadata_manager/src/jest.config.ts b/lib/workload/stateless/metadata_manager/src/jest.config.js similarity index 69% rename from lib/workload/stateless/metadata_manager/src/jest.config.ts rename to lib/workload/stateless/metadata_manager/src/jest.config.js index 26379f37a..c865147a9 100644 --- a/lib/workload/stateless/metadata_manager/src/jest.config.ts +++ b/lib/workload/stateless/metadata_manager/src/jest.config.js @@ -1,6 +1,5 @@ module.exports = { preset: 'ts-jest', testEnvironment: 'node', + roots: ['/tests/'], }; - -// jest.setTimeout(30000); diff --git a/lib/workload/stateless/metadata_manager/src/package.json b/lib/workload/stateless/metadata_manager/src/package.json index d15f93672..933386d33 100644 --- a/lib/workload/stateless/metadata_manager/src/package.json +++ b/lib/workload/stateless/metadata_manager/src/package.json @@ -1,34 +1,39 @@ { "name": "src", - "packageManager": "yarn@3.5.1", "scripts": { "watch": "NODE_ENV=development nodemon src/index.ts", "typecheck": "tsc -p tsconfig.json", - "init-db": "edgedb project init", - "migrate-db": "edgedb migration create || true && edgedb migrate", "start": "NODE_ENV=development ts-node src/index.ts", + "insert-scenario-1": "ts-node src/test-data/index.ts insert-scenario-1", + "insert-scenario-2": "ts-node src/test-data/index.ts insert-scenario-2", "//edgetypes": "Generates Typescript classes that match the schema of the *current* project EdgeDb", "edgetypes": "generate queries --file && generate edgeql-js && generate interfaces", - "test": "jest" + "test": "jest --config=jest.config.js", + "build-src": "NODE_OPTIONS='--max-old-space-size=8192' tsc" }, "dependencies": { - "@aws-sdk/client-ssm": "^3.382.0", + "@fastify/aws-lambda": "^3.3.0", + "@fastify/http-proxy": "^9.2.1", + "axios": "^1.5.1", "edgedb": "^1.3.4", "fastify": "^4.20.0", "google-auth-library": "^9.0.0", "google-spreadsheet": "^4.0.2", "lodash": "^4.17.21", + "pino": "^8.15.1", "pino-pretty": "^10.1.0", "reflect-metadata": "^0.1.13", "ts-node": "^10.9.1", "tsyringe": "^4.8.0", - "ulid": "^2.3.0" + "ulid": "^2.3.0", + "xlsx": "^0.18.5" }, "devDependencies": { "@edgedb/generate": "^0.3.1", "@types/jest": "^29.5.3", "@types/lodash": "^4", "@types/node": "^20.4.2", + "esbuild": "^0.19.5", "jest": "^29.6.2", "nodemon": "^3.0.1", "ts-jest": "^29.1.1", diff --git a/lib/workload/stateless/metadata_manager/src/src/api/routes/graphql-routes.ts b/lib/workload/stateless/metadata_manager/src/src/api/routes/graphql-routes.ts new file mode 100644 index 000000000..1627ca1c8 --- /dev/null +++ b/lib/workload/stateless/metadata_manager/src/src/api/routes/graphql-routes.ts @@ -0,0 +1,43 @@ +import { FastifyInstance, FastifyRequest } from 'fastify'; +import { fastifyHttpProxy } from '@fastify/http-proxy'; + +export const gqlRoutes = async (fastify: FastifyInstance) => { + const graphQLEndpoint = + `https://` + + `${process.env.EDGEDB_HOST ?? 'localhost'}` + + `:` + + `${process.env.EDGEDB_PORT ?? 5656}` + + `/db/` + + `${process.env.EDGEDB_DATABASE ?? 'edgedb'}` + + `/graphql`; + + fastify.register(fastifyHttpProxy, { + prefix: '/explore', + upstream: `${graphQLEndpoint}/explore`, + httpMethods: ['GET'], + proxyPayloads: false, + preHandler: async (request: FastifyRequest) => { + // It seems that fastify don't like if content-length == 0 while the body is undefined + // (despite of a GET request) and load-balancer/API-Gateway adds this automatically + // So, removing the 'content-length' to resolve this + if (request.headers['content-length']) { + delete request.headers['content-length']; + } + }, + }); + + fastify.register(fastifyHttpProxy, { + upstream: graphQLEndpoint, + httpMethods: ['POST'], + proxyPayloads: false, + preHandler: async (request: FastifyRequest, reply) => { + // We wanted to reject any kind of mutation via the GraphQL endpoint + const body = request.body as Record | undefined; + if (body.query?.includes('mutation')) { + reply + .code(400) + .send({ message: 'mutation is not supported through this graphql endpoint' }); + } + }, + }); +}; diff --git a/lib/workload/stateless/metadata_manager/src/src/api/routes/internal-routes.ts b/lib/workload/stateless/metadata_manager/src/src/api/routes/internal-routes.ts index 7e710428a..31b47e7fa 100644 --- a/lib/workload/stateless/metadata_manager/src/src/api/routes/internal-routes.ts +++ b/lib/workload/stateless/metadata_manager/src/src/api/routes/internal-routes.ts @@ -1,13 +1,22 @@ import { FastifyInstance } from 'fastify'; import { DependencyContainer } from 'tsyringe'; +import { MetadataService } from '../../service/metadata'; export const internalRoutes = async ( fastify: FastifyInstance, - // eslint-disable-next-line @typescript-eslint/no-unused-vars - _opts: { container: DependencyContainer } + opts: { container: DependencyContainer } ) => { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - fastify.get('/hello', async (request, reply) => { - return 'Hello World!\n'; + const metadataService = opts.container.resolve(MetadataService); + + fastify.get('/library', async () => { + return metadataService.getAllLibrary(); + }); + + fastify.get('/specimen', async () => { + return metadataService.getAllSpecimen(); + }); + + fastify.get('/subject', async () => { + return metadataService.getAllSubject(); }); }; diff --git a/lib/workload/stateless/metadata_manager/src/src/app.ts b/lib/workload/stateless/metadata_manager/src/src/app.ts index bfb215671..764ef66c0 100644 --- a/lib/workload/stateless/metadata_manager/src/src/app.ts +++ b/lib/workload/stateless/metadata_manager/src/src/app.ts @@ -1,9 +1,7 @@ import Fastify, { FastifyBaseLogger, FastifyInstance } from 'fastify'; -import e from '../dbschema/edgeql-js'; import { DependencyContainer } from 'tsyringe'; import { internalRoutes } from './api/routes/internal-routes'; -import insertScenario1 from './test-data/scenario-1'; -import { Client } from 'edgedb'; +import { gqlRoutes } from './api/routes/graphql-routes'; export class App { public readonly server: FastifyInstance; @@ -25,23 +23,15 @@ export class App { }); } - public async setupServer(dc: DependencyContainer): Promise { - // register global fastify plugins - // { - // } - const edgeDbClient = dc.resolve('Database'); - - // WARNING: THIS IS DEV MODE - await e.delete(e.metadata.Subject).run(edgeDbClient); - await e.delete(e.metadata.Specimen).run(edgeDbClient); - await e.delete(e.metadata.Library).run(edgeDbClient); - - await insertScenario1(dc); - + public async setupServer(): Promise { // Register Fastify routing - { - this.server.register(internalRoutes); - } + this.server.register(internalRoutes, { + container: this.dc, + }); + this.server.register(gqlRoutes, { + container: this.dc, + prefix: '/graphql', + }); return this.server; } diff --git a/lib/workload/stateless/metadata_manager/src/src/bootstrap/dependency-injection.ts b/lib/workload/stateless/metadata_manager/src/src/bootstrap/dependency-injection.ts index f9a732808..d8041571b 100644 --- a/lib/workload/stateless/metadata_manager/src/src/bootstrap/dependency-injection.ts +++ b/lib/workload/stateless/metadata_manager/src/src/bootstrap/dependency-injection.ts @@ -1,16 +1,30 @@ import { Client, Duration, createClient } from 'edgedb'; import * as tsyringe from 'tsyringe'; -import { SSMClient } from '@aws-sdk/client-ssm'; import { instanceCachingFactory } from 'tsyringe'; import pino, { Logger } from 'pino'; +import { MetadataService } from '../service/metadata'; +import { MetadataGoogleService } from '../service/loader-method/googleSheet'; +import { getSecretManagerWithLayerExtension } from '../utils'; export async function createDependencyContainer() { const dc = tsyringe.container.createChildContainer(); + // Get the edge-db password from SM + const edgeDbPassword = process.env.METADATA_MANAGER_EDGEDB_SECRET_NAME + ? await getSecretManagerWithLayerExtension(process.env.METADATA_MANAGER_EDGEDB_SECRET_NAME) + : undefined; + dc.register('Database', { // https://www.edgedb.com/docs/clients/js/driver#configuring-clients useFactory: instanceCachingFactory(() => - createClient().withConfig({ + createClient({ + host: process.env.EDGEDB_HOST ?? 'localhost', + port: process.env.EDGEDB_PORT ? parseInt(process.env.EDGEDB_PORT) : 5656, + database: process.env.EDGEDB_DATABASE ?? 'edgedb', + tlsSecurity: 'insecure', + password: edgeDbPassword ?? 'admin', + user: process.env.EDGEDB_USER ?? 'orcabus_admin', + }).withConfig({ session_idle_transaction_timeout: Duration.from({ seconds: 60 }), }) ), @@ -24,10 +38,8 @@ export async function createDependencyContainer() { }), }); - dc.register('SSMClient', { - useFactory: () => new SSMClient({}), - }); + dc.registerSingleton(MetadataService); + dc.registerSingleton(MetadataGoogleService); - // Note: dependencies of class constructors must be injected manually when using esbuild. return dc; } diff --git a/lib/workload/stateless/metadata_manager/src/src/handler/server.ts b/lib/workload/stateless/metadata_manager/src/src/handler/server.ts new file mode 100644 index 000000000..5ae9a6846 --- /dev/null +++ b/lib/workload/stateless/metadata_manager/src/src/handler/server.ts @@ -0,0 +1,16 @@ +// 'reflect-metadata' must be beginning of the line and before any DI is used +import 'reflect-metadata'; +import { App } from '../app'; +import { createDependencyContainer } from '../bootstrap/dependency-injection'; +import awsLambdaFastify from '@fastify/aws-lambda'; + +export const handler = async (event: unknown, context: unknown) => { + const dc = await createDependencyContainer(); + const app = new App(dc); + + // Setting/registering server routes + const server = await app.setupServer(); + + const proxy = awsLambdaFastify(server); + return proxy(event, context); +}; diff --git a/lib/workload/stateless/metadata_manager/src/src/handler/sync.ts b/lib/workload/stateless/metadata_manager/src/src/handler/sync.ts new file mode 100644 index 000000000..f176a39dc --- /dev/null +++ b/lib/workload/stateless/metadata_manager/src/src/handler/sync.ts @@ -0,0 +1,29 @@ +// 'reflect-metadata' must be beginning of the line and before any DI is used +import 'reflect-metadata'; +import { createDependencyContainer } from '../bootstrap/dependency-injection'; + +import { MetadataService } from '../service/metadata'; +import { MetadataGoogleService } from '../service/loader-method/googleSheet'; +import insertScenario1 from '../test-data/scenarios/scenario-1'; + +export const handler = async () => { + const dc = await createDependencyContainer(); + + if (process.env.NODE_ENV === 'development') { + await insertScenario1(dc); + } else { + const metadataGoogleService = dc.resolve(MetadataGoogleService); + const metadataService = dc.resolve(MetadataService); + + const downloadedMetadata = await metadataGoogleService.downloadGoogleMetadata(); + const convertedRecord = metadataGoogleService.convertToMetadataRecord(downloadedMetadata); + + // Updating Db + await metadataService.upsertMetadataRecords(convertedRecord); + await metadataService.removeDeletedMetadataRecords(convertedRecord); + } + + return { + statusCode: 200, + }; +}; diff --git a/lib/workload/stateless/metadata_manager/src/src/index.ts b/lib/workload/stateless/metadata_manager/src/src/index.ts index 11796b4dc..195ef56ed 100644 --- a/lib/workload/stateless/metadata_manager/src/src/index.ts +++ b/lib/workload/stateless/metadata_manager/src/src/index.ts @@ -12,7 +12,7 @@ import getAppSettings from './bootstrap/settings'; const app = new App(dc); // Setting/registering server routes - const server = await app.setupServer(dc); + const server = await app.setupServer(); server.listen({ host: appSettings.host, port: appSettings.port }, (err, address) => { if (err) { diff --git a/lib/workload/stateless/metadata_manager/src/src/service/helpers/audit-helper.ts b/lib/workload/stateless/metadata_manager/src/src/service/helpers/audit-helper.ts index 5475b08f2..98aeea30a 100644 --- a/lib/workload/stateless/metadata_manager/src/src/service/helpers/audit-helper.ts +++ b/lib/workload/stateless/metadata_manager/src/src/service/helpers/audit-helper.ts @@ -18,7 +18,7 @@ export const systemAuditEventPattern = async ( actionCategory: ActionType = 'E', actionDescription: string, transFunc: (tx: Transaction) => Promise -): Promise => { +): Promise => { const auditEventId = await startSystemAuditEvent(edgeDbClient, actionCategory, actionDescription); try { @@ -53,7 +53,6 @@ export const startSystemAuditEvent = async ( actionDescription: string, // eslint-disable-next-line @typescript-eslint/no-explicit-any details: any = { errorMessage: 'Audit entry not completed' }, - inProgress = true, actionOutcome: ActionOutcomeType = 'error' ): Promise => { return ( @@ -62,7 +61,6 @@ export const startSystemAuditEvent = async ( actionDescription, actionOutcome, details, - inProgress, }) ).id; }; @@ -88,7 +86,5 @@ export const completeSystemAuditEvent = async ( auditDbId: auditEventId, actionOutcome: outcome, details, - occurredDateTime: endDate, - inProgress: false, }); }; diff --git a/lib/workload/stateless/metadata_manager/src/src/service/helpers/metadata/library-helper.ts b/lib/workload/stateless/metadata_manager/src/src/service/helpers/metadata/library-helper.ts index f1ce32a56..6de20e831 100644 --- a/lib/workload/stateless/metadata_manager/src/src/service/helpers/metadata/library-helper.ts +++ b/lib/workload/stateless/metadata_manager/src/src/service/helpers/metadata/library-helper.ts @@ -1,14 +1,14 @@ -import { insertLibraryQuery } from '../../../../dbschema/queries'; +import { insertLibraryQuery, updateLibraryQuery } from '../../../../dbschema/queries'; import { Transaction } from 'edgedb/dist/transaction'; import { MetadataIdentifiableType } from './metadata-helper'; import { metadata } from '../../../../dbschema/interfaces'; import { isEqual } from 'lodash'; export type LibraryType = MetadataIdentifiableType & { - phenotype: metadata.Phenotype | null; + phenotype: string | null; workflow: metadata.WorkflowTypes | null; - quality: metadata.Quality | null; - type: metadata.LibraryTypes | null; + quality: string | null; + type: string | null; assay: string | null; coverage: string | null; specimenOrcaBusId?: string; @@ -61,7 +61,7 @@ export const insertLibraryRecord = async (tx: Transaction, props: LibraryType) = }; export const updateLibraryRecord = async (tx: Transaction, props: LibraryType) => { - await insertLibraryQuery(tx, { + await updateLibraryQuery(tx, { orcaBusId: props.orcaBusId, internalId: props.internalId, phenotype: props.phenotype, diff --git a/lib/workload/stateless/metadata_manager/src/src/service/loader-method/googleSheet.ts b/lib/workload/stateless/metadata_manager/src/src/service/loader-method/googleSheet.ts index cb3e4ffbf..723bd38c2 100644 --- a/lib/workload/stateless/metadata_manager/src/src/service/loader-method/googleSheet.ts +++ b/lib/workload/stateless/metadata_manager/src/src/service/loader-method/googleSheet.ts @@ -1,40 +1,13 @@ -import { Client } from 'edgedb'; -import { ulid } from 'ulid'; import { metadata } from '../../../dbschema/interfaces'; import { inject, injectable } from 'tsyringe'; import { Logger } from 'pino'; import { JWT } from 'google-auth-library'; -import { GetParameterCommand, SSMClient } from '@aws-sdk/client-ssm'; import { GoogleSpreadsheet } from 'google-spreadsheet'; -import { - selectLibraryByIdQuery, - selectSpecimenByIdQuery, - selectSubjectByIdQuery, -} from '../../../dbschema/queries'; -import { - isSubjectIdentical, - insertSubjectRecord, - updateSubjectRecord, -} from '../helpers/metadata/subject-helper'; -import { systemAuditEventPattern } from '../helpers/audit-helper'; -import { Transaction } from 'edgedb/dist/transaction'; -import { - insertSpecimenRecord, - isSpecimenIdentical, - updateSpecimenRecord, -} from '../helpers/metadata/specimen-helper'; -import { - insertLibraryRecord, - isLibraryIdentical, - updateLibraryRecord, -} from '../helpers/metadata/library-helper'; - -const GDRIVE_SERVICE_ACCOUNT = '/umccr/google/drive/lims_service_account_json'; -const TRACKING_SHEET_ID = '/umccr/google/drive/tracking_sheet_id'; -// const LIMS_SHEET_ID = '/umccr/google/drive/lims_sheet_id'; // DEPRECATE? +import { MetadataRecords } from '../metadata'; +import { getParameterDecryptedStoreWithLayerExtension } from '../../utils'; // This will tell from which year the system should query the worksheet -// Note: The title of the sheet are supposed to be th year +// The title of each sheet *SHOULD* be the year const YEAR_START = 2017; type GoogleMetadataTrackingHeader = @@ -56,22 +29,7 @@ type GoogleMetadataTrackingHeader = @injectable() export class MetadataGoogleService { - constructor( - @inject('Database') private readonly edgeDbClient: Client, - @inject('Settings') private readonly settings: Record, - @inject('Logger') private readonly logger: Logger, - @inject('SSMClient') private readonly ssmClient: SSMClient - ) {} - - private async getParameterValue(parameterString: string) { - const input = { - Name: parameterString, - WithDecryption: true, - }; - const command = new GetParameterCommand(input); - return (await this.ssmClient.send(command)).Parameter?.Value; - } - + constructor(@inject('Logger') private readonly logger: Logger) {} /** * Get SpreadSheet values from Google Drive * @param sheetTitle @@ -80,13 +38,18 @@ export class MetadataGoogleService { public async getSheetObject( sheetTitle: string ): Promise[]> { - const googleAuthString = await this.getParameterValue(GDRIVE_SERVICE_ACCOUNT); + const googleAuthString = await getParameterDecryptedStoreWithLayerExtension( + process.env.GDRIVE_SERVICE_ACCOUNT_PARAMETER_NAME + ); if (!googleAuthString) throw new Error('No GDrive credential found!'); - const googleSheetId = await this.getParameterValue(TRACKING_SHEET_ID); + const googleSheetId = await getParameterDecryptedStoreWithLayerExtension( + process.env.TRACKING_SHEET_ID_PARAMETER_NAME + ); if (!googleSheetId) throw new Error('No Google Sheet Id found!'); const googleAuthJson = JSON.parse(googleAuthString); + const jwt = new JWT({ email: googleAuthJson.client_email, key: googleAuthJson.private_key, @@ -100,245 +63,72 @@ export class MetadataGoogleService { if (!sheet) throw new Error(`No sheet found with title: ${sheetTitle}`); const rows = await sheet.getRows(); + return rows.map( (row) => >row.toObject() ); } - /** - * Insert or Update for the subject specified in the properties - * @param props - * @returns - */ - protected async syncSubject(props: { internalId: string; externalId: string | null }) { - const subject = await selectSubjectByIdQuery(this.edgeDbClient, { - internalId: props.internalId, - }); - - // If subject does not exist => insert one - if (!subject) { - return systemAuditEventPattern( - this.edgeDbClient, - 'C', - `Insert new subject record: ${props.internalId}`, - async (tx: Transaction) => { - const r = await insertSubjectRecord(tx, { - orcaBusId: `sbj.${ulid()}`, - internalId: props.internalId, - externalId: props.externalId, - }); - return r; - } - ); - } - - // Check if there it is the same with what we had in record and update if not - if (isSubjectIdentical(subject, props)) { - return systemAuditEventPattern( - this.edgeDbClient, - 'U', - `Update existing subject record: ${props.internalId}`, - async (tx: Transaction) => { - const r = await updateSubjectRecord(tx, { - orcaBusId: subject.orcaBusId, - internalId: props.internalId, - externalId: props.externalId, - }); - return r; - } - ); - } - return subject; - } + public async downloadGoogleMetadata(): Promise< + Record[] + > { + let year = YEAR_START; + let allRecords: Record[] = []; - /** - * Insert or Update for the specimen specified in the properties - * @param props - * @returns - */ - protected async syncSpecimen(props: { - internalId: string; - externalId: string | null; - subjectOrcaBusId?: string; - source: string | null; - }) { - const specimen = await selectSpecimenByIdQuery(this.edgeDbClient, { - internalId: props.internalId, - }); + // eslint-disable-next-line no-constant-condition + while (true) { + this.logger.info(`Retrieving Google Metadata Tracking Sheet year: ${year}`); - // If subject does not exist => insert one - if (!specimen) { - return systemAuditEventPattern( - this.edgeDbClient, - 'C', - `Insert new specimen record: ${props.internalId}`, - async (tx: Transaction) => { - const r = await insertSpecimenRecord(tx, { - orcaBusId: `spc.${ulid()}`, - internalId: props.internalId, - externalId: props.externalId, - subjectOrcaBusId: props.subjectOrcaBusId, - source: props.source, - }); - return r; - } - ); + try { + const yearlyMetadataObject = await this.getSheetObject(year.toString()); + allRecords = [...allRecords, ...yearlyMetadataObject]; + year += 1; + } catch (error) { + break; + } } - // Check if specimen is the same with what we had in record and update if not - if ( - isSpecimenIdentical( - { - internalId: specimen.internalId, - externalId: specimen.externalId, - source: specimen.source, - subjectOrcaBusId: specimen.subjectId, - }, - { ...props } - ) - ) { - return systemAuditEventPattern( - this.edgeDbClient, - 'U', - `Update existing specimen record: ${props.internalId}`, - async (tx: Transaction) => { - const r = await updateSpecimenRecord(tx, { - orcaBusId: specimen.orcaBusId, - internalId: props.internalId, - externalId: props.externalId, - source: props.source, - subjectOrcaBusId: props.subjectOrcaBusId, - }); - return r; - } - ); - } - return specimen; + return allRecords; } - /** - * Insert or Update for the library specified in the properties - * @param props - * @returns - */ - protected async syncLibrary(props: { - internalId: string; - phenotype: metadata.Phenotype | null; - workflow: metadata.WorkflowTypes | null; - quality: metadata.Quality | null; - type: metadata.LibraryTypes | null; - assay: string | null; - coverage: string | null; - specimenId?: string; - }) { - const library = await selectLibraryByIdQuery(this.edgeDbClient, { - libraryId: props.internalId, - }); - // If library does not exist => insert one - if (!library) { - return systemAuditEventPattern( - this.edgeDbClient, - 'C', - `Insert new library record: ${props.internalId}`, - async (tx: Transaction) => { - const r = await insertLibraryRecord(tx, { - orcaBusId: `lib.${ulid()}`, - internalId: props.internalId, - phenotype: props.phenotype, - workflow: props.workflow, - quality: props.quality, - type: props.type, - assay: props.assay, - coverage: props.coverage, - specimenOrcaBusId: props.specimenId, - }); - return r; - } - ); - } + public convertToMetadataRecord( + googleRecArray: Record[] + ): MetadataRecords[] { + this.logger.info('Converting all retrieved metadata to a recognized file format'); - // Check if specimen is the same with what we had in record and update if not - if (isLibraryIdentical(library, props)) { - return systemAuditEventPattern( - this.edgeDbClient, - 'U', - `Update existing specimen record: ${props.internalId}`, - async (tx: Transaction) => { - const r = await updateLibraryRecord(tx, { - orcaBusId: library.orcaBusId, - internalId: props.internalId, - phenotype: props.phenotype, - workflow: props.workflow, - quality: props.quality, - type: props.type, - assay: props.assay, - coverage: props.coverage, - specimenOrcaBusId: props.specimenId, - }); - return r; - } - ); - } - return library; - } + return googleRecArray.map((rec) => { + const val: MetadataRecords = {}; - /** - * Sync Google Metadata record - * - * NOTE (in DEV): Does not handle deletion (from gsheet) and if record is half filled. - * @param sheetRecords - */ - public async syncGoogleMetadataRecords( - sheetRecords: Record[] - ) { - for (const rec of sheetRecords) { - // Sync subject - const subject = rec.SubjectID - ? await this.syncSubject({ - internalId: rec.SubjectID, - externalId: rec.ExternalSubjectID ?? null, - }) - : undefined; + if (rec.SubjectID) { + val.subject = { + internalId: rec.SubjectID, + externalId: rec.ExternalSubjectID ? rec.ExternalSubjectID.toString() : null, + }; + } - // Sync Sample - const sample = rec.SampleID - ? await this.syncSpecimen({ - internalId: rec.SampleID, - externalId: rec.ExternalSampleID ?? null, - subjectOrcaBusId: subject?.orcaBusId, - source: rec.Source ?? null, - }) - : undefined; + if (rec.SampleID) { + val.specimen = { + internalId: rec.SampleID, + externalId: rec.ExternalSampleID ? rec.ExternalSampleID.toString() : null, + source: rec.Source ?? null, + }; + } - // Sync Library if (rec.LibraryID) { - await this.syncLibrary({ + val.library = { internalId: rec.LibraryID, - phenotype: rec.Phenotype ? rec.Phenotype : null, + phenotype: rec.Phenotype ? rec.Phenotype : null, workflow: rec.Workflow ? rec.Workflow : null, - quality: rec.Quality ? rec.Quality : null, - type: rec.Type ? rec.Type : null, + quality: rec.Quality ? rec.Quality : null, + type: rec.Type ? rec.Type : null, assay: rec.Assay ? rec.Assay : null, - coverage: rec['Coverage (X)'] ? rec['Coverage (X)'] : null, - specimenId: sample?.orcaBusId, - }); + coverage: rec['Coverage (X)'] ? rec['Coverage (X)'].toString() : null, + }; } - } - } - public async downloadGoogleMetadata() { - let year = YEAR_START; - for (;;) { - try { - // TODO: Deal with deletion!!! - const metadata_object = await this.getSheetObject(year.toString()); - this.syncGoogleMetadataRecords(metadata_object); - year += 1; - } catch (error) { - break; - } - } + return val; + }); } } diff --git a/lib/workload/stateless/metadata_manager/src/src/service/metadata-loader.ts b/lib/workload/stateless/metadata_manager/src/src/service/metadata-loader.ts deleted file mode 100644 index 84f1f8985..000000000 --- a/lib/workload/stateless/metadata_manager/src/src/service/metadata-loader.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Client } from 'edgedb'; -import { injectable, inject } from 'tsyringe'; - -@injectable() -export class LibraryLoaderService { - constructor(@inject('Database') private readonly edgeDbClient: Client) {} - - public fetchAndLoad() { - console.log('fetching'); - } -} diff --git a/lib/workload/stateless/metadata_manager/src/src/service/metadata.ts b/lib/workload/stateless/metadata_manager/src/src/service/metadata.ts new file mode 100644 index 000000000..c5b6cb43d --- /dev/null +++ b/lib/workload/stateless/metadata_manager/src/src/service/metadata.ts @@ -0,0 +1,358 @@ +import { Client } from 'edgedb'; +import { injectable, inject } from 'tsyringe'; +import { + isSubjectIdentical, + insertSubjectRecord, + updateSubjectRecord, + SubjectType, +} from './helpers/metadata/subject-helper'; +import { ulid } from 'ulid'; +import { + SpecimenType, + insertSpecimenRecord, + isSpecimenIdentical, + updateSpecimenRecord, +} from './helpers/metadata/specimen-helper'; +import { + LibraryType, + insertLibraryRecord, + isLibraryIdentical, + updateLibraryRecord, +} from './helpers/metadata/library-helper'; +import { + deleteLibraryByOrcaBusId, + deleteSpecimenByOrcaBusId, + deleteSubjectByOrcaBusId, + selectAllLibraryQuery, + selectAllSpecimenQuery, + selectAllSubjectQuery, + selectLibraryByInternalIdQuery, + selectSpecimenByInternalIdQuery, + selectSubjectByInternalIdQuery, +} from '../../dbschema/queries'; +import { Transaction } from 'edgedb/dist/transaction'; +import { systemAuditEventPattern } from './helpers/audit-helper'; +import { Logger } from 'pino'; + +export type MetadataRecords = { + subject?: Omit; + specimen?: Omit; + library?: Omit; +}; + +@injectable() +export class MetadataService { + constructor( + @inject('Database') private readonly edgeDbClient: Client, + @inject('Logger') private readonly logger: Logger + ) {} + + /** + * Update or Insert for the subject specified in the properties + * @param props + * @returns + */ + protected async upsertSubject(props: Omit) { + const subject = await selectSubjectByInternalIdQuery(this.edgeDbClient, { + internalId: props.internalId, + }); + + // If subject does not exist => insert one + if (!subject) { + const assignedOrcaBusId = `sbj.${ulid()}`; + return await systemAuditEventPattern( + this.edgeDbClient, + 'C', + `Insert new subject record: ${assignedOrcaBusId}`, + async (tx: Transaction) => { + const r = await insertSubjectRecord(tx, { + ...props, + orcaBusId: assignedOrcaBusId, + }); + return r; + } + ); + } + + // Check if there it is the same with what we had in record and update if not + if (isSubjectIdentical(subject, props)) { + return await systemAuditEventPattern( + this.edgeDbClient, + 'U', + `Update existing subject record: ${subject.orcaBusId}`, + async (tx: Transaction) => { + const r = await updateSubjectRecord(tx, { + ...props, + orcaBusId: subject.orcaBusId, + }); + return r; + } + ); + } + return subject; + } + + /** + * Check the current records and deletes it if no longer exist in the source truth of data + * @param sourceData The source truth of data + * @returns + */ + protected async checkAndRemoveSubject(sourceInternalIdArray: string[]) { + const allExistingSubject = await selectAllSubjectQuery(this.edgeDbClient); + for (const s of allExistingSubject) { + const shouldRetain = !!sourceInternalIdArray.find( + (sourceInternalId) => sourceInternalId == s.internalId + ); + + if (!shouldRetain) { + await systemAuditEventPattern( + this.edgeDbClient, + 'D', + `Delete subject record: ${s.orcaBusId}`, + async (tx: Transaction) => { + const r = await deleteSubjectByOrcaBusId(tx, { + orcaBusId: s.orcaBusId, + }); + return r; + } + ); + } + } + } + + /** + * Insert or Update for the specimen specified in the properties + * @param props + * @returns + */ + protected async upsertSpecimen( + props: Omit & { + subjectOrcaBusId?: string; + } + ) { + const specimen = await selectSpecimenByInternalIdQuery(this.edgeDbClient, { + internalId: props.internalId, + }); + + // If subject does not exist => insert one + if (!specimen) { + const assignedOrcaBusId = `spc.${ulid()}`; + + return await systemAuditEventPattern( + this.edgeDbClient, + 'C', + `Insert new specimen record: ${assignedOrcaBusId}`, + async (tx: Transaction) => { + const r = await insertSpecimenRecord(tx, { + ...props, + orcaBusId: assignedOrcaBusId, + }); + return r; + } + ); + } + + // Check if specimen is the same with what we had in record and update if not + if ( + isSpecimenIdentical( + { + internalId: specimen.internalId, + externalId: specimen.externalId, + source: specimen.source, + subjectOrcaBusId: specimen.subjectId, + }, + { ...props } + ) + ) { + return await systemAuditEventPattern( + this.edgeDbClient, + 'U', + `Update existing specimen record: ${specimen.orcaBusId}`, + async (tx: Transaction) => { + const r = await updateSpecimenRecord(tx, { + ...props, + orcaBusId: specimen.orcaBusId, + }); + return r; + } + ); + } + return specimen; + } + + /** + * Check the current records and deletes it if no longer exist in source data + * @param sourceData The source truth of data + * @returns + */ + protected async checkAndRemoveSpecimen(sourceInternalIdArray: string[]) { + const allExistingSpc = await selectAllSpecimenQuery(this.edgeDbClient); + for (const s of allExistingSpc) { + const shouldRetain = !!sourceInternalIdArray.find( + (sourceInternalId) => sourceInternalId == s.internalId + ); + + if (!shouldRetain) { + await systemAuditEventPattern( + this.edgeDbClient, + 'D', + `Delete specimen record: ${s.orcaBusId}`, + async (tx: Transaction) => { + const r = await deleteSpecimenByOrcaBusId(tx, { + orcaBusId: s.orcaBusId, + }); + return r; + } + ); + } + } + } + + /** + * Insert or Update for the library specified in the properties + * @param props + * @returns + */ + protected async upsertLibrary( + props: Omit & { + specimenOrcaBusId?: string; + } + ) { + const library = await selectLibraryByInternalIdQuery(this.edgeDbClient, { + libraryId: props.internalId, + }); + // If library does not exist => insert one + if (!library) { + const assignedOrcaBusId = `lib.${ulid()}`; + return await systemAuditEventPattern( + this.edgeDbClient, + 'C', + `Insert new library record: ${assignedOrcaBusId}`, + async (tx: Transaction) => { + const r = await insertLibraryRecord(tx, { + ...props, + orcaBusId: assignedOrcaBusId, + }); + return r; + } + ); + } + + // Check if specimen is the same with what we had in record and update if not + if (isLibraryIdentical(library, props)) { + return await systemAuditEventPattern( + this.edgeDbClient, + 'U', + `Update existing specimen record: ${library.orcaBusId}`, + async (tx: Transaction) => { + const r = await updateLibraryRecord(tx, { + ...props, + orcaBusId: library.orcaBusId, + }); + return r; + } + ); + } + return library; + } + + /** + * Check the current records and deletes it if no longer exist in source data + * @param internalIdArray The internalIds in an array of the truth + * @returns + */ + protected async checkAndRemoveLibrary(sourceInternalIdArray: string[]) { + const allExistingLib = await selectAllLibraryQuery(this.edgeDbClient); + for (const s of allExistingLib) { + const shouldRetain = !!sourceInternalIdArray.find( + (sourceInternalId) => sourceInternalId == s.internalId + ); + + if (!shouldRetain) { + await systemAuditEventPattern( + this.edgeDbClient, + 'D', + `Delete library record: ${s.orcaBusId}`, + async (tx: Transaction) => { + const r = await deleteLibraryByOrcaBusId(tx, { + orcaBusId: s.orcaBusId, + }); + return r; + } + ); + } + } + } + + /** + * Update or Insert record based on the given (source of truth) data + * @param metadataRecords + */ + public async upsertMetadataRecords(metadataRecords: MetadataRecords[]) { + this.logger.info(`Upsert for any new record that doesn't match or exist within the record`); + + for (const rec of metadataRecords) { + // Subject + const subject = rec.subject ? await this.upsertSubject(rec.subject) : undefined; + + // Specimen + const sample = rec.specimen + ? await this.upsertSpecimen({ + ...rec.specimen, + subjectOrcaBusId: subject?.orcaBusId, + }) + : undefined; + + // Library + if (rec.library) { + await this.upsertLibrary({ + ...rec.library, + specimenOrcaBusId: sample?.orcaBusId, + }); + } + } + } + + /** + * Check and delete if internalId is no longer exist in the single source of truth data + * @param metadataRecords the source of true data + */ + public async removeDeletedMetadataRecords(metadataRecords: MetadataRecords[]) { + this.logger.info('Removing any existing record that does not exist in the current dataset'); + const internalIdArrays: { subject: string[]; specimen: string[]; library: string[] } = { + subject: [], + specimen: [], + library: [], + }; + + for (const r of metadataRecords) { + if (r.subject?.internalId) { + internalIdArrays.subject.push(r.subject?.internalId); + } + + if (r.specimen?.internalId) { + internalIdArrays.specimen.push(r.specimen?.internalId); + } + + if (r.library?.internalId) { + internalIdArrays.library.push(r.library?.internalId); + } + } + + await this.checkAndRemoveSubject(internalIdArrays.subject); + await this.checkAndRemoveSpecimen(internalIdArrays.specimen); + await this.checkAndRemoveLibrary(internalIdArrays.library); + } + + public async getAllLibrary() { + return await selectAllLibraryQuery(this.edgeDbClient); + } + + public async getAllSpecimen() { + return await selectAllSpecimenQuery(this.edgeDbClient); + } + + public async getAllSubject() { + return await selectAllSubjectQuery(this.edgeDbClient); + } +} diff --git a/lib/workload/stateless/metadata_manager/src/src/test-data/index.ts b/lib/workload/stateless/metadata_manager/src/src/test-data/index.ts new file mode 100644 index 000000000..afdf39814 --- /dev/null +++ b/lib/workload/stateless/metadata_manager/src/src/test-data/index.ts @@ -0,0 +1,27 @@ +// must be first and before any DI is used +import 'reflect-metadata'; +import { createDependencyContainer } from '../bootstrap/dependency-injection'; +import insertScenario1 from './scenarios/scenario-1'; +import insertScenario2 from './scenarios/scenario-2'; + +(async () => { + if (!process.argv || process.argv.length <= 2) { + throw new Error('Invalid argument'); + } + + const arg = process.argv.slice(2).join(' '); + + const dc = await createDependencyContainer(); + + switch (arg) { + case 'insert-scenario-1': + await insertScenario1(dc); + break; + case 'insert-scenario-2': + await insertScenario2(dc); + break; + + default: + throw new Error('Invalid argument'); + } +})(); diff --git a/lib/workload/stateless/metadata_manager/src/src/test-data/scenario-1.ts b/lib/workload/stateless/metadata_manager/src/src/test-data/scenario-1.ts deleted file mode 100644 index 88642065d..000000000 --- a/lib/workload/stateless/metadata_manager/src/src/test-data/scenario-1.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { DependencyContainer } from 'tsyringe'; -import { Logger } from 'pino'; -import { MetadataGoogleService } from '../service/loader-method/googleSheet'; -import { METADATA_GOOGLE_OBJ } from '../../tests/service/gsheet.common'; - -export default async function insertScenario1(dc: DependencyContainer) { - const logger = dc.resolve('Logger'); - const gService = dc.resolve(MetadataGoogleService); - - logger.info('inserting scenario 1'); - await gService.syncGoogleMetadataRecords(METADATA_GOOGLE_OBJ); -} diff --git a/lib/workload/stateless/metadata_manager/src/src/test-data/scenarios/metadata.xlsx b/lib/workload/stateless/metadata_manager/src/src/test-data/scenarios/metadata.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..95b2bc41cf030d0849a34f99ed858f9ea4cd60fb GIT binary patch literal 12660 zcmeHtg?1fDvh5KwGg-35%*<#pGqWsaW@aXf!D5yyW@eVf7Be%`le_P{?(y{ff;+Wp zWu986A}XtLM@B}(mX!bjMFoHZAOQftM*uSB>WU!{0DuVw0H6RMfi(oJtsIQ39CQ?2 zZH(--Xk08U2y#Jz$+7{!@Av=r_&@vwdJ`tBy6Is1&*E?4l`0f)*6E~B0()L@S@WtP z2C)SRr-{Pg{2Q`xbW;o91NfHm<#3*!ylf2+29ElTDMP-rQVMtMhr(*^)Y)Fix5{K) zamIcmFHF3F7q13F-I}_YwP}X(!7|~b5|%rZG&wVv);pI6B|q9aLQs&{C5hOUZS*2J&ECx3rhFE6C39+vrYLPJ z%8?jaBNUmr5UNI;pi#kwLdnMsLg!BLRqvNlTh+g>0Gbt0I4KXRYGBPijGsvJo=++` zfa48empqfXwfQd}_Ai?OdUs^+TK;bzt#M;!y>zevXMyehQ*E|!ud>4&?&N`O z^~(@+)yTn876!$CKk-4Wei*RJ{7ac>!$ShCn##*G8yq?OCQ2JLO zGz+WkK4e66FlVQlhGobhI`3lldch7oSX-_!X+=i2d*Mu8V8IN9!o+7sQP=pHK5L_^ z0fV__=4i%m^bCNg3GvwCst^@QG=VBSGmh#rG?;hC%p#4!3@Gw&Q|lZ+k{;*R{}73^?bv;!o%LCui#9pQsCE7e2_8A>H6Bw=#N zNWr`3!Ac#1m5uj06NR|v6VrxjfJ4x>Mq6332g$$R8x!VzqJ%d+d!Ae*zZX8gqn_Ud&bGz57JF?E_IxV>ZJEJN5B@O_)=szFBdAF6Xs9>^MCk@{)utnI z<*N>-qEEI;I@K*`0o2^C&M1wqe#ntm(jGhQ6h;_~Vrk6I$RsmKEV+~Pfx4&}dp^Q{ z_O4CW=lsTZ+>TTM1x*9B|l7#*lqyAo$Cw59`>==N8gQc zzgI0rVSd$4+CemtxIV-Dvk>xh^$XAqcetS~%RW#@)U^rHc(7Ohl*$`uiNsi?a(WX= zi^O5#A^QCVS?RidVrC-JAg)BA7&s->(y|8}vIKK#0z--refceCA=1Ka>C5Cq=iv7w7!Ea+cFO3x+f3cD)_Xp` zO*TKn4;sInA+eAdf)HtVj5KmOJpPa}xWmHFkLemSYtD*rVzG>guVxkI|GDKhu|^6A z2_l(ampLC8N6jzlQ))d@zD<)8TNq>qOfh@($J*V~5D`INjLwU>GA3e?sIU|GLy|j7 z5quB#Gmninf9uKGmSqA$E)d5>4G<2{1GsXCl@txjR8GV+{!d#rbhmCjohOA}hqst

*f7}@_?#CtV0tT#na zy()ja>8c$PUf|h)mH~$@C)OW`rg@V?Sf zT+oDea1YSW0X|UL<$a%V-iQ{VHsMLx&l}E zJ_?ntJ6UWbKw~#5*AfTm;76n7Dxhn_+SrlG*@EFT+MF6vISV2hd^8sxvN!O;g$258 zAIa5ZC)Og``$hPu^~2eB_s@=5NpHx9yy9_AY@2L`+dw8HgqV#Rjf22!lZR(AEzA*| z444MWTM%w5p`|Lqjo&TQ-6IdDQQ(HT_+fJU%tStOGMkJ&B6J=54(~7#e#69~j`9KT zvakV~3@+w9(w<2Gfg``EKF z>5MnxSRB9SDDuq$$$G0#^~`yRN=%KJ~>4QJjQdrzg-{jHTJYa zm!^dsQ55>-7TIBwg_)W7Po(;K?);A?e}vD8(gC_WtP|m27HCW`qe)Qq#fLu)6M7|J z6<+vR;qv*>DWkg_5D=w)d2bXMS1agTjxI1ZjR0k%=+<^4DJ5|J zkuM^3Bg>x4Cf1Hb^Jc%8grM5=HKJaEdO43jjJGEj%tAFTvS*jFtbJCeR9+5`4~l(m zFz7ZI$8^IjJSoxzS1>L;F`q52r{E>!haM9zr~$CkXu@&$)^`+bMA#K5DjG2#`QoKdcXCj6}L& zE2aQ`*#aP6Et#>k?#6)ao0n*7Xc!wD-vR+uUaq_%D2 z9{G_W~0YztpgF!N*=X`*N`LeD_g{Y%9HEN_<1? zmMs=Z{J0u_-R4dfpz<{QcK`S`TpiM4!Gb(Mr}8HzYeo zcweld3Ovm8iDnr~6wSeR*pc{a&o^CMs1du@xKX7K;eB$WN}m~2T&d7M)2oCIF}!Y8 ztKtf0+7P??4d~mVx^^dSL;bqzx{dVUX+DC&xRpBP0u4Gm9{yGMP)umsomP93v=FN&22!kogSPa%r4kH;Z@(HB!#f8c{4UBFnJ$A-$Z{ zGC+uiI9~&N6J}U@Gw>^WZt&2k8u$VI>iQ>(t1~n`F^=6>i~R=7Pr{Qg5Az27pBFl; z?XMFth_%j_!R@W`N)OAF5@5#HpuXNOI(G87*f=^ zLGzrT55zn==Jd3|aijkU1MF~>AHX@kURh5*srq)O$8mm!58T4aRM?Yw)T=#lS8&HY zks)<<2C`N=w&?xy2*7jB0C>CwZp81ivmOD}#*+QfKR4`cu-DJwEL$vNO$}VtT(cOBKaDo<)p*`^Sj03j?uT8Ug_5C-{{!{UdI0_+n&fMEgfe|7)vqtTq;o z!;0F0@yH8n@BGZX6-~UlK4B5RLS&ecfLm98ET_!K5Z8)>0!++)BTtr>pDbX_oiNP@ z0@rpO4MkLYfIme#wm?|ELzHGAuI>aE{`s}7u<$O^%k9eHV!G|C+vl$^-Em1e?Xs8L z=@AQGiDr_#&DqG9JY+-@B9M%rtR7&fo+XyEyzG!Hhad+QKpuoFa+2`H*q15L`yhj2 z8#|5JeAh@K21L6Fv(N`{@%&f6qEqI}mtzvf-D~^l%es3qd?Y-EOBDBZFK(6DppO-R ziy&K5DXAvTsov_T5eNy~mp{e(xOAzPNzeIV(|!7m3>n$$%LDPt9!3K#`jj$>&%uUV{Ny~EJ;52qg(gSy*{C`iJ@XPL z+OiGT=CVR!c8x(afpuoiO-pEo-TP4}tFZq3ZE@riaxrkF$MOo2s-IYQ)FVzAcmO`Y z@+``DO9u24hBz8H1 zZ?O40pkcS*pFU{yvcyT)?N2v_V=~5aJ1s=Ya@j9Q#trs*k-&cxj&=4I!|;e+8ack(1-9IB}^3 zQ^6skAJe^o$6j?(k8xzLX-egjZX({Xcp2s3xYA9!E|5`NiTND4T{0x4(cMLYWtEAw zt)B}zSt!z4-UGJKintcrPP(F7Miji%Iy3MN{&x5b`8?P@U0h3t*ij^;nn|)7`l*MO z4W*a$_W@mrI`771W1VZX9TM}MUhNb99Sam_8mCp1q$s0u%Mv`oUykJL4 zw5-YUC+RDf=*Ssqlcuuf)M6O0xCa+<%}Bvy@q&GI?z7eMA4gvMiq2}u;AD$4n0k`N zIC74daysw=sM;n0+KVZwQx2+AvWLkz>LRu~&~%n)Xf8Xq>%wh2!Td}7LB_ZVdj@EQ zwJEI;70}};B5v`F#VJ6t`m~G$(GCiW&9<&)j;1AT!g89!YFgB<-$C94Z z`kPaNe=x{2={MonF&;)DAejq)B5m{~AyJs@<+OUJGlOiPAY?LsK-tIanRfwiBK)C& zk*mZ~goRNPER?{Z881ByP9OW#J)xIchuS+4j%f-v*OF4j2a!j8E0vED zKg|}=fpgG>p^MNoXa!R)QySlQL!rXvwWMziuZ(CBx4R8LGP(_fV~-UnPgRwc5+W+p zC*0reaE#tJtqLu6=fQbXclgVEYuGehuACzp zuCFB^w{0>jtoXCT_TZ+wCIx*Ihd&(R4}v+j;Yu$Bf7DRqTfInA+f|s;G{Ga!x{9}M z{O}A1>7t{~8fB1DYnAQ^`~F>Sxt5U%5?1C1%e|$e2pjiB1u5@f#;Cd@AJvg~#{J{) z&(>LE2xng|HydxZLiv4J0qbN!vd3wh!2}lF@SpK&k&tVx?4;ChUgQ=KE8+{(3D|la zh>HI5IY{-TflippBQI5&hmI5o>$l>_rMr&~MJV}VHF;gUL| z7>4y6&4`V>zNr;KB#LtuHQ>BtzYtIw=`eJ|#p?)O*P&i;#$k%K+$AKf25I6XnmI*kr-V2$*IQ`L)BS5y@xP+6hWEU~~; zz2S6`o}@aA{(A<=Z0*_V_b%CD1b-nYXP{H>y_T%DCY~W|ZhOlBGib?NP{LI@r7&Za zbsgR_8X9_rBo^Xwr5>2)Zn*aL$9p|{#mAvz_6A5)Y=!l4-IA7Q)mQFlfVK4Ue9*zA>%LRh^=!$p%Sdx065D#PqLuCyPNBB+4a5^0A+q zd38K1wT6-7B&=3?$HA)grt-qDcFIw3R}$6W)=tY&aVk*Z_iDCWKN1WBzezn#fT?cM z47or}yl#|Ak?VF_DT!W{bY=}b+WKylM(*v&oqu!PB9v%AXx$yP8|0^}DR~*DbniK8 z?nJQZxoB2891>pb;e^Vgk5pxh`B7spI&qA?l7;-4_YgF zY#=-NVCIvdcp3J=>`4%>!=`#!qcKg86j%J{awiD~99EEA?r@q;$)7|s7S)Ot*zbD# zq&i+xuXd+@6^b+fi4(KbP;{Qsp_+~hAErK<7?F-1Gib-ZD`?#)VK1CWCOKX>J6Idk z0?{`}vJ5bNuUlmRHe)Xs?a8(<*|d1$eaPH-i@h#Ig&!rEg>QkMHZhLy{T5qS5N4We zWSWSOv0$Cxm;l&>;A3-oIb-L(lRSb8c5I4lOlQ7*(A=nw55KI}4$b62{v@ymel5BhuB4)`Z0E|Xr>&}e!iK`@sXM8#2Z zMj8FiK*c-+1fdSs+^fOIwFAhk2b-T(XI5tQ6WXmBf(<=Y2c}+62pgx%%*O{wNnWJC(FDgc%nmn2w9 zff3?{@!j7OBY;+i780a{@npKDI-i#9B6qv}QT*U7v$FZUkVoB8UA2ph8U_S4Sv0Of z9aCNz3$ok^On*5uJ=FIxF0ZPv-z)RX9_?citdad!y0|f0-hpWp@pMsSB}rppd`(=>Rv_V~^$$BgH^c23Wu#yzJ=oPT*GY)tgc2=b1k)E| zeT&lhC`e7@+1XK+;iV&Aa?&lLo<;j}?WR!@hg zF{L=Nc`#?Opz<6kNz-C+XY5!Z9iuhW zafFLW&0>N-q~d;^)UEkxQcBf3pCq)7NIv4$H3KoOKqq^Hb^H-Q{4vK|5faeA^oU@U z$d7<18X=7M#YVf2qiDG^581ac86p?ABK*!uvOiQA1Ijgx9g*}0`euw}#x_)k zR{wbH??vTJt`HydcjT$Rr&&?|Tt4l;=-C+=Dmd7gTABQjY4uRnvR0WNRaeoOSBn|*#S^9hOan&(>ub-?uxH42Vb>EV}T0>mMB z=uZ`kAByxdv1mgSy&qT*-QkJQI00(g{Hm2};9x^VXT)WB@;hx%o|Sov5>QiEO)WPq zma&e@HJsxt>E~NTYw(5*cwf#Xd-E3dd@j29feVS8FKnA0z(SuV_*FVRAQFbQK1foo zNyM34hTzu3k&?NLr;PKu=XZ{wU|5MmJ6PB(fJ{JVqwh(C7iJ=YvZofST~P(@f88b+ zJ?6!HdrAMUf)f3eL!^FPtDHCWXIwIUs|#Uj_eMN+ZXBAM5mBD;er_Iql|zn%fbw{c zJN8Xm>6JlQ1B4N;eZA8~U#$rVPO#bC;Z0DeHI|^UH;Wav&S&bEnP~XpNnche%_K0v z8Lx=kL0Cycd>ol=hRl>$Tu{W!(z><|R7%y;w7WUeiM*~sxp>2drwUF6Oe46^=I9*tlt!{{!prDjH{C)B=~TWH zGQkKst%{{=Ek#N5JPG8@Vl(YI>xofz4Sc2JAHf-b`wb@)6aeUbFAw}LzMbJ$e4Vba z9JWk{=t+BxAFyih5a)t}VnW^mr$v^Z;Pg~BxTV@#qbb%T_jrc)5T_-&2xqQ8ws662 zviqgBk-H@IxJ$J-EnS3P6pBdzqh@jYdM|o*8-#f7qF}wwilC6R>e}hyb!9VqY)%;v zMIdNkug*Si9HA!XyU8+1&2%qQ9JvXPKNhq&2cYGMDN(}>B3IC4sWllKWyWo$%J*@n zc7n#9kH;)(>Up#z*5Irmw}s2tG;T2`6(~g~pQ}ka{ShmlD|B0BTDx(C{lp`pKr=YC zPTS9kWz>9!AubO6t(->7XSA&Hq2`4>jge+tGWkVE7)2_@x9u9|UI?wDJnxIsZdle} z9BW*@34?X=kW$$oC^!EgI-h&f}I(;KS)&5j6wkMkB(kywS+; zw`$VqRvml?r`Z+ukL0<%6MO1Mvp;9f~+s;Ec8EUOJ|?&`ez6<}5>7etebd zi>Lg2dW!ummH5kH8&$NN*C@!_`Nb>;EcJkyQr1H|LkCcFgU1uy|b%zVSfATiyGzG7;j>I^=C`wAHIKU=`HF&2%xTbxsG6WL{n2_FNlF63#nOOjW*OpRc|k_D`1*`2 zloqbFJ2Ix5)|i_Q?l6{9o)rYpC7Oc7!qvWvrb{Oe-*!=pq|<683Ba4Du9fqPqw#Qs zJq-azy8Ik>NC%^v>Kxcq39<@rghhEnggy>%^cE6M5yTdv5Hb1jRUh%vho&=7o&-76 z&Ze#!0_s&cLj3am#gpJE4o1t}W1~pK2tc68+LDTbZ0T@T48g0sP`lV(LTrs~Epa1p z#fysHkQAr4krd@e>G@J^sPuZ+d@Rxf;I^{k)mA55`rK5hJRCo|Z_xfVUwY#wAR;+?}%=PQ_{xLHM zJE9~l`u@)^|BCd^MKQECkhQb6v8Oe#wln&*ZoSjC{!2l5pSOrOIf))R)W9{cH^CwI zG!{IAfO?Qb-*vvK+nXaK8y_&!Vnd`wyFTYVRE+@;aRou3Yn|C7 z7@kjVbQ7QKb!ADUiC?+`qzfAr>eoNpI-F(TMrzFyYw`3#J}^Evd%0kj^vmD1Z2FW4 z*bGzCtt}l2vqTzFG|%%>oeLc_EYR)E>uumbZSI~gdzeCQ=L{kte1e|ZuO3u$9kM<< zL@N;$zhoQPq^g9<`3^?BUGDuh;DLYRk|Rz2DwsZNDs2+5dj)j?TLkTK!Cmqv_J7~n zQRQyXCBDOt;hofi_;>i}+1UISeebaQpCdiK%WC--X%6HTKIk-3)0r%YPnkXs$4#{w zAlCAoWTskHjX`Km^!EDO$*kj2kI#zeEAQY$UYS)?`GlM3zCKys4h04lC=MkCe7?(q zcgsB$0}%?vmVu9aI-oD|^`75S;g}#6WVBJZQ=Um^MP0lWt`=N{3PSnttGZx%fq#VK z3Dr-Lr=J1@YTFNW0fhWT+0FaALHdV{rw86?%2V(j_l>-cuw}E!6<6cfo0UKA#tTBK z3yxP+G061eJ-OA-#c3?V*qwE=;=jd@Cu$a$nM4M|MNigUK#I4c|G@jI=c%!UY&JX7 z3?V^pwC{BV3={jp012W>?iQa8)$8MLDc--}EGqUEaR7w_5FlQpLmRL;(CR;prx5{x z*z3>f0`2Z*-&~D_c$Tx4%JoKyhDA9GP}uHcx}aSd9qOLtJhnxFJvZJasn38SMc>_T zfswhNJlQJ$=(2d}DtCe%pS{^Ls`3@)FbX66dD3v^tBucL-<39|_Q2LP%>Kxcl2_tY z69zM}4t~q)J6QiDf&c+izegnh%uN5+)cvdf2cEjD#J?-}clPYR1b_7z?~nW&m-ctT ze`gf_U9cPck802V!Y}+?&+q)Qzcf9+$6mj&&3+gDoeA@oa5U^6!hi8%ei!|{KJ}L< z6WTvktA1DTdxq^V1>bT1|G@tv-}bwf-viCRv|N7t^9_CvJAc>kdo=KuhG?RH9LFEA z!S7oB-6{X20|1aF2LS%VMgK1T?~Cf+#m6ZBCjLK5tgHmsJ4SxdwP67L@4JAnG{3I? EA7Tf2asU7T literal 0 HcmV?d00001 diff --git a/lib/workload/stateless/metadata_manager/src/src/test-data/scenarios/scenario-1.ts b/lib/workload/stateless/metadata_manager/src/src/test-data/scenarios/scenario-1.ts new file mode 100644 index 000000000..6994a106d --- /dev/null +++ b/lib/workload/stateless/metadata_manager/src/src/test-data/scenarios/scenario-1.ts @@ -0,0 +1,18 @@ +import { Client } from 'edgedb'; +import { DependencyContainer } from 'tsyringe'; +import { Logger } from 'pino'; +import { blankDb } from '../utils'; +import { MetadataService } from '../../service/metadata'; +import { METADATA_REC_ARR } from '../../../tests/service/metadata.common'; + +export default async function insertScenario1(dc: DependencyContainer) { + const logger = dc.resolve('Logger'); + const metadataService = dc.resolve(MetadataService); + const edgeDbClient = dc.resolve('Database'); + + logger.info('Blank database before inserting scenario-1'); + await blankDb(edgeDbClient); + + logger.info('inserting scenario 1 - from test cases'); + await metadataService.upsertMetadataRecords(METADATA_REC_ARR); +} diff --git a/lib/workload/stateless/metadata_manager/src/src/test-data/scenarios/scenario-2.ts b/lib/workload/stateless/metadata_manager/src/src/test-data/scenarios/scenario-2.ts new file mode 100644 index 000000000..98c9b7722 --- /dev/null +++ b/lib/workload/stateless/metadata_manager/src/src/test-data/scenarios/scenario-2.ts @@ -0,0 +1,37 @@ +import { Client } from 'edgedb'; +import { DependencyContainer } from 'tsyringe'; +import { Logger } from 'pino'; +import { blankDb } from '../utils'; +import { MetadataService } from '../../service/metadata'; +import * as reader from 'xlsx'; +import * as path from 'path'; +import { MetadataGoogleService } from '../../service/loader-method/googleSheet'; + +const YEAR_START = 2018; +const YEAR_END = new Date().getFullYear(); + +export default async function insertScenario2(dc: DependencyContainer) { + const logger = dc.resolve('Logger'); + const metadataService = dc.resolve(MetadataService); + const metadataGoogleService = dc.resolve(MetadataGoogleService); + const edgeDbClient = dc.resolve('Database'); + + logger.info('Blank database before inserting scenario-2'); + await blankDb(edgeDbClient); + + logger.info('inserting scenario 2 (based on `metadata.xlsx`)'); + const file = reader.readFile(path.join(__dirname, './metadata.xlsx')); + + let data = []; + + for (let index = YEAR_START; index <= YEAR_END; index++) { + const sheetData = reader.utils.sheet_to_json(file.Sheets[index]); + data = data.concat(sheetData); + } + + const convertedRecord = metadataGoogleService.convertToMetadataRecord(data); + + // Updating Db + await metadataService.upsertMetadataRecords(convertedRecord); + await metadataService.removeDeletedMetadataRecords(convertedRecord); +} diff --git a/lib/workload/stateless/metadata_manager/src/src/test-data/utils.ts b/lib/workload/stateless/metadata_manager/src/src/test-data/utils.ts new file mode 100644 index 000000000..6a7cc2602 --- /dev/null +++ b/lib/workload/stateless/metadata_manager/src/src/test-data/utils.ts @@ -0,0 +1,8 @@ +import { Client } from 'edgedb'; +import e from '../../dbschema/edgeql-js'; + +export const blankDb = async (edgeDbClient: Client) => { + await e.delete(e.metadata.Subject).run(edgeDbClient); + await e.delete(e.metadata.Specimen).run(edgeDbClient); + await e.delete(e.metadata.Library).run(edgeDbClient); +}; diff --git a/lib/workload/stateless/metadata_manager/src/src/utils.ts b/lib/workload/stateless/metadata_manager/src/src/utils.ts new file mode 100644 index 000000000..43d10b8d4 --- /dev/null +++ b/lib/workload/stateless/metadata_manager/src/src/utils.ts @@ -0,0 +1,38 @@ +import axios from 'axios'; + +/** + * Use the default lambda layer extension to query secret manager + * Ref: https://docs.aws.amazon.com/secretsmanager/latest/userguide/retrieving-secrets_lambda.html + * @param secretManagerName The name of the secret or ARN + * @returns + */ +export const getSecretManagerWithLayerExtension = async (secretManagerName: string) => { + const apiUrl = `http://localhost:2773/secretsmanager/get?secretId=${encodeURIComponent( + secretManagerName + )}`; + const headers = { 'X-Aws-Parameters-Secrets-Token': process.env.AWS_SESSION_TOKEN }; + const res = await axios.get(apiUrl, { + headers: headers, + }); + + return res.data.SecretString; +}; + +/** + * Use the default lambda layer extension to query system parameter store (WITH decryption) + * Ref: https://docs.aws.amazon.com/systems-manager/latest/userguide/ps-integration-lambda-extensions.html + * @param parameterStoreName The name of the parameterStore or ARN + * @returns + */ +export const getParameterDecryptedStoreWithLayerExtension = async (parameterStoreName: string) => { + const apiUrl = `http://localhost:2773/systemsmanager/parameters/get/?name=${encodeURIComponent( + parameterStoreName + )}&withDecryption=true`; + + const headers = { 'X-Aws-Parameters-Secrets-Token': process.env.AWS_SESSION_TOKEN }; + const res = await axios.get(apiUrl, { + headers: headers, + }); + + return res.data.Parameter.Value; +}; diff --git a/lib/workload/stateless/metadata_manager/src/tests/service/gsheet.test.ts b/lib/workload/stateless/metadata_manager/src/tests/service/gsheet.test.ts deleted file mode 100644 index fb463f720..000000000 --- a/lib/workload/stateless/metadata_manager/src/tests/service/gsheet.test.ts +++ /dev/null @@ -1,94 +0,0 @@ -import e from '../../dbschema/edgeql-js'; -import { registerTypes } from './test-dependency.common'; -import { MetadataGoogleService } from '../../src/service/loader-method/googleSheet'; -import { METADATA_GOOGLE_OBJ, METADATA_REC_1, METADATA_REC_4 } from './gsheet.common'; -import { Client } from 'edgedb'; -import { resetDb } from './utils'; - -const testContainer = registerTypes(); -let edgeDbClient: Client; -let gService: MetadataGoogleService; - -describe('sync metadata from google spreadsheet', () => { - beforeAll(async () => { - gService = testContainer.resolve(MetadataGoogleService); - edgeDbClient = testContainer.resolve('Database'); - }); - - beforeEach(async () => { - await resetDb(edgeDbClient); - // jest.useFakeTimers(); - }); - - it('libraries with the same specimen', async () => { - await gService.syncGoogleMetadataRecords([METADATA_REC_1, METADATA_REC_4]); - - const libraries = await e - .select(e.metadata.Library, () => ({ - ...e.metadata.Library['*'], - specimen: { - internalId: true, - }, - })) - .run(edgeDbClient); - - const specimens = await e - .select(e.metadata.Specimen, () => ({ - ...e.metadata.Specimen['*'], - })) - .run(edgeDbClient); - - // Expecting 2 library record belong to the same subject - expect(specimens.length).toBe(1); - expect(libraries.length).toBe(2); - - // Checks if both libraries belong to the same subject - const subjectId = specimens[0].internalId; - for (const l of libraries) { - expect(l.specimen?.internalId).toBe(subjectId); - } - }); - - it('libraries with both the same specimen and subject', async () => { - await gService.syncGoogleMetadataRecords([METADATA_REC_1, METADATA_REC_4]); - - const specimens = await e - .select(e.metadata.Specimen, () => ({ - ...e.metadata.Specimen['*'], - subject: { internalId: true }, - })) - .run(edgeDbClient); - - const subjects = await e - .select(e.metadata.Subject, () => ({ ...e.metadata.Subject['*'] })) - .run(edgeDbClient); - - expect(subjects.length).toBe(1); - expect(specimens.length).toBe(1); - - expect(specimens[0].subject?.internalId).toBe(subjects[0].internalId); - }); - - it('test insert and update works', async () => { - await gService.syncGoogleMetadataRecords(METADATA_GOOGLE_OBJ); - - const libraries = await e - .select(e.metadata.Library, () => ({ ...e.metadata.Library['*'] })) - .run(edgeDbClient); - - const specimens = await e - .select(e.metadata.Specimen, () => ({ ...e.metadata.Specimen['*'] })) - .run(edgeDbClient); - - const subjects = await e - .select(e.metadata.Subject, () => ({ ...e.metadata.Subject['*'] })) - .run(edgeDbClient); - - // Testing for all google object exist in Db - for (const m of METADATA_GOOGLE_OBJ) { - expect(libraries.find((l) => l.internalId == m.LibraryID)); - expect(specimens.find((s) => s.internalId == m.SampleID)); - expect(subjects.find((s) => s.internalId == m.SubjectID)); - } - }); -}); diff --git a/lib/workload/stateless/metadata_manager/src/tests/service/gsheet.common.ts b/lib/workload/stateless/metadata_manager/src/tests/service/loader/gsheet.common.ts similarity index 88% rename from lib/workload/stateless/metadata_manager/src/tests/service/gsheet.common.ts rename to lib/workload/stateless/metadata_manager/src/tests/service/loader/gsheet.common.ts index 40192de09..ff047c663 100644 --- a/lib/workload/stateless/metadata_manager/src/tests/service/gsheet.common.ts +++ b/lib/workload/stateless/metadata_manager/src/tests/service/loader/gsheet.common.ts @@ -1,4 +1,4 @@ -export const METADATA_REC_1 = { +export const METADATA_GOOGLE_REC_1 = { LibraryID: 'LIB01', SampleName: 'SAMIDA-EXTSAMA', SampleID: 'SAMIDA', @@ -24,7 +24,7 @@ export const METADATA_REC_1 = { 'Sample_ID (SampleSheet)': 'SAMIDA_LIB01', }; -export const METADATA_REC_2 = { +export const METADATA_GOOGLE_REC_2 = { LibraryID: 'LIB02', SampleName: 'SAMIDB-EXTSAMB', SampleID: 'SAMIDB', @@ -50,7 +50,7 @@ export const METADATA_REC_2 = { 'Sample_ID (SampleSheet)': 'SAMIDB_LIB02', }; -export const METADATA_REC_3 = { +export const METADATA_GOOGLE_REC_3 = { LibraryID: 'LIB03', SampleName: 'SAMIDB-EXTSAMB', SampleID: 'SAMIDB', @@ -76,7 +76,7 @@ export const METADATA_REC_3 = { 'Sample_ID (SampleSheet)': 'SAMIDB_LIB03', }; -export const METADATA_REC_4 = { +export const METADATA_GOOGLE_REC_4 = { LibraryID: 'LIB04', SampleName: 'SAMIDA-EXTSAMA', SampleID: 'SAMIDA', @@ -102,4 +102,9 @@ export const METADATA_REC_4 = { 'Sample_ID (SampleSheet)': 'SAMIDA_LIB01', }; -export const METADATA_GOOGLE_OBJ = [METADATA_REC_1, METADATA_REC_2, METADATA_REC_3, METADATA_REC_4]; +export const METADATA_GOOGLE_OBJ = [ + METADATA_GOOGLE_REC_1, + METADATA_GOOGLE_REC_2, + METADATA_GOOGLE_REC_3, + METADATA_GOOGLE_REC_4, +]; diff --git a/lib/workload/stateless/metadata_manager/src/tests/service/loader/gsheet.test.ts b/lib/workload/stateless/metadata_manager/src/tests/service/loader/gsheet.test.ts new file mode 100644 index 000000000..c9b5645aa --- /dev/null +++ b/lib/workload/stateless/metadata_manager/src/tests/service/loader/gsheet.test.ts @@ -0,0 +1,34 @@ +import { registerTypes } from '../test-dependency.common'; +import { MetadataGoogleService } from '../../../src/service/loader-method/googleSheet'; +import { METADATA_GOOGLE_REC_1 } from './gsheet.common'; +import { isEqual } from 'lodash'; + +const testContainer = registerTypes(); +let gService: MetadataGoogleService; + +describe('metadata record from GoogleSheet tests', () => { + beforeAll(async () => { + gService = testContainer.resolve(MetadataGoogleService); + }); + + it('google record converted to internal types', async () => { + const convertedResultArr = gService.convertToMetadataRecord([METADATA_GOOGLE_REC_1]); + + expect(convertedResultArr.length).toBe(1); + expect( + isEqual(convertedResultArr[0], { + subject: { internalId: 'SUBIDA', externalId: 'EXTSUBIDA' }, + specimen: { internalId: 'SAMIDA', externalId: null, source: 'FFPE' }, + library: { + internalId: 'LIB01', + phenotype: null, + workflow: 'clinical', + quality: null, + type: 'WTS', + assay: 'NebRNA', + coverage: '6.0', + }, + }) + ).toBe(true); + }); +}); diff --git a/lib/workload/stateless/metadata_manager/src/tests/service/metadata.common.ts b/lib/workload/stateless/metadata_manager/src/tests/service/metadata.common.ts new file mode 100644 index 000000000..07ec2c233 --- /dev/null +++ b/lib/workload/stateless/metadata_manager/src/tests/service/metadata.common.ts @@ -0,0 +1,59 @@ +import { MetadataRecords } from '../../src/service/metadata'; + +export const METADATA_REC_1: MetadataRecords = { + subject: { internalId: 'SUBIDA', externalId: 'EXTSUBIDA' }, + specimen: { internalId: 'SAMIDA', externalId: '', source: 'FFPE' }, + library: { + internalId: 'LIB01', + phenotype: null, + workflow: 'clinical', + quality: null, + type: 'WTS', + assay: 'NebRNA', + coverage: '6.0', + }, +}; + +export const METADATA_REC_2: MetadataRecords = { + subject: { internalId: 'SUBIDB', externalId: 'EXTSUBIDB' }, + specimen: { internalId: 'SAMIDB', externalId: 'EXTSAMB', source: 'FFPE' }, + library: { + internalId: 'LIB02', + phenotype: 'tumor', + workflow: 'clinical', + quality: 'poor', + type: 'WTS', + assay: 'NebRNA', + coverage: '6.3', + }, +}; + +export const METADATA_REC_3: MetadataRecords = { + subject: { internalId: 'SUBIDB', externalId: 'EXTSUBIDB' }, + specimen: { internalId: 'SAMIDB', externalId: 'EXTSAMB', source: 'FFPE' }, + library: { + internalId: 'LIB03', + phenotype: 'tumor', + workflow: 'clinical', + quality: 'poor', + type: 'WTS', + assay: 'NebRNA', + coverage: '6.0', + }, +}; + +export const METADATA_REC_4: MetadataRecords = { + subject: { internalId: 'SUBIDA', externalId: 'EXTSUBIDA' }, + specimen: { internalId: 'SAMIDA', externalId: 'EXTSAMA', source: 'FFPE' }, + library: { + internalId: 'LIB04', + phenotype: 'tumor', + workflow: 'clinical', + quality: 'poor', + type: 'WTS', + assay: 'NebRNA', + coverage: '6.0', + }, +}; + +export const METADATA_REC_ARR = [METADATA_REC_1, METADATA_REC_2, METADATA_REC_3, METADATA_REC_4]; diff --git a/lib/workload/stateless/metadata_manager/src/tests/service/metadata.test.ts b/lib/workload/stateless/metadata_manager/src/tests/service/metadata.test.ts new file mode 100644 index 000000000..a0d2a14e8 --- /dev/null +++ b/lib/workload/stateless/metadata_manager/src/tests/service/metadata.test.ts @@ -0,0 +1,153 @@ +import e from '../../dbschema/edgeql-js'; +import { registerTypes } from './test-dependency.common'; +import { METADATA_REC_1, METADATA_REC_4, METADATA_REC_ARR } from './metadata.common'; +import { Client } from 'edgedb'; +import { resetDb } from './utils'; +import { MetadataService } from '../../src/service/metadata'; + +const testContainer = registerTypes(); +let edgeDbClient: Client; +let metadataService: MetadataService; + +describe('metadata service test', () => { + beforeAll(async () => { + edgeDbClient = testContainer.resolve('Database'); + metadataService = testContainer.resolve(MetadataService); + }); + + beforeEach(async () => { + await resetDb(edgeDbClient); + }); + + it('two libraries with the same specimen and subject', async () => { + await metadataService.upsertMetadataRecords([METADATA_REC_1, METADATA_REC_4]); + + const libraries = await e + .select(e.metadata.Library, () => ({ + ...e.metadata.Library['*'], + specimen: { + internalId: true, + }, + })) + .run(edgeDbClient); + + const specimens = await e + .select(e.metadata.Specimen, () => ({ + ...e.metadata.Specimen['*'], + subject: { internalId: true }, + })) + .run(edgeDbClient); + + const subjects = await e + .select(e.metadata.Subject, () => ({ ...e.metadata.Subject['*'] })) + .run(edgeDbClient); + + // Expecting 2 library record belong to the same subject and specimen + expect(libraries.length).toBe(2); + expect(subjects.length).toBe(1); + expect(specimens.length).toBe(1); + + // Checks if both libraries belong to the same subject + const specimenId = specimens[0].internalId; + for (const l of libraries) { + expect(l.specimen?.internalId).toBe(specimenId); + } + + // Check if specimen belong to the same subject + const subjectId = subjects[0].internalId; + expect(specimens[0].subject?.internalId).toBe(subjectId); + }); + + it('upsert function works as expected and appear in database', async () => { + await metadataService.upsertMetadataRecords(METADATA_REC_ARR); + + const libraries = await e + .select(e.metadata.Library, () => ({ ...e.metadata.Library['*'] })) + .run(edgeDbClient); + + const specimens = await e + .select(e.metadata.Specimen, () => ({ ...e.metadata.Specimen['*'] })) + .run(edgeDbClient); + + const subjects = await e + .select(e.metadata.Subject, () => ({ ...e.metadata.Subject['*'] })) + .run(edgeDbClient); + + // Testing for all record exist in database + for (const m of METADATA_REC_ARR) { + expect(libraries.find((l) => l.internalId == m.library?.internalId)); + expect(specimens.find((s) => s.internalId == m.specimen?.externalId)); + expect(subjects.find((s) => s.internalId == m.subject?.externalId)); + } + }); + + it('destroy all records works as expected', async () => { + await metadataService.upsertMetadataRecords(METADATA_REC_ARR); + + await metadataService.removeDeletedMetadataRecords([]); + + const libraries = await e + .select(e.metadata.Library, () => ({ ...e.metadata.Library['*'] })) + .run(edgeDbClient); + + const specimens = await e + .select(e.metadata.Specimen, () => ({ ...e.metadata.Specimen['*'] })) + .run(edgeDbClient); + + const subjects = await e + .select(e.metadata.Subject, () => ({ ...e.metadata.Subject['*'] })) + .run(edgeDbClient); + + expect(libraries.length).toBe(0); + expect(specimens.length).toBe(0); + expect(subjects.length).toBe(0); + }); + + it('destroy all records works as expected', async () => { + await metadataService.upsertMetadataRecords(METADATA_REC_ARR); + + await metadataService.removeDeletedMetadataRecords([]); + + const libraries = await e + .select(e.metadata.Library, () => ({ ...e.metadata.Library['*'] })) + .run(edgeDbClient); + + const specimens = await e + .select(e.metadata.Specimen, () => ({ ...e.metadata.Specimen['*'] })) + .run(edgeDbClient); + + const subjects = await e + .select(e.metadata.Subject, () => ({ ...e.metadata.Subject['*'] })) + .run(edgeDbClient); + + expect(libraries.length).toBe(0); + expect(specimens.length).toBe(0); + expect(subjects.length).toBe(0); + }); + + it('removing a library that has the same subject and specimen id', async () => { + await metadataService.upsertMetadataRecords([METADATA_REC_1, METADATA_REC_4]); + + await metadataService.removeDeletedMetadataRecords([METADATA_REC_1]); + + const libraries = await e + .select(e.metadata.Library, () => ({ ...e.metadata.Library['*'] })) + .run(edgeDbClient); + + const specimens = await e + .select(e.metadata.Specimen, () => ({ ...e.metadata.Specimen['*'] })) + .run(edgeDbClient); + + const subjects = await e + .select(e.metadata.Subject, () => ({ ...e.metadata.Subject['*'] })) + .run(edgeDbClient); + + expect(libraries.length).toBe(1); + expect(specimens.length).toBe(1); + expect(subjects.length).toBe(1); + + expect(libraries[0].internalId).toBe(METADATA_REC_1.library?.internalId); + expect(specimens[0].internalId).toBe(METADATA_REC_1.specimen?.internalId); + expect(subjects[0].internalId).toBe(METADATA_REC_1.subject?.internalId); + }); +}); diff --git a/lib/workload/stateless/metadata_manager/src/tests/service/test-dependency.common.ts b/lib/workload/stateless/metadata_manager/src/tests/service/test-dependency.common.ts index 92270c523..0f00027ce 100644 --- a/lib/workload/stateless/metadata_manager/src/tests/service/test-dependency.common.ts +++ b/lib/workload/stateless/metadata_manager/src/tests/service/test-dependency.common.ts @@ -3,7 +3,6 @@ import 'reflect-metadata'; import { container, instanceCachingFactory } from 'tsyringe'; import { Client, Duration, createClient } from 'edgedb'; import { Logger, pino } from 'pino'; -import { SSMClient } from '@aws-sdk/client-ssm'; export function registerTypes() { const dc = container.createChildContainer(); @@ -15,7 +14,14 @@ export function registerTypes() { dc.register('Database', { // https://www.edgedb.com/docs/clients/js/driver#configuring-clients useFactory: instanceCachingFactory(() => - createClient().withConfig({ + createClient({ + host: process.env.EDGEDB_HOST ?? 'localhost', + port: process.env.EDGEDB_PORT ? parseInt(process.env.EDGEDB_PORT) : 5656, + database: process.env.EDGEDB_DATABASE ?? 'edgedb', + tlsSecurity: 'insecure', + password: 'admin', // pragma: allowlist secret + user: process.env.EDGEDB_USER ?? 'orcabus_admin', + }).withConfig({ session_idle_transaction_timeout: Duration.from({ seconds: 60 }), }) ), @@ -29,10 +35,5 @@ export function registerTypes() { }), }); - dc.register('SSMClient', { - useFactory: () => new SSMClient({}), - }); - - // Note: dependencies of class constructors must be injected manually when using esbuild. return dc; } diff --git a/lib/workload/stateless/metadata_manager/src/tsconfig.json b/lib/workload/stateless/metadata_manager/src/tsconfig.json index 0b9690ae0..0c5b60a16 100644 --- a/lib/workload/stateless/metadata_manager/src/tsconfig.json +++ b/lib/workload/stateless/metadata_manager/src/tsconfig.json @@ -58,8 +58,9 @@ // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ // "outDir": "./", /* Specify an output folder for all emitted files. */ + "outDir": "dist", // "removeComments": true, /* Disable emitting comments. */ - "noEmit": true, /* Disable emitting files from a compilation. */ + "noEmit": false, /* Disable emitting files from a compilation. */ // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ @@ -84,7 +85,7 @@ "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ /* Type Checking */ - "strict": true, /* Enable all strict type-checking options. */ + // "strict": true, /* Enable all strict type-checking options. */ // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ @@ -109,5 +110,5 @@ "skipLibCheck": true /* Skip type checking all .d.ts files. */ }, "include": ["./src/**/*"], - "exclude": ["node_modules"] + "exclude": ["node_modules","./deploy/cdk.out"] } diff --git a/lib/workload/stateless/metadata_manager/src/yarn.lock b/lib/workload/stateless/metadata_manager/src/yarn.lock index ee4380a6a..591aa7d58 100644 --- a/lib/workload/stateless/metadata_manager/src/yarn.lock +++ b/lib/workload/stateless/metadata_manager/src/yarn.lock @@ -15,491 +15,6 @@ __metadata: languageName: node linkType: hard -"@aws-crypto/crc32@npm:3.0.0": - version: 3.0.0 - resolution: "@aws-crypto/crc32@npm:3.0.0" - dependencies: - "@aws-crypto/util": ^3.0.0 - "@aws-sdk/types": ^3.222.0 - tslib: ^1.11.1 - checksum: 9fdb3e837fc54119b017ea34fd0a6d71d2c88075d99e1e818a5158e0ad30ced67ddbcc423a11ceeef6cc465ab5ffd91830acab516470b48237ca7abd51be9642 - languageName: node - linkType: hard - -"@aws-crypto/ie11-detection@npm:^3.0.0": - version: 3.0.0 - resolution: "@aws-crypto/ie11-detection@npm:3.0.0" - dependencies: - tslib: ^1.11.1 - checksum: 299b2ddd46eddac1f2d54d91386ceb37af81aef8a800669281c73d634ed17fd855dcfb8b3157f2879344b93a2666a6d602550eb84b71e4d7868100ad6da8f803 - languageName: node - linkType: hard - -"@aws-crypto/sha256-browser@npm:3.0.0": - version: 3.0.0 - resolution: "@aws-crypto/sha256-browser@npm:3.0.0" - dependencies: - "@aws-crypto/ie11-detection": ^3.0.0 - "@aws-crypto/sha256-js": ^3.0.0 - "@aws-crypto/supports-web-crypto": ^3.0.0 - "@aws-crypto/util": ^3.0.0 - "@aws-sdk/types": ^3.222.0 - "@aws-sdk/util-locate-window": ^3.0.0 - "@aws-sdk/util-utf8-browser": ^3.0.0 - tslib: ^1.11.1 - checksum: ca89456bf508db2e08060a7f656460db97ac9a15b11e39d6fa7665e2b156508a1758695bff8e82d0a00178d6ac5c36f35eb4bcfac2e48621265224ca14a19bd2 - languageName: node - linkType: hard - -"@aws-crypto/sha256-js@npm:3.0.0, @aws-crypto/sha256-js@npm:^3.0.0": - version: 3.0.0 - resolution: "@aws-crypto/sha256-js@npm:3.0.0" - dependencies: - "@aws-crypto/util": ^3.0.0 - "@aws-sdk/types": ^3.222.0 - tslib: ^1.11.1 - checksum: 644ded32ea310237811afae873d3c7320739cb6f6cc39dced9c94801379e68e5ee2cca0c34f0384793fa9e750a7e0a5e2468f95754bd08e6fd72ab833c8fe23c - languageName: node - linkType: hard - -"@aws-crypto/supports-web-crypto@npm:^3.0.0": - version: 3.0.0 - resolution: "@aws-crypto/supports-web-crypto@npm:3.0.0" - dependencies: - tslib: ^1.11.1 - checksum: 35479a1558db9e9a521df6877a99f95670e972c602f2a0349303477e5d638a5baf569fb037c853710e382086e6fd77e8ed58d3fb9b49f6e1186a9d26ce7be006 - languageName: node - linkType: hard - -"@aws-crypto/util@npm:^3.0.0": - version: 3.0.0 - resolution: "@aws-crypto/util@npm:3.0.0" - dependencies: - "@aws-sdk/types": ^3.222.0 - "@aws-sdk/util-utf8-browser": ^3.0.0 - tslib: ^1.11.1 - checksum: d29d5545048721aae3d60b236708535059733019a105f8a64b4e4a8eab7cf8dde1546dc56bff7de20d36140a4d1f0f4693e639c5732a7059273a7b1e56354776 - languageName: node - linkType: hard - -"@aws-sdk/client-ssm@npm:^3.382.0": - version: 3.382.0 - resolution: "@aws-sdk/client-ssm@npm:3.382.0" - dependencies: - "@aws-crypto/sha256-browser": 3.0.0 - "@aws-crypto/sha256-js": 3.0.0 - "@aws-sdk/client-sts": 3.382.0 - "@aws-sdk/credential-provider-node": 3.382.0 - "@aws-sdk/middleware-host-header": 3.379.1 - "@aws-sdk/middleware-logger": 3.378.0 - "@aws-sdk/middleware-recursion-detection": 3.378.0 - "@aws-sdk/middleware-signing": 3.379.1 - "@aws-sdk/middleware-user-agent": 3.382.0 - "@aws-sdk/types": 3.378.0 - "@aws-sdk/util-endpoints": 3.382.0 - "@aws-sdk/util-user-agent-browser": 3.378.0 - "@aws-sdk/util-user-agent-node": 3.378.0 - "@smithy/config-resolver": ^2.0.1 - "@smithy/fetch-http-handler": ^2.0.1 - "@smithy/hash-node": ^2.0.1 - "@smithy/invalid-dependency": ^2.0.1 - "@smithy/middleware-content-length": ^2.0.1 - "@smithy/middleware-endpoint": ^2.0.1 - "@smithy/middleware-retry": ^2.0.1 - "@smithy/middleware-serde": ^2.0.1 - "@smithy/middleware-stack": ^2.0.0 - "@smithy/node-config-provider": ^2.0.1 - "@smithy/node-http-handler": ^2.0.1 - "@smithy/protocol-http": ^2.0.1 - "@smithy/smithy-client": ^2.0.1 - "@smithy/types": ^2.0.2 - "@smithy/url-parser": ^2.0.1 - "@smithy/util-base64": ^2.0.0 - "@smithy/util-body-length-browser": ^2.0.0 - "@smithy/util-body-length-node": ^2.0.0 - "@smithy/util-defaults-mode-browser": ^2.0.1 - "@smithy/util-defaults-mode-node": ^2.0.1 - "@smithy/util-retry": ^2.0.0 - "@smithy/util-utf8": ^2.0.0 - "@smithy/util-waiter": ^2.0.1 - tslib: ^2.5.0 - uuid: ^8.3.2 - checksum: 350e2f3bf489d5faa08fc5b92802133c6557980e764296f4e598de1d069065e136aa5254322d11e841531cc43c96439be9a738017cb7e7205b576e612d1bd814 - languageName: node - linkType: hard - -"@aws-sdk/client-sso-oidc@npm:3.382.0": - version: 3.382.0 - resolution: "@aws-sdk/client-sso-oidc@npm:3.382.0" - dependencies: - "@aws-crypto/sha256-browser": 3.0.0 - "@aws-crypto/sha256-js": 3.0.0 - "@aws-sdk/middleware-host-header": 3.379.1 - "@aws-sdk/middleware-logger": 3.378.0 - "@aws-sdk/middleware-recursion-detection": 3.378.0 - "@aws-sdk/middleware-user-agent": 3.382.0 - "@aws-sdk/types": 3.378.0 - "@aws-sdk/util-endpoints": 3.382.0 - "@aws-sdk/util-user-agent-browser": 3.378.0 - "@aws-sdk/util-user-agent-node": 3.378.0 - "@smithy/config-resolver": ^2.0.1 - "@smithy/fetch-http-handler": ^2.0.1 - "@smithy/hash-node": ^2.0.1 - "@smithy/invalid-dependency": ^2.0.1 - "@smithy/middleware-content-length": ^2.0.1 - "@smithy/middleware-endpoint": ^2.0.1 - "@smithy/middleware-retry": ^2.0.1 - "@smithy/middleware-serde": ^2.0.1 - "@smithy/middleware-stack": ^2.0.0 - "@smithy/node-config-provider": ^2.0.1 - "@smithy/node-http-handler": ^2.0.1 - "@smithy/protocol-http": ^2.0.1 - "@smithy/smithy-client": ^2.0.1 - "@smithy/types": ^2.0.2 - "@smithy/url-parser": ^2.0.1 - "@smithy/util-base64": ^2.0.0 - "@smithy/util-body-length-browser": ^2.0.0 - "@smithy/util-body-length-node": ^2.0.0 - "@smithy/util-defaults-mode-browser": ^2.0.1 - "@smithy/util-defaults-mode-node": ^2.0.1 - "@smithy/util-retry": ^2.0.0 - "@smithy/util-utf8": ^2.0.0 - tslib: ^2.5.0 - checksum: 8e63db2ed9d27326d4afe897f7debbe4d7f6c2b27015d5a5e2ce0656adc3757860c313403c1f0e5bfb6790e610d63c8ef3d6ce103abaa07155b4578e4fae768d - languageName: node - linkType: hard - -"@aws-sdk/client-sso@npm:3.382.0": - version: 3.382.0 - resolution: "@aws-sdk/client-sso@npm:3.382.0" - dependencies: - "@aws-crypto/sha256-browser": 3.0.0 - "@aws-crypto/sha256-js": 3.0.0 - "@aws-sdk/middleware-host-header": 3.379.1 - "@aws-sdk/middleware-logger": 3.378.0 - "@aws-sdk/middleware-recursion-detection": 3.378.0 - "@aws-sdk/middleware-user-agent": 3.382.0 - "@aws-sdk/types": 3.378.0 - "@aws-sdk/util-endpoints": 3.382.0 - "@aws-sdk/util-user-agent-browser": 3.378.0 - "@aws-sdk/util-user-agent-node": 3.378.0 - "@smithy/config-resolver": ^2.0.1 - "@smithy/fetch-http-handler": ^2.0.1 - "@smithy/hash-node": ^2.0.1 - "@smithy/invalid-dependency": ^2.0.1 - "@smithy/middleware-content-length": ^2.0.1 - "@smithy/middleware-endpoint": ^2.0.1 - "@smithy/middleware-retry": ^2.0.1 - "@smithy/middleware-serde": ^2.0.1 - "@smithy/middleware-stack": ^2.0.0 - "@smithy/node-config-provider": ^2.0.1 - "@smithy/node-http-handler": ^2.0.1 - "@smithy/protocol-http": ^2.0.1 - "@smithy/smithy-client": ^2.0.1 - "@smithy/types": ^2.0.2 - "@smithy/url-parser": ^2.0.1 - "@smithy/util-base64": ^2.0.0 - "@smithy/util-body-length-browser": ^2.0.0 - "@smithy/util-body-length-node": ^2.0.0 - "@smithy/util-defaults-mode-browser": ^2.0.1 - "@smithy/util-defaults-mode-node": ^2.0.1 - "@smithy/util-retry": ^2.0.0 - "@smithy/util-utf8": ^2.0.0 - tslib: ^2.5.0 - checksum: ef6c13d334913e05d3f4e0296259312beb8e257a8ed2a7421bf3239e96b8712259e8f94c12d26dc2b3b2948dfd1ea1141bde24931916c55ab398f7556e05bb6b - languageName: node - linkType: hard - -"@aws-sdk/client-sts@npm:3.382.0": - version: 3.382.0 - resolution: "@aws-sdk/client-sts@npm:3.382.0" - dependencies: - "@aws-crypto/sha256-browser": 3.0.0 - "@aws-crypto/sha256-js": 3.0.0 - "@aws-sdk/credential-provider-node": 3.382.0 - "@aws-sdk/middleware-host-header": 3.379.1 - "@aws-sdk/middleware-logger": 3.378.0 - "@aws-sdk/middleware-recursion-detection": 3.378.0 - "@aws-sdk/middleware-sdk-sts": 3.379.1 - "@aws-sdk/middleware-signing": 3.379.1 - "@aws-sdk/middleware-user-agent": 3.382.0 - "@aws-sdk/types": 3.378.0 - "@aws-sdk/util-endpoints": 3.382.0 - "@aws-sdk/util-user-agent-browser": 3.378.0 - "@aws-sdk/util-user-agent-node": 3.378.0 - "@smithy/config-resolver": ^2.0.1 - "@smithy/fetch-http-handler": ^2.0.1 - "@smithy/hash-node": ^2.0.1 - "@smithy/invalid-dependency": ^2.0.1 - "@smithy/middleware-content-length": ^2.0.1 - "@smithy/middleware-endpoint": ^2.0.1 - "@smithy/middleware-retry": ^2.0.1 - "@smithy/middleware-serde": ^2.0.1 - "@smithy/middleware-stack": ^2.0.0 - "@smithy/node-config-provider": ^2.0.1 - "@smithy/node-http-handler": ^2.0.1 - "@smithy/protocol-http": ^2.0.1 - "@smithy/smithy-client": ^2.0.1 - "@smithy/types": ^2.0.2 - "@smithy/url-parser": ^2.0.1 - "@smithy/util-base64": ^2.0.0 - "@smithy/util-body-length-browser": ^2.0.0 - "@smithy/util-body-length-node": ^2.0.0 - "@smithy/util-defaults-mode-browser": ^2.0.1 - "@smithy/util-defaults-mode-node": ^2.0.1 - "@smithy/util-retry": ^2.0.0 - "@smithy/util-utf8": ^2.0.0 - fast-xml-parser: 4.2.5 - tslib: ^2.5.0 - checksum: e13fe8cfc271ea8fb56718e3e844a9715960165b65f6f8b226f02859d34344f1380987a4ce808530444c78853033ec37048dd4fa9c93ac0df8de89eeba71bd8e - languageName: node - linkType: hard - -"@aws-sdk/credential-provider-env@npm:3.378.0": - version: 3.378.0 - resolution: "@aws-sdk/credential-provider-env@npm:3.378.0" - dependencies: - "@aws-sdk/types": 3.378.0 - "@smithy/property-provider": ^2.0.0 - "@smithy/types": ^2.0.2 - tslib: ^2.5.0 - checksum: ff32e595305f93756bb8fe9b26ca9a5336ca0517ca0d62dfc4cfa36d3bb990a65ebe7b0afcebaf102e4037ddb5b03132a6dde268f421bb72cbbd4249a22715b6 - languageName: node - linkType: hard - -"@aws-sdk/credential-provider-ini@npm:3.382.0": - version: 3.382.0 - resolution: "@aws-sdk/credential-provider-ini@npm:3.382.0" - dependencies: - "@aws-sdk/credential-provider-env": 3.378.0 - "@aws-sdk/credential-provider-process": 3.378.0 - "@aws-sdk/credential-provider-sso": 3.382.0 - "@aws-sdk/credential-provider-web-identity": 3.378.0 - "@aws-sdk/types": 3.378.0 - "@smithy/credential-provider-imds": ^2.0.0 - "@smithy/property-provider": ^2.0.0 - "@smithy/shared-ini-file-loader": ^2.0.0 - "@smithy/types": ^2.0.2 - tslib: ^2.5.0 - checksum: c52c431f03864d46d23e3515516c62a91af175995fba9dadb7cff4e005d7d2ed19b9b5508859768ce4d98746da260709e7caf703c7211b1a21c62a6a1606ef5d - languageName: node - linkType: hard - -"@aws-sdk/credential-provider-node@npm:3.382.0": - version: 3.382.0 - resolution: "@aws-sdk/credential-provider-node@npm:3.382.0" - dependencies: - "@aws-sdk/credential-provider-env": 3.378.0 - "@aws-sdk/credential-provider-ini": 3.382.0 - "@aws-sdk/credential-provider-process": 3.378.0 - "@aws-sdk/credential-provider-sso": 3.382.0 - "@aws-sdk/credential-provider-web-identity": 3.378.0 - "@aws-sdk/types": 3.378.0 - "@smithy/credential-provider-imds": ^2.0.0 - "@smithy/property-provider": ^2.0.0 - "@smithy/shared-ini-file-loader": ^2.0.0 - "@smithy/types": ^2.0.2 - tslib: ^2.5.0 - checksum: 895405b84fc938b0c3e34f73c63b5426761de3bc2dcfa06e1a06f55ae0f8135d81530c0340c0b1b33b4bcb479f5048a9ec0390288503a261c692a0df2a0b933d - languageName: node - linkType: hard - -"@aws-sdk/credential-provider-process@npm:3.378.0": - version: 3.378.0 - resolution: "@aws-sdk/credential-provider-process@npm:3.378.0" - dependencies: - "@aws-sdk/types": 3.378.0 - "@smithy/property-provider": ^2.0.0 - "@smithy/shared-ini-file-loader": ^2.0.0 - "@smithy/types": ^2.0.2 - tslib: ^2.5.0 - checksum: 6b8343fb9266ef490bf8e654f0d0b53585498ecf755e0e5cbee9bc93426927703637d02740050c491738a83c097a4d848244f3a66a633fd526d9339d846bdbdd - languageName: node - linkType: hard - -"@aws-sdk/credential-provider-sso@npm:3.382.0": - version: 3.382.0 - resolution: "@aws-sdk/credential-provider-sso@npm:3.382.0" - dependencies: - "@aws-sdk/client-sso": 3.382.0 - "@aws-sdk/token-providers": 3.382.0 - "@aws-sdk/types": 3.378.0 - "@smithy/property-provider": ^2.0.0 - "@smithy/shared-ini-file-loader": ^2.0.0 - "@smithy/types": ^2.0.2 - tslib: ^2.5.0 - checksum: ec0d216077a0dd5724fed30cdbc4a235b998c5b5821ba250be749e0e4c0410ce1e06c1a2531281570798b77fbe7a9ff36a0d9960853d8f6b2d98247702649d68 - languageName: node - linkType: hard - -"@aws-sdk/credential-provider-web-identity@npm:3.378.0": - version: 3.378.0 - resolution: "@aws-sdk/credential-provider-web-identity@npm:3.378.0" - dependencies: - "@aws-sdk/types": 3.378.0 - "@smithy/property-provider": ^2.0.0 - "@smithy/types": ^2.0.2 - tslib: ^2.5.0 - checksum: 22cf227f609ea654749517e25c88e9c5e7b9dd97cc781d168b1f7cedf26a692a0d1643c3933a1975a95414c0d6a7dbcef6255ca4f13a788e101f95372e17a3af - languageName: node - linkType: hard - -"@aws-sdk/middleware-host-header@npm:3.379.1": - version: 3.379.1 - resolution: "@aws-sdk/middleware-host-header@npm:3.379.1" - dependencies: - "@aws-sdk/types": 3.378.0 - "@smithy/protocol-http": ^2.0.1 - "@smithy/types": ^2.0.2 - tslib: ^2.5.0 - checksum: 32651531108e43edf745721828feab703ab7f39837da8214bb37593200daab71042336a25b58bd9b3e9b78ac647a828674a48ebbc1f5946a533f8642fb16b92d - languageName: node - linkType: hard - -"@aws-sdk/middleware-logger@npm:3.378.0": - version: 3.378.0 - resolution: "@aws-sdk/middleware-logger@npm:3.378.0" - dependencies: - "@aws-sdk/types": 3.378.0 - "@smithy/types": ^2.0.2 - tslib: ^2.5.0 - checksum: c1c32a5ba4ae92cf988d2c0fed3a15975e1b4612cb546133ac74eb91276fc0714278e3aa30e88d0fae00596208baed76b58e97d952daafd63777b79f185a6c3f - languageName: node - linkType: hard - -"@aws-sdk/middleware-recursion-detection@npm:3.378.0": - version: 3.378.0 - resolution: "@aws-sdk/middleware-recursion-detection@npm:3.378.0" - dependencies: - "@aws-sdk/types": 3.378.0 - "@smithy/protocol-http": ^2.0.1 - "@smithy/types": ^2.0.2 - tslib: ^2.5.0 - checksum: 2104b3834ac6674afac7a50eb4430277ef789f3fbf439d2adab9d43b6dca5dad7518f2a8cb578d3f2ff2c9883ee4e756c7fa10166c0e49f8ea307555f69b06f0 - languageName: node - linkType: hard - -"@aws-sdk/middleware-sdk-sts@npm:3.379.1": - version: 3.379.1 - resolution: "@aws-sdk/middleware-sdk-sts@npm:3.379.1" - dependencies: - "@aws-sdk/middleware-signing": 3.379.1 - "@aws-sdk/types": 3.378.0 - "@smithy/types": ^2.0.2 - tslib: ^2.5.0 - checksum: 22fd2f565c5270ca0de75fbd7d751e15639a8d5fb75656bd8caf62091eda8e47ea208514964a1ae211db63b4d7e98d9a8a8f6e4067953e18a74c039e1a8b9084 - languageName: node - linkType: hard - -"@aws-sdk/middleware-signing@npm:3.379.1": - version: 3.379.1 - resolution: "@aws-sdk/middleware-signing@npm:3.379.1" - dependencies: - "@aws-sdk/types": 3.378.0 - "@smithy/property-provider": ^2.0.0 - "@smithy/protocol-http": ^2.0.1 - "@smithy/signature-v4": ^2.0.0 - "@smithy/types": ^2.0.2 - "@smithy/util-middleware": ^2.0.0 - tslib: ^2.5.0 - checksum: f36f6de13624f504f14db8039e02a6473d366eb11c670f555613ddeb0feac523d08f7d66a985c2a7c1eee548c66f55ac4ed7c148e79efe3fa1f5ad165af627f4 - languageName: node - linkType: hard - -"@aws-sdk/middleware-user-agent@npm:3.382.0": - version: 3.382.0 - resolution: "@aws-sdk/middleware-user-agent@npm:3.382.0" - dependencies: - "@aws-sdk/types": 3.378.0 - "@aws-sdk/util-endpoints": 3.382.0 - "@smithy/protocol-http": ^2.0.1 - "@smithy/types": ^2.0.2 - tslib: ^2.5.0 - checksum: e53150ecc07f408caa6fa69e6e30ebf9aa000fb59737eeb350fdf4db4789e0d2163bf14f17f4ff4223174e932ce5b71bd9ec662efc61a78a963e12891ecfed6f - languageName: node - linkType: hard - -"@aws-sdk/token-providers@npm:3.382.0": - version: 3.382.0 - resolution: "@aws-sdk/token-providers@npm:3.382.0" - dependencies: - "@aws-sdk/client-sso-oidc": 3.382.0 - "@aws-sdk/types": 3.378.0 - "@smithy/property-provider": ^2.0.0 - "@smithy/shared-ini-file-loader": ^2.0.0 - "@smithy/types": ^2.0.2 - tslib: ^2.5.0 - checksum: 813dc973f616c2d7ec6f71da14e92d7c4b84c28309ac4d8426fe88d0c6bbe70006f9df0a984985cfcf232976188afc3d17ac5168e832e717ae4db41a21c6d67d - languageName: node - linkType: hard - -"@aws-sdk/types@npm:3.378.0, @aws-sdk/types@npm:^3.222.0": - version: 3.378.0 - resolution: "@aws-sdk/types@npm:3.378.0" - dependencies: - "@smithy/types": ^2.0.2 - tslib: ^2.5.0 - checksum: c4c7ebb48a625cb990a1288466f2dd8f0d770078cc77b60d5ee4a803b473ff41df474271dff26d3dadad151d5a016b398167738dd4926266ff1cd04585d4d8e8 - languageName: node - linkType: hard - -"@aws-sdk/util-endpoints@npm:3.382.0": - version: 3.382.0 - resolution: "@aws-sdk/util-endpoints@npm:3.382.0" - dependencies: - "@aws-sdk/types": 3.378.0 - tslib: ^2.5.0 - checksum: 9573e0d30ef7aafb5f51a51d7cf0416b8fe21af6456bff2c1e660a615325012177b70bf78f6591dbb6d863f4e57ac6ac3279bfa3eca2d504a9121f82edf73118 - languageName: node - linkType: hard - -"@aws-sdk/util-locate-window@npm:^3.0.0": - version: 3.310.0 - resolution: "@aws-sdk/util-locate-window@npm:3.310.0" - dependencies: - tslib: ^2.5.0 - checksum: d552ce5f0f836ecb13d7920ae650552c56706f26a5e8abf894ba471e18775a3791869bda95269153735bac9d211efc3ba78ea01c34428c3fed4318ac693a08bc - languageName: node - linkType: hard - -"@aws-sdk/util-user-agent-browser@npm:3.378.0": - version: 3.378.0 - resolution: "@aws-sdk/util-user-agent-browser@npm:3.378.0" - dependencies: - "@aws-sdk/types": 3.378.0 - "@smithy/types": ^2.0.2 - bowser: ^2.11.0 - tslib: ^2.5.0 - checksum: 412ef9ffdcd3d32b9e9bb62dfa252871bc9fbee19814553aeff65bffb21de6ca236199b47eb646c4af8cb326aebab3d63ef4b303050e61fb08eed0d12bb73f8c - languageName: node - linkType: hard - -"@aws-sdk/util-user-agent-node@npm:3.378.0": - version: 3.378.0 - resolution: "@aws-sdk/util-user-agent-node@npm:3.378.0" - dependencies: - "@aws-sdk/types": 3.378.0 - "@smithy/node-config-provider": ^2.0.1 - "@smithy/types": ^2.0.2 - tslib: ^2.5.0 - peerDependencies: - aws-crt: ">=1.0.0" - peerDependenciesMeta: - aws-crt: - optional: true - checksum: b37271d56a8d91072b7af5d71351e388a822b389167638d779ce0b099a1024b412fd3b50a6b6334687a3ae0bebec89479e48a9dceed2262f8801e76e3b5f89ad - languageName: node - linkType: hard - -"@aws-sdk/util-utf8-browser@npm:^3.0.0": - version: 3.259.0 - resolution: "@aws-sdk/util-utf8-browser@npm:3.259.0" - dependencies: - tslib: ^2.3.1 - checksum: b6a1e580da1c9b62c749814182a7649a748ca4253edb4063aa521df97d25b76eae3359eb1680b86f71aac668e05cc05c514379bca39ebf4ba998ae4348412da8 - languageName: node - linkType: hard - "@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.22.5": version: 7.22.5 resolution: "@babel/code-frame@npm:7.22.5" @@ -1029,6 +544,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-arm64@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/android-arm64@npm:0.19.5" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/android-arm@npm:0.17.19": version: 0.17.19 resolution: "@esbuild/android-arm@npm:0.17.19" @@ -1036,6 +558,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-arm@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/android-arm@npm:0.19.5" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + "@esbuild/android-x64@npm:0.17.19": version: 0.17.19 resolution: "@esbuild/android-x64@npm:0.17.19" @@ -1043,6 +572,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-x64@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/android-x64@npm:0.19.5" + conditions: os=android & cpu=x64 + languageName: node + linkType: hard + "@esbuild/darwin-arm64@npm:0.17.19": version: 0.17.19 resolution: "@esbuild/darwin-arm64@npm:0.17.19" @@ -1050,6 +586,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/darwin-arm64@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/darwin-arm64@npm:0.19.5" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/darwin-x64@npm:0.17.19": version: 0.17.19 resolution: "@esbuild/darwin-x64@npm:0.17.19" @@ -1057,6 +600,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/darwin-x64@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/darwin-x64@npm:0.19.5" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + "@esbuild/freebsd-arm64@npm:0.17.19": version: 0.17.19 resolution: "@esbuild/freebsd-arm64@npm:0.17.19" @@ -1064,6 +614,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/freebsd-arm64@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/freebsd-arm64@npm:0.19.5" + conditions: os=freebsd & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/freebsd-x64@npm:0.17.19": version: 0.17.19 resolution: "@esbuild/freebsd-x64@npm:0.17.19" @@ -1071,6 +628,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/freebsd-x64@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/freebsd-x64@npm:0.19.5" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/linux-arm64@npm:0.17.19": version: 0.17.19 resolution: "@esbuild/linux-arm64@npm:0.17.19" @@ -1078,6 +642,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-arm64@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/linux-arm64@npm:0.19.5" + conditions: os=linux & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/linux-arm@npm:0.17.19": version: 0.17.19 resolution: "@esbuild/linux-arm@npm:0.17.19" @@ -1085,6 +656,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-arm@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/linux-arm@npm:0.19.5" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + "@esbuild/linux-ia32@npm:0.17.19": version: 0.17.19 resolution: "@esbuild/linux-ia32@npm:0.17.19" @@ -1092,6 +670,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-ia32@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/linux-ia32@npm:0.19.5" + conditions: os=linux & cpu=ia32 + languageName: node + linkType: hard + "@esbuild/linux-loong64@npm:0.17.19": version: 0.17.19 resolution: "@esbuild/linux-loong64@npm:0.17.19" @@ -1099,6 +684,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-loong64@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/linux-loong64@npm:0.19.5" + conditions: os=linux & cpu=loong64 + languageName: node + linkType: hard + "@esbuild/linux-mips64el@npm:0.17.19": version: 0.17.19 resolution: "@esbuild/linux-mips64el@npm:0.17.19" @@ -1106,6 +698,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-mips64el@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/linux-mips64el@npm:0.19.5" + conditions: os=linux & cpu=mips64el + languageName: node + linkType: hard + "@esbuild/linux-ppc64@npm:0.17.19": version: 0.17.19 resolution: "@esbuild/linux-ppc64@npm:0.17.19" @@ -1113,6 +712,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-ppc64@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/linux-ppc64@npm:0.19.5" + conditions: os=linux & cpu=ppc64 + languageName: node + linkType: hard + "@esbuild/linux-riscv64@npm:0.17.19": version: 0.17.19 resolution: "@esbuild/linux-riscv64@npm:0.17.19" @@ -1120,6 +726,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-riscv64@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/linux-riscv64@npm:0.19.5" + conditions: os=linux & cpu=riscv64 + languageName: node + linkType: hard + "@esbuild/linux-s390x@npm:0.17.19": version: 0.17.19 resolution: "@esbuild/linux-s390x@npm:0.17.19" @@ -1127,6 +740,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-s390x@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/linux-s390x@npm:0.19.5" + conditions: os=linux & cpu=s390x + languageName: node + linkType: hard + "@esbuild/linux-x64@npm:0.17.19": version: 0.17.19 resolution: "@esbuild/linux-x64@npm:0.17.19" @@ -1134,6 +754,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-x64@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/linux-x64@npm:0.19.5" + conditions: os=linux & cpu=x64 + languageName: node + linkType: hard + "@esbuild/netbsd-x64@npm:0.17.19": version: 0.17.19 resolution: "@esbuild/netbsd-x64@npm:0.17.19" @@ -1141,6 +768,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/netbsd-x64@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/netbsd-x64@npm:0.19.5" + conditions: os=netbsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/openbsd-x64@npm:0.17.19": version: 0.17.19 resolution: "@esbuild/openbsd-x64@npm:0.17.19" @@ -1148,6 +782,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/openbsd-x64@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/openbsd-x64@npm:0.19.5" + conditions: os=openbsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/sunos-x64@npm:0.17.19": version: 0.17.19 resolution: "@esbuild/sunos-x64@npm:0.17.19" @@ -1155,6 +796,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/sunos-x64@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/sunos-x64@npm:0.19.5" + conditions: os=sunos & cpu=x64 + languageName: node + linkType: hard + "@esbuild/win32-arm64@npm:0.17.19": version: 0.17.19 resolution: "@esbuild/win32-arm64@npm:0.17.19" @@ -1162,6 +810,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-arm64@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/win32-arm64@npm:0.19.5" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/win32-ia32@npm:0.17.19": version: 0.17.19 resolution: "@esbuild/win32-ia32@npm:0.17.19" @@ -1169,6 +824,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-ia32@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/win32-ia32@npm:0.19.5" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + "@esbuild/win32-x64@npm:0.17.19": version: 0.17.19 resolution: "@esbuild/win32-x64@npm:0.17.19" @@ -1176,6 +838,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-x64@npm:0.19.5": + version: 0.19.5 + resolution: "@esbuild/win32-x64@npm:0.19.5" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@fastify/ajv-compiler@npm:^3.5.0": version: 3.5.0 resolution: "@fastify/ajv-compiler@npm:3.5.0" @@ -1187,6 +856,13 @@ __metadata: languageName: node linkType: hard +"@fastify/aws-lambda@npm:^3.3.0": + version: 3.3.0 + resolution: "@fastify/aws-lambda@npm:3.3.0" + checksum: 18d271f6d11f0e8eb4a6539be21b09a3174c27ded50a018413e0acce9fd1184af88da5b74e5f2b981a353b90a3f67e7eecb37495ea0869c67000d2b725ff0ce2 + languageName: node + linkType: hard + "@fastify/deepmerge@npm:^1.0.0": version: 1.3.0 resolution: "@fastify/deepmerge@npm:1.3.0" @@ -1194,7 +870,7 @@ __metadata: languageName: node linkType: hard -"@fastify/error@npm:^3.2.0": +"@fastify/error@npm:^3.0.0, @fastify/error@npm:^3.2.0": version: 3.3.0 resolution: "@fastify/error@npm:3.3.0" checksum: 202507c8c7f49922cac2f5afc82802151b0bd9c583ca1c2850bf43d0f4cd97eedb3a3388b9016da74f8a01b517a5861d1f666c506dd64fd22995e559bc139264 @@ -1210,6 +886,32 @@ __metadata: languageName: node linkType: hard +"@fastify/http-proxy@npm:^9.2.1": + version: 9.2.1 + resolution: "@fastify/http-proxy@npm:9.2.1" + dependencies: + "@fastify/reply-from": ^9.0.0 + fastify-plugin: ^4.5.0 + ws: ^8.4.2 + checksum: 2d405ad1aa52f106a605f34260450398adfcf15ec9fc4328b36fd2cda2600daec6444c584da7a5bf25513b7e8b443f6e408ce7eec8eb6f8ffff6921df159dd3c + languageName: node + linkType: hard + +"@fastify/reply-from@npm:^9.0.0": + version: 9.4.0 + resolution: "@fastify/reply-from@npm:9.4.0" + dependencies: + "@fastify/error": ^3.0.0 + end-of-stream: ^1.4.4 + fast-querystring: ^1.0.0 + fastify-plugin: ^4.0.0 + pump: ^3.0.0 + tiny-lru: ^11.0.0 + undici: ^5.19.1 + checksum: a048d55d2b06898aa4b5b399e4b5e31ec1ca0abbbe06168951cca0342e508dfedd79d857d1d34ffe478e1a2c2713edd6a2a7358250e080db11c1b4c6b5196b6f + languageName: node + linkType: hard + "@isaacs/cliui@npm:^8.0.2": version: 8.0.2 resolution: "@isaacs/cliui@npm:8.0.2" @@ -1448,563 +1150,136 @@ __metadata: 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.6.2 - jest-regex-util: ^29.4.3 - jest-util: ^29.6.2 - micromatch: ^4.0.4 - pirates: ^4.0.4 - slash: ^3.0.0 - write-file-atomic: ^4.0.2 - checksum: ffb8c3c344cd48bedadec295d9c436737eccc39c1f0868aa9753b76397b33b2e5b121058af6f287ba6f2036181137e37df1212334bfa9d9a712986a4518cdc18 - languageName: node - linkType: hard - -"@jest/types@npm:^29.6.1": - version: 29.6.1 - resolution: "@jest/types@npm:29.6.1" - dependencies: - "@jest/schemas": ^29.6.0 - "@types/istanbul-lib-coverage": ^2.0.0 - "@types/istanbul-reports": ^3.0.0 - "@types/node": "*" - "@types/yargs": ^17.0.8 - chalk: ^4.0.0 - checksum: 89fc1ccf71a84fe0da643e0675b1cfe6a6f19ea72e935b2ab1dbdb56ec547e94433fb59b3536d3832a6e156c077865b7176fe9dae707dab9c3d2f9405ba6233c - languageName: node - linkType: hard - -"@jridgewell/gen-mapping@npm:^0.3.0, @jridgewell/gen-mapping@npm:^0.3.2": - version: 0.3.3 - resolution: "@jridgewell/gen-mapping@npm:0.3.3" - dependencies: - "@jridgewell/set-array": ^1.0.1 - "@jridgewell/sourcemap-codec": ^1.4.10 - "@jridgewell/trace-mapping": ^0.3.9 - checksum: 4a74944bd31f22354fc01c3da32e83c19e519e3bbadafa114f6da4522ea77dd0c2842607e923a591d60a76699d819a2fbb6f3552e277efdb9b58b081390b60ab - languageName: node - linkType: hard - -"@jridgewell/resolve-uri@npm:3.1.0": - version: 3.1.0 - resolution: "@jridgewell/resolve-uri@npm:3.1.0" - checksum: b5ceaaf9a110fcb2780d1d8f8d4a0bfd216702f31c988d8042e5f8fbe353c55d9b0f55a1733afdc64806f8e79c485d2464680ac48a0d9fcadb9548ee6b81d267 - languageName: node - linkType: hard - -"@jridgewell/resolve-uri@npm:^3.0.3": - version: 3.1.1 - resolution: "@jridgewell/resolve-uri@npm:3.1.1" - checksum: f5b441fe7900eab4f9155b3b93f9800a916257f4e8563afbcd3b5a5337b55e52bd8ae6735453b1b745457d9f6cdb16d74cd6220bbdd98cf153239e13f6cbb653 - languageName: node - linkType: hard - -"@jridgewell/set-array@npm:^1.0.1": - version: 1.1.2 - resolution: "@jridgewell/set-array@npm:1.1.2" - checksum: 69a84d5980385f396ff60a175f7177af0b8da4ddb81824cb7016a9ef914eee9806c72b6b65942003c63f7983d4f39a5c6c27185bbca88eb4690b62075602e28e - languageName: node - linkType: hard - -"@jridgewell/sourcemap-codec@npm:1.4.14": - version: 1.4.14 - resolution: "@jridgewell/sourcemap-codec@npm:1.4.14" - checksum: 61100637b6d173d3ba786a5dff019e1a74b1f394f323c1fee337ff390239f053b87266c7a948777f4b1ee68c01a8ad0ab61e5ff4abb5a012a0b091bec391ab97 - languageName: node - linkType: hard - -"@jridgewell/sourcemap-codec@npm:^1.4.10": - version: 1.4.15 - resolution: "@jridgewell/sourcemap-codec@npm:1.4.15" - checksum: b881c7e503db3fc7f3c1f35a1dd2655a188cc51a3612d76efc8a6eb74728bef5606e6758ee77423e564092b4a518aba569bbb21c9bac5ab7a35b0c6ae7e344c8 - languageName: node - linkType: hard - -"@jridgewell/trace-mapping@npm:0.3.9": - version: 0.3.9 - resolution: "@jridgewell/trace-mapping@npm:0.3.9" - dependencies: - "@jridgewell/resolve-uri": ^3.0.3 - "@jridgewell/sourcemap-codec": ^1.4.10 - checksum: d89597752fd88d3f3480845691a05a44bd21faac18e2185b6f436c3b0fd0c5a859fbbd9aaa92050c4052caf325ad3e10e2e1d1b64327517471b7d51babc0ddef - languageName: node - linkType: hard - -"@jridgewell/trace-mapping@npm:^0.3.12, @jridgewell/trace-mapping@npm:^0.3.17, @jridgewell/trace-mapping@npm:^0.3.18, @jridgewell/trace-mapping@npm:^0.3.9": - version: 0.3.18 - resolution: "@jridgewell/trace-mapping@npm:0.3.18" - dependencies: - "@jridgewell/resolve-uri": 3.1.0 - "@jridgewell/sourcemap-codec": 1.4.14 - checksum: 0572669f855260808c16fe8f78f5f1b4356463b11d3f2c7c0b5580c8ba1cbf4ae53efe9f627595830856e57dbac2325ac17eb0c3dd0ec42102e6f227cc289c02 - languageName: node - linkType: hard - -"@npmcli/fs@npm:^3.1.0": - version: 3.1.0 - resolution: "@npmcli/fs@npm:3.1.0" - dependencies: - semver: ^7.3.5 - checksum: a50a6818de5fc557d0b0e6f50ec780a7a02ab8ad07e5ac8b16bf519e0ad60a144ac64f97d05c443c3367235d337182e1d012bbac0eb8dbae8dc7b40b193efd0e - languageName: node - linkType: hard - -"@pkgjs/parseargs@npm:^0.11.0": - version: 0.11.0 - resolution: "@pkgjs/parseargs@npm:0.11.0" - checksum: 6ad6a00fc4f2f2cfc6bff76fb1d88b8ee20bc0601e18ebb01b6d4be583733a860239a521a7fbca73b612e66705078809483549d2b18f370eb346c5155c8e4a0f - languageName: node - linkType: hard - -"@sinclair/typebox@npm:^0.27.8": - version: 0.27.8 - resolution: "@sinclair/typebox@npm:0.27.8" - checksum: 00bd7362a3439021aa1ea51b0e0d0a0e8ca1351a3d54c606b115fdcc49b51b16db6e5f43b4fe7a28c38688523e22a94d49dd31168868b655f0d4d50f032d07a1 - languageName: node - linkType: hard - -"@sinonjs/commons@npm:^3.0.0": - version: 3.0.0 - resolution: "@sinonjs/commons@npm:3.0.0" - dependencies: - type-detect: 4.0.8 - checksum: b4b5b73d4df4560fb8c0c7b38c7ad4aeabedd362f3373859d804c988c725889cde33550e4bcc7cd316a30f5152a2d1d43db71b6d0c38f5feef71fd8d016763f8 - languageName: node - linkType: hard - -"@sinonjs/fake-timers@npm:^10.0.2": - version: 10.3.0 - resolution: "@sinonjs/fake-timers@npm:10.3.0" - dependencies: - "@sinonjs/commons": ^3.0.0 - checksum: 614d30cb4d5201550c940945d44c9e0b6d64a888ff2cd5b357f95ad6721070d6b8839cd10e15b76bf5e14af0bcc1d8f9ec00d49a46318f1f669a4bec1d7f3148 - languageName: node - linkType: hard - -"@smithy/abort-controller@npm:^2.0.1": - version: 2.0.1 - resolution: "@smithy/abort-controller@npm:2.0.1" - dependencies: - "@smithy/types": ^2.0.2 - tslib: ^2.5.0 - checksum: ec126164886a6f44ed83bde7599cd1a16e20cf429c05bf68897d06220b638aab6c7b6b3b937e65fc25d383d015ed2218ca8c1afaed2ff65fad197d0df2ccebc7 - languageName: node - linkType: hard - -"@smithy/config-resolver@npm:^2.0.1": - version: 2.0.1 - resolution: "@smithy/config-resolver@npm:2.0.1" - dependencies: - "@smithy/types": ^2.0.2 - "@smithy/util-config-provider": ^2.0.0 - "@smithy/util-middleware": ^2.0.0 - tslib: ^2.5.0 - checksum: ded6c77fd29ab026b5dcc1b4c4adb417515f7fd18af80f487f1868273ae98003d35ff7c6286207895fc74f5098e6eb8a94555a5af89818796a2fb8bb01a80c60 - languageName: node - linkType: hard - -"@smithy/credential-provider-imds@npm:^2.0.0, @smithy/credential-provider-imds@npm:^2.0.1": - version: 2.0.1 - resolution: "@smithy/credential-provider-imds@npm:2.0.1" - dependencies: - "@smithy/node-config-provider": ^2.0.1 - "@smithy/property-provider": ^2.0.1 - "@smithy/types": ^2.0.2 - "@smithy/url-parser": ^2.0.1 - tslib: ^2.5.0 - checksum: cf0ee4b50da5584685afc9019af1a8e8c910890dc3128a574b606b7845d898cd65429263682ef27da79dc358286f48b4452617a2fe9fcb98e5483908ac05ce8b - languageName: node - linkType: hard - -"@smithy/eventstream-codec@npm:^2.0.1": - version: 2.0.1 - resolution: "@smithy/eventstream-codec@npm:2.0.1" - dependencies: - "@aws-crypto/crc32": 3.0.0 - "@smithy/types": ^2.0.2 - "@smithy/util-hex-encoding": ^2.0.0 - tslib: ^2.5.0 - checksum: 2b7dc1f974b5302dd9fc0982c2484a4d6286e512db78c1c0b8796a5916c3846644b02c6dbbc8433181aeb41c5468d73635459e9f37d640a0bdaf3fe670da8914 - languageName: node - linkType: hard - -"@smithy/fetch-http-handler@npm:^2.0.1": - version: 2.0.1 - resolution: "@smithy/fetch-http-handler@npm:2.0.1" - dependencies: - "@smithy/protocol-http": ^2.0.1 - "@smithy/querystring-builder": ^2.0.1 - "@smithy/types": ^2.0.2 - "@smithy/util-base64": ^2.0.0 - tslib: ^2.5.0 - checksum: ba80a2182d3c68a88212a99cbeb1bd645f5f6f7584081763faf5590443266e9f32b15e8f7380eaf92ed61fe9fdfbdec1ec030eb0c02b68ed48b4fa710c6718e3 - languageName: node - linkType: hard - -"@smithy/hash-node@npm:^2.0.1": - version: 2.0.1 - resolution: "@smithy/hash-node@npm:2.0.1" - dependencies: - "@smithy/types": ^2.0.2 - "@smithy/util-buffer-from": ^2.0.0 - "@smithy/util-utf8": ^2.0.0 - tslib: ^2.5.0 - checksum: e1a1b1ea44f42eacd982680877c31ce4ea4243455bc16e89357981c60902f93074874148701bc82776f41e66eacc6b16c8cc46cd7c99f4135ba13f4ba4a44edf - languageName: node - linkType: hard - -"@smithy/invalid-dependency@npm:^2.0.1": - version: 2.0.1 - resolution: "@smithy/invalid-dependency@npm:2.0.1" - dependencies: - "@smithy/types": ^2.0.2 - tslib: ^2.5.0 - checksum: d50f5781c9e0b1cb336fa20979ee69640bfa586139237eacae9f9068e40c8c729b3b4646af5fab0250e8e49649acab14262d3524f515ecbecc58cd24b68b7ef5 - languageName: node - linkType: hard - -"@smithy/is-array-buffer@npm:^2.0.0": - version: 2.0.0 - resolution: "@smithy/is-array-buffer@npm:2.0.0" - dependencies: - tslib: ^2.5.0 - checksum: 6d101cf509a7818667f42d297894f88f86ef41d3cc9d02eae38bbe5e69b16edf83b8e67eb691964d859a16a4e39db1aad323d83f6ae55ae4512a14ff6406c02d - languageName: node - linkType: hard - -"@smithy/middleware-content-length@npm:^2.0.1": - version: 2.0.1 - resolution: "@smithy/middleware-content-length@npm:2.0.1" - dependencies: - "@smithy/protocol-http": ^2.0.1 - "@smithy/types": ^2.0.2 - tslib: ^2.5.0 - checksum: f9074ba2d5780b0d55e46aeacff8276fb11acf828afdc813ec3c5f118323533f774dd2b99ae00c946993c5ba91c66afa5b40d66ce5f035a456cf6c4cd38a83e1 - languageName: node - linkType: hard - -"@smithy/middleware-endpoint@npm:^2.0.1": - version: 2.0.1 - resolution: "@smithy/middleware-endpoint@npm:2.0.1" - dependencies: - "@smithy/middleware-serde": ^2.0.1 - "@smithy/types": ^2.0.2 - "@smithy/url-parser": ^2.0.1 - "@smithy/util-middleware": ^2.0.0 - tslib: ^2.5.0 - checksum: 5aa0a4c6972a533936dba5eb0d719bb9b534484a401f1a6135a201fc683083aa925d207f2155e15656b2c941c05de2a2aa74dae5e0b9d1a183371a3c3b90b3f6 - languageName: node - linkType: hard - -"@smithy/middleware-retry@npm:^2.0.1": - version: 2.0.1 - resolution: "@smithy/middleware-retry@npm:2.0.1" - dependencies: - "@smithy/protocol-http": ^2.0.1 - "@smithy/service-error-classification": ^2.0.0 - "@smithy/types": ^2.0.2 - "@smithy/util-middleware": ^2.0.0 - "@smithy/util-retry": ^2.0.0 - tslib: ^2.5.0 - uuid: ^8.3.2 - checksum: a1dd6d1feb560632075f3b3be2f3d406635dc3a158e286eb43f3b93c52deacb2a7c7262f3c911cb652f42e4cb4091155482b04a6c0c61360b650468a54f944b2 - languageName: node - linkType: hard - -"@smithy/middleware-serde@npm:^2.0.1": - version: 2.0.1 - resolution: "@smithy/middleware-serde@npm:2.0.1" - dependencies: - "@smithy/types": ^2.0.2 - tslib: ^2.5.0 - checksum: 115d2b94925f24e3592d6e3889179c30c8992957021bfdc67496f9e36dcb3ffe2282a01c0e439282e89c0a5b56bf125a1bec2c87aed02e325316e3b6050ed9fa - languageName: node - linkType: hard - -"@smithy/middleware-stack@npm:^2.0.0": - version: 2.0.0 - resolution: "@smithy/middleware-stack@npm:2.0.0" - dependencies: - tslib: ^2.5.0 - checksum: dd23dff4da44964e936c5ae465de9416bb8dd67da2ae72ffe450156ad52e82475836ed5c18d82cef7edeca421b33d363889549e34482008eeb9ca0bb97f061f2 - languageName: node - linkType: hard - -"@smithy/node-config-provider@npm:^2.0.1": - version: 2.0.1 - resolution: "@smithy/node-config-provider@npm:2.0.1" - dependencies: - "@smithy/property-provider": ^2.0.1 - "@smithy/shared-ini-file-loader": ^2.0.1 - "@smithy/types": ^2.0.2 - tslib: ^2.5.0 - checksum: 9752c8e7c01fc991b93bb080e8486b82d55d592a2c7573004c2e296c192c153b967c79c03be0924c59e14ffc3de04ca861e99370d2ae9a0d8c54f25ea3f99be8 - languageName: node - linkType: hard - -"@smithy/node-http-handler@npm:^2.0.1": - version: 2.0.1 - resolution: "@smithy/node-http-handler@npm:2.0.1" - dependencies: - "@smithy/abort-controller": ^2.0.1 - "@smithy/protocol-http": ^2.0.1 - "@smithy/querystring-builder": ^2.0.1 - "@smithy/types": ^2.0.2 - tslib: ^2.5.0 - checksum: 04705e7c28fb71a5800a511f64dd182230a501742f779860b1d2155a02eec9c9df3b573e2ad9cd3a0148891f02b780edb7803c95b321dd4a2659715ac73566ee - languageName: node - linkType: hard - -"@smithy/property-provider@npm:^2.0.0, @smithy/property-provider@npm:^2.0.1": - version: 2.0.1 - resolution: "@smithy/property-provider@npm:2.0.1" - dependencies: - "@smithy/types": ^2.0.2 - tslib: ^2.5.0 - checksum: 56ea840032911b37a2e602144cf4cf08401a79a3ab06e226a4cf65a14b77e70e4d0bd8f762d172e322a0cf75f45bd1886a265687e090a2848798225e276f2882 - languageName: node - linkType: hard - -"@smithy/protocol-http@npm:^2.0.1": - version: 2.0.1 - resolution: "@smithy/protocol-http@npm:2.0.1" - dependencies: - "@smithy/types": ^2.0.2 - tslib: ^2.5.0 - checksum: cc3d354fad3f27ab29cf7053bbdbbd150dca1864595a46d463abf06595af68e5c31cfc2d03b971fbb693cb9abd3be5763a195497a4fe19f8aed3132069ae3246 - languageName: node - linkType: hard - -"@smithy/querystring-builder@npm:^2.0.1": - version: 2.0.1 - resolution: "@smithy/querystring-builder@npm:2.0.1" - dependencies: - "@smithy/types": ^2.0.2 - "@smithy/util-uri-escape": ^2.0.0 - tslib: ^2.5.0 - checksum: f8ec37623054fcbad8317b57ef41fc906f3f22260b365e7c3b107219dcf456c5c7347165f3bf25d47a4c592548d835778f9c8bc7cc7306b65aa6ce429d94a345 - languageName: node - linkType: hard - -"@smithy/querystring-parser@npm:^2.0.1": - version: 2.0.1 - resolution: "@smithy/querystring-parser@npm:2.0.1" - dependencies: - "@smithy/types": ^2.0.2 - tslib: ^2.5.0 - checksum: a6107281ae33beb5518b85de82fea7692cfcb6c15155719c6ba6ee44cc75b20f07ce28214c635ee38b0474995c0a23b4872feef8bd9f98a7811b7ccf59bac819 - languageName: node - linkType: hard - -"@smithy/service-error-classification@npm:^2.0.0": - version: 2.0.0 - resolution: "@smithy/service-error-classification@npm:2.0.0" - checksum: f6f9b869dca8e74871c428e1277dd3700f67b0ca61de69fc838ac55187bbc602193a7d1073113ea6916892babf3f8fe4938b182fc902ce0a415928799a7e3f9a - languageName: node - linkType: hard - -"@smithy/shared-ini-file-loader@npm:^2.0.0, @smithy/shared-ini-file-loader@npm:^2.0.1": - version: 2.0.1 - resolution: "@smithy/shared-ini-file-loader@npm:2.0.1" - dependencies: - "@smithy/types": ^2.0.2 - tslib: ^2.5.0 - checksum: 0f67d0ba9e44286a444301e603260a2ae5973324d43bc89f6ca15d2a830b32c1232474ff452cf3d607ee08d4fa6d17517fd901a4e6fd4dddbc571aa6b1ae3b6d - languageName: node - linkType: hard - -"@smithy/signature-v4@npm:^2.0.0": - version: 2.0.1 - resolution: "@smithy/signature-v4@npm:2.0.1" - dependencies: - "@smithy/eventstream-codec": ^2.0.1 - "@smithy/is-array-buffer": ^2.0.0 - "@smithy/types": ^2.0.2 - "@smithy/util-hex-encoding": ^2.0.0 - "@smithy/util-middleware": ^2.0.0 - "@smithy/util-uri-escape": ^2.0.0 - "@smithy/util-utf8": ^2.0.0 - tslib: ^2.5.0 - checksum: 2c4bc499251dfbdbea0359fc5196002ac805df7f6f87d7cba36164d8fcd16a749a3c1a52259569134628511dc496724d5e76744c1c39fee3a3f42c5fbfe3749b - languageName: node - linkType: hard - -"@smithy/smithy-client@npm:^2.0.1": - version: 2.0.1 - resolution: "@smithy/smithy-client@npm:2.0.1" - dependencies: - "@smithy/middleware-stack": ^2.0.0 - "@smithy/types": ^2.0.2 - "@smithy/util-stream": ^2.0.1 - tslib: ^2.5.0 - checksum: 5c4abe0a0a67f2c2aa47cbf2806d0d44a34f97ebc83f1add9654d95cef3303fc0dff41237a7e360ae6c2be721e945c889bf869f11476a759c0ad82d61df18f5a - languageName: node - linkType: hard - -"@smithy/types@npm:^2.0.2": - version: 2.0.2 - resolution: "@smithy/types@npm:2.0.2" - dependencies: - tslib: ^2.5.0 - checksum: 4afdd7c77b212abd9e0770a1489057aa0470f8a59061c4fb2175b1f12e02180db3d85e16f2cd870a95c17bd28a5a4b8ef1dff1ade6852f85eafea12872d9588e - languageName: node - linkType: hard - -"@smithy/url-parser@npm:^2.0.1": - version: 2.0.1 - resolution: "@smithy/url-parser@npm:2.0.1" - dependencies: - "@smithy/querystring-parser": ^2.0.1 - "@smithy/types": ^2.0.2 - tslib: ^2.5.0 - checksum: 653bdeff812b972fa88a4e2d795c38df1aca68055818d150727b8b7d2b7b6bb00aed003b113febe371ed2e38e8dd4715b31af6afce7e883d937aed75e7ff48fb + graceful-fs: ^4.2.9 + jest-haste-map: ^29.6.2 + jest-regex-util: ^29.4.3 + jest-util: ^29.6.2 + micromatch: ^4.0.4 + pirates: ^4.0.4 + slash: ^3.0.0 + write-file-atomic: ^4.0.2 + checksum: ffb8c3c344cd48bedadec295d9c436737eccc39c1f0868aa9753b76397b33b2e5b121058af6f287ba6f2036181137e37df1212334bfa9d9a712986a4518cdc18 languageName: node linkType: hard -"@smithy/util-base64@npm:^2.0.0": - version: 2.0.0 - resolution: "@smithy/util-base64@npm:2.0.0" +"@jest/types@npm:^29.6.1": + version: 29.6.1 + resolution: "@jest/types@npm:29.6.1" dependencies: - "@smithy/util-buffer-from": ^2.0.0 - tslib: ^2.5.0 - checksum: 52124a684dfac853288acd2a0ffff02559c21bf7faaa3db58a914e4acb4b1f7925fd48593e7545db87f8f962250824d1249dc8be645ecbd2c1dd1728cfe1069b + "@jest/schemas": ^29.6.0 + "@types/istanbul-lib-coverage": ^2.0.0 + "@types/istanbul-reports": ^3.0.0 + "@types/node": "*" + "@types/yargs": ^17.0.8 + chalk: ^4.0.0 + checksum: 89fc1ccf71a84fe0da643e0675b1cfe6a6f19ea72e935b2ab1dbdb56ec547e94433fb59b3536d3832a6e156c077865b7176fe9dae707dab9c3d2f9405ba6233c languageName: node linkType: hard -"@smithy/util-body-length-browser@npm:^2.0.0": - version: 2.0.0 - resolution: "@smithy/util-body-length-browser@npm:2.0.0" +"@jridgewell/gen-mapping@npm:^0.3.0, @jridgewell/gen-mapping@npm:^0.3.2": + version: 0.3.3 + resolution: "@jridgewell/gen-mapping@npm:0.3.3" dependencies: - tslib: ^2.5.0 - checksum: 4bccdd857bd24c9dcb6e9f2d5be03d59415f9a94d660ec7b3efb45e9aa04017f34c387368f176f24233a071af3b7a2b5f8236a2f5a83bfc884d24dfcc341e836 + "@jridgewell/set-array": ^1.0.1 + "@jridgewell/sourcemap-codec": ^1.4.10 + "@jridgewell/trace-mapping": ^0.3.9 + checksum: 4a74944bd31f22354fc01c3da32e83c19e519e3bbadafa114f6da4522ea77dd0c2842607e923a591d60a76699d819a2fbb6f3552e277efdb9b58b081390b60ab languageName: node linkType: hard -"@smithy/util-body-length-node@npm:^2.0.0": - version: 2.0.0 - resolution: "@smithy/util-body-length-node@npm:2.0.0" - dependencies: - tslib: ^2.5.0 - checksum: 47ded0cc99f880eda353700e10d6131289683164d4ef98a24a2d79449d33f3bbf70c1ce0a66fc457e0c8d14be9fb2a3430fa09302bbc3daa5d23129e11fff478 +"@jridgewell/resolve-uri@npm:3.1.0": + version: 3.1.0 + resolution: "@jridgewell/resolve-uri@npm:3.1.0" + checksum: b5ceaaf9a110fcb2780d1d8f8d4a0bfd216702f31c988d8042e5f8fbe353c55d9b0f55a1733afdc64806f8e79c485d2464680ac48a0d9fcadb9548ee6b81d267 languageName: node linkType: hard -"@smithy/util-buffer-from@npm:^2.0.0": - version: 2.0.0 - resolution: "@smithy/util-buffer-from@npm:2.0.0" - dependencies: - "@smithy/is-array-buffer": ^2.0.0 - tslib: ^2.5.0 - checksum: d33cbf3e488d23390c88705ddae71b08de7a87b6453e38b508cd37a22a02e8b5be9f0cd46c1347b496c3977a815a7399b18840544ecdc4cce8cf3dcd0f5bb009 +"@jridgewell/resolve-uri@npm:^3.0.3": + version: 3.1.1 + resolution: "@jridgewell/resolve-uri@npm:3.1.1" + checksum: f5b441fe7900eab4f9155b3b93f9800a916257f4e8563afbcd3b5a5337b55e52bd8ae6735453b1b745457d9f6cdb16d74cd6220bbdd98cf153239e13f6cbb653 languageName: node linkType: hard -"@smithy/util-config-provider@npm:^2.0.0": - version: 2.0.0 - resolution: "@smithy/util-config-provider@npm:2.0.0" - dependencies: - tslib: ^2.5.0 - checksum: cdc34db5b42658a7c98652ddb2e35b31e0d76f22a051d71724927999a53467fb38fe6dcf228585544bc168cbd54ded3913e14cbc33c947d3c8a45ca518a9b7b0 +"@jridgewell/set-array@npm:^1.0.1": + version: 1.1.2 + resolution: "@jridgewell/set-array@npm:1.1.2" + checksum: 69a84d5980385f396ff60a175f7177af0b8da4ddb81824cb7016a9ef914eee9806c72b6b65942003c63f7983d4f39a5c6c27185bbca88eb4690b62075602e28e languageName: node linkType: hard -"@smithy/util-defaults-mode-browser@npm:^2.0.1": - version: 2.0.1 - resolution: "@smithy/util-defaults-mode-browser@npm:2.0.1" - dependencies: - "@smithy/property-provider": ^2.0.1 - "@smithy/types": ^2.0.2 - bowser: ^2.11.0 - tslib: ^2.5.0 - checksum: b436183ca880c1bb607116c780e7e8d1e252aeb51daf5f35740281671a4553431f393847d74ad180e9388bf11aeab1c675f61bb3a34a0d2fa9943111b063b17d +"@jridgewell/sourcemap-codec@npm:1.4.14": + version: 1.4.14 + resolution: "@jridgewell/sourcemap-codec@npm:1.4.14" + checksum: 61100637b6d173d3ba786a5dff019e1a74b1f394f323c1fee337ff390239f053b87266c7a948777f4b1ee68c01a8ad0ab61e5ff4abb5a012a0b091bec391ab97 languageName: node linkType: hard -"@smithy/util-defaults-mode-node@npm:^2.0.1": - version: 2.0.1 - resolution: "@smithy/util-defaults-mode-node@npm:2.0.1" - dependencies: - "@smithy/config-resolver": ^2.0.1 - "@smithy/credential-provider-imds": ^2.0.1 - "@smithy/node-config-provider": ^2.0.1 - "@smithy/property-provider": ^2.0.1 - "@smithy/types": ^2.0.2 - tslib: ^2.5.0 - checksum: ffd9601a8b37e1ea7a2c23bcaa70bf297c5c95113e8bab41a2f533d1a2f9f9631e66b5360312e202980dbd03ed3c8d8146dd33c8d4e5d3caf30c78a39b301de2 +"@jridgewell/sourcemap-codec@npm:^1.4.10": + version: 1.4.15 + resolution: "@jridgewell/sourcemap-codec@npm:1.4.15" + checksum: b881c7e503db3fc7f3c1f35a1dd2655a188cc51a3612d76efc8a6eb74728bef5606e6758ee77423e564092b4a518aba569bbb21c9bac5ab7a35b0c6ae7e344c8 languageName: node linkType: hard -"@smithy/util-hex-encoding@npm:^2.0.0": - version: 2.0.0 - resolution: "@smithy/util-hex-encoding@npm:2.0.0" +"@jridgewell/trace-mapping@npm:0.3.9": + version: 0.3.9 + resolution: "@jridgewell/trace-mapping@npm:0.3.9" dependencies: - tslib: ^2.5.0 - checksum: 884373e089d909e3c9805bdb78f367d1f3612e4e1e6d8f0263cc82a8b9689eddc0bc80b8b58aa711bd5b48d9cb124f9996906c172e951c9dac78984459e831cf + "@jridgewell/resolve-uri": ^3.0.3 + "@jridgewell/sourcemap-codec": ^1.4.10 + checksum: d89597752fd88d3f3480845691a05a44bd21faac18e2185b6f436c3b0fd0c5a859fbbd9aaa92050c4052caf325ad3e10e2e1d1b64327517471b7d51babc0ddef languageName: node linkType: hard -"@smithy/util-middleware@npm:^2.0.0": - version: 2.0.0 - resolution: "@smithy/util-middleware@npm:2.0.0" +"@jridgewell/trace-mapping@npm:^0.3.12, @jridgewell/trace-mapping@npm:^0.3.17, @jridgewell/trace-mapping@npm:^0.3.18, @jridgewell/trace-mapping@npm:^0.3.9": + version: 0.3.18 + resolution: "@jridgewell/trace-mapping@npm:0.3.18" dependencies: - tslib: ^2.5.0 - checksum: 10401734a10e0c48ed684f20b7a34c40ed85f2e906e61adb6295963d035f2a93b524e80149a252a259a4bca3626773bf89c5eaa2423fd565358c6b4eb9b6d4e0 + "@jridgewell/resolve-uri": 3.1.0 + "@jridgewell/sourcemap-codec": 1.4.14 + checksum: 0572669f855260808c16fe8f78f5f1b4356463b11d3f2c7c0b5580c8ba1cbf4ae53efe9f627595830856e57dbac2325ac17eb0c3dd0ec42102e6f227cc289c02 languageName: node linkType: hard -"@smithy/util-retry@npm:^2.0.0": - version: 2.0.0 - resolution: "@smithy/util-retry@npm:2.0.0" +"@npmcli/fs@npm:^3.1.0": + version: 3.1.0 + resolution: "@npmcli/fs@npm:3.1.0" dependencies: - "@smithy/service-error-classification": ^2.0.0 - tslib: ^2.5.0 - checksum: d5bfe5e81f41dffce6ba5aaf784f08247602d00f883c10c0de9e34a7f04f5369d7ac43901dd75eecc3864882b7390ad40885d07b3dcb35a366411b639482e673 + semver: ^7.3.5 + checksum: a50a6818de5fc557d0b0e6f50ec780a7a02ab8ad07e5ac8b16bf519e0ad60a144ac64f97d05c443c3367235d337182e1d012bbac0eb8dbae8dc7b40b193efd0e languageName: node linkType: hard -"@smithy/util-stream@npm:^2.0.1": - version: 2.0.1 - resolution: "@smithy/util-stream@npm:2.0.1" - dependencies: - "@smithy/fetch-http-handler": ^2.0.1 - "@smithy/node-http-handler": ^2.0.1 - "@smithy/types": ^2.0.2 - "@smithy/util-base64": ^2.0.0 - "@smithy/util-buffer-from": ^2.0.0 - "@smithy/util-hex-encoding": ^2.0.0 - "@smithy/util-utf8": ^2.0.0 - tslib: ^2.5.0 - checksum: 3a190a9e5e3675e69ffdb72bec00216cb8c3e5a565cdcea47bff593c8aac34bc39897c870c4ad82ea369a5be5caa63b08a20516653b6de0e0a19a291315c3773 +"@pkgjs/parseargs@npm:^0.11.0": + version: 0.11.0 + resolution: "@pkgjs/parseargs@npm:0.11.0" + checksum: 6ad6a00fc4f2f2cfc6bff76fb1d88b8ee20bc0601e18ebb01b6d4be583733a860239a521a7fbca73b612e66705078809483549d2b18f370eb346c5155c8e4a0f languageName: node linkType: hard -"@smithy/util-uri-escape@npm:^2.0.0": - version: 2.0.0 - resolution: "@smithy/util-uri-escape@npm:2.0.0" - dependencies: - tslib: ^2.5.0 - checksum: d201cee524ece997c406902463b5ea0b72599994f7b3ac1d923d5645497e9ef93126d146016f13dd4afafe33b9a3e92faf4e023cf0af510b270c1b9ce3d78da8 +"@sinclair/typebox@npm:^0.27.8": + version: 0.27.8 + resolution: "@sinclair/typebox@npm:0.27.8" + checksum: 00bd7362a3439021aa1ea51b0e0d0a0e8ca1351a3d54c606b115fdcc49b51b16db6e5f43b4fe7a28c38688523e22a94d49dd31168868b655f0d4d50f032d07a1 languageName: node linkType: hard -"@smithy/util-utf8@npm:^2.0.0": - version: 2.0.0 - resolution: "@smithy/util-utf8@npm:2.0.0" +"@sinonjs/commons@npm:^3.0.0": + version: 3.0.0 + resolution: "@sinonjs/commons@npm:3.0.0" dependencies: - "@smithy/util-buffer-from": ^2.0.0 - tslib: ^2.5.0 - checksum: bc8cda84f85b513380a61352635b306ae50d3b92974454db32835b39bbaa38150332b89346098ba9dea2e0002e2963fcbdd622bc9b3eec7b7ea8fa3f8c7ce737 + type-detect: 4.0.8 + checksum: b4b5b73d4df4560fb8c0c7b38c7ad4aeabedd362f3373859d804c988c725889cde33550e4bcc7cd316a30f5152a2d1d43db71b6d0c38f5feef71fd8d016763f8 languageName: node linkType: hard -"@smithy/util-waiter@npm:^2.0.1": - version: 2.0.1 - resolution: "@smithy/util-waiter@npm:2.0.1" +"@sinonjs/fake-timers@npm:^10.0.2": + version: 10.3.0 + resolution: "@sinonjs/fake-timers@npm:10.3.0" dependencies: - "@smithy/abort-controller": ^2.0.1 - "@smithy/types": ^2.0.2 - tslib: ^2.5.0 - checksum: d85893533b4222545151d8a0e4c67400a8370bc3dce34c17f5ce0c19b4dadf102ffa7b3ef2b5004abcf0892c318825b07498f8a86f2430cc886f55bf7369a57f + "@sinonjs/commons": ^3.0.0 + checksum: 614d30cb4d5201550c940945d44c9e0b6d64a888ff2cd5b357f95ad6721070d6b8839cd10e15b76bf5e14af0bcc1d8f9ec00d49a46318f1f669a4bec1d7f3148 languageName: node linkType: hard @@ -2211,6 +1486,13 @@ __metadata: languageName: node linkType: hard +"adler-32@npm:~1.3.0": + version: 1.3.1 + resolution: "adler-32@npm:1.3.1" + checksum: c7f6b02df64a4392fcf1591862344f56733716a558e97a8b06a553dadeeaec792054512389000f42f371b13d2be5370e056e18db3b573944b595c4cb7742c5c6 + languageName: node + linkType: hard + "agent-base@npm:6, agent-base@npm:^6.0.2": version: 6.0.2 resolution: "agent-base@npm:6.0.2" @@ -2417,6 +1699,17 @@ __metadata: languageName: node linkType: hard +"axios@npm:^1.5.1": + version: 1.5.1 + resolution: "axios@npm:1.5.1" + dependencies: + follow-redirects: ^1.15.0 + form-data: ^4.0.0 + proxy-from-env: ^1.1.0 + checksum: 4444f06601f4ede154183767863d2b8e472b4a6bfc5253597ed6d21899887e1fd0ee2b3de792ac4f8459fe2e359d2aa07c216e45fd8b9e4e0688a6ebf48a5a8d + languageName: node + linkType: hard + "babel-jest@npm:^29.6.2": version: 29.6.2 resolution: "babel-jest@npm:29.6.2" @@ -2521,13 +1814,6 @@ __metadata: languageName: node linkType: hard -"bowser@npm:^2.11.0": - version: 2.11.0 - resolution: "bowser@npm:2.11.0" - checksum: 29c3f01f22e703fa6644fc3b684307442df4240b6e10f6cfe1b61c6ca5721073189ca97cdeedb376081148c8518e33b1d818a57f781d70b0b70e1f31fb48814f - languageName: node - linkType: hard - "brace-expansion@npm:^1.1.7": version: 1.1.11 resolution: "brace-expansion@npm:1.1.11" @@ -2612,6 +1898,15 @@ __metadata: languageName: node linkType: hard +"busboy@npm:^1.6.0": + version: 1.6.0 + resolution: "busboy@npm:1.6.0" + dependencies: + streamsearch: ^1.1.0 + checksum: 32801e2c0164e12106bf236291a00795c3c4e4b709ae02132883fe8478ba2ae23743b11c5735a0aae8afe65ac4b6ca4568b91f0d9fed1fdbc32ede824a73746e + languageName: node + linkType: hard + "cacache@npm:^17.0.0": version: 17.1.3 resolution: "cacache@npm:17.1.3" @@ -2660,6 +1955,16 @@ __metadata: languageName: node linkType: hard +"cfb@npm:~1.2.1": + version: 1.2.2 + resolution: "cfb@npm:1.2.2" + dependencies: + adler-32: ~1.3.0 + crc-32: ~1.2.0 + checksum: cfb63a7d630a7fa415c1b25655dca66666584f29c95fb0ee90866ada1a28090857827f2ba70a9a50df28bdce05728ae58d495bce417249f305ef7b3c85840024 + languageName: node + linkType: hard + "chalk@npm:^2.0.0, chalk@npm:^2.4.2": version: 2.4.2 resolution: "chalk@npm:2.4.2" @@ -2753,6 +2058,13 @@ __metadata: languageName: node linkType: hard +"codepage@npm:~1.15.0": + version: 1.15.0 + resolution: "codepage@npm:1.15.0" + checksum: 86bdfd8f8fd4d78ace6ddab02a1621cbb4a833686fe886984b4155d99cd0287581d69495774b816ab2f571c4dc851c1595e1dbb8d69bd6dbb5a631ebf317fab0 + languageName: node + linkType: hard + "collect-v8-coverage@npm:^1.0.0": version: 1.0.2 resolution: "collect-v8-coverage@npm:1.0.2" @@ -2852,6 +2164,15 @@ __metadata: languageName: node linkType: hard +"crc-32@npm:~1.2.0, crc-32@npm:~1.2.1": + version: 1.2.2 + resolution: "crc-32@npm:1.2.2" + bin: + crc32: bin/crc32.njs + checksum: ad2d0ad0cbd465b75dcaeeff0600f8195b686816ab5f3ba4c6e052a07f728c3e70df2e3ca9fd3d4484dc4ba70586e161ca5a2334ec8bf5a41bf022a6103ff243 + languageName: node + linkType: hard + "create-require@npm:^1.1.0": version: 1.1.1 resolution: "create-require@npm:1.1.1" @@ -3021,7 +2342,7 @@ __metadata: languageName: node linkType: hard -"end-of-stream@npm:^1.1.0": +"end-of-stream@npm:^1.1.0, end-of-stream@npm:^1.4.4": version: 1.4.4 resolution: "end-of-stream@npm:1.4.4" dependencies: @@ -3053,6 +2374,83 @@ __metadata: languageName: node linkType: hard +"esbuild@npm:^0.19.5": + version: 0.19.5 + resolution: "esbuild@npm:0.19.5" + dependencies: + "@esbuild/android-arm": 0.19.5 + "@esbuild/android-arm64": 0.19.5 + "@esbuild/android-x64": 0.19.5 + "@esbuild/darwin-arm64": 0.19.5 + "@esbuild/darwin-x64": 0.19.5 + "@esbuild/freebsd-arm64": 0.19.5 + "@esbuild/freebsd-x64": 0.19.5 + "@esbuild/linux-arm": 0.19.5 + "@esbuild/linux-arm64": 0.19.5 + "@esbuild/linux-ia32": 0.19.5 + "@esbuild/linux-loong64": 0.19.5 + "@esbuild/linux-mips64el": 0.19.5 + "@esbuild/linux-ppc64": 0.19.5 + "@esbuild/linux-riscv64": 0.19.5 + "@esbuild/linux-s390x": 0.19.5 + "@esbuild/linux-x64": 0.19.5 + "@esbuild/netbsd-x64": 0.19.5 + "@esbuild/openbsd-x64": 0.19.5 + "@esbuild/sunos-x64": 0.19.5 + "@esbuild/win32-arm64": 0.19.5 + "@esbuild/win32-ia32": 0.19.5 + "@esbuild/win32-x64": 0.19.5 + dependenciesMeta: + "@esbuild/android-arm": + optional: true + "@esbuild/android-arm64": + optional: true + "@esbuild/android-x64": + optional: true + "@esbuild/darwin-arm64": + optional: true + "@esbuild/darwin-x64": + optional: true + "@esbuild/freebsd-arm64": + optional: true + "@esbuild/freebsd-x64": + optional: true + "@esbuild/linux-arm": + optional: true + "@esbuild/linux-arm64": + optional: true + "@esbuild/linux-ia32": + optional: true + "@esbuild/linux-loong64": + optional: true + "@esbuild/linux-mips64el": + optional: true + "@esbuild/linux-ppc64": + optional: true + "@esbuild/linux-riscv64": + optional: true + "@esbuild/linux-s390x": + optional: true + "@esbuild/linux-x64": + optional: true + "@esbuild/netbsd-x64": + optional: true + "@esbuild/openbsd-x64": + optional: true + "@esbuild/sunos-x64": + optional: true + "@esbuild/win32-arm64": + optional: true + "@esbuild/win32-ia32": + optional: true + "@esbuild/win32-x64": + optional: true + bin: + esbuild: bin/esbuild + checksum: 5a0227cf6ffffa3076714d88230af1dfdd2fc363d91bd712a81fb91230c315a395e2c9b7588eee62986aeebf4999804b9b1b59eeab8e2457184eb0056bfe20c8 + languageName: node + linkType: hard + "esbuild@npm:~0.17.6": version: 0.17.19 resolution: "esbuild@npm:0.17.19" @@ -3306,14 +2704,10 @@ __metadata: languageName: node linkType: hard -"fast-xml-parser@npm:4.2.5": - version: 4.2.5 - resolution: "fast-xml-parser@npm:4.2.5" - dependencies: - strnum: ^1.0.5 - bin: - fxparser: src/cli/cli.js - checksum: d32b22005504eeb207249bf40dc82d0994b5bb9ca9dcc731d335a1f425e47fe085b3cace3cf9d32172dd1a5544193c49e8615ca95b4bf95a4a4920a226b06d80 +"fastify-plugin@npm:^4.0.0, fastify-plugin@npm:^4.5.0": + version: 4.5.1 + resolution: "fastify-plugin@npm:4.5.1" + checksum: ddd1b2d470c3acd9397c2617b5842dcf71a6f9a32f05d02be1c12e8d37b8fc03af656900cec38e2afef5e9a3dfe5f994317810f4c5e9960b127b1ca179b56f73 languageName: node linkType: hard @@ -3427,6 +2821,13 @@ __metadata: languageName: node linkType: hard +"frac@npm:~1.1.2": + version: 1.1.2 + resolution: "frac@npm:1.1.2" + checksum: fbfbb28003bb84506dd35e7aad8543c5a358bdc95451d0065b6127d40d2c45106f14221575c3e9ce3ea4bf0bbf1225b73c5d655965c9f4ce44332cbe1b34667d + languageName: node + linkType: hard + "fs-minipass@npm:^2.0.0": version: 2.1.0 resolution: "fs-minipass@npm:2.1.0" @@ -5105,6 +4506,16 @@ __metadata: languageName: node linkType: hard +"pino-abstract-transport@npm:v1.1.0": + version: 1.1.0 + resolution: "pino-abstract-transport@npm:1.1.0" + dependencies: + readable-stream: ^4.0.0 + split2: ^4.0.0 + checksum: cc84caabee5647b5753ae484d5f63a1bca0f6e1791845e2db2b6d830a561c2b5dd1177720f68d78994c8a93aecc69f2729e6ac2bc871a1bf5bb4b0ec17210668 + languageName: node + linkType: hard + "pino-pretty@npm:^10.1.0": version: 10.1.0 resolution: "pino-pretty@npm:10.1.0" @@ -5157,6 +4568,27 @@ __metadata: languageName: node linkType: hard +"pino@npm:^8.15.1": + version: 8.15.1 + resolution: "pino@npm:8.15.1" + dependencies: + atomic-sleep: ^1.0.0 + fast-redact: ^3.1.1 + on-exit-leak-free: ^2.1.0 + pino-abstract-transport: v1.1.0 + pino-std-serializers: ^6.0.0 + process-warning: ^2.0.0 + quick-format-unescaped: ^4.0.3 + real-require: ^0.2.0 + safe-stable-stringify: ^2.3.1 + sonic-boom: ^3.1.0 + thread-stream: ^2.0.0 + bin: + pino: bin.js + checksum: cbc6aa4e7fcf28dac326292f6c9276bb6abd1c480e49a830601071c99fc74c09eb56c7049034ea011ccf7a224243af3452f59b73f07f4a22929b8f886130d5a2 + languageName: node + linkType: hard + "pirates@npm:^4.0.4": version: 4.0.6 resolution: "pirates@npm:4.0.6" @@ -5642,18 +5074,22 @@ __metadata: version: 0.0.0-use.local resolution: "src@workspace:." dependencies: - "@aws-sdk/client-ssm": ^3.382.0 "@edgedb/generate": ^0.3.1 + "@fastify/aws-lambda": ^3.3.0 + "@fastify/http-proxy": ^9.2.1 "@types/jest": ^29.5.3 "@types/lodash": ^4 "@types/node": ^20.4.2 + axios: ^1.5.1 edgedb: ^1.3.4 + esbuild: ^0.19.5 fastify: ^4.20.0 google-auth-library: ^9.0.0 google-spreadsheet: ^4.0.2 jest: ^29.6.2 lodash: ^4.17.21 nodemon: ^3.0.1 + pino: ^8.15.1 pino-pretty: ^10.1.0 reflect-metadata: ^0.1.13 ts-jest: ^29.1.1 @@ -5662,9 +5098,19 @@ __metadata: tsyringe: ^4.8.0 typescript: ^5.1.6 ulid: ^2.3.0 + xlsx: ^0.18.5 languageName: unknown linkType: soft +"ssf@npm:~0.11.2": + version: 0.11.2 + resolution: "ssf@npm:0.11.2" + dependencies: + frac: ~1.1.2 + checksum: 6ecef6ae0a90e67dc4b05bc3cca883e2dffad9773b41124af36ee308884e4a29f98bde66d6c8d2bd1ccf5f860ea4f6c49338bd8d733007fc42ebe02dd5295dcf + languageName: node + linkType: hard + "ssri@npm:^10.0.0": version: 10.0.4 resolution: "ssri@npm:10.0.4" @@ -5683,6 +5129,13 @@ __metadata: languageName: node linkType: hard +"streamsearch@npm:^1.1.0": + version: 1.1.0 + resolution: "streamsearch@npm:1.1.0" + checksum: 1cce16cea8405d7a233d32ca5e00a00169cc0e19fbc02aa839959985f267335d435c07f96e5e0edd0eadc6d39c98d5435fb5bbbdefc62c41834eadc5622ad942 + languageName: node + linkType: hard + "string-length@npm:^4.0.1": version: 4.0.2 resolution: "string-length@npm:4.0.2" @@ -5763,13 +5216,6 @@ __metadata: languageName: node linkType: hard -"strnum@npm:^1.0.5": - version: 1.0.5 - resolution: "strnum@npm:1.0.5" - checksum: 651b2031db5da1bf4a77fdd2f116a8ac8055157c5420f5569f64879133825915ad461513e7202a16d7fec63c54fd822410d0962f8ca12385c4334891b9ae6dd2 - languageName: node - linkType: hard - "supports-color@npm:^5.3.0, supports-color@npm:^5.5.0": version: 5.5.0 resolution: "supports-color@npm:5.5.0" @@ -5838,6 +5284,13 @@ __metadata: languageName: node linkType: hard +"tiny-lru@npm:^11.0.0": + version: 11.1.2 + resolution: "tiny-lru@npm:11.1.2" + checksum: 2f1f38ac9fb75919b9017c4b49d0720f2a2fc9922bf7443c66eb00538ebe5823458e002d50460743f2cd9548227d5daec4d5382d77d6789b36ca894746968d07 + languageName: node + linkType: hard + "tiny-lru@npm:^11.0.1": version: 11.0.1 resolution: "tiny-lru@npm:11.0.1" @@ -5957,20 +5410,13 @@ __metadata: languageName: node linkType: hard -"tslib@npm:^1.11.1, tslib@npm:^1.9.3": +"tslib@npm:^1.9.3": version: 1.14.1 resolution: "tslib@npm:1.14.1" checksum: dbe628ef87f66691d5d2959b3e41b9ca0045c3ee3c7c7b906cc1e328b39f199bb1ad9e671c39025bd56122ac57dfbf7385a94843b1cc07c60a4db74795829acd languageName: node linkType: hard -"tslib@npm:^2.3.1, tslib@npm:^2.5.0": - version: 2.6.1 - resolution: "tslib@npm:2.6.1" - checksum: b0d176d176487905b66ae4d5856647df50e37beea7571c53b8d10ba9222c074b81f1410fb91da13debaf2cbc970663609068bdebafa844ea9d69b146527c38fe - languageName: node - linkType: hard - "tsx@npm:^3.12.7": version: 3.12.7 resolution: "tsx@npm:3.12.7" @@ -6047,6 +5493,15 @@ __metadata: languageName: node linkType: hard +"undici@npm:^5.19.1": + version: 5.25.2 + resolution: "undici@npm:5.25.2" + dependencies: + busboy: ^1.6.0 + checksum: 1177a9c4fc9a1ddb765508d0f69ae61c166559badce8d797aaa92beef70ec5ac8fdc420b643f5d8d40b9a37891ba5536e2070d86a9c54a128aec67ad0c862d06 + languageName: node + linkType: hard + "unique-filename@npm:^3.0.0": version: 3.0.0 resolution: "unique-filename@npm:3.0.0" @@ -6095,15 +5550,6 @@ __metadata: languageName: node linkType: hard -"uuid@npm:^8.3.2": - version: 8.3.2 - resolution: "uuid@npm:8.3.2" - bin: - uuid: dist/bin/uuid - checksum: 5575a8a75c13120e2f10e6ddc801b2c7ed7d8f3c8ac22c7ed0c7b2ba6383ec0abda88c905085d630e251719e0777045ae3236f04c812184b7c765f63a70e58df - languageName: node - linkType: hard - "v8-compile-cache-lib@npm:^3.0.1": version: 3.0.1 resolution: "v8-compile-cache-lib@npm:3.0.1" @@ -6168,6 +5614,20 @@ __metadata: languageName: node linkType: hard +"wmf@npm:~1.0.1": + version: 1.0.2 + resolution: "wmf@npm:1.0.2" + checksum: d336acb2c76fa868ef006fbb06c4e64c7c1ed5ff77d16c48a273cf1f4d0a44e35df209b8fde28d93dd4a924d652a9c4fc8a92ad57885a5e437df0b0900769e3b + languageName: node + linkType: hard + +"word@npm:~0.3.0": + version: 0.3.0 + resolution: "word@npm:0.3.0" + checksum: f84e7061883380c1bcb0d98bd183b7f2b281688011924af7a96d3ed3ee20aeb12cc59a0451b66e5e57520338a056725ff8e0c07b358c0afecf5488a9557c19fe + languageName: node + linkType: hard + "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0, wrap-ansi@npm:^7.0.0": version: 7.0.0 resolution: "wrap-ansi@npm:7.0.0" @@ -6207,6 +5667,38 @@ __metadata: languageName: node linkType: hard +"ws@npm:^8.4.2": + version: 8.14.2 + resolution: "ws@npm:8.14.2" + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ">=5.0.2" + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: 3ca0dad26e8cc6515ff392b622a1467430814c463b3368b0258e33696b1d4bed7510bc7030f7b72838b9fdeb8dbd8839cbf808367d6aae2e1d668ce741d4308b + languageName: node + linkType: hard + +"xlsx@npm:^0.18.5": + version: 0.18.5 + resolution: "xlsx@npm:0.18.5" + dependencies: + adler-32: ~1.3.0 + cfb: ~1.2.1 + codepage: ~1.15.0 + crc-32: ~1.2.1 + ssf: ~0.11.2 + wmf: ~1.0.1 + word: ~0.3.0 + bin: + xlsx: bin/xlsx.njs + checksum: c5774d3c6abdf2db24f33a7b786e305255dac0e41a4e6bf6167c3f8517bfb5bfcb98e8207c39d5105f8304aa7416758da0400a993fb79aaf8e2ea4cfa8801f2e + languageName: node + linkType: hard + "y18n@npm:^5.0.5": version: 5.0.8 resolution: "y18n@npm:5.0.8"